diff options
Diffstat (limited to 'arch/mips/ralink/ill_acc.c')
-rw-r--r-- | arch/mips/ralink/ill_acc.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/arch/mips/ralink/ill_acc.c b/arch/mips/ralink/ill_acc.c new file mode 100644 index 000000000..bea857c9d --- /dev/null +++ b/arch/mips/ralink/ill_acc.c | |||
@@ -0,0 +1,88 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /* | ||
3 | * | ||
4 | * Copyright (C) 2013 John Crispin <john@phrozen.org> | ||
5 | */ | ||
6 | |||
7 | #include <linux/interrupt.h> | ||
8 | #include <linux/of_platform.h> | ||
9 | #include <linux/of_irq.h> | ||
10 | |||
11 | #include <asm/mach-ralink/ralink_regs.h> | ||
12 | |||
13 | #define REG_ILL_ACC_ADDR 0x10 | ||
14 | #define REG_ILL_ACC_TYPE 0x14 | ||
15 | |||
16 | #define ILL_INT_STATUS BIT(31) | ||
17 | #define ILL_ACC_WRITE BIT(30) | ||
18 | #define ILL_ACC_LEN_M 0xff | ||
19 | #define ILL_ACC_OFF_M 0xf | ||
20 | #define ILL_ACC_OFF_S 16 | ||
21 | #define ILL_ACC_ID_M 0x7 | ||
22 | #define ILL_ACC_ID_S 8 | ||
23 | |||
24 | #define DRV_NAME "ill_acc" | ||
25 | |||
26 | static const char * const ill_acc_ids[] = { | ||
27 | "cpu", "dma", "ppe", "pdma rx", "pdma tx", "pci/e", "wmac", "usb", | ||
28 | }; | ||
29 | |||
30 | static irqreturn_t ill_acc_irq_handler(int irq, void *_priv) | ||
31 | { | ||
32 | struct device *dev = (struct device *) _priv; | ||
33 | u32 addr = rt_memc_r32(REG_ILL_ACC_ADDR); | ||
34 | u32 type = rt_memc_r32(REG_ILL_ACC_TYPE); | ||
35 | |||
36 | dev_err(dev, "illegal %s access from %s - addr:0x%08x offset:%d len:%d\n", | ||
37 | (type & ILL_ACC_WRITE) ? ("write") : ("read"), | ||
38 | ill_acc_ids[(type >> ILL_ACC_ID_S) & ILL_ACC_ID_M], | ||
39 | addr, (type >> ILL_ACC_OFF_S) & ILL_ACC_OFF_M, | ||
40 | type & ILL_ACC_LEN_M); | ||
41 | |||
42 | rt_memc_w32(ILL_INT_STATUS, REG_ILL_ACC_TYPE); | ||
43 | |||
44 | return IRQ_HANDLED; | ||
45 | } | ||
46 | |||
47 | static int __init ill_acc_of_setup(void) | ||
48 | { | ||
49 | struct platform_device *pdev; | ||
50 | struct device_node *np; | ||
51 | int irq; | ||
52 | |||
53 | /* somehow this driver breaks on RT5350 */ | ||
54 | if (of_machine_is_compatible("ralink,rt5350-soc")) | ||
55 | return -EINVAL; | ||
56 | |||
57 | np = of_find_compatible_node(NULL, NULL, "ralink,rt3050-memc"); | ||
58 | if (!np) | ||
59 | return -EINVAL; | ||
60 | |||
61 | pdev = of_find_device_by_node(np); | ||
62 | if (!pdev) { | ||
63 | pr_err("%pOFn: failed to lookup pdev\n", np); | ||
64 | of_node_put(np); | ||
65 | return -EINVAL; | ||
66 | } | ||
67 | |||
68 | irq = irq_of_parse_and_map(np, 0); | ||
69 | if (!irq) { | ||
70 | dev_err(&pdev->dev, "failed to get irq\n"); | ||
71 | put_device(&pdev->dev); | ||
72 | return -EINVAL; | ||
73 | } | ||
74 | |||
75 | if (request_irq(irq, ill_acc_irq_handler, 0, "ill_acc", &pdev->dev)) { | ||
76 | dev_err(&pdev->dev, "failed to request irq\n"); | ||
77 | put_device(&pdev->dev); | ||
78 | return -EINVAL; | ||
79 | } | ||
80 | |||
81 | rt_memc_w32(ILL_INT_STATUS, REG_ILL_ACC_TYPE); | ||
82 | |||
83 | dev_info(&pdev->dev, "irq registered\n"); | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | arch_initcall(ill_acc_of_setup); | ||