0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/kernel.h>
0012 #include <linux/slab.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/io.h>
0016 #include <linux/module.h>
0017 #include <linux/of.h>
0018 #include <linux/of_device.h>
0019
0020 #include "omap_l3_smx.h"
0021
0022 static inline u64 omap3_l3_readll(void __iomem *base, u16 reg)
0023 {
0024 return __raw_readll(base + reg);
0025 }
0026
0027 static inline void omap3_l3_writell(void __iomem *base, u16 reg, u64 value)
0028 {
0029 __raw_writell(value, base + reg);
0030 }
0031
0032 static inline enum omap3_l3_code omap3_l3_decode_error_code(u64 error)
0033 {
0034 return (error & 0x0f000000) >> L3_ERROR_LOG_CODE;
0035 }
0036
0037 static inline u32 omap3_l3_decode_addr(u64 error_addr)
0038 {
0039 return error_addr & 0xffffffff;
0040 }
0041
0042 static inline unsigned omap3_l3_decode_cmd(u64 error)
0043 {
0044 return (error & 0x07) >> L3_ERROR_LOG_CMD;
0045 }
0046
0047 static inline enum omap3_l3_initiator_id omap3_l3_decode_initid(u64 error)
0048 {
0049 return (error & 0xff00) >> L3_ERROR_LOG_INITID;
0050 }
0051
0052 static inline unsigned omap3_l3_decode_req_info(u64 error)
0053 {
0054 return (error >> 32) & 0xffff;
0055 }
0056
0057 static char *omap3_l3_code_string(u8 code)
0058 {
0059 switch (code) {
0060 case OMAP_L3_CODE_NOERROR:
0061 return "No Error";
0062 case OMAP_L3_CODE_UNSUP_CMD:
0063 return "Unsupported Command";
0064 case OMAP_L3_CODE_ADDR_HOLE:
0065 return "Address Hole";
0066 case OMAP_L3_CODE_PROTECT_VIOLATION:
0067 return "Protection Violation";
0068 case OMAP_L3_CODE_IN_BAND_ERR:
0069 return "In-band Error";
0070 case OMAP_L3_CODE_REQ_TOUT_NOT_ACCEPT:
0071 return "Request Timeout Not Accepted";
0072 case OMAP_L3_CODE_REQ_TOUT_NO_RESP:
0073 return "Request Timeout, no response";
0074 default:
0075 return "UNKNOWN error";
0076 }
0077 }
0078
0079 static char *omap3_l3_initiator_string(u8 initid)
0080 {
0081 switch (initid) {
0082 case OMAP_L3_LCD:
0083 return "LCD";
0084 case OMAP_L3_SAD2D:
0085 return "SAD2D";
0086 case OMAP_L3_IA_MPU_SS_1:
0087 case OMAP_L3_IA_MPU_SS_2:
0088 case OMAP_L3_IA_MPU_SS_3:
0089 case OMAP_L3_IA_MPU_SS_4:
0090 case OMAP_L3_IA_MPU_SS_5:
0091 return "MPU";
0092 case OMAP_L3_IA_IVA_SS_1:
0093 case OMAP_L3_IA_IVA_SS_2:
0094 case OMAP_L3_IA_IVA_SS_3:
0095 return "IVA_SS";
0096 case OMAP_L3_IA_IVA_SS_DMA_1:
0097 case OMAP_L3_IA_IVA_SS_DMA_2:
0098 case OMAP_L3_IA_IVA_SS_DMA_3:
0099 case OMAP_L3_IA_IVA_SS_DMA_4:
0100 case OMAP_L3_IA_IVA_SS_DMA_5:
0101 case OMAP_L3_IA_IVA_SS_DMA_6:
0102 return "IVA_SS_DMA";
0103 case OMAP_L3_IA_SGX:
0104 return "SGX";
0105 case OMAP_L3_IA_CAM_1:
0106 case OMAP_L3_IA_CAM_2:
0107 case OMAP_L3_IA_CAM_3:
0108 return "CAM";
0109 case OMAP_L3_IA_DAP:
0110 return "DAP";
0111 case OMAP_L3_SDMA_WR_1:
0112 case OMAP_L3_SDMA_WR_2:
0113 return "SDMA_WR";
0114 case OMAP_L3_SDMA_RD_1:
0115 case OMAP_L3_SDMA_RD_2:
0116 case OMAP_L3_SDMA_RD_3:
0117 case OMAP_L3_SDMA_RD_4:
0118 return "SDMA_RD";
0119 case OMAP_L3_USBOTG:
0120 return "USB_OTG";
0121 case OMAP_L3_USBHOST:
0122 return "USB_HOST";
0123 default:
0124 return "UNKNOWN Initiator";
0125 }
0126 }
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140 static irqreturn_t omap3_l3_block_irq(struct omap3_l3 *l3,
0141 u64 error, int error_addr)
0142 {
0143 u8 code = omap3_l3_decode_error_code(error);
0144 u8 initid = omap3_l3_decode_initid(error);
0145 u8 multi = error & L3_ERROR_LOG_MULTI;
0146 u32 address = omap3_l3_decode_addr(error_addr);
0147
0148 pr_err("%s seen by %s %s at address %x\n",
0149 omap3_l3_code_string(code),
0150 omap3_l3_initiator_string(initid),
0151 multi ? "Multiple Errors" : "", address);
0152 WARN_ON(1);
0153
0154 return IRQ_HANDLED;
0155 }
0156
0157 static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
0158 {
0159 struct omap3_l3 *l3 = _l3;
0160 u64 status, clear;
0161 u64 error;
0162 u64 error_addr;
0163 u64 err_source = 0;
0164 void __iomem *base;
0165 int int_type;
0166 irqreturn_t ret = IRQ_NONE;
0167
0168 int_type = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
0169 if (!int_type) {
0170 status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_0);
0171
0172
0173
0174
0175
0176
0177 BUG_ON(status & L3_STATUS_0_TIMEOUT_MASK);
0178 } else {
0179 status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_1);
0180
0181 }
0182
0183
0184 err_source = __ffs(status);
0185
0186 base = l3->rt + omap3_l3_bases[int_type][err_source];
0187 error = omap3_l3_readll(base, L3_ERROR_LOG);
0188 if (error) {
0189 error_addr = omap3_l3_readll(base, L3_ERROR_LOG_ADDR);
0190 ret |= omap3_l3_block_irq(l3, error, error_addr);
0191 }
0192
0193
0194 clear = (L3_AGENT_STATUS_CLEAR_IA << int_type) |
0195 L3_AGENT_STATUS_CLEAR_TA;
0196 omap3_l3_writell(base, L3_AGENT_STATUS, clear);
0197
0198
0199 omap3_l3_writell(base, L3_ERROR_LOG, error);
0200
0201 return ret;
0202 }
0203
0204 #if IS_BUILTIN(CONFIG_OF)
0205 static const struct of_device_id omap3_l3_match[] = {
0206 {
0207 .compatible = "ti,omap3-l3-smx",
0208 },
0209 { },
0210 };
0211 MODULE_DEVICE_TABLE(of, omap3_l3_match);
0212 #endif
0213
0214 static int omap3_l3_probe(struct platform_device *pdev)
0215 {
0216 struct omap3_l3 *l3;
0217 struct resource *res;
0218 int ret;
0219
0220 l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
0221 if (!l3)
0222 return -ENOMEM;
0223
0224 platform_set_drvdata(pdev, l3);
0225
0226 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0227 if (!res) {
0228 dev_err(&pdev->dev, "couldn't find resource\n");
0229 ret = -ENODEV;
0230 goto err0;
0231 }
0232 l3->rt = ioremap(res->start, resource_size(res));
0233 if (!l3->rt) {
0234 dev_err(&pdev->dev, "ioremap failed\n");
0235 ret = -ENOMEM;
0236 goto err0;
0237 }
0238
0239 l3->debug_irq = platform_get_irq(pdev, 0);
0240 ret = request_irq(l3->debug_irq, omap3_l3_app_irq, IRQF_TRIGGER_RISING,
0241 "l3-debug-irq", l3);
0242 if (ret) {
0243 dev_err(&pdev->dev, "couldn't request debug irq\n");
0244 goto err1;
0245 }
0246
0247 l3->app_irq = platform_get_irq(pdev, 1);
0248 ret = request_irq(l3->app_irq, omap3_l3_app_irq, IRQF_TRIGGER_RISING,
0249 "l3-app-irq", l3);
0250 if (ret) {
0251 dev_err(&pdev->dev, "couldn't request app irq\n");
0252 goto err2;
0253 }
0254
0255 return 0;
0256
0257 err2:
0258 free_irq(l3->debug_irq, l3);
0259 err1:
0260 iounmap(l3->rt);
0261 err0:
0262 kfree(l3);
0263 return ret;
0264 }
0265
0266 static int omap3_l3_remove(struct platform_device *pdev)
0267 {
0268 struct omap3_l3 *l3 = platform_get_drvdata(pdev);
0269
0270 free_irq(l3->app_irq, l3);
0271 free_irq(l3->debug_irq, l3);
0272 iounmap(l3->rt);
0273 kfree(l3);
0274
0275 return 0;
0276 }
0277
0278 static struct platform_driver omap3_l3_driver = {
0279 .probe = omap3_l3_probe,
0280 .remove = omap3_l3_remove,
0281 .driver = {
0282 .name = "omap_l3_smx",
0283 .of_match_table = of_match_ptr(omap3_l3_match),
0284 },
0285 };
0286
0287 static int __init omap3_l3_init(void)
0288 {
0289 return platform_driver_register(&omap3_l3_driver);
0290 }
0291 postcore_initcall_sync(omap3_l3_init);
0292
0293 static void __exit omap3_l3_exit(void)
0294 {
0295 platform_driver_unregister(&omap3_l3_driver);
0296 }
0297 module_exit(omap3_l3_exit);
0298
0299 MODULE_AUTHOR("Felipe Balbi");
0300 MODULE_AUTHOR("Santosh Shilimkar");
0301 MODULE_AUTHOR("Sricharan R");
0302 MODULE_DESCRIPTION("OMAP3XXX L3 Interconnect Driver");
0303 MODULE_LICENSE("GPL");