1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
25433acd8SJohn Crispin /*
35433acd8SJohn Crispin *
497b92108SJohn Crispin * Copyright (C) 2013 John Crispin <john@phrozen.org>
55433acd8SJohn Crispin */
65433acd8SJohn Crispin
75433acd8SJohn Crispin #include <linux/interrupt.h>
8*e1a7566dSRob Herring #include <linux/of.h>
95433acd8SJohn Crispin #include <linux/of_platform.h>
105433acd8SJohn Crispin #include <linux/of_irq.h>
11*e1a7566dSRob Herring #include <linux/platform_device.h>
125433acd8SJohn Crispin
135433acd8SJohn Crispin #include <asm/mach-ralink/ralink_regs.h>
145433acd8SJohn Crispin
155433acd8SJohn Crispin #define REG_ILL_ACC_ADDR 0x10
165433acd8SJohn Crispin #define REG_ILL_ACC_TYPE 0x14
175433acd8SJohn Crispin
185433acd8SJohn Crispin #define ILL_INT_STATUS BIT(31)
195433acd8SJohn Crispin #define ILL_ACC_WRITE BIT(30)
205433acd8SJohn Crispin #define ILL_ACC_LEN_M 0xff
215433acd8SJohn Crispin #define ILL_ACC_OFF_M 0xf
225433acd8SJohn Crispin #define ILL_ACC_OFF_S 16
235433acd8SJohn Crispin #define ILL_ACC_ID_M 0x7
245433acd8SJohn Crispin #define ILL_ACC_ID_S 8
255433acd8SJohn Crispin
265433acd8SJohn Crispin #define DRV_NAME "ill_acc"
275433acd8SJohn Crispin
285433acd8SJohn Crispin static const char * const ill_acc_ids[] = {
295433acd8SJohn Crispin "cpu", "dma", "ppe", "pdma rx", "pdma tx", "pci/e", "wmac", "usb",
305433acd8SJohn Crispin };
315433acd8SJohn Crispin
ill_acc_irq_handler(int irq,void * _priv)325433acd8SJohn Crispin static irqreturn_t ill_acc_irq_handler(int irq, void *_priv)
335433acd8SJohn Crispin {
345433acd8SJohn Crispin struct device *dev = (struct device *) _priv;
355433acd8SJohn Crispin u32 addr = rt_memc_r32(REG_ILL_ACC_ADDR);
365433acd8SJohn Crispin u32 type = rt_memc_r32(REG_ILL_ACC_TYPE);
375433acd8SJohn Crispin
385433acd8SJohn Crispin dev_err(dev, "illegal %s access from %s - addr:0x%08x offset:%d len:%d\n",
395433acd8SJohn Crispin (type & ILL_ACC_WRITE) ? ("write") : ("read"),
405433acd8SJohn Crispin ill_acc_ids[(type >> ILL_ACC_ID_S) & ILL_ACC_ID_M],
415433acd8SJohn Crispin addr, (type >> ILL_ACC_OFF_S) & ILL_ACC_OFF_M,
425433acd8SJohn Crispin type & ILL_ACC_LEN_M);
435433acd8SJohn Crispin
449dd6f1c1SJonas Gorski rt_memc_w32(ILL_INT_STATUS, REG_ILL_ACC_TYPE);
455433acd8SJohn Crispin
465433acd8SJohn Crispin return IRQ_HANDLED;
475433acd8SJohn Crispin }
485433acd8SJohn Crispin
ill_acc_of_setup(void)495433acd8SJohn Crispin static int __init ill_acc_of_setup(void)
505433acd8SJohn Crispin {
515433acd8SJohn Crispin struct platform_device *pdev;
525433acd8SJohn Crispin struct device_node *np;
535433acd8SJohn Crispin int irq;
545433acd8SJohn Crispin
555433acd8SJohn Crispin /* somehow this driver breaks on RT5350 */
565433acd8SJohn Crispin if (of_machine_is_compatible("ralink,rt5350-soc"))
575433acd8SJohn Crispin return -EINVAL;
585433acd8SJohn Crispin
595433acd8SJohn Crispin np = of_find_compatible_node(NULL, NULL, "ralink,rt3050-memc");
605433acd8SJohn Crispin if (!np)
615433acd8SJohn Crispin return -EINVAL;
625433acd8SJohn Crispin
635433acd8SJohn Crispin pdev = of_find_device_by_node(np);
645433acd8SJohn Crispin if (!pdev) {
659475e90fSRob Herring pr_err("%pOFn: failed to lookup pdev\n", np);
664a0a1436SHangyu Hua of_node_put(np);
675433acd8SJohn Crispin return -EINVAL;
685433acd8SJohn Crispin }
695433acd8SJohn Crispin
705433acd8SJohn Crispin irq = irq_of_parse_and_map(np, 0);
71405db98bSWang Qing of_node_put(np);
725433acd8SJohn Crispin if (!irq) {
735433acd8SJohn Crispin dev_err(&pdev->dev, "failed to get irq\n");
74defed0bbSyu kuai put_device(&pdev->dev);
755433acd8SJohn Crispin return -EINVAL;
765433acd8SJohn Crispin }
775433acd8SJohn Crispin
785433acd8SJohn Crispin if (request_irq(irq, ill_acc_irq_handler, 0, "ill_acc", &pdev->dev)) {
795433acd8SJohn Crispin dev_err(&pdev->dev, "failed to request irq\n");
80defed0bbSyu kuai put_device(&pdev->dev);
815433acd8SJohn Crispin return -EINVAL;
825433acd8SJohn Crispin }
835433acd8SJohn Crispin
845433acd8SJohn Crispin rt_memc_w32(ILL_INT_STATUS, REG_ILL_ACC_TYPE);
855433acd8SJohn Crispin
865433acd8SJohn Crispin dev_info(&pdev->dev, "irq registered\n");
875433acd8SJohn Crispin
885433acd8SJohn Crispin return 0;
895433acd8SJohn Crispin }
905433acd8SJohn Crispin
915433acd8SJohn Crispin arch_initcall(ill_acc_of_setup);
92