^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * OMAP3XXX L3 Interconnect Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2011 Texas Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Felipe Balbi <balbi@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Santosh Shilimkar <santosh.shilimkar@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Sricharan <r.sricharan@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "omap_l3_smx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static inline u64 omap3_l3_readll(void __iomem *base, u16 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) return __raw_readll(base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static inline void omap3_l3_writell(void __iomem *base, u16 reg, u64 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) __raw_writell(value, base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static inline enum omap3_l3_code omap3_l3_decode_error_code(u64 error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return (error & 0x0f000000) >> L3_ERROR_LOG_CODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static inline u32 omap3_l3_decode_addr(u64 error_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return error_addr & 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static inline unsigned omap3_l3_decode_cmd(u64 error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return (error & 0x07) >> L3_ERROR_LOG_CMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static inline enum omap3_l3_initiator_id omap3_l3_decode_initid(u64 error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return (error & 0xff00) >> L3_ERROR_LOG_INITID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static inline unsigned omap3_l3_decode_req_info(u64 error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return (error >> 32) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static char *omap3_l3_code_string(u8 code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) switch (code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) case OMAP_L3_CODE_NOERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return "No Error";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) case OMAP_L3_CODE_UNSUP_CMD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return "Unsupported Command";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) case OMAP_L3_CODE_ADDR_HOLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return "Address Hole";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) case OMAP_L3_CODE_PROTECT_VIOLATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return "Protection Violation";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) case OMAP_L3_CODE_IN_BAND_ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return "In-band Error";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) case OMAP_L3_CODE_REQ_TOUT_NOT_ACCEPT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return "Request Timeout Not Accepted";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) case OMAP_L3_CODE_REQ_TOUT_NO_RESP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return "Request Timeout, no response";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return "UNKNOWN error";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static char *omap3_l3_initiator_string(u8 initid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) switch (initid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) case OMAP_L3_LCD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return "LCD";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) case OMAP_L3_SAD2D:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return "SAD2D";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) case OMAP_L3_IA_MPU_SS_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) case OMAP_L3_IA_MPU_SS_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) case OMAP_L3_IA_MPU_SS_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) case OMAP_L3_IA_MPU_SS_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) case OMAP_L3_IA_MPU_SS_5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return "MPU";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) case OMAP_L3_IA_IVA_SS_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) case OMAP_L3_IA_IVA_SS_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) case OMAP_L3_IA_IVA_SS_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return "IVA_SS";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) case OMAP_L3_IA_IVA_SS_DMA_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) case OMAP_L3_IA_IVA_SS_DMA_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) case OMAP_L3_IA_IVA_SS_DMA_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) case OMAP_L3_IA_IVA_SS_DMA_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) case OMAP_L3_IA_IVA_SS_DMA_5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) case OMAP_L3_IA_IVA_SS_DMA_6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return "IVA_SS_DMA";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) case OMAP_L3_IA_SGX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return "SGX";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) case OMAP_L3_IA_CAM_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) case OMAP_L3_IA_CAM_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) case OMAP_L3_IA_CAM_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return "CAM";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) case OMAP_L3_IA_DAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return "DAP";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) case OMAP_L3_SDMA_WR_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) case OMAP_L3_SDMA_WR_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return "SDMA_WR";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) case OMAP_L3_SDMA_RD_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) case OMAP_L3_SDMA_RD_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) case OMAP_L3_SDMA_RD_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) case OMAP_L3_SDMA_RD_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return "SDMA_RD";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) case OMAP_L3_USBOTG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return "USB_OTG";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) case OMAP_L3_USBHOST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return "USB_HOST";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return "UNKNOWN Initiator";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * omap3_l3_block_irq - handles a register block's irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * @l3: struct omap3_l3 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * @base: register block base address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * @error: L3_ERROR_LOG register of our block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * Called in hard-irq context. Caller should take care of locking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * OMAP36xx TRM gives, on page 2001, Figure 9-10, the Typical Error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * Analysis Sequence, we are following that sequence here, please
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * refer to that Figure for more information on the subject.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static irqreturn_t omap3_l3_block_irq(struct omap3_l3 *l3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) u64 error, int error_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) u8 code = omap3_l3_decode_error_code(error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) u8 initid = omap3_l3_decode_initid(error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) u8 multi = error & L3_ERROR_LOG_MULTI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) u32 address = omap3_l3_decode_addr(error_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) pr_err("%s seen by %s %s at address %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) omap3_l3_code_string(code),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) omap3_l3_initiator_string(initid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) multi ? "Multiple Errors" : "", address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct omap3_l3 *l3 = _l3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) u64 status, clear;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) u64 error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) u64 error_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) u64 err_source = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) int int_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) irqreturn_t ret = IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) int_type = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (!int_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * if we have a timeout error, there's nothing we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * do besides rebooting the board. So let's BUG on any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * of such errors and handle the others. timeout error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * is severe and not expected to occur.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) BUG_ON(status & L3_STATUS_0_TIMEOUT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /* No timeout error for debug sources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* identify the error source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) err_source = __ffs(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) base = l3->rt + omap3_l3_bases[int_type][err_source];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) error = omap3_l3_readll(base, L3_ERROR_LOG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) error_addr = omap3_l3_readll(base, L3_ERROR_LOG_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ret |= omap3_l3_block_irq(l3, error, error_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /* Clear the status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) clear = (L3_AGENT_STATUS_CLEAR_IA << int_type) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) L3_AGENT_STATUS_CLEAR_TA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) omap3_l3_writell(base, L3_AGENT_STATUS, clear);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /* clear the error log register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) omap3_l3_writell(base, L3_ERROR_LOG, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) #if IS_BUILTIN(CONFIG_OF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static const struct of_device_id omap3_l3_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .compatible = "ti,omap3-l3-smx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) MODULE_DEVICE_TABLE(of, omap3_l3_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static int omap3_l3_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct omap3_l3 *l3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (!l3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) platform_set_drvdata(pdev, l3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) dev_err(&pdev->dev, "couldn't find resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) goto err0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) l3->rt = ioremap(res->start, resource_size(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (!l3->rt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) dev_err(&pdev->dev, "ioremap failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) goto err0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) l3->debug_irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ret = request_irq(l3->debug_irq, omap3_l3_app_irq, IRQF_TRIGGER_RISING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) "l3-debug-irq", l3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) dev_err(&pdev->dev, "couldn't request debug irq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) goto err1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) l3->app_irq = platform_get_irq(pdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) ret = request_irq(l3->app_irq, omap3_l3_app_irq, IRQF_TRIGGER_RISING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) "l3-app-irq", l3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) dev_err(&pdev->dev, "couldn't request app irq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) goto err2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) err2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) free_irq(l3->debug_irq, l3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) err1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) iounmap(l3->rt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) err0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) kfree(l3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static int omap3_l3_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct omap3_l3 *l3 = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) free_irq(l3->app_irq, l3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) free_irq(l3->debug_irq, l3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) iounmap(l3->rt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) kfree(l3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static struct platform_driver omap3_l3_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) .probe = omap3_l3_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .remove = omap3_l3_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .name = "omap_l3_smx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .of_match_table = of_match_ptr(omap3_l3_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static int __init omap3_l3_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return platform_driver_register(&omap3_l3_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) postcore_initcall_sync(omap3_l3_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static void __exit omap3_l3_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) platform_driver_unregister(&omap3_l3_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) module_exit(omap3_l3_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) MODULE_AUTHOR("Felipe Balbi");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) MODULE_AUTHOR("Santosh Shilimkar");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) MODULE_AUTHOR("Sricharan R");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) MODULE_DESCRIPTION("OMAP3XXX L3 Interconnect Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) MODULE_LICENSE("GPL");