Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751608Ab3JYFJB (ORCPT ); Fri, 25 Oct 2013 01:09:01 -0400 Received: from mx0a-0016f401.pphosted.com ([67.231.148.174]:16720 "EHLO mx0a-0016f401.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751387Ab3JYFI7 (ORCPT ); Fri, 25 Oct 2013 01:08:59 -0400 From: Neil Zhang To: Neil Zhang , "linux-kernel@vger.kernel.org" CC: "haojian.zhuang@gmail.com" , "tglx@linutronix.de" Date: Thu, 24 Oct 2013 22:08:48 -0700 Subject: RE: [PATCH 2/2 v2] irqchip: mmp: add dt support for wakeup Thread-Topic: [PATCH 2/2 v2] irqchip: mmp: add dt support for wakeup Thread-Index: Ac7GW1Eq27AdMp+8S66HQxTbZByyBAFjBqRAAVYxqEA= Message-ID: <175CCF5F49938B4D99B2E3EF7F558EBE49FD068363@SC-VEXCH4.marvell.com> References: <1381479838-7794-1-git-send-email-zhangwm@marvell.com> <1381479838-7794-3-git-send-email-zhangwm@marvell.com> <175CCF5F49938B4D99B2E3EF7F558EBE49FCEFF788@SC-VEXCH4.marvell.com> In-Reply-To: <175CCF5F49938B4D99B2E3EF7F558EBE49FCEFF788@SC-VEXCH4.marvell.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: acceptlanguage: en-US Content-Type: text/plain; charset="gb2312" MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.10.8794,1.0.431,0.0.0000 definitions=2013-10-25_02:2013-10-24,2013-10-25,1970-01-01 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=7.0.1-1305240000 definitions=main-1310240267 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from base64 to 8bit by mail.home.local id r9P59C2k022666 Content-Length: 8684 Lines: 263 Haojian, > -----Original Message----- > From: Neil Zhang > Sent: 2013??10??18?? 17:50 > To: Neil Zhang; linux-kernel@vger.kernel.org > Cc: haojian.zhuang@gmail.com; tglx@linutronix.de > Subject: RE: [PATCH 2/2 v2] irqchip: mmp: add dt support for wakeup > > Ping ? > > > -----Original Message----- > > From: Neil Zhang [mailto:zhangwm@marvell.com] > > Sent: 2013??10??11?? 16:24 > > To: linux-kernel@vger.kernel.org > > Cc: haojian.zhuang@gmail.com; tglx@linutronix.de; Neil Zhang > > Subject: [PATCH 2/2 v2] irqchip: mmp: add dt support for wakeup > > Would you please have a look? > > Some of the Marvell SoCs use GIC as its interrupt controller,and ICU > > only used as wakeup logic. When AP subsystem is powered off, GIC will > > lose its context, the PMU will need ICU to wakeup the AP subsystem. > > So add wakeup entry for such kind of usage. > > > > Signed-off-by: Neil Zhang > > --- > > .../devicetree/bindings/arm/mrvl/intc.txt | 14 ++- > > drivers/irqchip/irq-mmp.c | 124 > > ++++++++++++++++++++ > > include/linux/irqchip/mmp.h | 13 ++ > > 3 files changed, 150 insertions(+), 1 deletion(-) > > > > diff --git a/Documentation/devicetree/bindings/arm/mrvl/intc.txt > > b/Documentation/devicetree/bindings/arm/mrvl/intc.txt > > index 8b53273..4180928 100644 > > --- a/Documentation/devicetree/bindings/arm/mrvl/intc.txt > > +++ b/Documentation/devicetree/bindings/arm/mrvl/intc.txt > > @@ -2,7 +2,7 @@ > > > > Required properties: > > - compatible : Should be "mrvl,mmp-intc", "mrvl,mmp2-intc" or > > - "mrvl,mmp2-mux-intc" > > + "mrvl,mmp2-mux-intc", "mrvl,mmp-intc-wakeupgen" > > - reg : Address and length of the register set of the interrupt controller. > > If the interrupt controller is intc, address and length means the range > > of the whold interrupt controller. If the interrupt controller is > > mux-intc, @@ > > -15,6 +15,9 @@ Required properties: > > - interrupt-controller : Identifies the node as an interrupt controller. > > - #interrupt-cells : Specifies the number of cells needed to encode an > > interrupt source. > > +- mrvl,intc-gbl-mask : Specifies the address and value for global > > +mask in the > > + interrupt controller. > > +- mrvl,intc-for-cp : Specifies the irqs that will be routed to cp > > - mrvl,intc-nr-irqs : Specifies the number of interrupts in the interrupt > > controller. > > - mrvl,clr-mfp-irq : Specifies the interrupt that needs to clear MFP > > edge @@ > > -39,6 +42,15 @@ Example: > > mrvl,intc-nr-irqs = <2>; > > }; > > > > + intc: wakeupgen@d4282000 { > > + compatible = "mrvl,mmp-intc-wakeupgen"; > > + reg = <0xd4282000 0x1000>; > > + mrvl,intc-nr-irqs = <64>; > > + mrvl,intc-gbl-mask = <0x114 0x3 > > + 0x144 0x3>; > > + mrvl,intc-for-cp = <0 31 32>; > > + }; > > + > > * Marvell Orion Interrupt controller > > > > Required properties > > diff --git a/drivers/irqchip/irq-mmp.c b/drivers/irqchip/irq-mmp.c > > index 470c5de..445a00c 100644 > > --- a/drivers/irqchip/irq-mmp.c > > +++ b/drivers/irqchip/irq-mmp.c > > @@ -16,6 +16,8 @@ > > #include > > #include > > #include > > +#include > > +#include > > #include > > #include > > #include > > @@ -58,6 +60,8 @@ struct mmp_intc_conf { static void __iomem > > *mmp_icu_base; static struct icu_chip_data icu_data[MAX_ICU_NR]; > > static int max_icu_nr; > > +static u32 irq_for_cp[64]; > > +static u32 irq_for_cp_nr; /* How many irqs will be routed to cp */ > > > > extern void mmp2_clear_pmic_int(void); > > > > @@ -123,6 +127,50 @@ static void icu_unmask_irq(struct irq_data *d) > > } > > } > > > > +static int irq_ignore_wakeup(struct icu_chip_data *data, int hwirq) { > > + int i; > > + > > + if (hwirq < 0 || hwirq >= data->nr_irqs) > > + return 1; > > + > > + for (i = 0; i < irq_for_cp_nr; i++) > > + if (irq_for_cp[i] == hwirq) > > + return 1; > > + > > + return 0; > > +} > > + > > +static void icu_mask_irq_wakeup(struct irq_data *d) { > > + struct icu_chip_data *data = &icu_data[0]; > > + int hwirq = d->hwirq - data->virq_base; > > + u32 r; > > + > > + if (irq_ignore_wakeup(data, hwirq)) > > + return; > > + > > + r = readl_relaxed(mmp_icu_base + (hwirq << 2)); > > + r &= ~data->conf_mask; > > + r |= data->conf_disable; > > + writel_relaxed(r, mmp_icu_base + (hwirq << 2)); } > > + > > +static void icu_unmask_irq_wakeup(struct irq_data *d) { > > + struct icu_chip_data *data = &icu_data[0]; > > + int hwirq = d->irq - data->virq_base; > > + u32 r; > > + > > + if (irq_ignore_wakeup(data, hwirq)) > > + return; > > + > > + r = readl_relaxed(mmp_icu_base + (hwirq << 2)); > > + r &= ~data->conf_mask; > > + r |= data->conf_enable; > > + writel_relaxed(r, mmp_icu_base + (hwirq << 2)); } > > + > > struct irq_chip icu_irq_chip = { > > .name = "icu_irq", > > .irq_mask = icu_mask_irq, > > @@ -491,5 +539,81 @@ err: > > irq_domain_remove(icu_data[i].domain); > > return -EINVAL; > > } > > + > > +void __init mmp_of_wakeup_init(void) > > +{ > > + struct device_node *node; > > + const __be32 *wakeup_reg; > > + const __be32 *cp_irq_reg; > > + int ret, nr_irqs; > > + int size, i = 0; > > + int irq; > > + > > + node = of_find_compatible_node(NULL, NULL, > > "mrvl,mmp-intc-wakeupgen"); > > + if (!node) { > > + pr_err("Failed to find interrupt controller in arch-mmp\n"); > > + return; > > + } > > + > > + mmp_icu_base = of_iomap(node, 0); > > + if (!mmp_icu_base) { > > + pr_err("Failed to get interrupt controller register\n"); > > + return; > > + } > > + > > + ret = of_property_read_u32(node, "mrvl,intc-nr-irqs", &nr_irqs); > > + if (ret) { > > + pr_err("Not found mrvl,intc-nr-irqs property\n"); > > + return; > > + } > > + > > + /* > > + * Config all the interrupt source be able to interrupt the cpu 0, > > + * in IRQ mode, with priority 0 as masked by default. > > + */ > > + for (irq = 0; irq < nr_irqs; irq++) > > + __raw_writel(ICU_IRQ_CPU0_MASKED, mmp_icu_base + (irq << 2)); > > + > > + /* ICU is only used as wake up logic > > + * disable the global irq/fiq in icu for all cores. > > + */ > > + wakeup_reg = of_get_property(node, "mrvl,intc-gbl-mask", &size); > > + if (!wakeup_reg) { > > + pr_err("Not found mrvl,intc-gbl-mask property\n"); > > + return; > > + } > > + > > + size /= sizeof(*wakeup_reg); > > + while (i < size) { > > + unsigned offset, val; > > + > > + offset = be32_to_cpup(wakeup_reg + i++); > > + val = be32_to_cpup(wakeup_reg + i++); > > + writel_relaxed(val, mmp_icu_base + offset); > > + } > > + > > + /* Get the irq lines and ignore irqs */ > > + cp_irq_reg = of_get_property(node, "mrvl,intc-for-cp", &size); > > + if (!cp_irq_reg) > > + return; > > + > > + irq_for_cp_nr = size / sizeof(*cp_irq_reg); > > + for (i = 0; i < irq_for_cp_nr; i++) { > > + irq_for_cp[i] = be32_to_cpup(cp_irq_reg + i); > > + __raw_writel(ICU_CONF_SEAGULL, mmp_icu_base + (irq_for_cp[i] > > << 2)); > > + } > > + > > + icu_data[0].conf_enable = mmp_conf.conf_enable; > > + icu_data[0].conf_disable = mmp_conf.conf_disable; > > + icu_data[0].conf_mask = mmp_conf.conf_mask; > > + icu_data[0].nr_irqs = nr_irqs; > > + icu_data[0].virq_base = 32; > > + > > + gic_arch_extn.irq_mask = icu_mask_irq_wakeup; > > + gic_arch_extn.irq_unmask = icu_unmask_irq_wakeup; > > + > > + return; > > +} > > + > > IRQCHIP_DECLARE(mmp2_mux_intc, "mrvl,mmp2-mux-intc", > > mmp2_mux_of_init); #endif diff --git a/include/linux/irqchip/mmp.h > > b/include/linux/irqchip/mmp.h index c78a892..93b05ad 100644 > > --- a/include/linux/irqchip/mmp.h > > +++ b/include/linux/irqchip/mmp.h > > @@ -1,6 +1,19 @@ > > #ifndef __IRQCHIP_MMP_H > > #define __IRQCHIP_MMP_H > > > > +#define ICU_CONF_CPU3 (1 << 9) > > +#define ICU_CONF_CPU2 (1 << 8) > > +#define ICU_CONF_CPU1 (1 << 7) > > +#define ICU_CONF_CPU0 (1 << 6) > > +#define ICU_CONF_AP(n) (1 << (6 + (n & 0x3))) > > +#define ICU_CONF_AP_MASK (0xF << 6) > > +#define ICU_CONF_SEAGULL (1 << 5) > > +#define ICU_CONF_IRQ_FIQ (1 << 4) > > +#define ICU_CONF_PRIO(n) (n & 0xF) > > + > > +#define ICU_IRQ_CPU0_MASKED (ICU_CONF_IRQ_FIQ | > > ICU_CONF_CPU0) > > + > > extern struct irq_chip icu_irq_chip; > > > > +extern void __init mmp_of_wakeup_init(void); > > #endif /* __IRQCHIP_MMP_H */ > > -- > > 1.7.9.5 > > Best Regards, > Neil Zhang Best Regards, Neil Zhang ????{.n?+???????+%?????ݶ??w??{.n?+????{??G?????{ay?ʇڙ?,j??f???h?????????z_??(?階?ݢj"???m??????G????????????&???~???iO???z??v?^?m???? ????????I?