diff options
6 files changed, 425 insertions, 4 deletions
diff --git a/target/linux/sunxi/config-3.12 b/target/linux/sunxi/config-3.12 index 3a59082..b57168b 100644 --- a/target/linux/sunxi/config-3.12 +++ b/target/linux/sunxi/config-3.12 @@ -235,7 +235,6 @@ CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_XZ is not set CONFIG_KSM=y CONFIG_KTIME_SCALAR=y -# CONFIG_LBDAF is not set CONFIG_LEDS_GPIO=y # CONFIG_LEDS_REGULATOR is not set CONFIG_LEGACY_PTYS=y @@ -359,6 +358,7 @@ CONFIG_STOP_MACHINE=y CONFIG_STRICT_DEVMEM=y # CONFIG_SUN4I_EMAC is not set CONFIG_SUN4I_TIMER=y +CONFIG_SUN5I_HSTIMER=y # CONFIG_SUNXI_WATCHDOG is not set CONFIG_SWP_EMULATE=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y diff --git a/target/linux/sunxi/patches-3.12/136-clksrc-add-hstimer.patch b/target/linux/sunxi/patches-3.12/136-clksrc-add-hstimer.patch new file mode 100644 index 0000000..db54eb8 --- /dev/null +++ b/target/linux/sunxi/patches-3.12/136-clksrc-add-hstimer.patch @@ -0,0 +1,297 @@ +From 3bf30f6381f9287eb99ce096bf2fa327a69c8a71 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Thu, 7 Nov 2013 12:01:48 +0100 +Subject: [PATCH] clocksource: Add Allwinner SoCs HS timers driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Most of the Allwinner SoCs (at this time, all but the A10) also have a +High Speed timers that are not using the 24MHz oscillator as a source +but rather the AHB clock running much faster. + +The IP is slightly different between the A10s/A13 and the one used in +the A20/A31, since the latter have 4 timers available, while the former +have only 2 of them. + +[dlezcano] : Fixed conflict with b788beda "Order Kconfig options + alphabetically" + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +Tested-by: Emilio López <emilio@elopez.com.ar> +Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> +--- + .../bindings/timer/allwinner,sun5i-a13-hstimer.txt | 22 +++ + arch/arm/mach-sunxi/Kconfig | 1 + + drivers/clocksource/Kconfig | 4 + + drivers/clocksource/Makefile | 1 + + drivers/clocksource/timer-sun5i.c | 192 +++++++++++++++++++++ + 5 files changed, 220 insertions(+) + create mode 100644 Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt + create mode 100644 drivers/clocksource/timer-sun5i.c + +diff --git a/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt +new file mode 100644 +index 0000000..7c26154 +--- /dev/null ++++ b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt +@@ -0,0 +1,22 @@ ++Allwinner SoCs High Speed Timer Controller ++ ++Required properties: ++ ++- compatible : should be "allwinner,sun5i-a13-hstimer" or ++ "allwinner,sun7i-a20-hstimer" ++- reg : Specifies base physical address and size of the registers. ++- interrupts : The interrupts of these timers (2 for the sun5i IP, 4 for the sun7i ++ one) ++- clocks: phandle to the source clock (usually the AHB clock) ++ ++Example: ++ ++timer@01c60000 { ++ compatible = "allwinner,sun7i-a20-hstimer"; ++ reg = <0x01c60000 0x1000>; ++ interrupts = <0 51 1>, ++ <0 52 1>, ++ <0 53 1>, ++ <0 54 1>; ++ clocks = <&ahb1_gates 19>; ++}; +diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig +index e3457b9..547004c 100644 +--- a/arch/arm/mach-sunxi/Kconfig ++++ b/arch/arm/mach-sunxi/Kconfig +@@ -13,3 +13,4 @@ config ARCH_SUNXI + select PINCTRL_SUNXI + select SPARSE_IRQ + select SUN4I_TIMER ++ select SUN5I_HSTIMER +diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig +index 634c4d6..cd6950f 100644 +--- a/drivers/clocksource/Kconfig ++++ b/drivers/clocksource/Kconfig +@@ -37,6 +37,10 @@ config SUN4I_TIMER + select CLKSRC_MMIO + bool + ++config SUN5I_HSTIMER ++ select CLKSRC_MMIO ++ bool ++ + config VT8500_TIMER + bool + +diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile +index 33621ef..358358d 100644 +--- a/drivers/clocksource/Makefile ++++ b/drivers/clocksource/Makefile +@@ -22,6 +22,7 @@ obj-$(CONFIG_ARCH_MOXART) += moxart_timer.o + obj-$(CONFIG_ARCH_MXS) += mxs_timer.o + obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o + obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o ++obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o + obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o + obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o + obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o +diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c +new file mode 100644 +index 0000000..bddc522 +--- /dev/null ++++ b/drivers/clocksource/timer-sun5i.c +@@ -0,0 +1,192 @@ ++/* ++ * Allwinner SoCs hstimer driver. ++ * ++ * Copyright (C) 2013 Maxime Ripard ++ * ++ * Maxime Ripard <maxime.ripard@free-electrons.com> ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++ ++#include <linux/clk.h> ++#include <linux/clockchips.h> ++#include <linux/delay.h> ++#include <linux/interrupt.h> ++#include <linux/irq.h> ++#include <linux/irqreturn.h> ++#include <linux/sched_clock.h> ++#include <linux/of.h> ++#include <linux/of_address.h> ++#include <linux/of_irq.h> ++ ++#define TIMER_IRQ_EN_REG 0x00 ++#define TIMER_IRQ_EN(val) BIT(val) ++#define TIMER_IRQ_ST_REG 0x04 ++#define TIMER_CTL_REG(val) (0x20 * (val) + 0x10) ++#define TIMER_CTL_ENABLE BIT(0) ++#define TIMER_CTL_RELOAD BIT(1) ++#define TIMER_CTL_CLK_PRES(val) (((val) & 0x7) << 4) ++#define TIMER_CTL_ONESHOT BIT(7) ++#define TIMER_INTVAL_LO_REG(val) (0x20 * (val) + 0x14) ++#define TIMER_INTVAL_HI_REG(val) (0x20 * (val) + 0x18) ++#define TIMER_CNTVAL_LO_REG(val) (0x20 * (val) + 0x1c) ++#define TIMER_CNTVAL_HI_REG(val) (0x20 * (val) + 0x20) ++ ++#define TIMER_SYNC_TICKS 3 ++ ++static void __iomem *timer_base; ++static u32 ticks_per_jiffy; ++ ++/* ++ * When we disable a timer, we need to wait at least for 2 cycles of ++ * the timer source clock. We will use for that the clocksource timer ++ * that is already setup and runs at the same frequency than the other ++ * timers, and we never will be disabled. ++ */ ++static void sun5i_clkevt_sync(void) ++{ ++ u32 old = readl(timer_base + TIMER_CNTVAL_LO_REG(1)); ++ ++ while ((old - readl(timer_base + TIMER_CNTVAL_LO_REG(1))) < TIMER_SYNC_TICKS) ++ cpu_relax(); ++} ++ ++static void sun5i_clkevt_time_stop(u8 timer) ++{ ++ u32 val = readl(timer_base + TIMER_CTL_REG(timer)); ++ writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(timer)); ++ ++ sun5i_clkevt_sync(); ++} ++ ++static void sun5i_clkevt_time_setup(u8 timer, u32 delay) ++{ ++ writel(delay, timer_base + TIMER_INTVAL_LO_REG(timer)); ++} ++ ++static void sun5i_clkevt_time_start(u8 timer, bool periodic) ++{ ++ u32 val = readl(timer_base + TIMER_CTL_REG(timer)); ++ ++ if (periodic) ++ val &= ~TIMER_CTL_ONESHOT; ++ else ++ val |= TIMER_CTL_ONESHOT; ++ ++ writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, ++ timer_base + TIMER_CTL_REG(timer)); ++} ++ ++static void sun5i_clkevt_mode(enum clock_event_mode mode, ++ struct clock_event_device *clk) ++{ ++ switch (mode) { ++ case CLOCK_EVT_MODE_PERIODIC: ++ sun5i_clkevt_time_stop(0); ++ sun5i_clkevt_time_setup(0, ticks_per_jiffy); ++ sun5i_clkevt_time_start(0, true); ++ break; ++ case CLOCK_EVT_MODE_ONESHOT: ++ sun5i_clkevt_time_stop(0); ++ sun5i_clkevt_time_start(0, false); ++ break; ++ case CLOCK_EVT_MODE_UNUSED: ++ case CLOCK_EVT_MODE_SHUTDOWN: ++ default: ++ sun5i_clkevt_time_stop(0); ++ break; ++ } ++} ++ ++static int sun5i_clkevt_next_event(unsigned long evt, ++ struct clock_event_device *unused) ++{ ++ sun5i_clkevt_time_stop(0); ++ sun5i_clkevt_time_setup(0, evt - TIMER_SYNC_TICKS); ++ sun5i_clkevt_time_start(0, false); ++ ++ return 0; ++} ++ ++static struct clock_event_device sun5i_clockevent = { ++ .name = "sun5i_tick", ++ .rating = 340, ++ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, ++ .set_mode = sun5i_clkevt_mode, ++ .set_next_event = sun5i_clkevt_next_event, ++}; ++ ++ ++static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id) ++{ ++ struct clock_event_device *evt = (struct clock_event_device *)dev_id; ++ ++ writel(0x1, timer_base + TIMER_IRQ_ST_REG); ++ evt->event_handler(evt); ++ ++ return IRQ_HANDLED; ++} ++ ++static struct irqaction sun5i_timer_irq = { ++ .name = "sun5i_timer0", ++ .flags = IRQF_TIMER | IRQF_IRQPOLL, ++ .handler = sun5i_timer_interrupt, ++ .dev_id = &sun5i_clockevent, ++}; ++ ++static u32 sun5i_timer_sched_read(void) ++{ ++ return ~readl(timer_base + TIMER_CNTVAL_LO_REG(1)); ++} ++ ++static void __init sun5i_timer_init(struct device_node *node) ++{ ++ unsigned long rate; ++ struct clk *clk; ++ int ret, irq; ++ u32 val; ++ ++ timer_base = of_iomap(node, 0); ++ if (!timer_base) ++ panic("Can't map registers"); ++ ++ irq = irq_of_parse_and_map(node, 0); ++ if (irq <= 0) ++ panic("Can't parse IRQ"); ++ ++ clk = of_clk_get(node, 0); ++ if (IS_ERR(clk)) ++ panic("Can't get timer clock"); ++ clk_prepare_enable(clk); ++ rate = clk_get_rate(clk); ++ ++ writel(~0, timer_base + TIMER_INTVAL_LO_REG(1)); ++ writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, ++ timer_base + TIMER_CTL_REG(1)); ++ ++ setup_sched_clock(sun5i_timer_sched_read, 32, rate); ++ clocksource_mmio_init(timer_base + TIMER_CNTVAL_LO_REG(1), node->name, ++ rate, 340, 32, clocksource_mmio_readl_down); ++ ++ ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); ++ ++ ret = setup_irq(irq, &sun5i_timer_irq); ++ if (ret) ++ pr_warn("failed to setup irq %d\n", irq); ++ ++ /* Enable timer0 interrupt */ ++ val = readl(timer_base + TIMER_IRQ_EN_REG); ++ writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); ++ ++ sun5i_clockevent.cpumask = cpu_possible_mask; ++ sun5i_clockevent.irq = irq; ++ ++ clockevents_config_and_register(&sun5i_clockevent, rate, ++ TIMER_SYNC_TICKS, 0xffffffff); ++} ++CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer", ++ sun5i_timer_init); ++CLOCKSOURCE_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer", ++ sun5i_timer_init); +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/137-1-dt-sun7i-add-hstimer.patch b/target/linux/sunxi/patches-3.12/137-1-dt-sun7i-add-hstimer.patch new file mode 100644 index 0000000..7112ff0 --- /dev/null +++ b/target/linux/sunxi/patches-3.12/137-1-dt-sun7i-add-hstimer.patch @@ -0,0 +1,48 @@ +From 6c23e1fa6bd220b8f5665c150c83d4c016d95482 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Thu, 7 Nov 2013 12:01:48 +0100 +Subject: [PATCH] ARM: sun7i: a20: Add support for the High Speed Timers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The Allwinner A20 has support for four high speed timers. Apart for the +number of timers (4 vs 2), it's basically the same logic than the high +speed timers found in the sun5i chips. + +Now that we have a driver to support it, we can enable them in the +device tree. + +[dlezcano] : Fixed conflict with 428abbb8 "Enable the I2C controllers" + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +Tested-by: Emilio López <emilio@elopez.com.ar> +Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> +--- + arch/arm/boot/dts/sun7i-a20.dtsi | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index 93f7f96..c74147a 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -405,6 +405,16 @@ + status = "disabled"; + }; + ++ hstimer@01c60000 { ++ compatible = "allwinner,sun7i-a20-hstimer"; ++ reg = <0x01c60000 0x1000>; ++ interrupts = <0 81 1>, ++ <0 82 1>, ++ <0 83 1>, ++ <0 84 1>; ++ clocks = <&ahb_gates 28>; ++ }; ++ + gic: interrupt-controller@01c81000 { + compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic"; + reg = <0x01c81000 0x1000>, +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/137-2-dt-sun5i-add-hstimer.patch b/target/linux/sunxi/patches-3.12/137-2-dt-sun5i-add-hstimer.patch new file mode 100644 index 0000000..b209b12 --- /dev/null +++ b/target/linux/sunxi/patches-3.12/137-2-dt-sun5i-add-hstimer.patch @@ -0,0 +1,38 @@ +From 22a3eff19679e0e592e061201690670a2f5fdba7 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Thu, 7 Nov 2013 12:01:48 +0100 +Subject: [PATCH] ARM: sun5i: a13: Add support for the High Speed Timers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The Allwinner A13 has support for two high speed timers. Now that we +have a driver to support it, we can enable them in the device tree. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +Tested-by: Emilio López <emilio@elopez.com.ar> +Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> +--- + arch/arm/boot/dts/sun5i-a13.dtsi | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi +index ce8ef2a..1ccd75d 100644 +--- a/arch/arm/boot/dts/sun5i-a13.dtsi ++++ b/arch/arm/boot/dts/sun5i-a13.dtsi +@@ -273,5 +273,12 @@ + clock-frequency = <100000>; + status = "disabled"; + }; ++ ++ timer@01c60000 { ++ compatible = "allwinner,sun5i-a13-hstimer"; ++ reg = <0x01c60000 0x1000>; ++ interrupts = <82>, <83>; ++ clocks = <&ahb_gates 28>; ++ }; + }; + }; +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/137-3-dt-sun5i-a10s-add-hstimer.patch b/target/linux/sunxi/patches-3.12/137-3-dt-sun5i-a10s-add-hstimer.patch new file mode 100644 index 0000000..afdaa5a --- /dev/null +++ b/target/linux/sunxi/patches-3.12/137-3-dt-sun5i-a10s-add-hstimer.patch @@ -0,0 +1,38 @@ +From 5ace5467690055b1772dcac69dd1377735b8a34b Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Thu, 7 Nov 2013 12:01:48 +0100 +Subject: [PATCH] ARM: sun5i: a10s: Add support for the High Speed Timers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The Allwinner A10s has support for two high speed timers. Now that we +have a driver to support it, we can enable them in the device tree. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +Tested-by: Emilio López <emilio@elopez.com.ar> +Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> +--- + arch/arm/boot/dts/sun5i-a10s.dtsi | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index b4764be..924a2c1 100644 +--- a/arch/arm/boot/dts/sun5i-a10s.dtsi ++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi +@@ -336,5 +336,12 @@ + clock-frequency = <100000>; + status = "disabled"; + }; ++ ++ timer@01c60000 { ++ compatible = "allwinner,sun5i-a13-hstimer"; ++ reg = <0x01c60000 0x1000>; ++ interrupts = <82>, <83>; ++ clocks = <&ahb_gates 28>; ++ }; + }; + }; +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/160-sun5i-dt-add-usb-ehci-bindings.patch b/target/linux/sunxi/patches-3.12/160-sun5i-dt-add-usb-ehci-bindings.patch index 2e80601..0f72598 100644 --- a/target/linux/sunxi/patches-3.12/160-sun5i-dt-add-usb-ehci-bindings.patch +++ b/target/linux/sunxi/patches-3.12/160-sun5i-dt-add-usb-ehci-bindings.patch @@ -23,9 +23,9 @@ index aad270c..a271a2d 100644 #address-cells = <1>; #size-cells = <0>; @@ -310,5 +314,22 @@ - clock-frequency = <100000>; - status = "disabled"; - }; + interrupts = <82>, <83>; + clocks = <&ahb_gates 28>; + }; + + usb_rst: reset@0x01c200cc { + #reset-cells = <1>; |