diff options
author | Linus Torvalds | 2013-07-02 22:43:38 +0200 |
---|---|---|
committer | Linus Torvalds | 2013-07-02 22:43:38 +0200 |
commit | 3883cbb6c1bda013a3ce2dbdab7dc97c52e4a232 (patch) | |
tree | 5b69f83b049d24ac81123ac954ca8c9128e48443 /arch/arm/mach-clps711x/common.c | |
parent | Merge tag 'cleanup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/gi... (diff) | |
parent | ARM: integrator: let pciv3 use mem/premem from device tree (diff) | |
download | kernel-qcow2-linux-3883cbb6c1bda013a3ce2dbdab7dc97c52e4a232.tar.gz kernel-qcow2-linux-3883cbb6c1bda013a3ce2dbdab7dc97c52e4a232.tar.xz kernel-qcow2-linux-3883cbb6c1bda013a3ce2dbdab7dc97c52e4a232.zip |
Merge tag 'soc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC specific changes from Arnd Bergmann:
"These changes are all to SoC-specific code, a total of 33 branches on
17 platforms were pulled into this. Like last time, Renesas sh-mobile
is now the platform with the most changes, followed by OMAP and
EXYNOS.
Two new platforms, TI Keystone and Rockchips RK3xxx are added in this
branch, both containing almost no platform specific code at all, since
they are using generic subsystem interfaces for clocks, pinctrl,
interrupts etc. The device drivers are getting merged through the
respective subsystem maintainer trees.
One more SoC (u300) is now multiplatform capable and several others
(shmobile, exynos, msm, integrator, kirkwood, clps711x) are moving
towards that goal with this series but need more work.
Also noteworthy is the work on PCI here, which is traditionally part
of the SoC specific code. With the changes done by Thomas Petazzoni,
we can now more easily have PCI host controller drivers as loadable
modules and keep them separate from the platform code in
drivers/pci/host. This has already led to the discovery that three
platforms (exynos, spear and imx) are actually using an identical PCIe
host controller and will be able to share a driver once support for
spear and imx is added."
* tag 'soc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (480 commits)
ARM: integrator: let pciv3 use mem/premem from device tree
ARM: integrator: set local side PCI addresses right
ARM: dts: Add pcie controller node for exynos5440-ssdk5440
ARM: dts: Add pcie controller node for Samsung EXYNOS5440 SoC
ARM: EXYNOS: Enable PCIe support for Exynos5440
pci: Add PCIe driver for Samsung Exynos
ARM: OMAP5: voltagedomain data: remove temporary OMAP4 voltage data
ARM: keystone: Move CPU bringup code to dedicated asm file
ARM: multiplatform: always pick one CPU type
ARM: imx: select syscon for IMX6SL
ARM: keystone: select ARM_ERRATA_798181 only for SMP
ARM: imx: Synertronixx scb9328 needs to select SOC_IMX1
ARM: OMAP2+: AM43x: resolve SMP related build error
dmaengine: edma: enable build for AM33XX
ARM: edma: Add EDMA crossbar event mux support
ARM: edma: Add DT and runtime PM support to the private EDMA API
dmaengine: edma: Add TI EDMA device tree binding
arm: add basic support for Rockchip RK3066a boards
arm: add debug uarts for rockchip rk29xx and rk3xxx series
arm: Add basic clocks for Rockchip rk3066a SoCs
...
Diffstat (limited to 'arch/arm/mach-clps711x/common.c')
-rw-r--r-- | arch/arm/mach-clps711x/common.c | 89 |
1 files changed, 62 insertions, 27 deletions
diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c index 20ff50f3ccf0..f6d1746366d4 100644 --- a/arch/arm/mach-clps711x/common.c +++ b/arch/arm/mach-clps711x/common.c @@ -27,12 +27,14 @@ #include <linux/clk.h> #include <linux/clkdev.h> #include <linux/clockchips.h> +#include <linux/clocksource.h> #include <linux/clk-provider.h> #include <asm/exception.h> #include <asm/mach/irq.h> #include <asm/mach/map.h> #include <asm/mach/time.h> +#include <asm/sched_clock.h> #include <asm/system_misc.h> #include <mach/hardware.h> @@ -213,7 +215,7 @@ void __init clps711x_init_irq(void) } } -inline u32 fls16(u32 x) +static inline u32 fls16(u32 x) { u32 r = 15; @@ -237,27 +239,52 @@ inline u32 fls16(u32 x) asmlinkage void __exception_irq_entry clps711x_handle_irq(struct pt_regs *regs) { - u32 irqstat; - void __iomem *base = CLPS711X_VIRT_BASE; - - irqstat = readl_relaxed(base + INTSR1) & readl_relaxed(base + INTMR1); - if (irqstat) { - handle_IRQ(fls16(irqstat), regs); - return; - } + do { + u32 irqstat; + void __iomem *base = CLPS711X_VIRT_BASE; + + irqstat = readw_relaxed(base + INTSR1) & + readw_relaxed(base + INTMR1); + if (irqstat) + handle_IRQ(fls16(irqstat), regs); + + irqstat = readw_relaxed(base + INTSR2) & + readw_relaxed(base + INTMR2); + if (irqstat) { + handle_IRQ(fls16(irqstat) + 16, regs); + continue; + } + + break; + } while (1); +} - irqstat = readl_relaxed(base + INTSR2) & readl_relaxed(base + INTMR2); - if (likely(irqstat)) - handle_IRQ(fls16(irqstat) + 16, regs); +static u32 notrace clps711x_sched_clock_read(void) +{ + return ~readw_relaxed(CLPS711X_VIRT_BASE + TC1D); } static void clps711x_clockevent_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { + disable_irq(IRQ_TC2OI); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + enable_irq(IRQ_TC2OI); + break; + case CLOCK_EVT_MODE_ONESHOT: + /* Not supported */ + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_RESUME: + /* Left event sources disabled, no more interrupts appear */ + break; + } } static struct clock_event_device clockevent_clps711x = { - .name = "CLPS711x Clockevents", + .name = "clps711x-clockevent", .rating = 300, .features = CLOCK_EVT_FEAT_PERIODIC, .set_mode = clps711x_clockevent_set_mode, @@ -271,8 +298,8 @@ static irqreturn_t clps711x_timer_interrupt(int irq, void *dev_id) } static struct irqaction clps711x_timer_irq = { - .name = "CLPS711x Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .name = "clps711x-timer", + .flags = IRQF_TIMER | IRQF_IRQPOLL, .handler = clps711x_timer_interrupt, }; @@ -301,6 +328,7 @@ void __init clps711x_timer_init(void) cpu = ext; bus = cpu; spi = 135400; + pll = 0; } else { cpu = pll; if (cpu >= 36864000) @@ -319,9 +347,9 @@ void __init clps711x_timer_init(void) else timh = 541440; } else - timh = cpu / 144; + timh = DIV_ROUND_CLOSEST(cpu, 144); - timl = timh / 256; + timl = DIV_ROUND_CLOSEST(timh, 256); /* All clocks are fixed */ add_fixed_clk(clk_pll, "pll", pll); @@ -334,13 +362,24 @@ void __init clps711x_timer_init(void) pr_info("CPU frequency set at %i Hz.\n", cpu); + /* Start Timer1 in free running mode (Low frequency) */ + tmp = clps_readl(SYSCON1) & ~(SYSCON1_TC1S | SYSCON1_TC1M); + clps_writel(tmp, SYSCON1); + + setup_sched_clock(clps711x_sched_clock_read, 16, timl); + + clocksource_mmio_init(CLPS711X_VIRT_BASE + TC1D, + "clps711x_clocksource", timl, 300, 16, + clocksource_mmio_readw_down); + + /* Set Timer2 prescaler */ clps_writew(DIV_ROUND_CLOSEST(timh, HZ), TC2D); - tmp = clps_readl(SYSCON1); - tmp |= SYSCON1_TC2S | SYSCON1_TC2M; + /* Start Timer2 in prescale mode (High frequency)*/ + tmp = clps_readl(SYSCON1) | SYSCON1_TC2M | SYSCON1_TC2S; clps_writel(tmp, SYSCON1); - clockevents_config_and_register(&clockevent_clps711x, timh, 1, 0xffff); + clockevents_config_and_register(&clockevent_clps711x, timh, 0, 0); setup_irq(IRQ_TC2OI, &clps711x_timer_irq); } @@ -353,15 +392,11 @@ void clps711x_restart(char mode, const char *cmd) static void clps711x_idle(void) { clps_writel(1, HALT); - __asm__ __volatile__( - "mov r0, r0\n\ - mov r0, r0"); + asm("mov r0, r0"); + asm("mov r0, r0"); } -static int __init clps711x_idle_init(void) +void __init clps711x_init_early(void) { arm_pm_idle = clps711x_idle; - return 0; } - -arch_initcall(clps711x_idle_init); |