1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * CoreNet Coherency Fabric error reporting 4 * 5 * Copyright 2014 Freescale Semiconductor Inc. 6 */ 7 8 #include <linux/interrupt.h> 9 #include <linux/io.h> 10 #include <linux/irq.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/platform_device.h> 14 #include <linux/property.h> 15 16 enum ccf_version { 17 CCF1, 18 CCF2, 19 }; 20 21 struct ccf_info { 22 enum ccf_version version; 23 int err_reg_offs; 24 bool has_brr; 25 }; 26 27 static const struct ccf_info ccf1_info = { 28 .version = CCF1, 29 .err_reg_offs = 0xa00, 30 .has_brr = false, 31 }; 32 33 static const struct ccf_info ccf2_info = { 34 .version = CCF2, 35 .err_reg_offs = 0xe40, 36 .has_brr = true, 37 }; 38 39 /* 40 * This register is present but not documented, with different values for 41 * IP_ID, on other chips with fsl,corenet2-cf such as t4240 and b4860. 42 */ 43 #define CCF_BRR 0xbf8 44 #define CCF_BRR_IPID 0xffff0000 45 #define CCF_BRR_IPID_T1040 0x09310000 46 47 static const struct of_device_id ccf_matches[] = { 48 { 49 .compatible = "fsl,corenet1-cf", 50 .data = &ccf1_info, 51 }, 52 { 53 .compatible = "fsl,corenet2-cf", 54 .data = &ccf2_info, 55 }, 56 {} 57 }; 58 MODULE_DEVICE_TABLE(of, ccf_matches); 59 60 struct ccf_err_regs { 61 u32 errdet; /* 0x00 Error Detect Register */ 62 /* 0x04 Error Enable (ccf1)/Disable (ccf2) Register */ 63 u32 errdis; 64 /* 0x08 Error Interrupt Enable Register (ccf2 only) */ 65 u32 errinten; 66 u32 cecar; /* 0x0c Error Capture Attribute Register */ 67 u32 cecaddrh; /* 0x10 Error Capture Address High */ 68 u32 cecaddrl; /* 0x14 Error Capture Address Low */ 69 u32 cecar2; /* 0x18 Error Capture Attribute Register 2 */ 70 }; 71 72 /* LAE/CV also valid for errdis and errinten */ 73 #define ERRDET_LAE (1 << 0) /* Local Access Error */ 74 #define ERRDET_CV (1 << 1) /* Coherency Violation */ 75 #define ERRDET_UTID (1 << 2) /* Unavailable Target ID (t1040) */ 76 #define ERRDET_MCST (1 << 3) /* Multicast Stash (t1040) */ 77 #define ERRDET_CTYPE_SHIFT 26 /* Capture Type (ccf2 only) */ 78 #define ERRDET_CTYPE_MASK (0x1f << ERRDET_CTYPE_SHIFT) 79 #define ERRDET_CAP (1 << 31) /* Capture Valid (ccf2 only) */ 80 81 #define CECAR_VAL (1 << 0) /* Valid (ccf1 only) */ 82 #define CECAR_UVT (1 << 15) /* Unavailable target ID (ccf1) */ 83 #define CECAR_SRCID_SHIFT_CCF1 24 84 #define CECAR_SRCID_MASK_CCF1 (0xff << CECAR_SRCID_SHIFT_CCF1) 85 #define CECAR_SRCID_SHIFT_CCF2 18 86 #define CECAR_SRCID_MASK_CCF2 (0xff << CECAR_SRCID_SHIFT_CCF2) 87 88 #define CECADDRH_ADDRH 0xff 89 90 struct ccf_private { 91 const struct ccf_info *info; 92 struct device *dev; 93 void __iomem *regs; 94 struct ccf_err_regs __iomem *err_regs; 95 bool t1040; 96 }; 97 98 static irqreturn_t ccf_irq(int irq, void *dev_id) 99 { 100 struct ccf_private *ccf = dev_id; 101 static DEFINE_RATELIMIT_STATE(ratelimit, DEFAULT_RATELIMIT_INTERVAL, 102 DEFAULT_RATELIMIT_BURST); 103 u32 errdet, cecar, cecar2; 104 u64 addr; 105 u32 src_id; 106 bool uvt = false; 107 bool cap_valid = false; 108 109 errdet = ioread32be(&ccf->err_regs->errdet); 110 cecar = ioread32be(&ccf->err_regs->cecar); 111 cecar2 = ioread32be(&ccf->err_regs->cecar2); 112 addr = ioread32be(&ccf->err_regs->cecaddrl); 113 addr |= ((u64)(ioread32be(&ccf->err_regs->cecaddrh) & 114 CECADDRH_ADDRH)) << 32; 115 116 if (!__ratelimit(&ratelimit)) 117 goto out; 118 119 switch (ccf->info->version) { 120 case CCF1: 121 if (cecar & CECAR_VAL) { 122 if (cecar & CECAR_UVT) 123 uvt = true; 124 125 src_id = (cecar & CECAR_SRCID_MASK_CCF1) >> 126 CECAR_SRCID_SHIFT_CCF1; 127 cap_valid = true; 128 } 129 130 break; 131 case CCF2: 132 if (errdet & ERRDET_CAP) { 133 src_id = (cecar & CECAR_SRCID_MASK_CCF2) >> 134 CECAR_SRCID_SHIFT_CCF2; 135 cap_valid = true; 136 } 137 138 break; 139 } 140 141 dev_crit(ccf->dev, "errdet 0x%08x cecar 0x%08x cecar2 0x%08x\n", 142 errdet, cecar, cecar2); 143 144 if (errdet & ERRDET_LAE) { 145 if (uvt) 146 dev_crit(ccf->dev, "LAW Unavailable Target ID\n"); 147 else 148 dev_crit(ccf->dev, "Local Access Window Error\n"); 149 } 150 151 if (errdet & ERRDET_CV) 152 dev_crit(ccf->dev, "Coherency Violation\n"); 153 154 if (errdet & ERRDET_UTID) 155 dev_crit(ccf->dev, "Unavailable Target ID\n"); 156 157 if (errdet & ERRDET_MCST) 158 dev_crit(ccf->dev, "Multicast Stash\n"); 159 160 if (cap_valid) { 161 dev_crit(ccf->dev, "address 0x%09llx, src id 0x%x\n", 162 addr, src_id); 163 } 164 165 out: 166 iowrite32be(errdet, &ccf->err_regs->errdet); 167 return errdet ? IRQ_HANDLED : IRQ_NONE; 168 } 169 170 static int ccf_probe(struct platform_device *pdev) 171 { 172 struct ccf_private *ccf; 173 u32 errinten; 174 int ret, irq; 175 176 ccf = devm_kzalloc(&pdev->dev, sizeof(*ccf), GFP_KERNEL); 177 if (!ccf) 178 return -ENOMEM; 179 180 ccf->regs = devm_platform_ioremap_resource(pdev, 0); 181 if (IS_ERR(ccf->regs)) 182 return PTR_ERR(ccf->regs); 183 184 ccf->dev = &pdev->dev; 185 ccf->info = device_get_match_data(&pdev->dev); 186 ccf->err_regs = ccf->regs + ccf->info->err_reg_offs; 187 188 if (ccf->info->has_brr) { 189 u32 brr = ioread32be(ccf->regs + CCF_BRR); 190 191 if ((brr & CCF_BRR_IPID) == CCF_BRR_IPID_T1040) 192 ccf->t1040 = true; 193 } 194 195 dev_set_drvdata(&pdev->dev, ccf); 196 197 irq = platform_get_irq(pdev, 0); 198 if (irq < 0) 199 return irq; 200 201 ret = devm_request_irq(&pdev->dev, irq, ccf_irq, 0, pdev->name, ccf); 202 if (ret) { 203 dev_err(&pdev->dev, "%s: can't request irq\n", __func__); 204 return ret; 205 } 206 207 errinten = ERRDET_LAE | ERRDET_CV; 208 if (ccf->t1040) 209 errinten |= ERRDET_UTID | ERRDET_MCST; 210 211 switch (ccf->info->version) { 212 case CCF1: 213 /* On CCF1 this register enables rather than disables. */ 214 iowrite32be(errinten, &ccf->err_regs->errdis); 215 break; 216 217 case CCF2: 218 iowrite32be(0, &ccf->err_regs->errdis); 219 iowrite32be(errinten, &ccf->err_regs->errinten); 220 break; 221 } 222 223 return 0; 224 } 225 226 static void ccf_remove(struct platform_device *pdev) 227 { 228 struct ccf_private *ccf = dev_get_drvdata(&pdev->dev); 229 230 switch (ccf->info->version) { 231 case CCF1: 232 iowrite32be(0, &ccf->err_regs->errdis); 233 break; 234 235 case CCF2: 236 /* 237 * We clear errdis on ccf1 because that's the only way to 238 * disable interrupts, but on ccf2 there's no need to disable 239 * detection. 240 */ 241 iowrite32be(0, &ccf->err_regs->errinten); 242 break; 243 } 244 } 245 246 static struct platform_driver ccf_driver = { 247 .driver = { 248 .name = KBUILD_MODNAME, 249 .of_match_table = ccf_matches, 250 }, 251 .probe = ccf_probe, 252 .remove_new = ccf_remove, 253 }; 254 255 module_platform_driver(ccf_driver); 256 257 MODULE_LICENSE("GPL"); 258 MODULE_AUTHOR("Freescale Semiconductor"); 259 MODULE_DESCRIPTION("Freescale CoreNet Coherency Fabric error reporting"); 260