From patchwork Sun May 1 04:59:18 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 8988181 Return-Path: X-Original-To: patchwork-linux-sh@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id DC90C9FC46 for ; Sun, 1 May 2016 05:18:25 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BE15F202FF for ; Sun, 1 May 2016 05:18:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 948A4202EC for ; Sun, 1 May 2016 05:18:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750743AbcEAFST (ORCPT ); Sun, 1 May 2016 01:18:19 -0400 Received: from mail1.asahi-net.or.jp ([202.224.39.197]:55809 "EHLO mail1.asahi-net.or.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750771AbcEAFSS (ORCPT ); Sun, 1 May 2016 01:18:18 -0400 Received: from sa76r4 (y081184.ppp.asahi-net.or.jp [118.243.81.184]) by mail1.asahi-net.or.jp (Postfix) with ESMTP id 0B3561D320; Sun, 1 May 2016 13:59:27 +0900 (JST) Received: from localhost (localhost [127.0.0.1]) by sa76r4 (Postfix) with ESMTP id D850F12164; Sun, 1 May 2016 13:59:26 +0900 (JST) X-Virus-Scanned: Debian amavisd-new at sa76r4.localdomain Received: from sa76r4 ([127.0.0.1]) by localhost (sa76r4.localdomain [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id JnQUDdrBlXVa; Sun, 1 May 2016 13:59:26 +0900 (JST) Received: by sa76r4 (Postfix, from userid 1000) id 8C066A53F; Sun, 1 May 2016 13:59:26 +0900 (JST) From: Yoshinori Sato To: linux-sh@vger.kernel.org, linux-kerel@vger.kernel.org Cc: Yoshinori Sato Subject: [PATCH 08/12] intc: sh: Renesas Super H INTC driver Date: Sun, 1 May 2016 13:59:18 +0900 Message-Id: <1462078763-27135-9-git-send-email-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1462078763-27135-1-git-send-email-ysato@users.sourceforge.jp> References: <1462078763-27135-1-git-send-email-ysato@users.sourceforge.jp> Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org X-Spam-Status: No, score=-7.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP SuperH IPR based driver. Signed-off-by: Yoshinori Sato --- .../interrupt-controller/renesas,sh7751-intc.txt | 25 ++++ drivers/irqchip/Kconfig | 5 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-renesas-shipr.c | 138 +++++++++++++++++++++ 4 files changed, 169 insertions(+) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/renesas,sh7751-intc.txt create mode 100644 drivers/irqchip/irq-renesas-shipr.c diff --git a/Documentation/devicetree/bindings/interrupt-controller/renesas,sh7751-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/renesas,sh7751-intc.txt new file mode 100644 index 0000000..6d9bf6c --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,sh7751-intc.txt @@ -0,0 +1,25 @@ +DT bindings for the SH7751 interrupt controller + +Required properties: + + - compatible: has to be "renesas,sh7751-intc". + + - reg: Base address and length of interrupt controller register + and extend register. + + - interrupt-controller: Identifies the node as an interrupt controller. + + - #interrupt-cells: has to be <2>: an interrupt index and flags, as defined + in interrupts.txt in this directory. + +Example +------- + + shintc: interrupt-controller@ffd00000 { + compatible = "renesas,sh7751-intc"; + #interrupt-cells = <2>; + #address-cells = <1>; + #size-cells = <1>; + interrupt-controller; + reg = <0xffd00000 14>, <0xfe080000 128>; + }; diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 3e12479..273f19d 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -244,3 +244,8 @@ config IRQ_MXS config MVEBU_ODMI bool select GENERIC_MSI_IRQ_DOMAIN + +config RENESAS_SH_INTC + def_bool y if SH_DEVICE_TREE + select IRQ_DOMAIN + select IRQ_DOMAIN_HIERARCHY diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index b03cfcb..3f9fc5c 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -65,3 +65,4 @@ obj-$(CONFIG_INGENIC_IRQ) += irq-ingenic.o obj-$(CONFIG_IMX_GPCV2) += irq-imx-gpcv2.o obj-$(CONFIG_PIC32_EVIC) += irq-pic32-evic.o obj-$(CONFIG_MVEBU_ODMI) += irq-mvebu-odmi.o +obj-$(CONFIG_RENESAS_SH_INTC) += irq-renesas-shipr.o irq-io-landisk.o diff --git a/drivers/irqchip/irq-renesas-shipr.c b/drivers/irqchip/irq-renesas-shipr.c new file mode 100644 index 0000000..67cce6a --- /dev/null +++ b/drivers/irqchip/irq-renesas-shipr.c @@ -0,0 +1,138 @@ +/* + * SH IPR-INTC interrupt contoller driver + * + * Copyright 2016 Yoshinori Sato + */ + +#include +#include +#include +#include +#include +#include + +static struct sh7751_intc_regs { + void *icr; + void *ipr; + void *intpri00; + void *intreq00; + void *intmsk00; + void *intmskclr00; +} sh7751_regs; + +static const unsigned int ipr_table[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0 - 7 */ + 0x41, 0xff, 0xff, 0x40, 0xff, 0xff, 0xff, 0xff, /* 8 - 15 */ + 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x11, /* 16 - 23 */ + 0x11, 0x11, 0x11, 0x13, 0x12, 0x12, 0xff, 0xff, /* 24 - 31 */ + 0x30, 0x33, 0x32, 0x32, 0x32, 0x32, 0x32, 0x21, /* 32 - 39 */ + 0x21, 0x21, 0x21, 0x21, 0x32, 0x32, 0x32, 0x32, /* 40 - 47 */ + 0xff, 0xff, 0xff, 0x40, 0xff, 0xff, 0xff, 0xff, /* 48 - 55 */ + 0xff, 0xff, 0xff, 0x40, 0xff, 0xff, 0xff, 0xff, /* 56 - 63 */ +}; + +static const unsigned int pri_table[] = { + 0, 4, 4, 4, 4, 4, 4, 4, + 8, 32, 32, 32, 12, 32, 32, 32, +}; + +static void sh_disable_irq(struct irq_data *data) +{ + int pos; + unsigned int addr; + unsigned long pri; + int irq = data->irq; + struct sh7751_intc_regs *reg = data->chip_data; + + if (irq < 64) { + if (ipr_table[irq] != 0xff) { + addr = (ipr_table[irq] & 0xf0) >> 2; + pos = (ipr_table[irq] & 0x0f) << 4; + pri = ~(0x000f << pos); + pri &= __raw_readw(reg->ipr + addr); + __raw_writew(pri, reg->ipr + addr); + } + } else { + if (pri_table[irq - 64] < 32) { + pos = pri_table[irq - 64]; + pri = ~(0x000f << pos); + pri &= __raw_readw(reg->intpri00); + __raw_writew(pri, reg->intpri00); + } + } +} + +static void sh_enable_irq(struct irq_data *data) +{ + int pos; + unsigned int addr; + unsigned long pri; + int irq = data->irq; + struct sh7751_intc_regs *reg = data->chip_data; + + if (irq < 64) { + if (ipr_table[irq] != 0xff) { + addr = (ipr_table[irq] & 0xf0) >> 2; + pos = (ipr_table[irq] & 0x0f) * 4; + pri = ~(0x000f << pos); + pri &= __raw_readw(reg->ipr + addr); + pri |= 1 << pos; + __raw_writew(pri, reg->ipr + addr); + } + } else { + if (pri_table[irq - 64] < 32) { + pos = pri_table[irq - 64]; + pri = ~(0x000f << pos); + pri &= __raw_readw(reg->intpri00); + pri |= 1 << pos; + __raw_writew(pri, reg->intpri00); + } + } +} + +struct irq_chip sh_irq_chip = { + .name = "SH-IPR", + .irq_unmask = sh_enable_irq, + .irq_mask = sh_disable_irq, +}; + +static __init int irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw_irq_num) +{ + irq_set_chip_and_handler(virq, &sh_irq_chip, handle_level_irq); + irq_get_irq_data(virq)->chip_data = h->host_data; + irq_modify_status(virq, IRQ_NOREQUEST, IRQ_NOPROBE); + + return 0; +} + +static struct irq_domain_ops irq_ops = { + .map = irq_map, + .xlate = irq_domain_xlate_onecell, +}; + +static int __init sh_intc_of_init(struct device_node *intc, + struct device_node *parent) +{ + struct irq_domain *domain; + void *intc_baseaddr; + void *intc_baseaddr2; + + intc_baseaddr = of_iomap(intc, 0); + intc_baseaddr2 = of_iomap(intc, 1); + BUG_ON(!intc_baseaddr); + + sh7751_regs.icr = intc_baseaddr; + sh7751_regs.ipr = intc_baseaddr + 4; + sh7751_regs.intpri00 = intc_baseaddr2; + sh7751_regs.intreq00 = intc_baseaddr2 + 0x20; + sh7751_regs.intmsk00 = intc_baseaddr2 + 0x40; + sh7751_regs.intmskclr00 = intc_baseaddr2 + 0x60; + + domain = irq_domain_add_linear(intc, NR_IRQS, &irq_ops, &sh7751_regs); + BUG_ON(!domain); + irq_set_default_host(domain); + return 0; +} + +IRQCHIP_DECLARE(sh_7751_intc, "renesas,sh7751-intc", sh_intc_of_init);