Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
[sfrench/cifs-2.6.git] / arch / mips / ralink / ill_acc.c
1 /*
2  * This program is free software; you can redistribute it and/or modify it
3  * under the terms of the GNU General Public License version 2 as published
4  * by the Free Software Foundation.
5  *
6  * Copyright (C) 2013 John Crispin <john@phrozen.org>
7  */
8
9 #include <linux/interrupt.h>
10 #include <linux/of_platform.h>
11 #include <linux/of_irq.h>
12
13 #include <asm/mach-ralink/ralink_regs.h>
14
15 #define REG_ILL_ACC_ADDR        0x10
16 #define REG_ILL_ACC_TYPE        0x14
17
18 #define ILL_INT_STATUS          BIT(31)
19 #define ILL_ACC_WRITE           BIT(30)
20 #define ILL_ACC_LEN_M           0xff
21 #define ILL_ACC_OFF_M           0xf
22 #define ILL_ACC_OFF_S           16
23 #define ILL_ACC_ID_M            0x7
24 #define ILL_ACC_ID_S            8
25
26 #define DRV_NAME                "ill_acc"
27
28 static const char * const ill_acc_ids[] = {
29         "cpu", "dma", "ppe", "pdma rx", "pdma tx", "pci/e", "wmac", "usb",
30 };
31
32 static irqreturn_t ill_acc_irq_handler(int irq, void *_priv)
33 {
34         struct device *dev = (struct device *) _priv;
35         u32 addr = rt_memc_r32(REG_ILL_ACC_ADDR);
36         u32 type = rt_memc_r32(REG_ILL_ACC_TYPE);
37
38         dev_err(dev, "illegal %s access from %s - addr:0x%08x offset:%d len:%d\n",
39                 (type & ILL_ACC_WRITE) ? ("write") : ("read"),
40                 ill_acc_ids[(type >> ILL_ACC_ID_S) & ILL_ACC_ID_M],
41                 addr, (type >> ILL_ACC_OFF_S) & ILL_ACC_OFF_M,
42                 type & ILL_ACC_LEN_M);
43
44         rt_memc_w32(ILL_INT_STATUS, REG_ILL_ACC_TYPE);
45
46         return IRQ_HANDLED;
47 }
48
49 static int __init ill_acc_of_setup(void)
50 {
51         struct platform_device *pdev;
52         struct device_node *np;
53         int irq;
54
55         /* somehow this driver breaks on RT5350 */
56         if (of_machine_is_compatible("ralink,rt5350-soc"))
57                 return -EINVAL;
58
59         np = of_find_compatible_node(NULL, NULL, "ralink,rt3050-memc");
60         if (!np)
61                 return -EINVAL;
62
63         pdev = of_find_device_by_node(np);
64         if (!pdev) {
65                 pr_err("%pOFn: failed to lookup pdev\n", np);
66                 return -EINVAL;
67         }
68
69         irq = irq_of_parse_and_map(np, 0);
70         if (!irq) {
71                 dev_err(&pdev->dev, "failed to get irq\n");
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                 return -EINVAL;
78         }
79
80         rt_memc_w32(ILL_INT_STATUS, REG_ILL_ACC_TYPE);
81
82         dev_info(&pdev->dev, "irq registered\n");
83
84         return 0;
85 }
86
87 arch_initcall(ill_acc_of_setup);