Commit a2821146 authored by Arnd Bergmann's avatar Arnd Bergmann

Merge branch 'vexpress/timer' into next/timer

* vexpress/timer:
  ARM: versatile: Map local timers using Device Tree when possible
  ARM: vexpress: Get rid of MMIO_P2V
parents 69adb983 e129440a
...@@ -9,7 +9,12 @@ ...@@ -9,7 +9,12 @@
* *
* Integrator AP has 16-bit timers, Integrator CP, Versatile and Realview * Integrator AP has 16-bit timers, Integrator CP, Versatile and Realview
* can have 16-bit or 32-bit selectable via a bit in the control register. * can have 16-bit or 32-bit selectable via a bit in the control register.
*
* Every SP804 contains two identical timers.
*/ */
#define TIMER_1_BASE 0x00
#define TIMER_2_BASE 0x20
#define TIMER_LOAD 0x00 /* ACVR rw */ #define TIMER_LOAD 0x00 /* ACVR rw */
#define TIMER_VALUE 0x04 /* ACVR ro */ #define TIMER_VALUE 0x04 /* ACVR ro */
#define TIMER_CTRL 0x08 /* ACVR rw */ #define TIMER_CTRL 0x08 /* ACVR rw */
......
#define __MMIO_P2V(x) (((x) & 0xfffff) | (((x) & 0x0f000000) >> 4) | 0xf8000000)
#define MMIO_P2V(x) ((void __iomem *)__MMIO_P2V(x))
#define AMBA_DEVICE(name,busid,base,plat) \ #define AMBA_DEVICE(name,busid,base,plat) \
struct amba_device name##_device = { \ struct amba_device name##_device = { \
.dev = { \ .dev = { \
...@@ -17,3 +14,9 @@ struct amba_device name##_device = { \ ...@@ -17,3 +14,9 @@ struct amba_device name##_device = { \
.irq = IRQ_##base, \ .irq = IRQ_##base, \
/* .dma = DMA_##base,*/ \ /* .dma = DMA_##base,*/ \
} }
/* 2MB large area for motherboard's peripherals static mapping */
#define V2M_PERIPH 0xf8000000
/* Tile's peripherals static mappings should start here */
#define V2T_PERIPH 0xf8200000
...@@ -30,57 +30,29 @@ ...@@ -30,57 +30,29 @@
#include <plat/clcd.h> #include <plat/clcd.h>
#define V2M_PA_CS7 0x10000000
static struct map_desc ct_ca9x4_io_desc[] __initdata = { static struct map_desc ct_ca9x4_io_desc[] __initdata = {
{ {
.virtual = __MMIO_P2V(CT_CA9X4_MPIC), .virtual = V2T_PERIPH,
.pfn = __phys_to_pfn(CT_CA9X4_MPIC), .pfn = __phys_to_pfn(CT_CA9X4_MPIC),
.length = SZ_16K, .length = SZ_8K,
.type = MT_DEVICE,
}, {
.virtual = __MMIO_P2V(CT_CA9X4_SP804_TIMER),
.pfn = __phys_to_pfn(CT_CA9X4_SP804_TIMER),
.length = SZ_4K,
.type = MT_DEVICE,
}, {
.virtual = __MMIO_P2V(CT_CA9X4_L2CC),
.pfn = __phys_to_pfn(CT_CA9X4_L2CC),
.length = SZ_4K,
.type = MT_DEVICE, .type = MT_DEVICE,
}, },
}; };
static void __init ct_ca9x4_map_io(void) static void __init ct_ca9x4_map_io(void)
{ {
iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
#ifdef CONFIG_LOCAL_TIMERS #ifdef CONFIG_LOCAL_TIMERS
twd_base = MMIO_P2V(A9_MPCORE_TWD); twd_base = ioremap(A9_MPCORE_TWD, SZ_32);
#endif #endif
iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
} }
static void __init ct_ca9x4_init_irq(void) static void __init ct_ca9x4_init_irq(void)
{ {
gic_init(0, 29, MMIO_P2V(A9_MPCORE_GIC_DIST), gic_init(0, 29, ioremap(A9_MPCORE_GIC_DIST, SZ_4K),
MMIO_P2V(A9_MPCORE_GIC_CPU)); ioremap(A9_MPCORE_GIC_CPU, SZ_256));
} }
#if 0
static void __init ct_ca9x4_timer_init(void)
{
writel(0, MMIO_P2V(CT_CA9X4_TIMER0) + TIMER_CTRL);
writel(0, MMIO_P2V(CT_CA9X4_TIMER1) + TIMER_CTRL);
sp804_clocksource_init(MMIO_P2V(CT_CA9X4_TIMER1), "ct-timer1");
sp804_clockevents_init(MMIO_P2V(CT_CA9X4_TIMER0), IRQ_CT_CA9X4_TIMER0,
"ct-timer0");
}
static struct sys_timer ct_ca9x4_timer = {
.init = ct_ca9x4_timer_init,
};
#endif
static void ct_ca9x4_clcd_enable(struct clcd_fb *fb) static void ct_ca9x4_clcd_enable(struct clcd_fb *fb)
{ {
v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE_DB1, 0); v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE_DB1, 0);
...@@ -201,7 +173,7 @@ static void __init ct_ca9x4_init(void) ...@@ -201,7 +173,7 @@ static void __init ct_ca9x4_init(void)
int i; int i;
#ifdef CONFIG_CACHE_L2X0 #ifdef CONFIG_CACHE_L2X0
void __iomem *l2x0_base = MMIO_P2V(CT_CA9X4_L2CC); void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K);
/* set RAM latencies to 1 cycle for this core tile. */ /* set RAM latencies to 1 cycle for this core tile. */
writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL); writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL);
...@@ -217,9 +189,17 @@ static void __init ct_ca9x4_init(void) ...@@ -217,9 +189,17 @@ static void __init ct_ca9x4_init(void)
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
static void *ct_ca9x4_scu_base __initdata;
static void __init ct_ca9x4_init_cpu_map(void) static void __init ct_ca9x4_init_cpu_map(void)
{ {
int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU)); int i, ncores;
ct_ca9x4_scu_base = ioremap(A9_MPCORE_SCU, SZ_128);
if (WARN_ON(!ct_ca9x4_scu_base))
return;
ncores = scu_get_core_count(ct_ca9x4_scu_base);
if (ncores > nr_cpu_ids) { if (ncores > nr_cpu_ids) {
pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
...@@ -235,7 +215,7 @@ static void __init ct_ca9x4_init_cpu_map(void) ...@@ -235,7 +215,7 @@ static void __init ct_ca9x4_init_cpu_map(void)
static void __init ct_ca9x4_smp_enable(unsigned int max_cpus) static void __init ct_ca9x4_smp_enable(unsigned int max_cpus)
{ {
scu_enable(MMIO_P2V(A9_MPCORE_SCU)); scu_enable(ct_ca9x4_scu_base);
} }
#endif #endif
......
...@@ -22,9 +22,6 @@ ...@@ -22,9 +22,6 @@
#define CT_CA9X4_SYSWDT (0x1e007000) #define CT_CA9X4_SYSWDT (0x1e007000)
#define CT_CA9X4_L2CC (0x1e00a000) #define CT_CA9X4_L2CC (0x1e00a000)
#define CT_CA9X4_TIMER0 (CT_CA9X4_SP804_TIMER + 0x000)
#define CT_CA9X4_TIMER1 (CT_CA9X4_SP804_TIMER + 0x020)
#define A9_MPCORE_SCU (CT_CA9X4_MPIC + 0x0000) #define A9_MPCORE_SCU (CT_CA9X4_MPIC + 0x0000)
#define A9_MPCORE_GIC_CPU (CT_CA9X4_MPIC + 0x0100) #define A9_MPCORE_GIC_CPU (CT_CA9X4_MPIC + 0x0100)
#define A9_MPCORE_GIT (CT_CA9X4_MPIC + 0x0200) #define A9_MPCORE_GIT (CT_CA9X4_MPIC + 0x0200)
......
...@@ -39,33 +39,30 @@ ...@@ -39,33 +39,30 @@
#define V2M_CF (V2M_PA_CS7 + 0x0001a000) #define V2M_CF (V2M_PA_CS7 + 0x0001a000)
#define V2M_CLCD (V2M_PA_CS7 + 0x0001f000) #define V2M_CLCD (V2M_PA_CS7 + 0x0001f000)
#define V2M_SYS_ID (V2M_SYSREGS + 0x000) /*
#define V2M_SYS_SW (V2M_SYSREGS + 0x004) * Offsets from SYSREGS base
#define V2M_SYS_LED (V2M_SYSREGS + 0x008) */
#define V2M_SYS_100HZ (V2M_SYSREGS + 0x024) #define V2M_SYS_ID 0x000
#define V2M_SYS_FLAGS (V2M_SYSREGS + 0x030) #define V2M_SYS_SW 0x004
#define V2M_SYS_FLAGSSET (V2M_SYSREGS + 0x030) #define V2M_SYS_LED 0x008
#define V2M_SYS_FLAGSCLR (V2M_SYSREGS + 0x034) #define V2M_SYS_100HZ 0x024
#define V2M_SYS_NVFLAGS (V2M_SYSREGS + 0x038) #define V2M_SYS_FLAGS 0x030
#define V2M_SYS_NVFLAGSSET (V2M_SYSREGS + 0x038) #define V2M_SYS_FLAGSSET 0x030
#define V2M_SYS_NVFLAGSCLR (V2M_SYSREGS + 0x03c) #define V2M_SYS_FLAGSCLR 0x034
#define V2M_SYS_MCI (V2M_SYSREGS + 0x048) #define V2M_SYS_NVFLAGS 0x038
#define V2M_SYS_FLASH (V2M_SYSREGS + 0x03c) #define V2M_SYS_NVFLAGSSET 0x038
#define V2M_SYS_CFGSW (V2M_SYSREGS + 0x058) #define V2M_SYS_NVFLAGSCLR 0x03c
#define V2M_SYS_24MHZ (V2M_SYSREGS + 0x05c) #define V2M_SYS_MCI 0x048
#define V2M_SYS_MISC (V2M_SYSREGS + 0x060) #define V2M_SYS_FLASH 0x03c
#define V2M_SYS_DMA (V2M_SYSREGS + 0x064) #define V2M_SYS_CFGSW 0x058
#define V2M_SYS_PROCID0 (V2M_SYSREGS + 0x084) #define V2M_SYS_24MHZ 0x05c
#define V2M_SYS_PROCID1 (V2M_SYSREGS + 0x088) #define V2M_SYS_MISC 0x060
#define V2M_SYS_CFGDATA (V2M_SYSREGS + 0x0a0) #define V2M_SYS_DMA 0x064
#define V2M_SYS_CFGCTRL (V2M_SYSREGS + 0x0a4) #define V2M_SYS_PROCID0 0x084
#define V2M_SYS_CFGSTAT (V2M_SYSREGS + 0x0a8) #define V2M_SYS_PROCID1 0x088
#define V2M_SYS_CFGDATA 0x0a0
#define V2M_TIMER0 (V2M_TIMER01 + 0x000) #define V2M_SYS_CFGCTRL 0x0a4
#define V2M_TIMER1 (V2M_TIMER01 + 0x020) #define V2M_SYS_CFGSTAT 0x0a8
#define V2M_TIMER2 (V2M_TIMER23 + 0x000)
#define V2M_TIMER3 (V2M_TIMER23 + 0x020)
/* /*
...@@ -117,6 +114,7 @@ ...@@ -117,6 +114,7 @@
int v2m_cfg_write(u32 devfn, u32 data); int v2m_cfg_write(u32 devfn, u32 data);
int v2m_cfg_read(u32 devfn, u32 *data); int v2m_cfg_read(u32 devfn, u32 *data);
void v2m_flags_set(u32 data);
/* /*
* Core tile IDs * Core tile IDs
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <linux/io.h> #include <linux/io.h>
#include <mach/motherboard.h> #include <mach/motherboard.h>
#define V2M_PA_CS7 0x10000000
#include "core.h" #include "core.h"
...@@ -43,7 +42,5 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus) ...@@ -43,7 +42,5 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
* until it receives a soft interrupt, and then the * until it receives a soft interrupt, and then the
* secondary CPU branches to this address. * secondary CPU branches to this address.
*/ */
writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR)); v2m_flags_set(virt_to_phys(versatile_secondary_startup));
writel(virt_to_phys(versatile_secondary_startup),
MMIO_P2V(V2M_SYS_FLAGSSET));
} }
...@@ -40,29 +40,45 @@ ...@@ -40,29 +40,45 @@
static struct map_desc v2m_io_desc[] __initdata = { static struct map_desc v2m_io_desc[] __initdata = {
{ {
.virtual = __MMIO_P2V(V2M_PA_CS7), .virtual = V2M_PERIPH,
.pfn = __phys_to_pfn(V2M_PA_CS7), .pfn = __phys_to_pfn(V2M_PA_CS7),
.length = SZ_128K, .length = SZ_128K,
.type = MT_DEVICE, .type = MT_DEVICE,
}, },
}; };
static void __init v2m_timer_init(void) static void __iomem *v2m_sysreg_base;
static void __init v2m_sysctl_init(void __iomem *base)
{ {
u32 scctrl; u32 scctrl;
if (WARN_ON(!base))
return;
/* Select 1MHz TIMCLK as the reference clock for SP804 timers */ /* Select 1MHz TIMCLK as the reference clock for SP804 timers */
scctrl = readl(MMIO_P2V(V2M_SYSCTL + SCCTRL)); scctrl = readl(base + SCCTRL);
scctrl |= SCCTRL_TIMEREN0SEL_TIMCLK; scctrl |= SCCTRL_TIMEREN0SEL_TIMCLK;
scctrl |= SCCTRL_TIMEREN1SEL_TIMCLK; scctrl |= SCCTRL_TIMEREN1SEL_TIMCLK;
writel(scctrl, MMIO_P2V(V2M_SYSCTL + SCCTRL)); writel(scctrl, base + SCCTRL);
}
writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL); static void __init v2m_sp804_init(void __iomem *base, unsigned int irq)
writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL); {
if (WARN_ON(!base || irq == NO_IRQ))
return;
writel(0, base + TIMER_1_BASE + TIMER_CTRL);
writel(0, base + TIMER_2_BASE + TIMER_CTRL);
sp804_clocksource_init(MMIO_P2V(V2M_TIMER1), "v2m-timer1"); sp804_clocksource_init(base + TIMER_2_BASE, "v2m-timer1");
sp804_clockevents_init(MMIO_P2V(V2M_TIMER0), IRQ_V2M_TIMER0, sp804_clockevents_init(base + TIMER_1_BASE, irq, "v2m-timer0");
"v2m-timer0"); }
static void __init v2m_timer_init(void)
{
v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K));
v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
} }
static struct sys_timer v2m_timer = { static struct sys_timer v2m_timer = {
...@@ -82,14 +98,14 @@ int v2m_cfg_write(u32 devfn, u32 data) ...@@ -82,14 +98,14 @@ int v2m_cfg_write(u32 devfn, u32 data)
devfn |= SYS_CFG_START | SYS_CFG_WRITE; devfn |= SYS_CFG_START | SYS_CFG_WRITE;
spin_lock(&v2m_cfg_lock); spin_lock(&v2m_cfg_lock);
val = readl(MMIO_P2V(V2M_SYS_CFGSTAT)); val = readl(v2m_sysreg_base + V2M_SYS_CFGSTAT);
writel(val & ~SYS_CFG_COMPLETE, MMIO_P2V(V2M_SYS_CFGSTAT)); writel(val & ~SYS_CFG_COMPLETE, v2m_sysreg_base + V2M_SYS_CFGSTAT);
writel(data, MMIO_P2V(V2M_SYS_CFGDATA)); writel(data, v2m_sysreg_base + V2M_SYS_CFGDATA);
writel(devfn, MMIO_P2V(V2M_SYS_CFGCTRL)); writel(devfn, v2m_sysreg_base + V2M_SYS_CFGCTRL);
do { do {
val = readl(MMIO_P2V(V2M_SYS_CFGSTAT)); val = readl(v2m_sysreg_base + V2M_SYS_CFGSTAT);
} while (val == 0); } while (val == 0);
spin_unlock(&v2m_cfg_lock); spin_unlock(&v2m_cfg_lock);
...@@ -103,22 +119,28 @@ int v2m_cfg_read(u32 devfn, u32 *data) ...@@ -103,22 +119,28 @@ int v2m_cfg_read(u32 devfn, u32 *data)
devfn |= SYS_CFG_START; devfn |= SYS_CFG_START;
spin_lock(&v2m_cfg_lock); spin_lock(&v2m_cfg_lock);
writel(0, MMIO_P2V(V2M_SYS_CFGSTAT)); writel(0, v2m_sysreg_base + V2M_SYS_CFGSTAT);
writel(devfn, MMIO_P2V(V2M_SYS_CFGCTRL)); writel(devfn, v2m_sysreg_base + V2M_SYS_CFGCTRL);
mb(); mb();
do { do {
cpu_relax(); cpu_relax();
val = readl(MMIO_P2V(V2M_SYS_CFGSTAT)); val = readl(v2m_sysreg_base + V2M_SYS_CFGSTAT);
} while (val == 0); } while (val == 0);
*data = readl(MMIO_P2V(V2M_SYS_CFGDATA)); *data = readl(v2m_sysreg_base + V2M_SYS_CFGDATA);
spin_unlock(&v2m_cfg_lock); spin_unlock(&v2m_cfg_lock);
return !!(val & SYS_CFG_ERR); return !!(val & SYS_CFG_ERR);
} }
void __init v2m_flags_set(u32 data)
{
writel(~0, v2m_sysreg_base + V2M_SYS_FLAGSCLR);
writel(data, v2m_sysreg_base + V2M_SYS_FLAGSSET);
}
static struct resource v2m_pcie_i2c_resource = { static struct resource v2m_pcie_i2c_resource = {
.start = V2M_SERIAL_BUS_PCI, .start = V2M_SERIAL_BUS_PCI,
...@@ -204,7 +226,7 @@ static struct platform_device v2m_usb_device = { ...@@ -204,7 +226,7 @@ static struct platform_device v2m_usb_device = {
static void v2m_flash_set_vpp(struct platform_device *pdev, int on) static void v2m_flash_set_vpp(struct platform_device *pdev, int on)
{ {
writel(on != 0, MMIO_P2V(V2M_SYS_FLASH)); writel(on != 0, v2m_sysreg_base + V2M_SYS_FLASH);
} }
static struct physmap_flash_data v2m_flash_data = { static struct physmap_flash_data v2m_flash_data = {
...@@ -258,7 +280,7 @@ static struct platform_device v2m_cf_device = { ...@@ -258,7 +280,7 @@ static struct platform_device v2m_cf_device = {
static unsigned int v2m_mmci_status(struct device *dev) static unsigned int v2m_mmci_status(struct device *dev)
{ {
return readl(MMIO_P2V(V2M_SYS_MCI)) & (1 << 0); return readl(v2m_sysreg_base + V2M_SYS_MCI) & (1 << 0);
} }
static struct mmci_platform_data v2m_mmci_data = { static struct mmci_platform_data v2m_mmci_data = {
...@@ -371,7 +393,7 @@ static void __init v2m_init_early(void) ...@@ -371,7 +393,7 @@ static void __init v2m_init_early(void)
{ {
ct_desc->init_early(); ct_desc->init_early();
clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups)); clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups));
versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000); versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000);
} }
static void v2m_power_off(void) static void v2m_power_off(void)
...@@ -400,7 +422,8 @@ static void __init v2m_populate_ct_desc(void) ...@@ -400,7 +422,8 @@ static void __init v2m_populate_ct_desc(void)
u32 current_tile_id; u32 current_tile_id;
ct_desc = NULL; ct_desc = NULL;
current_tile_id = readl(MMIO_P2V(V2M_SYS_PROCID0)) & V2M_CT_ID_MASK; current_tile_id = readl(v2m_sysreg_base + V2M_SYS_PROCID0)
& V2M_CT_ID_MASK;
for (i = 0; i < ARRAY_SIZE(ct_descs) && !ct_desc; ++i) for (i = 0; i < ARRAY_SIZE(ct_descs) && !ct_desc; ++i)
if (ct_descs[i]->id == current_tile_id) if (ct_descs[i]->id == current_tile_id)
...@@ -414,6 +437,7 @@ static void __init v2m_populate_ct_desc(void) ...@@ -414,6 +437,7 @@ static void __init v2m_populate_ct_desc(void)
static void __init v2m_map_io(void) static void __init v2m_map_io(void)
{ {
iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc)); iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
v2m_sysreg_base = ioremap(V2M_SYSREGS, SZ_4K);
v2m_populate_ct_desc(); v2m_populate_ct_desc();
ct_desc->map_io(); ct_desc->map_io();
} }
......
...@@ -11,16 +11,42 @@ ...@@ -11,16 +11,42 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/clockchips.h> #include <linux/clockchips.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <asm/smp_twd.h> #include <asm/smp_twd.h>
#include <asm/localtimer.h> #include <asm/localtimer.h>
#include <mach/irqs.h> #include <mach/irqs.h>
const static struct of_device_id twd_of_match[] __initconst = {
{ .compatible = "arm,cortex-a9-twd-timer", },
{ .compatible = "arm,cortex-a5-twd-timer", },
{ .compatible = "arm,arm11mp-twd-timer", },
{ },
};
/* /*
* Setup the local clock events for a CPU. * Setup the local clock events for a CPU.
*/ */
int __cpuinit local_timer_setup(struct clock_event_device *evt) int __cpuinit local_timer_setup(struct clock_event_device *evt)
{ {
#if defined(CONFIG_OF)
static int dt_node_probed;
/* Look for TWD node only once */
if (!dt_node_probed) {
struct device_node *node = of_find_matching_node(NULL,
twd_of_match);
if (node)
twd_base = of_iomap(node, 0);
dt_node_probed = 1;
}
#endif
if (!twd_base)
return -ENXIO;
evt->irq = IRQ_LOCALTIMER; evt->irq = IRQ_LOCALTIMER;
twd_timer_setup(evt); twd_timer_setup(evt);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment