Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * OMAP3XXX L3 Interconnect Driver
0004  *
0005  * Copyright (C) 2011 Texas Corporation
0006  *  Felipe Balbi <balbi@ti.com>
0007  *  Santosh Shilimkar <santosh.shilimkar@ti.com>
0008  *  Sricharan <r.sricharan@ti.com>
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  * omap3_l3_block_irq - handles a register block's irq
0130  * @l3: struct omap3_l3 *
0131  * @base: register block base address
0132  * @error: L3_ERROR_LOG register of our block
0133  *
0134  * Called in hard-irq context. Caller should take care of locking
0135  *
0136  * OMAP36xx TRM gives, on page 2001, Figure 9-10, the Typical Error
0137  * Analysis Sequence, we are following that sequence here, please
0138  * refer to that Figure for more information on the subject.
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          * if we have a timeout error, there's nothing we can
0173          * do besides rebooting the board. So let's BUG on any
0174          * of such errors and handle the others. timeout error
0175          * is severe and not expected to occur.
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         /* No timeout error for debug sources */
0181     }
0182 
0183     /* identify the error source */
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     /* Clear the status register */
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     /* clear the error log register */
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");