cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

omap_l3_smx.c (7223B)


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