From: Vladimir Zapolskiy <vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org> To: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>, Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>, Jason Cooper <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org>, Marc Zyngier <marc.zyngier-5wv7dgnIgG8@public.gmane.org>, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> Cc: Russell King <linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>, Roland Stigge <stigge-uj/7R2tJ6VmzQB+pC5nmwQ@public.gmane.org>, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org Subject: [PATCH 04/10] arm: lpc32xx: add wakeup platform driver Date: Fri, 20 Nov 2015 03:28:39 +0200 [thread overview] Message-ID: <1447982925-30138-5-git-send-email-vz@mleia.com> (raw) In-Reply-To: <1447982925-30138-1-git-send-email-vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org> NXP LPC32xx has three wakeup controllers of two types, this change adds support of two wakeup controllers connected to MIC, SIC1 and SIC2 interrupt controllers, which may propagate interrupt wakeup source status to one of the wakeup controllers. Wakeup controllers are found as subdevices of System Control Block with offsets 0x20 and 0x30. The change does not add support of P01 wakeup controller, which may define Port0 and Port1 I/O pins as wakeup sources. Signed-off-by: Vladimir Zapolskiy <vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org> --- arch/arm/mach-lpc32xx/Makefile | 2 +- arch/arm/mach-lpc32xx/include/mach/wakeup.h | 21 ++++ arch/arm/mach-lpc32xx/wakeup.c | 144 ++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-lpc32xx/include/mach/wakeup.h create mode 100644 arch/arm/mach-lpc32xx/wakeup.c diff --git a/arch/arm/mach-lpc32xx/Makefile b/arch/arm/mach-lpc32xx/Makefile index c70709a..b1023c0 100644 --- a/arch/arm/mach-lpc32xx/Makefile +++ b/arch/arm/mach-lpc32xx/Makefile @@ -3,5 +3,5 @@ # obj-y := irq.o common.o serial.o -obj-y += pm.o suspend.o +obj-y += pm.o suspend.o wakeup.o obj-y += phy3250.o diff --git a/arch/arm/mach-lpc32xx/include/mach/wakeup.h b/arch/arm/mach-lpc32xx/include/mach/wakeup.h new file mode 100644 index 0000000..2c6c5fa --- /dev/null +++ b/arch/arm/mach-lpc32xx/include/mach/wakeup.h @@ -0,0 +1,21 @@ +/* + * Copyright 2015 Vladimir Zapolskiy <vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org> + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#ifndef __LPC32XX_WAKEUP_H +#define __LPC32XX_WAKEUP_H + +struct wakeup_controller; + +void lpc32xx_wakeup_clear(struct wakeup_controller *wuc, u32 bit); +void lpc32xx_wakeup_set_edge(struct wakeup_controller *wuc, u32 bit, bool val); +void lpc32xx_wakeup_enable(struct wakeup_controller *wuc, u32 bit, bool on); + +#endif diff --git a/arch/arm/mach-lpc32xx/wakeup.c b/arch/arm/mach-lpc32xx/wakeup.c new file mode 100644 index 0000000..a2b7747 --- /dev/null +++ b/arch/arm/mach-lpc32xx/wakeup.c @@ -0,0 +1,144 @@ +/* + * Copyright 2015 Vladimir Zapolskiy <vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org> + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <linux/io.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <mach/wakeup.h> + +#undef pr_fmt +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#define LPC32XX_CLKPWR_P01_ER 0x0 + +#define LPC32XX_CLKPWR_PIN_ER 0x0 +#define LPC32XX_CLKPWR_PIN_RS 0x4 +#define LPC32XX_CLKPWR_PIN_SR 0x8 +#define LPC32XX_CLKPWR_PIN_AP 0xC + +struct wakeup_ops { + void (*clear)(struct wakeup_controller *wuc, u32 bit); + void (*set_edge)(struct wakeup_controller *wuc, u32 bit, bool val); + void (*enable)(struct wakeup_controller *wuc, u32 bit, bool on); +}; + +struct wakeup_controller { + void __iomem *base; + struct wakeup_ops ops; +}; + +void lpc32xx_wakeup_clear(struct wakeup_controller *wuc, u32 bit) +{ + wuc->ops.clear(wuc, bit); +} + +void lpc32xx_wakeup_set_edge(struct wakeup_controller *wuc, u32 bit, bool val) +{ + wuc->ops.set_edge(wuc, bit, val); +} + +void lpc32xx_wakeup_enable(struct wakeup_controller *wuc, u32 bit, bool on) +{ + wuc->ops.enable(wuc, bit, on); +} + +static inline u32 lpc32xx_wakeup_read(struct wakeup_controller *wuc, u32 reg) +{ + return readl(wuc->base + reg); +} + +static inline void lpc32xx_wakeup_write(struct wakeup_controller *wuc, + u32 reg, u32 val) +{ + writel(val, wuc->base + reg); +} + +static void wakeup_clear(struct wakeup_controller *wuc, u32 bit) +{ + lpc32xx_wakeup_write(wuc, LPC32XX_CLKPWR_PIN_RS, BIT(bit)); +} + +static void wakeup_set_edge(struct wakeup_controller *wuc, u32 bit, bool pol) +{ + u32 val = lpc32xx_wakeup_read(wuc, LPC32XX_CLKPWR_PIN_AP); + + /* Here pol == true means rising edge */ + if (pol) + val |= BIT(bit); + else + val &= ~BIT(bit); + + lpc32xx_wakeup_write(wuc, LPC32XX_CLKPWR_PIN_AP, val); +} + +static void wakeup_enable(struct wakeup_controller *wuc, u32 bit, bool on) +{ + u32 val = lpc32xx_wakeup_read(wuc, LPC32XX_CLKPWR_PIN_ER); + + if (on) + val |= BIT(bit); + else + val &= ~BIT(bit); + + wakeup_clear(wuc, bit); + lpc32xx_wakeup_write(wuc, LPC32XX_CLKPWR_PIN_ER, val); +} + +static int lpc32xx_wakeup_probe(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct wakeup_controller *wuc; + u32 val; + + wuc = devm_kzalloc(&pdev->dev, sizeof(*wuc), GFP_KERNEL); + if (!wuc) + return -ENOMEM; + + wuc->base = of_iomap(node, 0); + if (!wuc->base) { + pr_err("%s: unable to map registers\n", node->full_name); + return -ENODEV; + } + + wuc->ops.clear = wakeup_clear, + wuc->ops.set_edge = wakeup_set_edge, + wuc->ops.enable = wakeup_enable, + + platform_set_drvdata(pdev, wuc); + + lpc32xx_wakeup_write(wuc, LPC32XX_CLKPWR_PIN_ER, 0x00); + val = lpc32xx_wakeup_read(wuc, LPC32XX_CLKPWR_PIN_RS); + lpc32xx_wakeup_write(wuc, LPC32XX_CLKPWR_PIN_RS, val); + lpc32xx_wakeup_write(wuc, LPC32XX_CLKPWR_PIN_AP, 0x00); + + pr_debug("%s: wakeup controller is initialized\n", node->full_name); + + return 0; +} + +static const struct of_device_id lpc32xx_wakeup_dt_ids[] = { + { .compatible = "nxp,lpc3220-wakeup" }, + { } +}; + +static struct platform_driver lpc32xx_wakeup_driver = { + .driver = { + .name = "lpc32xx-wakeup", + .of_match_table = lpc32xx_wakeup_dt_ids, + }, + .probe = lpc32xx_wakeup_probe, +}; + +static int __init lpc32xx_wakeup_init(void) +{ + return platform_driver_register(&lpc32xx_wakeup_driver); +} +postcore_initcall(lpc32xx_wakeup_init); -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html
WARNING: multiple messages have this Message-ID (diff)
From: vz@mleia.com (Vladimir Zapolskiy) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 04/10] arm: lpc32xx: add wakeup platform driver Date: Fri, 20 Nov 2015 03:28:39 +0200 [thread overview] Message-ID: <1447982925-30138-5-git-send-email-vz@mleia.com> (raw) In-Reply-To: <1447982925-30138-1-git-send-email-vz@mleia.com> NXP LPC32xx has three wakeup controllers of two types, this change adds support of two wakeup controllers connected to MIC, SIC1 and SIC2 interrupt controllers, which may propagate interrupt wakeup source status to one of the wakeup controllers. Wakeup controllers are found as subdevices of System Control Block with offsets 0x20 and 0x30. The change does not add support of P01 wakeup controller, which may define Port0 and Port1 I/O pins as wakeup sources. Signed-off-by: Vladimir Zapolskiy <vz@mleia.com> --- arch/arm/mach-lpc32xx/Makefile | 2 +- arch/arm/mach-lpc32xx/include/mach/wakeup.h | 21 ++++ arch/arm/mach-lpc32xx/wakeup.c | 144 ++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-lpc32xx/include/mach/wakeup.h create mode 100644 arch/arm/mach-lpc32xx/wakeup.c diff --git a/arch/arm/mach-lpc32xx/Makefile b/arch/arm/mach-lpc32xx/Makefile index c70709a..b1023c0 100644 --- a/arch/arm/mach-lpc32xx/Makefile +++ b/arch/arm/mach-lpc32xx/Makefile @@ -3,5 +3,5 @@ # obj-y := irq.o common.o serial.o -obj-y += pm.o suspend.o +obj-y += pm.o suspend.o wakeup.o obj-y += phy3250.o diff --git a/arch/arm/mach-lpc32xx/include/mach/wakeup.h b/arch/arm/mach-lpc32xx/include/mach/wakeup.h new file mode 100644 index 0000000..2c6c5fa --- /dev/null +++ b/arch/arm/mach-lpc32xx/include/mach/wakeup.h @@ -0,0 +1,21 @@ +/* + * Copyright 2015 Vladimir Zapolskiy <vz@mleia.com> + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#ifndef __LPC32XX_WAKEUP_H +#define __LPC32XX_WAKEUP_H + +struct wakeup_controller; + +void lpc32xx_wakeup_clear(struct wakeup_controller *wuc, u32 bit); +void lpc32xx_wakeup_set_edge(struct wakeup_controller *wuc, u32 bit, bool val); +void lpc32xx_wakeup_enable(struct wakeup_controller *wuc, u32 bit, bool on); + +#endif diff --git a/arch/arm/mach-lpc32xx/wakeup.c b/arch/arm/mach-lpc32xx/wakeup.c new file mode 100644 index 0000000..a2b7747 --- /dev/null +++ b/arch/arm/mach-lpc32xx/wakeup.c @@ -0,0 +1,144 @@ +/* + * Copyright 2015 Vladimir Zapolskiy <vz@mleia.com> + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <linux/io.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <mach/wakeup.h> + +#undef pr_fmt +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#define LPC32XX_CLKPWR_P01_ER 0x0 + +#define LPC32XX_CLKPWR_PIN_ER 0x0 +#define LPC32XX_CLKPWR_PIN_RS 0x4 +#define LPC32XX_CLKPWR_PIN_SR 0x8 +#define LPC32XX_CLKPWR_PIN_AP 0xC + +struct wakeup_ops { + void (*clear)(struct wakeup_controller *wuc, u32 bit); + void (*set_edge)(struct wakeup_controller *wuc, u32 bit, bool val); + void (*enable)(struct wakeup_controller *wuc, u32 bit, bool on); +}; + +struct wakeup_controller { + void __iomem *base; + struct wakeup_ops ops; +}; + +void lpc32xx_wakeup_clear(struct wakeup_controller *wuc, u32 bit) +{ + wuc->ops.clear(wuc, bit); +} + +void lpc32xx_wakeup_set_edge(struct wakeup_controller *wuc, u32 bit, bool val) +{ + wuc->ops.set_edge(wuc, bit, val); +} + +void lpc32xx_wakeup_enable(struct wakeup_controller *wuc, u32 bit, bool on) +{ + wuc->ops.enable(wuc, bit, on); +} + +static inline u32 lpc32xx_wakeup_read(struct wakeup_controller *wuc, u32 reg) +{ + return readl(wuc->base + reg); +} + +static inline void lpc32xx_wakeup_write(struct wakeup_controller *wuc, + u32 reg, u32 val) +{ + writel(val, wuc->base + reg); +} + +static void wakeup_clear(struct wakeup_controller *wuc, u32 bit) +{ + lpc32xx_wakeup_write(wuc, LPC32XX_CLKPWR_PIN_RS, BIT(bit)); +} + +static void wakeup_set_edge(struct wakeup_controller *wuc, u32 bit, bool pol) +{ + u32 val = lpc32xx_wakeup_read(wuc, LPC32XX_CLKPWR_PIN_AP); + + /* Here pol == true means rising edge */ + if (pol) + val |= BIT(bit); + else + val &= ~BIT(bit); + + lpc32xx_wakeup_write(wuc, LPC32XX_CLKPWR_PIN_AP, val); +} + +static void wakeup_enable(struct wakeup_controller *wuc, u32 bit, bool on) +{ + u32 val = lpc32xx_wakeup_read(wuc, LPC32XX_CLKPWR_PIN_ER); + + if (on) + val |= BIT(bit); + else + val &= ~BIT(bit); + + wakeup_clear(wuc, bit); + lpc32xx_wakeup_write(wuc, LPC32XX_CLKPWR_PIN_ER, val); +} + +static int lpc32xx_wakeup_probe(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct wakeup_controller *wuc; + u32 val; + + wuc = devm_kzalloc(&pdev->dev, sizeof(*wuc), GFP_KERNEL); + if (!wuc) + return -ENOMEM; + + wuc->base = of_iomap(node, 0); + if (!wuc->base) { + pr_err("%s: unable to map registers\n", node->full_name); + return -ENODEV; + } + + wuc->ops.clear = wakeup_clear, + wuc->ops.set_edge = wakeup_set_edge, + wuc->ops.enable = wakeup_enable, + + platform_set_drvdata(pdev, wuc); + + lpc32xx_wakeup_write(wuc, LPC32XX_CLKPWR_PIN_ER, 0x00); + val = lpc32xx_wakeup_read(wuc, LPC32XX_CLKPWR_PIN_RS); + lpc32xx_wakeup_write(wuc, LPC32XX_CLKPWR_PIN_RS, val); + lpc32xx_wakeup_write(wuc, LPC32XX_CLKPWR_PIN_AP, 0x00); + + pr_debug("%s: wakeup controller is initialized\n", node->full_name); + + return 0; +} + +static const struct of_device_id lpc32xx_wakeup_dt_ids[] = { + { .compatible = "nxp,lpc3220-wakeup" }, + { } +}; + +static struct platform_driver lpc32xx_wakeup_driver = { + .driver = { + .name = "lpc32xx-wakeup", + .of_match_table = lpc32xx_wakeup_dt_ids, + }, + .probe = lpc32xx_wakeup_probe, +}; + +static int __init lpc32xx_wakeup_init(void) +{ + return platform_driver_register(&lpc32xx_wakeup_driver); +} +postcore_initcall(lpc32xx_wakeup_init); -- 2.1.4
next prev parent reply other threads:[~2015-11-20 1:28 UTC|newest] Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top 2015-11-20 1:28 [PATCH 00/10] irqchip: lpc32xx: add LPC32xx irqchip driver Vladimir Zapolskiy 2015-11-20 1:28 ` Vladimir Zapolskiy [not found] ` <1447982925-30138-1-git-send-email-vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org> 2015-11-20 1:28 ` [PATCH 01/10] dt-bindings: create arm/nxp folder and move LPC32xx SoC description to it Vladimir Zapolskiy 2015-11-20 1:28 ` Vladimir Zapolskiy [not found] ` <1447982925-30138-2-git-send-email-vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org> 2015-11-20 16:43 ` Rob Herring 2015-11-20 16:43 ` Rob Herring 2015-11-20 1:28 ` [PATCH 02/10] dt-bindings: nxp: add description of wakeup controller on LPC32xx Vladimir Zapolskiy 2015-11-20 1:28 ` Vladimir Zapolskiy [not found] ` <1447982925-30138-3-git-send-email-vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org> 2015-11-20 16:55 ` Rob Herring 2015-11-20 16:55 ` Rob Herring 2015-11-20 1:28 ` [PATCH 03/10] dt-bindings: interrupt-controllers: add description of SIC1 and SIC2 Vladimir Zapolskiy 2015-11-20 1:28 ` Vladimir Zapolskiy [not found] ` <1447982925-30138-4-git-send-email-vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org> 2015-11-20 16:58 ` Rob Herring 2015-11-20 16:58 ` Rob Herring 2015-11-20 17:52 ` Vladimir Zapolskiy 2015-11-20 17:52 ` Vladimir Zapolskiy [not found] ` <564F5DF8.7040908-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org> 2015-11-20 18:02 ` Marc Zyngier 2015-11-20 18:02 ` Marc Zyngier [not found] ` <564F6021.7090000-5wv7dgnIgG8@public.gmane.org> 2015-11-20 18:16 ` Vladimir Zapolskiy 2015-11-20 18:16 ` Vladimir Zapolskiy 2015-11-20 1:28 ` Vladimir Zapolskiy [this message] 2015-11-20 1:28 ` [PATCH 04/10] arm: lpc32xx: add wakeup platform driver Vladimir Zapolskiy 2015-11-20 1:28 ` [PATCH 05/10] arm: dts: lpc32xx: assign interrupt types Vladimir Zapolskiy 2015-11-20 1:28 ` Vladimir Zapolskiy 2015-11-20 1:28 ` [PATCH 06/10] arm: dts: lpc32xx: add description of IC wakeup controllers Vladimir Zapolskiy 2015-11-20 1:28 ` Vladimir Zapolskiy 2015-11-20 1:28 ` [PATCH 07/10] arm: dts: lpc32xx: reparent SIC1 and SIC2 interrupts from MIC Vladimir Zapolskiy 2015-11-20 1:28 ` Vladimir Zapolskiy 2015-11-20 1:28 ` [PATCH 08/10] irqchip: add LPC32xx interrupt controller driver Vladimir Zapolskiy 2015-11-20 1:28 ` Vladimir Zapolskiy [not found] ` <1447982925-30138-9-git-send-email-vz-ChpfBGZJDbMAvxtiuMwx3w@public.gmane.org> 2015-11-20 10:56 ` Marc Zyngier 2015-11-20 10:56 ` Marc Zyngier 2015-11-20 1:28 ` [PATCH 09/10] irqchip: lpc32xx: add option to wakeup from an interrupt Vladimir Zapolskiy 2015-11-20 1:28 ` Vladimir Zapolskiy 2015-11-20 1:28 ` [PATCH 10/10] arm: dts: lpc32xx: enable SIC1 and SIC2 by default Vladimir Zapolskiy 2015-11-20 1:28 ` Vladimir Zapolskiy 2016-02-10 19:45 ` [PATCH 00/10] irqchip: lpc32xx: add LPC32xx irqchip driver Sylvain Lemieux [not found] ` <loom.20160210T204046-649-eS7Uydv5nfjZ+VzJOa5vwg@public.gmane.org> 2016-04-04 17:37 ` Sylvain Lemieux 2016-04-04 17:37 ` Sylvain Lemieux 2016-04-05 1:24 ` Vladimir Zapolskiy 2016-04-05 1:24 ` Vladimir Zapolskiy
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1447982925-30138-5-git-send-email-vz@mleia.com \ --to=vz-chpfbgzjdbmavxtiumwx3w@public.gmane.org \ --cc=arnd-r2nGTMty4D4@public.gmane.org \ --cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \ --cc=jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org \ --cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \ --cc=linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org \ --cc=marc.zyngier-5wv7dgnIgG8@public.gmane.org \ --cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \ --cc=stigge-uj/7R2tJ6VmzQB+pC5nmwQ@public.gmane.org \ --cc=tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.