* [RFC 2/8] ARM:global_timer: Add ARM global timer support.
2013-05-08 14:09 [RFC 0/8] ARM:STiH41x: Add STiH41x platform and board support Srinivas KANDAGATLA
@ 2013-05-08 14:11 ` Srinivas KANDAGATLA
2013-05-08 14:26 ` Rob Herring
` (2 more replies)
2013-05-08 14:11 ` [RFC 3/8] mfd:syscon: Introduce claim/read/write/release APIs Srinivas KANDAGATLA
` (4 subsequent siblings)
5 siblings, 3 replies; 79+ messages in thread
From: Srinivas KANDAGATLA @ 2013-05-08 14:11 UTC (permalink / raw)
To: linux, will.deacon
Cc: Rob Landley, Grant Likely, Rob Herring, Samuel Ortiz,
Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Srinivas Kandagatla, Stuart Menefy, Shawn Guo, Olof Johansson,
Jason Cooper, Stephen Warren, Maxime Ripard, Nicolas Pitre,
Dave Martin, Marc Zyngier, Viresh Kumar, Arnd Bergmann,
Mark Brown, Dong Aisheng, linux-doc, linux-kernel
From: Stuart Menefy <stuart.menefy@st.com>
This is a simple driver for the global timer module found in the Cortex
A9-MP cores from revision r1p0 onwards. This should be able to perform
the functions of the system timer and the local timer in an SMP system.
The global timer has the following features:
The global timer is a 64-bit incrementing counter with an
auto-incrementing feature. It continues incrementing after sending
interrupts. The global timer is memory mapped in the private memory
region.
The global timer is accessible to all Cortex-A9 processors in the
cluster. Each Cortex-A9 processor has a private 64-bit comparator that
is used to assert a private interrupt when the global timer has reached
the comparator value. All the Cortex-A9 processors in a design use the
banked ID, ID27, for this interrupt. ID27 is sent to the Interrupt
Controller as a Private Peripheral Interrupt. The global timer is
clocked by PERIPHCLK.
Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
---
Documentation/devicetree/bindings/arm/gt.txt | 21 ++
arch/arm/Kconfig | 6 +
arch/arm/include/asm/global_timer.h | 12 +
arch/arm/kernel/Makefile | 1 +
arch/arm/kernel/global_timer.c | 325 ++++++++++++++++++++++++++
5 files changed, 365 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/gt.txt
create mode 100644 arch/arm/include/asm/global_timer.h
create mode 100644 arch/arm/kernel/global_timer.c
diff --git a/Documentation/devicetree/bindings/arm/gt.txt b/Documentation/devicetree/bindings/arm/gt.txt
new file mode 100644
index 0000000..4ec5fb0
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/gt.txt
@@ -0,0 +1,21 @@
+
+* ARM Global Timer
+ Cortex-A9 are often associated with a per-core Global timer.
+
+** Timer node required properties:
+
+- compatible : Should be one of:
+ "arm,cortex-a9-global-timer"
+
+- interrupts : One interrupt to each core
+
+- reg : Specify the base address and the size of the GT timer
+ register window.
+
+Example:
+
+ gt-timer@2c000600 {
+ compatible = "arm,cortex-a9-global-timer";
+ reg = <0x2c000600 0x20>;
+ interrupts = <1 13 0xf01>;
+ };
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1cacda4..c8c524e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1606,6 +1606,12 @@ config HAVE_ARM_TWD
help
This options enables support for the ARM timer and watchdog unit
+config HAVE_ARM_GT
+ bool
+ select CLKSRC_OF if OF
+ help
+ This options enables support for the ARM global timer unit
+
choice
prompt "Memory split"
default VMSPLIT_3G
diff --git a/arch/arm/include/asm/global_timer.h b/arch/arm/include/asm/global_timer.h
new file mode 100644
index 0000000..46f9188
--- /dev/null
+++ b/arch/arm/include/asm/global_timer.h
@@ -0,0 +1,12 @@
+/*
+ * arch/arm/include/asm/global_timer.h
+ *
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Stuart Menefy <stuart.menefy@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+int __init global_timer_init(void __iomem *base, unsigned int timer_irq);
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 5f3338e..af51808 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.o
obj-$(CONFIG_SMP) += smp.o smp_tlb.o
obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
+obj-$(CONFIG_HAVE_ARM_GT) += global_timer.o
obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o
diff --git a/arch/arm/kernel/global_timer.c b/arch/arm/kernel/global_timer.c
new file mode 100644
index 0000000..0ab1af3
--- /dev/null
+++ b/arch/arm/kernel/global_timer.c
@@ -0,0 +1,325 @@
+/*
+ * linux/arch/arm/kernel/global_timer.c
+ *
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Stuart Menefy <stuart.menefy@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+
+#include <asm/mach/irq.h>
+#include <asm/global_timer.h>
+#include <asm/localtimer.h>
+
+#define GT_COUNTER0 0x00
+#define GT_COUNTER1 0x04
+
+#define GT_CONTROL 0x08
+#define GT_CONTROL_TIMER_ENABLE BIT(0)
+#define GT_CONTROL_COMP_ENABLE BIT(1) /* banked */
+#define GT_CONTROL_IRQ_ENABLE BIT(2) /* banked */
+#define GT_CONTROL_AUTO_INC BIT(3) /* banked */
+
+#define GT_INT_STATUS 0x0c
+#define GT_INT_STATUS_EVENT_FLAG BIT(0)
+
+#define GT_COMP0 0x10
+#define GT_COMP1 0x14
+#define GT_AUTO_INC 0x18
+
+/*
+ * We are expecting to be clocked by the ARM peripheral clock.
+ *
+ * Note: it is assumed we are using a prescaler value of zero, so this is
+ * the units for all operations.
+ */
+static void __iomem *gt_base;
+static struct clk *gt_clk;
+static unsigned long gt_clk_rate;
+static int gt_ppi;
+static struct clock_event_device __percpu **gt_evt;
+static DEFINE_PER_CPU(bool, percpu_init_called);
+static DEFINE_PER_CPU(struct clock_event_device, gt_clockevent);
+
+union gt_counter {
+ cycle_t cycles;
+ struct {
+ uint32_t lower;
+ uint32_t upper;
+ };
+};
+
+static union gt_counter gt_counter_read(void)
+{
+ union gt_counter res;
+ uint32_t upper;
+
+ upper = readl(gt_base + GT_COUNTER1);
+ do {
+ res.upper = upper;
+ res.lower = readl(gt_base + GT_COUNTER0);
+ upper = readl(gt_base + GT_COUNTER1);
+ } while (upper != res.upper);
+
+ return res;
+}
+
+static void gt_compare_set(unsigned long delta, int periodic)
+{
+ union gt_counter counter = gt_counter_read();
+ unsigned long ctrl = readl(gt_base + GT_CONTROL);
+
+ BUG_ON(!(ctrl & GT_CONTROL_TIMER_ENABLE));
+ BUG_ON(ctrl & (GT_CONTROL_COMP_ENABLE |
+ GT_CONTROL_IRQ_ENABLE |
+ GT_CONTROL_AUTO_INC));
+
+ counter.cycles += delta;
+ writel(counter.lower, gt_base + GT_COMP0);
+ writel(counter.upper, gt_base + GT_COMP1);
+
+ ctrl |= GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE;
+
+ if (periodic) {
+ writel(delta, gt_base + GT_AUTO_INC);
+ ctrl |= GT_CONTROL_AUTO_INC;
+ }
+
+ writel(ctrl, gt_base + GT_CONTROL);
+}
+
+static void gt_clockevent_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *clk)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ gt_compare_set(gt_clk_rate/HZ, 1);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ /* period set, and timer enabled in 'next_event' hook */
+ BUG_ON(readl(gt_base + GT_CONTROL) &
+ (GT_CONTROL_COMP_ENABLE |
+ GT_CONTROL_IRQ_ENABLE |
+ GT_CONTROL_AUTO_INC));
+ /* Fall through */
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ default:
+ writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
+ break;
+ }
+}
+
+static int gt_clockevent_set_next_event(unsigned long evt,
+ struct clock_event_device *unused)
+{
+ gt_compare_set(evt, 0);
+ return 0;
+}
+
+static irqreturn_t gt_clockevent_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+
+ writel(GT_INT_STATUS_EVENT_FLAG, gt_base + GT_INT_STATUS);
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static int __cpuinit gt_clockevents_init(struct clock_event_device *clk)
+{
+ struct clock_event_device **this_cpu_clk;
+ int cpu = smp_processor_id();
+
+ clk->name = "Global Timer CE";
+ clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ clk->set_mode = gt_clockevent_set_mode;
+ clk->set_next_event = gt_clockevent_set_next_event;
+ this_cpu_clk = __this_cpu_ptr(gt_evt);
+ *this_cpu_clk = clk;
+ clk->irq = gt_ppi;
+ clockevents_config_and_register(clk, gt_clk_rate,
+ 0xf, 0xffffffff);
+ per_cpu(percpu_init_called, cpu) = true;
+ enable_percpu_irq(clk->irq, IRQ_TYPE_NONE);
+ return 0;
+}
+
+static void gt_clockevents_stop(struct clock_event_device *clk)
+{
+ gt_clockevent_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
+ disable_percpu_irq(clk->irq);
+}
+
+static int __cpuinit gt_clockevents_setup(struct clock_event_device *clk)
+{
+ int cpu = smp_processor_id();
+
+ /* Use existing clock_event for boot cpu */
+ if (per_cpu(percpu_init_called, cpu))
+ return 0;
+
+ writel(0, gt_base + GT_CONTROL);
+ writel(0, gt_base + GT_COUNTER0);
+ writel(0, gt_base + GT_COUNTER1);
+ writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
+
+ return gt_clockevents_init(clk);
+}
+
+static cycle_t gt_clocksource_read(struct clocksource *cs)
+{
+ union gt_counter res = gt_counter_read();
+ return res.cycles;
+}
+
+static struct clocksource gt_clocksource = {
+ .name = "Global Timer CS",
+ .rating = 300,
+ .read = gt_clocksource_read,
+ .mask = CLOCKSOURCE_MASK(64),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void __init gt_clocksource_init(void)
+{
+ writel(0, gt_base + GT_CONTROL);
+ writel(0, gt_base + GT_COUNTER0);
+ writel(0, gt_base + GT_COUNTER1);
+ writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
+
+ gt_clocksource.shift = 20;
+ gt_clocksource.mult =
+ clocksource_hz2mult(gt_clk_rate, gt_clocksource.shift);
+ clocksource_register(>_clocksource);
+}
+
+static struct clk *gt_get_clock(void)
+{
+ struct clk *clk;
+ int err;
+
+ clk = clk_get_sys("gt", NULL);
+ if (IS_ERR(clk)) {
+ pr_err("global-timer: clock not found: %ld\n", PTR_ERR(clk));
+ return clk;
+ }
+
+ err = clk_prepare_enable(clk);
+ if (err) {
+ pr_err("global-timer: clock prepare+enable failed: %d\n", err);
+ clk_put(clk);
+ return ERR_PTR(err);
+ }
+
+ return clk;
+}
+
+static struct local_timer_ops gt_lt_ops __cpuinitdata = {
+ .setup = gt_clockevents_setup,
+ .stop = gt_clockevents_stop,
+};
+
+int __init global_timer_init(void __iomem *base, unsigned int timer_irq)
+{
+ unsigned int cpu = smp_processor_id();
+ struct clock_event_device *evt = &per_cpu(gt_clockevent, cpu);
+ int err = 0;
+
+ if (gt_base) {
+ pr_warn("global-timer: invalid base address\n");
+ return -EINVAL;
+ }
+
+ gt_clk = gt_get_clock();
+ if (IS_ERR(gt_clk)) {
+ pr_warn("global-timer: clk not found\n");
+ return -EINVAL;
+ }
+
+ gt_evt = alloc_percpu(struct clock_event_device *);
+ if (!gt_evt) {
+ pr_warn("global-timer: can't allocate memory\n");
+ return -ENOMEM;
+ }
+
+ err = request_percpu_irq(timer_irq, gt_clockevent_interrupt,
+ "gt", gt_evt);
+ if (err) {
+ pr_warn("global-timer: can't register interrupt %d (%d)\n",
+ timer_irq, err);
+ goto out_free;
+ }
+
+ gt_base = base;
+ gt_clk_rate = clk_get_rate(gt_clk);
+
+ evt->irq = timer_irq;
+ gt_ppi = timer_irq;
+ evt->cpumask = cpumask_of(cpu);
+
+ gt_clocksource_init();
+ gt_clockevents_init(evt);
+ err = local_timer_register(>_lt_ops);
+ if (err) {
+ pr_warn("global-timer: unable to register local timer.\n");
+ goto out_irq;
+ }
+
+ return 0;
+
+out_irq:
+ free_percpu_irq(timer_irq, gt_evt);
+out_free:
+ free_percpu(gt_evt);
+ return err;
+}
+
+#ifdef CONFIG_OF
+static void __init global_timer_of_register(struct device_node *np)
+{
+ struct clk *clk;
+ int err = 0;
+ int gt_ppi;
+ static void __iomem *gt_base;
+
+ gt_ppi = irq_of_parse_and_map(np, 0);
+ if (!gt_ppi) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ gt_base = of_iomap(np, 0);
+ if (!gt_base) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ clk = of_clk_get(np, 0);
+ if (!IS_ERR(clk))
+ clk_register_clkdev(clk, NULL, "gt");
+
+ global_timer_init(gt_base, gt_ppi);
+
+out:
+ WARN(err, "Global timer register failed (%d)\n", err);
+}
+
+CLOCKSOURCE_OF_DECLARE(arm_gt_a9, "arm,cortex-a9-global-timer",
+ global_timer_of_register);
+#endif
--
1.7.6.5
^ permalink raw reply related [flat|nested] 79+ messages in thread
* Re: [RFC 2/8] ARM:global_timer: Add ARM global timer support.
2013-05-08 14:11 ` [RFC 2/8] ARM:global_timer: Add ARM global timer support Srinivas KANDAGATLA
@ 2013-05-08 14:26 ` Rob Herring
2013-05-08 15:06 ` Stuart MENEFY
2013-05-08 14:38 ` Arnd Bergmann
[not found] ` <1368022260-2197-1-git-send-email-srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
2 siblings, 1 reply; 79+ messages in thread
From: Rob Herring @ 2013-05-08 14:26 UTC (permalink / raw)
To: Srinivas KANDAGATLA
Cc: linux, will.deacon, Rob Landley, Grant Likely, Samuel Ortiz,
Linus Walleij, Greg Kroah-Hartman, Jiri Slaby, Stuart Menefy,
Shawn Guo, Olof Johansson, Jason Cooper, Stephen Warren,
Maxime Ripard, Nicolas Pitre, Dave Martin, Marc Zyngier,
Viresh Kumar, Arnd Bergmann, Mark Brown, Dong Aisheng, linux-doc,
linux-kernel, devicetree-discuss
On 05/08/2013 09:11 AM, Srinivas KANDAGATLA wrote:
> From: Stuart Menefy <stuart.menefy@st.com>
>
> This is a simple driver for the global timer module found in the Cortex
> A9-MP cores from revision r1p0 onwards. This should be able to perform
> the functions of the system timer and the local timer in an SMP system.
>
> The global timer has the following features:
> The global timer is a 64-bit incrementing counter with an
> auto-incrementing feature. It continues incrementing after sending
> interrupts. The global timer is memory mapped in the private memory
> region.
> The global timer is accessible to all Cortex-A9 processors in the
> cluster. Each Cortex-A9 processor has a private 64-bit comparator that
> is used to assert a private interrupt when the global timer has reached
> the comparator value. All the Cortex-A9 processors in a design use the
> banked ID, ID27, for this interrupt. ID27 is sent to the Interrupt
> Controller as a Private Peripheral Interrupt. The global timer is
> clocked by PERIPHCLK.
PERIPHCLK scales with cpu clock typically so the global timer is not a
suitable clocksource if you use cpufreq. You can deal with the scaling
on clockevents, but not a clocksource. I imagine the global timers is
also typically power-gated in some low power modes. This is why no one
has added support already. Are neither of those an issue or going to be
an issue for you?
Rob
>
> Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
> ---
> Documentation/devicetree/bindings/arm/gt.txt | 21 ++
> arch/arm/Kconfig | 6 +
> arch/arm/include/asm/global_timer.h | 12 +
> arch/arm/kernel/Makefile | 1 +
> arch/arm/kernel/global_timer.c | 325 ++++++++++++++++++++++++++
> 5 files changed, 365 insertions(+), 0 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/arm/gt.txt
> create mode 100644 arch/arm/include/asm/global_timer.h
> create mode 100644 arch/arm/kernel/global_timer.c
>
> diff --git a/Documentation/devicetree/bindings/arm/gt.txt b/Documentation/devicetree/bindings/arm/gt.txt
> new file mode 100644
> index 0000000..4ec5fb0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/gt.txt
> @@ -0,0 +1,21 @@
> +
> +* ARM Global Timer
> + Cortex-A9 are often associated with a per-core Global timer.
> +
> +** Timer node required properties:
> +
> +- compatible : Should be one of:
> + "arm,cortex-a9-global-timer"
> +
> +- interrupts : One interrupt to each core
> +
> +- reg : Specify the base address and the size of the GT timer
> + register window.
> +
> +Example:
> +
> + gt-timer@2c000600 {
> + compatible = "arm,cortex-a9-global-timer";
> + reg = <0x2c000600 0x20>;
> + interrupts = <1 13 0xf01>;
> + };
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 1cacda4..c8c524e 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1606,6 +1606,12 @@ config HAVE_ARM_TWD
> help
> This options enables support for the ARM timer and watchdog unit
>
> +config HAVE_ARM_GT
> + bool
> + select CLKSRC_OF if OF
> + help
> + This options enables support for the ARM global timer unit
> +
> choice
> prompt "Memory split"
> default VMSPLIT_3G
> diff --git a/arch/arm/include/asm/global_timer.h b/arch/arm/include/asm/global_timer.h
> new file mode 100644
> index 0000000..46f9188
> --- /dev/null
> +++ b/arch/arm/include/asm/global_timer.h
> @@ -0,0 +1,12 @@
> +/*
> + * arch/arm/include/asm/global_timer.h
> + *
> + * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
> + * Author: Stuart Menefy <stuart.menefy@st.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +int __init global_timer_init(void __iomem *base, unsigned int timer_irq);
> diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
> index 5f3338e..af51808 100644
> --- a/arch/arm/kernel/Makefile
> +++ b/arch/arm/kernel/Makefile
> @@ -35,6 +35,7 @@ obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.o
> obj-$(CONFIG_SMP) += smp.o smp_tlb.o
> obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
> obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
> +obj-$(CONFIG_HAVE_ARM_GT) += global_timer.o
> obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o
> obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o
> obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o
> diff --git a/arch/arm/kernel/global_timer.c b/arch/arm/kernel/global_timer.c
> new file mode 100644
> index 0000000..0ab1af3
> --- /dev/null
> +++ b/arch/arm/kernel/global_timer.c
> @@ -0,0 +1,325 @@
> +/*
> + * linux/arch/arm/kernel/global_timer.c
> + *
> + * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
> + * Author: Stuart Menefy <stuart.menefy@st.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/clocksource.h>
> +#include <linux/clockchips.h>
> +#include <linux/clk.h>
> +#include <linux/clkdev.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_address.h>
> +
> +#include <asm/mach/irq.h>
> +#include <asm/global_timer.h>
> +#include <asm/localtimer.h>
> +
> +#define GT_COUNTER0 0x00
> +#define GT_COUNTER1 0x04
> +
> +#define GT_CONTROL 0x08
> +#define GT_CONTROL_TIMER_ENABLE BIT(0)
> +#define GT_CONTROL_COMP_ENABLE BIT(1) /* banked */
> +#define GT_CONTROL_IRQ_ENABLE BIT(2) /* banked */
> +#define GT_CONTROL_AUTO_INC BIT(3) /* banked */
> +
> +#define GT_INT_STATUS 0x0c
> +#define GT_INT_STATUS_EVENT_FLAG BIT(0)
> +
> +#define GT_COMP0 0x10
> +#define GT_COMP1 0x14
> +#define GT_AUTO_INC 0x18
> +
> +/*
> + * We are expecting to be clocked by the ARM peripheral clock.
> + *
> + * Note: it is assumed we are using a prescaler value of zero, so this is
> + * the units for all operations.
> + */
> +static void __iomem *gt_base;
> +static struct clk *gt_clk;
> +static unsigned long gt_clk_rate;
> +static int gt_ppi;
> +static struct clock_event_device __percpu **gt_evt;
> +static DEFINE_PER_CPU(bool, percpu_init_called);
> +static DEFINE_PER_CPU(struct clock_event_device, gt_clockevent);
> +
> +union gt_counter {
> + cycle_t cycles;
> + struct {
> + uint32_t lower;
> + uint32_t upper;
> + };
> +};
> +
> +static union gt_counter gt_counter_read(void)
> +{
> + union gt_counter res;
> + uint32_t upper;
> +
> + upper = readl(gt_base + GT_COUNTER1);
> + do {
> + res.upper = upper;
> + res.lower = readl(gt_base + GT_COUNTER0);
> + upper = readl(gt_base + GT_COUNTER1);
> + } while (upper != res.upper);
> +
> + return res;
> +}
> +
> +static void gt_compare_set(unsigned long delta, int periodic)
> +{
> + union gt_counter counter = gt_counter_read();
> + unsigned long ctrl = readl(gt_base + GT_CONTROL);
> +
> + BUG_ON(!(ctrl & GT_CONTROL_TIMER_ENABLE));
> + BUG_ON(ctrl & (GT_CONTROL_COMP_ENABLE |
> + GT_CONTROL_IRQ_ENABLE |
> + GT_CONTROL_AUTO_INC));
> +
> + counter.cycles += delta;
> + writel(counter.lower, gt_base + GT_COMP0);
> + writel(counter.upper, gt_base + GT_COMP1);
> +
> + ctrl |= GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE;
> +
> + if (periodic) {
> + writel(delta, gt_base + GT_AUTO_INC);
> + ctrl |= GT_CONTROL_AUTO_INC;
> + }
> +
> + writel(ctrl, gt_base + GT_CONTROL);
> +}
> +
> +static void gt_clockevent_set_mode(enum clock_event_mode mode,
> + struct clock_event_device *clk)
> +{
> + switch (mode) {
> + case CLOCK_EVT_MODE_PERIODIC:
> + gt_compare_set(gt_clk_rate/HZ, 1);
> + break;
> + case CLOCK_EVT_MODE_ONESHOT:
> + /* period set, and timer enabled in 'next_event' hook */
> + BUG_ON(readl(gt_base + GT_CONTROL) &
> + (GT_CONTROL_COMP_ENABLE |
> + GT_CONTROL_IRQ_ENABLE |
> + GT_CONTROL_AUTO_INC));
> + /* Fall through */
> + case CLOCK_EVT_MODE_UNUSED:
> + case CLOCK_EVT_MODE_SHUTDOWN:
> + default:
> + writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
> + break;
> + }
> +}
> +
> +static int gt_clockevent_set_next_event(unsigned long evt,
> + struct clock_event_device *unused)
> +{
> + gt_compare_set(evt, 0);
> + return 0;
> +}
> +
> +static irqreturn_t gt_clockevent_interrupt(int irq, void *dev_id)
> +{
> + struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
> +
> + writel(GT_INT_STATUS_EVENT_FLAG, gt_base + GT_INT_STATUS);
> + evt->event_handler(evt);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int __cpuinit gt_clockevents_init(struct clock_event_device *clk)
> +{
> + struct clock_event_device **this_cpu_clk;
> + int cpu = smp_processor_id();
> +
> + clk->name = "Global Timer CE";
> + clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
> + clk->set_mode = gt_clockevent_set_mode;
> + clk->set_next_event = gt_clockevent_set_next_event;
> + this_cpu_clk = __this_cpu_ptr(gt_evt);
> + *this_cpu_clk = clk;
> + clk->irq = gt_ppi;
> + clockevents_config_and_register(clk, gt_clk_rate,
> + 0xf, 0xffffffff);
> + per_cpu(percpu_init_called, cpu) = true;
> + enable_percpu_irq(clk->irq, IRQ_TYPE_NONE);
> + return 0;
> +}
> +
> +static void gt_clockevents_stop(struct clock_event_device *clk)
> +{
> + gt_clockevent_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
> + disable_percpu_irq(clk->irq);
> +}
> +
> +static int __cpuinit gt_clockevents_setup(struct clock_event_device *clk)
> +{
> + int cpu = smp_processor_id();
> +
> + /* Use existing clock_event for boot cpu */
> + if (per_cpu(percpu_init_called, cpu))
> + return 0;
> +
> + writel(0, gt_base + GT_CONTROL);
> + writel(0, gt_base + GT_COUNTER0);
> + writel(0, gt_base + GT_COUNTER1);
> + writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
> +
> + return gt_clockevents_init(clk);
> +}
> +
> +static cycle_t gt_clocksource_read(struct clocksource *cs)
> +{
> + union gt_counter res = gt_counter_read();
> + return res.cycles;
> +}
> +
> +static struct clocksource gt_clocksource = {
> + .name = "Global Timer CS",
> + .rating = 300,
> + .read = gt_clocksource_read,
> + .mask = CLOCKSOURCE_MASK(64),
> + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
> +};
> +
> +static void __init gt_clocksource_init(void)
> +{
> + writel(0, gt_base + GT_CONTROL);
> + writel(0, gt_base + GT_COUNTER0);
> + writel(0, gt_base + GT_COUNTER1);
> + writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
> +
> + gt_clocksource.shift = 20;
> + gt_clocksource.mult =
> + clocksource_hz2mult(gt_clk_rate, gt_clocksource.shift);
> + clocksource_register(>_clocksource);
> +}
> +
> +static struct clk *gt_get_clock(void)
> +{
> + struct clk *clk;
> + int err;
> +
> + clk = clk_get_sys("gt", NULL);
> + if (IS_ERR(clk)) {
> + pr_err("global-timer: clock not found: %ld\n", PTR_ERR(clk));
> + return clk;
> + }
> +
> + err = clk_prepare_enable(clk);
> + if (err) {
> + pr_err("global-timer: clock prepare+enable failed: %d\n", err);
> + clk_put(clk);
> + return ERR_PTR(err);
> + }
> +
> + return clk;
> +}
> +
> +static struct local_timer_ops gt_lt_ops __cpuinitdata = {
> + .setup = gt_clockevents_setup,
> + .stop = gt_clockevents_stop,
> +};
> +
> +int __init global_timer_init(void __iomem *base, unsigned int timer_irq)
> +{
> + unsigned int cpu = smp_processor_id();
> + struct clock_event_device *evt = &per_cpu(gt_clockevent, cpu);
> + int err = 0;
> +
> + if (gt_base) {
> + pr_warn("global-timer: invalid base address\n");
> + return -EINVAL;
> + }
> +
> + gt_clk = gt_get_clock();
> + if (IS_ERR(gt_clk)) {
> + pr_warn("global-timer: clk not found\n");
> + return -EINVAL;
> + }
> +
> + gt_evt = alloc_percpu(struct clock_event_device *);
> + if (!gt_evt) {
> + pr_warn("global-timer: can't allocate memory\n");
> + return -ENOMEM;
> + }
> +
> + err = request_percpu_irq(timer_irq, gt_clockevent_interrupt,
> + "gt", gt_evt);
> + if (err) {
> + pr_warn("global-timer: can't register interrupt %d (%d)\n",
> + timer_irq, err);
> + goto out_free;
> + }
> +
> + gt_base = base;
> + gt_clk_rate = clk_get_rate(gt_clk);
> +
> + evt->irq = timer_irq;
> + gt_ppi = timer_irq;
> + evt->cpumask = cpumask_of(cpu);
> +
> + gt_clocksource_init();
> + gt_clockevents_init(evt);
> + err = local_timer_register(>_lt_ops);
> + if (err) {
> + pr_warn("global-timer: unable to register local timer.\n");
> + goto out_irq;
> + }
> +
> + return 0;
> +
> +out_irq:
> + free_percpu_irq(timer_irq, gt_evt);
> +out_free:
> + free_percpu(gt_evt);
> + return err;
> +}
> +
> +#ifdef CONFIG_OF
> +static void __init global_timer_of_register(struct device_node *np)
> +{
> + struct clk *clk;
> + int err = 0;
> + int gt_ppi;
> + static void __iomem *gt_base;
> +
> + gt_ppi = irq_of_parse_and_map(np, 0);
> + if (!gt_ppi) {
> + err = -EINVAL;
> + goto out;
> + }
> +
> + gt_base = of_iomap(np, 0);
> + if (!gt_base) {
> + err = -ENOMEM;
> + goto out;
> + }
> +
> + clk = of_clk_get(np, 0);
> + if (!IS_ERR(clk))
> + clk_register_clkdev(clk, NULL, "gt");
> +
> + global_timer_init(gt_base, gt_ppi);
> +
> +out:
> + WARN(err, "Global timer register failed (%d)\n", err);
> +}
> +
> +CLOCKSOURCE_OF_DECLARE(arm_gt_a9, "arm,cortex-a9-global-timer",
> + global_timer_of_register);
> +#endif
>
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 2/8] ARM:global_timer: Add ARM global timer support.
2013-05-08 14:26 ` Rob Herring
@ 2013-05-08 15:06 ` Stuart MENEFY
0 siblings, 0 replies; 79+ messages in thread
From: Stuart MENEFY @ 2013-05-08 15:06 UTC (permalink / raw)
To: Rob Herring
Cc: Dave Martin, Srinivas KANDAGATLA, Viresh Kumar, Linus Walleij,
will.deacon, Grant Likely, Jiri Slaby, linux, Samuel Ortiz,
Nicolas Pitre, linux-doc, linux-serial, Jason Cooper,
Arnd Bergmann, Marc Zyngier, devicetree-discuss, Stephen Warren,
Dong Aisheng, linux-arm-kernel, Greg Kroah-Hartman, Mark Brown,
linux-kernel, Rob Landley, Olof Johansson,
Maxime Ripard <max>
On 08/05/13 15:26, Rob Herring wrote:
> On 05/08/2013 09:11 AM, Srinivas KANDAGATLA wrote:
>> From: Stuart Menefy <stuart.menefy@st.com>
>>
>> This is a simple driver for the global timer module found in the Cortex
>> A9-MP cores from revision r1p0 onwards. This should be able to perform
>> the functions of the system timer and the local timer in an SMP system.
>>
>> The global timer has the following features:
>> The global timer is a 64-bit incrementing counter with an
>> auto-incrementing feature. It continues incrementing after sending
>> interrupts. The global timer is memory mapped in the private memory
>> region.
>> The global timer is accessible to all Cortex-A9 processors in the
>> cluster. Each Cortex-A9 processor has a private 64-bit comparator that
>> is used to assert a private interrupt when the global timer has reached
>> the comparator value. All the Cortex-A9 processors in a design use the
>> banked ID, ID27, for this interrupt. ID27 is sent to the Interrupt
>> Controller as a Private Peripheral Interrupt. The global timer is
>> clocked by PERIPHCLK.
>
> PERIPHCLK scales with cpu clock typically so the global timer is not a
> suitable clocksource if you use cpufreq. You can deal with the scaling
> on clockevents, but not a clocksource. I imagine the global timers is
> also typically power-gated in some low power modes. This is why no one
> has added support already. Are neither of those an issue or going to be
> an issue for you?
I agree but we're limited by the available hardware, the SoC designers
didn't put down any general purpose timers unfortunately, so we have to
use the global timer as a clocksource.
The full version of this code has a cpufreq notifier to try and cope with
changes, but we didn't include that as the rest of the cpufreq code is
missing in this first post. There will be inaccuracies of course, but its
the best we can do.
There is no power gating on these devices, and clock gating only occurs
at the clock input to the A9 subsystem including the cores and timers,
so we don't have that issue.
Stuart
>> Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
>> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>> ---
>> Documentation/devicetree/bindings/arm/gt.txt | 21 ++
>> arch/arm/Kconfig | 6 +
>> arch/arm/include/asm/global_timer.h | 12 +
>> arch/arm/kernel/Makefile | 1 +
>> arch/arm/kernel/global_timer.c | 325 ++++++++++++++++++++++++++
>> 5 files changed, 365 insertions(+), 0 deletions(-)
>> create mode 100644 Documentation/devicetree/bindings/arm/gt.txt
>> create mode 100644 arch/arm/include/asm/global_timer.h
>> create mode 100644 arch/arm/kernel/global_timer.c
>>
>> diff --git a/Documentation/devicetree/bindings/arm/gt.txt b/Documentation/devicetree/bindings/arm/gt.txt
>> new file mode 100644
>> index 0000000..4ec5fb0
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/gt.txt
>> @@ -0,0 +1,21 @@
>> +
>> +* ARM Global Timer
>> + Cortex-A9 are often associated with a per-core Global timer.
>> +
>> +** Timer node required properties:
>> +
>> +- compatible : Should be one of:
>> + "arm,cortex-a9-global-timer"
>> +
>> +- interrupts : One interrupt to each core
>> +
>> +- reg : Specify the base address and the size of the GT timer
>> + register window.
>> +
>> +Example:
>> +
>> + gt-timer@2c000600 {
>> + compatible = "arm,cortex-a9-global-timer";
>> + reg = <0x2c000600 0x20>;
>> + interrupts = <1 13 0xf01>;
>> + };
>> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
>> index 1cacda4..c8c524e 100644
>> --- a/arch/arm/Kconfig
>> +++ b/arch/arm/Kconfig
>> @@ -1606,6 +1606,12 @@ config HAVE_ARM_TWD
>> help
>> This options enables support for the ARM timer and watchdog unit
>>
>> +config HAVE_ARM_GT
>> + bool
>> + select CLKSRC_OF if OF
>> + help
>> + This options enables support for the ARM global timer unit
>> +
>> choice
>> prompt "Memory split"
>> default VMSPLIT_3G
>> diff --git a/arch/arm/include/asm/global_timer.h b/arch/arm/include/asm/global_timer.h
>> new file mode 100644
>> index 0000000..46f9188
>> --- /dev/null
>> +++ b/arch/arm/include/asm/global_timer.h
>> @@ -0,0 +1,12 @@
>> +/*
>> + * arch/arm/include/asm/global_timer.h
>> + *
>> + * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
>> + * Author: Stuart Menefy <stuart.menefy@st.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +int __init global_timer_init(void __iomem *base, unsigned int timer_irq);
>> diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
>> index 5f3338e..af51808 100644
>> --- a/arch/arm/kernel/Makefile
>> +++ b/arch/arm/kernel/Makefile
>> @@ -35,6 +35,7 @@ obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.o
>> obj-$(CONFIG_SMP) += smp.o smp_tlb.o
>> obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
>> obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
>> +obj-$(CONFIG_HAVE_ARM_GT) += global_timer.o
>> obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o
>> obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o
>> obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o
>> diff --git a/arch/arm/kernel/global_timer.c b/arch/arm/kernel/global_timer.c
>> new file mode 100644
>> index 0000000..0ab1af3
>> --- /dev/null
>> +++ b/arch/arm/kernel/global_timer.c
>> @@ -0,0 +1,325 @@
>> +/*
>> + * linux/arch/arm/kernel/global_timer.c
>> + *
>> + * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
>> + * Author: Stuart Menefy <stuart.menefy@st.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include <linux/init.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/clocksource.h>
>> +#include <linux/clockchips.h>
>> +#include <linux/clk.h>
>> +#include <linux/clkdev.h>
>> +#include <linux/err.h>
>> +#include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/of_irq.h>
>> +#include <linux/of_address.h>
>> +
>> +#include <asm/mach/irq.h>
>> +#include <asm/global_timer.h>
>> +#include <asm/localtimer.h>
>> +
>> +#define GT_COUNTER0 0x00
>> +#define GT_COUNTER1 0x04
>> +
>> +#define GT_CONTROL 0x08
>> +#define GT_CONTROL_TIMER_ENABLE BIT(0)
>> +#define GT_CONTROL_COMP_ENABLE BIT(1) /* banked */
>> +#define GT_CONTROL_IRQ_ENABLE BIT(2) /* banked */
>> +#define GT_CONTROL_AUTO_INC BIT(3) /* banked */
>> +
>> +#define GT_INT_STATUS 0x0c
>> +#define GT_INT_STATUS_EVENT_FLAG BIT(0)
>> +
>> +#define GT_COMP0 0x10
>> +#define GT_COMP1 0x14
>> +#define GT_AUTO_INC 0x18
>> +
>> +/*
>> + * We are expecting to be clocked by the ARM peripheral clock.
>> + *
>> + * Note: it is assumed we are using a prescaler value of zero, so this is
>> + * the units for all operations.
>> + */
>> +static void __iomem *gt_base;
>> +static struct clk *gt_clk;
>> +static unsigned long gt_clk_rate;
>> +static int gt_ppi;
>> +static struct clock_event_device __percpu **gt_evt;
>> +static DEFINE_PER_CPU(bool, percpu_init_called);
>> +static DEFINE_PER_CPU(struct clock_event_device, gt_clockevent);
>> +
>> +union gt_counter {
>> + cycle_t cycles;
>> + struct {
>> + uint32_t lower;
>> + uint32_t upper;
>> + };
>> +};
>> +
>> +static union gt_counter gt_counter_read(void)
>> +{
>> + union gt_counter res;
>> + uint32_t upper;
>> +
>> + upper = readl(gt_base + GT_COUNTER1);
>> + do {
>> + res.upper = upper;
>> + res.lower = readl(gt_base + GT_COUNTER0);
>> + upper = readl(gt_base + GT_COUNTER1);
>> + } while (upper != res.upper);
>> +
>> + return res;
>> +}
>> +
>> +static void gt_compare_set(unsigned long delta, int periodic)
>> +{
>> + union gt_counter counter = gt_counter_read();
>> + unsigned long ctrl = readl(gt_base + GT_CONTROL);
>> +
>> + BUG_ON(!(ctrl & GT_CONTROL_TIMER_ENABLE));
>> + BUG_ON(ctrl & (GT_CONTROL_COMP_ENABLE |
>> + GT_CONTROL_IRQ_ENABLE |
>> + GT_CONTROL_AUTO_INC));
>> +
>> + counter.cycles += delta;
>> + writel(counter.lower, gt_base + GT_COMP0);
>> + writel(counter.upper, gt_base + GT_COMP1);
>> +
>> + ctrl |= GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE;
>> +
>> + if (periodic) {
>> + writel(delta, gt_base + GT_AUTO_INC);
>> + ctrl |= GT_CONTROL_AUTO_INC;
>> + }
>> +
>> + writel(ctrl, gt_base + GT_CONTROL);
>> +}
>> +
>> +static void gt_clockevent_set_mode(enum clock_event_mode mode,
>> + struct clock_event_device *clk)
>> +{
>> + switch (mode) {
>> + case CLOCK_EVT_MODE_PERIODIC:
>> + gt_compare_set(gt_clk_rate/HZ, 1);
>> + break;
>> + case CLOCK_EVT_MODE_ONESHOT:
>> + /* period set, and timer enabled in 'next_event' hook */
>> + BUG_ON(readl(gt_base + GT_CONTROL) &
>> + (GT_CONTROL_COMP_ENABLE |
>> + GT_CONTROL_IRQ_ENABLE |
>> + GT_CONTROL_AUTO_INC));
>> + /* Fall through */
>> + case CLOCK_EVT_MODE_UNUSED:
>> + case CLOCK_EVT_MODE_SHUTDOWN:
>> + default:
>> + writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
>> + break;
>> + }
>> +}
>> +
>> +static int gt_clockevent_set_next_event(unsigned long evt,
>> + struct clock_event_device *unused)
>> +{
>> + gt_compare_set(evt, 0);
>> + return 0;
>> +}
>> +
>> +static irqreturn_t gt_clockevent_interrupt(int irq, void *dev_id)
>> +{
>> + struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
>> +
>> + writel(GT_INT_STATUS_EVENT_FLAG, gt_base + GT_INT_STATUS);
>> + evt->event_handler(evt);
>> +
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static int __cpuinit gt_clockevents_init(struct clock_event_device *clk)
>> +{
>> + struct clock_event_device **this_cpu_clk;
>> + int cpu = smp_processor_id();
>> +
>> + clk->name = "Global Timer CE";
>> + clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
>> + clk->set_mode = gt_clockevent_set_mode;
>> + clk->set_next_event = gt_clockevent_set_next_event;
>> + this_cpu_clk = __this_cpu_ptr(gt_evt);
>> + *this_cpu_clk = clk;
>> + clk->irq = gt_ppi;
>> + clockevents_config_and_register(clk, gt_clk_rate,
>> + 0xf, 0xffffffff);
>> + per_cpu(percpu_init_called, cpu) = true;
>> + enable_percpu_irq(clk->irq, IRQ_TYPE_NONE);
>> + return 0;
>> +}
>> +
>> +static void gt_clockevents_stop(struct clock_event_device *clk)
>> +{
>> + gt_clockevent_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
>> + disable_percpu_irq(clk->irq);
>> +}
>> +
>> +static int __cpuinit gt_clockevents_setup(struct clock_event_device *clk)
>> +{
>> + int cpu = smp_processor_id();
>> +
>> + /* Use existing clock_event for boot cpu */
>> + if (per_cpu(percpu_init_called, cpu))
>> + return 0;
>> +
>> + writel(0, gt_base + GT_CONTROL);
>> + writel(0, gt_base + GT_COUNTER0);
>> + writel(0, gt_base + GT_COUNTER1);
>> + writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
>> +
>> + return gt_clockevents_init(clk);
>> +}
>> +
>> +static cycle_t gt_clocksource_read(struct clocksource *cs)
>> +{
>> + union gt_counter res = gt_counter_read();
>> + return res.cycles;
>> +}
>> +
>> +static struct clocksource gt_clocksource = {
>> + .name = "Global Timer CS",
>> + .rating = 300,
>> + .read = gt_clocksource_read,
>> + .mask = CLOCKSOURCE_MASK(64),
>> + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
>> +};
>> +
>> +static void __init gt_clocksource_init(void)
>> +{
>> + writel(0, gt_base + GT_CONTROL);
>> + writel(0, gt_base + GT_COUNTER0);
>> + writel(0, gt_base + GT_COUNTER1);
>> + writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
>> +
>> + gt_clocksource.shift = 20;
>> + gt_clocksource.mult =
>> + clocksource_hz2mult(gt_clk_rate, gt_clocksource.shift);
>> + clocksource_register(>_clocksource);
>> +}
>> +
>> +static struct clk *gt_get_clock(void)
>> +{
>> + struct clk *clk;
>> + int err;
>> +
>> + clk = clk_get_sys("gt", NULL);
>> + if (IS_ERR(clk)) {
>> + pr_err("global-timer: clock not found: %ld\n", PTR_ERR(clk));
>> + return clk;
>> + }
>> +
>> + err = clk_prepare_enable(clk);
>> + if (err) {
>> + pr_err("global-timer: clock prepare+enable failed: %d\n", err);
>> + clk_put(clk);
>> + return ERR_PTR(err);
>> + }
>> +
>> + return clk;
>> +}
>> +
>> +static struct local_timer_ops gt_lt_ops __cpuinitdata = {
>> + .setup = gt_clockevents_setup,
>> + .stop = gt_clockevents_stop,
>> +};
>> +
>> +int __init global_timer_init(void __iomem *base, unsigned int timer_irq)
>> +{
>> + unsigned int cpu = smp_processor_id();
>> + struct clock_event_device *evt = &per_cpu(gt_clockevent, cpu);
>> + int err = 0;
>> +
>> + if (gt_base) {
>> + pr_warn("global-timer: invalid base address\n");
>> + return -EINVAL;
>> + }
>> +
>> + gt_clk = gt_get_clock();
>> + if (IS_ERR(gt_clk)) {
>> + pr_warn("global-timer: clk not found\n");
>> + return -EINVAL;
>> + }
>> +
>> + gt_evt = alloc_percpu(struct clock_event_device *);
>> + if (!gt_evt) {
>> + pr_warn("global-timer: can't allocate memory\n");
>> + return -ENOMEM;
>> + }
>> +
>> + err = request_percpu_irq(timer_irq, gt_clockevent_interrupt,
>> + "gt", gt_evt);
>> + if (err) {
>> + pr_warn("global-timer: can't register interrupt %d (%d)\n",
>> + timer_irq, err);
>> + goto out_free;
>> + }
>> +
>> + gt_base = base;
>> + gt_clk_rate = clk_get_rate(gt_clk);
>> +
>> + evt->irq = timer_irq;
>> + gt_ppi = timer_irq;
>> + evt->cpumask = cpumask_of(cpu);
>> +
>> + gt_clocksource_init();
>> + gt_clockevents_init(evt);
>> + err = local_timer_register(>_lt_ops);
>> + if (err) {
>> + pr_warn("global-timer: unable to register local timer.\n");
>> + goto out_irq;
>> + }
>> +
>> + return 0;
>> +
>> +out_irq:
>> + free_percpu_irq(timer_irq, gt_evt);
>> +out_free:
>> + free_percpu(gt_evt);
>> + return err;
>> +}
>> +
>> +#ifdef CONFIG_OF
>> +static void __init global_timer_of_register(struct device_node *np)
>> +{
>> + struct clk *clk;
>> + int err = 0;
>> + int gt_ppi;
>> + static void __iomem *gt_base;
>> +
>> + gt_ppi = irq_of_parse_and_map(np, 0);
>> + if (!gt_ppi) {
>> + err = -EINVAL;
>> + goto out;
>> + }
>> +
>> + gt_base = of_iomap(np, 0);
>> + if (!gt_base) {
>> + err = -ENOMEM;
>> + goto out;
>> + }
>> +
>> + clk = of_clk_get(np, 0);
>> + if (!IS_ERR(clk))
>> + clk_register_clkdev(clk, NULL, "gt");
>> +
>> + global_timer_init(gt_base, gt_ppi);
>> +
>> +out:
>> + WARN(err, "Global timer register failed (%d)\n", err);
>> +}
>> +
>> +CLOCKSOURCE_OF_DECLARE(arm_gt_a9, "arm,cortex-a9-global-timer",
>> + global_timer_of_register);
>> +#endif
>>
>
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 2/8] ARM:global_timer: Add ARM global timer support.
2013-05-08 14:11 ` [RFC 2/8] ARM:global_timer: Add ARM global timer support Srinivas KANDAGATLA
2013-05-08 14:26 ` Rob Herring
@ 2013-05-08 14:38 ` Arnd Bergmann
[not found] ` <201305081638.23100.arnd-r2nGTMty4D4@public.gmane.org>
` (2 more replies)
[not found] ` <1368022260-2197-1-git-send-email-srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
2 siblings, 3 replies; 79+ messages in thread
From: Arnd Bergmann @ 2013-05-08 14:38 UTC (permalink / raw)
To: Srinivas KANDAGATLA
Cc: linux, will.deacon, Rob Landley, Grant Likely, Rob Herring,
Samuel Ortiz, Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Stuart Menefy, Shawn Guo, Olof Johansson, Jason Cooper,
Stephen Warren, Maxime Ripard, Nicolas Pitre, Dave Martin,
Marc Zyngier, Viresh Kumar, Mark Brown, Dong Aisheng, linux-doc,
linux-kernel, devicetree-discuss
On Wednesday 08 May 2013, Srinivas KANDAGATLA wrote:
> From: Stuart Menefy <stuart.menefy@st.com>
>
> This is a simple driver for the global timer module found in the Cortex
> A9-MP cores from revision r1p0 onwards. This should be able to perform
> the functions of the system timer and the local timer in an SMP system.
>
> The global timer has the following features:
> The global timer is a 64-bit incrementing counter with an
> auto-incrementing feature. It continues incrementing after sending
> interrupts. The global timer is memory mapped in the private memory
> region.
> The global timer is accessible to all Cortex-A9 processors in the
> cluster. Each Cortex-A9 processor has a private 64-bit comparator that
> is used to assert a private interrupt when the global timer has reached
> the comparator value. All the Cortex-A9 processors in a design use the
> banked ID, ID27, for this interrupt. ID27 is sent to the Interrupt
> Controller as a Private Peripheral Interrupt. The global timer is
> clocked by PERIPHCLK.
>
> Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>
Are you sure we don't already have a driver for this? It sounds unlikely
that you are the first one to do this when the hardware is so common.
> Documentation/devicetree/bindings/arm/gt.txt | 21 ++
> arch/arm/Kconfig | 6 +
> arch/arm/include/asm/global_timer.h | 12 +
> arch/arm/kernel/Makefile | 1 +
> arch/arm/kernel/global_timer.c | 325 ++++++++++++++++++++++++++
> 5 files changed, 365 insertions(+), 0 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/arm/gt.txt
> create mode 100644 arch/arm/include/asm/global_timer.h
> create mode 100644 arch/arm/kernel/global_timer.c
Move it into drivers/clocksource?
> diff --git a/arch/arm/include/asm/global_timer.h b/arch/arm/include/asm/global_timer.h
> new file mode 100644
> index 0000000..46f9188
> --- /dev/null
> +++ b/arch/arm/include/asm/global_timer.h
> @@ -0,0 +1,12 @@
> +int __init global_timer_init(void __iomem *base, unsigned int timer_irq);
I don't see a need to call this from platform code for non-DT platforms, it
can easily be used with CLOCKSOURCE_OF_DECLARE() all the time I think.
Arnd
^ permalink raw reply [flat|nested] 79+ messages in thread
[parent not found: <201305081638.23100.arnd-r2nGTMty4D4@public.gmane.org>]
* Re: [RFC 2/8] ARM:global_timer: Add ARM global timer support.
[not found] ` <201305081638.23100.arnd-r2nGTMty4D4@public.gmane.org>
@ 2013-05-08 14:49 ` Will Deacon
2013-05-08 15:48 ` Stuart MENEFY
0 siblings, 1 reply; 79+ messages in thread
From: Will Deacon @ 2013-05-08 14:49 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Srinivas KANDAGATLA, Viresh Kumar, Jiri Slaby,
linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org, Samuel Ortiz,
Nicolas Pitre, linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Jason Cooper,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org,
rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org,
Stuart Menefy, Stephen Warren, Dong Aisheng,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
Greg Kroah-Hartman, Mark Brown,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
On Wed, May 08, 2013 at 03:38:22PM +0100, Arnd Bergmann wrote:
> On Wednesday 08 May 2013, Srinivas KANDAGATLA wrote:
> > From: Stuart Menefy <stuart.menefy-qxv4g6HH51o@public.gmane.org>
> >
> > This is a simple driver for the global timer module found in the Cortex
> > A9-MP cores from revision r1p0 onwards. This should be able to perform
> > the functions of the system timer and the local timer in an SMP system.
> >
> > The global timer has the following features:
> > The global timer is a 64-bit incrementing counter with an
> > auto-incrementing feature. It continues incrementing after sending
> > interrupts. The global timer is memory mapped in the private memory
> > region.
> > The global timer is accessible to all Cortex-A9 processors in the
> > cluster. Each Cortex-A9 processor has a private 64-bit comparator that
> > is used to assert a private interrupt when the global timer has reached
> > the comparator value. All the Cortex-A9 processors in a design use the
> > banked ID, ID27, for this interrupt. ID27 is sent to the Interrupt
> > Controller as a Private Peripheral Interrupt. The global timer is
> > clocked by PERIPHCLK.
> >
> > Signed-off-by: Stuart Menefy <stuart.menefy-qxv4g6HH51o@public.gmane.org>
> > Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
> >
>
> Are you sure we don't already have a driver for this? It sounds unlikely
> that you are the first one to do this when the hardware is so common.
An additional reason why people don't make use of this timer (on top of the
power domain concerns raised by Rob) is due to the following from the A9
TRM:
`From r2p0 the comparators for each processor with the global timer fire
when the timer value is greater than or equal to. In previous revisions
the comparators fired when the timer value was equal to.'
So you'll get into all sorts of horrible races on those older revisions if
you're not careful.
Will
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 2/8] ARM:global_timer: Add ARM global timer support.
2013-05-08 14:49 ` Will Deacon
@ 2013-05-08 15:48 ` Stuart MENEFY
[not found] ` <518A73CF.8000309-qxv4g6HH51o@public.gmane.org>
0 siblings, 1 reply; 79+ messages in thread
From: Stuart MENEFY @ 2013-05-08 15:48 UTC (permalink / raw)
To: Will Deacon
Cc: Dave Martin, Srinivas KANDAGATLA, Viresh Kumar, Linus Walleij,
Grant Likely, Jiri Slaby, linux@arm.linux.org.uk, Samuel Ortiz,
Nicolas Pitre, linux-doc@vger.kernel.org,
linux-serial@vger.kernel.org, Jason Cooper, Arnd Bergmann,
Marc Zyngier, devicetree-discuss@lists.ozlabs.org,
rob.herring@calxeda.com, Stephen Warren, Dong Aisheng,
linux-arm-kernel@lists.infradead.org, Greg
On 08/05/13 15:49, Will Deacon wrote:
> On Wed, May 08, 2013 at 03:38:22PM +0100, Arnd Bergmann wrote:
>> On Wednesday 08 May 2013, Srinivas KANDAGATLA wrote:
>>> From: Stuart Menefy <stuart.menefy@st.com>
>>>
>>> This is a simple driver for the global timer module found in the Cortex
>>> A9-MP cores from revision r1p0 onwards. This should be able to perform
>>> the functions of the system timer and the local timer in an SMP system.
>>>
>>> The global timer has the following features:
>>> The global timer is a 64-bit incrementing counter with an
>>> auto-incrementing feature. It continues incrementing after sending
>>> interrupts. The global timer is memory mapped in the private memory
>>> region.
>>> The global timer is accessible to all Cortex-A9 processors in the
>>> cluster. Each Cortex-A9 processor has a private 64-bit comparator that
>>> is used to assert a private interrupt when the global timer has reached
>>> the comparator value. All the Cortex-A9 processors in a design use the
>>> banked ID, ID27, for this interrupt. ID27 is sent to the Interrupt
>>> Controller as a Private Peripheral Interrupt. The global timer is
>>> clocked by PERIPHCLK.
>>>
>>> Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
>>> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>>>
>>
>> Are you sure we don't already have a driver for this? It sounds unlikely
>> that you are the first one to do this when the hardware is so common.
>
> An additional reason why people don't make use of this timer (on top of the
> power domain concerns raised by Rob) is due to the following from the A9
> TRM:
>
> `From r2p0 the comparators for each processor with the global timer fire
> when the timer value is greater than or equal to. In previous revisions
> the comparators fired when the timer value was equal to.'
>
> So you'll get into all sorts of horrible races on those older revisions if
> you're not careful.
Fortunately the earliest version of these SoCs uses r2p2, so we avoided that
particular issue. But as the code doesn't attempt to work around these
problems a check on the version number might be a good idea to prevent other
people accidentally hitting it.
Stuart
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 2/8] ARM:global_timer: Add ARM global timer support.
2013-05-08 14:38 ` Arnd Bergmann
[not found] ` <201305081638.23100.arnd-r2nGTMty4D4@public.gmane.org>
@ 2013-05-08 14:51 ` Steffen Trumtrar
2013-05-09 14:07 ` Srinivas KANDAGATLA
2 siblings, 0 replies; 79+ messages in thread
From: Steffen Trumtrar @ 2013-05-08 14:51 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Srinivas KANDAGATLA, linux-doc, Viresh Kumar, will.deacon,
Jiri Slaby, linux, Samuel Ortiz, Nicolas Pitre, linux-serial,
Jason Cooper, devicetree-discuss, Rob Herring, Stuart Menefy,
Stephen Warren, Dong Aisheng, linux-arm-kernel,
Greg Kroah-Hartman, Mark Brown, linux-kernel
On Wed, May 08, 2013 at 04:38:22PM +0200, Arnd Bergmann wrote:
> On Wednesday 08 May 2013, Srinivas KANDAGATLA wrote:
> > From: Stuart Menefy <stuart.menefy@st.com>
> >
> > This is a simple driver for the global timer module found in the Cortex
> > A9-MP cores from revision r1p0 onwards. This should be able to perform
> > the functions of the system timer and the local timer in an SMP system.
> >
> > The global timer has the following features:
> > The global timer is a 64-bit incrementing counter with an
> > auto-incrementing feature. It continues incrementing after sending
> > interrupts. The global timer is memory mapped in the private memory
> > region.
> > The global timer is accessible to all Cortex-A9 processors in the
> > cluster. Each Cortex-A9 processor has a private 64-bit comparator that
> > is used to assert a private interrupt when the global timer has reached
> > the comparator value. All the Cortex-A9 processors in a design use the
> > banked ID, ID27, for this interrupt. ID27 is sent to the Interrupt
> > Controller as a Private Peripheral Interrupt. The global timer is
> > clocked by PERIPHCLK.
> >
> > Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
> > Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
> >
>
> Are you sure we don't already have a driver for this? It sounds unlikely
> that you are the first one to do this when the hardware is so common.
>
Isn't this the same as arch/arm/kernel/smp_twd.c ?
That is atleast the timer I used with Cortex-A9. I don't think the core
has another one. But maybe I'm wrong.
> > Documentation/devicetree/bindings/arm/gt.txt | 21 ++
> > arch/arm/Kconfig | 6 +
> > arch/arm/include/asm/global_timer.h | 12 +
> > arch/arm/kernel/Makefile | 1 +
> > arch/arm/kernel/global_timer.c | 325 ++++++++++++++++++++++++++
> > 5 files changed, 365 insertions(+), 0 deletions(-)
> > create mode 100644 Documentation/devicetree/bindings/arm/gt.txt
> > create mode 100644 arch/arm/include/asm/global_timer.h
> > create mode 100644 arch/arm/kernel/global_timer.c
>
> Move it into drivers/clocksource?
>
> > diff --git a/arch/arm/include/asm/global_timer.h b/arch/arm/include/asm/global_timer.h
> > new file mode 100644
> > index 0000000..46f9188
> > --- /dev/null
> > +++ b/arch/arm/include/asm/global_timer.h
> > @@ -0,0 +1,12 @@
> > +int __init global_timer_init(void __iomem *base, unsigned int timer_irq);
>
> I don't see a need to call this from platform code for non-DT platforms, it
> can easily be used with CLOCKSOURCE_OF_DECLARE() all the time I think.
>
Regards,
Steffen
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 2/8] ARM:global_timer: Add ARM global timer support.
2013-05-08 14:38 ` Arnd Bergmann
[not found] ` <201305081638.23100.arnd-r2nGTMty4D4@public.gmane.org>
2013-05-08 14:51 ` Steffen Trumtrar
@ 2013-05-09 14:07 ` Srinivas KANDAGATLA
2013-05-09 14:51 ` Arnd Bergmann
2 siblings, 1 reply; 79+ messages in thread
From: Srinivas KANDAGATLA @ 2013-05-09 14:07 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Dave Martin, linux-doc, Viresh Kumar, Linus Walleij, will.deacon,
Grant Likely, Jiri Slaby, linux, Samuel Ortiz, Nicolas Pitre,
linux-serial, Jason Cooper, Marc Zyngier, devicetree-discuss,
Rob Herring, Stuart Menefy, Stephen Warren, Dong Aisheng,
linux-arm-kernel, Greg Kroah-Hartman, Mark Brown, linux-kernel,
Rob Landley, Olof Johansson
On 08/05/13 15:38, Arnd Bergmann wrote:
> On Wednesday 08 May 2013, Srinivas KANDAGATLA wrote:
>> From: Stuart Menefy <stuart.menefy@st.com>
>>
>> This is a simple driver for the global timer module found in the Cortex
>> A9-MP cores from revision r1p0 onwards. This should be able to perform
>> the functions of the system timer and the local timer in an SMP system.
>>
>> The global timer has the following features:
>> The global timer is a 64-bit incrementing counter with an
>> auto-incrementing feature. It continues incrementing after sending
>> interrupts. The global timer is memory mapped in the private memory
>> region.
>> The global timer is accessible to all Cortex-A9 processors in the
>> cluster. Each Cortex-A9 processor has a private 64-bit comparator that
>> is used to assert a private interrupt when the global timer has reached
>> the comparator value. All the Cortex-A9 processors in a design use the
>> banked ID, ID27, for this interrupt. ID27 is sent to the Interrupt
>> Controller as a Private Peripheral Interrupt. The global timer is
>> clocked by PERIPHCLK.
>>
>> Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
>> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>>
>
> Are you sure we don't already have a driver for this? It sounds unlikely
> that you are the first one to do this when the hardware is so common.
Yes, in mainline we do not have support to this.
>
>> Documentation/devicetree/bindings/arm/gt.txt | 21 ++
>> arch/arm/Kconfig | 6 +
>> arch/arm/include/asm/global_timer.h | 12 +
>> arch/arm/kernel/Makefile | 1 +
>> arch/arm/kernel/global_timer.c | 325 ++++++++++++++++++++++++++
>> 5 files changed, 365 insertions(+), 0 deletions(-)
>> create mode 100644 Documentation/devicetree/bindings/arm/gt.txt
>> create mode 100644 arch/arm/include/asm/global_timer.h
>> create mode 100644 arch/arm/kernel/global_timer.c
>
> Move it into drivers/clocksource?
Sure, I will move this in the next version.
>
>> diff --git a/arch/arm/include/asm/global_timer.h b/arch/arm/include/asm/global_timer.h
>> new file mode 100644
>> index 0000000..46f9188
>> --- /dev/null
>> +++ b/arch/arm/include/asm/global_timer.h
>> @@ -0,0 +1,12 @@
>> +int __init global_timer_init(void __iomem *base, unsigned int timer_irq);
>
> I don't see a need to call this from platform code for non-DT platforms, it
> can easily be used with CLOCKSOURCE_OF_DECLARE() all the time I think.
sorry Am confused here.
How would this work for non-DT?
Looking at the code in clocksource_of_init it just goes through the
of_device_id table, which is not used in case of non-DT.
>
> Arnd
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
>
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 2/8] ARM:global_timer: Add ARM global timer support.
2013-05-09 14:07 ` Srinivas KANDAGATLA
@ 2013-05-09 14:51 ` Arnd Bergmann
2013-05-09 14:51 ` Srinivas KANDAGATLA
0 siblings, 1 reply; 79+ messages in thread
From: Arnd Bergmann @ 2013-05-09 14:51 UTC (permalink / raw)
To: srinivas.kandagatla
Cc: Dave Martin, linux-doc, Viresh Kumar, Linus Walleij, will.deacon,
Grant Likely, Jiri Slaby, linux, Samuel Ortiz, Nicolas Pitre,
linux-serial, Jason Cooper, Marc Zyngier, devicetree-discuss,
Rob Herring, Stuart Menefy, Stephen Warren, Dong Aisheng,
linux-arm-kernel, Greg Kroah-Hartman, Mark Brown, linux-kernel,
Rob Landley, Olof Johansson
On Thursday 09 May 2013, Srinivas KANDAGATLA wrote:
> >> diff --git a/arch/arm/include/asm/global_timer.h b/arch/arm/include/asm/global_timer.h
> >> new file mode 100644
> >> index 0000000..46f9188
> >> --- /dev/null
> >> +++ b/arch/arm/include/asm/global_timer.h
> >> @@ -0,0 +1,12 @@
> >> +int __init global_timer_init(void __iomem *base, unsigned int timer_irq);
> >
> > I don't see a need to call this from platform code for non-DT platforms, it
> > can easily be used with CLOCKSOURCE_OF_DECLARE() all the time I think.
>
> sorry Am confused here.
> How would this work for non-DT?
It won't.
> Looking at the code in clocksource_of_init it just goes through the
> of_device_id table, which is not used in case of non-DT.
All new platforms are DT-only, and none of the old platforms use this
driver, so it does not matter.
Arnd
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 2/8] ARM:global_timer: Add ARM global timer support.
2013-05-09 14:51 ` Arnd Bergmann
@ 2013-05-09 14:51 ` Srinivas KANDAGATLA
0 siblings, 0 replies; 79+ messages in thread
From: Srinivas KANDAGATLA @ 2013-05-09 14:51 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Dave Martin, linux-doc, Viresh Kumar, Linus Walleij, will.deacon,
Grant Likely, Jiri Slaby, linux, Samuel Ortiz, Nicolas Pitre,
linux-serial, Jason Cooper, Marc Zyngier, devicetree-discuss,
Rob Herring, Stuart Menefy, Stephen Warren, Dong Aisheng,
linux-arm-kernel, Greg Kroah-Hartman, Mark Brown, linux-kernel,
Rob Landley, Olof Johansson
On 09/05/13 15:51, Arnd Bergmann wrote:
> It won't.
>
>> > Looking at the code in clocksource_of_init it just goes through the
>> > of_device_id table, which is not used in case of non-DT.
> All new platforms are DT-only, and none of the old platforms use this
> driver, so it does not matter.
>
It makes sense, I will remove the header file.
> Arnd
>
^ permalink raw reply [flat|nested] 79+ messages in thread
[parent not found: <1368022260-2197-1-git-send-email-srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>]
* Re: [RFC 2/8] ARM:global_timer: Add ARM global timer support.
[not found] ` <1368022260-2197-1-git-send-email-srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
@ 2013-05-13 19:05 ` Linus Walleij
[not found] ` <CACRpkdZCP=w=4Q3bnuMQxm=Oe-uZke+Cc5NgddM5vsQbgr9E-Q-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
0 siblings, 1 reply; 79+ messages in thread
From: Linus Walleij @ 2013-05-13 19:05 UTC (permalink / raw)
To: Srinivas KANDAGATLA, John Stultz, Thomas Gleixner
Cc: linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Viresh Kumar,
Will Deacon, Jiri Slaby, Russell King - ARM Linux, Samuel Ortiz,
Nicolas Pitre,
linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Jason Cooper,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org,
Rob Herring, Stuart Menefy, Stephen Warren, Dong Aisheng,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
Greg Kroah-Hartman, Mark Brown,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
On Wed, May 8, 2013 at 4:11 PM, Srinivas KANDAGATLA
<srinivas.kandagatla-qxv4g6HH51o@public.gmane.org> wrote:
Thomas Gleixner and John Stultz should always be included on timer code review.
This is one reason I really like to move the clocksource/clockevent/etc code out
of arch/arm, so that people can get their To: line right from MAINTAINERS.
(Whether it goes to drivers/clocksource or not is another issue.)
> diff --git a/arch/arm/include/asm/global_timer.h b/arch/arm/include/asm/global_timer.h
Using CLKSRC_OF_INIT() this header goes away entirely I guess.
> diff --git a/arch/arm/kernel/global_timer.c b/arch/arm/kernel/global_timer.c
> +#define GT_COUNTER0 0x00
> +#define GT_COUNTER1 0x04
So two counters, nice.
> +union gt_counter {
> + cycle_t cycles;
> + struct {
> + uint32_t lower;
> + uint32_t upper;
Just u32 is fine.
> + };
> +};
> +
> +static union gt_counter gt_counter_read(void)
> +{
> + union gt_counter res;
> + uint32_t upper;
u32
> +
> + upper = readl(gt_base + GT_COUNTER1);
> + do {
> + res.upper = upper;
> + res.lower = readl(gt_base + GT_COUNTER0);
> + upper = readl(gt_base + GT_COUNTER1);
> + } while (upper != res.upper);
> +
> + return res;
> +}
I guess this is some cleverness to avoid wrap-around...
A comment stating what's going on wouldn't hurt.
But why on earth do you need this complicated union
to hold the result? Have two local u32 variables and return
a u64 from this function.
Since this will be performance critical, isn't readl_relaxed() suffient
here, or what's the rationale for just using readl()?
> +static void gt_compare_set(unsigned long delta, int periodic)
> +{
> + union gt_counter counter = gt_counter_read();
So here you get something easy to read like
u64 counter = gt_counter_read();
> + unsigned long ctrl = readl(gt_base + GT_CONTROL);
> +
> + BUG_ON(!(ctrl & GT_CONTROL_TIMER_ENABLE));
> + BUG_ON(ctrl & (GT_CONTROL_COMP_ENABLE |
> + GT_CONTROL_IRQ_ENABLE |
> + GT_CONTROL_AUTO_INC));
Do you really have to check this *whenever the counter is set*?
Will it not suffice to do this once during initialization?
It looks like some leftover debug code. It also looks kind of clock
dangerous, can you explain exactly why this check is here?
> +
> + counter.cycles += delta;
> + writel(counter.lower, gt_base + GT_COMP0);
> + writel(counter.upper, gt_base + GT_COMP1);
This is another instance of the union struct making things
complicated. With a u64 just:
counter += delta;
writel(lower_32_bits(counter), gt_base + GT_COMP0);
writel(upper_32_bits(counter), gt_base + GT_COMP1);
As you can see <linux/kernel.h> has really nice helpers in place
to deal with 64 bit arithmetics.
> +
> + ctrl |= GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE;
> +
> + if (periodic) {
> + writel(delta, gt_base + GT_AUTO_INC);
> + ctrl |= GT_CONTROL_AUTO_INC;
> + }
> +
> + writel(ctrl, gt_base + GT_CONTROL);
> +}
> +
> +static void gt_clockevent_set_mode(enum clock_event_mode mode,
> + struct clock_event_device *clk)
> +{
> + switch (mode) {
> + case CLOCK_EVT_MODE_PERIODIC:
> + gt_compare_set(gt_clk_rate/HZ, 1);
Use
gt_compare_set(DIV_ROUND_CLOSEST(gt_clk_rate, HZ), 1);
to get integer arithmetics right.
> + break;
> + case CLOCK_EVT_MODE_ONESHOT:
> + /* period set, and timer enabled in 'next_event' hook */
> + BUG_ON(readl(gt_base + GT_CONTROL) &
> + (GT_CONTROL_COMP_ENABLE |
> + GT_CONTROL_IRQ_ENABLE |
> + GT_CONTROL_AUTO_INC));
Here is another one of these checks. Why aren't you just
zeroing these flags if you don't want them, especially since
you're writing the register at the end of the function? Now it
looks like instead of setting up the timer the way you want it
you bug out if it isn't already set up as you want it (hint,
the name of this function).
> + /* Fall through */
> + case CLOCK_EVT_MODE_UNUSED:
> + case CLOCK_EVT_MODE_SHUTDOWN:
> + default:
> + writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
Why are you enabling the timer in unused and shutdown mode?
This doesn't make sense.
> + break;
> + }
> +}
> +
> +static int gt_clockevent_set_next_event(unsigned long evt,
> + struct clock_event_device *unused)
> +{
> + gt_compare_set(evt, 0);
> + return 0;
> +}
> +
> +static irqreturn_t gt_clockevent_interrupt(int irq, void *dev_id)
> +{
> + struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
> +
> + writel(GT_INT_STATUS_EVENT_FLAG, gt_base + GT_INT_STATUS);
You're clearing the flag before checking if it was set. What happens
if this was a spurious interrupt that should be disregarded?
> + evt->event_handler(evt);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int __cpuinit gt_clockevents_init(struct clock_event_device *clk)
> +{
> + struct clock_event_device **this_cpu_clk;
> + int cpu = smp_processor_id();
> +
> + clk->name = "Global Timer CE";
Name it after the hardware feature. "ARM global timer clock event"
there is no need to abbreviate randomly.
> + clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
> + clk->set_mode = gt_clockevent_set_mode;
> + clk->set_next_event = gt_clockevent_set_next_event;
> + this_cpu_clk = __this_cpu_ptr(gt_evt);
> + *this_cpu_clk = clk;
> + clk->irq = gt_ppi;
> + clockevents_config_and_register(clk, gt_clk_rate,
> + 0xf, 0xffffffff);
Why can't this clock event handle anything lower than 0xf?
Does that come from the datasheet or have you just copied some
code?
Further, since this clock event hardware *most definately* supports
using a delta upper bound *beyond* 32 bits, I think the clock event
core code should be altered to allow for registereing such clock
events, but TGLX may have some idea here. This will work but will
not expose the full potential of this 64-bit counter hardware.
> + per_cpu(percpu_init_called, cpu) = true;
> + enable_percpu_irq(clk->irq, IRQ_TYPE_NONE);
> + return 0;
> +}
> +
> +static void gt_clockevents_stop(struct clock_event_device *clk)
> +{
> + gt_clockevent_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
> + disable_percpu_irq(clk->irq);
> +}
> +
> +static int __cpuinit gt_clockevents_setup(struct clock_event_device *clk)
> +{
> + int cpu = smp_processor_id();
> +
> + /* Use existing clock_event for boot cpu */
> + if (per_cpu(percpu_init_called, cpu))
> + return 0;
> +
> + writel(0, gt_base + GT_CONTROL);
> + writel(0, gt_base + GT_COUNTER0);
> + writel(0, gt_base + GT_COUNTER1);
> + writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
> +
> + return gt_clockevents_init(clk);
> +}
> +
> +static cycle_t gt_clocksource_read(struct clocksource *cs)
> +{
> + union gt_counter res = gt_counter_read();
> + return res.cycles;
> +}
> +
> +static struct clocksource gt_clocksource = {
> + .name = "Global Timer CS",
"ARM global timer clock source"
> + .rating = 300,
> + .read = gt_clocksource_read,
> + .mask = CLOCKSOURCE_MASK(64),
> + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
> +};
> +
> +static void __init gt_clocksource_init(void)
> +{
> + writel(0, gt_base + GT_CONTROL);
> + writel(0, gt_base + GT_COUNTER0);
> + writel(0, gt_base + GT_COUNTER1);
> + writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
> +
> + gt_clocksource.shift = 20;
So how did you come up with that?
> + gt_clocksource.mult =
> + clocksource_hz2mult(gt_clk_rate, gt_clocksource.shift);
> + clocksource_register(>_clocksource);
Why don't you just replace all of this hazzle with:
clocksource_register_hz(>_clocksource, gt_clk_rate);
That will calculate mult and shift for you? (Leave these
unassigned.)
Since the hpet timer does this it's pretty well tested...
No more comments right now...
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 79+ messages in thread
* [RFC 3/8] mfd:syscon: Introduce claim/read/write/release APIs
2013-05-08 14:09 [RFC 0/8] ARM:STiH41x: Add STiH41x platform and board support Srinivas KANDAGATLA
2013-05-08 14:11 ` [RFC 2/8] ARM:global_timer: Add ARM global timer support Srinivas KANDAGATLA
@ 2013-05-08 14:11 ` Srinivas KANDAGATLA
2013-05-08 14:50 ` Arnd Bergmann
2013-05-08 14:11 ` =?y?q?=5BRFC=205/8=5D=20ARM=3Astih41x=3A=20Add=20STiH415=20SOC=20support?= Srinivas KANDAGATLA
` (3 subsequent siblings)
5 siblings, 1 reply; 79+ messages in thread
From: Srinivas KANDAGATLA @ 2013-05-08 14:11 UTC (permalink / raw)
To: dong.aisheng, sameo
Cc: Rob Landley, Grant Likely, Rob Herring, Russell King,
Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Srinivas Kandagatla, Stuart Menefy, Shawn Guo, Olof Johansson,
Jason Cooper, Stephen Warren, Maxime Ripard, Nicolas Pitre,
Will Deacon, Dave Martin, Marc Zyngier, Viresh Kumar,
Arnd Bergmann, Mark Brown, linux-doc, linux-kernel, dev
From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
This patch introduces syscon_claim, syscon_read, syscon_write,
syscon_release APIs to help drivers to use syscon registers in much more
flexible way.
With this patch, a driver can claim few/all bits in the syscon registers
and do read/write and then release them when its totally finished with
them, in the mean time if another driver requests same bits or registers
the API will detect conflit and return error to the second request.
Reason to introduce this API.
System configuration/control registers are very basic configuration
registers arranged in groups across ST Settop Box parts. These registers
are independent of IP itself. Many IPs, clock, pad and other functions
are wired up to these registers.
In many cases a single syconf register contains bits related to multiple
devices, and therefore it need to be shared across multiple drivers at
bit level. The same IP block can have different syscon mappings on
different SOCs.
Typically in a SOC there will be more than hundreds of these registers,
which are again divided into groups.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
CC: Stuart Menefy <stuart.menefy@st.com>
---
drivers/mfd/syscon.c | 199 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/mfd/syscon.h | 43 ++++++++++
2 files changed, 242 insertions(+), 0 deletions(-)
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 61aea63..fab85da 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -16,6 +16,7 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/slab.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
@@ -28,8 +29,23 @@ struct syscon {
struct device *dev;
void __iomem *base;
struct regmap *regmap;
+ struct device_node *of_node;
+ struct list_head list;
+ struct list_head fields;
+ spinlock_t fields_lock;
};
+struct syscon_field {
+ struct syscon *syscon;
+ u16 num;
+ u8 lsb, msb;
+ unsigned int offset;
+ const char *owner;
+ struct list_head list;
+};
+
+static LIST_HEAD(syscons);
+
static int syscon_match(struct device *dev, void *data)
{
struct syscon *syscon = dev_get_drvdata(dev);
@@ -87,6 +103,185 @@ struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
}
EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle);
+static int syscon_add_field(struct syscon_field *field)
+{
+ struct syscon_field *entry;
+ enum {
+ status_not_found,
+ status_found_register,
+ status_add_field_here,
+ } status = status_not_found;
+ int bit_avail = 0;
+ struct syscon *syscon = field->syscon;
+ int rval = 0;
+ int num = field->num;
+ int lsb = field->lsb;
+ int msb = field->msb;
+
+ spin_lock(&syscon->fields_lock);
+ /*
+ * The list is always in syscon->num->lsb/msb order, so it's easy to
+ * find a place to insert a new field (and to detect conflicts)
+ */
+ list_for_each_entry(entry, &syscon->fields, list) {
+ if (entry->num == num) {
+ status = status_found_register;
+ /*
+ * Someone already claimed a field from this
+ * register - let's try to find some space for
+ * requested bits...
+ */
+ if (bit_avail <= lsb && msb < entry->lsb) {
+ status = status_add_field_here;
+ break;
+ }
+ bit_avail = entry->msb + 1;
+ } else if (entry->num > num) {
+ /*
+ * There is no point of looking further -
+ * the num values are bigger then
+ * the ones we are looking for
+ */
+ if ((status == status_found_register &&
+ bit_avail <= lsb) ||
+ status == status_not_found)
+ /*
+ * A remainder of the given register is not
+ * used or the register wasn't used at all
+ */
+ status = status_add_field_here;
+ else
+ /*
+ * Apparently some bits of the claimed field
+ * are already in use...
+ */
+ rval = -EBUSY;
+ break;
+ }
+ }
+
+ if ((status == status_not_found) || (status == status_found_register))
+ list_add_tail(&field->list, &syscon->fields);
+ else if (status == status_add_field_here)
+ list_add(&field->list, entry->list.prev);
+
+ spin_unlock(&syscon->fields_lock);
+ return rval;
+}
+
+static struct syscon *find_syscon(struct device_node *np)
+{
+ struct syscon *syscon;
+
+ list_for_each_entry(syscon, &syscons, list) {
+ if (syscon->of_node == np)
+ return syscon;
+ }
+ return NULL;
+}
+
+#define MIN_SYSCON_CELLS (4)
+
+struct syscon_field *syscon_claim(struct device_node *np,
+ const char *prop)
+{
+ const __be32 *list;
+ const struct property *pp;
+ struct syscon_field *field;
+ phandle phandle;
+ struct device_node *syscon_np;
+ u32 syscon_num;
+
+ pp = of_find_property(np, prop, NULL);
+ if (!pp)
+ return NULL;
+
+ if (pp->length < ((MIN_SYSCON_CELLS) * sizeof(*list)))
+ return NULL;
+
+ list = pp->value;
+
+ /* syscon */
+ phandle = be32_to_cpup(list++);
+ syscon_np = of_find_node_by_phandle(phandle);
+ if (!syscon_np) {
+ pr_warn("No syscon found for %s syscon\n", prop);
+ return NULL;
+ }
+
+ field = kzalloc(sizeof(struct syscon_field), GFP_KERNEL);
+ if (!field)
+ return NULL;
+
+ field->syscon = find_syscon(syscon_np);
+ if (!field->syscon) {
+ pr_warn("No syscon registered for %s syscon\n", prop);
+ goto error;
+ }
+
+ of_node_put(syscon_np);
+ syscon_num = be32_to_cpup(list++);
+ field->offset = (syscon_num) * 4;
+ field->lsb = be32_to_cpup(list++);
+ field->msb = be32_to_cpup(list++);
+ field->num = syscon_num;
+ field->owner = pp->name;
+
+ if (syscon_add_field(field))
+ goto error;
+
+ return field;
+error:
+ kfree(field);
+ return NULL;
+}
+EXPORT_SYMBOL(syscon_claim);
+
+void syscon_release(struct syscon_field *field)
+{
+ struct syscon *syscon;
+ if (field) {
+ syscon = field->syscon;
+ spin_lock(&syscon->fields_lock);
+ list_del(&field->list);
+ spin_unlock(&syscon->fields_lock);
+ kfree(field);
+ }
+}
+EXPORT_SYMBOL(syscon_release);
+
+void syscon_write(struct syscon_field *field, unsigned long value)
+{
+ int field_bits;
+ struct syscon *syscon = field->syscon;
+
+ field_bits = field->msb - field->lsb + 1;
+ if (field_bits == 32) {
+ regmap_write(syscon->regmap, field->offset, value);
+ } else {
+ u32 reg_mask;
+ reg_mask = (((1 << field_bits) - 1) << field->lsb);
+ regmap_update_bits(syscon->regmap, field->offset,
+ reg_mask, value << field->lsb);
+ }
+}
+EXPORT_SYMBOL(syscon_write);
+
+unsigned long syscon_read(struct syscon_field *field)
+{
+ int field_bits;
+ u32 result;
+ struct syscon *syscon = field->syscon;
+
+ regmap_read(syscon->regmap, field->offset, &result);
+ field_bits = field->msb - field->lsb + 1;
+ result >>= field->lsb;
+ result &= (1 << field_bits) - 1;
+
+ return result;
+}
+EXPORT_SYMBOL(syscon_read);
+
static const struct of_device_id of_syscon_match[] = {
{ .compatible = "syscon", },
{ },
@@ -122,6 +317,10 @@ static int syscon_probe(struct platform_device *pdev)
if (ret)
return ret;
+ list_add_tail(&syscon->list, &syscons);
+ INIT_LIST_HEAD(&syscon->fields);
+ syscon->of_node = np;
+
syscon_regmap_config.max_register = res.end - res.start - 3;
syscon->regmap = devm_regmap_init_mmio(dev, syscon->base,
&syscon_regmap_config);
diff --git a/include/linux/mfd/syscon.h b/include/linux/mfd/syscon.h
index 6aeb6b8..0de0da5 100644
--- a/include/linux/mfd/syscon.h
+++ b/include/linux/mfd/syscon.h
@@ -15,9 +15,52 @@
#ifndef __LINUX_MFD_SYSCON_H__
#define __LINUX_MFD_SYSCON_H__
+struct syscon_field;
+
extern struct regmap *syscon_node_to_regmap(struct device_node *np);
extern struct regmap *syscon_regmap_lookup_by_compatible(const char *s);
extern struct regmap *syscon_regmap_lookup_by_phandle(
struct device_node *np,
const char *property);
+
+/**
+ * syscon_claim - Claim ownership of a field of a syscon register
+ * @np: parent node pointer.
+ * @prop: name of sysconf to claim.
+ *
+ * This function claims ownership of a field from a syscon register.
+ * It returns a &struct syscon_field which can be used in subsequent
+ * operations on this field.
+ */
+struct syscon_field *syscon_claim(struct device_node *np,
+ const char *prop);
+
+/**
+ * syscon_release - Release ownership of a field of a syscon register
+ * @field: the syscon field to write to
+ *
+ * Release ownership of a field from a syscon register.
+ * @field must have been claimed using syscon_claim().
+ */
+void syscon_release(struct syscon_field *field);
+
+/**
+ * syscon_write - Write a value into a field of a syscon register
+ * @field: the syscon field to write to
+ * @value: the value to write into the field
+ *
+ * This writes @value into the field of the syscon register @field.
+ * @field must have been claimed using syscon_claim().
+ */
+void syscon_write(struct syscon_field *field, unsigned long value);
+
+/**
+ * syscon_read - Read a field of a syscon register
+ * @field: the syscon field to read
+ *
+ * This reads a field of the syscon register @field.
+ * @field must have been claimed using syscon_claim().
+ */
+unsigned long syscon_read(struct syscon_field *field);
+
#endif /* __LINUX_MFD_SYSCON_H__ */
--
1.7.6.5
^ permalink raw reply related [flat|nested] 79+ messages in thread
* Re: [RFC 3/8] mfd:syscon: Introduce claim/read/write/release APIs
2013-05-08 14:11 ` [RFC 3/8] mfd:syscon: Introduce claim/read/write/release APIs Srinivas KANDAGATLA
@ 2013-05-08 14:50 ` Arnd Bergmann
2013-05-08 15:01 ` Mark Brown
` (2 more replies)
0 siblings, 3 replies; 79+ messages in thread
From: Arnd Bergmann @ 2013-05-08 14:50 UTC (permalink / raw)
To: Srinivas KANDAGATLA
Cc: dong.aisheng, sameo, Rob Landley, Grant Likely, Rob Herring,
Russell King, Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Stuart Menefy, Shawn Guo, Olof Johansson, Jason Cooper,
Stephen Warren, Maxime Ripard, Nicolas Pitre, Will Deacon,
Dave Martin, Marc Zyngier, Viresh Kumar, Mark Brown, linux-doc,
linux-kernel, devicetree-discuss
On Wednesday 08 May 2013, Srinivas KANDAGATLA wrote:
> From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>
> This patch introduces syscon_claim, syscon_read, syscon_write,
> syscon_release APIs to help drivers to use syscon registers in much more
> flexible way.
>
> With this patch, a driver can claim few/all bits in the syscon registers
> and do read/write and then release them when its totally finished with
> them, in the mean time if another driver requests same bits or registers
> the API will detect conflit and return error to the second request.
>
> Reason to introduce this API.
> System configuration/control registers are very basic configuration
> registers arranged in groups across ST Settop Box parts. These registers
> are independent of IP itself. Many IPs, clock, pad and other functions
> are wired up to these registers.
>
> In many cases a single syconf register contains bits related to multiple
> devices, and therefore it need to be shared across multiple drivers at
> bit level. The same IP block can have different syscon mappings on
> different SOCs.
>
> Typically in a SOC there will be more than hundreds of these registers,
> which are again divided into groups.
>
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
> CC: Stuart Menefy <stuart.menefy@st.com>
My feeling is that syscon is the wrong place for this functionality,
since regmap already handles (some of?) these issues. If you need
additional synchronization, it's probably best to extend regmap
as needed so other code besides syscon can take advantage of that
as well.
Arnd
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 3/8] mfd:syscon: Introduce claim/read/write/release APIs
2013-05-08 14:50 ` Arnd Bergmann
@ 2013-05-08 15:01 ` Mark Brown
2013-05-08 17:42 ` Srinivas KANDAGATLA
2013-05-08 17:32 ` Srinivas KANDAGATLA
[not found] ` <201305081650.23264.arnd-r2nGTMty4D4@public.gmane.org>
2 siblings, 1 reply; 79+ messages in thread
From: Mark Brown @ 2013-05-08 15:01 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Srinivas KANDAGATLA, dong.aisheng, sameo, Rob Landley,
Grant Likely, Rob Herring, Russell King, Linus Walleij,
Greg Kroah-Hartman, Jiri Slaby, Stuart Menefy, Shawn Guo,
Olof Johansson, Jason Cooper, Stephen Warren, Maxime Ripard,
Nicolas Pitre, Will Deacon, Dave Martin, Marc Zyngier,
Viresh Kumar, linux-doc, linux-kernel, devicetree-discuss
[-- Attachment #1: Type: text/plain, Size: 662 bytes --]
On Wed, May 08, 2013 at 04:50:22PM +0200, Arnd Bergmann wrote:
> > In many cases a single syconf register contains bits related to multiple
> > devices, and therefore it need to be shared across multiple drivers at
> > bit level. The same IP block can have different syscon mappings on
> > different SOCs.
> My feeling is that syscon is the wrong place for this functionality,
> since regmap already handles (some of?) these issues. If you need
> additional synchronization, it's probably best to extend regmap
> as needed so other code besides syscon can take advantage of that
> as well.
This sounds like regmap_update_bits() ought to be all that's needed.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 3/8] mfd:syscon: Introduce claim/read/write/release APIs
2013-05-08 15:01 ` Mark Brown
@ 2013-05-08 17:42 ` Srinivas KANDAGATLA
[not found] ` <518A8E6C.6070907-qxv4g6HH51o@public.gmane.org>
0 siblings, 1 reply; 79+ messages in thread
From: Srinivas KANDAGATLA @ 2013-05-08 17:42 UTC (permalink / raw)
To: Mark Brown
Cc: Arnd Bergmann, dong.aisheng, sameo, Rob Landley, Grant Likely,
Rob Herring, Russell King, Linus Walleij, Greg Kroah-Hartman,
Jiri Slaby, Stuart Menefy, Shawn Guo, Olof Johansson,
Jason Cooper, Stephen Warren, Maxime Ripard, Nicolas Pitre,
Will Deacon, Dave Martin, Marc Zyngier, Viresh Kumar, linux-doc,
linux-kernel, devicetree-discuss, linux-arm-kernel
Thankyou for the comments.
On 08/05/13 16:01, Mark Brown wrote:
> On Wed, May 08, 2013 at 04:50:22PM +0200, Arnd Bergmann wrote:
>
>>> In many cases a single syconf register contains bits related to multiple
>>> devices, and therefore it need to be shared across multiple drivers at
>>> bit level. The same IP block can have different syscon mappings on
>>> different SOCs.
>> My feeling is that syscon is the wrong place for this functionality,
>> since regmap already handles (some of?) these issues. If you need
>> additional synchronization, it's probably best to extend regmap
>> as needed so other code besides syscon can take advantage of that
>> as well.
> This sounds like regmap_update_bits() ought to be all that's needed.
Ultimately the syscon_write use the regmap_update_bits, however we really want is the flexibility in using/referring the syscon registers/bits in both device-trees and non-device tree cases.
The reason for these APIs, is the extent of syscon usage is very high in ST set-top-box parts.
Without these new APIs, its very difficult to pass this information to
the drivers.
Thanks,
srini
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 3/8] mfd:syscon: Introduce claim/read/write/release APIs
2013-05-08 14:50 ` Arnd Bergmann
2013-05-08 15:01 ` Mark Brown
@ 2013-05-08 17:32 ` Srinivas KANDAGATLA
[not found] ` <518A8C1D.3090600-qxv4g6HH51o@public.gmane.org>
[not found] ` <201305081650.23264.arnd-r2nGTMty4D4@public.gmane.org>
2 siblings, 1 reply; 79+ messages in thread
From: Srinivas KANDAGATLA @ 2013-05-08 17:32 UTC (permalink / raw)
To: Arnd Bergmann
Cc: dong.aisheng, sameo, Rob Landley, Grant Likely, Rob Herring,
Russell King, Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Stuart Menefy, Shawn Guo, Olof Johansson, Jason Cooper,
Stephen Warren, Maxime Ripard, Nicolas Pitre, Will Deacon,
Dave Martin, Marc Zyngier, Viresh Kumar, Mark Brown, linux-doc,
linux-kernel, devicetree-discuss
Thankyou for your comments.
On 08/05/13 15:50, Arnd Bergmann wrote:
> On Wednesday 08 May 2013, Srinivas KANDAGATLA wrote:
>> From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>>
>> This patch introduces syscon_claim, syscon_read, syscon_write,
>> syscon_release APIs to help drivers to use syscon registers in much more
>> flexible way.
>>
>> With this patch, a driver can claim few/all bits in the syscon registers
>> and do read/write and then release them when its totally finished with
>> them, in the mean time if another driver requests same bits or registers
>> the API will detect conflit and return error to the second request.
>>
>> Reason to introduce this API.
>> System configuration/control registers are very basic configuration
>> registers arranged in groups across ST Settop Box parts. These registers
>> are independent of IP itself. Many IPs, clock, pad and other functions
>> are wired up to these registers.
>>
>> In many cases a single syconf register contains bits related to multiple
>> devices, and therefore it need to be shared across multiple drivers at
>> bit level. The same IP block can have different syscon mappings on
>> different SOCs.
>>
>> Typically in a SOC there will be more than hundreds of these registers,
>> which are again divided into groups.
>>
>> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>> CC: Stuart Menefy <stuart.menefy@st.com>
> My feeling is that syscon is the wrong place for this functionality,
> since regmap already handles (some of?) these issues. If you need
> additional synchronization, it's probably best to extend regmap
> as needed so other code besides syscon can take advantage of that
> as well.
Its not just synchronisation that we are looking for.
It also the usability, drivers want to just refer to a syscon
register/bits of it from device trees/non-devicetrees.
The extent of syscon usage is very high in ST set-top-box parts.
As example, ST pinctrl driver uses use bits of the syscon register to
control alternate functions, and many other parameters of pinconf.
In device tree we do something like:
syscfg_sbc: syscon@fe600000{
compatible = "syscon";
reg = <0xfe600000 0xb4>;
};
and in pinctrl dts file
st,alt-control = <&syscfg_sbc 0 0 31>;
st,od-control = <&syscfg_sbc 9 0 7>;
the pinctrl driver calls syconf_claim(np, "st,alt-control) to get a
field and then do a read/write on the field.
Just in pinctrl driver we use around 50-100 sysconf registers scatters
across different groups.
Without these new APIs, its very difficult to pass this information to
the drivers.
Thanks,
srini
>
> Arnd
>
^ permalink raw reply [flat|nested] 79+ messages in thread
[parent not found: <201305081650.23264.arnd-r2nGTMty4D4@public.gmane.org>]
* Re[2]: [RFC 3/8] mfd:syscon: Introduce claim/read/write/release APIs
[not found] ` <201305081650.23264.arnd-r2nGTMty4D4@public.gmane.org>
@ 2013-05-08 19:41 ` Alexander Shiyan
0 siblings, 0 replies; 79+ messages in thread
From: Alexander Shiyan @ 2013-05-08 19:41 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-doc-u79uwXL29TY76Z2rM5mHXA, Viresh Kumar, Will Deacon,
Jiri Slaby, Russell King, sameo-VuQAYsv1563Yd54FQh9/CA,
Nicolas Pitre, Srinivas KANDAGATLA,
linux-serial-u79uwXL29TY76Z2rM5mHXA, Jason Cooper,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring,
Stuart Menefy, Stephen Warren,
dong.aisheng-QSEj5FYQhm4dnm+yROfE0A,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Greg Kroah-Hartman, Mark Brown
> On Wednesday 08 May 2013, Srinivas KANDAGATLA wrote:
> > From: Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
> >
> > This patch introduces syscon_claim, syscon_read, syscon_write,
> > syscon_release APIs to help drivers to use syscon registers in much more
> > flexible way.
> >
> > With this patch, a driver can claim few/all bits in the syscon registers
> > and do read/write and then release them when its totally finished with
> > them, in the mean time if another driver requests same bits or registers
> > the API will detect conflit and return error to the second request.
> >
> > Reason to introduce this API.
> > System configuration/control registers are very basic configuration
> > registers arranged in groups across ST Settop Box parts. These registers
> > are independent of IP itself. Many IPs, clock, pad and other functions
> > are wired up to these registers.
> >
> > In many cases a single syconf register contains bits related to multiple
> > devices, and therefore it need to be shared across multiple drivers at
> > bit level. The same IP block can have different syscon mappings on
> > different SOCs.
> >
> > Typically in a SOC there will be more than hundreds of these registers,
> > which are again divided into groups.
> >
> > Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
> > CC: Stuart Menefy <stuart.menefy-qxv4g6HH51o@public.gmane.org>
>
> My feeling is that syscon is the wrong place for this functionality,
> since regmap already handles (some of?) these issues. If you need
> additional synchronization, it's probably best to extend regmap
> as needed so other code besides syscon can take advantage of that
> as well.
+1
---
^ permalink raw reply [flat|nested] 79+ messages in thread
* =?y?q?=5BRFC=205/8=5D=20ARM=3Astih41x=3A=20Add=20STiH415=20SOC=20support?=
2013-05-08 14:09 [RFC 0/8] ARM:STiH41x: Add STiH41x platform and board support Srinivas KANDAGATLA
2013-05-08 14:11 ` [RFC 2/8] ARM:global_timer: Add ARM global timer support Srinivas KANDAGATLA
2013-05-08 14:11 ` [RFC 3/8] mfd:syscon: Introduce claim/read/write/release APIs Srinivas KANDAGATLA
@ 2013-05-08 14:11 ` Srinivas KANDAGATLA
2013-05-08 16:18 ` [RFC 5/8] ARM:stih41x: Add STiH415 SOC support Arnd Bergmann
2013-05-08 14:11 ` [RFC 6/8] ARM:stih41x: Add STiH416 " Srinivas KANDAGATLA
` (2 subsequent siblings)
5 siblings, 1 reply; 79+ messages in thread
From: Srinivas KANDAGATLA @ 2013-05-08 14:11 UTC (permalink / raw)
To: linux, arnd, olof
Cc: Rob Landley, Grant Likely, Rob Herring, Samuel Ortiz,
Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Srinivas Kandagatla, Stuart Menefy, Shawn Guo, Jason Cooper,
Stephen Warren, Maxime Ripard, Nicolas Pitre, Will Deacon,
Dave Martin, Marc Zyngier, Viresh Kumar, Mark Brown, Dong Aisheng,
linux-doc, linux-kernel, devicetree-discuss
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 51630 bytes --]
From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
The STiH415 is the next generation of HD, AVC set-top box processors for
satellite, cable, terrestrial and IP-STB markets. It is an ARM Cortex-A9
1.0 GHz, dual-core CPU.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
CC: Stephen Gallimore <stephen.gallimore@st.com>
CC: Stuart Menefy <stuart.menefy@st.com>
---
Documentation/arm/STiH41x/overview.txt | 39 ++
Documentation/arm/STiH41x/stih415-overview.txt | 12 +
arch/arm/Kconfig | 3 +
arch/arm/Kconfig.debug | 38 ++
arch/arm/Makefile | 2 +
arch/arm/boot/dts/stih415-clock.dtsi | 38 ++
arch/arm/boot/dts/stih415-pinctrl.dtsi | 480 ++++++++++++++++++++++++
arch/arm/boot/dts/stih415.dtsi | 94 +++++
arch/arm/boot/dts/stih415.h | 20 +
arch/arm/boot/dts/stih41x.dtsi | 30 ++
arch/arm/boot/dts/stixxxx-pincfg.h | 95 +++++
arch/arm/configs/stih41x_defconfig | 94 +++++
arch/arm/include/debug/stixxxx.S | 61 +++
arch/arm/mach-stih41x/Kconfig | 35 ++
arch/arm/mach-stih41x/Makefile | 4 +
arch/arm/mach-stih41x/board-dt.c | 76 ++++
arch/arm/mach-stih41x/stih41x.c | 82 ++++
arch/arm/mach-stih41x/stih41x.h | 7 +
arch/arm/plat-stixxxx/Kconfig | 2 +
arch/arm/plat-stixxxx/Makefile | 2 +
arch/arm/plat-stixxxx/headsmp.S | 44 +++
arch/arm/plat-stixxxx/include/plat/hardware.h | 20 +
arch/arm/plat-stixxxx/include/plat/smp.h | 19 +
arch/arm/plat-stixxxx/platsmp.c | 144 +++++++
24 files changed, 1441 insertions(+), 0 deletions(-)
create mode 100644 Documentation/arm/STiH41x/overview.txt
create mode 100644 Documentation/arm/STiH41x/stih415-overview.txt
create mode 100644 arch/arm/boot/dts/stih415-clock.dtsi
create mode 100644 arch/arm/boot/dts/stih415-pinctrl.dtsi
create mode 100644 arch/arm/boot/dts/stih415.dtsi
create mode 100644 arch/arm/boot/dts/stih415.h
create mode 100644 arch/arm/boot/dts/stih41x.dtsi
create mode 100644 arch/arm/boot/dts/stixxxx-pincfg.h
create mode 100644 arch/arm/configs/stih41x_defconfig
create mode 100644 arch/arm/include/debug/stixxxx.S
create mode 100644 arch/arm/mach-stih41x/Kconfig
create mode 100644 arch/arm/mach-stih41x/Makefile
create mode 100644 arch/arm/mach-stih41x/board-dt.c
create mode 100644 arch/arm/mach-stih41x/stih41x.c
create mode 100644 arch/arm/mach-stih41x/stih41x.h
create mode 100644 arch/arm/plat-stixxxx/Kconfig
create mode 100644 arch/arm/plat-stixxxx/Makefile
create mode 100644 arch/arm/plat-stixxxx/headsmp.S
create mode 100644 arch/arm/plat-stixxxx/include/plat/hardware.h
create mode 100644 arch/arm/plat-stixxxx/include/plat/smp.h
create mode 100644 arch/arm/plat-stixxxx/platsmp.c
diff --git a/Documentation/arm/STiH41x/overview.txt b/Documentation/arm/STiH41x/overview.txt
new file mode 100644
index 0000000..2411506
--- /dev/null
+++ b/Documentation/arm/STiH41x/overview.txt
@@ -0,0 +1,39 @@
+ STiH41x ARM Linux Overview
+ ==========================
+
+Introduction
+------------
+
+ The ST Microelectronics Multimedia and Application Processors range of
+ CortexA9 System-on-Chip are supported by the 'STixxxx' platform of
+ ARM Linux. Currently STiH415, STiH416 SOCs are supported with both
+ B2000 and B2020 Reference boards.
+
+
+ configuration
+ -------------
+
+ A generic configuration is provided for both STiH415/416, and can be used as the
+ default by
+ make stih41x_defconfig
+
+ Layout
+ ------
+ The common files for multiple machine families (STiH415, STiH416, and STiG125)
+ are located in the platform code contained in arch/arm/plat-stixxxx
+ with headers in plat/.
+ - common files to support Stixxxx SoCs which includes things
+ like platsmp.
+
+ Each machine series have a directory with name arch/arm/mach-sti followed by
+ series name. Like mach-stih41x to support stih415 and stih416.
+
+ There is a generic board board-dt.c in each mach folder which support
+ Flattened Device Tree, which means, It works with any compatible board with
+ Device Trees.
+
+
+ Document Author
+ ---------------
+
+ Srinivas Kandagatla <srinivas.kandagatla@st.com>, (c) 2013 ST Microelectronics
diff --git a/Documentation/arm/STiH41x/stih415-overview.txt b/Documentation/arm/STiH41x/stih415-overview.txt
new file mode 100644
index 0000000..1c264b7
--- /dev/null
+++ b/Documentation/arm/STiH41x/stih415-overview.txt
@@ -0,0 +1,12 @@
+ STiH415 Overview
+ ================
+
+Introduction
+------------
+
+ The STiH415 is the next generation of HD, AVC set-top box processors
+ for satellite, cable, terrestrial and IP-STB markets.
+
+ Features
+ - ARM Cortex-A9 1.0 GHz, dual-core CPU
+ - SATA2×2,USB 2.0×3, PCIe, Gbit Ethernet MAC×2
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c8c524e..b960c7d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1106,6 +1106,9 @@ source "arch/arm/mach-socfpga/Kconfig"
source "arch/arm/plat-spear/Kconfig"
+source "arch/arm/mach-stih41x/Kconfig"
+source "arch/arm/plat-stixxxx/Kconfig"
+
source "arch/arm/mach-s3c24xx/Kconfig"
if ARCH_S3C64XX
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 9b31f43..42a5193 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -447,6 +447,16 @@ choice
This option selects UART0 on VIA/Wondermedia System-on-a-chip
devices, including VT8500, WM8505, WM8650 and WM8850.
+ config DEBUG_STIH41X_UART
+ depends on ARCH_STIH41X
+ bool "Use StiH415/416 ASC for low-level debug"
+ help
+ Say Y here if you want kernel low-level debugging support
+ on StiH415/416 based platforms like B2000, B2020.
+ It support UART2 and SBC_UART1.
+
+ If unsure, say N.
+
config DEBUG_LL_UART_NONE
bool "No low-level debugging UART"
depends on !ARCH_MULTIPLATFORM
@@ -578,6 +588,33 @@ choice
endchoice
+choice
+ prompt "Low-level debug console UART"
+ depends on DEBUG_LL && DEBUG_STIH41X_UART
+
+ config STIH41X_DEBUG_ASC2
+ bool "ASC2 UART"
+ help
+ Say Y here if you want kernel low-level debugging support
+ on STiH415/416 based platforms like b2000, which has
+ default UART wired up to ASC2.
+
+ If unsure, say N.
+
+ config STIH41X_DEBUG_SBC_ASC1
+ bool "SBC ASC1 UART"
+ help
+ Say Y here if you want kernel low-level debugging support
+ on STiH415/416 based platforms like b2020. which has
+ default UART wired up to SBC ASC1.
+
+ If unsure, say N.
+
+endchoice
+
+
+
+
config DEBUG_LL_INCLUDE
string
default "debug/icedcc.S" if DEBUG_ICEDCC
@@ -600,6 +637,7 @@ config DEBUG_LL_INCLUDE
default "debug/vt8500.S" if DEBUG_VT8500_UART0
default "debug/tegra.S" if DEBUG_TEGRA_UART
default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
+ default "debug/stixxxx.S" if DEBUG_STIH41X_UART
default "mach/debug-macro.S"
config EARLY_PRINTK
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index ee4605f..2bb7e7d 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -194,6 +194,7 @@ machine-$(CONFIG_ARCH_SOCFPGA) += socfpga
machine-$(CONFIG_ARCH_SPEAR13XX) += spear13xx
machine-$(CONFIG_ARCH_SPEAR3XX) += spear3xx
machine-$(CONFIG_MACH_SPEAR600) += spear6xx
+machine-$(CONFIG_ARCH_STIH41X) += stih41x
machine-$(CONFIG_ARCH_VIRT) += virt
machine-$(CONFIG_ARCH_ZYNQ) += zynq
machine-$(CONFIG_ARCH_SUNXI) += sunxi
@@ -207,6 +208,7 @@ plat-$(CONFIG_PLAT_ORION) += orion
plat-$(CONFIG_PLAT_PXA) += pxa
plat-$(CONFIG_PLAT_S3C24XX) += samsung
plat-$(CONFIG_PLAT_S5P) += samsung
+plat-$(CONFIG_PLAT_STIXXXX) += stixxxx
plat-$(CONFIG_PLAT_SPEAR) += spear
plat-$(CONFIG_PLAT_VERSATILE) += versatile
diff --git a/arch/arm/boot/dts/stih415-clock.dtsi b/arch/arm/boot/dts/stih415-clock.dtsi
new file mode 100644
index 0000000..174c799
--- /dev/null
+++ b/arch/arm/boot/dts/stih415-clock.dtsi
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/ {
+ clocks {
+ /*
+ * Fixed 30MHz oscillator input to SoC
+ */
+ CLK_SYSIN: CLK_SYSIN {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <30000000>;
+ };
+
+ /*
+ * ARM Peripheral clock for timers
+ */
+ arm_periph_clk: arm_periph_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <500000000>;
+ };
+
+ /*
+ * Bootloader initialized system infrastructure clock for
+ * serial devices.
+ */
+ CLKS_ICN_REG_0: CLKS_ICN_REG_0 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <100000000>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/stih415-pinctrl.dtsi b/arch/arm/boot/dts/stih415-pinctrl.dtsi
new file mode 100644
index 0000000..0f8c770
--- /dev/null
+++ b/arch/arm/boot/dts/stih415-pinctrl.dtsi
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+#include "stih415.h"
+#include "stixxxx-pincfg.h"
+/ {
+
+ aliases {
+ gpio0 = &PIO0;
+ gpio1 = &PIO1;
+ gpio2 = &PIO2;
+ gpio3 = &PIO3;
+ gpio4 = &PIO4;
+ gpio5 = &PIO5;
+ gpio6 = &PIO6;
+ gpio7 = &PIO7;
+ gpio8 = &PIO8;
+ gpio9 = &PIO9;
+ gpio10 = &PIO10;
+ gpio11 = &PIO11;
+ gpio12 = &PIO12;
+ gpio13 = &PIO13;
+ gpio14 = &PIO14;
+ gpio15 = &PIO15;
+ gpio16 = &PIO16;
+ gpio17 = &PIO17;
+ gpio18 = &PIO18;
+ gpio19 = &PIO100;
+ gpio20 = &PIO101;
+ gpio21 = &PIO102;
+ gpio22 = &PIO103;
+ gpio23 = &PIO104;
+ gpio24 = &PIO105;
+ gpio25 = &PIO106;
+ gpio26 = &PIO107;
+ };
+
+
+ soc {
+ pin-controller {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #retime-delay-cells = <4>;
+ compatible = "st,stixxxx-pinctrl", "simple-bus";
+ st,retime-offset = <&pio_retime_offset>;
+ st,retime-in-delay = <0 500 1000 1500>;
+ st,retime-out-delay = <0 1000 2000 3000>;
+ ranges;
+
+ PIO0: pinctrl@fe610000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfe610000 0x100>;
+ st,bank-name = "PIO0";
+ st,alt-control = <&SYSCFG_SBC(0) 0 31>;
+ st,oe-control = <&SYSCFG_SBC(5) 0 7>;
+ st,pu-control = <&SYSCFG_SBC(7) 0 7>;
+ st,od-control = <&SYSCFG_SBC(9) 0 7>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_SBC(16) 0 31>;
+ st,retime-control1 = <&SYSCFG_SBC(17) 0 31>;
+ };
+ PIO1: pinctrl@fe611000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfe611000 0x100>;
+ st,bank-name = "PIO1";
+ st,alt-control = <&SYSCFG_SBC(1) 0 31>;
+ st,oe-control = <&SYSCFG_SBC(5) 8 15>;
+ st,pu-control = <&SYSCFG_SBC(7) 8 15>;
+ st,od-control = <&SYSCFG_SBC(9) 8 15>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_SBC(18) 0 31>;
+ st,retime-control1 = <&SYSCFG_SBC(19) 0 31>;
+ };
+ PIO2: pinctrl@fe612000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfe612000 0x100>;
+ st,bank-name = "PIO2";
+ st,alt-control = <&SYSCFG_SBC(2) 0 31>;
+ st,oe-control = <&SYSCFG_SBC(5) 16 23>;
+ st,pu-control = <&SYSCFG_SBC(7) 16 23>;
+ st,od-control = <&SYSCFG_SBC(9) 16 23>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_SBC(20) 0 31>;
+ st,retime-control1 = <&SYSCFG_SBC(21) 0 31>;
+ };
+ PIO3: pinctrl@fe613000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfe613000 0x100>;
+ st,bank-name = "PIO3";
+ st,alt-control = <&SYSCFG_SBC(3) 0 31>;
+ st,oe-control = <&SYSCFG_SBC(5) 24 31>;
+ st,pu-control = <&SYSCFG_SBC(7) 24 31>;
+ st,od-control = <&SYSCFG_SBC(9) 24 31>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_SBC(22) 0 31>;
+ st,retime-control1 = <&SYSCFG_SBC(23) 0 31>;
+
+ };
+ PIO4: pinctrl@fe614000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfe614000 0x100>;
+ st,bank-name = "PIO4";
+ st,alt-control = <&SYSCFG_SBC(4) 0 31>;
+ st,oe-control = <&SYSCFG_SBC(6) 0 7>;
+ st,pu-control = <&SYSCFG_SBC(8) 0 7>;
+ st,od-control = <&SYSCFG_SBC(10) 0 7>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_SBC(24) 0 31>;
+ st,retime-control1 = <&SYSCFG_SBC(25) 0 31>;
+
+ };
+ /* 5-12:pinctrl_FRONT */
+ PIO5: pinctrl@fee00000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfee00000 0x100>;
+ st,bank-name = "PIO5";
+ st,alt-control = <&SYSCFG_FRONT(100) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(108) 0 7>;
+ st,pu-control = <&SYSCFG_FRONT(110) 0 7>;
+ st,od-control = <&SYSCFG_FRONT(112) 0 7>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_FRONT(116) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(117) 0 31>;
+ };
+ PIO6: pinctrl@fee01000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfee01000 0x100>;
+ st,bank-name = "PIO6";
+ st,alt-control = <&SYSCFG_FRONT(101) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(108) 8 15>;
+ st,pu-control = <&SYSCFG_FRONT(110) 8 15>;
+ st,od-control = <&SYSCFG_FRONT(112) 8 15>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_FRONT(118) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(119) 0 31>;
+ };
+
+ PIO7: pinctrl@fee02000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfee02000 0x100>;
+ st,bank-name = "PIO7";
+ st,alt-control = <&SYSCFG_FRONT(102) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(108) 16 23>;
+ st,pu-control = <&SYSCFG_FRONT(110) 16 23>;
+ st,od-control = <&SYSCFG_FRONT(112) 16 23>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_FRONT(120) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(121) 0 31>;
+ };
+ PIO8: pinctrl@fee03000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfee03000 0x100>;
+ st,bank-name = "PIO8";
+ st,alt-control = <&SYSCFG_FRONT(103) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(108) 24 31>;
+ st,pu-control = <&SYSCFG_FRONT(110) 24 31>;
+ st,od-control = <&SYSCFG_FRONT(112) 24 31>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_FRONT(122) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(123) 0 31>;
+ };
+ PIO9: pinctrl@fee04000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfee04000 0x100>;
+ st,bank-name = "PIO9";
+ st,alt-control = <&SYSCFG_FRONT(104) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(109) 0 7>;
+ st,pu-control = <&SYSCFG_FRONT(111) 0 7>;
+ st,od-control = <&SYSCFG_FRONT(113) 0 7>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_FRONT(124) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(125) 0 31>;
+ };
+ PIO10: pinctrl@fee05000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfee05000 0x100>;
+ st,bank-name = "PIO10";
+ st,alt-control = <&SYSCFG_FRONT(105) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(109) 8 15>;
+ st,pu-control = <&SYSCFG_FRONT(111) 8 15>;
+ st,od-control = <&SYSCFG_FRONT(113) 8 15>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_FRONT(126) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(127) 0 31>;
+ };
+ PIO11: pinctrl@fee06000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfee06000 0x100>;
+ st,bank-name = "PIO11";
+ st,alt-control = <&SYSCFG_FRONT(106) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(109) 16 23>;
+ st,pu-control = <&SYSCFG_FRONT(111) 16 23>;
+ st,od-control = <&SYSCFG_FRONT(113) 16 23>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_FRONT(128) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(129) 0 31>;
+ };
+ PIO12: pinctrl@fee07000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfee07000 0x100>;
+ st,bank-name = "PIO12";
+ st,alt-control = <&SYSCFG_FRONT(107) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(109) 24 31>;
+ st,pu-control = <&SYSCFG_FRONT(111) 24 31>;
+ st,od-control = <&SYSCFG_FRONT(113) 24 31>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_FRONT(130) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(131) 0 31>;
+ };
+ /* 13-18:pinctrl_REAR */
+ PIO13: pinctrl@fe820000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfe820000 0x100>;
+ st,bank-name = "PIO13";
+ st,alt-control = <&SYSCFG_REAR(300) 0 31>;
+ st,oe-control = <&SYSCFG_REAR(306) 0 7>;
+ st,pu-control = <&SYSCFG_REAR(308) 0 7>;
+ st,od-control = <&SYSCFG_REAR(310) 0 7>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_REAR(338) 0 31>;
+ st,retime-control1 = <&SYSCFG_REAR(339) 0 31>;
+ };
+ PIO14: pinctrl@fe821000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfe821000 0x100>;
+ st,bank-name = "PIO14";
+ st,alt-control = <&SYSCFG_REAR(301) 0 31>;
+ st,oe-control = <&SYSCFG_REAR(306) 8 15>;
+ st,pu-control = <&SYSCFG_REAR(308) 8 15>;
+ st,od-control = <&SYSCFG_REAR(310) 8 15>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_REAR(340) 0 31>;
+ st,retime-control1 = <&SYSCFG_REAR(341) 0 31>;
+ };
+ PIO15: pinctrl@fe822000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfe822000 0x100>;
+ st,bank-name = "PIO15";
+ st,alt-control = <&SYSCFG_REAR(302) 0 31>;
+ st,oe-control = <&SYSCFG_REAR(306) 16 23>;
+ st,pu-control = <&SYSCFG_REAR(308) 16 23>;
+ st,od-control = <&SYSCFG_REAR(310) 16 23>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_REAR(342) 0 31>;
+ st,retime-control1 = <&SYSCFG_REAR(343) 0 31>;
+ };
+ PIO16: pinctrl@fe823000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfe823000 0x100>;
+ st,bank-name = "PIO16";
+ st,alt-control = <&SYSCFG_REAR(303) 0 31>;
+ st,oe-control = <&SYSCFG_REAR(306) 24 31>;
+ st,pu-control = <&SYSCFG_REAR(308) 24 31>;
+ st,od-control = <&SYSCFG_REAR(310) 24 31>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_REAR(344) 0 31>;
+ st,retime-control1 = <&SYSCFG_REAR(345) 0 31>;
+
+ };
+ PIO17: pinctrl@fe824000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfe824000 0x100>;
+ st,bank-name = "PIO17";
+ st,alt-control = <&SYSCFG_REAR(304) 0 31>;
+ st,oe-control = <&SYSCFG_REAR(307) 0 7>;
+ st,pu-control = <&SYSCFG_REAR(309) 0 7>;
+ st,od-control = <&SYSCFG_REAR(311) 0 7>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_REAR(346) 0 31>;
+ st,retime-control1 = <&SYSCFG_REAR(347) 0 31>;
+
+ };
+ PIO18: pinctrl@fe825000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfe825000 0x100>;
+ st,bank-name = "PIO18";
+ st,alt-control = <&SYSCFG_REAR(305) 0 31>;
+ st,oe-control = <&SYSCFG_REAR(307) 8 15>;
+ st,pu-control = <&SYSCFG_REAR(309) 8 15>;
+ st,od-control = <&SYSCFG_REAR(311) 8 15>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_REAR(348) 0 31>;
+ st,retime-control1 = <&SYSCFG_REAR(349) 0 31>;
+
+ };
+ /* MPE */
+ /* 100-102:pinctrl_RIGHT (aka MPE_pinctrl) */
+ PIO100: pinctrl@fd6b0000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfd6b0000 0x100>;
+ st,bank-name = "PIO100";
+ st,alt-control = <&SYSCFG_LEFT(400) 0 31>;
+ st,oe-control = <&SYSCFG_LEFT(403) 0 7>;
+ st,pu-control = <&SYSCFG_LEFT(404) 0 7>;
+ st,od-control = <&SYSCFG_LEFT(405) 0 7>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_LEFT(406) 0 31>;
+ st,retime-control1 = <&SYSCFG_LEFT(407) 0 31>;
+ };
+ PIO101: pinctrl@fd6b1000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfd6b1000 0x100>;
+ st,bank-name = "PIO101";
+ st,alt-control = <&SYSCFG_LEFT(401) 0 31>;
+ st,oe-control = <&SYSCFG_LEFT(403) 8 15>;
+ st,pu-control = <&SYSCFG_LEFT(404) 8 15>;
+ st,od-control = <&SYSCFG_LEFT(405) 8 15>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_LEFT(408) 0 31>;
+ st,retime-control1 = <&SYSCFG_LEFT(409) 0 31>;
+
+ };
+ PIO102: pinctrl@fd6b2000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfd6b2000 0x100>;
+ st,bank-name = "PIO102";
+ st,alt-control = <&SYSCFG_LEFT(402) 0 31>;
+ st,oe-control = <&SYSCFG_LEFT(403) 16 23>;
+ st,pu-control = <&SYSCFG_LEFT(404) 16 23>;
+ st,od-control = <&SYSCFG_LEFT(405) 16 23>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_LEFT(410) 0 31>;
+ st,retime-control1 = <&SYSCFG_LEFT(411) 0 31>;
+
+ };
+ /* 103-107:pinctrl_LEFT (aka pinctrl_1_MPE) */
+ PIO103: pinctrl@fd330000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfd330000 0x100>;
+ st,bank-name = "PIO103";
+ st,alt-control = <&SYSCFG_RIGHT(500) 0 31>;
+ st,oe-control = <&SYSCFG_RIGHT(505) 0 7>;
+ st,pu-control = <&SYSCFG_RIGHT(507) 0 7>;
+ st,od-control = <&SYSCFG_RIGHT(509) 0 7>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_RIGHT(511) 0 31>;
+ st,retime-control1 = <&SYSCFG_RIGHT(512) 0 31>;
+ };
+ PIO104: pinctrl@fd331000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfd331000 0x100>;
+ st,bank-name = "PIO104";
+ st,alt-control = <&SYSCFG_RIGHT(501) 0 31>;
+ st,oe-control = <&SYSCFG_RIGHT(505) 8 15>;
+ st,pu-control = <&SYSCFG_RIGHT(507) 8 15>;
+ st,od-control = <&SYSCFG_RIGHT(509) 8 15>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_RIGHT(513) 0 31>;
+ st,retime-control1 = <&SYSCFG_RIGHT(514) 0 31>;
+ };
+ PIO105: pinctrl@fd332000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfd332000 0x100>;
+ st,bank-name = "PIO105";
+ st,alt-control = <&SYSCFG_RIGHT(502) 0 31>;
+ st,oe-control = <&SYSCFG_RIGHT(505) 16 23>;
+ st,pu-control = <&SYSCFG_RIGHT(507) 16 23>;
+ st,od-control = <&SYSCFG_RIGHT(509) 16 23>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_RIGHT(515) 0 31>;
+ st,retime-control1 = <&SYSCFG_RIGHT(516) 0 31>;
+ };
+ PIO106: pinctrl@fd333000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfd333000 0x100>;
+ st,bank-name = "PIO106";
+ st,alt-control = <&SYSCFG_RIGHT(503) 0 31>;
+ st,oe-control = <&SYSCFG_RIGHT(505) 24 31>;
+ st,pu-control = <&SYSCFG_RIGHT(507) 24 31>;
+ st,od-control = <&SYSCFG_RIGHT(509) 24 31>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_RIGHT(517) 0 31>;
+ st,retime-control1 = <&SYSCFG_RIGHT(518) 0 31>;
+ };
+ PIO107: pinctrl@fd334000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfd334000 0x100>;
+ st,bank-name = "PIO107";
+ st,alt-control = <&SYSCFG_RIGHT(504) 0 31>;
+ st,oe-control = <&SYSCFG_RIGHT(506) 0 7>;
+ st,pu-control = <&SYSCFG_RIGHT(508) 0 7>;
+ st,od-control = <&SYSCFG_RIGHT(510) 0 7>;
+ st,retime-style = "packed";
+ st,retime-control0 = <&SYSCFG_RIGHT(519) 0 31>;
+ st,retime-control1 = <&SYSCFG_RIGHT(520) 0 31>;
+ };
+
+ uart2 {
+ pinctrl_uart2: uart2-0 {
+ st,function = <ALT2>;
+ st,pins {
+ tx = <&PIO17 4 OUT>;
+ rx = <&PIO17 5 IN>;
+ };
+ };
+ };
+
+ sbc_uart1 {
+ pinctrl_sbc_uart1: sbc_uart1 {
+ st,function = <ALT3>;
+ st,pins {
+ tx = <&PIO2 6 OUT>;
+ rx = <&PIO2 7 IN>;
+ };
+ };
+ };
+
+ };
+
+ pio_retime_offset: pio-retime-offset {
+ clk1notclk0 = <0>;
+ delay-lsb = <2>;
+ delay-msb = <3>;
+ invertclk = <4>;
+ retime = <5>;
+ clknotdata = <6>;
+ double-edge = <7>;
+ };
+
+ };
+};
diff --git a/arch/arm/boot/dts/stih415.dtsi b/arch/arm/boot/dts/stih415.dtsi
new file mode 100644
index 0000000..b881d22
--- /dev/null
+++ b/arch/arm/boot/dts/stih415.dtsi
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+#include "stih41x.dtsi"
+#include "stih415-clock.dtsi"
+#include "stih415-pinctrl.dtsi"
+/ {
+
+ L2: cache-controller {
+ compatible = "arm,pl310-cache";
+ reg = <0xfffe2000 0x1000>;
+ arm,data-latency = <3 2 2>;
+ arm,tag-latency = <1 1 1>;
+ cache-unified;
+ cache-level = <2>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&intc>;
+ ranges;
+ compatible = "simple-bus";
+
+ syscfg_sbc: syscon@fe600000{
+ compatible = "syscon";
+ reg = <0xfe600000 0xb4>;
+ syscon-name = "SYSCFG_SBC";
+ };
+
+ syscfg_front: syscon@fee10000{
+ compatible = "syscon";
+ reg = <0xfee10000 0x194>;
+ syscon-name = "SYSCFG_FRONT";
+ };
+
+ syscfg_rear: syscon@fe830000{
+ compatible = "syscon";
+ reg = <0xfe830000 0x190>;
+ syscon-name = "SYSCFG_REAR";
+ };
+
+ syscfg_left: syscon@fd690000{
+ compatible = "syscon";
+ reg = <0xfd690000 0x78>;
+ syscon-name = "SYSCFG_LEFT";
+ };
+
+ syscfg_right: syscon@fd320000{
+ compatible = "syscon";
+ reg = <0xfd320000 0x180>;
+ syscon-name = "SYSCFG_RIGHT";
+ };
+
+ syscfg_system: syscon@fdde0000 {
+ compatible = "syscon";
+ reg = <0xfdde0000 0x15c>;
+ syscon-name = "SYSCFG_SYSTEM";
+ };
+
+ syscfg_lpm: syscon@fe4b5100{
+ compatible = "syscon";
+ reg = <0xfe4b5100 0x08>;
+ syscon-name = "LPM_CFG_REGS";
+ };
+
+ uart2: uart@fed32000 {
+ compatible = "st,asc";
+ status = "disabled";
+ reg = <0xfed32000 0x2c>;
+ interrupts = <0 197 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ clocks = <&CLKS_ICN_REG_0>;
+ };
+
+ /* SBC comms block ASCs in SASG1 */
+ sbc_uart1: uart@fe531000 {
+ compatible = "st,asc";
+ status = "disabled";
+ reg = <0xfe531000 0x2c>;
+ interrupts = <0 210 0>;
+ clocks = <&CLK_SYSIN>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sbc_uart1>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/stih415.h b/arch/arm/boot/dts/stih415.h
new file mode 100644
index 0000000..fc46ecc
--- /dev/null
+++ b/arch/arm/boot/dts/stih415.h
@@ -0,0 +1,20 @@
+#ifndef __STIH415_H_
+#define __STIH415_H_
+
+#define CONFIG_SBC(num) (num)
+#define CONFIG_FRONT(num) (num - 100)
+#define CONFIG_REAR(num) (num - 300)
+#define CONFIG_LEFT(num) (num - 400)
+#define CONFIG_RIGHT(num) (num - 500)
+#define CONFIG_SYSTEM(num) (num - 600)
+#define CONFIG_LPM(num) (num)
+
+#define SYSCFG_SBC(num) syscfg_sbc CONFIG_SBC(num)
+#define SYSCFG_FRONT(num) syscfg_front CONFIG_FRONT(num)
+#define SYSCFG_REAR(num) syscfg_rear CONFIG_REAR(num)
+#define SYSCFG_LEFT(num) syscfg_left CONFIG_LEFT(num)
+#define SYSCFG_RIGHT(num) syscfg_right CONFIG_RIGHT(num)
+#define SYSCFG_SYSTEM(num) syscfg_system CONFIG_SYSTEM(num)
+#define SYSCFG_LPM(num) syscfg_lpm CONFIG_LPM(num)
+
+#endif /* __STIH415_H_ */
diff --git a/arch/arm/boot/dts/stih41x.dtsi b/arch/arm/boot/dts/stih41x.dtsi
new file mode 100644
index 0000000..a7f0fa4
--- /dev/null
+++ b/arch/arm/boot/dts/stih41x.dtsi
@@ -0,0 +1,30 @@
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ cpu@0 {
+ compatible = "arm,cortex-a9";
+ };
+ cpu@1 {
+ compatible = "arm,cortex-a9";
+ };
+ };
+
+ intc: interrupt-controller@fffe1000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0xfffe1000 0x1000>,
+ <0xfffe0100 0x100>;
+ };
+
+ timer@fffe0200 {
+ #interrupt-cells = <3>;
+ interrupt-parent = <&intc>;
+ compatible = "arm,cortex-a9-global-timer";
+ reg = <0xfffe0200 0x100>;
+ interrupts = <1 11 0x04>;
+ clocks = <&arm_periph_clk>;
+ };
+};
diff --git a/arch/arm/boot/dts/stixxxx-pincfg.h b/arch/arm/boot/dts/stixxxx-pincfg.h
new file mode 100644
index 0000000..5398ff2
--- /dev/null
+++ b/arch/arm/boot/dts/stixxxx-pincfg.h
@@ -0,0 +1,95 @@
+#ifndef _ST_PINCFG_H_
+#define _ST_PINCFG_H
+
+/* Alternate functions */
+#define ALT1 1
+#define ALT2 2
+#define ALT3 3
+#define ALT4 4
+#define ALT5 5
+#define ALT6 6
+#define ALT7 7
+
+/* Output enable */
+#define OE_MASK 0x1
+#define OE_SHIFT 27
+#define OE (1 << OE_SHIFT)
+
+/* Pull Up */
+#define PU_MASK 0x1
+#define PU_SHIFT 26
+#define PU (1 << PU_SHIFT)
+
+/* Open Drain */
+#define OD_MASK 0x1
+#define OD_SHIFT 25
+#define OD (1 << OD_SHIFT)
+
+#define RT_MASK 0x1
+#define RT_SHIFT 23
+#define RT (1 << RT_SHIFT)
+
+#define INVERTCLK_MASK 0x1
+#define INVERTCLK_SHIFT 22
+#define INVERTCLK (1 << INVERTCLK_SHIFT)
+
+#define CLKNOTDATA_MASK 0x1
+#define CLKNOTDATA_SHIFT 21
+#define CLKNOTDATA (1 << CLKNOTDATA_SHIFT)
+
+#define DOUBLE_EDGE_MASK 0x1
+#define DOUBLE_EDGE_SHIFT 20
+#define DOUBLE_EDGE (1 << DOUBLE_EDGE_SHIFT)
+
+#define CLK_MASK 0x3
+#define CLK_SHIFT 18
+#define CLK_A (0 << CLK_SHIFT)
+#define CLK_B (1 << CLK_SHIFT)
+#define CLK_C (2 << CLK_SHIFT)
+#define CLK_D (3 << CLK_SHIFT)
+
+/* User-frendly defines for Pin Direction */
+ /* oe = 0, pu = 0, od = 0 */
+#define IN (0)
+ /* oe = 0, pu = 1, od = 0 */
+#define IN_PU (PU)
+ /* oe = 1, pu = 0, od = 0 */
+#define OUT (OE)
+ /* oe = 1, pu = 0, od = 1 */
+#define BIDIR (OE | OD)
+ /* oe = 1, pu = 1, od = 1 */
+#define BIDIR_PU (OE | PU | OD)
+
+/* RETIME_TYPE */
+/*
+ * B Mode
+ * Bypass retime with optional delay parameter
+ */
+#define BYPASS (0)
+/*
+ * R0, R1, R0D, R1D modes
+ * single-edge data non inverted clock, retime data with clk
+ */
+#define SE_NICLK_IO (RT)
+/*
+ * RIV0, RIV1, RIV0D, RIV1D modes
+ * single-edge data inverted clock, retime data with clk
+ */
+#define SE_ICLK_IO (RT | INVERTCLK)
+/*
+ * R0E, R1E, R0ED, R1ED modes
+ * double-edge data, retime data with clk
+ */
+#define DE_IO (RT | DOUBLE_EDGE)
+/*
+ * CIV0, CIV1 modes with inverted clock
+ * Retiming the clk pins will park clock & reduce the noise within the core.
+ */
+#define ICLK (RT | CLKNOTDATA | INVERTCLK)
+/*
+ * CLK0, CLK1 modes with non-inverted clock
+ * Retiming the clk pins will park clock & reduce the noise within the core.
+ */
+#define NICLK (RT | CLKNOTDATA)
+#endif /* _ST_PINCFG_H */
+
diff --git a/arch/arm/configs/stih41x_defconfig b/arch/arm/configs/stih41x_defconfig
new file mode 100644
index 0000000..dd9268b
--- /dev/null
+++ b/arch/arm/configs/stih41x_defconfig
@@ -0,0 +1,94 @@
+CONFIG_LOCALVERSION="-STiH41x"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_NAMESPACES=y
+CONFIG_RELAY=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_ARCH_STIH41X=y
+CONFIG_SOC_STIH415=y
+# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
+# CONFIG_SWP_EMULATE is not set
+CONFIG_ARM_ERRATA_720789=y
+CONFIG_PL310_ERRATA_753970=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_PL310_ERRATA_769419=y
+CONFIG_SMP=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_KSM=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_SUSPEND is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_DEBUG_DEVRES=y
+# CONFIG_BLK_DEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HWMON is not set
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_COMMON_CLK_DEBUG=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_XFS_FS=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_NLS=y
+CONFIG_PRINTK_TIME=y
+CONFIG_FRAME_WARN=2048
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_UNUSED_SYMBOLS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_STIH41X_UART=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SECURITYFS=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_T10DIF=y
diff --git a/arch/arm/include/debug/stixxxx.S b/arch/arm/include/debug/stixxxx.S
new file mode 100644
index 0000000..7bc02a7
--- /dev/null
+++ b/arch/arm/include/debug/stixxxx.S
@@ -0,0 +1,61 @@
+/*
+ * arch/arm/include/debug/stixxxx.S
+ *
+ * Debugging macro include header
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define STIH41X_COMMS_BASE 0xfed00000
+#define STIH41X_ASC2_BASE (STIH41X_COMMS_BASE+0x32000)
+
+#define STIH41X_SBC_LPM_BASE 0xfe400000
+#define STIH41X_SBC_COMMS_BASE (STIH41X_SBC_LPM_BASE + 0x100000)
+#define STIH41X_SBC_ASC1_BASE (STIH41X_SBC_COMMS_BASE + 0x31000)
+
+
+#define VIRT_ADDRESS(x) (x - 0x1000000)
+
+#if IS_ENABLED(CONFIG_STIH41X_DEBUG_ASC2)
+#define DEBUG_LL_UART_BASE STIH41X_ASC2_BASE
+#endif
+
+#if IS_ENABLED(CONFIG_STIH41X_DEBUG_SBC_ASC1)
+#define DEBUG_LL_UART_BASE STIH41X_SBC_ASC1_BASE
+#endif
+
+#ifndef DEBUG_LL_UART_BASE
+#error "DEBUG UART is not Configured"
+#endif
+
+#define ASC_TX_BUF_OFF 0x04
+#define ASC_CTRL_OFF 0x0c
+#define ASC_STA_OFF 0x14
+
+#define ASC_STA_TX_FULL (1<<9)
+#define ASC_STA_TX_EMPTY (1<<1)
+
+
+ .macro addruart, rp, rv, tmp
+ ldr \rp, =DEBUG_LL_UART_BASE @ physical base
+ ldr \rv, =VIRT_ADDRESS(DEBUG_LL_UART_BASE) @ virt base
+ .endm
+
+ .macro senduart,rd,rx
+ strb \rd, [\rx, #ASC_TX_BUF_OFF]
+ .endm
+
+ .macro waituart,rd,rx
+1001: ldr \rd, [\rx, #ASC_STA_OFF]
+ tst \rd, #ASC_STA_TX_FULL
+ bne 1001b
+ .endm
+
+ .macro busyuart,rd,rx
+1001: ldr \rd, [\rx, #ASC_STA_OFF]
+ tst \rd, #ASC_STA_TX_EMPTY
+ beq 1001b
+ .endm
diff --git a/arch/arm/mach-stih41x/Kconfig b/arch/arm/mach-stih41x/Kconfig
new file mode 100644
index 0000000..9c40540
--- /dev/null
+++ b/arch/arm/mach-stih41x/Kconfig
@@ -0,0 +1,35 @@
+config ARCH_STIH41X
+ bool "STMicroelectronics STiH41x SOCs with Flattened Device Tree" if ARCH_MULTI_V7
+ select GENERIC_CLOCKEVENTS
+ select CLKDEV_LOOKUP
+ select ARM_GIC
+ select HAVE_ARM_GT
+ select PINCTRL
+ select PINCTRL_STIXXXX
+ select MIGHT_HAVE_CACHE_L2X0
+ select HAVE_SMP
+ select GPIOLIB
+ select MACH_STIH41X_GENERIC
+ help
+ Include support for STiH41x SOCs like STiH415/416 using the device tree
+ for discovery
+ More information at Documentation/arm/STiH41x and
+ at Documentation/devicetree
+
+config MACH_STIH41X_GENERIC
+ bool
+
+if ARCH_STIH41X
+menu "STMicroelectronics Consumer Electronics SOCs"
+
+config SOC_STIH415
+ bool "STiH415 STMicroelectronics Consumer Electronics family"
+ select PLAT_STIXXXX
+ help
+ This enables support for STMicroelectronics Digital Consumer
+ Electronics family StiH415 parts, primarily targetted at set-top-box
+ and other digital audio/video applications using Flattned Device
+ Trees.
+
+endmenu
+endif
diff --git a/arch/arm/mach-stih41x/Makefile b/arch/arm/mach-stih41x/Makefile
new file mode 100644
index 0000000..91d6863
--- /dev/null
+++ b/arch/arm/mach-stih41x/Makefile
@@ -0,0 +1,4 @@
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
+ -I$(srctree)/arch/arm/plat-stixxxx/include
+obj-y := stih41x.o
+obj-$(CONFIG_MACH_STIH41X_GENERIC) += board-dt.o
diff --git a/arch/arm/mach-stih41x/board-dt.c b/arch/arm/mach-stih41x/board-dt.c
new file mode 100644
index 0000000..c51e2c9
--- /dev/null
+++ b/arch/arm/mach-stih41x/board-dt.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author(s): Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/of_platform.h>
+#include <linux/clk-provider.h>
+#include <linux/clocksource.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/arm-gic.h>
+
+#include <asm/mach/arch.h>
+
+#include <plat/smp.h>
+#include <plat/hardware.h>
+
+#include "stih41x.h"
+
+static void __init stih41x_timer_init(void)
+{
+ of_clk_init(NULL);
+ clocksource_of_init();
+ stih41x_l2x0_init();
+}
+
+/*
+ * A basic implementation of irq_set_wake that ensures wakeup source
+ * interrupts are not disabled during PM_SUSPEND_FREEZE.
+ */
+static int stih41x_set_wake(struct irq_data *d, unsigned int on)
+{
+ struct irq_desc *desc = irq_to_desc(d->irq);
+
+ if (on) {
+ if (desc->action)
+ desc->action->flags |= IRQF_NO_SUSPEND;
+ } else {
+ if (desc->action)
+ desc->action->flags &= ~IRQF_NO_SUSPEND;
+ }
+ return 0;
+}
+
+static void __init stih41x_irq_init(void)
+{
+ gic_arch_extn.irq_set_wake = stih41x_set_wake;
+ gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
+
+ irqchip_init();
+}
+
+void __init stih41x_dt_init(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table,
+ NULL, NULL);
+ return;
+}
+
+static const char *stih41x_dt_match[] __initdata = {
+ NULL
+};
+
+DT_MACHINE_START(STM, "STiH415 SoC with Flattened Device Tree")
+ .map_io = stih41x_map_io,
+ .init_time = stih41x_timer_init,
+ .init_machine = stih41x_dt_init,
+ .smp = smp_ops(stixxxx_smp_ops),
+ .init_irq = stih41x_irq_init,
+ .dt_compat = stih41x_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-stih41x/stih41x.c b/arch/arm/mach-stih41x/stih41x.c
new file mode 100644
index 0000000..b76cac1
--- /dev/null
+++ b/arch/arm/mach-stih41x/stih41x.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author(s): Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/bug.h>
+
+#include <asm/mach/map.h>
+#include <asm/page.h>
+#include <asm/mach/arch.h>
+
+#include <plat/smp.h>
+#include <plat/hardware.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#define MPE41_SCU_BASE (0xFFFE0000 + 0x0000)
+
+#define STIH41X_COMMS_BASE 0xFED00000
+#define STIH41X_ASC0_BASE (STIH41X_COMMS_BASE+0x30000)
+#define STIH41X_ASC1_BASE (STIH41X_COMMS_BASE+0x31000)
+#define STIH41X_ASC2_BASE (STIH41X_COMMS_BASE+0x32000)
+#define STIH41X_ASC3_BASE (STIH41X_COMMS_BASE+0x33000)
+
+#define STIH41X_SBC_LPM_BASE 0xfe400000
+#define STIH41X_SBC_COMMS_BASE (STIH41X_SBC_LPM_BASE + 0x100000)
+#define STIH41X_SBC_ASC0_BASE (STIH41X_SBC_COMMS_BASE + 0x30000)
+#define STIH41X_SBC_ASC1_BASE (STIH41X_SBC_COMMS_BASE + 0x31000)
+
+
+static struct map_desc stih41x_io_desc[] __initdata = {
+#ifdef CONFIG_SMP
+ {
+ .virtual = IO_ADDRESS(MPE41_SCU_BASE),
+ .pfn = __phys_to_pfn(MPE41_SCU_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+#endif
+#ifdef CONFIG_STIH41X_DEBUG_ASC2
+ { /* For DEBUG_LL and Early Prints */
+ .virtual = IO_ADDRESS(STIH41X_ASC2_BASE),
+ .pfn = __phys_to_pfn(STIH41X_ASC2_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+#endif
+#ifdef CONFIG_STIH41X_DEBUG_SBC_ASC1
+ {
+ .virtual = IO_ADDRESS(STIH41X_SBC_ASC1_BASE),
+ .pfn = __phys_to_pfn(STIH41X_SBC_ASC1_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+#endif
+};
+
+void __init stih41x_map_io(void)
+{
+#ifdef CONFIG_SMP
+ stixxxx_scu_base_addr = ((void __iomem *)IO_ADDRESS(MPE41_SCU_BASE));
+#endif
+ iotable_init(stih41x_io_desc, ARRAY_SIZE(stih41x_io_desc));
+}
+
+void __init stih41x_l2x0_init(void)
+{
+ u32 way_size = 0x4;
+ u32 aux_ctrl;
+
+ aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
+ (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
+ (0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
+ (way_size << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
+
+ l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK);
+}
diff --git a/arch/arm/mach-stih41x/stih41x.h b/arch/arm/mach-stih41x/stih41x.h
new file mode 100644
index 0000000..6c0e90b
--- /dev/null
+++ b/arch/arm/mach-stih41x/stih41x.h
@@ -0,0 +1,7 @@
+#ifndef __STIH41X_H_
+#define __STIH41X_H_
+
+void stih41x_map_io(void);
+void stih41x_l2x0_init(void);
+
+#endif /* __STIH41X_H_ */
diff --git a/arch/arm/plat-stixxxx/Kconfig b/arch/arm/plat-stixxxx/Kconfig
new file mode 100644
index 0000000..ceeda96
--- /dev/null
+++ b/arch/arm/plat-stixxxx/Kconfig
@@ -0,0 +1,2 @@
+config PLAT_STIXXXX
+ bool
diff --git a/arch/arm/plat-stixxxx/Makefile b/arch/arm/plat-stixxxx/Makefile
new file mode 100644
index 0000000..36534a9
--- /dev/null
+++ b/arch/arm/plat-stixxxx/Makefile
@@ -0,0 +1,2 @@
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
+obj-$(CONFIG_SMP) += platsmp.o headsmp.o
diff --git a/arch/arm/plat-stixxxx/headsmp.S b/arch/arm/plat-stixxxx/headsmp.S
new file mode 100644
index 0000000..3dd5c04
--- /dev/null
+++ b/arch/arm/plat-stixxxx/headsmp.S
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/plat-stixxxx/headsmp.S
+ *
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * http://www.st.com
+ *
+ * Cloned from linux/arch/arm/mach-vexpress/headsmp.S
+ *
+ * Copyright (c) 2003 ARM Limited
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+ __INIT
+
+/*
+ * ST specific entry point for secondary CPUs. This provides
+ * a "holding pen" into which all secondary cores are held until we're
+ * ready for them to initialise.
+ */
+ENTRY(stixxxx_secondary_startup)
+ mrc p15, 0, r0, c0, c0, 5
+ and r0, r0, #15
+ adr r4, 1f
+ ldmia r4, {r5, r6}
+ sub r4, r4, r5
+ add r6, r6, r4
+pen: ldr r7, [r6]
+ cmp r7, r0
+ bne pen
+
+ /*
+ * we've been released from the holding pen: secondary_stack
+ * should now contain the SVC stack for this core
+ */
+ b secondary_startup
+
+1: .long .
+ .long pen_release
diff --git a/arch/arm/plat-stixxxx/include/plat/hardware.h b/arch/arm/plat-stixxxx/include/plat/hardware.h
new file mode 100644
index 0000000..7a9a804
--- /dev/null
+++ b/arch/arm/plat-stixxxx/include/plat/hardware.h
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/plat-stixxxx/include/mach/hardware.h
+ *
+ * Copyright (C) 2013 STMicroelectronics Limited.
+ * Author: Stuart Menefy <stuart.menefy@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PLAT_HARDWARE_H
+#define __PLAT_HARDWARE_H
+/*
+ * Statically mapped addresses:
+ *
+ * fc000000 to ffffffff (physical) -> fb000000 to feffffff (virtual)
+ */
+#define IO_ADDRESS(x) (((x) & 0x03ffffff) + 0xfb000000)
+#endif
diff --git a/arch/arm/plat-stixxxx/include/plat/smp.h b/arch/arm/plat-stixxxx/include/plat/smp.h
new file mode 100644
index 0000000..c3e3d40
--- /dev/null
+++ b/arch/arm/plat-stixxxx/include/plat/smp.h
@@ -0,0 +1,19 @@
+/*
+ * arch/arm/plat-stixxxx/platsmp.c
+ *
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * http://www.st.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PLAT_SMP_H
+#define __PLAT_SMP_H
+
+extern struct smp_operations stixxxx_smp_ops;
+extern void __iomem *stixxxx_scu_base_addr;
+extern void stixxxx_secondary_startup(void);
+
+#endif
diff --git a/arch/arm/plat-stixxxx/platsmp.c b/arch/arm/plat-stixxxx/platsmp.c
new file mode 100644
index 0000000..256640d
--- /dev/null
+++ b/arch/arm/plat-stixxxx/platsmp.c
@@ -0,0 +1,144 @@
+/*
+ * arch/arm/plat-stixxxx/platsmp.c
+ *
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * http://www.st.com
+ *
+ * Cloned from linux/arch/arm/mach-vexpress/platsmp.c
+ *
+ * Copyright (C) 2002 ARM Ltd.
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+
+#include <plat/hardware.h>
+#include <plat/smp.h>
+
+
+void __iomem *stixxxx_scu_base_addr;
+
+static void __cpuinit write_pen_release(int val)
+{
+ pen_release = val;
+ smp_wmb();
+ __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+ outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
+static inline unsigned int get_core_count(void)
+{
+ return scu_get_core_count(stixxxx_scu_base_addr);
+}
+
+static DEFINE_SPINLOCK(boot_lock);
+
+void __cpuinit stixxxx_secondary_init(unsigned int cpu)
+{
+ trace_hardirqs_off();
+
+ /*
+ * if any interrupts are already enabled for the primary
+ * core (e.g. timer irq), then they will not have been enabled
+ * for us: do so
+ */
+ gic_secondary_init(0);
+
+ /*
+ * let the primary processor know we're out of the
+ * pen, then head off into the C entry point
+ */
+ write_pen_release(-1);
+
+ /*
+ * Synchronise with the boot thread.
+ */
+ spin_lock(&boot_lock);
+ spin_unlock(&boot_lock);
+}
+
+int __cpuinit stixxxx_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ unsigned long timeout;
+
+ /*
+ * set synchronisation state between this boot processor
+ * and the secondary one
+ */
+ spin_lock(&boot_lock);
+
+ /*
+ * The secondary processor is waiting to be released from
+ * the holding pen - release it, then wait for it to flag
+ * that it has been released by resetting pen_release.
+ *
+ * Note that "pen_release" is the hardware CPU ID, whereas
+ * "cpu" is Linux's internal ID.
+ */
+ write_pen_release(cpu_logical_map(cpu));
+
+ /*
+ * Send the secondary CPU a soft interrupt, thereby causing
+ * it to jump to the secondary entrypoint.
+ */
+ arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+ timeout = jiffies + (1 * HZ);
+ while (time_before(jiffies, timeout)) {
+ smp_rmb();
+ if (pen_release == -1)
+ break;
+
+ udelay(10);
+ }
+
+ /*
+ * now the secondary core is starting up let it run its
+ * calibrations, then wait for it to finish
+ */
+ spin_unlock(&boot_lock);
+
+ return pen_release != -1 ? -ENOSYS : 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init stixxxx_smp_init_cpus(void)
+{
+ unsigned int i, ncores = get_core_count();
+
+ if (ncores > nr_cpu_ids) {
+ pr_warn("STM: %u greater than maximum (%u), clipping\n",
+ ncores, nr_cpu_ids);
+ ncores = nr_cpu_ids;
+ }
+
+ for (i = 0; i < ncores; i++)
+ set_cpu_possible(i, true);
+}
+
+void __init stixxxx_smp_prepare_cpus(unsigned int max_cpus)
+{
+ scu_enable(stixxxx_scu_base_addr);
+}
+
+struct smp_operations __initdata stixxxx_smp_ops = {
+ .smp_init_cpus = stixxxx_smp_init_cpus,
+ .smp_prepare_cpus = stixxxx_smp_prepare_cpus,
+ .smp_secondary_init = stixxxx_secondary_init,
+ .smp_boot_secondary = stixxxx_boot_secondary,
+};
--
1.7.6.5
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 79+ messages in thread
* Re: [RFC 5/8] ARM:stih41x: Add STiH415 SOC support
2013-05-08 14:11 ` =?y?q?=5BRFC=205/8=5D=20ARM=3Astih41x=3A=20Add=20STiH415=20SOC=20support?= Srinivas KANDAGATLA
@ 2013-05-08 16:18 ` Arnd Bergmann
2013-05-08 16:21 ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-08 17:03 ` Srinivas KANDAGATLA
0 siblings, 2 replies; 79+ messages in thread
From: Arnd Bergmann @ 2013-05-08 16:18 UTC (permalink / raw)
To: Srinivas KANDAGATLA
Cc: linux, olof, Rob Landley, Grant Likely, Rob Herring, Samuel Ortiz,
Linus Walleij, Greg Kroah-Hartman, Jiri Slaby, Stuart Menefy,
Shawn Guo, Jason Cooper, Stephen Warren, Maxime Ripard,
Nicolas Pitre, Will Deacon, Dave Martin, Marc Zyngier,
Viresh Kumar, Mark Brown, Dong Aisheng, linux-doc, linux-kernel,
devicetree-discuss
On Wednesday 08 May 2013, Srinivas KANDAGATLA wrote:
> From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>
> The STiH415 is the next generation of HD, AVC set-top box processors for
> satellite, cable, terrestrial and IP-STB markets. It is an ARM Cortex-A9
> 1.0 GHz, dual-core CPU.
>
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
> CC: Stephen Gallimore <stephen.gallimore@st.com>
> CC: Stuart Menefy <stuart.menefy@st.com>
> ---
> Documentation/arm/STiH41x/overview.txt | 39 ++
> Documentation/arm/STiH41x/stih415-overview.txt | 12 +
> arch/arm/Kconfig | 3 +
> arch/arm/Kconfig.debug | 38 ++
> arch/arm/Makefile | 2 +
> arch/arm/boot/dts/stih415-clock.dtsi | 38 ++
> arch/arm/boot/dts/stih415-pinctrl.dtsi | 480 ++++++++++++++++++++++++
> arch/arm/boot/dts/stih415.dtsi | 94 +++++
> arch/arm/boot/dts/stih415.h | 20 +
> arch/arm/boot/dts/stih41x.dtsi | 30 ++
> arch/arm/boot/dts/stixxxx-pincfg.h | 95 +++++
> arch/arm/configs/stih41x_defconfig | 94 +++++
> arch/arm/include/debug/stixxxx.S | 61 +++
> arch/arm/mach-stih41x/Kconfig | 35 ++
> arch/arm/mach-stih41x/Makefile | 4 +
> arch/arm/mach-stih41x/board-dt.c | 76 ++++
> arch/arm/mach-stih41x/stih41x.c | 82 ++++
> arch/arm/mach-stih41x/stih41x.h | 7 +
> arch/arm/plat-stixxxx/Kconfig | 2 +
> arch/arm/plat-stixxxx/Makefile | 2 +
> arch/arm/plat-stixxxx/headsmp.S | 44 +++
> arch/arm/plat-stixxxx/include/plat/hardware.h | 20 +
> arch/arm/plat-stixxxx/include/plat/smp.h | 19 +
> arch/arm/plat-stixxxx/platsmp.c | 144 +++++++
I think there is no point in having a separate mach- and plat- directory
here, given that modern machines require very little code. You can probably
fold the three files in mach-stih41x (board-dt.c, stih41x.c and stih41x.h)
into a single file and rename plat-stixxxx to mach-stixxxx
> diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
> index 9b31f43..42a5193 100644
> --- a/arch/arm/Kconfig.debug
> +++ b/arch/arm/Kconfig.debug
> @@ -447,6 +447,16 @@ choice
> This option selects UART0 on VIA/Wondermedia System-on-a-chip
> devices, including VT8500, WM8505, WM8650 and WM8850.
>
> + config DEBUG_STIH41X_UART
> + depends on ARCH_STIH41X
> + bool "Use StiH415/416 ASC for low-level debug"
> + help
> + Say Y here if you want kernel low-level debugging support
> + on StiH415/416 based platforms like B2000, B2020.
> + It support UART2 and SBC_UART1.
> +
> + If unsure, say N.
> +
> config DEBUG_LL_UART_NONE
> bool "No low-level debugging UART"
> depends on !ARCH_MULTIPLATFORM
I would split out the debug code into a separate patch though.
> @@ -600,6 +637,7 @@ config DEBUG_LL_INCLUDE
> default "debug/vt8500.S" if DEBUG_VT8500_UART0
> default "debug/tegra.S" if DEBUG_TEGRA_UART
> default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
> + default "debug/stixxxx.S" if DEBUG_STIH41X_UART
> default "mach/debug-macro.S"
Please keep this in alphabetical order.
> + soc {
> + #address-cells = <1>;
> + #size-cells = <1>;
> + #interrupt-cells = <3>;
> + interrupt-parent = <&intc>;
The "#interrupt-cells" property doesn't belong here I think.
> +
> + uart2: uart@fed32000 {
> + compatible = "st,asc";
> + status = "disabled";
> + reg = <0xfed32000 0x2c>;
> + interrupts = <0 197 0>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&pinctrl_uart2>;
> + clocks = <&CLKS_ICN_REG_0>;
> + };
> +
> + /* SBC comms block ASCs in SASG1 */
> + sbc_uart1: uart@fe531000 {
> + compatible = "st,asc";
> + status = "disabled";
> + reg = <0xfe531000 0x2c>;
> + interrupts = <0 210 0>;
> + clocks = <&CLK_SYSIN>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&pinctrl_sbc_uart1>;
> + };
> + };
Please name these devices "serial", not "uart".
> diff --git a/arch/arm/configs/stih41x_defconfig b/arch/arm/configs/stih41x_defconfig
> new file mode 100644
> index 0000000..dd9268b
> --- /dev/null
> +++ b/arch/arm/configs/stih41x_defconfig
I would prefer to have this be part of multi_v7_defconfig, unless
you have strong reason why it can't be.
> diff --git a/arch/arm/mach-stih41x/Kconfig b/arch/arm/mach-stih41x/Kconfig
> new file mode 100644
> index 0000000..9c40540
> --- /dev/null
> +++ b/arch/arm/mach-stih41x/Kconfig
> @@ -0,0 +1,35 @@
> +config ARCH_STIH41X
> + bool "STMicroelectronics STiH41x SOCs with Flattened Device Tree" if ARCH_MULTI_V7
> + select GENERIC_CLOCKEVENTS
> + select CLKDEV_LOOKUP
> + select ARM_GIC
> +if ARCH_STIH41X
> +menu "STMicroelectronics Consumer Electronics SOCs"
You can use 'menuconfig' to combine these two.
> +static void __init stih41x_timer_init(void)
> +{
> + of_clk_init(NULL);
> + clocksource_of_init();
> + stih41x_l2x0_init();
> +}
I'm hoping we can kill make the clk and l2x0 init work by default in 3.11,
as clocksource_of_init already does, so you won't need this function
any more.
> +/*
> + * A basic implementation of irq_set_wake that ensures wakeup source
> + * interrupts are not disabled during PM_SUSPEND_FREEZE.
> + */
> +static int stih41x_set_wake(struct irq_data *d, unsigned int on)
> +{
> + struct irq_desc *desc = irq_to_desc(d->irq);
> +
> + if (on) {
> + if (desc->action)
> + desc->action->flags |= IRQF_NO_SUSPEND;
> + } else {
> + if (desc->action)
> + desc->action->flags &= ~IRQF_NO_SUSPEND;
> + }
> + return 0;
> +}
> +
> +static void __init stih41x_irq_init(void)
> +{
> + gic_arch_extn.irq_set_wake = stih41x_set_wake;
> + gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
> +
> + irqchip_init();
> +}
This looks like it should be generic. Why do you need this?
> +void __init stih41x_dt_init(void)
> +{
> + of_platform_populate(NULL, of_default_bus_match_table,
> + NULL, NULL);
> + return;
> +}
This is already not needed in 3.10.
> +static struct map_desc stih41x_io_desc[] __initdata = {
> +#ifdef CONFIG_SMP
> + {
> + .virtual = IO_ADDRESS(MPE41_SCU_BASE),
> + .pfn = __phys_to_pfn(MPE41_SCU_BASE),
> + .length = SZ_4K,
> + .type = MT_DEVICE,
> + },
> +#endif
> +void __init stih41x_map_io(void)
> +{
> +#ifdef CONFIG_SMP
> + stixxxx_scu_base_addr = ((void __iomem *)IO_ADDRESS(MPE41_SCU_BASE));
> +#endif
> + iotable_init(stih41x_io_desc, ARRAY_SIZE(stih41x_io_desc));
> +}
IIRC the SCU no longer needs to be mapped this early, so you can use
ioremap these days.
> +void __init stih41x_l2x0_init(void)
> +{
> + u32 way_size = 0x4;
> + u32 aux_ctrl;
> +
> + aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
> + (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
> + (0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
> + (way_size << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
> +
> + l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK);
> +}
I don't know where we stand on this, but I think we should kill all
calls like these.
Arnd
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 5/8] ARM:stih41x: Add STiH415 SOC support
2013-05-08 16:18 ` [RFC 5/8] ARM:stih41x: Add STiH415 SOC support Arnd Bergmann
@ 2013-05-08 16:21 ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-08 17:03 ` Srinivas KANDAGATLA
1 sibling, 0 replies; 79+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-05-08 16:21 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Mark Brown, linux, Samuel Ortiz, linux-doc, Viresh Kumar,
devicetree-discuss, Srinivas KANDAGATLA, Will Deacon,
Stephen Gallimore, Rob Herring, linux-kernel, Stuart Menefy,
Nicolas Pitre, linux-serial, Greg Kroah-Hartman, Stephen Warren,
Dong Aisheng, Jiri Slaby, linux-arm-kernel, Jason Cooper
On 18:18 Wed 08 May , Arnd Bergmann wrote:
> On Wednesday 08 May 2013, Srinivas KANDAGATLA wrote:
> > From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
> >
> > The STiH415 is the next generation of HD, AVC set-top box processors for
> > satellite, cable, terrestrial and IP-STB markets. It is an ARM Cortex-A9
> > 1.0 GHz, dual-core CPU.
> >
> > Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
> > CC: Stephen Gallimore <stephen.gallimore@st.com>
> > CC: Stuart Menefy <stuart.menefy@st.com>
> > ---
patch no receive on the ML
please resend
Best Regards,
J.
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 5/8] ARM:stih41x: Add STiH415 SOC support
2013-05-08 16:18 ` [RFC 5/8] ARM:stih41x: Add STiH415 SOC support Arnd Bergmann
2013-05-08 16:21 ` Jean-Christophe PLAGNIOL-VILLARD
@ 2013-05-08 17:03 ` Srinivas KANDAGATLA
1 sibling, 0 replies; 79+ messages in thread
From: Srinivas KANDAGATLA @ 2013-05-08 17:03 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux, olof, Rob Landley, Grant Likely, Rob Herring, Samuel Ortiz,
Linus Walleij, Greg Kroah-Hartman, Jiri Slaby, Stuart Menefy,
Shawn Guo, Jason Cooper, Stephen Warren, Maxime Ripard,
Nicolas Pitre, Will Deacon, Dave Martin, Marc Zyngier,
Viresh Kumar, Mark Brown, Dong Aisheng, linux-doc, linux-kernel,
devicetree-discuss
Thankyou for the comments.
On 08/05/13 17:18, Arnd Bergmann wrote:
> On Wednesday 08 May 2013, Srinivas KANDAGATLA wrote:
>> From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>>
>> The STiH415 is the next generation of HD, AVC set-top box processors for
>> satellite, cable, terrestrial and IP-STB markets. It is an ARM Cortex-A9
>> 1.0 GHz, dual-core CPU.
>>
>> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>> CC: Stephen Gallimore <stephen.gallimore@st.com>
>> CC: Stuart Menefy <stuart.menefy@st.com>
>> ---
>> Documentation/arm/STiH41x/overview.txt | 39 ++
>> Documentation/arm/STiH41x/stih415-overview.txt | 12 +
>> arch/arm/Kconfig | 3 +
>> arch/arm/Kconfig.debug | 38 ++
>> arch/arm/Makefile | 2 +
>> arch/arm/boot/dts/stih415-clock.dtsi | 38 ++
>> arch/arm/boot/dts/stih415-pinctrl.dtsi | 480 ++++++++++++++++++++++++
>> arch/arm/boot/dts/stih415.dtsi | 94 +++++
>> arch/arm/boot/dts/stih415.h | 20 +
>> arch/arm/boot/dts/stih41x.dtsi | 30 ++
>> arch/arm/boot/dts/stixxxx-pincfg.h | 95 +++++
>> arch/arm/configs/stih41x_defconfig | 94 +++++
>> arch/arm/include/debug/stixxxx.S | 61 +++
>> arch/arm/mach-stih41x/Kconfig | 35 ++
>> arch/arm/mach-stih41x/Makefile | 4 +
>> arch/arm/mach-stih41x/board-dt.c | 76 ++++
>> arch/arm/mach-stih41x/stih41x.c | 82 ++++
>> arch/arm/mach-stih41x/stih41x.h | 7 +
>> arch/arm/plat-stixxxx/Kconfig | 2 +
>> arch/arm/plat-stixxxx/Makefile | 2 +
>> arch/arm/plat-stixxxx/headsmp.S | 44 +++
>> arch/arm/plat-stixxxx/include/plat/hardware.h | 20 +
>> arch/arm/plat-stixxxx/include/plat/smp.h | 19 +
>> arch/arm/plat-stixxxx/platsmp.c | 144 +++++++
> I think there is no point in having a separate mach- and plat- directory
> here, given that modern machines require very little code. You can probably
> fold the three files in mach-stih41x (board-dt.c, stih41x.c and stih41x.h)
> into a single file and rename plat-stixxxx to mach-stixxxx
Yep, sounds good.
>
>> diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
>> index 9b31f43..42a5193 100644
>> --- a/arch/arm/Kconfig.debug
>> +++ b/arch/arm/Kconfig.debug
>> @@ -447,6 +447,16 @@ choice
>> This option selects UART0 on VIA/Wondermedia System-on-a-chip
>> devices, including VT8500, WM8505, WM8650 and WM8850.
>>
>> + config DEBUG_STIH41X_UART
>> + depends on ARCH_STIH41X
>> + bool "Use StiH415/416 ASC for low-level debug"
>> + help
>> + Say Y here if you want kernel low-level debugging support
>> + on StiH415/416 based platforms like B2000, B2020.
>> + It support UART2 and SBC_UART1.
>> +
>> + If unsure, say N.
>> +
>> config DEBUG_LL_UART_NONE
>> bool "No low-level debugging UART"
>> depends on !ARCH_MULTIPLATFORM
> I would split out the debug code into a separate patch though.
Will do this in next version.
>
>> @@ -600,6 +637,7 @@ config DEBUG_LL_INCLUDE
>> default "debug/vt8500.S" if DEBUG_VT8500_UART0
>> default "debug/tegra.S" if DEBUG_TEGRA_UART
>> default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
>> + default "debug/stixxxx.S" if DEBUG_STIH41X_UART
>> default "mach/debug-macro.S"
> Please keep this in alphabetical order.
Yes.
>
>> + soc {
>> + #address-cells = <1>;
>> + #size-cells = <1>;
>> + #interrupt-cells = <3>;
>> + interrupt-parent = <&intc>;
> The "#interrupt-cells" property doesn't belong here I think.
>
>> +
>> + uart2: uart@fed32000 {
>> + compatible = "st,asc";
>> + status = "disabled";
>> + reg = <0xfed32000 0x2c>;
>> + interrupts = <0 197 0>;
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_uart2>;
>> + clocks = <&CLKS_ICN_REG_0>;
>> + };
>> +
>> + /* SBC comms block ASCs in SASG1 */
>> + sbc_uart1: uart@fe531000 {
>> + compatible = "st,asc";
>> + status = "disabled";
>> + reg = <0xfe531000 0x2c>;
>> + interrupts = <0 210 0>;
>> + clocks = <&CLK_SYSIN>;
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_sbc_uart1>;
>> + };
>> + };
> Please name these devices "serial", not "uart".
Ok, I will rename them to serial.
>> diff --git a/arch/arm/configs/stih41x_defconfig b/arch/arm/configs/stih41x_defconfig
>> new file mode 100644
>> index 0000000..dd9268b
>> --- /dev/null
>> +++ b/arch/arm/configs/stih41x_defconfig
> I would prefer to have this be part of multi_v7_defconfig, unless
> you have strong reason why it can't be.
I think we can move this to multi_v7_defconfig.
>> diff --git a/arch/arm/mach-stih41x/Kconfig b/arch/arm/mach-stih41x/Kconfig
>> new file mode 100644
>> index 0000000..9c40540
>> --- /dev/null
>> +++ b/arch/arm/mach-stih41x/Kconfig
>> @@ -0,0 +1,35 @@
>> +config ARCH_STIH41X
>> + bool "STMicroelectronics STiH41x SOCs with Flattened Device Tree" if ARCH_MULTI_V7
>> + select GENERIC_CLOCKEVENTS
>> + select CLKDEV_LOOKUP
>> + select ARM_GIC
>
>> +if ARCH_STIH41X
>> +menu "STMicroelectronics Consumer Electronics SOCs"
> You can use 'menuconfig' to combine these two.
Thats a nice one.. Will use it.
>> +static void __init stih41x_timer_init(void)
>> +{
>> + of_clk_init(NULL);
>> + clocksource_of_init();
>> + stih41x_l2x0_init();
>> +}
> I'm hoping we can kill make the clk and l2x0 init work by default in 3.11,
> as clocksource_of_init already does, so you won't need this function
> any more.
Ok.
>
>> +/*
>> + * A basic implementation of irq_set_wake that ensures wakeup source
>> + * interrupts are not disabled during PM_SUSPEND_FREEZE.
>> + */
>> +static int stih41x_set_wake(struct irq_data *d, unsigned int on)
>> +{
>> + struct irq_desc *desc = irq_to_desc(d->irq);
>> +
>> + if (on) {
>> + if (desc->action)
>> + desc->action->flags |= IRQF_NO_SUSPEND;
>> + } else {
>> + if (desc->action)
>> + desc->action->flags &= ~IRQF_NO_SUSPEND;
>> + }
>> + return 0;
>> +}
>> +
>> +static void __init stih41x_irq_init(void)
>> +{
>> + gic_arch_extn.irq_set_wake = stih41x_set_wake;
>> + gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
>> +
>> + irqchip_init();
>> +}
> This looks like it should be generic. Why do you need this?
>
>> +void __init stih41x_dt_init(void)
>> +{
>> + of_platform_populate(NULL, of_default_bus_match_table,
>> + NULL, NULL);
>> + return;
>> +}
> This is already not needed in 3.10.
Ok, cool... will get rid of this..
>
>> +static struct map_desc stih41x_io_desc[] __initdata = {
>> +#ifdef CONFIG_SMP
>> + {
>> + .virtual = IO_ADDRESS(MPE41_SCU_BASE),
>> + .pfn = __phys_to_pfn(MPE41_SCU_BASE),
>> + .length = SZ_4K,
>> + .type = MT_DEVICE,
>> + },
>> +#endif
>> +void __init stih41x_map_io(void)
>> +{
>> +#ifdef CONFIG_SMP
>> + stixxxx_scu_base_addr = ((void __iomem *)IO_ADDRESS(MPE41_SCU_BASE));
>> +#endif
>> + iotable_init(stih41x_io_desc, ARRAY_SIZE(stih41x_io_desc));
>> +}
> IIRC the SCU no longer needs to be mapped this early, so you can use
> ioremap these days.
yep, I agree.
>
>> +void __init stih41x_l2x0_init(void)
>> +{
>> + u32 way_size = 0x4;
>> + u32 aux_ctrl;
>> +
>> + aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
>> + (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
>> + (0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
>> + (way_size << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
>> +
>> + l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK);
>> +}
> I don't know where we stand on this, but I think we should kill all
> calls like these.
I agree, but we don't have other ways as of today..
>
> Arnd
>
^ permalink raw reply [flat|nested] 79+ messages in thread
* [RFC 6/8] ARM:stih41x: Add STiH416 SOC support
2013-05-08 14:09 [RFC 0/8] ARM:STiH41x: Add STiH41x platform and board support Srinivas KANDAGATLA
` (2 preceding siblings ...)
2013-05-08 14:11 ` =?y?q?=5BRFC=205/8=5D=20ARM=3Astih41x=3A=20Add=20STiH415=20SOC=20support?= Srinivas KANDAGATLA
@ 2013-05-08 14:11 ` Srinivas KANDAGATLA
[not found] ` <1368022318-2380-1-git-send-email-srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
[not found] ` <1368022187-1633-1-git-send-email-srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
2013-05-08 14:12 ` [RFC 8/8] ARM:stih41x: Add B2020 " Srinivas KANDAGATLA
5 siblings, 1 reply; 79+ messages in thread
From: Srinivas KANDAGATLA @ 2013-05-08 14:11 UTC (permalink / raw)
To: linux, arnd, olof
Cc: Rob Landley, Grant Likely, Rob Herring, Samuel Ortiz,
Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Srinivas Kandagatla, Stuart Menefy, Shawn Guo, Jason Cooper,
Stephen Warren, Maxime Ripard, Nicolas Pitre, Will Deacon,
Dave Martin, Marc Zyngier, Viresh Kumar, Mark Brown, Dong Aisheng,
linux-doc, linux-kernel, devicetree-discuss
From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
The STiH416 is advanced HD AVC processor with 3D graphics acceleration
and 1.2-GHz ARM Cortex-A9 SMP CPU.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
CC: Stephen Gallimore <stephen.gallimore@st.com>
CC: Stuart Menefy <stuart.menefy@st.com>
---
Documentation/arm/STiH41x/stih416-overview.txt | 12 +
arch/arm/boot/dts/stih416-clock.dtsi | 41 ++
arch/arm/boot/dts/stih416-pinctrl.dtsi | 718 ++++++++++++++++++++++++
arch/arm/boot/dts/stih416.dtsi | 103 ++++
arch/arm/boot/dts/stih416.h | 24 +
arch/arm/configs/stih41x_defconfig | 1 +
arch/arm/mach-stih41x/Kconfig | 9 +
arch/arm/mach-stih41x/board-dt.c | 2 +-
8 files changed, 909 insertions(+), 1 deletions(-)
create mode 100644 Documentation/arm/STiH41x/stih416-overview.txt
create mode 100644 arch/arm/boot/dts/stih416-clock.dtsi
create mode 100644 arch/arm/boot/dts/stih416-pinctrl.dtsi
create mode 100644 arch/arm/boot/dts/stih416.dtsi
create mode 100644 arch/arm/boot/dts/stih416.h
diff --git a/Documentation/arm/STiH41x/stih416-overview.txt b/Documentation/arm/STiH41x/stih416-overview.txt
new file mode 100644
index 0000000..e060867
--- /dev/null
+++ b/Documentation/arm/STiH41x/stih416-overview.txt
@@ -0,0 +1,12 @@
+ STiH416 Overview
+ ================
+
+Introduction
+------------
+
+ The STiH416 is the next generation of HD, AVC set-top box processors
+ for satellite, cable, terrestrial and IP-STB markets.
+
+ Features
+ - ARM Cortex-A9 1.2 GHz dual core CPU
+ - SATA2×2,USB 2.0×3, PCIe, Gbit Ethernet MAC×2
diff --git a/arch/arm/boot/dts/stih416-clock.dtsi b/arch/arm/boot/dts/stih416-clock.dtsi
new file mode 100644
index 0000000..7026bf1
--- /dev/null
+++ b/arch/arm/boot/dts/stih416-clock.dtsi
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics R&D Limited
+ * <stlinux-devel@stlinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/ {
+ clocks {
+ /*
+ * Fixed 30MHz oscillator inputs to SoC
+ */
+ CLK_SYSIN: CLK_SYSIN {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <30000000>;
+ clock-output-names = "CLK_SYSIN";
+ };
+
+ /*
+ * ARM Peripheral clock for timers
+ */
+ arm_periph_clk: arm_periph_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <600000000>;
+ };
+
+ /*
+ * Bootloader initialized system infrastructure clock for
+ * serial devices.
+ */
+ CLK_S_ICN_REG_0: clockgenA0@4 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <100000000>;
+ clock-output-names = "CLK_S_ICN_REG_0";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/stih416-pinctrl.dtsi b/arch/arm/boot/dts/stih416-pinctrl.dtsi
new file mode 100644
index 0000000..f1266bb
--- /dev/null
+++ b/arch/arm/boot/dts/stih416-pinctrl.dtsi
@@ -0,0 +1,718 @@
+
+/*
+ * Copyright (C) 2013 STMicroelectronics Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+#include "stixxxx-pincfg.h"
+#include "stih416.h"
+/ {
+
+ aliases {
+ gpio0 = &PIO0;
+ gpio1 = &PIO1;
+ gpio2 = &PIO2;
+ gpio3 = &PIO3;
+ gpio4 = &PIO4;
+ gpio5 = &PIO40;
+ gpio6 = &PIO5;
+ gpio7 = &PIO6;
+ gpio8 = &PIO7;
+ gpio9 = &PIO8;
+ gpio10 = &PIO9;
+ gpio11 = &PIO10;
+ gpio12 = &PIO11;
+ gpio13 = &PIO12;
+ gpio14 = &PIO30;
+ gpio15 = &PIO31;
+ gpio16 = &PIO13;
+ gpio17 = &PIO14;
+ gpio18 = &PIO15;
+ gpio19 = &PIO16;
+ gpio20 = &PIO17;
+ gpio21 = &PIO18;
+ gpio22 = &PIO100;
+ gpio23 = &PIO101;
+ gpio24 = &PIO102;
+ gpio25 = &PIO103;
+ gpio26 = &PIO104;
+ gpio27 = &PIO105;
+ gpio28 = &PIO106;
+ gpio29 = &PIO107;
+ };
+
+
+ soc {
+ pin-controller {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #retime-delay-cells = <14>;
+ compatible = "st,stixxxx-pinctrl", "simple-bus";
+ st,retime-in-delay = <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
+ st,retime-out-delay = <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
+ ranges;
+ PIO0: pinctrl@fe610000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfe610000 0x100>;
+ st,bank-name = "PIO0";
+ st,alt-control = <&SYSCFG_SBC(0) 0 31>;
+ st,oe-control = <&SYSCFG_SBC(40) 0 7>;
+ st,pu-control = <&SYSCFG_SBC(50) 0 7>;
+ st,od-control = <&SYSCFG_SBC(60) 0 7>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_SBC(100) 0 31>;
+ st,retime-control1 = <&SYSCFG_SBC(101) 0 31>;
+ st,retime-control2 = <&SYSCFG_SBC(102) 0 31>;
+ st,retime-control3 = <&SYSCFG_SBC(103) 0 31>;
+ st,retime-control4 = <&SYSCFG_SBC(104) 0 31>;
+ st,retime-control5 = <&SYSCFG_SBC(105) 0 31>;
+ st,retime-control6 = <&SYSCFG_SBC(106) 0 31>;
+ st,retime-control7 = <&SYSCFG_SBC(107) 0 31>;
+ };
+ PIO1: pinctrl@fe611000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfe611000 0x100>;
+ st,bank-name = "PIO1";
+ st,alt-control = <&SYSCFG_SBC(1) 0 31>;
+ st,oe-control = <&SYSCFG_SBC(40) 8 15>;
+ st,pu-control = <&SYSCFG_SBC(50) 8 15>;
+ st,od-control = <&SYSCFG_SBC(60) 8 15>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_SBC(108) 0 31>;
+ st,retime-control1 = <&SYSCFG_SBC(109) 0 31>;
+ st,retime-control2 = <&SYSCFG_SBC(110) 0 31>;
+ st,retime-control3 = <&SYSCFG_SBC(111) 0 31>;
+ st,retime-control4 = <&SYSCFG_SBC(112) 0 31>;
+ st,retime-control5 = <&SYSCFG_SBC(113) 0 31>;
+ st,retime-control6 = <&SYSCFG_SBC(114) 0 31>;
+ st,retime-control7 = <&SYSCFG_SBC(115) 0 31>;
+ };
+ PIO2: pinctrl@fe612000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfe612000 0x100>;
+ st,bank-name = "PIO2";
+ st,alt-control = <&SYSCFG_SBC(2) 0 31>;
+ st,oe-control = <&SYSCFG_SBC(40) 16 23>;
+ st,pu-control = <&SYSCFG_SBC(50) 16 23>;
+ st,od-control = <&SYSCFG_SBC(60) 16 23>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_SBC(116) 0 31>;
+ st,retime-control1 = <&SYSCFG_SBC(117) 0 31>;
+ st,retime-control2 = <&SYSCFG_SBC(118) 0 31>;
+ st,retime-control3 = <&SYSCFG_SBC(119) 0 31>;
+ st,retime-control4 = <&SYSCFG_SBC(120) 0 31>;
+ st,retime-control5 = <&SYSCFG_SBC(121) 0 31>;
+ st,retime-control6 = <&SYSCFG_SBC(122) 0 31>;
+ st,retime-control7 = <&SYSCFG_SBC(123) 0 31>;
+ };
+ PIO3: pinctrl@fe613000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfe613000 0x100>;
+ st,bank-name = "PIO3";
+ st,alt-control = <&SYSCFG_SBC(3) 0 31>;
+ st,oe-control = <&SYSCFG_SBC(40) 24 31>;
+ st,pu-control = <&SYSCFG_SBC(50) 24 31>;
+ st,od-control = <&SYSCFG_SBC(60) 24 31>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_SBC(124) 0 31>;
+ st,retime-control1 = <&SYSCFG_SBC(125) 0 31>;
+ st,retime-control2 = <&SYSCFG_SBC(126) 0 31>;
+ st,retime-control3 = <&SYSCFG_SBC(127) 0 31>;
+ st,retime-control4 = <&SYSCFG_SBC(128) 0 31>;
+ st,retime-control5 = <&SYSCFG_SBC(129) 0 31>;
+ st,retime-control6 = <&SYSCFG_SBC(130) 0 31>;
+ st,retime-control7 = <&SYSCFG_SBC(131) 0 31>;
+ };
+
+ PIO4: pinctrl@fe614000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfe614000 0x100>;
+ st,bank-name = "PIO4";
+ st,alt-control = <&SYSCFG_SBC(4) 0 31>;
+ st,oe-control = <&SYSCFG_SBC(41) 0 7>;
+ st,pu-control = <&SYSCFG_SBC(51) 0 7>;
+ st,od-control = <&SYSCFG_SBC(61) 0 7>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_SBC(132) 0 31>;
+ st,retime-control1 = <&SYSCFG_SBC(133) 0 31>;
+ st,retime-control2 = <&SYSCFG_SBC(134) 0 31>;
+ st,retime-control3 = <&SYSCFG_SBC(135) 0 31>;
+ st,retime-control4 = <&SYSCFG_SBC(136) 0 31>;
+ st,retime-control5 = <&SYSCFG_SBC(137) 0 31>;
+ st,retime-control6 = <&SYSCFG_SBC(138) 0 31>;
+ st,retime-control7 = <&SYSCFG_SBC(139) 0 31>;
+ };
+
+ PIO40: pinctrl@fe615000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfe615000 0x100>;
+ st,bank-name = "PIO40";
+ st,alt-control = <&SYSCFG_SBC(5) 0 31>;
+ st,oe-control = <&SYSCFG_SBC(41) 8 15>;
+ st,pu-control = <&SYSCFG_SBC(51) 8 15>;
+ st,od-control = <&SYSCFG_SBC(61) 8 15>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0x7f>;
+ st,retime-control0 = <&SYSCFG_SBC(140) 0 31>;
+ st,retime-control1 = <&SYSCFG_SBC(141) 0 31>;
+ st,retime-control2 = <&SYSCFG_SBC(142) 0 31>;
+ st,retime-control3 = <&SYSCFG_SBC(143) 0 31>;
+ st,retime-control4 = <&SYSCFG_SBC(144) 0 31>;
+ st,retime-control5 = <&SYSCFG_SBC(145) 0 31>;
+ st,retime-control6 = <&SYSCFG_SBC(146) 0 31>;
+ };
+
+ PIO5: pinctrl@fee00000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfee00000 0x100>;
+ st,bank-name = "PIO5";
+ st,alt-control = <&SYSCFG_FRONT(1000) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(1040) 0 7>;
+ st,pu-control = <&SYSCFG_FRONT(1050) 0 7>;
+ st,od-control = <&SYSCFG_FRONT(1060) 0 7>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FRONT(1100) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(1101) 0 31>;
+ st,retime-control2 = <&SYSCFG_FRONT(1102) 0 31>;
+ st,retime-control3 = <&SYSCFG_FRONT(1103) 0 31>;
+ st,retime-control4 = <&SYSCFG_FRONT(1104) 0 31>;
+ st,retime-control5 = <&SYSCFG_FRONT(1105) 0 31>;
+ st,retime-control6 = <&SYSCFG_FRONT(1106) 0 31>;
+ st,retime-control7 = <&SYSCFG_FRONT(1107) 0 31>;
+ };
+ PIO6: pinctrl@fee01000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfee01000 0x100>;
+ st,bank-name = "PIO6";
+ st,alt-control = <&SYSCFG_FRONT(1001) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(1040) 8 15>;
+ st,pu-control = <&SYSCFG_FRONT(1050) 8 15>;
+ st,od-control = <&SYSCFG_FRONT(1060) 8 15>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FRONT(1108) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(1109) 0 31>;
+ st,retime-control2 = <&SYSCFG_FRONT(1110) 0 31>;
+ st,retime-control3 = <&SYSCFG_FRONT(1111) 0 31>;
+ st,retime-control4 = <&SYSCFG_FRONT(1112) 0 31>;
+ st,retime-control5 = <&SYSCFG_FRONT(1113) 0 31>;
+ st,retime-control6 = <&SYSCFG_FRONT(1114) 0 31>;
+ st,retime-control7 = <&SYSCFG_FRONT(1115) 0 31>;
+ };
+ PIO7: pinctrl@fee02000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfee02000 0x100>;
+ st,bank-name = "PIO7";
+ st,alt-control = <&SYSCFG_FRONT(1002) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(1040) 16 23>;
+ st,pu-control = <&SYSCFG_FRONT(1050) 16 23>;
+ st,od-control = <&SYSCFG_FRONT(1060) 16 23>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FRONT(1116) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(1117) 0 31>;
+ st,retime-control2 = <&SYSCFG_FRONT(1118) 0 31>;
+ st,retime-control3 = <&SYSCFG_FRONT(1119) 0 31>;
+ st,retime-control4 = <&SYSCFG_FRONT(1120) 0 31>;
+ st,retime-control5 = <&SYSCFG_FRONT(1121) 0 31>;
+ st,retime-control6 = <&SYSCFG_FRONT(1122) 0 31>;
+ st,retime-control7 = <&SYSCFG_FRONT(1123) 0 31>;
+ };
+ PIO8: pinctrl@fee03000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfee03000 0x100>;
+ st,bank-name = "PIO8";
+ st,alt-control = <&SYSCFG_FRONT(1003) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(1040) 24 31>;
+ st,pu-control = <&SYSCFG_FRONT(1050) 24 31>;
+ st,od-control = <&SYSCFG_FRONT(1060) 24 31>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FRONT(1124) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(1125) 0 31>;
+ st,retime-control2 = <&SYSCFG_FRONT(1126) 0 31>;
+ st,retime-control3 = <&SYSCFG_FRONT(1127) 0 31>;
+ st,retime-control4 = <&SYSCFG_FRONT(1128) 0 31>;
+ st,retime-control5 = <&SYSCFG_FRONT(1129) 0 31>;
+ st,retime-control6 = <&SYSCFG_FRONT(1130) 0 31>;
+ st,retime-control7 = <&SYSCFG_FRONT(1131) 0 31>;
+ };
+
+ PIO9: pinctrl@fee04000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfee04000 0x100>;
+ st,bank-name = "PIO9";
+ st,alt-control = <&SYSCFG_FRONT(1004) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(1041) 0 7>;
+ st,pu-control = <&SYSCFG_FRONT(1051) 0 7>;
+ st,od-control = <&SYSCFG_FRONT(1061) 0 7>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FRONT(1132) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(1133) 0 31>;
+ st,retime-control2 = <&SYSCFG_FRONT(1134) 0 31>;
+ st,retime-control3 = <&SYSCFG_FRONT(1135) 0 31>;
+ st,retime-control4 = <&SYSCFG_FRONT(1136) 0 31>;
+ st,retime-control5 = <&SYSCFG_FRONT(1137) 0 31>;
+ st,retime-control6 = <&SYSCFG_FRONT(1138) 0 31>;
+ st,retime-control7 = <&SYSCFG_FRONT(1139) 0 31>;
+ };
+ PIO10: pinctrl@fee05000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfee05000 0x100>;
+ st,bank-name = "PIO10";
+ st,alt-control = <&SYSCFG_FRONT(1005) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(1041) 8 15>;
+ st,pu-control = <&SYSCFG_FRONT(1051) 8 15>;
+ st,od-control = <&SYSCFG_FRONT(1061) 8 15>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FRONT(1140) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(1141) 0 31>;
+ st,retime-control2 = <&SYSCFG_FRONT(1142) 0 31>;
+ st,retime-control3 = <&SYSCFG_FRONT(1143) 0 31>;
+ st,retime-control4 = <&SYSCFG_FRONT(1144) 0 31>;
+ st,retime-control5 = <&SYSCFG_FRONT(1145) 0 31>;
+ st,retime-control6 = <&SYSCFG_FRONT(1146) 0 31>;
+ st,retime-control7 = <&SYSCFG_FRONT(1147) 0 31>;
+ };
+ PIO11: pinctrl@fee06000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfee06000 0x100>;
+ st,bank-name = "PIO11";
+ st,alt-control = <&SYSCFG_FRONT(1006) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(1041) 16 23>;
+ st,pu-control = <&SYSCFG_FRONT(1051) 16 23>;
+ st,od-control = <&SYSCFG_FRONT(1061) 16 23>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FRONT(1148) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(1149) 0 31>;
+ st,retime-control2 = <&SYSCFG_FRONT(1150) 0 31>;
+ st,retime-control3 = <&SYSCFG_FRONT(1151) 0 31>;
+ st,retime-control4 = <&SYSCFG_FRONT(1152) 0 31>;
+ st,retime-control5 = <&SYSCFG_FRONT(1153) 0 31>;
+ st,retime-control6 = <&SYSCFG_FRONT(1154) 0 31>;
+ st,retime-control7 = <&SYSCFG_FRONT(1155) 0 31>;
+ };
+ PIO12: pinctrl@fee07000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfee07000 0x100>;
+ st,bank-name = "PIO12";
+ st,alt-control = <&SYSCFG_FRONT(1007) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(1041) 24 31>;
+ st,pu-control = <&SYSCFG_FRONT(1051) 24 31>;
+ st,od-control = <&SYSCFG_FRONT(1061) 24 31>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FRONT(1156) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(1157) 0 31>;
+ st,retime-control2 = <&SYSCFG_FRONT(1158) 0 31>;
+ st,retime-control3 = <&SYSCFG_FRONT(1159) 0 31>;
+ st,retime-control4 = <&SYSCFG_FRONT(1160) 0 31>;
+ st,retime-control5 = <&SYSCFG_FRONT(1161) 0 31>;
+ st,retime-control6 = <&SYSCFG_FRONT(1162) 0 31>;
+ st,retime-control7 = <&SYSCFG_FRONT(1163) 0 31>;
+ };
+
+ PIO30: pinctrl@fee08000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfee08000 0x100>;
+ st,bank-name = "PIO30";
+ st,alt-control = <&SYSCFG_FRONT(1008) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(1042) 0 7>;
+ st,pu-control = <&SYSCFG_FRONT(1052) 0 7>;
+ st,od-control = <&SYSCFG_FRONT(1062) 0 7>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FRONT(1164) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(1165) 0 31>;
+ st,retime-control2 = <&SYSCFG_FRONT(1166) 0 31>;
+ st,retime-control3 = <&SYSCFG_FRONT(1167) 0 31>;
+ st,retime-control4 = <&SYSCFG_FRONT(1168) 0 31>;
+ st,retime-control5 = <&SYSCFG_FRONT(1169) 0 31>;
+ st,retime-control6 = <&SYSCFG_FRONT(1170) 0 31>;
+ st,retime-control7 = <&SYSCFG_FRONT(1171) 0 31>;
+ };
+
+ PIO31: pinctrl@fee09000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfee09000 0x100>;
+ st,bank-name = "PIO31";
+ st,alt-control = <&SYSCFG_FRONT(1009) 0 31>;
+ st,oe-control = <&SYSCFG_FRONT(1042) 8 15>;
+ st,pu-control = <&SYSCFG_FRONT(1052) 8 15>;
+ st,od-control = <&SYSCFG_FRONT(1062) 8 15>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FRONT(1172) 0 31>;
+ st,retime-control1 = <&SYSCFG_FRONT(1173) 0 31>;
+ st,retime-control2 = <&SYSCFG_FRONT(1174) 0 31>;
+ st,retime-control3 = <&SYSCFG_FRONT(1175) 0 31>;
+ st,retime-control4 = <&SYSCFG_FRONT(1176) 0 31>;
+ st,retime-control5 = <&SYSCFG_FRONT(1177) 0 31>;
+ st,retime-control6 = <&SYSCFG_FRONT(1178) 0 31>;
+ st,retime-control7 = <&SYSCFG_FRONT(1179) 0 31>;
+ };
+
+
+
+ PIO13: pinctrl@fe820000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfe820000 0x100>;
+ st,bank-name = "PIO13";
+ st,alt-control = <&SYSCFG_REAR(2000) 0 31>;
+ st,oe-control = <&SYSCFG_REAR(2040) 0 7>;
+ st,pu-control = <&SYSCFG_REAR(2050) 0 7>;
+ st,od-control = <&SYSCFG_REAR(2060) 0 7>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_REAR(2100) 0 31>;
+ st,retime-control1 = <&SYSCFG_REAR(2101) 0 31>;
+ st,retime-control2 = <&SYSCFG_REAR(2102) 0 31>;
+ st,retime-control3 = <&SYSCFG_REAR(2103) 0 31>;
+ st,retime-control4 = <&SYSCFG_REAR(2104) 0 31>;
+ st,retime-control5 = <&SYSCFG_REAR(2105) 0 31>;
+ st,retime-control6 = <&SYSCFG_REAR(2106) 0 31>;
+ st,retime-control7 = <&SYSCFG_REAR(2107) 0 31>;
+ };
+ PIO14: pinctrl@fe821000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfe821000 0x100>;
+ st,bank-name = "PIO14";
+ st,alt-control = <&SYSCFG_REAR(2001) 0 31>;
+ st,oe-control = <&SYSCFG_REAR(2040) 8 15>;
+ st,pu-control = <&SYSCFG_REAR(2050) 8 15>;
+ st,od-control = <&SYSCFG_REAR(2060) 8 15>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_REAR(2108) 0 31>;
+ st,retime-control1 = <&SYSCFG_REAR(2109) 0 31>;
+ st,retime-control2 = <&SYSCFG_REAR(2110) 0 31>;
+ st,retime-control3 = <&SYSCFG_REAR(2111) 0 31>;
+ st,retime-control4 = <&SYSCFG_REAR(2112) 0 31>;
+ st,retime-control5 = <&SYSCFG_REAR(2113) 0 31>;
+ st,retime-control6 = <&SYSCFG_REAR(2114) 0 31>;
+ st,retime-control7 = <&SYSCFG_REAR(2115) 0 31>;
+ };
+ PIO15: pinctrl@fe822000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfe822000 0x100>;
+ st,bank-name = "PIO15";
+ st,alt-control = <&SYSCFG_REAR(2002) 0 31>;
+ st,oe-control = <&SYSCFG_REAR(2040) 16 23>;
+ st,pu-control = <&SYSCFG_REAR(2050) 16 23>;
+ st,od-control = <&SYSCFG_REAR(2060) 16 23>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_REAR(2116) 0 31>;
+ st,retime-control1 = <&SYSCFG_REAR(2117) 0 31>;
+ st,retime-control2 = <&SYSCFG_REAR(2118) 0 31>;
+ st,retime-control3 = <&SYSCFG_REAR(2119) 0 31>;
+ st,retime-control4 = <&SYSCFG_REAR(2120) 0 31>;
+ st,retime-control5 = <&SYSCFG_REAR(2121) 0 31>;
+ st,retime-control6 = <&SYSCFG_REAR(2122) 0 31>;
+ st,retime-control7 = <&SYSCFG_REAR(2123) 0 31>;
+ };
+ PIO16: pinctrl@fe823000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfe823000 0x100>;
+ st,bank-name = "PIO16";
+ st,alt-control = <&SYSCFG_REAR(2003) 0 31>;
+ st,oe-control = <&SYSCFG_REAR(2040) 24 31>;
+ st,pu-control = <&SYSCFG_REAR(2050) 24 31>;
+ st,od-control = <&SYSCFG_REAR(2060) 24 31>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_REAR(2124) 0 31>;
+ st,retime-control1 = <&SYSCFG_REAR(2125) 0 31>;
+ st,retime-control2 = <&SYSCFG_REAR(2126) 0 31>;
+ st,retime-control3 = <&SYSCFG_REAR(2127) 0 31>;
+ st,retime-control4 = <&SYSCFG_REAR(2128) 0 31>;
+ st,retime-control5 = <&SYSCFG_REAR(2129) 0 31>;
+ st,retime-control6 = <&SYSCFG_REAR(2130) 0 31>;
+ st,retime-control7 = <&SYSCFG_REAR(2131) 0 31>;
+ };
+
+ PIO17: pinctrl@fe824000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfe824000 0x100>;
+ st,bank-name = "PIO17";
+ st,alt-control = <&SYSCFG_REAR(2004) 0 31>;
+ st,oe-control = <&SYSCFG_REAR(2041) 0 7>;
+ st,pu-control = <&SYSCFG_REAR(2051) 0 7>;
+ st,od-control = <&SYSCFG_REAR(2061) 0 7>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_REAR(2132) 0 31>;
+ st,retime-control1 = <&SYSCFG_REAR(2133) 0 31>;
+ st,retime-control2 = <&SYSCFG_REAR(2134) 0 31>;
+ st,retime-control3 = <&SYSCFG_REAR(2135) 0 31>;
+ st,retime-control4 = <&SYSCFG_REAR(2136) 0 31>;
+ st,retime-control5 = <&SYSCFG_REAR(2137) 0 31>;
+ st,retime-control6 = <&SYSCFG_REAR(2138) 0 31>;
+ st,retime-control7 = <&SYSCFG_REAR(2139) 0 31>;
+ };
+
+ PIO18: pinctrl@fe825000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfe825000 0x100>;
+ st,bank-name = "PIO18";
+ st,alt-control = <&SYSCFG_REAR(2005) 0 31>;
+ st,oe-control = <&SYSCFG_REAR(2041) 8 15>;
+ st,pu-control = <&SYSCFG_REAR(2051) 8 15>;
+ st,od-control = <&SYSCFG_REAR(2061) 8 15>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xf>;
+ st,retime-control0 = <&SYSCFG_REAR(2140) 0 31>;
+ st,retime-control1 = <&SYSCFG_REAR(2141) 0 31>;
+ st,retime-control2 = <&SYSCFG_REAR(2142) 0 31>;
+ st,retime-control3 = <&SYSCFG_REAR(2143) 0 31>;
+ };
+ PIO100: pinctrl@fd6b0000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfd6b0000 0x100>;
+ st,bank-name = "PIO100";
+ st,alt-control = <&SYSCFG_FVDP_FE(5000) 0 31>;
+ st,oe-control = <&SYSCFG_FVDP_FE(5040) 0 7>;
+ st,pu-control = <&SYSCFG_FVDP_FE(5050) 0 7>;
+ st,od-control = <&SYSCFG_FVDP_FE(5060) 0 7>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FVDP_FE(5100) 0 31>;
+ st,retime-control1 = <&SYSCFG_FVDP_FE(5101) 0 31>;
+ st,retime-control2 = <&SYSCFG_FVDP_FE(5102) 0 31>;
+ st,retime-control3 = <&SYSCFG_FVDP_FE(5103) 0 31>;
+ st,retime-control4 = <&SYSCFG_FVDP_FE(5104) 0 31>;
+ st,retime-control5 = <&SYSCFG_FVDP_FE(5105) 0 31>;
+ st,retime-control6 = <&SYSCFG_FVDP_FE(5106) 0 31>;
+ st,retime-control7 = <&SYSCFG_FVDP_FE(5107) 0 31>;
+ };
+
+ PIO101: pinctrl@fd6b1000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfd6b1000 0x100>;
+ st,bank-name = "PIO101";
+ st,alt-control = <&SYSCFG_FVDP_FE(5001) 0 31>;
+ st,oe-control = <&SYSCFG_FVDP_FE(5040) 8 15>;
+ st,pu-control = <&SYSCFG_FVDP_FE(5050) 8 15>;
+ st,od-control = <&SYSCFG_FVDP_FE(5060) 8 15>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FVDP_FE(5108) 0 31>;
+ st,retime-control1 = <&SYSCFG_FVDP_FE(5109) 0 31>;
+ st,retime-control2 = <&SYSCFG_FVDP_FE(5110) 0 31>;
+ st,retime-control3 = <&SYSCFG_FVDP_FE(5111) 0 31>;
+ st,retime-control4 = <&SYSCFG_FVDP_FE(5112) 0 31>;
+ st,retime-control5 = <&SYSCFG_FVDP_FE(5113) 0 31>;
+ st,retime-control6 = <&SYSCFG_FVDP_FE(5114) 0 31>;
+ st,retime-control7 = <&SYSCFG_FVDP_FE(5115) 0 31>;
+ };
+
+ PIO102: pinctrl@fd6b2000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfd6b2000 0x100>;
+ st,bank-name = "PIO102";
+ st,alt-control = <&SYSCFG_FVDP_FE(5002) 0 31>;
+ st,oe-control = <&SYSCFG_FVDP_FE(5040) 16 23>;
+ st,pu-control = <&SYSCFG_FVDP_FE(5050) 16 23>;
+ st,od-control = <&SYSCFG_FVDP_FE(5060) 16 23>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FVDP_FE(5116) 0 31>;
+ st,retime-control1 = <&SYSCFG_FVDP_FE(5117) 0 31>;
+ st,retime-control2 = <&SYSCFG_FVDP_FE(5118) 0 31>;
+ st,retime-control3 = <&SYSCFG_FVDP_FE(5119) 0 31>;
+ st,retime-control4 = <&SYSCFG_FVDP_FE(5120) 0 31>;
+ st,retime-control5 = <&SYSCFG_FVDP_FE(5121) 0 31>;
+ st,retime-control6 = <&SYSCFG_FVDP_FE(5122) 0 31>;
+ st,retime-control7 = <&SYSCFG_FVDP_FE(5123) 0 31>;
+ };
+
+
+
+ PIO103: pinctrl@fd330000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfd330000 0x100>;
+ st,bank-name = "PIO103";
+ st,alt-control = <&SYSCFG_FVDP_LITE(6000) 0 31>;
+ st,oe-control = <&SYSCFG_FVDP_LITE(6040) 0 7>;
+ st,pu-control = <&SYSCFG_FVDP_LITE(6050) 0 7>;
+ st,od-control = <&SYSCFG_FVDP_LITE(6060) 0 7>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FVDP_LITE(6100) 0 31>;
+ st,retime-control1 = <&SYSCFG_FVDP_LITE(6101) 0 31>;
+ st,retime-control2 = <&SYSCFG_FVDP_LITE(6102) 0 31>;
+ st,retime-control3 = <&SYSCFG_FVDP_LITE(6103) 0 31>;
+ st,retime-control4 = <&SYSCFG_FVDP_LITE(6104) 0 31>;
+ st,retime-control5 = <&SYSCFG_FVDP_LITE(6105) 0 31>;
+ st,retime-control6 = <&SYSCFG_FVDP_LITE(6106) 0 31>;
+ st,retime-control7 = <&SYSCFG_FVDP_LITE(6107) 0 31>;
+ };
+ PIO104: pinctrl@fd331000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfd331000 0x100>;
+ st,bank-name = "PIO104";
+ st,alt-control = <&SYSCFG_FVDP_LITE(6001) 0 31>;
+ st,oe-control = <&SYSCFG_FVDP_LITE(6040) 8 15>;
+ st,pu-control = <&SYSCFG_FVDP_LITE(6050) 8 15>;
+ st,od-control = <&SYSCFG_FVDP_LITE(6060) 8 15>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FVDP_LITE(6108) 0 31>;
+ st,retime-control1 = <&SYSCFG_FVDP_LITE(6109) 0 31>;
+ st,retime-control2 = <&SYSCFG_FVDP_LITE(6110) 0 31>;
+ st,retime-control3 = <&SYSCFG_FVDP_LITE(6111) 0 31>;
+ st,retime-control4 = <&SYSCFG_FVDP_LITE(6112) 0 31>;
+ st,retime-control5 = <&SYSCFG_FVDP_LITE(6113) 0 31>;
+ st,retime-control6 = <&SYSCFG_FVDP_LITE(6114) 0 31>;
+ st,retime-control7 = <&SYSCFG_FVDP_LITE(6115) 0 31>;
+ };
+ PIO105: pinctrl@fd332000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfd332000 0x100>;
+ st,bank-name = "PIO105";
+ st,alt-control = <&SYSCFG_FVDP_LITE(6002) 0 31>;
+ st,oe-control = <&SYSCFG_FVDP_LITE(6040) 16 23>;
+ st,pu-control = <&SYSCFG_FVDP_LITE(6050) 16 23>;
+ st,od-control = <&SYSCFG_FVDP_LITE(6060) 16 23>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FVDP_LITE(6116) 0 31>;
+ st,retime-control1 = <&SYSCFG_FVDP_LITE(6117) 0 31>;
+ st,retime-control2 = <&SYSCFG_FVDP_LITE(6118) 0 31>;
+ st,retime-control3 = <&SYSCFG_FVDP_LITE(6119) 0 31>;
+ st,retime-control4 = <&SYSCFG_FVDP_LITE(6120) 0 31>;
+ st,retime-control5 = <&SYSCFG_FVDP_LITE(6121) 0 31>;
+ st,retime-control6 = <&SYSCFG_FVDP_LITE(6122) 0 31>;
+ st,retime-control7 = <&SYSCFG_FVDP_LITE(6123) 0 31>;
+ };
+ PIO106: pinctrl@fd333000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfd333000 0x100>;
+ st,bank-name = "PIO106";
+ st,alt-control = <&SYSCFG_FVDP_LITE(6003) 0 31>;
+ st,oe-control = <&SYSCFG_FVDP_LITE(6040) 24 31>;
+ st,pu-control = <&SYSCFG_FVDP_LITE(6050) 24 31>;
+ st,od-control = <&SYSCFG_FVDP_LITE(6060) 24 31>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCFG_FVDP_LITE(6124) 0 31>;
+ st,retime-control1 = <&SYSCFG_FVDP_LITE(6125) 0 31>;
+ st,retime-control2 = <&SYSCFG_FVDP_LITE(6126) 0 31>;
+ st,retime-control3 = <&SYSCFG_FVDP_LITE(6127) 0 31>;
+ st,retime-control4 = <&SYSCFG_FVDP_LITE(6128) 0 31>;
+ st,retime-control5 = <&SYSCFG_FVDP_LITE(6129) 0 31>;
+ st,retime-control6 = <&SYSCFG_FVDP_LITE(6130) 0 31>;
+ st,retime-control7 = <&SYSCFG_FVDP_LITE(6131) 0 31>;
+ };
+
+ PIO107: pinctrl@fd334000 {
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfd334000 0x100>;
+ st,bank-name = "PIO107";
+ st,alt-control = <&SYSCFG_FVDP_LITE(6004) 0 31>;
+ st,oe-control = <&SYSCFG_FVDP_LITE(6041) 0 7>;
+ st,pu-control = <&SYSCFG_FVDP_LITE(6051) 0 7>;
+ st,od-control = <&SYSCFG_FVDP_LITE(6061) 0 7>;
+ st,retime-style = "dedicated";
+ st,retime-pin-mask = <0xf>;
+ st,retime-control0 = <&SYSCFG_FVDP_LITE(6132) 0 31>;
+ st,retime-control1 = <&SYSCFG_FVDP_LITE(6133) 0 31>;
+ st,retime-control2 = <&SYSCFG_FVDP_LITE(6134) 0 31>;
+ st,retime-control3 = <&SYSCFG_FVDP_LITE(6135) 0 31>;
+ };
+
+ uart2 {
+ pinctrl_uart2: uart2-0 {
+ st,function = <ALT2>;
+ st,pins {
+ tx = <&PIO17 4 OUT>;
+ rx = <&PIO17 5 IN>;
+ output-enable = <&PIO11 3 OUT>;
+ };
+ };
+ };
+
+ sbc_uart1 {
+ pinctrl_sbc_uart1: sbc_uart1 {
+ st,function = <ALT3>;
+ st,pins {
+ tx = <&PIO2 6 OUT>;
+ rx = <&PIO2 7 IN>;
+ };
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/stih416.dtsi b/arch/arm/boot/dts/stih416.dtsi
new file mode 100644
index 0000000..47439b3
--- /dev/null
+++ b/arch/arm/boot/dts/stih416.dtsi
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2012 STMicroelectronics Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+#include "stih41x.dtsi"
+#include "stih416-clock.dtsi"
+#include "stih416-pinctrl.dtsi"
+/ {
+ L2: cache-controller {
+ compatible = "arm,pl310-cache";
+ reg = <0xfffe2000 0x1000>;
+ arm,data-latency = <3 3 3>;
+ arm,tag-latency = <2 2 2>;
+ cache-unified;
+ cache-level = <2>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&intc>;
+ ranges;
+ compatible = "simple-bus";
+
+ syscfg_sbc:syscon@fe600000{
+ compatible = "syscon";
+ reg = <0xfe600000 0x1000>;
+ syscon-name = "SYSCFG_SBC";
+ };
+ syscfg_front:syscon@fee10000{
+ compatible = "syscon";
+ reg = <0xfee10000 0x1000>;
+ syscon-name = "SYSCFG_FRONT";
+ };
+ syscfg_rear:syscon@fe830000{
+ compatible = "syscon";
+ reg = <0xfe830000 0x1000>;
+ syscon-name = "SYSCFG_REAR";
+ };
+
+ /* MPE */
+ syscfg_fvdp_fe:syscon@fddf0000{
+ compatible = "syscon";
+ reg = <0xfddf0000 0x1000>;
+ syscon-name = "SYSCFG_FVDP_FE";
+ };
+ syscfg_fvdp_lite:syscon@fd6a0000{
+ compatible = "syscon";
+ reg = <0xfd6a0000 0x1000>;
+ syscon-name = "SYSCFG_FVDP_LITE";
+ };
+
+ syscfg_cpu:syscon@fdde0000{
+ compatible = "syscon";
+ reg = <0xfdde0000 0x1000>;
+ syscon-name = "SYSCFG_CPU";
+ };
+
+ syscfg_compo:syscon@fd320000{
+ compatible = "syscon";
+ reg = <0xfd320000 0x1000>;
+ syscon-name = "SYSCFG_COMPO";
+ };
+
+ syscfg_transport:syscon@fd690000{
+ compatible = "syscon";
+ reg = <0xfd690000 0x1000>;
+ syscon-name = "SYSCFG_TRANSPORT";
+ };
+
+ syscfg_lpm:syscon@fe4b5100{
+ compatible = "syscon";
+ reg = <0xfe4b5100 0x54>;
+ syscon-name = "LPM_CFG_REGS";
+ };
+
+ uart2: uart@fed32000{
+ compatible = "st,asc";
+ status = "disabled";
+ reg = <0xfed32000 0x2c>;
+ interrupts = <0 197 0>;
+ clocks = <&CLK_S_ICN_REG_0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ };
+
+ /* SBC_UART1 */
+ sbc_uart1: uart@fe531000 {
+ compatible = "st,asc";
+ status = "disabled";
+ reg = <0xfe531000 0x2c>;
+ interrupts = <0 210 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sbc_uart1>;
+ clocks = <&CLK_SYSIN>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/stih416.h b/arch/arm/boot/dts/stih416.h
new file mode 100644
index 0000000..2e27792
--- /dev/null
+++ b/arch/arm/boot/dts/stih416.h
@@ -0,0 +1,24 @@
+#ifndef __STIH416_H_
+#define __STIH416_H_
+
+#define CONFIG_SBC(num) num
+#define CONFIG_FRONT(num) (num - 1000)
+#define CONFIG_REAR(num) (num - 2000)
+#define CONFIG_FVDP_FE(num) (num - 5000)
+#define CONFIG_FVDP_LITE(num) (num - 6000)
+#define CONFIG_CPU(num) (num - 7000)
+#define CONFIG_COMPO(num) (num - 8000)
+#define CONFIG_TRANSPORT(num) (num - 9000)
+#define CONFIG_LPM(num) num
+
+#define SYSCFG_SBC(num) syscfg_sbc CONFIG_SBC(num)
+#define SYSCFG_FRONT(num) syscfg_front CONFIG_FRONT(num)
+#define SYSCFG_REAR(num) syscfg_rear CONFIG_REAR(num)
+#define SYSCFG_FVDP_FE(num) syscfg_fvdp_fe CONFIG_FVDP_FE(num)
+#define SYSCFG_FVDP_LITE(num) syscfg_fvdp_lite CONFIG_FVDP_LITE(num)
+#define SYSCFG_CPU(num) syscfg_cpu CONFIG_CPU(num)
+#define SYSCFG_COMPO(num) syscfg_compo CONFIG_COMPO(num)
+#define SYSCFG_TRANSPORT(num) syscfg_transport CONFIG_TRANSPORT(num)
+#define SYSCFG_LPM(num) syscfg_lpm CONFIG_LPM(num)
+
+#endif /* __STIH416_H_ */
diff --git a/arch/arm/configs/stih41x_defconfig b/arch/arm/configs/stih41x_defconfig
index dd9268b..cc4e2dc 100644
--- a/arch/arm/configs/stih41x_defconfig
+++ b/arch/arm/configs/stih41x_defconfig
@@ -24,6 +24,7 @@ CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_BLK_DEV_INTEGRITY=y
CONFIG_ARCH_STIH41X=y
CONFIG_SOC_STIH415=y
+CONFIG_SOC_STIH416=y
# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
# CONFIG_SWP_EMULATE is not set
CONFIG_ARM_ERRATA_720789=y
diff --git a/arch/arm/mach-stih41x/Kconfig b/arch/arm/mach-stih41x/Kconfig
index 9c40540..848d3e8 100644
--- a/arch/arm/mach-stih41x/Kconfig
+++ b/arch/arm/mach-stih41x/Kconfig
@@ -31,5 +31,14 @@ config SOC_STIH415
and other digital audio/video applications using Flattned Device
Trees.
+config SOC_STIH416
+ bool "STiH416 STMicroelectronics Consumer Electronics family"
+ select PLAT_STIXXXX
+ help
+ This enables support for STMicroelectronics Digital Consumer
+ Electronics family StiH416 parts, primarily targetted at set-top-box
+ and other digital audio/video applications using Flattened Device
+ Trees.
+
endmenu
endif
diff --git a/arch/arm/mach-stih41x/board-dt.c b/arch/arm/mach-stih41x/board-dt.c
index c51e2c9..8005f71 100644
--- a/arch/arm/mach-stih41x/board-dt.c
+++ b/arch/arm/mach-stih41x/board-dt.c
@@ -66,7 +66,7 @@ static const char *stih41x_dt_match[] __initdata = {
NULL
};
-DT_MACHINE_START(STM, "STiH415 SoC with Flattened Device Tree")
+DT_MACHINE_START(STM, "STiH415/416 SoC with Flattened Device Tree")
.map_io = stih41x_map_io,
.init_time = stih41x_timer_init,
.init_machine = stih41x_dt_init,
--
1.7.6.5
^ permalink raw reply related [flat|nested] 79+ messages in thread
[parent not found: <1368022187-1633-1-git-send-email-srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>]
* [RFC 1/8] serial:st-asc: Add ST ASC driver.
[not found] ` <1368022187-1633-1-git-send-email-srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
@ 2013-05-08 14:10 ` Srinivas KANDAGATLA
2013-05-08 14:34 ` Arnd Bergmann
2013-05-08 14:11 ` [RFC 4/8] pinctrl:stixxxx: Add pinctrl and pinconf support Srinivas KANDAGATLA
2013-05-08 14:12 ` [RFC 7/8] ARM:stih41x: Add B2000 board support Srinivas KANDAGATLA
2 siblings, 1 reply; 79+ messages in thread
From: Srinivas KANDAGATLA @ 2013-05-08 14:10 UTC (permalink / raw)
To: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, jslaby-AlSwsSmVLrQ
Cc: Srinivas Kandagatla, Viresh Kumar, Will Deacon, Russell King,
Samuel Ortiz, Nicolas Pitre, linux-doc-u79uwXL29TY76Z2rM5mHXA,
Stephen Gallimore, linux-serial-u79uwXL29TY76Z2rM5mHXA,
Jason Cooper, devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
Rob Herring, Stuart Menefy, Stephen Warren, Dong Aisheng,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Mark Brown,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
This patch adds support to ASC (asynchronous serial controller)
driver, which is basically a standard serial driver. This IP is common
across all the ST parts for settop box platforms.
ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
It support all industry standard baud rates.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
CC: Stephen Gallimore <stephen.gallimore-qxv4g6HH51o@public.gmane.org>
CC: Stuart Menefy <stuart.menefy-qxv4g6HH51o@public.gmane.org>
---
.../devicetree/bindings/tty/serial/st-asc.txt | 18 +
drivers/tty/serial/Kconfig | 19 +
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/st-asc.c | 821 ++++++++++++++++++++
drivers/tty/serial/st-asc.h | 146 ++++
include/uapi/linux/serial_core.h | 3 +
6 files changed, 1008 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/tty/serial/st-asc.txt
create mode 100644 drivers/tty/serial/st-asc.c
create mode 100644 drivers/tty/serial/st-asc.h
diff --git a/Documentation/devicetree/bindings/tty/serial/st-asc.txt b/Documentation/devicetree/bindings/tty/serial/st-asc.txt
new file mode 100644
index 0000000..75d877f
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/st-asc.txt
@@ -0,0 +1,18 @@
+*st-asc(Serial Port)
+
+Required properties:
+- compatible : Should be "st,asc".
+- reg, reg-names, interrupts, interrupt-names : Standard way to define device
+ resources with names. look in
+ Documentation/devicetree/bindings/resource-names.txt
+
+Optional properties:
+- st,hw-flow-ctrl bool flag to enable hardware flow control.
+- st,force-m1 bool flat to force asc to be in Mode-1 recommeded
+ for high bit rates (above 19.2K)
+Example:
+serial@fe440000{
+ compatible = "st,asc";
+ reg = <0xfe440000 0x2c>;
+ interrupts = <0 209 0>;
+};
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 7e7006f..346f325 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1484,6 +1484,25 @@ config SERIAL_RP2_NR_UARTS
If multiple cards are present, the default limit of 32 ports may
need to be increased.
+config SERIAL_ST_ASC
+ tristate "ST ASC serial port support"
+ depends on PLAT_STIXXXX
+ default y
+ select SERIAL_CORE
+ help
+ This driver is for the on-chip Asychronous Serial Controller on
+ STMicroelectronics STixxxx SoCs.
+ ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
+ It support all industry standard baud rates.
+
+ If unsure, say N.
+
+config SERIAL_ST_ASC_CONSOLE
+ bool "Support for console on ST ASC"
+ depends on SERIAL_ST_ASC
+ default y
+ select SERIAL_CORE_CONSOLE
+
endmenu
endif # TTY
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index eedfec4..536ccc7 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o
obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
+obj-$(CONFIG_SERIAL_ST_ASC) += st-asc.o
obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
new file mode 100644
index 0000000..2acc597
--- /dev/null
+++ b/drivers/tty/serial/st-asc.c
@@ -0,0 +1,821 @@
+/*
+ * st-asc.c: ST Asynchronous serial controller (ASC) driver
+ *
+ * Copyright (C) 2003-2013 STMicroelectronics (R&D) Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#if defined(CONFIG_SERIAL_ST_ASC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+#include "st-asc.h"
+
+#define DRIVER_NAME "st-asc"
+#define ASC_SERIAL_NAME "ttyAS"
+
+static struct asc_port asc_ports[ASC_MAX_PORTS];
+static struct uart_driver asc_uart_driver;
+
+/*---- Forward function declarations---------------------------*/
+static irqreturn_t asc_interrupt(int irq, void *ptr);
+static void asc_transmit_chars(struct uart_port *);
+static int asc_set_baud(struct asc_port *ascport, int baud);
+
+/*---- Inline function definitions ---------------------------*/
+
+static inline struct asc_port *to_asc_port(struct uart_port *port)
+{
+ return container_of(port, struct asc_port, port);
+}
+
+static inline u32 asc_in(struct uart_port *port, u32 offset)
+{
+ return readl(port->membase + offset);
+}
+
+static inline void asc_out(struct uart_port *port, u32 offset, u32 value)
+{
+ writel(value, port->membase + offset);
+}
+
+/*
+ * Some simple utility functions to enable and disable interrupts.
+ * Note that these need to be called with interrupts disabled.
+ */
+static inline void asc_disable_tx_interrupts(struct uart_port *port)
+{
+ u32 intenable = asc_in(port, ASC_INTEN) & ~ASC_INTEN_THE;
+ asc_out(port, ASC_INTEN, intenable);
+ (void)asc_in(port, ASC_INTEN); /* Defeat bus write posting */
+}
+
+static inline void asc_enable_tx_interrupts(struct uart_port *port)
+{
+ u32 intenable = asc_in(port, ASC_INTEN) | ASC_INTEN_THE;
+ asc_out(port, ASC_INTEN, intenable);
+}
+
+static inline void asc_disable_rx_interrupts(struct uart_port *port)
+{
+ u32 intenable = asc_in(port, ASC_INTEN) & ~ASC_INTEN_RBE;
+ asc_out(port, ASC_INTEN, intenable);
+ (void)asc_in(port, ASC_INTEN); /* Defeat bus write posting */
+}
+
+static inline void asc_enable_rx_interrupts(struct uart_port *port)
+{
+ u32 intenable = asc_in(port, ASC_INTEN) | ASC_INTEN_RBE;
+ asc_out(port, ASC_INTEN, intenable);
+}
+
+static inline u32 asc_txfifo_is_empty(struct uart_port *port)
+{
+ return asc_in(port, ASC_STA) & ASC_STA_TE;
+}
+
+static inline int asc_txfifo_is_full(struct uart_port *port)
+{
+ return asc_in(port, ASC_STA) & ASC_STA_TF;
+}
+
+static const char *asc_port_name(struct uart_port *port)
+{
+ return to_platform_device(port->dev)->name;
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * UART Functions
+ */
+
+static unsigned int asc_tx_empty(struct uart_port *port)
+{
+ return asc_txfifo_is_empty(port) ? TIOCSER_TEMT : 0;
+}
+
+static void asc_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ /*
+ * This routine is used for seting signals of: DTR, DCD, CTS/RTS
+ * We use ASC's hardware for CTS/RTS, so don't need any for that.
+ * Some boards have DTR and DCD implemented using PIO pins,
+ * code to do this should be hooked in here.
+ */
+}
+
+static unsigned int asc_get_mctrl(struct uart_port *port)
+{
+ /*
+ * This routine is used for geting signals of: DTR, DCD, DSR, RI,
+ * and CTS/RTS
+ */
+ return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+/* There are probably characters waiting to be transmitted. */
+static void asc_start_tx(struct uart_port *port)
+{
+ struct circ_buf *xmit = &port->state->xmit;
+
+ if (!uart_circ_empty(xmit))
+ asc_enable_tx_interrupts(port);
+}
+
+/* Transmit stop */
+static void asc_stop_tx(struct uart_port *port)
+{
+ asc_disable_tx_interrupts(port);
+}
+
+/* Receive stop */
+static void asc_stop_rx(struct uart_port *port)
+{
+ asc_disable_rx_interrupts(port);
+}
+
+/* Force modem status interrupts on */
+static void asc_enable_ms(struct uart_port *port)
+{
+ /* Nothing here yet .. */
+}
+
+/* Handle breaks - ignored by us */
+static void asc_break_ctl(struct uart_port *port, int break_state)
+{
+ /* Nothing here yet .. */
+}
+
+/*
+ * Enable port for reception.
+ */
+static int asc_startup(struct uart_port *port)
+{
+ if (request_irq(port->irq, asc_interrupt, 0,
+ asc_port_name(port), port)) {
+ dev_err(port->dev, "cannot allocate irq.\n");
+ return -ENODEV;
+ }
+
+ asc_transmit_chars(port);
+ asc_enable_rx_interrupts(port);
+
+ return 0;
+}
+
+static void asc_shutdown(struct uart_port *port)
+{
+ asc_disable_tx_interrupts(port);
+ asc_disable_rx_interrupts(port);
+ free_irq(port->irq, port);
+}
+
+static void asc_pm(struct uart_port *port, unsigned int state,
+ unsigned int oldstate)
+{
+ struct asc_port *ascport = to_asc_port(port);
+ unsigned long flags = 0;
+ u32 ctl;
+
+ switch (state) {
+ case UART_PM_STATE_ON:
+ clk_prepare_enable(ascport->clk);
+ break;
+ case UART_PM_STATE_OFF:
+ /*
+ * Disable the ASC baud rate generator, which is as close as
+ * we can come to turning it off. Note this is not called with
+ * the port spinlock held.
+ */
+ spin_lock_irqsave(&port->lock, flags);
+ ctl = asc_in(port, ASC_CTL) & ~ASC_CTL_RUN;
+ asc_out(port, ASC_CTL, ctl);
+ spin_unlock_irqrestore(&port->lock, flags);
+ clk_disable_unprepare(ascport->clk);
+ break;
+ }
+}
+
+static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
+{
+ struct asc_port *ascport = to_asc_port(port);
+ unsigned int baud;
+ u32 ctrl_val;
+ tcflag_t cflag;
+ unsigned long flags;
+
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+ cflag = termios->c_cflag;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* read control register */
+ ctrl_val = asc_in(port, ASC_CTL);
+
+ /* stop serial port and reset value */
+ asc_out(port, ASC_CTL, (ctrl_val & ~ASC_CTL_RUN));
+ ctrl_val = ASC_CTL_RXENABLE | ASC_CTL_FIFOENABLE;
+
+ /* reset fifo rx & tx */
+ asc_out(port, ASC_TXRESET, 1);
+ asc_out(port, ASC_RXRESET, 1);
+
+ /* set character length */
+ if ((cflag & CSIZE) == CS7) {
+ ctrl_val |= ASC_CTL_MODE_7BIT_PAR;
+ } else {
+ if (cflag & PARENB)
+ ctrl_val |= ASC_CTL_MODE_8BIT_PAR;
+ else
+ ctrl_val |= ASC_CTL_MODE_8BIT;
+ }
+
+ ascport->check_parity = (cflag & PARENB) ? 1 : 0;
+
+ /* set stop bit */
+ if (cflag & CSTOPB)
+ ctrl_val |= ASC_CTL_STOP_2BIT;
+ else
+ ctrl_val |= ASC_CTL_STOP_1BIT;
+
+ /* odd parity */
+ if (cflag & PARODD)
+ ctrl_val |= ASC_CTL_PARITYODD;
+
+ /* hardware flow control */
+ if ((cflag & CRTSCTS) && ascport->hw_flow_control)
+ ctrl_val |= ASC_CTL_CTSENABLE;
+
+ ctrl_val |= asc_set_baud(ascport, baud);
+ uart_update_timeout(port, cflag, baud);
+
+ /* Set the timeout */
+ asc_out(port, ASC_TIMEOUT, 20);
+
+ /* write final value and enable port */
+ asc_out(port, ASC_CTL, (ctrl_val | ASC_CTL_RUN));
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *asc_type(struct uart_port *port)
+{
+ return (port->type == PORT_ASC) ? DRIVER_NAME : NULL;
+}
+
+static void asc_release_port(struct uart_port *port)
+{
+}
+
+static int asc_request_port(struct uart_port *port)
+{
+ return 0;
+}
+
+/*
+ * Called when the port is opened, and UPF_BOOT_AUTOCONF flag is set
+ * Set type field if successful
+ */
+static void asc_config_port(struct uart_port *port, int flags)
+{
+ if ((flags & UART_CONFIG_TYPE))
+ port->type = PORT_ASC;
+}
+
+static int
+asc_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ /* No user changeable parameters */
+ return -EINVAL;
+}
+
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Console polling routines for writing and reading from the uart while
+ * in an interrupt or debug context (i.e. kgdb).
+ */
+
+static int asc_get_poll_char(struct uart_port *port)
+{
+ if (!(asc_in(port, ASC_STA) & ASC_STA_RBF))
+ return NO_POLL_CHAR;
+
+ return asc_in(port, ASC_RXBUF);
+}
+
+static void asc_put_poll_char(struct uart_port *port, unsigned char c)
+{
+ while (asc_txfifo_is_full(port))
+ cpu_relax();
+ asc_out(port, ASC_TXBUF, c);
+}
+
+#endif /* CONFIG_CONSOLE_POLL */
+
+/*---------------------------------------------------------------------*/
+
+static struct uart_ops asc_uart_ops = {
+ .tx_empty = asc_tx_empty,
+ .set_mctrl = asc_set_mctrl,
+ .get_mctrl = asc_get_mctrl,
+ .start_tx = asc_start_tx,
+ .stop_tx = asc_stop_tx,
+ .stop_rx = asc_stop_rx,
+ .enable_ms = asc_enable_ms,
+ .break_ctl = asc_break_ctl,
+ .startup = asc_startup,
+ .shutdown = asc_shutdown,
+ .set_termios = asc_set_termios,
+ .type = asc_type,
+ .release_port = asc_release_port,
+ .request_port = asc_request_port,
+ .config_port = asc_config_port,
+ .verify_port = asc_verify_port,
+ .pm = asc_pm,
+#ifdef CONFIG_CONSOLE_POLL
+ .poll_get_char = asc_get_poll_char,
+ .poll_put_char = asc_put_poll_char,
+#endif /* CONFIG_CONSOLE_POLL */
+};
+
+static int asc_init_port(struct asc_port *ascport,
+ struct platform_device *pdev)
+{
+ struct uart_port *port = &ascport->port;
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!res) {
+ dev_err(&pdev->dev, "Unable to get io resource\n");
+ return -ENODEV;
+ }
+
+ port->iotype = UPIO_MEM;
+ port->flags = UPF_BOOT_AUTOCONF;
+ port->ops = &asc_uart_ops;
+ port->fifosize = ASC_FIFO_SIZE;
+ port->dev = &pdev->dev;
+ port->mapbase = res->start;
+ port->irq = platform_get_irq(pdev, 0);
+
+ port->membase = devm_request_and_ioremap(&pdev->dev, res);
+ if (!port->membase) {
+ dev_err(&pdev->dev, "Unable to request io memory\n");
+ return -ENODEV;
+ }
+
+ spin_lock_init(&port->lock);
+
+ ascport->clk = devm_clk_get(&pdev->dev, NULL);
+
+ if (WARN_ON(IS_ERR(ascport->clk)))
+ return -EINVAL;
+ /* ensure that clk rate is correct by enabling the clk */
+ clk_prepare_enable(ascport->clk);
+ ascport->port.uartclk = clk_get_rate(ascport->clk);
+ WARN_ON(ascport->port.uartclk == 0);
+ clk_disable_unprepare(ascport->clk);
+
+ return 0;
+}
+
+static struct asc_port *asc_of_get_asc_port(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int id;
+
+ if (!np)
+ return NULL;
+
+ id = of_alias_get_id(np, ASC_SERIAL_NAME);
+ if (WARN_ON(id >= ASC_MAX_PORTS))
+ return NULL;
+
+ asc_ports[id].hw_flow_control = of_property_read_bool(np,
+ "st,hw-flow-control");
+ asc_ports[id].force_m1 = of_property_read_bool(np, "st,force_m1");
+ asc_ports[id].port.line = id;
+ return &asc_ports[id];
+}
+
+static struct of_device_id asc_match[] = {
+ { .compatible = "st,asc", },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, asc_match);
+
+static int asc_serial_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct asc_port *ascport;
+
+ ascport = asc_of_get_asc_port(pdev);
+ if (!ascport)
+ return -ENODEV;
+
+ ret = asc_init_port(ascport, pdev);
+ if (ret)
+ return ret;
+
+ ret = uart_add_one_port(&asc_uart_driver, &ascport->port);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, &ascport->port);
+
+ return 0;
+}
+
+static int asc_serial_remove(struct platform_device *pdev)
+{
+ struct uart_port *port = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+ return uart_remove_one_port(&asc_uart_driver, port);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int asc_serial_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct uart_port *port = platform_get_drvdata(pdev);
+
+ return uart_suspend_port(&asc_uart_driver, port);
+}
+
+static int asc_serial_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct uart_port *port = platform_get_drvdata(pdev);
+
+ if (pdev->dev.pins->default_state) {
+ if (pinctrl_select_state(pdev->dev.pins->p,
+ pdev->dev.pins->default_state) < 0)
+ return -EBUSY;
+ }
+
+ return uart_resume_port(&asc_uart_driver, port);
+}
+
+#endif /* CONFIG_PM_SLEEP */
+
+/*----------------------------------------------------------------------*/
+
+/* This sections contains code to support the use of the ASC as a
+ * generic serial port.
+ */
+
+static int asc_set_baud(struct asc_port *ascport, int baud)
+{
+ struct uart_port *port = &ascport->port;
+ unsigned long rate = clk_get_rate(ascport->clk);
+ u32 t;
+
+ if ((baud < 19200) && !ascport->force_m1) {
+ t = BAUDRATE_VAL_M0(baud, rate);
+ asc_out(port, ASC_BAUDRATE, t);
+ return 0;
+ } else {
+ t = BAUDRATE_VAL_M1(baud, rate);
+ asc_out(port, ASC_BAUDRATE, t);
+ return ASC_CTL_BAUDMODE;
+ }
+}
+
+static inline unsigned asc_hw_txroom(struct uart_port *port)
+{
+ u32 status = asc_in(port, ASC_STA);
+
+ if (status & ASC_STA_THE)
+ return port->fifosize / 2;
+ else if (!(status & ASC_STA_TF))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Start transmitting chars.
+ * This is called from both interrupt and task level.
+ * Either way interrupts are disabled.
+ */
+static void asc_transmit_chars(struct uart_port *port)
+{
+ struct circ_buf *xmit = &port->state->xmit;
+ int txroom;
+ unsigned char c;
+
+ txroom = asc_hw_txroom(port);
+
+ if ((txroom != 0) && port->x_char) {
+ c = port->x_char;
+ port->x_char = 0;
+ asc_out(port, ASC_TXBUF, c);
+ port->icount.tx++;
+ txroom = asc_hw_txroom(port);
+ }
+
+ if (uart_tx_stopped(port)) {
+ /*
+ * We should try and stop the hardware here, but I
+ * don't think the ASC has any way to do that.
+ */
+ asc_disable_tx_interrupts(port);
+ return;
+ }
+
+ if (uart_circ_empty(xmit)) {
+ asc_disable_tx_interrupts(port);
+ return;
+ }
+
+ if (txroom == 0)
+ return;
+
+ do {
+ c = xmit->buf[xmit->tail];
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ asc_out(port, ASC_TXBUF, c);
+ port->icount.tx++;
+ txroom--;
+ } while ((txroom > 0) && (!uart_circ_empty(xmit)));
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (uart_circ_empty(xmit))
+ asc_disable_tx_interrupts(port);
+}
+
+static void asc_receive_chars(struct uart_port *port)
+{
+ int count;
+ struct asc_port *ascport = to_asc_port(port);
+ struct tty_port *tport = &port->state->port;
+ int copied = 0;
+ unsigned long status;
+ unsigned long c = 0;
+ char flag;
+ int overrun;
+
+ if (port->irq_wake)
+ pm_wakeup_event(tport->tty->dev, 0);
+
+ while (1) {
+ status = asc_in(port, ASC_STA);
+ if (status & ASC_STA_RHF)
+ count = port->fifosize / 2;
+ else if (status & ASC_STA_RBF)
+ count = 1;
+ else
+ break;
+
+ /*
+ * Check for overrun before reading any data from the
+ * RX FIFO, as this clears the overflow error condition.
+ */
+ overrun = status & ASC_STA_OE;
+
+ for (; count != 0; count--) {
+ c = asc_in(port, ASC_RXBUF);
+ flag = TTY_NORMAL;
+ port->icount.rx++;
+
+ if (unlikely(c & ASC_RXBUF_FE)) {
+ if (c == ASC_RXBUF_FE) {
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ continue;
+ flag = TTY_BREAK;
+ } else {
+ port->icount.frame++;
+ flag = TTY_FRAME;
+ }
+ } else if (ascport->check_parity &&
+ unlikely(c & ASC_RXBUF_PE)) {
+ port->icount.parity++;
+ flag = TTY_PARITY;
+ }
+
+ if (uart_handle_sysrq_char(port, c))
+ continue;
+ tty_insert_flip_char(tport, c & 0xff, flag);
+ }
+ if (overrun) {
+ port->icount.overrun++;
+ tty_insert_flip_char(tport, 0, TTY_OVERRUN);
+ }
+
+ copied = 1;
+ }
+
+ if (copied) {
+ /* Tell the rest of the system the news. New characters! */
+ tty_flip_buffer_push(tport);
+ }
+}
+
+static irqreturn_t asc_interrupt(int irq, void *ptr)
+{
+ struct uart_port *port = ptr;
+ u32 status;
+
+ spin_lock(&port->lock);
+
+ status = asc_in(port, ASC_STA);
+
+ if (status & ASC_STA_RBF) {
+ /* Receive FIFO not empty */
+ asc_receive_chars(port);
+ }
+
+ if ((status & ASC_STA_THE) &&
+ (asc_in(port, ASC_INTEN) & ASC_INTEN_THE)) {
+ /* Transmitter FIFO at least half empty */
+ asc_transmit_chars(port);
+ }
+
+ spin_unlock(&port->lock);
+
+ return IRQ_HANDLED;
+}
+
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_SERIAL_ST_ASC_CONSOLE
+static void asc_console_putchar(struct uart_port *port, int ch)
+{
+ unsigned int timeout = 1000000;
+
+ /* Wait for upto 1 second in case flow control is stopping us. */
+ while (--timeout && asc_txfifo_is_full(port))
+ udelay(1);
+
+ asc_out(port, ASC_TXBUF, ch);
+}
+
+/*
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
+ */
+
+static void asc_console_write(struct console *co, const char *s, unsigned count)
+{
+ struct uart_port *port = &asc_ports[co->index].port;
+ unsigned long flags;
+ unsigned long timeout = 1000000;
+ int locked = 1;
+ u32 intenable;
+
+ local_irq_save(flags);
+ if (port->sysrq)
+ locked = 0; /* asc_interrupt has already claimed the lock */
+ else if (oops_in_progress)
+ locked = spin_trylock(&port->lock);
+ else
+ spin_lock(&port->lock);
+
+ /*
+ * Disable interrupts so we don't get the IRQ line bouncing
+ * up and down while interrupts are disabled.
+ */
+ intenable = asc_in(port, ASC_INTEN);
+ asc_out(port, ASC_INTEN, 0);
+ (void)asc_in(port, ASC_INTEN); /* Defeat bus write posting */
+
+ uart_console_write(port, s, count, asc_console_putchar);
+
+ while (--timeout && !asc_txfifo_is_empty(port))
+ udelay(1);
+
+ asc_out(port, ASC_INTEN, intenable);
+
+ if (locked)
+ spin_unlock(&port->lock);
+ local_irq_restore(flags);
+}
+
+static int asc_console_setup(struct console *co, char *options)
+{
+ struct asc_port *ascport;
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if (co->index >= ASC_MAX_PORTS)
+ return -ENODEV;
+
+ ascport = &asc_ports[co->index];
+
+ /*
+ * This driver does not support early console initialization
+ * (use ARM early printk support instead), so we only expect
+ * this to be called during the uart port registration when the
+ * driver gets probed and the port should be mapped at that point.
+ */
+ BUG_ON(ascport->port.mapbase == 0 || ascport->port.membase == NULL);
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(&ascport->port, co, baud, parity, bits, flow);
+}
+
+static struct console asc_console = {
+ .name = ASC_SERIAL_NAME,
+ .device = uart_console_device,
+ .write = asc_console_write,
+ .setup = asc_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &asc_uart_driver,
+};
+
+#define ASC_SERIAL_CONSOLE (&asc_console)
+
+#else
+#define ASC_SERIAL_CONSOLE NULL
+#endif /* CONFIG_SERIAL_ST_ASC_CONSOLE */
+
+
+static struct uart_driver asc_uart_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = DRIVER_NAME,
+ .dev_name = ASC_SERIAL_NAME,
+ .major = ASC_MAJOR,
+ .minor = ASC_MINOR_START,
+ .nr = ASC_MAX_PORTS,
+ .cons = ASC_SERIAL_CONSOLE,
+};
+
+static const struct dev_pm_ops asc_serial_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(asc_serial_suspend, asc_serial_resume)
+};
+
+
+static struct platform_driver asc_serial_driver = {
+ .probe = asc_serial_probe,
+ .remove = asc_serial_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .pm = &asc_serial_pm_ops,
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(asc_match),
+ },
+};
+
+static int __init asc_init(void)
+{
+ int ret;
+ static char banner[] __initdata =
+ KERN_INFO "STMicroelectronics ASC driver initialized\n";
+
+ printk(banner);
+
+ ret = uart_register_driver(&asc_uart_driver);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&asc_serial_driver);
+ if (ret)
+ uart_unregister_driver(&asc_uart_driver);
+
+ return ret;
+}
+
+static void __exit asc_exit(void)
+{
+ platform_driver_unregister(&asc_serial_driver);
+ uart_unregister_driver(&asc_uart_driver);
+}
+
+module_init(asc_init);
+module_exit(asc_exit);
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("STMicroelectronics (R&D) Limited");
+MODULE_DESCRIPTION("STMicroelectronics ASC serial port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/st-asc.h b/drivers/tty/serial/st-asc.h
new file mode 100644
index 0000000..e59f818
--- /dev/null
+++ b/drivers/tty/serial/st-asc.h
@@ -0,0 +1,146 @@
+/*
+ * st-asc.h: ST Asynchronous serial controller (ASC) driver
+ *
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#ifndef _ST_ASC_H
+#define _ST_ASC_H
+
+#include <linux/serial_core.h>
+#include <linux/clk.h>
+
+struct asc_port {
+ struct uart_port port;
+ struct clk *clk;
+ unsigned int hw_flow_control:1;
+ unsigned int check_parity:1;
+ unsigned int force_m1:1;
+};
+
+#define ASC_MAJOR 204
+#define ASC_MINOR_START 40
+
+#define ASC_FIFO_SIZE 16
+
+#define ASC_MAX_PORTS 8
+
+/*---- UART Register definitions ------------------------------*/
+
+/* Register offsets */
+
+#define ASC_BAUDRATE 0x00
+#define ASC_TXBUF 0x04
+#define ASC_RXBUF 0x08
+#define ASC_CTL 0x0C
+#define ASC_INTEN 0x10
+#define ASC_STA 0x14
+#define ASC_GUARDTIME 0x18
+#define ASC_TIMEOUT 0x1C
+#define ASC_TXRESET 0x20
+#define ASC_RXRESET 0x24
+#define ASC_RETRIES 0x28
+
+/* ASC_RXBUF */
+#define ASC_RXBUF_PE 0x100
+#define ASC_RXBUF_FE 0x200
+
+/* ASC_CTL */
+
+#define ASC_CTL_MODE_MSK 0x0007
+#define ASC_CTL_MODE_8BIT 0x0001
+#define ASC_CTL_MODE_7BIT_PAR 0x0003
+#define ASC_CTL_MODE_9BIT 0x0004
+#define ASC_CTL_MODE_8BIT_WKUP 0x0005
+#define ASC_CTL_MODE_8BIT_PAR 0x0007
+#define ASC_CTL_STOP_MSK 0x0018
+#define ASC_CTL_STOP_HALFBIT 0x0000
+#define ASC_CTL_STOP_1BIT 0x0008
+#define ASC_CTL_STOP_1_HALFBIT 0x0010
+#define ASC_CTL_STOP_2BIT 0x0018
+#define ASC_CTL_PARITYODD 0x0020
+#define ASC_CTL_LOOPBACK 0x0040
+#define ASC_CTL_RUN 0x0080
+#define ASC_CTL_RXENABLE 0x0100
+#define ASC_CTL_SCENABLE 0x0200
+#define ASC_CTL_FIFOENABLE 0x0400
+#define ASC_CTL_CTSENABLE 0x0800
+#define ASC_CTL_BAUDMODE 0x1000
+
+/* ASC_GUARDTIME */
+
+#define ASC_GUARDTIME_MSK 0x00FF
+
+/* ASC_INTEN */
+
+#define ASC_INTEN_RBE 0x0001
+#define ASC_INTEN_TE 0x0002
+#define ASC_INTEN_THE 0x0004
+#define ASC_INTEN_PE 0x0008
+#define ASC_INTEN_FE 0x0010
+#define ASC_INTEN_OE 0x0020
+#define ASC_INTEN_TNE 0x0040
+#define ASC_INTEN_TOI 0x0080
+#define ASC_INTEN_RHF 0x0100
+
+/* ASC_RETRIES */
+
+#define ASC_RETRIES_MSK 0x00FF
+
+/* ASC_RXBUF */
+
+#define ASC_RXBUF_MSK 0x03FF
+
+/* ASC_STA */
+
+#define ASC_STA_RBF 0x0001
+#define ASC_STA_TE 0x0002
+#define ASC_STA_THE 0x0004
+#define ASC_STA_PE 0x0008
+#define ASC_STA_FE 0x0010
+#define ASC_STA_OE 0x0020
+#define ASC_STA_TNE 0x0040
+#define ASC_STA_TOI 0x0080
+#define ASC_STA_RHF 0x0100
+#define ASC_STA_TF 0x0200
+#define ASC_STA_NKD 0x0400
+
+/* ASC_TIMEOUT */
+
+#define ASC_TIMEOUT_MSK 0x00FF
+
+/* ASC_TXBUF */
+
+#define ASC_TXBUF_MSK 0x01FF
+
+/*---- Values for the BAUDRATE Register -----------------------*/
+
+/*
+ * MODE 0
+ * recommended for low bit rates (below 19.2K)
+ *
+ * ICCLK
+ * ASCBaudRate = ----------------
+ * baudrate * 16
+ *
+ * MODE 1
+ * recommended for high bit rates (above 19.2K)
+ *
+ * baudrate * 16 * 2^16
+ * ASCBaudRate = ------------------------
+ * ICCLK
+ */
+
+#define ADJ 1
+#define BAUDRATE_VAL_M0(bps, clk) \
+ ((clk) / (16 * (bps)))
+#define BAUDRATE_VAL_M1(bps, clk) \
+ (((bps * (1 << 14)) / ((clk) / (1 << 6))) + ADJ)
+
+#endif /* _ST_ASC_H */
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 74c2bf7..ec80e01 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -226,4 +226,7 @@
/* Rocketport EXPRESS/INFINITY */
#define PORT_RP2 102
+/* ST ASC type numbers */
+#define PORT_ASC 103
+
#endif /* _UAPILINUX_SERIAL_CORE_H */
--
1.7.6.5
^ permalink raw reply related [flat|nested] 79+ messages in thread
* Re: [RFC 1/8] serial:st-asc: Add ST ASC driver.
2013-05-08 14:10 ` [RFC 1/8] serial:st-asc: Add ST ASC driver Srinivas KANDAGATLA
@ 2013-05-08 14:34 ` Arnd Bergmann
2013-05-08 14:39 ` Jean-Christophe PLAGNIOL-VILLARD
` (3 more replies)
0 siblings, 4 replies; 79+ messages in thread
From: Arnd Bergmann @ 2013-05-08 14:34 UTC (permalink / raw)
To: Srinivas KANDAGATLA
Cc: Dave Martin, linux-doc, Viresh Kumar, Linus Walleij, Will Deacon,
Grant Likely, jslaby, Russell King, Samuel Ortiz, Nicolas Pitre,
Stephen Gallimore, linux-serial, Jason Cooper, Marc Zyngier,
devicetree-discuss, Rob Herring, Stuart Menefy, Stephen Warren,
Dong Aisheng, linux-arm-kernel, gregkh, Mark Brown, linux-kernel,
Rob Landley
On Wednesday 08 May 2013, Srinivas KANDAGATLA wrote:
> From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
> +*st-asc(Serial Port)
> +
> +Required properties:
> +- compatible : Should be "st,asc".
Are there any hardware revision numbers for the asc? If there are potentially
incompatible or backwards-compatible variants, it would be good to include
the version in this string.
> +- reg, reg-names, interrupts, interrupt-names : Standard way to define device
> + resources with names. look in
> + Documentation/devicetree/bindings/resource-names.txt
> +
> +Optional properties:
> +- st,hw-flow-ctrl bool flag to enable hardware flow control.
> +- st,force-m1 bool flat to force asc to be in Mode-1 recommeded
> + for high bit rates (above 19.2K)
> +Example:
> +serial@fe440000{
> + compatible = "st,asc";
> + reg = <0xfe440000 0x2c>;
> + interrupts = <0 209 0>;
> +};
I would also recommed adding a way to set the default baud rate through
a property. Following the example of the 8250 driver, you should probably
call that "current-speed".
> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> index 7e7006f..346f325 100644
> --- a/drivers/tty/serial/Kconfig
> +++ b/drivers/tty/serial/Kconfig
> @@ -1484,6 +1484,25 @@ config SERIAL_RP2_NR_UARTS
> If multiple cards are present, the default limit of 32 ports may
> need to be increased.
>
> +config SERIAL_ST_ASC
> + tristate "ST ASC serial port support"
> + depends on PLAT_STIXXXX
> + default y
> + select SERIAL_CORE
> + help
> + This driver is for the on-chip Asychronous Serial Controller on
> + STMicroelectronics STixxxx SoCs.
> + ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
> + It support all industry standard baud rates.
> +
> + If unsure, say N.
I would not make it "default y".
> +config SERIAL_ST_ASC_CONSOLE
> + bool "Support for console on ST ASC"
> + depends on SERIAL_ST_ASC
> + default y
> + select SERIAL_CORE_CONSOLE
> +
> endmenu
This needs to be "depends on SERIAL_ST_ASC=y". You would get a link error
if you try to make SERIAL_ST_ASC a loadable module and SERIAL_ST_ASC_CONSOLE
built-in.
> +
> +static struct asc_port asc_ports[ASC_MAX_PORTS];
> +static struct uart_driver asc_uart_driver;
> +
> +/*---- Forward function declarations---------------------------*/
> +static irqreturn_t asc_interrupt(int irq, void *ptr);
> +static void asc_transmit_chars(struct uart_port *);
> +static int asc_set_baud(struct asc_port *ascport, int baud);
> +
Please remove all forward declarations, by reordering the functions in
the way they are called.
> diff --git a/drivers/tty/serial/st-asc.h b/drivers/tty/serial/st-asc.h
> new file mode 100644
> index 0000000..e59f818
> --- /dev/null
> +++ b/drivers/tty/serial/st-asc.h
> +#ifndef _ST_ASC_H
> +#define _ST_ASC_H
> +
> +#include <linux/serial_core.h>
> +#include <linux/clk.h>
> +
> +struct asc_port {
> + struct uart_port port;
> + struct clk *clk;
> + unsigned int hw_flow_control:1;
> + unsigned int check_parity:1;
> + unsigned int force_m1:1;
> +};
Since this header file is only used in one place, just merge it into
the driver itself.
> +#define ASC_MAJOR 204
> +#define ASC_MINOR_START 40
I don't know what the current policy is on allocating major/minor numbers,
but I'm sure you cannot just reuse one that is already used.
Documentation/devices.txt lists the ones that are officially assigned.
Can't you use dynamic allocation here?
Arnd
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 1/8] serial:st-asc: Add ST ASC driver.
2013-05-08 14:34 ` Arnd Bergmann
@ 2013-05-08 14:39 ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-08 18:18 ` Srinivas KANDAGATLA
[not found] ` <201305081634.43498.arnd-r2nGTMty4D4@public.gmane.org>
` (2 subsequent siblings)
3 siblings, 1 reply; 79+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-05-08 14:39 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Srinivas KANDAGATLA, linux-doc, Viresh Kumar, Will Deacon, jslaby,
Russell King, Samuel Ortiz, Nicolas Pitre, Stephen Gallimore,
linux-serial, Jason Cooper, devicetree-discuss, Rob Herring,
Stuart Menefy, Stephen Warren, Dong Aisheng, linux-arm-kernel,
gregkh, Mark Brown, linux-kernel
On 16:34 Wed 08 May , Arnd Bergmann wrote:
> On Wednesday 08 May 2013, Srinivas KANDAGATLA wrote:
> > From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>
> > +*st-asc(Serial Port)
> > +
> > +Required properties:
> > +- compatible : Should be "st,asc".
>
> Are there any hardware revision numbers for the asc? If there are potentially
> incompatible or backwards-compatible variants, it would be good to include
> the version in this string.
The st,asc come from st20 or st200 IIRC which was not ARM but a ST arch
and then used on st40 series
an the st,asc for st200 and st40 are not compatible completly
>
> > +- reg, reg-names, interrupts, interrupt-names : Standard way to define device
> > + resources with names. look in
> > + Documentation/devicetree/bindings/resource-names.txt
> > +
> > +Optional properties:
> > +- st,hw-flow-ctrl bool flag to enable hardware flow control.
> > +- st,force-m1 bool flat to force asc to be in Mode-1 recommeded
> > + for high bit rates (above 19.2K)
> > +Example:
> > +serial@fe440000{
> > + compatible = "st,asc";
> > + reg = <0xfe440000 0x2c>;
> > + interrupts = <0 209 0>;
> > +};
>
> I would also recommed adding a way to set the default baud rate through
> a property. Following the example of the 8250 driver, you should probably
> call that "current-speed".
on st it has always be 38k
>
> > diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> > index 7e7006f..346f325 100644
> > --- a/drivers/tty/serial/Kconfig
> > +++ b/drivers/tty/serial/Kconfig
> > @@ -1484,6 +1484,25 @@ config SERIAL_RP2_NR_UARTS
> > If multiple cards are present, the default limit of 32 ports may
> > need to be increased.
> >
> > +config SERIAL_ST_ASC
> > + tristate "ST ASC serial port support"
> > + depends on PLAT_STIXXXX
> > + default y
> > + select SERIAL_CORE
> > + help
> > + This driver is for the on-chip Asychronous Serial Controller on
> > + STMicroelectronics STixxxx SoCs.
> > + ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
> > + It support all industry standard baud rates.
> > +
> > + If unsure, say N.
>
> I would not make it "default y".
me too
>
> > +config SERIAL_ST_ASC_CONSOLE
> > + bool "Support for console on ST ASC"
> > + depends on SERIAL_ST_ASC
> > + default y
> > + select SERIAL_CORE_CONSOLE
> > +
> > endmenu
>
> This needs to be "depends on SERIAL_ST_ASC=y". You would get a link error
> if you try to make SERIAL_ST_ASC a loadable module and SERIAL_ST_ASC_CONSOLE
> built-in.
>
> > +
> > +static struct asc_port asc_ports[ASC_MAX_PORTS];
> > +static struct uart_driver asc_uart_driver;
> > +
> > +/*---- Forward function declarations---------------------------*/
> > +static irqreturn_t asc_interrupt(int irq, void *ptr);
> > +static void asc_transmit_chars(struct uart_port *);
> > +static int asc_set_baud(struct asc_port *ascport, int baud);
> > +
>
> Please remove all forward declarations, by reordering the functions in
> the way they are called.
>
and drop the dummy functions
>
> > diff --git a/drivers/tty/serial/st-asc.h b/drivers/tty/serial/st-asc.h
> > new file mode 100644
> > index 0000000..e59f818
> > --- /dev/null
> > +++ b/drivers/tty/serial/st-asc.h
> > +#ifndef _ST_ASC_H
> > +#define _ST_ASC_H
> > +
> > +#include <linux/serial_core.h>
> > +#include <linux/clk.h>
> > +
> > +struct asc_port {
> > + struct uart_port port;
> > + struct clk *clk;
> > + unsigned int hw_flow_control:1;
> > + unsigned int check_parity:1;
> > + unsigned int force_m1:1;
> > +};
>
> Since this header file is only used in one place, just merge it into
> the driver itself.
>
> > +#define ASC_MAJOR 204
> > +#define ASC_MINOR_START 40
>
> I don't know what the current policy is on allocating major/minor numbers,
> but I'm sure you cannot just reuse one that is already used.
>
> Documentation/devices.txt lists the ones that are officially assigned.
> Can't you use dynamic allocation here?
>
> Arnd
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 1/8] serial:st-asc: Add ST ASC driver.
2013-05-08 14:39 ` Jean-Christophe PLAGNIOL-VILLARD
@ 2013-05-08 18:18 ` Srinivas KANDAGATLA
2013-05-08 19:55 ` Arnd Bergmann
0 siblings, 1 reply; 79+ messages in thread
From: Srinivas KANDAGATLA @ 2013-05-08 18:18 UTC (permalink / raw)
To: Jean-Christophe PLAGNIOL-VILLARD
Cc: Mark Brown, Russell King, Samuel Ortiz, Arnd Bergmann, linux-doc,
Viresh Kumar, devicetree-discuss, Nicolas Pitre, Will Deacon,
Stephen Gallimore, Rob Herring, linux-kernel, Stuart Menefy,
linux-serial, gregkh, Stephen Warren, Dong Aisheng, jslaby,
linux-arm-kernel, Jason Cooper
On 08/05/13 15:39, Jean-Christophe PLAGNIOL-VILLARD wrote:
>>> +
>> >
>> > Please remove all forward declarations, by reordering the functions in
>> > the way they are called.
>> >
> and drop the dummy functions
We can not remove the dummy functions, as the serial-core does not check
it before using them.
>> >
>>> > > diff --git a/drivers/tty/serial/st-asc.h b/drivers/tty/serial/st-asc.h
>>> > > new file mode 100644
>>> > > index 0000000..e59f818
>>> > > --- /dev/null
>>> > > +++ b/drivers/tty/serial/st-asc.h
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 1/8] serial:st-asc: Add ST ASC driver.
2013-05-08 18:18 ` Srinivas KANDAGATLA
@ 2013-05-08 19:55 ` Arnd Bergmann
0 siblings, 0 replies; 79+ messages in thread
From: Arnd Bergmann @ 2013-05-08 19:55 UTC (permalink / raw)
To: srinivas.kandagatla
Cc: Jean-Christophe PLAGNIOL-VILLARD, linux-doc, Viresh Kumar,
Will Deacon, jslaby, Russell King, Samuel Ortiz, Nicolas Pitre,
Stephen Gallimore, linux-serial, Jason Cooper, devicetree-discuss,
Rob Herring, Stuart Menefy, Stephen Warren, Dong Aisheng,
linux-arm-kernel, gregkh, Mark Brown, linux-kernel
On Wednesday 08 May 2013, Srinivas KANDAGATLA wrote:
>
> On 08/05/13 15:39, Jean-Christophe PLAGNIOL-VILLARD wrote:
> >>> +
> >> >
> >> > Please remove all forward declarations, by reordering the functions in
> >> > the way they are called.
> >> >
> > and drop the dummy functions
>
> We can not remove the dummy functions, as the serial-core does not check
> it before using them.
None of them seem performance critical, so it sounds reasonable to change
this in the core so you don't have to provide them. It's up to Greg to decide
whether he'd like that change or not.
Arnd
^ permalink raw reply [flat|nested] 79+ messages in thread
[parent not found: <201305081634.43498.arnd-r2nGTMty4D4@public.gmane.org>]
* Re: [RFC 1/8] serial:st-asc: Add ST ASC driver.
[not found] ` <201305081634.43498.arnd-r2nGTMty4D4@public.gmane.org>
@ 2013-05-08 15:34 ` Greg KH
[not found] ` <20130508153459.GA17186-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
` (3 more replies)
0 siblings, 4 replies; 79+ messages in thread
From: Greg KH @ 2013-05-08 15:34 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Srinivas KANDAGATLA, Viresh Kumar, Will Deacon,
jslaby-AlSwsSmVLrQ, Russell King, Samuel Ortiz, Nicolas Pitre,
linux-doc-u79uwXL29TY76Z2rM5mHXA, Stephen Gallimore,
linux-serial-u79uwXL29TY76Z2rM5mHXA, Jason Cooper,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring,
Stuart Menefy, Stephen Warren, Dong Aisheng,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Mark Brown,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Wed, May 08, 2013 at 04:34:43PM +0200, Arnd Bergmann wrote:
> > +#define ASC_MAJOR 204
> > +#define ASC_MINOR_START 40
>
> I don't know what the current policy is on allocating major/minor numbers,
> but I'm sure you cannot just reuse one that is already used.
I agree, why are you trying to create a new tty device name? Can't you
use the existing ttyS name and minor number as you will not have any
other type of serial device on this system?
thanks,
greg k-h
^ permalink raw reply [flat|nested] 79+ messages in thread
[parent not found: <20130508153459.GA17186-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>]
* Re: [RFC 1/8] serial:st-asc: Add ST ASC driver.
[not found] ` <20130508153459.GA17186-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
@ 2013-05-08 15:40 ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-08 15:53 ` Greg KH
0 siblings, 1 reply; 79+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-05-08 15:40 UTC (permalink / raw)
To: Greg KH
Cc: Mark Brown, Russell King, Samuel Ortiz, Srinivas KANDAGATLA,
Viresh Kumar, devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
Nicolas Pitre, Will Deacon, Stephen Gallimore, Rob Herring,
linux-doc-u79uwXL29TY76Z2rM5mHXA, Stuart Menefy,
linux-serial-u79uwXL29TY76Z2rM5mHXA, Stephen Warren,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Dong Aisheng,
jslaby-AlSwsSmVLrQ,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Jason Cooper
On 08:34 Wed 08 May , Greg KH wrote:
> On Wed, May 08, 2013 at 04:34:43PM +0200, Arnd Bergmann wrote:
> > > +#define ASC_MAJOR 204
> > > +#define ASC_MINOR_START 40
> >
> > I don't know what the current policy is on allocating major/minor numbers,
> > but I'm sure you cannot just reuse one that is already used.
>
> I agree, why are you trying to create a new tty device name? Can't you
> use the existing ttyS name and minor number as you will not have any
> other type of serial device on this system?
Greg on ST STB for more than 10 years we use ttyASC I'll prefer ttySx
on the DTB SoC you have one one IP present the st,asc
Best Regards,
J.
>
> thanks,
>
> greg k-h
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 1/8] serial:st-asc: Add ST ASC driver.
2013-05-08 15:40 ` Jean-Christophe PLAGNIOL-VILLARD
@ 2013-05-08 15:53 ` Greg KH
2013-05-08 16:03 ` Jean-Christophe PLAGNIOL-VILLARD
0 siblings, 1 reply; 79+ messages in thread
From: Greg KH @ 2013-05-08 15:53 UTC (permalink / raw)
To: Jean-Christophe PLAGNIOL-VILLARD
Cc: Arnd Bergmann, Srinivas KANDAGATLA, Viresh Kumar, Will Deacon,
jslaby, Russell King, Samuel Ortiz, Nicolas Pitre, linux-doc,
Stephen Gallimore, linux-serial, Jason Cooper, devicetree-discuss,
Rob Herring, Stuart Menefy, Stephen Warren, Dong Aisheng,
linux-arm-kernel, Mark Brown, linux-kernel
On Wed, May 08, 2013 at 05:40:57PM +0200, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 08:34 Wed 08 May , Greg KH wrote:
> > On Wed, May 08, 2013 at 04:34:43PM +0200, Arnd Bergmann wrote:
> > > > +#define ASC_MAJOR 204
> > > > +#define ASC_MINOR_START 40
> > >
> > > I don't know what the current policy is on allocating major/minor numbers,
> > > but I'm sure you cannot just reuse one that is already used.
> >
> > I agree, why are you trying to create a new tty device name? Can't you
> > use the existing ttyS name and minor number as you will not have any
> > other type of serial device on this system?
>
> Greg on ST STB for more than 10 years we use ttyASC I'll prefer ttySx
For 10+ years you have had an out-of-tree serial driver? What
major/minor numbers did you use for it?
> on the DTB SoC you have one one IP present the st,asc
I don't understand, what do you mean by this?
confused,
greg k-h
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 1/8] serial:st-asc: Add ST ASC driver.
2013-05-08 15:53 ` Greg KH
@ 2013-05-08 16:03 ` Jean-Christophe PLAGNIOL-VILLARD
[not found] ` <B5A00B86-5332-427E-A82A-5B71EC0979A8-sclMFOaUSTBWk0Htik3J/w@public.gmane.org>
0 siblings, 1 reply; 79+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-05-08 16:03 UTC (permalink / raw)
To: Greg KH
Cc: Jean-Christophe PLAGNIOL-VILLARD, Arnd Bergmann,
Srinivas KANDAGATLA, Viresh Kumar, Will Deacon, jslaby,
Russell King, Samuel Ortiz, Nicolas Pitre, linux-doc,
Stephen Gallimore, linux-serial, Jason Cooper, devicetree-discuss,
Rob Herring, Stuart Menefy, Stephen Warren, Dong Aisheng,
linux-arm-kernel, Mark Brown, linux-kernel
On May 8, 2013, at 11:53 PM, Greg KH <gregkh@linuxfoundation.org> wrote:
> On Wed, May 08, 2013 at 05:40:57PM +0200, Jean-Christophe PLAGNIOL-VILLARD wrote:
>> On 08:34 Wed 08 May , Greg KH wrote:
>>> On Wed, May 08, 2013 at 04:34:43PM +0200, Arnd Bergmann wrote:
>>>>> +#define ASC_MAJOR 204
>>>>> +#define ASC_MINOR_START 40
>>>>
>>>> I don't know what the current policy is on allocating major/minor numbers,
>>>> but I'm sure you cannot just reuse one that is already used.
>>>
>>> I agree, why are you trying to create a new tty device name? Can't you
>>> use the existing ttyS name and minor number as you will not have any
>>> other type of serial device on this system?
>>
>> Greg on ST STB for more than 10 years we use ttyASC I'll prefer ttySx
>
> For 10+ years you have had an out-of-tree serial driver?
yes ST have it out of tree for very long time even I puts them to come mainline
> What
> major/minor numbers did you use for it?
http://git.stlinux.com/?p=havana/com.st.havana.kernel.git;a=blob;f=drivers/serial/stm-asc.h;h=79e003ffeb21df55a6af94774fc9c4b3d8de18e9;hb=HEAD
52 #define ASC_MAJOR 204
53 #define ASC_MINOR_START 40
same as in this patch
>
>> on the DTB SoC you have one one IP present the st,asc
>
> I don't understand, what do you mean by this?
>
> confused,
just mention there is not hardware reason to not use the generic ttySx in place of ttyAS
as we have only one IP that handle serial on this family of SoC
personally I'll switch to ttySx
Best Regards,
J.
^ permalink raw reply [flat|nested] 79+ messages in thread
* RE: [RFC 1/8] serial:st-asc: Add ST ASC driver.
2013-05-08 15:34 ` Greg KH
[not found] ` <20130508153459.GA17186-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
@ 2013-05-08 16:10 ` Stephen GALLIMORE
2013-05-10 13:50 ` Stephen GALLIMORE
2013-05-10 14:45 ` Ben Dooks
3 siblings, 0 replies; 79+ messages in thread
From: Stephen GALLIMORE @ 2013-05-08 16:10 UTC (permalink / raw)
To: Greg KH, Arnd Bergmann
Cc: linux-doc@vger.kernel.org, Srinivas KANDAGATLA,
linux-kernel@vger.kernel.org, Stuart MENEFY,
linux-serial@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
>On Wed, May 08, 2013 at 04:34:43PM +0200, Arnd Bergmann wrote:
> > > +#define ASC_MAJOR 204
> > > +#define ASC_MINOR_START 40
> >
> > I don't know what the current policy is on allocating major/minor
> > numbers, but I'm sure you cannot just reuse one that is already used.
First, our apologies, this issue was raised internally and then got forgotten about, there's always something I guess.
> >I agree, why are you trying to create a new tty device name? Can't you use the existing ttyS name and minor number as you will not have any other type of serial
> >device on this system?
That is an interesting question Greg; I believe it probably stems from historic ST SoCs that had two different types of serial devices, something that is no longer the case. We will review our approach to this again, although we are not sure we can use the existing ttyS major/minor (even if that is an acceptable thing to do) because of the (remote) possibility of someone using a standard PCIe attached serial card.
Regards,
-stephen
^ permalink raw reply [flat|nested] 79+ messages in thread
* RE: [RFC 1/8] serial:st-asc: Add ST ASC driver.
2013-05-08 15:34 ` Greg KH
[not found] ` <20130508153459.GA17186-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
2013-05-08 16:10 ` Stephen GALLIMORE
@ 2013-05-10 13:50 ` Stephen GALLIMORE
2013-05-10 14:08 ` Greg KH
2013-05-10 14:45 ` Ben Dooks
3 siblings, 1 reply; 79+ messages in thread
From: Stephen GALLIMORE @ 2013-05-10 13:50 UTC (permalink / raw)
To: Greg KH, Arnd Bergmann
Cc: Srinivas KANDAGATLA, Stuart MENEFY, linux-kernel@vger.kernel.org,
linux-serial@vger.kernel.org
>On Wed, May 08, 2013 at 04:34:43PM +0200, Arnd Bergmann wrote:
> > > +#define ASC_MAJOR 204
> > > +#define ASC_MINOR_START 40
> >
> > I don't know what the current policy is on allocating major/minor
> > numbers, but I'm sure you cannot just reuse one that is already used.
>
> First, our apologies, this issue was raised internally and then got forgotten about, there's always something I guess.
>
> > >I agree, why are you trying to create a new tty device name? Can't
> > >you use the existing ttyS name and minor number as you will not have any other type of serial device on this system?
>
> That is an interesting question Greg; I believe it probably stems from historic ST SoCs that had two different types of serial devices,
> something that is no longer the case. We will review our approach to this again, although we are not sure we can use the
> existing ttyS major/minor (even if that is an acceptable thing to do) because of the (remote) possibility of someone using
> a standard PCIe attached serial card.
Greg, having looked at this we have concluded that we should just go dynamic, as others have mentioned with udev on a full system
or devtmpfs on a minimal initramfs system there is no reason to use a static major/minor. However the view here is that we
would prefer to keep the unique name, as for example the lantiq driver which is also dynamic does, for the reason previously
mentioned regarding PCIe cards.
Is that acceptable?
Regards,
-stephen
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 1/8] serial:st-asc: Add ST ASC driver.
2013-05-10 13:50 ` Stephen GALLIMORE
@ 2013-05-10 14:08 ` Greg KH
0 siblings, 0 replies; 79+ messages in thread
From: Greg KH @ 2013-05-10 14:08 UTC (permalink / raw)
To: Stephen GALLIMORE
Cc: Arnd Bergmann, Srinivas KANDAGATLA, Stuart MENEFY,
linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org
On Fri, May 10, 2013 at 03:50:16PM +0200, Stephen GALLIMORE wrote:
> Greg, having looked at this we have concluded that we should just go
> dynamic, as others have mentioned with udev on a full system or
> devtmpfs on a minimal initramfs system there is no reason to use a
> static major/minor. However the view here is that we would prefer to
> keep the unique name, as for example the lantiq driver which is also
> dynamic does, for the reason previously mentioned regarding PCIe
> cards.
Why do you want your own name?
> Is that acceptable?
I would prefer not to use a new serial port name, as this is only going
to make it harder for me to delete that name in the next year :)
Sorry,
greg k-h
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 1/8] serial:st-asc: Add ST ASC driver.
2013-05-08 15:34 ` Greg KH
` (2 preceding siblings ...)
2013-05-10 13:50 ` Stephen GALLIMORE
@ 2013-05-10 14:45 ` Ben Dooks
[not found] ` <518D07FB.7010606-4yDnlxn2s6sWdaTGBSpHTA@public.gmane.org>
3 siblings, 1 reply; 79+ messages in thread
From: Ben Dooks @ 2013-05-10 14:45 UTC (permalink / raw)
To: Greg KH
Cc: Dave Martin, Srinivas KANDAGATLA, Viresh Kumar, Linus Walleij,
Will Deacon, Grant Likely, jslaby, Russell King, Samuel Ortiz,
Nicolas Pitre, linux-doc, Stephen Gallimore, linux-serial,
Jason Cooper, Arnd Bergmann, Marc Zyngier, devicetree-discuss,
Rob Herring, Stuart Menefy, Stephen Warren, Dong Aisheng,
linux-arm-kernel, Mark Brown, linux-kernel
On 08/05/13 17:34, Greg KH wrote:
> On Wed, May 08, 2013 at 04:34:43PM +0200, Arnd Bergmann wrote:
>>> +#define ASC_MAJOR 204
>>> +#define ASC_MINOR_START 40
>>
>> I don't know what the current policy is on allocating major/minor numbers,
>> but I'm sure you cannot just reuse one that is already used.
>
> I agree, why are you trying to create a new tty device name? Can't you
> use the existing ttyS name and minor number as you will not have any
> other type of serial device on this system?
This would be an issue on systems that either accept plug-in cards
such as PCMCIA/CardBus/PCI or have additional off SoC IO spaces
where 8250 compatible UARTS could live.
--
Ben Dooks http://www.codethink.co.uk/
Senior Engineer Codethink - Providing Genius
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 1/8] serial:st-asc: Add ST ASC driver.
2013-05-08 14:34 ` Arnd Bergmann
2013-05-08 14:39 ` Jean-Christophe PLAGNIOL-VILLARD
[not found] ` <201305081634.43498.arnd-r2nGTMty4D4@public.gmane.org>
@ 2013-05-08 18:02 ` Srinivas KANDAGATLA
2013-05-20 11:49 ` Stephen GALLIMORE
3 siblings, 0 replies; 79+ messages in thread
From: Srinivas KANDAGATLA @ 2013-05-08 18:02 UTC (permalink / raw)
To: Arnd Bergmann
Cc: gregkh, jslaby, Rob Landley, Grant Likely, Rob Herring,
Russell King, Samuel Ortiz, Linus Walleij, Stuart Menefy,
Shawn Guo, Olof Johansson, Jason Cooper, Stephen Warren,
Maxime Ripard, Nicolas Pitre, Will Deacon, Dave Martin,
Marc Zyngier, Viresh Kumar, Mark Brown, Dong Aisheng, linux-doc,
linux-kernel, devicetree-discuss
Thankyou for the comments.
On 08/05/13 15:34, Arnd Bergmann wrote:
> On Wednesday 08 May 2013, Srinivas KANDAGATLA wrote:
>> From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>> +*st-asc(Serial Port)
>> +
>> +Required properties:
>> +- compatible : Should be "st,asc".
> Are there any hardware revision numbers for the asc? If there are potentially
> incompatible or backwards-compatible variants, it would be good to include
> the version in this string.
Unfortunately, there is no version numbering for this IP.
>
>> +- reg, reg-names, interrupts, interrupt-names : Standard way to define device
>> + resources with names. look in
>> + Documentation/devicetree/bindings/resource-names.txt
>> +
>> +Optional properties:
>> +- st,hw-flow-ctrl bool flag to enable hardware flow control.
>> +- st,force-m1 bool flat to force asc to be in Mode-1 recommeded
>> + for high bit rates (above 19.2K)
>> +Example:
>> +serial@fe440000{
>> + compatible = "st,asc";
>> + reg = <0xfe440000 0x2c>;
>> + interrupts = <0 209 0>;
>> +};
> I would also recommed adding a way to set the default baud rate through
> a property. Following the example of the 8250 driver, you should probably
> call that "current-speed".
Yes, I will add this in the next version.
>
>> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
>> index 7e7006f..346f325 100644
>> --- a/drivers/tty/serial/Kconfig
>> +++ b/drivers/tty/serial/Kconfig
>> @@ -1484,6 +1484,25 @@ config SERIAL_RP2_NR_UARTS
>> If multiple cards are present, the default limit of 32 ports may
>> need to be increased.
>>
>> +config SERIAL_ST_ASC
>> + tristate "ST ASC serial port support"
>> + depends on PLAT_STIXXXX
>> + default y
>> + select SERIAL_CORE
>> + help
>> + This driver is for the on-chip Asychronous Serial Controller on
>> + STMicroelectronics STixxxx SoCs.
>> + ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
>> + It support all industry standard baud rates.
>> +
>> + If unsure, say N.
> I would not make it "default y".
Yep.
>> +config SERIAL_ST_ASC_CONSOLE
>> + bool "Support for console on ST ASC"
>> + depends on SERIAL_ST_ASC
>> + default y
>> + select SERIAL_CORE_CONSOLE
>> +
>> endmenu
> This needs to be "depends on SERIAL_ST_ASC=y". You would get a link error
> if you try to make SERIAL_ST_ASC a loadable module and SERIAL_ST_ASC_CONSOLE
> built-in.
Ok, got it.
>
>> +
>> +static struct asc_port asc_ports[ASC_MAX_PORTS];
>> +static struct uart_driver asc_uart_driver;
>> +
>> +/*---- Forward function declarations---------------------------*/
>> +static irqreturn_t asc_interrupt(int irq, void *ptr);
>> +static void asc_transmit_chars(struct uart_port *);
>> +static int asc_set_baud(struct asc_port *ascport, int baud);
>> +
> Please remove all forward declarations, by reordering the functions in
> the way they are called.
Will do.
>
>
>> diff --git a/drivers/tty/serial/st-asc.h b/drivers/tty/serial/st-asc.h
>> new file mode 100644
>> index 0000000..e59f818
>> --- /dev/null
>> +++ b/drivers/tty/serial/st-asc.h
>> +#ifndef _ST_ASC_H
>> +#define _ST_ASC_H
>> +
>> +#include <linux/serial_core.h>
>> +#include <linux/clk.h>
>> +
>> +struct asc_port {
>> + struct uart_port port;
>> + struct clk *clk;
>> + unsigned int hw_flow_control:1;
>> + unsigned int check_parity:1;
>> + unsigned int force_m1:1;
>> +};
> Since this header file is only used in one place, just merge it into
> the driver itself.
Ok, will do it.
>
>> +#define ASC_MAJOR 204
>> +#define ASC_MINOR_START 40
> I don't know what the current policy is on allocating major/minor numbers,
> but I'm sure you cannot just reuse one that is already used.
>
> Documentation/devices.txt lists the ones that are officially assigned.
> Can't you use dynamic allocation here?
>
> Arnd
>
^ permalink raw reply [flat|nested] 79+ messages in thread
* RE: [RFC 1/8] serial:st-asc: Add ST ASC driver.
2013-05-08 14:34 ` Arnd Bergmann
` (2 preceding siblings ...)
2013-05-08 18:02 ` Srinivas KANDAGATLA
@ 2013-05-20 11:49 ` Stephen GALLIMORE
2013-05-22 15:13 ` Arnd Bergmann
3 siblings, 1 reply; 79+ messages in thread
From: Stephen GALLIMORE @ 2013-05-20 11:49 UTC (permalink / raw)
To: Arnd Bergmann, Srinivas KANDAGATLA
Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org
Hi Arnd,
We have pretty much completed reworking the patch set we sent recently, but
there is one comment you made which seemed to make perfect sense
but after investigating it has left me totally confused, which was:
>I would also recommed adding a way to set the default baud rate through
> a property. Following the example of the 8250 driver, you should probably
> call that "current-speed".
I note that you are listed as the author of of_serial.c so I was assuming
that looking at this would make sense, but it doesn't at all, and I would
be really grateful if you could explain what you were trying to achieve
and how you thought it worked. The code does:
/* If current-speed was set, then try not to change it. */
if (of_property_read_u32(np, "current-speed", &spd) == 0)
port->custom_divisor = clk / (16 * spd);
The "spd" variable is not used again and I do not understand why you
thought setting port->custom_divisor would have any impact on the default
or current baud rate of the UART, or that this information was useful to
any other part of the system. A search has only revealed that this port
field has only one purpose, which is to provide a "custom" speed
(unsurprisingly) when the user requests 38.4K _and_ the port flag
UPF_SPD_CUST has been set through a TIOCSSERIAL ioctl call, instead of
actually getting 38.4K. The key part of that assessment being the
implementation of uart_get_divisor() :
if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
quot = port->custom_divisor;
else
quot = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud);
Also all of the custom_divisor functionality is basically commented as "old"
or has a kernel warning saying it is deprecated (see uart_set_info), so as
far as I can see for our (and I suspect most) hardware it is completely
irrelevant functionality.
If you really wanted to specify a default rate for a TTY then surely you need
to change the driver's init_termios, or change the termios on a per port basis
after they get registered. Only a handful of drivers do not use the default
uart_register_driver() and change the init_termios (statically) to something
other than 9600 8N1. I have been unable so far to find any evidence of drivers
changing the termios after a port has been registered based on either platform
data or OF attributes. So I do not see why we would want to provide that
functionality explicitly in the ASC driver if nobody else does; if you want
to change the TTY speed, use the tty IOCTL interfaces (or stty).
So I don't see why you think the concept of a default or current speed belongs
in the device tree description of the uart at all, unless there is something
special about the hardware. One possible example of that seems to be the ARC
driver which only appears to support one serial speed and uses "current-speed"
attribute to specify that speed; or the ARC driver is broken and they have
made a mistake in their set_termios implementation, we cannot quite work out
which of those two things is true. But that isn't the case for the ASC
hardware so it again would not be relevant in this driver.
So basically we would like some help understanding what it is you would
really like us to do. Clearly we can just duplicate what you did in
of_serial.c for the 8250 and move on, but we would like to understand why
that wouldn't just be adding redundant code.
Regards,
-stephen
^ permalink raw reply [flat|nested] 79+ messages in thread
* Re: [RFC 1/8] serial:st-asc: Add ST ASC driver.
2013-05-20 11:49 ` Stephen GALLIMORE
@ 2013-05-22 15:13 ` Arnd Bergmann
2013-05-23 16:26 ` Stephen GALLIMORE
0 siblings, 1 reply; 79+ messages in thread
From: Arnd Bergmann @ 2013-05-22 15:13 UTC (permalink / raw)
To: Stephen GALLIMORE
Cc: Srinivas KANDAGATLA, linux-serial@vger.kernel.org,
linux-kernel@vger.kernel.org
On Monday 20 May 2013, Stephen GALLIMORE wrote:
> We have pretty much completed reworking the patch set we sent recently, but
> there is one comment you made which seemed to make perfect sense
> but after investigating it has left me totally confused, which was:
>
> >I would also recommed adding a way to set the default baud rate through
> > a property. Following the example of the 8250 driver, you should probably
> > call that "current-speed".
>
> I note that you are listed as the author of of_serial.c so I was assuming
> that looking at this would make sense, but it doesn't at all, and I would
> be really grateful if you could explain what you were trying to achieve
> and how you thought it worked. The code does:
>
> /* If current-speed was set, then try not to change it. */
> if (of_property_read_u32(np, "current-speed", &spd) == 0)
> port->custom_divisor = clk / (16 * spd);
>
> The "spd" variable is not used again and I do not understand why you
> thought setting port->custom_divisor would have any impact on the default
> or current baud rate of the UART, or that this information was useful to
> any other part of the system. A search has only revealed that this port
> field has only one purpose, which is to provide a "custom" speed
> (unsurprisingly) when the user requests 38.4K and the port flag
> UPF_SPD_CUST has been set through a TIOCSSERIAL ioctl call, instead of
> actually getting 38.4K. The key part of that assessment being the
> implementation of uart_get_divisor() :
>
> if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
> quot = port->custom_divisor;
> else
> quot = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud);
>
> Also all of the custom_divisor functionality is basically commented as "old"
> or has a kernel warning saying it is deprecated (see uart_set_info), so as
> far as I can see for our (and I suspect most) hardware it is completely
> irrelevant functionality.
What may have happened here is that custom_divisor was used in a different
way when I added that code than it is today, and the change was not propagated
into the of_serial driver. However, going back to 2.6.20 shows no different
code than what we have today in this regard. It may simply have been a mistake
on my side.
> So I don't see why you think the concept of a default or current speed belongs
> in the device tree description of the uart at all, unless there is something
> special about the hardware.
I looked it up in the original serial port binding at
http://www.openfirmware.org/1275/bindings/devices/html/serial.html, which does
not specify the property, and in ePAPR, which does have it in the section about
"serial class devices":
18 6.2.1.2 current-speed
19 Property: current-speed
20 Value type: <u32>
21 Description:
22 Specifies the current speed of a serial device in bits per second. A boot program should set
23 this property if it has initialized the serial device.
24 Example:
25 current - speed = <115200>; # 115200 baud
The reason you want this is so that the driver can initialize the hardware from
scratch more easily and get back to the same settings. Why they only specified
the baud rate but not also start/stop bits and flow control I don't understand
though.
I guess you can ignore my original comment.
Arnd
^ permalink raw reply [flat|nested] 79+ messages in thread
* RE: [RFC 1/8] serial:st-asc: Add ST ASC driver.
2013-05-22 15:13 ` Arnd Bergmann
@ 2013-05-23 16:26 ` Stephen GALLIMORE
0 siblings, 0 replies; 79+ messages in thread
From: Stephen GALLIMORE @ 2013-05-23 16:26 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Srinivas KANDAGATLA, linux-kernel@vger.kernel.org,
linux-serial@vger.kernel.org
On Wednesday 22 May 2013, Arnd Bergmann wrote:
> > Also all of the custom_divisor functionality is basically commented as "old"
> > or has a kernel warning saying it is deprecated (see uart_set_info), so as
> > far as I can see for our (and I suspect most) hardware it is completely
> > irrelevant functionality.
>
> What may have happened here is that custom_divisor was used in a different
> way when I added that code than it is today, and the change was not propagated
> into the of_serial driver. However, going back to 2.6.20 shows no different
> code than what we have today in this regard. It may simply have been
> a mistake on my side.
Thanks for looking into this and digging around in the history. At least I didn't
miss something really obvious.
> I looked it up in the original serial port binding at
> http://www.openfirmware.org/1275/bindings/devices/html/serial.ht
> ml, which does
> not specify the property, and in ePAPR, which does have it in the
> section about
> "serial class devices":
>
> 18 6.2.1.2 current-speed
> 19 Property: current-speed
> 20 Value type: <u32>
> 21 Description:
> 22 Specifies the current speed of a serial device in bits per second. A
> boot program should set
> 23 this property if it has initialized the serial device.
> 24 Example:
> 25 current - speed = <115200>; # 115200 baud
>
> The reason you want this is so that the driver can initialize the hardware from
> scratch more easily and get back to the same settings. Why they only specified
> the baud rate but not also start/stop bits and flow control I don't understand
> though.
Yes, I had been made aware of the ePAPR definition by Srini after I sent the post.
In fact I had exactly the same question in my head about the other settings as
well.
>
> I guess you can ignore my original comment.
>
OK.
Thanks again for your time.
Regards,
-stephen
^ permalink raw reply [flat|nested] 79+ messages in thread
* [RFC 4/8] pinctrl:stixxxx: Add pinctrl and pinconf support.
[not found] ` <1368022187-1633-1-git-send-email-srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
2013-05-08 14:10 ` [RFC 1/8] serial:st-asc: Add ST ASC driver Srinivas KANDAGATLA
@ 2013-05-08 14:11 ` Srinivas KANDAGATLA
[not found] ` <1368022284-2283-1-git-send-email-srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
2013-05-08 14:12 ` [RFC 7/8] ARM:stih41x: Add B2000 board support Srinivas KANDAGATLA
2 siblings, 1 reply; 79+ messages in thread
From: Srinivas KANDAGATLA @ 2013-05-08 14:11 UTC (permalink / raw)
To: linus.walleij-QSEj5FYQhm4dnm+yROfE0A
Cc: Srinivas Kandagatla, Viresh Kumar, Will Deacon, Jiri Slaby,
Russell King, Samuel Ortiz, Nicolas Pitre,
linux-doc-u79uwXL29TY76Z2rM5mHXA, Stephen Gallimore,
linux-serial-u79uwXL29TY76Z2rM5mHXA, Jason Cooper,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring,
Stuart Menefy, Stephen Warren, Dong Aisheng,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Greg Kroah-Hartman, Mark Brown,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
This patch add pinctrl support to ST SoCs.
About hardware:
ST Set-Top-Box parts have two blocks called PIO and PIO-mux which handle
pin configurations.
Each multi-function pin is controlled, driven and routed through the PIO
multiplexing block. Each pin supports GPIO functionality (ALT0) and
multiple alternate functions(ALT1 - ALTx) that directly connect the pin
to different hardware blocks. When a pin is in GPIO mode, Output Enable
(OE), Open Drain(OD), and Pull Up (PU) are driven by the related PIO
block. Otherwise the PIO multiplexing block configures these parameters
and retiming the signal.
About driver:
This pinctrl driver manages both PIO and PIO-mux block using pinctrl,
pinconf, pinmux, gpio subsystems. All the pinctrl related config
information can only come from device trees.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
CC: Stephen Gallimore <stephen.gallimore-qxv4g6HH51o@public.gmane.org>
CC: Stuart Menefy <stuart.menefy-qxv4g6HH51o@public.gmane.org>
---
.../bindings/pinctrl/pinctrl-stixxxx.txt | 160 +++
drivers/pinctrl/Kconfig | 13 +
drivers/pinctrl/Makefile | 1 +
drivers/pinctrl/pinctrl-stixxxx.c | 1151 ++++++++++++++++++++
drivers/pinctrl/pinctrl-stixxxx.h | 197 ++++
5 files changed, 1522 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pinctrl/pinctrl-stixxxx.txt
create mode 100644 drivers/pinctrl/pinctrl-stixxxx.c
create mode 100644 drivers/pinctrl/pinctrl-stixxxx.h
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-stixxxx.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-stixxxx.txt
new file mode 100644
index 0000000..b0a93b5
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-stixxxx.txt
@@ -0,0 +1,160 @@
+*ST pin controller.
+
+Each multi-function pin is controlled, driven and routed through the
+PIO multiplexing block. Each pin supports GPIO functionality (ALT0)
+and multiple alternate functions(ALT1 - ALTx) that directly connect
+the pin to different hardware blocks.
+
+When a pin is in GPIO mode, Output Enable (OE), Open Drain(OD), and
+Pull Up (PU) are driven by the related PIO block.
+
+ST pinctrl driver controls PIO multiplexing block and also interacts with
+gpio driver to configure a pin.
+
+Required properties: (PIO multiplexing block)
+- compatible : should be "st,stixxxx-pinctrl"
+ each subnode should set "st,stixxxx-gpio"
+ as compatible for each gpio-controller bank.
+- gpio-controller : Indicates this device is a GPIO controller
+- #gpio-cells : Should be one. The first cell is the pin number.
+- #retime-delay-cells : Should be number of possible retime delays.
+- st,retime-in-delay : Should be array of delays in nsecs.
+- st,retime-out-delay : Should be array of delays in nsecs.
+- retime-style : Should indicate which type of retime is used.
+ possible values are "none", "packed" and "dedicated".
+- st,retime-offset : phandle to retime offsets in retime registers.
+ These are not necessary for "dedicated" retime-style registers.
+ - clk1notclk0 : Should define offset for clk1not clk0 in retime register.
+ - delay-lsb : Should define offset for delay-lsb in retime register.
+ - delay-msb : Should define offset for delay msb in retime register.
+ - invertclk : Should define offset for invertclk in retime register.
+ - retime : Should define offset for retime in retime register.
+ - clknotdata : Should define offset for clknotdata in retime register.
+ - double_edge : Should define offset for double edge in retime register.
+- st,alt-control : Should be sysconf to control alternate function on pio.
+- st,oe-control : Should be sysconf to control output enable on pio.
+- st,pu-control : Should be sysconf to control pull up on pio.
+- st,od-control : Should be sysconf to control open drain on pio.
+- st,retime-style : Should indicate which type of retime is used.
+ possible values are "none", "packed" and "dedicated".
+- st,retime-pin-mask : Should be mask to specify which pins can be retimed.
+- retime-control[0...N]: These properties point to sysconfs which control retime.
+ Depending on retime-style the number of retime-controls
+ vary: 2 for "packed"; 8 for "dedicated".
+- st,bank-name : Should be a name string for this bank.
+
+Example:
+ pio_retime_offset: pio-retime-offset {
+ clk1notclk0 = <0>;
+ delay-lsb = <2>;
+ delay-msb = <3>;
+ invertclk = <4>;
+ retime = <5>;
+ clknotdata = <6>;
+ double-edge = <7>;
+ };
+
+ pin-controller {
+ #retime-delay-cells = <4>;
+ compatible = "st,stixxxx-pinctrl", "simple-bus";
+ st,retime-offset = <&pio_retime_offset>;
+ st,retime-in-delay = <0 500 1000 1500>;
+ st,retime-out-delay = <0 1000 2000 3000>;
+ ranges;
+ PIO0: pinctrl@fe610000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfe610000 0x100>;
+ st,bank-name = "PIO0";
+ st,alt-control = <&SYSCONF_SBC(0) 0 31>;
+ st,oe-control = <&SYSCONF_SBC(5) 0 7>;
+ st,pu-control = <&SYSCONF_SBC(7) 0 7>;
+ st,od-control = <&SYSCONF_SBC(9) 0 7>;
+ st,retime-style = "packed";
+ st,retime-pin-mask = <0xff>;
+ st,retime-control0 = <&SYSCONF_SBC(16) 0 31>;
+ st,retime-control1 = <&SYSCONF_SBC(17) 0 31>;
+ };
+ ...
+ pin-functions nodes follow...
+ };
+
+
+Contents of function subnode node:
+----------------------
+Required properties for pin configuration node:
+- st,function : Should be alternate function number associated
+ with this set of pins.
+ possible altfunction values:
+ ALT1
+ ALT2
+ ALT3
+ ALT4
+ ALT5
+ ALT6
+ ALT7
+
+- st,pins : Child node with list of pins with configuration.
+
+Below is the format of how each pin conf should look like.
+
+<bank offset mode rt_type rt_delay rt_clk>
+
+Every PIO is represented with 4-7 parameters depending on retime configuration.
+Each parameter is explained as below.
+
+-bank : Should be bank phandle to which this PIO belongs.
+-offset : Offset in the PIO bank.
+-mode :pin configuration is selected from one of the below values.
+ IN
+ IN_PU
+ OUT
+ BIDIR
+ BIDIR_PU
+
+-rt_type Retiming Configuration for the pin.
+ Possible retime configuration are:
+
+ ------- -------------
+ value args
+ ------- -------------
+ NICLK <delay> <clk>
+ ICLK_IO <delay> <clk>
+ BYPASS <delay>
+ DE_IO <delay> <clk>
+ SE_ICLK_IO <delay> <clk>
+ SE_NICLK_IO <delay> <clk>
+
+- delay is retime delay in pico seconds.
+ Possible values are: refer to retime-in/out-delays
+
+- rt_clk :clk to be use for retime.
+ Possible values are:
+ CLK_A
+ CLK_B
+ CLK_C
+ CLK_D
+
+Example of mmcclk pin which is a bi-direction pull pu with retime config
+as non inverted clock retimed with CLK_B and delay of 0 pico seconds:
+
+pin-controller {
+ ...
+ mmc0 {
+ pinctrl_mmc: mmc {
+ st,function = <ALT4>;
+ st,pins {
+ mmcclk = <&PIO13 4 BIDIR_PU NICLK 0 CLK_B>;
+ ...
+ };
+ };
+ ...
+ };
+};
+
+sdhci0:sdhci@fe810000{
+ ...
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mmc>;
+};
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 34f51d2..611a399 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -179,6 +179,19 @@ config PINCTRL_SUNXI
select PINMUX
select GENERIC_PINCONF
+config PINCTRL_STIXXXX
+ bool "ST Microelectronics pin controller driver for STixxxx SoCs"
+ depends on PLAT_STIXXXX
+ select PINMUX
+ select PINCONF
+ select MFD_SYSCON
+ help
+ Say yes here to support pinctrl interface on STixxxx SOCs.
+ This driver is used to control both PIO block and PIO-mux
+ block to configure a pin.
+
+ If unsure, say N.
+
config PINCTRL_TEGRA
bool
select PINMUX
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index f82cc5b..99a2c78 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_PINCTRL_EXYNOS) += pinctrl-exynos.o
obj-$(CONFIG_PINCTRL_EXYNOS5440) += pinctrl-exynos5440.o
obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
+obj-$(CONFIG_PINCTRL_STIXXXX) += pinctrl-stixxxx.o
obj-$(CONFIG_PLAT_ORION) += mvebu/
obj-$(CONFIG_ARCH_SHMOBILE) += sh-pfc/
diff --git a/drivers/pinctrl/pinctrl-stixxxx.c b/drivers/pinctrl/pinctrl-stixxxx.c
new file mode 100644
index 0000000..7d2c59c
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-stixxxx.c
@@ -0,0 +1,1151 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Authors:
+ * Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_address.h>
+#include <linux/mfd/syscon.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/platform_device.h>
+#include "core.h"
+#include "pinctrl-stixxxx.h"
+
+struct stixxxx_pinconf {
+ int pin;
+ const char *name;
+ unsigned long config;
+};
+
+struct stixxxx_pmx_func {
+ const char *name;
+ const char **groups;
+ unsigned ngroups;
+};
+
+struct stixxxx_pctl_group {
+ const char *name;
+ unsigned int *pins;
+ unsigned npins;
+ int altfunc;
+ struct stixxxx_pinconf *pin_conf;
+};
+
+#define to_stixxxx_gpio_port(chip) \
+ container_of(chip, struct stixxxx_gpio_port, gpio_chip)
+
+struct stixxxx_gpio_port {
+ struct gpio_chip gpio_chip;
+ struct pinctrl_gpio_range range;
+ void __iomem *base;
+ struct device_node *of_node;
+ const char *bank_name;
+};
+
+static struct stixxxx_gpio_port *gpio_ports[STIXXXX_MAX_GPIO_BANKS];
+
+struct stixxxx_pinctrl {
+ struct device *dev;
+ struct pinctrl_dev *pctl;
+ int nbanks;
+ struct stixxxx_pmx_func *functions;
+ int nfunctions;
+ struct stixxxx_pctl_group *groups;
+ int ngroups;
+ struct stixxxx_pio_control *pio_controls;
+};
+
+/* Low level functions.. */
+static void stixxxx_pinconf_set_direction(struct stixxxx_pio_control *pc,
+ int pin_id, unsigned long config)
+{
+ struct syscon_field *output_enable;
+ struct syscon_field *pull_up;
+ struct syscon_field *open_drain;
+ unsigned long oe_value, pu_value, od_value;
+ unsigned long mask;
+ int pin = stixxxx_gpio_pin(pin_id);
+
+ output_enable = pc->oe;
+ pull_up = pc->pu;
+ open_drain = pc->od;
+
+ mask = BIT(pin);
+
+ oe_value = syscon_read(output_enable);
+ pu_value = syscon_read(pull_up);
+ od_value = syscon_read(open_drain);
+
+ /* Clear old values */
+ oe_value &= ~mask;
+ pu_value &= ~mask;
+ od_value &= ~mask;
+
+ if (config & STIXXXX_PINCONF_OE)
+ oe_value |= mask;
+ if (config & STIXXXX_PINCONF_PU)
+ pu_value |= mask;
+ if (config & STIXXXX_PINCONF_OD)
+ od_value |= mask;
+
+ syscon_write(output_enable, oe_value);
+ syscon_write(pull_up, pu_value);
+ syscon_write(open_drain, od_value);
+}
+
+static void stixxxx_pctl_set_function(struct stixxxx_pio_control *pc,
+ int pin_id, int function)
+{
+ struct syscon_field *selector;
+ int offset;
+ unsigned long val;
+ int pin = stixxxx_gpio_pin(pin_id);
+
+ selector = pc->alt;
+ offset = pin * 4;
+ val = syscon_read(selector);
+ val &= ~(0xf << offset);
+ val |= function << offset;
+ syscon_write(selector, val);
+}
+
+static unsigned long stixxxx_pinconf_delay_to_bit(unsigned int delay,
+ const struct stixxxx_retime_params *rt_params,
+ unsigned long config)
+{
+ unsigned int *delay_times;
+ int num_delay_times, i, closest_index = -1;
+ unsigned int closest_divergence = UINT_MAX;
+
+ if (STIXXXX_PINCONF_UNPACK_OE(config)) {
+ delay_times = rt_params->delay_times_out;
+ num_delay_times = rt_params->num_delay_times_out;
+ } else {
+ delay_times = rt_params->delay_times_in;
+ num_delay_times = rt_params->num_delay_times_in;
+ }
+
+ for (i = 0; i < num_delay_times; i++) {
+ unsigned int divergence = abs(delay - delay_times[i]);
+
+ if (divergence == 0)
+ return i;
+
+ if (divergence < closest_divergence) {
+ closest_divergence = divergence;
+ closest_index = i;
+ }
+ }
+
+ pr_warn("Attempt to set delay %d, closest available %d\n",
+ delay, delay_times[closest_index]);
+
+ return closest_index;
+}
+
+static unsigned long stixxxx_pinconf_bit_to_delay(unsigned int index,
+ const struct stixxxx_retime_params *rt_params,
+ unsigned long output)
+{
+ unsigned int *delay_times;
+ int num_delay_times;
+
+ if (output) {
+ delay_times = rt_params->delay_times_out;
+ num_delay_times = rt_params->num_delay_times_out;
+ } else {
+ delay_times = rt_params->delay_times_in;
+ num_delay_times = rt_params->num_delay_times_in;
+ }
+
+ if (index < num_delay_times) {
+ return delay_times[index];
+ } else {
+ pr_warn("Delay not found in/out delay list\n");
+ return 0;
+ }
+}
+
+static void stixxxx_pinconf_set_retime_packed(
+ struct stixxxx_pio_control *pc,
+ unsigned long config, int pin)
+{
+ const struct stixxxx_retime_params *rt_params = pc->rt_params;
+ const struct stixxxx_retime_offset *offset = rt_params->retime_offset;
+ struct syscon_field **regs;
+ unsigned long values[2];
+ unsigned long mask;
+ int i, j;
+ int clk = STIXXXX_PINCONF_UNPACK_RT_CLK(config);
+ int clknotdata = STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(config);
+ int double_edge = STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(config);
+ int invertclk = STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(config);
+ int retime = STIXXXX_PINCONF_UNPACK_RT(config);
+ unsigned long delay = stixxxx_pinconf_delay_to_bit(
+ STIXXXX_PINCONF_UNPACK_RT_DELAY(config),
+ pc->rt_params, config);
+
+ unsigned long rt_cfg =
+ ((clk & 1) << offset->clk1notclk0_offset) |
+ ((clknotdata & 1) << offset->clknotdata_offset) |
+ ((delay & 1) << offset->delay_lsb_offset) |
+ (((delay >> 1) & 1) << offset->delay_msb_offset) |
+ ((double_edge & 1) << offset->double_edge_offset) |
+ ((invertclk & 1) << offset->invertclk_offset) |
+ ((retime & 1) << offset->retime_offset);
+
+ regs = pc->retiming;
+ values[0] = syscon_read(regs[0]);
+ values[1] = syscon_read(regs[1]);
+
+ for (i = 0; i < 2; i++) {
+ mask = BIT(pin);
+ for (j = 0; j < 4; j++) {
+ if (rt_cfg & 1)
+ values[i] |= mask;
+ else
+ values[i] &= ~mask;
+ mask <<= 8;
+ rt_cfg >>= 1;
+ }
+ }
+
+ syscon_write(regs[0], values[0]);
+ syscon_write(regs[1], values[1]);
+}
+
+static void stixxxx_pinconf_set_retime_dedicated(
+ struct stixxxx_pio_control *pc,
+ unsigned long config, int pin)
+{
+ struct syscon_field *reg;
+ int input = STIXXXX_PINCONF_UNPACK_OE(config) ? 0 : 1;
+ int clk = STIXXXX_PINCONF_UNPACK_RT_CLK(config);
+ int clknotdata = STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(config);
+ int double_edge = STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(config);
+ int invertclk = STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(config);
+ int retime = STIXXXX_PINCONF_UNPACK_RT(config);
+ unsigned long delay = stixxxx_pinconf_delay_to_bit(
+ STIXXXX_PINCONF_UNPACK_RT_DELAY(config),
+ pc->rt_params, config);
+
+ unsigned long retime_config =
+ ((clk & 0x3) << 0) |
+ ((clknotdata & 0x1) << 2) |
+ ((delay & 0xf) << 3) |
+ ((input & 0x1) << 7) |
+ ((double_edge & 0x1) << 8) |
+ ((invertclk & 0x1) << 9) |
+ ((retime & 0x1) << 10);
+
+ reg = pc->retiming[pin];
+ syscon_write(reg, retime_config);
+}
+
+static void stixxxx_pinconf_get_direction(struct stixxxx_pio_control *pc,
+ int pin_id, unsigned long *config)
+{
+ unsigned long oe_value, pu_value, od_value;
+ int pin = stixxxx_gpio_pin(pin_id);
+
+ oe_value = (syscon_read(pc->oe) >> pin) & 1;
+ pu_value = (syscon_read(pc->pu) >> pin) & 1;
+ od_value = (syscon_read(pc->od) >> pin) & 1;
+
+ STIXXXX_PINCONF_PACK_OE(*config, oe_value);
+ STIXXXX_PINCONF_PACK_PU(*config, pu_value);
+ STIXXXX_PINCONF_PACK_OD(*config, od_value);
+}
+
+static int stixxxx_pinconf_get_retime_packed(
+ struct stixxxx_pio_control *pc,
+ int pin, unsigned long *config)
+{
+ const struct stixxxx_retime_params *rt_params = pc->rt_params;
+ const struct stixxxx_retime_offset *offset = rt_params->retime_offset;
+ unsigned long delay_bits, delay, rt_reduced;
+ unsigned long rt_value[2];
+ int i, j;
+ int output = STIXXXX_PINCONF_UNPACK_OE(*config);
+
+ rt_value[0] = syscon_read(pc->retiming[0]);
+ rt_value[1] = syscon_read(pc->retiming[1]);
+
+ rt_reduced = 0;
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 4; j++) {
+ if (rt_value[i] & (1<<((8*j)+pin)))
+ rt_reduced |= 1 << ((i*4)+j);
+ }
+ }
+
+ STIXXXX_PINCONF_PACK_RT(*config,
+ (rt_reduced >> offset->retime_offset) & 1);
+ STIXXXX_PINCONF_PACK_RT_CLK(*config,
+ (rt_reduced >> offset->clk1notclk0_offset) & 1);
+ STIXXXX_PINCONF_PACK_RT_CLKNOTDATA(*config,
+ (rt_reduced >> offset->clknotdata_offset) & 1);
+ STIXXXX_PINCONF_PACK_RT_DOUBLE_EDGE(*config,
+ (rt_reduced >> offset->double_edge_offset) & 1);
+ STIXXXX_PINCONF_PACK_RT_INVERTCLK(*config,
+ (rt_reduced >> offset->invertclk_offset) & 1);
+
+ delay_bits = (((rt_reduced >> offset->delay_msb_offset) & 1)<<1) |
+ ((rt_reduced >> offset->delay_lsb_offset) & 1);
+ delay = stixxxx_pinconf_bit_to_delay(delay_bits, rt_params, output);
+ STIXXXX_PINCONF_PACK_RT_DELAY(*config, delay);
+ return 0;
+}
+
+static int stixxxx_pinconf_get_retime_dedicated(
+ struct stixxxx_pio_control *pc,
+ int pin, unsigned long *config)
+{
+ unsigned long value;
+ unsigned long delay_bits, delay;
+ const struct stixxxx_retime_params *rt_params = pc->rt_params;
+ int output = STIXXXX_PINCONF_UNPACK_OE(*config);
+
+ value = syscon_read(pc->retiming[pin]);
+ STIXXXX_PINCONF_PACK_RT_CLK(*config, ((value >> 0) & 0x3));
+ STIXXXX_PINCONF_PACK_RT_CLKNOTDATA(*config, ((value >> 2) & 0x1));
+ delay_bits = ((value >> 3) & 0xf);
+ delay = stixxxx_pinconf_bit_to_delay(delay_bits, rt_params, output);
+ STIXXXX_PINCONF_PACK_RT_DELAY(*config, delay);
+ STIXXXX_PINCONF_PACK_RT_DOUBLE_EDGE(*config, ((value >> 8) & 0x1));
+ STIXXXX_PINCONF_PACK_RT_INVERTCLK(*config, ((value >> 9) & 0x1));
+ STIXXXX_PINCONF_PACK_RT(*config, ((value >> 10) & 0x1));
+
+ return 0;
+}
+
+/* GPIO related functions */
+
+static inline void __stixxxx_gpio_set(struct stixxxx_gpio_port *port,
+ unsigned offset, int value)
+{
+ if (value)
+ writel(BIT(offset), port->base + REG_PIO_SET_POUT);
+ else
+ writel(BIT(offset), port->base + REG_PIO_CLR_POUT);
+}
+
+static void stixxxx_gpio_direction(unsigned int gpio, unsigned int direction)
+{
+ int port_num = stixxxx_gpio_port(gpio);
+ int offset = stixxxx_gpio_pin(gpio);
+ struct stixxxx_gpio_port *port = gpio_ports[port_num];
+ int i = 0;
+
+ for (i = 0; i <= 2; i++) {
+ if (direction & BIT(i))
+ writel(BIT(offset), port->base + REG_PIO_SET_PC(i));
+ else
+ writel(BIT(offset), port->base + REG_PIO_CLR_PC(i));
+ }
+}
+
+static int stixxxx_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void stixxxx_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ pinctrl_free_gpio(chip->base + offset);
+}
+
+static int stixxxx_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct stixxxx_gpio_port *port = to_stixxxx_gpio_port(chip);
+
+ return (readl(port->base + REG_PIO_PIN) >> offset) & 1;
+}
+
+static void stixxxx_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct stixxxx_gpio_port *port = to_stixxxx_gpio_port(chip);
+ __stixxxx_gpio_set(port, offset, value);
+}
+
+static int stixxxx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ pinctrl_gpio_direction_input(chip->base + offset);
+ return 0;
+}
+
+static int stixxxx_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct stixxxx_gpio_port *port = to_stixxxx_gpio_port(chip);
+
+ __stixxxx_gpio_set(port, offset, value);
+ pinctrl_gpio_direction_output(chip->base + offset);
+
+ return 0;
+}
+
+static int stixxxx_gpio_xlate(struct gpio_chip *gc,
+ const struct of_phandle_args *gpiospec, u32 *flags)
+{
+ if (WARN_ON(gc->of_gpio_n_cells < 1))
+ return -EINVAL;
+
+ if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
+ return -EINVAL;
+
+ if (gpiospec->args[0] > gc->ngpio)
+ return -EINVAL;
+
+ return gpiospec->args[0];
+}
+
+/* Pinctrl Groups */
+static int stixxxx_pctl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ return info->ngroups;
+}
+
+static const char *stixxxx_pctl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ return info->groups[selector].name;
+}
+
+static int stixxxx_pctl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned selector, const unsigned **pins, unsigned *npins)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ if (selector >= info->ngroups)
+ return -EINVAL;
+
+ *pins = info->groups[selector].pins;
+ *npins = info->groups[selector].npins;
+
+ return 0;
+}
+
+static const inline struct stixxxx_pctl_group *stixxxx_pctl_find_group_by_name(
+ const struct stixxxx_pinctrl *info, const char *name)
+{
+ int i;
+
+ for (i = 0; i < info->ngroups; i++) {
+ if (!strcmp(info->groups[i].name, name))
+ return &info->groups[i];
+ }
+
+ return NULL;
+}
+
+static int stixxxx_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np, struct pinctrl_map **map, unsigned *num_maps)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ const struct stixxxx_pctl_group *grp;
+ struct pinctrl_map *new_map;
+ struct device_node *parent;
+ int map_num, i;
+
+ grp = stixxxx_pctl_find_group_by_name(info, np->name);
+ if (!grp) {
+ dev_err(info->dev, "unable to find group for node %s\n",
+ np->name);
+ return -EINVAL;
+ }
+
+ map_num = grp->npins + 1;
+ new_map = devm_kzalloc(pctldev->dev,
+ sizeof(*new_map) * map_num, GFP_KERNEL);
+ if (!new_map)
+ return -ENOMEM;
+
+ parent = of_get_parent(np);
+ if (!parent) {
+ devm_kfree(pctldev->dev, new_map);
+ return -EINVAL;
+ }
+
+ *map = new_map;
+ *num_maps = map_num;
+ new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
+ new_map[0].data.mux.function = parent->name;
+ new_map[0].data.mux.group = np->name;
+ of_node_put(parent);
+
+ /* create config map per pin */
+ new_map++;
+ for (i = 0; i < grp->npins; i++) {
+ new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
+ new_map[i].data.configs.group_or_pin =
+ pin_get_name(pctldev, grp->pins[i]);
+ new_map[i].data.configs.configs = &grp->pin_conf[i].config;
+ new_map[i].data.configs.num_configs = 1;
+ }
+ dev_info(pctldev->dev, "maps: function %s group %s num %d\n",
+ (*map)->data.mux.function, grp->name, map_num);
+
+ return 0;
+}
+
+static void stixxxx_pctl_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+}
+
+static struct pinctrl_ops stixxxx_pctlops = {
+ .get_groups_count = stixxxx_pctl_get_groups_count,
+ .get_group_pins = stixxxx_pctl_get_group_pins,
+ .get_group_name = stixxxx_pctl_get_group_name,
+ .dt_node_to_map = stixxxx_pctl_dt_node_to_map,
+ .dt_free_map = stixxxx_pctl_dt_free_map,
+};
+
+/* Pinmux */
+static int stixxxx_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ return info->nfunctions;
+}
+
+const char *stixxxx_pmx_get_fname(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ return info->functions[selector].name;
+}
+
+static int stixxxx_pmx_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector, const char * const **grps, unsigned * const ngrps)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ *grps = info->functions[selector].groups;
+ *ngrps = info->functions[selector].ngroups;
+
+ return 0;
+}
+
+static struct stixxxx_pio_control *stixxxx_get_pio_control(
+ struct stixxxx_pinctrl *info, int pin_id)
+{
+ int port = stixxxx_gpio_port(pin_id);
+ return &info->pio_controls[port];
+}
+
+static int stixxxx_pmx_enable(struct pinctrl_dev *pctldev, unsigned fselector,
+ unsigned group)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ struct stixxxx_pinconf *conf = info->groups[group].pin_conf;
+ struct stixxxx_pio_control *pc;
+ int i;
+
+ for (i = 0; i < info->groups[group].npins; i++) {
+ pc = stixxxx_get_pio_control(info, conf[i].pin);
+ stixxxx_pctl_set_function(pc, conf[i].pin,
+ info->groups[group].altfunc);
+ }
+
+ return 0;
+}
+
+static void stixxxx_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+}
+
+static int stixxxx_pmx_set_gpio_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range, unsigned gpio,
+ bool input)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ struct stixxxx_pio_control *pc = &info->pio_controls[range->id];
+ /*
+ * When a PIO port is used in its primary function mode (altfunc = 0)
+ * Output Enable (OE), Open Drain(OD), and Pull Up (PU)
+ * for the primary PIO functions are driven by the related PIO block
+ */
+ stixxxx_pctl_set_function(pc, gpio, 0);
+ stixxxx_gpio_direction(gpio, input ?
+ STIXXXX_GPIO_DIRECTION_IN : STIXXXX_GPIO_DIRECTION_OUT);
+
+ return 0;
+}
+
+static struct pinmux_ops stixxxx_pmxops = {
+ .get_functions_count = stixxxx_pmx_get_funcs_count,
+ .get_function_name = stixxxx_pmx_get_fname,
+ .get_function_groups = stixxxx_pmx_get_groups,
+ .enable = stixxxx_pmx_enable,
+ .disable = stixxxx_pmx_disable,
+ .gpio_set_direction = stixxxx_pmx_set_gpio_direction,
+};
+
+/* Pinconf */
+static void stixxxx_pinconf_get_retime(struct stixxxx_pio_control *pc,
+ int pin_id, unsigned long *config)
+{
+ int pin = stixxxx_gpio_pin(pin_id);
+ if (pc->rt_style == stixxxx_retime_style_packed)
+ stixxxx_pinconf_get_retime_packed(pc, pin, config);
+ else if (pc->rt_style == stixxxx_retime_style_dedicated)
+ if ((BIT(pin) & pc->rt_pin_mask))
+ stixxxx_pinconf_get_retime_dedicated(pc, pin, config);
+}
+
+static void stixxxx_pinconf_set_retime(struct stixxxx_pio_control *pc,
+ int pin_id, unsigned long config)
+{
+ int pin = stixxxx_gpio_pin(pin_id);
+
+ if (pc->rt_style == stixxxx_retime_style_packed)
+ stixxxx_pinconf_set_retime_packed(pc, config, pin);
+ else if (pc->rt_style == stixxxx_retime_style_dedicated)
+ if ((BIT(pin) & pc->rt_pin_mask))
+ stixxxx_pinconf_set_retime_dedicated(pc, config, pin);
+}
+
+static int stixxxx_pinconf_set(struct pinctrl_dev *pctldev,
+ unsigned pin_id, unsigned long config)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ struct stixxxx_pio_control *pc = stixxxx_get_pio_control(info, pin_id);
+
+ stixxxx_pinconf_set_direction(pc, pin_id, config);
+ stixxxx_pinconf_set_retime(pc, pin_id, config);
+ return 0;
+}
+
+static int stixxxx_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned pin_id, unsigned long *config)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ struct stixxxx_pio_control *pc = stixxxx_get_pio_control(info, pin_id);
+
+ *config = 0;
+ stixxxx_pinconf_get_direction(pc, pin_id, config);
+ stixxxx_pinconf_get_retime(pc, pin_id, config);
+
+ return 0;
+}
+
+static void stixxxx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned pin_id)
+{
+ unsigned long config;
+ stixxxx_pinconf_get(pctldev, pin_id, &config);
+
+ seq_printf(s, "[OE:%ld,PU:%ld,OD:%ld]\n"
+ "\t\t[retime:%ld,invclk:%ld,clknotdat:%ld,"
+ "de:%ld,rt-clk:%ld,rt-delay:%ld]",
+ STIXXXX_PINCONF_UNPACK_OE(config),
+ STIXXXX_PINCONF_UNPACK_PU(config),
+ STIXXXX_PINCONF_UNPACK_OD(config),
+ STIXXXX_PINCONF_UNPACK_RT(config),
+ STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(config),
+ STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(config),
+ STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(config),
+ STIXXXX_PINCONF_UNPACK_RT_CLK(config),
+ STIXXXX_PINCONF_UNPACK_RT_DELAY(config));
+}
+
+static struct pinconf_ops stixxxx_confops = {
+ .pin_config_get = stixxxx_pinconf_get,
+ .pin_config_set = stixxxx_pinconf_set,
+ .pin_config_dbg_show = stixxxx_pinconf_dbg_show,
+};
+
+/* pinctrl */
+static struct pinctrl_desc stixxxx_pctl_desc = {
+ .owner = THIS_MODULE,
+ .pctlops = &stixxxx_pctlops,
+ .pmxops = &stixxxx_pmxops,
+ .confops = &stixxxx_confops,
+};
+
+static int stixxxx_pinconf_dt_parse_rt_params(struct stixxxx_pinctrl *info,
+ struct device_node *np, struct stixxxx_retime_params *params)
+{
+ const __be32 *ip;
+ struct device_node *offset_np;
+ struct stixxxx_retime_offset *rt_offset;
+ int delay_count = 0;
+
+ ip = of_get_property(np, "#retime-delay-cells", NULL);
+ if (ip)
+ delay_count = be32_to_cpup(ip);
+ else
+ pr_warn("No #retime-delay-cells specified\n");
+
+ params->num_delay_times_out = delay_count;
+ params->num_delay_times_in = delay_count;
+ params->delay_times_in = devm_kzalloc(info->dev,
+ sizeof(u32) * delay_count, GFP_KERNEL);
+ params->delay_times_out = devm_kzalloc(info->dev,
+ sizeof(u32) * delay_count, GFP_KERNEL);
+
+ if (!params->delay_times_in || !params->delay_times_out)
+ return -ENOMEM;
+
+ of_property_read_u32_array(np, "st,retime-in-delay",
+ (u32 *)params->delay_times_in, delay_count);
+ of_property_read_u32_array(np, "st,retime-out-delay",
+ (u32 *)params->delay_times_out, delay_count);
+
+ offset_np = of_parse_phandle(np, "st,retime-offset", 0);
+
+ if (offset_np) {
+ rt_offset = devm_kzalloc(info->dev,
+ sizeof(*rt_offset), GFP_KERNEL);
+ if (!rt_offset)
+ return -ENOMEM;
+
+ params->retime_offset = rt_offset;
+ WARN_ON(of_property_read_u32(offset_np, "retime",
+ &rt_offset->retime_offset));
+ WARN_ON(of_property_read_u32(offset_np, "clk1notclk0",
+ &rt_offset->clk1notclk0_offset));
+ WARN_ON(of_property_read_u32(offset_np, "clknotdata",
+ &rt_offset->clknotdata_offset));
+ WARN_ON(of_property_read_u32(offset_np, "double-edge",
+ &rt_offset->double_edge_offset));
+ WARN_ON(of_property_read_u32(offset_np, "invertclk",
+ &rt_offset->invertclk_offset));
+ WARN_ON(of_property_read_u32(offset_np, "delay-lsb",
+ &rt_offset->delay_lsb_offset));
+ WARN_ON(of_property_read_u32(offset_np, "delay-msb",
+ &rt_offset->delay_msb_offset));
+ }
+
+ return 0;
+}
+
+static const char *gpio_compat = "st,stixxxx-gpio";
+
+static void stixxxx_pctl_dt_child_count(struct stixxxx_pinctrl *info,
+ struct device_node *np)
+{
+ struct device_node *child;
+ for_each_child_of_node(np, child) {
+ if (of_device_is_compatible(child, gpio_compat)) {
+ info->nbanks++;
+ } else {
+ info->nfunctions++;
+ info->ngroups += of_get_child_count(child);
+ }
+ }
+}
+
+static int stixxxx_pctl_dt_get_retime_conf(struct device_node *np,
+ struct stixxxx_pio_control *pc)
+{
+ const char *style;
+ char name[20];
+ unsigned int j;
+ of_property_read_string(np, "st,retime-style", &style);
+
+ if (strcmp(style, "packed") == 0) {
+ pc->rt_style = stixxxx_retime_style_packed;
+ for (j = 0; j < 2; j++) {
+ snprintf(name, sizeof(name), "st,retime-control%d", j);
+ pc->retiming[j] = syscon_claim(np, name);
+ if (!pc->retiming[j])
+ return -ENODATA;
+ }
+ } else if (strcmp(style, "dedicated") == 0) {
+ pc->rt_style = stixxxx_retime_style_dedicated;
+ for (j = 0; j < 8; j++) {
+ if ((1<<j) & pc->rt_pin_mask) {
+ snprintf(name, sizeof(name),
+ "st,retime-control%d", j);
+ pc->retiming[j] = syscon_claim(np, name);
+ if (!pc->retiming[j])
+ return -ENODATA;
+ }
+ }
+ } else if (strcmp(style, "none") == 0) {
+ pc->rt_style = stixxxx_retime_style_none;
+ }
+
+ return 0;
+}
+
+static int stixxxx_pctl_dt_init(struct stixxxx_pinctrl *info,
+ struct device_node *np)
+{
+ struct stixxxx_pio_control *pc;
+ struct stixxxx_retime_params *rt_params;
+ struct device *dev = info->dev;
+ unsigned int i = 0;
+ struct device_node *child = NULL;
+
+ pc = devm_kzalloc(dev, sizeof(*pc) * info->nbanks, GFP_KERNEL);
+ rt_params = devm_kzalloc(dev, sizeof(*rt_params), GFP_KERNEL);
+
+ if (!pc || !rt_params)
+ return -ENOMEM;
+
+ info->pio_controls = pc;
+ if (stixxxx_pinconf_dt_parse_rt_params(info, np, rt_params))
+ return -ENOMEM;
+
+ for_each_child_of_node(np, child) {
+ if (of_device_is_compatible(child, gpio_compat)) {
+ pc[i].rt_params = rt_params;
+
+ pc[i].alt = syscon_claim(child, "st,alt-control");
+ if (!pc[i].alt)
+ goto failed;
+
+ pc[i].oe = syscon_claim(child, "st,oe-control");
+ if (!pc[i].oe)
+ goto failed;
+
+ pc[i].pu = syscon_claim(child, "st,pu-control");
+ if (!pc[i].pu)
+ goto failed;
+
+ pc[i].od = syscon_claim(child, "st,od-control");
+ if (!pc[i].od)
+ goto failed;
+
+ of_property_read_u32(child, "st,retime-pin-mask",
+ &pc[i].rt_pin_mask);
+
+ stixxxx_pctl_dt_get_retime_conf(child, &pc[i]);
+ i++;
+ }
+ }
+
+ return 0;
+failed:
+ return -ENODATA;
+}
+
+#define OF_GPIO_ARGS_MIN (3)
+/*
+ * Each pin is represented in of the below forms.
+ * <bank offset direction func rt_type rt_delay rt_clk>
+ */
+static int stixxxx_pctl_dt_parse_groups(struct device_node *np,
+ struct stixxxx_pctl_group *grp, struct stixxxx_pinctrl *info, int idx)
+{
+ /* bank pad direction val altfunction */
+ const __be32 *list;
+ struct property *pp;
+ struct stixxxx_pinconf *conf;
+ phandle phandle;
+ struct device_node *pins;
+ u32 pin;
+ int i = 0, npins = 0, nr_props;
+
+ pins = of_get_child_by_name(np, "st,pins");
+ if (!pins)
+ return -ENODATA;
+
+ for_each_property_of_node(pins, pp) {
+ /* Skip those we do not want to proceed */
+ if (!strcmp(pp->name, "name"))
+ continue;
+
+ if (pp && (pp->length/sizeof(__be32)) >= OF_GPIO_ARGS_MIN) {
+ npins++;
+ } else {
+ pr_warn("Invalid st,pins in %s node\n", np->name);
+ return -EINVAL;
+ }
+ }
+
+ grp->npins = npins;
+ grp->name = np->name;
+ grp->pins = devm_kzalloc(info->dev, npins * sizeof(u32), GFP_KERNEL);
+ grp->pin_conf = devm_kzalloc(info->dev,
+ npins * sizeof(*conf), GFP_KERNEL);
+ of_property_read_u32(np, "st,function", &grp->altfunc);
+
+ if (!grp->pins || !grp->pin_conf)
+ return -ENOMEM;
+
+ /* <bank offset direction func rt_type rt_delay rt_clk> */
+ for_each_property_of_node(pins, pp) {
+ if (!strcmp(pp->name, "name"))
+ continue;
+ nr_props = pp->length/sizeof(u32);
+ list = pp->value;
+ conf = &grp->pin_conf[i];
+
+ /* bank & offset */
+ phandle = be32_to_cpup(list++);
+ pin = be32_to_cpup(list++);
+ conf->pin = of_get_named_gpio(pins, pp->name, 0);
+ conf->name = pp->name;
+ grp->pins[i] = conf->pin;
+
+ conf->config = 0;
+ /* direction */
+ conf->config |= be32_to_cpup(list++);
+ /* rt_type rt_delay rt_clk */
+ if (nr_props >= OF_GPIO_ARGS_MIN + 2) {
+ /* rt_type */
+ conf->config |= be32_to_cpup(list++);
+ /* rt_delay */
+ conf->config |= be32_to_cpup(list++);
+ /* rt_clk */
+ if (nr_props > OF_GPIO_ARGS_MIN + 2)
+ conf->config |= be32_to_cpup(list++);
+ }
+ i++;
+ }
+ of_node_put(pins);
+
+ return 0;
+}
+
+static int stixxxx_pctl_parse_functions(struct device_node *np,
+ struct stixxxx_pinctrl *info, u32 index, int *grp_index)
+{
+ struct device_node *child;
+ struct stixxxx_pmx_func *func;
+ struct stixxxx_pctl_group *grp;
+ int ret, i;
+
+ func = &info->functions[index];
+ func->name = np->name;
+ func->ngroups = of_get_child_count(np);
+ if (func->ngroups <= 0) {
+ dev_err(info->dev, "No groups defined\n");
+ return -EINVAL;
+ }
+ func->groups = devm_kzalloc(info->dev,
+ func->ngroups * sizeof(char *), GFP_KERNEL);
+ if (!func->groups)
+ return -ENOMEM;
+
+ i = 0;
+ for_each_child_of_node(np, child) {
+ func->groups[i] = child->name;
+ grp = &info->groups[*grp_index];
+ *grp_index += 1;
+ ret = stixxxx_pctl_dt_parse_groups(child, grp, info, i++);
+ if (ret)
+ return ret;
+ }
+ dev_info(info->dev, "Function[%d\t name:%s,\tgroups:%d]\n",
+ index, func->name, func->ngroups);
+
+ return 0;
+}
+
+static int stixxxx_pctl_probe_dt(struct platform_device *pdev,
+ struct stixxxx_pinctrl *info)
+{
+ int ret = 0;
+ int i = 0, j = 0, k = 0;
+ struct pinctrl_pin_desc *pdesc;
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *child;
+ int grp_index = 0;
+
+ stixxxx_pctl_dt_child_count(info, np);
+ if (info->nbanks < 1) {
+ dev_err(&pdev->dev, "you need atleast one gpio bank\n");
+ return -EINVAL;
+ }
+
+ ret = stixxxx_pctl_dt_init(info, np);
+ if (ret)
+ return ret;
+
+ dev_info(&pdev->dev, "nbanks = %d\n", info->nbanks);
+ dev_info(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+ dev_info(&pdev->dev, "ngroups = %d\n", info->ngroups);
+ info->functions = devm_kzalloc(&pdev->dev,
+ info->nfunctions * sizeof(*info->functions), GFP_KERNEL);
+
+ info->groups = devm_kzalloc(&pdev->dev,
+ info->ngroups * sizeof(*info->groups) , GFP_KERNEL);
+
+ if (!info->functions || !info->groups)
+ return -ENOMEM;
+
+ stixxxx_pctl_desc.npins = info->nbanks * STIXXXX_GPIO_PINS_PER_PORT;
+ pdesc = devm_kzalloc(&pdev->dev,
+ sizeof(*pdesc) * stixxxx_pctl_desc.npins, GFP_KERNEL);
+ if (!pdesc)
+ return -ENOMEM;
+
+ stixxxx_pctl_desc.pins = pdesc;
+
+ for_each_child_of_node(np, child) {
+ if (of_device_is_compatible(child, gpio_compat)) {
+ for (j = 0; j < STIXXXX_GPIO_PINS_PER_PORT; j++, k++) {
+ const char *port_name = NULL;
+ pdesc->number = k;
+ of_property_read_string(child, "st,bank-name",
+ &port_name);
+ pdesc->name = kasprintf(GFP_KERNEL, "%s[%d]",
+ port_name ? : "PIO",
+ port_name ? j : k);
+ pdesc++;
+ }
+ } else {
+ ret = stixxxx_pctl_parse_functions(child, info,
+ i++, &grp_index);
+ if (ret) {
+ dev_err(&pdev->dev, "No functions found.\n");
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int stixxxx_pctl_probe(struct platform_device *pdev)
+{
+ struct stixxxx_pinctrl *info;
+ int ret, i;
+
+ if (!pdev->dev.of_node) {
+ dev_err(&pdev->dev, "device node not found.\n");
+ return -EINVAL;
+ }
+
+ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->dev = &pdev->dev;
+ platform_set_drvdata(pdev, info);
+ ret = stixxxx_pctl_probe_dt(pdev, info);
+ if (ret)
+ return ret;
+
+ stixxxx_pctl_desc.name = dev_name(&pdev->dev);
+ info->pctl = pinctrl_register(&stixxxx_pctl_desc, &pdev->dev, info);
+ if (IS_ERR(info->pctl)) {
+ dev_err(&pdev->dev, "Failed pinctrl registration\n");
+ return PTR_ERR(info->pctl);
+ }
+
+ for (i = 0; i < info->nbanks; i++)
+ pinctrl_add_gpio_range(info->pctl, &gpio_ports[i]->range);
+
+ return 0;
+}
+
+static struct gpio_chip stixxxx_gpio_template = {
+ .request = stixxxx_gpio_request,
+ .free = stixxxx_gpio_free,
+ .get = stixxxx_gpio_get,
+ .set = stixxxx_gpio_set,
+ .direction_input = stixxxx_gpio_direction_input,
+ .direction_output = stixxxx_gpio_direction_output,
+ .ngpio = STIXXXX_GPIO_PINS_PER_PORT,
+ .of_gpio_n_cells = 1,
+ .of_xlate = stixxxx_gpio_xlate,
+};
+
+static int stixxxx_gpio_probe(struct platform_device *pdev)
+{
+ struct stixxxx_gpio_port *port;
+ struct pinctrl_gpio_range *range;
+ struct device_node *np = pdev->dev.of_node;
+ int port_num = of_alias_get_id(np, "gpio");
+ struct resource *res;
+ int err;
+
+ port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
+ if (!port)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ port->base = devm_request_and_ioremap(&pdev->dev, res);
+ if (!port->base) {
+ dev_err(&pdev->dev, "Can't get IO memory mapping!\n");
+ return -ENODEV;
+ }
+
+ of_property_read_string(np, "st,bank-name", &port->bank_name);
+ port->of_node = np;
+
+ port->gpio_chip = stixxxx_gpio_template;
+ port->gpio_chip.base = port_num * STIXXXX_GPIO_PINS_PER_PORT;
+ port->gpio_chip.ngpio = STIXXXX_GPIO_PINS_PER_PORT;
+ port->gpio_chip.of_node = np;
+ port->gpio_chip.label = dev_name(&pdev->dev);
+
+ dev_set_drvdata(&pdev->dev, port);
+ range = &port->range;
+ range->name = port->gpio_chip.label;
+ range->id = port_num;
+ range->pin_base = range->base = range->id * STIXXXX_GPIO_PINS_PER_PORT;
+ range->npins = port->gpio_chip.ngpio;
+ range->gc = &port->gpio_chip;
+ gpio_ports[port_num] = port;
+ err = gpiochip_add(&port->gpio_chip);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to add gpiochip(%d)!\n", port_num);
+ return err;
+ }
+ dev_info(&pdev->dev, "gpioport[%s] Added as bank%d\n",
+ port->bank_name, port_num);
+ return 0;
+}
+
+static struct of_device_id stixxxx_gpio_of_match[] = {
+ { .compatible = "st,stixxxx-gpio", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver stixxxx_gpio_driver = {
+ .driver = {
+ .name = "st-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(stixxxx_gpio_of_match),
+ },
+ .probe = stixxxx_gpio_probe,
+};
+
+static struct of_device_id stixxxx_pctl_of_match[] = {
+ { .compatible = "st,stixxxx-pinctrl",},
+ { /* sentinel */ }
+};
+
+static struct platform_driver stixxxx_pctl_driver = {
+ .driver = {
+ .name = "st-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(stixxxx_pctl_of_match),
+ },
+ .probe = stixxxx_pctl_probe,
+};
+
+static int __init stixxxx_pctl_init(void)
+{
+ int ret = platform_driver_register(&stixxxx_gpio_driver);
+ if (ret)
+ return ret;
+ return platform_driver_register(&stixxxx_pctl_driver);
+}
+arch_initcall(stixxxx_pctl_init);
diff --git a/drivers/pinctrl/pinctrl-stixxxx.h b/drivers/pinctrl/pinctrl-stixxxx.h
new file mode 100644
index 0000000..a340964
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-stixxxx.h
@@ -0,0 +1,197 @@
+
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Authors:
+ * Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __LINUX_DRIVERS_PINCTRL_STIXXXX_H
+#define __LINUX_DRIVERS_PINCTRL_STIXXXX_H
+
+enum stixxxx_retime_style {
+ stixxxx_retime_style_none,
+ stixxxx_retime_style_packed,
+ stixxxx_retime_style_dedicated,
+};
+
+/* Byte positions in 2 syscon words, starts from 0 */
+struct stixxxx_retime_offset {
+ int retime_offset;
+ int clk1notclk0_offset;
+ int clknotdata_offset;
+ int double_edge_offset;
+ int invertclk_offset;
+ int delay_lsb_offset;
+ int delay_msb_offset;
+};
+
+struct stixxxx_retime_params {
+ const struct stixxxx_retime_offset *retime_offset;
+ unsigned int *delay_times_in;
+ int num_delay_times_in;
+ unsigned int *delay_times_out;
+ int num_delay_times_out;
+};
+
+struct stixxxx_pio_control {
+ enum stixxxx_retime_style rt_style;
+ u32 rt_pin_mask;
+ const struct stixxxx_retime_params *rt_params;
+ struct syscon_field *alt;
+ struct syscon_field *oe, *pu, *od;
+ struct syscon_field *retiming[8];
+};
+
+/* PIO Block registers */
+/* PIO output */
+#define REG_PIO_POUT 0x00
+/* Set bits of POUT */
+#define REG_PIO_SET_POUT 0x04
+/* Clear bits of POUT */
+#define REG_PIO_CLR_POUT 0x08
+/* PIO input */
+#define REG_PIO_PIN 0x10
+/* PIO configuration */
+#define REG_PIO_PC(n) (0x20 + (n) * 0x10)
+/* Set bits of PC[2:0] */
+#define REG_PIO_SET_PC(n) (0x24 + (n) * 0x10)
+/* Clear bits of PC[2:0] */
+#define REG_PIO_CLR_PC(n) (0x28 + (n) * 0x10)
+/* PIO input comparison */
+#define REG_PIO_PCOMP 0x50
+/* Set bits of PCOMP */
+#define REG_PIO_SET_PCOMP 0x54
+/* Clear bits of PCOMP */
+#define REG_PIO_CLR_PCOMP 0x58
+/* PIO input comparison mask */
+#define REG_PIO_PMASK 0x60
+/* Set bits of PMASK */
+#define REG_PIO_SET_PMASK 0x64
+/* Clear bits of PMASK */
+#define REG_PIO_CLR_PMASK 0x68
+
+#define STIXXXX_MAX_GPIO_BANKS 32
+
+#define STIXXXX_GPIO_DIRECTION_BIDIR 0x1
+#define STIXXXX_GPIO_DIRECTION_OUT 0x2
+#define STIXXXX_GPIO_DIRECTION_IN 0x4
+
+#define STIXXXX_GPIO_PINS_PER_PORT 8
+#define stixxxx_gpio_port(gpio) ((gpio) / STIXXXX_GPIO_PINS_PER_PORT)
+#define stixxxx_gpio_pin(gpio) ((gpio) % STIXXXX_GPIO_PINS_PER_PORT)
+
+/* pinconf */
+/*
+ * Pinconf is represented in an opaque unsigned long variable.
+ * Below is the bit allocation details for each possible configuration.
+ * All the bit fields can be encapsulated into four variables
+ * (direction, retime-type, retime-clk, retime-delay)
+ *
+ * +----------------+
+ *[31:28]| reserved-3 |
+ * +----------------+-------------
+ *[27] | oe | |
+ * +----------------+ v
+ *[26] | pu | [Direction ]
+ * +----------------+ ^
+ *[25] | od | |
+ * +----------------+-------------
+ *[24] | reserved-2 |
+ * +----------------+-------------
+ *[23] | retime | |
+ * +----------------+ |
+ *[22] | retime-invclk | |
+ * +----------------+ v
+ *[21] |retime-clknotdat| [Retime-type ]
+ * +----------------+ ^
+ *[20] | retime-de | |
+ * +----------------+-------------
+ *[19:18]| retime-clk |------>[Retime-Clk ]
+ * +----------------+
+ *[17:16]| reserved-1 |
+ * +----------------+
+ *[15..0]| retime-delay |------>[Retime Delay]
+ * +----------------+
+ */
+
+#define STIXXXX_PINCONF_UNPACK(conf, param)\
+ ((conf >> STIXXXX_PINCONF_ ##param ##_SHIFT) \
+ & STIXXXX_PINCONF_ ##param ##_MASK)
+
+#define STIXXXX_PINCONF_PACK(conf, val, param) (conf |=\
+ ((val & STIXXXX_PINCONF_ ##param ##_MASK) << \
+ STIXXXX_PINCONF_ ##param ##_SHIFT))
+
+/* Output enable */
+#define STIXXXX_PINCONF_OE_MASK 0x1
+#define STIXXXX_PINCONF_OE_SHIFT 27
+#define STIXXXX_PINCONF_OE BIT(27)
+#define STIXXXX_PINCONF_UNPACK_OE(conf) STIXXXX_PINCONF_UNPACK(conf, OE)
+#define STIXXXX_PINCONF_PACK_OE(conf, val) STIXXXX_PINCONF_PACK(conf, val, OE)
+
+/* Pull Up */
+#define STIXXXX_PINCONF_PU_MASK 0x1
+#define STIXXXX_PINCONF_PU_SHIFT 26
+#define STIXXXX_PINCONF_PU BIT(26)
+#define STIXXXX_PINCONF_UNPACK_PU(conf) STIXXXX_PINCONF_UNPACK(conf, PU)
+#define STIXXXX_PINCONF_PACK_PU(conf, val) STIXXXX_PINCONF_PACK(conf, val, PU)
+
+/* Open Drain */
+#define STIXXXX_PINCONF_OD_MASK 0x1
+#define STIXXXX_PINCONF_OD_SHIFT 25
+#define STIXXXX_PINCONF_OD BIT(25)
+#define STIXXXX_PINCONF_UNPACK_OD(conf) STIXXXX_PINCONF_UNPACK(conf, OD)
+#define STIXXXX_PINCONF_PACK_OD(conf, val) STIXXXX_PINCONF_PACK(conf, val, OD)
+
+#define STIXXXX_PINCONF_RT_MASK 0x1
+#define STIXXXX_PINCONF_RT_SHIFT 23
+#define STIXXXX_PINCONF_RT BIT(23)
+#define STIXXXX_PINCONF_UNPACK_RT(conf) STIXXXX_PINCONF_UNPACK(conf, RT)
+#define STIXXXX_PINCONF_PACK_RT(conf, val) STIXXXX_PINCONF_PACK(conf, val, RT)
+
+#define STIXXXX_PINCONF_RT_INVERTCLK_MASK 0x1
+#define STIXXXX_PINCONF_RT_INVERTCLK_SHIFT 22
+#define STIXXXX_PINCONF_RT_INVERTCLK BIT(22)
+#define STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(conf) \
+ STIXXXX_PINCONF_UNPACK(conf, RT_INVERTCLK)
+#define STIXXXX_PINCONF_PACK_RT_INVERTCLK(conf, val) \
+ STIXXXX_PINCONF_PACK(conf, val, RT_INVERTCLK)
+
+#define STIXXXX_PINCONF_RT_CLKNOTDATA_MASK 0x1
+#define STIXXXX_PINCONF_RT_CLKNOTDATA_SHIFT 21
+#define STIXXXX_PINCONF_RT_CLKNOTDATA BIT(21)
+#define STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(conf) \
+ STIXXXX_PINCONF_UNPACK(conf, RT_CLKNOTDATA)
+#define STIXXXX_PINCONF_PACK_RT_CLKNOTDATA(conf, val) \
+ STIXXXX_PINCONF_PACK(conf, val, RT_CLKNOTDATA)
+
+#define STIXXXX_PINCONF_RT_DOUBLE_EDGE_MASK 0x1
+#define STIXXXX_PINCONF_RT_DOUBLE_EDGE_SHIFT 20
+#define STIXXXX_PINCONF_RT_DOUBLE_EDGE BIT(20)
+#define STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(conf) \
+ STIXXXX_PINCONF_UNPACK(conf, RT_DOUBLE_EDGE)
+#define STIXXXX_PINCONF_PACK_RT_DOUBLE_EDGE(conf, val) \
+ STIXXXX_PINCONF_PACK(conf, val, RT_DOUBLE_EDGE)
+
+#define STIXXXX_PINCONF_RT_CLK_MASK 0x3
+#define STIXXXX_PINCONF_RT_CLK_SHIFT 18
+#define STIXXXX_PINCONF_RT_CLK BIT(18)
+#define STIXXXX_PINCONF_UNPACK_RT_CLK(conf) \
+ STIXXXX_PINCONF_UNPACK(conf, RT_CLK)
+#define STIXXXX_PINCONF_PACK_RT_CLK(conf, val) \
+ STIXXXX_PINCONF_PACK(conf, val, RT_CLK)
+
+/* RETIME_DELAY in Pico Secs */
+#define STIXXXX_PINCONF_RT_DELAY_MASK 0xffff
+#define STIXXXX_PINCONF_RT_DELAY_SHIFT 0
+#define STIXXXX_PINCONF_UNPACK_RT_DELAY(conf) \
+ STIXXXX_PINCONF_UNPACK(conf, RT_DELAY)
+#define STIXXXX_PINCONF_PACK_RT_DELAY(conf, val) \
+ STIXXXX_PINCONF_PACK(conf, val, RT_DELAY)
+
+#endif /* __LINUX_DRIVERS_PINCTRL_STIXXXX_H */
--
1.7.6.5
^ permalink raw reply related [flat|nested] 79+ messages in thread
* [RFC 7/8] ARM:stih41x: Add B2000 board support
[not found] ` <1368022187-1633-1-git-send-email-srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
2013-05-08 14:10 ` [RFC 1/8] serial:st-asc: Add ST ASC driver Srinivas KANDAGATLA
2013-05-08 14:11 ` [RFC 4/8] pinctrl:stixxxx: Add pinctrl and pinconf support Srinivas KANDAGATLA
@ 2013-05-08 14:12 ` Srinivas KANDAGATLA
[not found] ` <1368022329-2424-1-git-send-email-srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
2 siblings, 1 reply; 79+ messages in thread
From: Srinivas KANDAGATLA @ 2013-05-08 14:12 UTC (permalink / raw)
To: linux-lFZ/pmaqli7XmaaqVzeoHQ, arnd-r2nGTMty4D4,
olof-nZhT3qVonbNeoWH0uzbU5w
Cc: Srinivas Kandagatla, Viresh Kumar, Will Deacon, Jiri Slaby,
Stephen Warren, Samuel Ortiz, Nicolas Pitre,
linux-doc-u79uwXL29TY76Z2rM5mHXA, Stephen Gallimore,
linux-serial-u79uwXL29TY76Z2rM5mHXA, Jason Cooper,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring,
Stuart Menefy, Dong Aisheng,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Greg Kroah-Hartman, Mark Brown,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
B2000 board is reference board for STIH415/416 SOCs, it has
2 x UART, 4x USB, 2 x Ethernet, 1 x SATA, 1 x PCIe, and 1GB RAM.
This patch add initial support to b2000 with STiH415/416 with UART2 as
console and a heard beat LED.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
CC: Stephen Gallimore <stephen.gallimore-qxv4g6HH51o@public.gmane.org>
CC: Stuart Menefy <stuart.menefy-qxv4g6HH51o@public.gmane.org>
---
arch/arm/boot/dts/Makefile | 2 +
arch/arm/boot/dts/stih415-b2000.dtsp | 15 ++++++++++++
arch/arm/boot/dts/stih416-b2000.dtsp | 16 +++++++++++++
arch/arm/boot/dts/stih41x-b2000.dtsi | 41 ++++++++++++++++++++++++++++++++++
arch/arm/mach-stih41x/board-dt.c | 2 +
5 files changed, 76 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/boot/dts/stih415-b2000.dtsp
create mode 100644 arch/arm/boot/dts/stih416-b2000.dtsp
create mode 100644 arch/arm/boot/dts/stih41x-b2000.dtsi
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 9c62558..78b0271 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -147,6 +147,8 @@ dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \
spear320-evb.dtb \
spear320-hmi.dtb
dtb-$(CONFIG_ARCH_SPEAR6XX)+= spear600-evb.dtb
+dtb-$(CONFIG_ARCH_STIH41X)+= stih415-b2000.dtb \
+ stih416-b2000.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun4i-a10-cubieboard.dtb \
sun4i-a10-hackberry.dtb \
sun5i-a13-olinuxino.dtb
diff --git a/arch/arm/boot/dts/stih415-b2000.dtsp b/arch/arm/boot/dts/stih415-b2000.dtsp
new file mode 100644
index 0000000..d4af531
--- /dev/null
+++ b/arch/arm/boot/dts/stih415-b2000.dtsp
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+/dts-v1/;
+#include "stih415.dtsi"
+#include "stih41x-b2000.dtsi"
+/ {
+ model = "STiH415 B2000 Board";
+ compatible = "st,stih415", "st,stih415-b2000";
+};
diff --git a/arch/arm/boot/dts/stih416-b2000.dtsp b/arch/arm/boot/dts/stih416-b2000.dtsp
new file mode 100644
index 0000000..a5eb6ee
--- /dev/null
+++ b/arch/arm/boot/dts/stih416-b2000.dtsp
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+/dts-v1/;
+#include "stih416.dtsi"
+#include "stih41x-b2000.dtsi"
+
+/ {
+ compatible = "st,stih416", "st,stih416-b2000";
+ model = "STiH416 B2000";
+};
diff --git a/arch/arm/boot/dts/stih41x-b2000.dtsi b/arch/arm/boot/dts/stih41x-b2000.dtsi
new file mode 100644
index 0000000..8c17e4a
--- /dev/null
+++ b/arch/arm/boot/dts/stih41x-b2000.dtsi
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+/ {
+
+ memory{
+ device_type = "memory";
+ reg = <0x60000000 0x40000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyAS0,115200";
+ linux,stdout-path = &uart2;
+ };
+
+ aliases {
+ ttyAS0 = &uart2;
+ };
+
+ soc {
+ uart2: uart@fed32000 {
+ status = "okay";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ fp_led {
+ #gpio-cells = <1>;
+ label = "Front Panel LED";
+ gpios = <&PIO105 7>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ };
+};
diff --git a/arch/arm/mach-stih41x/board-dt.c b/arch/arm/mach-stih41x/board-dt.c
index 8005f71..1f23aca 100644
--- a/arch/arm/mach-stih41x/board-dt.c
+++ b/arch/arm/mach-stih41x/board-dt.c
@@ -63,6 +63,8 @@ void __init stih41x_dt_init(void)
}
static const char *stih41x_dt_match[] __initdata = {
+ "st,stih415-b2000",
+ "st,stih416-b2000",
NULL
};
--
1.7.6.5
^ permalink raw reply related [flat|nested] 79+ messages in thread
* [RFC 8/8] ARM:stih41x: Add B2020 board support
2013-05-08 14:09 [RFC 0/8] ARM:STiH41x: Add STiH41x platform and board support Srinivas KANDAGATLA
` (4 preceding siblings ...)
[not found] ` <1368022187-1633-1-git-send-email-srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
@ 2013-05-08 14:12 ` Srinivas KANDAGATLA
5 siblings, 0 replies; 79+ messages in thread
From: Srinivas KANDAGATLA @ 2013-05-08 14:12 UTC (permalink / raw)
To: arnd, linux, olof
Cc: Rob Landley, Grant Likely, Rob Herring, Samuel Ortiz,
Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Srinivas Kandagatla, Stuart Menefy, Shawn Guo, Jason Cooper,
Stephen Warren, Maxime Ripard, Nicolas Pitre, Will Deacon,
Dave Martin, Marc Zyngier, Viresh Kumar, Mark Brown, Dong Aisheng,
linux-doc, linux-kernel, devicetree-discuss
From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
B2020 ADI board is reference board for STIH415/416 SOCs, it has 2 x
UART, 4x USB, 1 x Ethernet, 1 x SATA, 1 x PCIe, and 2GB RAM with
standard set-top box IPs.
This patch adds initial support to B2020 with STiH415/416 with SBC_UART1
as console and a heard beat LED.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
CC: Stephen Gallimore <stephen.gallimore@st.com>
CC: Stuart Menefy <stuart.menefy@st.com>
---
arch/arm/boot/dts/Makefile | 4 ++-
arch/arm/boot/dts/stih415-b2020.dtsp | 15 ++++++++++++
arch/arm/boot/dts/stih416-b2020.dtsp | 16 +++++++++++++
arch/arm/boot/dts/stih41x-b2020.dtsi | 42 ++++++++++++++++++++++++++++++++++
arch/arm/mach-stih41x/board-dt.c | 2 +
5 files changed, 78 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/boot/dts/stih415-b2020.dtsp
create mode 100644 arch/arm/boot/dts/stih416-b2020.dtsp
create mode 100644 arch/arm/boot/dts/stih41x-b2020.dtsi
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 78b0271..2e69b90 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -148,7 +148,9 @@ dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \
spear320-hmi.dtb
dtb-$(CONFIG_ARCH_SPEAR6XX)+= spear600-evb.dtb
dtb-$(CONFIG_ARCH_STIH41X)+= stih415-b2000.dtb \
- stih416-b2000.dtb
+ stih416-b2000.dtb \
+ stih415-b2020.dtb \
+ stih416-b2020.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun4i-a10-cubieboard.dtb \
sun4i-a10-hackberry.dtb \
sun5i-a13-olinuxino.dtb
diff --git a/arch/arm/boot/dts/stih415-b2020.dtsp b/arch/arm/boot/dts/stih415-b2020.dtsp
new file mode 100644
index 0000000..442b019
--- /dev/null
+++ b/arch/arm/boot/dts/stih415-b2020.dtsp
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+/dts-v1/;
+#include "stih415.dtsi"
+#include "stih41x-b2020.dtsi"
+/ {
+ model = "STiH415 B2020 Board";
+ compatible = "st,stih415", "st,stih415-b2020";
+};
diff --git a/arch/arm/boot/dts/stih416-b2020.dtsp b/arch/arm/boot/dts/stih416-b2020.dtsp
new file mode 100644
index 0000000..276f28d
--- /dev/null
+++ b/arch/arm/boot/dts/stih416-b2020.dtsp
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+/dts-v1/;
+#include "stih416.dtsi"
+#include "stih41x-b2020.dtsi"
+/ {
+ model = "STiH416 B2020";
+ compatible = "st,stih416", "st,stih416-b2020";
+
+};
diff --git a/arch/arm/boot/dts/stih41x-b2020.dtsi b/arch/arm/boot/dts/stih41x-b2020.dtsi
new file mode 100644
index 0000000..855b583
--- /dev/null
+++ b/arch/arm/boot/dts/stih41x-b2020.dtsi
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+/ {
+ memory{
+ device_type = "memory";
+ reg = <0x40000000 0x80000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyAS0,115200";
+ linux,stdout-path = &sbc_uart1;
+ };
+
+ aliases {
+ ttyAS0 = &sbc_uart1;
+ };
+ soc {
+ sbc_uart1: uart@fe531000 {
+ status = "okay";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ red {
+ #gpio-cells = <1>;
+ label = "Front Panel LED";
+ gpios = <&PIO4 1>;
+ linux,default-trigger = "heartbeat";
+ };
+ green {
+ gpios = <&PIO4 7>;
+ default-state = "off";
+ };
+ };
+ };
+};
diff --git a/arch/arm/mach-stih41x/board-dt.c b/arch/arm/mach-stih41x/board-dt.c
index 1f23aca..ed0ccae 100644
--- a/arch/arm/mach-stih41x/board-dt.c
+++ b/arch/arm/mach-stih41x/board-dt.c
@@ -65,6 +65,8 @@ void __init stih41x_dt_init(void)
static const char *stih41x_dt_match[] __initdata = {
"st,stih415-b2000",
"st,stih416-b2000",
+ "st,stih415-b2020",
+ "st,stih416-b2020",
NULL
};
--
1.7.6.5
^ permalink raw reply related [flat|nested] 79+ messages in thread