Received: by 10.213.65.68 with SMTP id h4csp1059144imn; Sun, 18 Mar 2018 12:54:45 -0700 (PDT) X-Google-Smtp-Source: AG47ELtAsbh+nG6ppVJOfsSIkr6fOlIO4xlOEnx38wI/VvrTw3mlfYXuPOXc6P2GctWmt2Tn7/OU X-Received: by 2002:a17:902:bc04:: with SMTP id n4-v6mr9808577pls.97.1521402885731; Sun, 18 Mar 2018 12:54:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521402885; cv=none; d=google.com; s=arc-20160816; b=t+kxJQ3+SnGkuST+FCS2kTnD92u6v1HMH/M3zaF363ydQlcM35r5yeYYPKHiHBKN7m RWznqqVGkmrm6ISKnZfQBK7HSpqDFLefh4qQjOw36Q6PwjX0R+5uevIooHwoFofpcxSn eEmL0CwvXBTjE+EogpkiRSOqtLIMArWh58SivKgOxyV7VbNya3V0z+pmNhj4NiiCFxWB 0kfVowFRe1Bwx3lrhHY7Q1tFMzDk3nyWSYmMimFG74lpsXkZ3IQAy2hiRy4x/Th/acGx ozA04JBk12ksBLMO58dUW0yYhHVdzbBpmffOCGOmtFYhSnNRdAh623NSL8TFV1VD3zBt Iadg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=ogzTLxmI8IkuwxxyvG+1eNWoSJJ7OK/HnSXzU4z+Uag=; b=KLwR5PPcABqx10Xu3BjBoxIRVaJh5VBQ66dR6eZ1D7C20uJLlnxsgk3A2DQjQS8YZI 8/amrpBvoV/HMktOwgW1QSBwL6UI2tYl1TkUERuOrFprghIYPCZW/NhJZsk7DqHuimtx YZWrUxPU6ELXlprPvik+6N1u8juhYOSPHqBQxvb1GoHA7PxaNxjIV7+zszrSHdbpUa5x TGFQClAUucoiLCb0HHg1Oa2r3648weRiR+81JfVrCmYOOmhk2fFd/BHOMvUbAiGywoH0 RRxQ2bL3kgEWdkDtSAMhhAbB/whmpCLB1QcA2pYN/Z5+6GkVj6tPIfS65w2y9SMzsIpS ey8g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d62si8339214pgc.627.2018.03.18.12.54.31; Sun, 18 Mar 2018 12:54:45 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754634AbeCRTxC (ORCPT + 99 others); Sun, 18 Mar 2018 15:53:02 -0400 Received: from smtp2200-217.mail.aliyun.com ([121.197.200.217]:34152 "EHLO smtp2200-217.mail.aliyun.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754549AbeCRTwx (ORCPT ); Sun, 18 Mar 2018 15:52:53 -0400 X-Alimail-AntiSpam: AC=CONTINUE;BC=0.02444197|-1;CH=blue;FP=0|0|0|0|0|-1|-1|-1;HT=e01l07447;MF=ren_guo@c-sky.com;NM=1;PH=DS;RN=11;RT=11;SR=0;TI=SMTPD_---.BMBvJZE_1521402743; Received: from localhost(mailfrom:ren_guo@c-sky.com fp:183.159.50.56) by smtp.aliyun-inc.com(10.147.41.231); Mon, 19 Mar 2018 03:52:23 +0800 From: Guo Ren To: linux-arch@vger.kernel.org, linux-kernel@vger.kernel.org, tglx@linutronix.de, daniel.lezcano@linaro.org, jason@lakedaemon.net, arnd@arndb.de Cc: c-sky_gcc_upstream@c-sky.com, gnu-csky@mentor.com, thomas.petazzoni@bootlin.com, wbx@uclibc-ng.org, Guo Ren Subject: [PATCH 19/19] irqchip: add irq-nationalchip.c and irq-csky.c Date: Mon, 19 Mar 2018 03:51:41 +0800 Message-Id: <62e687d3eb67505aa6f4d4d01ce268fd432bf58e.1521399976.git.ren_guo@c-sky.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Signed-off-by: Guo Ren --- drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-csky.c | 151 ++++++++++++++++++++++++++++ drivers/irqchip/irq-nationalchip.c | 196 +++++++++++++++++++++++++++++++++++++ 3 files changed, 348 insertions(+) create mode 100644 drivers/irqchip/irq-csky.c create mode 100644 drivers/irqchip/irq-nationalchip.c diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index d27e3e3..7b98917 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -85,3 +85,4 @@ obj-$(CONFIG_IRQ_UNIPHIER_AIDET) += irq-uniphier-aidet.o obj-$(CONFIG_ARCH_SYNQUACER) += irq-sni-exiu.o obj-$(CONFIG_MESON_IRQ_GPIO) += irq-meson-gpio.o obj-$(CONFIG_GOLDFISH_PIC) += irq-goldfish-pic.o +obj-$(CONFIG_CSKY) += irq-csky.o irq-nationalchip.o diff --git a/drivers/irqchip/irq-csky.c b/drivers/irqchip/irq-csky.c new file mode 100644 index 0000000..77041e3 --- /dev/null +++ b/drivers/irqchip/irq-csky.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned int intc_reg; + +#define CK_VA_INTC_ICR (void *)(intc_reg + 0x00) /* Interrupt control register(High 16bits) */ +#define CK_VA_INTC_ISR (void *)(intc_reg + 0x00) /* Interrupt status register(Low 16bits) */ +#define CK_VA_INTC_NEN31_00 (void *)(intc_reg + 0x10) /* Normal interrupt enable register Low */ +#define CK_VA_INTC_NEN63_32 (void *)(intc_reg + 0x28) /* Normal interrupt enable register High */ +#define CK_VA_INTC_IFR31_00 (void *)(intc_reg + 0x08) /* Normal interrupt force register Low */ +#define CK_VA_INTC_IFR63_32 (void *)(intc_reg + 0x20) /* Normal interrupt force register High */ +#define CK_VA_INTC_SOURCE (void *)(intc_reg + 0x40) /* Proiority Level Select Registers 0 */ + +static void ck_irq_mask(struct irq_data *d) +{ + unsigned int temp, irq; + + irq = d->irq; + + if (irq < 32) { + temp = __raw_readl(CK_VA_INTC_NEN31_00); + temp &= ~(1 << irq); + __raw_writel(temp, CK_VA_INTC_NEN31_00); + } else { + temp = __raw_readl(CK_VA_INTC_NEN63_32); + temp &= ~(1 << (irq -32)); + __raw_writel(temp, CK_VA_INTC_NEN63_32); + } +} + +static void ck_irq_unmask(struct irq_data *d) +{ + unsigned int temp, irq; + + irq = d->irq; + + /* set IFR to support rising edge triggering */ + if (irq < 32) { + temp = __raw_readl(CK_VA_INTC_IFR31_00); + temp &= ~(1 << irq); + __raw_writel(temp, CK_VA_INTC_IFR31_00); + } else { + temp = __raw_readl(CK_VA_INTC_IFR63_32); + temp &= ~(1 << (irq -32)); + __raw_writel(temp, CK_VA_INTC_IFR63_32); + } + + if (irq < 32) { + temp = __raw_readl(CK_VA_INTC_NEN31_00); + temp |= 1 << irq; + __raw_writel(temp, CK_VA_INTC_NEN31_00); + } else { + temp = __raw_readl(CK_VA_INTC_NEN63_32); + temp |= 1 << (irq -32); + __raw_writel(temp, CK_VA_INTC_NEN63_32); + } +} + +static struct irq_chip ck_irq_chip = { + .name = "csky_intc_v1", + .irq_mask = ck_irq_mask, + .irq_unmask = ck_irq_unmask, +}; + +static int ck_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw_irq_num) +{ + irq_set_chip_and_handler(virq, &ck_irq_chip, handle_level_irq); + return 0; +} + +static const struct irq_domain_ops ck_irq_ops = { + .map = ck_irq_map, + .xlate = irq_domain_xlate_onecell, +}; + +static unsigned int ck_get_irqno(void) +{ + unsigned int temp; + temp = __raw_readl(CK_VA_INTC_ISR); + return temp & 0x3f; +}; + +static int __init +__intc_init(struct device_node *np, struct device_node *parent, bool ave) +{ + struct irq_domain *root_domain; + int i; + + csky_get_auto_irqno = ck_get_irqno; + + if (parent) + panic("pic not a root intc\n"); + + intc_reg = (unsigned int)of_iomap(np, 0); + if (!intc_reg) + panic("%s, of_iomap err.\n", __func__); + + __raw_writel(0, CK_VA_INTC_NEN31_00); + __raw_writel(0, CK_VA_INTC_NEN63_32); + + if (ave == true) + __raw_writel( 0xc0000000, CK_VA_INTC_ICR); + else + __raw_writel( 0x0, CK_VA_INTC_ICR); + /* + * csky irq ctrl has 64 sources. + */ + #define INTC_IRQS 64 + for (i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NC_VA_INTC_NINT31_00 (void *)(intc_reg + 0x00) +#define NC_VA_INTC_NINT63_32 (void *)(intc_reg + 0x04) +#define NC_VA_INTC_NPEND31_00 (void *)(intc_reg + 0x10) +#define NC_VA_INTC_NPEND63_32 (void *)(intc_reg + 0x14) +#define NC_VA_INTC_NENSET31_00 (void *)(intc_reg + 0x20) +#define NC_VA_INTC_NENSET63_32 (void *)(intc_reg + 0x24) +#define NC_VA_INTC_NENCLR31_00 (void *)(intc_reg + 0x30) +#define NC_VA_INTC_NENCLR63_32 (void *)(intc_reg + 0x34) +#define NC_VA_INTC_NEN31_00 (void *)(intc_reg + 0x40) +#define NC_VA_INTC_NEN63_32 (void *)(intc_reg + 0x44) +#define NC_VA_INTC_NMASK31_00 (void *)(intc_reg + 0x50) +#define NC_VA_INTC_NMASK63_32 (void *)(intc_reg + 0x54) +#define NC_VA_INTC_SOURCE (void *)(intc_reg + 0x60) + +static unsigned int intc_reg; + +static void nc_irq_mask(struct irq_data *d) +{ + unsigned int mask, irq; + + irq = d->irq; + + if (irq < 32) { + mask = __raw_readl(NC_VA_INTC_NMASK31_00); + mask |= 1 << irq; + __raw_writel(mask, NC_VA_INTC_NMASK31_00); + } else { + mask = __raw_readl(NC_VA_INTC_NMASK63_32); + mask |= 1 << (irq - 32); + __raw_writel(mask, NC_VA_INTC_NMASK63_32); + } +} + +static void nc_irq_unmask(struct irq_data *d) +{ + unsigned int mask, irq; + + irq = d->irq; + + if (irq < 32) { + mask = __raw_readl(NC_VA_INTC_NMASK31_00); + mask &= ~( 1 << irq); + __raw_writel(mask, NC_VA_INTC_NMASK31_00); + } else { + mask = __raw_readl( NC_VA_INTC_NMASK63_32); + mask &= ~(1 << (irq - 32)); + __raw_writel(mask, NC_VA_INTC_NMASK63_32); + } +} + +static void nc_irq_en(struct irq_data *d) +{ + unsigned int mask, irq; + + irq = d->irq; + + if (irq < 32) { + mask = 1 << irq; + __raw_writel(mask, NC_VA_INTC_NENSET31_00); + } else { + mask = 1 << (irq - 32); + __raw_writel(mask, NC_VA_INTC_NENSET63_32); + } + + nc_irq_unmask(d); +} + +static void nc_irq_dis(struct irq_data *d) +{ + unsigned int mask, irq; + + irq = d->irq; + + if (irq < 32) { + mask = 1 << irq; + __raw_writel(mask, NC_VA_INTC_NENCLR31_00); + } else { + mask = 1 << (irq - 32); + __raw_writel(mask, NC_VA_INTC_NENCLR63_32); + } + + nc_irq_mask(d); +} + +struct irq_chip nc_irq_chip = { + .name = "nationalchip_intc_v1", + .irq_mask = nc_irq_mask, + .irq_unmask = nc_irq_unmask, + .irq_enable = nc_irq_en, + .irq_disable = nc_irq_dis, +}; + +inline int ff1_64(unsigned int hi, unsigned int lo) +{ + int result; + asm volatile( + "ff1 %0\n" + :"=r"(hi) + :"r"(hi) + : + ); + + asm volatile( + "ff1 %0\n" + :"=r"(lo) + :"r"(lo) + : + ); + if( lo != 32 ) + result = 31-lo; + else if( hi != 32 ) result = 31-hi + 32; + else { + printk("nc_get_irqno error hi:%x, lo:%x.\n", hi, lo); + result = NR_IRQS; + } + return result; +} + +unsigned int nc_get_irqno(void) +{ + unsigned int nint64hi, nint64lo, irq_no; + + nint64lo = __raw_readl(NC_VA_INTC_NINT31_00); + nint64hi = __raw_readl(NC_VA_INTC_NINT63_32); + irq_no = ff1_64(nint64hi, nint64lo); + + return irq_no; +} + +static int irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw_irq_num) +{ + irq_set_chip_and_handler(virq, &nc_irq_chip, handle_level_irq); + + return 0; +} + +static const struct irq_domain_ops nc_irq_ops = { + .map = irq_map, + .xlate = irq_domain_xlate_onecell, +}; + +static int __init +intc_init(struct device_node *intc, struct device_node *parent) +{ + struct irq_domain *root_domain; + unsigned int i; + + if (parent) + panic("DeviceTree incore intc not a root irq controller\n"); + + csky_get_auto_irqno = nc_get_irqno; + + intc_reg = (unsigned int) of_iomap(intc, 0); + if (!intc_reg) + panic("Nationalchip Intc Reg: %x.\n", intc_reg); + + __raw_writel(0xffffffff, NC_VA_INTC_NENCLR31_00); + __raw_writel(0xffffffff, NC_VA_INTC_NENCLR63_32); + __raw_writel(0xffffffff, NC_VA_INTC_NMASK31_00); + __raw_writel(0xffffffff, NC_VA_INTC_NMASK63_32); + + /* + * nationalchip irq ctrl has 64 sources. + */ + #define INTC_IRQS 64 + for (i=0; i