18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2013 John Crispin <john@phrozen.org> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 88c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 98c2ecf20Sopenharmony_ci#include <linux/of_irq.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <asm/mach-ralink/ralink_regs.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define REG_ILL_ACC_ADDR 0x10 148c2ecf20Sopenharmony_ci#define REG_ILL_ACC_TYPE 0x14 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define ILL_INT_STATUS BIT(31) 178c2ecf20Sopenharmony_ci#define ILL_ACC_WRITE BIT(30) 188c2ecf20Sopenharmony_ci#define ILL_ACC_LEN_M 0xff 198c2ecf20Sopenharmony_ci#define ILL_ACC_OFF_M 0xf 208c2ecf20Sopenharmony_ci#define ILL_ACC_OFF_S 16 218c2ecf20Sopenharmony_ci#define ILL_ACC_ID_M 0x7 228c2ecf20Sopenharmony_ci#define ILL_ACC_ID_S 8 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define DRV_NAME "ill_acc" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic const char * const ill_acc_ids[] = { 278c2ecf20Sopenharmony_ci "cpu", "dma", "ppe", "pdma rx", "pdma tx", "pci/e", "wmac", "usb", 288c2ecf20Sopenharmony_ci}; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic irqreturn_t ill_acc_irq_handler(int irq, void *_priv) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci struct device *dev = (struct device *) _priv; 338c2ecf20Sopenharmony_ci u32 addr = rt_memc_r32(REG_ILL_ACC_ADDR); 348c2ecf20Sopenharmony_ci u32 type = rt_memc_r32(REG_ILL_ACC_TYPE); 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci dev_err(dev, "illegal %s access from %s - addr:0x%08x offset:%d len:%d\n", 378c2ecf20Sopenharmony_ci (type & ILL_ACC_WRITE) ? ("write") : ("read"), 388c2ecf20Sopenharmony_ci ill_acc_ids[(type >> ILL_ACC_ID_S) & ILL_ACC_ID_M], 398c2ecf20Sopenharmony_ci addr, (type >> ILL_ACC_OFF_S) & ILL_ACC_OFF_M, 408c2ecf20Sopenharmony_ci type & ILL_ACC_LEN_M); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci rt_memc_w32(ILL_INT_STATUS, REG_ILL_ACC_TYPE); 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci return IRQ_HANDLED; 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic int __init ill_acc_of_setup(void) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci struct platform_device *pdev; 508c2ecf20Sopenharmony_ci struct device_node *np; 518c2ecf20Sopenharmony_ci int irq; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci /* somehow this driver breaks on RT5350 */ 548c2ecf20Sopenharmony_ci if (of_machine_is_compatible("ralink,rt5350-soc")) 558c2ecf20Sopenharmony_ci return -EINVAL; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "ralink,rt3050-memc"); 588c2ecf20Sopenharmony_ci if (!np) 598c2ecf20Sopenharmony_ci return -EINVAL; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci pdev = of_find_device_by_node(np); 628c2ecf20Sopenharmony_ci if (!pdev) { 638c2ecf20Sopenharmony_ci pr_err("%pOFn: failed to lookup pdev\n", np); 648c2ecf20Sopenharmony_ci of_node_put(np); 658c2ecf20Sopenharmony_ci return -EINVAL; 668c2ecf20Sopenharmony_ci } 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci irq = irq_of_parse_and_map(np, 0); 698c2ecf20Sopenharmony_ci if (!irq) { 708c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to get irq\n"); 718c2ecf20Sopenharmony_ci put_device(&pdev->dev); 728c2ecf20Sopenharmony_ci return -EINVAL; 738c2ecf20Sopenharmony_ci } 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci if (request_irq(irq, ill_acc_irq_handler, 0, "ill_acc", &pdev->dev)) { 768c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to request irq\n"); 778c2ecf20Sopenharmony_ci put_device(&pdev->dev); 788c2ecf20Sopenharmony_ci return -EINVAL; 798c2ecf20Sopenharmony_ci } 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci rt_memc_w32(ILL_INT_STATUS, REG_ILL_ACC_TYPE); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "irq registered\n"); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci return 0; 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ciarch_initcall(ill_acc_of_setup); 89