From ef5911966d2312478a74e93d993cd623a869ab10 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 4 Jul 2012 16:01:16 +0100 Subject: [PATCH 1/9] ARM: vexpress: remove automatic errata workaround selection The vexpress Kconfig setup tries to be clever^Whelpful and selects some errata workarounds for certain revisions of the Cortex-A9 and PL310, which may be required depending on the core tile. Since the mach-vexpress can support A5, A7 and A15 coretiles, let's make errata workaround selection optional. Signed-off-by: Will Deacon Signed-off-by: Rob Herring Signed-off-by: Pawel Moll --- arch/arm/mach-vexpress/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig index cf8730d35e70..fc3730f01650 100644 --- a/arch/arm/mach-vexpress/Kconfig +++ b/arch/arm/mach-vexpress/Kconfig @@ -2,7 +2,8 @@ menu "Versatile Express platform type" depends on ARCH_VEXPRESS config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA - bool + bool "Enable A5 and A9 only errata work-arounds" + default y select ARM_ERRATA_720789 select ARM_ERRATA_751472 select PL310_ERRATA_753970 if CACHE_PL310 @@ -14,7 +15,6 @@ config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA config ARCH_VEXPRESS_CA9X4 bool "Versatile Express Cortex-A9x4 tile" - select ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA select ARM_GIC select CPU_V7 select HAVE_SMP @@ -22,7 +22,6 @@ config ARCH_VEXPRESS_CA9X4 config ARCH_VEXPRESS_DT bool "Device Tree support for Versatile Express platforms" - select ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA select ARM_GIC select ARM_PATCH_PHYS_VIRT select AUTO_ZRELADDR From d927daf5c81c9b6bf2d6a83dc4c8c60268930ee5 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Tue, 12 Jun 2012 16:14:03 +0100 Subject: [PATCH 2/9] ARM: vexpress: Check master site in daughterboard's sysctl operations With recent enough motherboard firmware, core tile can be fitted in either of the two daughterboard sites. The non-DT tile code for V2P-CA9 did not check that when configuring DVI output nor setting CLCD pixel clock. Fixed now, providing "get master site" API in motherboard's code. Signed-off-by: Pawel Moll --- arch/arm/mach-vexpress/ct-ca9x4.c | 15 ++++++++++++--- .../mach-vexpress/include/mach/motherboard.h | 9 ++++++--- arch/arm/mach-vexpress/v2m.c | 18 +++++++++++++----- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index c65cc3b462a5..ab15a5515312 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -66,8 +66,15 @@ static void __init ct_ca9x4_init_irq(void) 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_DVIMODE | SYS_CFG_SITE_DB1, 2); + u32 site = v2m_get_master_site(); + + /* + * Old firmware was using the "site" component of the command + * to control the DVI muxer (while it should be always 0 ie. MB). + * Newer firmware uses the data register. Keep both for compatibility. + */ + v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE(site), site); + v2m_cfg_write(SYS_CFG_DVIMODE | SYS_CFG_SITE(SYS_CFG_SITE_MB), 2); } static int ct_ca9x4_clcd_setup(struct clcd_fb *fb) @@ -112,7 +119,9 @@ static long ct_round(struct clk *clk, unsigned long rate) static int ct_set(struct clk *clk, unsigned long rate) { - return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_DB1 | 1, rate); + u32 site = v2m_get_master_site(); + + return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE(site) | 1, rate); } static const struct clk_ops osc1_clk_ops = { diff --git a/arch/arm/mach-vexpress/include/mach/motherboard.h b/arch/arm/mach-vexpress/include/mach/motherboard.h index 31a92890893d..f004ec982d29 100644 --- a/arch/arm/mach-vexpress/include/mach/motherboard.h +++ b/arch/arm/mach-vexpress/include/mach/motherboard.h @@ -104,9 +104,10 @@ #define SYS_CFG_REBOOT (9 << 20) #define SYS_CFG_DVIMODE (11 << 20) #define SYS_CFG_POWER (12 << 20) -#define SYS_CFG_SITE_MB (0 << 16) -#define SYS_CFG_SITE_DB1 (1 << 16) -#define SYS_CFG_SITE_DB2 (2 << 16) +#define SYS_CFG_SITE(n) ((n) << 16) +#define SYS_CFG_SITE_MB 0 +#define SYS_CFG_SITE_DB1 1 +#define SYS_CFG_SITE_DB2 2 #define SYS_CFG_STACK(n) ((n) << 12) #define SYS_CFG_ERR (1 << 1) @@ -122,6 +123,8 @@ void v2m_flags_set(u32 data); #define SYS_MISC_MASTERSITE (1 << 14) #define SYS_PROCIDx_HBI_MASK 0xfff +int v2m_get_master_site(void); + /* * Core tile IDs */ diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index fde26adaef32..bb185921fce1 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -147,6 +147,13 @@ void __init v2m_flags_set(u32 data) writel(data, v2m_sysreg_base + V2M_SYS_FLAGSSET); } +int v2m_get_master_site(void) +{ + u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC); + + return misc & SYS_MISC_MASTERSITE ? SYS_CFG_SITE_DB2 : SYS_CFG_SITE_DB1; +} + static struct resource v2m_pcie_i2c_resource = { .start = V2M_SERIAL_BUS_PCI, @@ -326,7 +333,8 @@ static long v2m_osc_round(struct clk *clk, unsigned long rate) static int v2m_osc1_set(struct clk *clk, unsigned long rate) { - return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_MB | 1, rate); + return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE(SYS_CFG_SITE_MB) | 1, + rate); } static const struct clk_ops osc1_clk_ops = { @@ -404,13 +412,13 @@ static void __init v2m_init_early(void) static void v2m_power_off(void) { - if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE_MB, 0)) + if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE(SYS_CFG_SITE_MB), 0)) printk(KERN_EMERG "Unable to shutdown\n"); } static void v2m_restart(char str, const char *cmd) { - if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE_MB, 0)) + if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE(SYS_CFG_SITE_MB), 0)) printk(KERN_EMERG "Unable to reboot\n"); } @@ -605,8 +613,8 @@ void __init v2m_dt_init_early(void) /* Confirm board type against DT property, if available */ if (of_property_read_u32(allnodes, "arm,hbi", &dt_hbi) == 0) { - u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC); - u32 id = readl(v2m_sysreg_base + (misc & SYS_MISC_MASTERSITE ? + int site = v2m_get_master_site(); + u32 id = readl(v2m_sysreg_base + (site == SYS_CFG_SITE_DB2 ? V2M_SYS_PROCID1 : V2M_SYS_PROCID0)); u32 hbi = id & SYS_PROCIDx_HBI_MASK; From 56a34b03ff427046494db87f05fc810aaedd23a5 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Thu, 5 Jul 2012 11:35:33 +0100 Subject: [PATCH 3/9] ARM: versatile: Make plat-versatile clock optional ... in preparation for common clock coming for Integrator and Versatile Express. Based on Linus Walleij's "ARM: integrator: convert to common clock" patch. Signed-off-by: Pawel Moll --- arch/arm/Kconfig | 4 ++++ arch/arm/plat-versatile/Kconfig | 3 +++ arch/arm/plat-versatile/Makefile | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a91009c61870..17beb66c6fa1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -260,6 +260,7 @@ config ARCH_INTEGRATOR select ICST select GENERIC_CLOCKEVENTS select PLAT_VERSATILE + select PLAT_VERSATILE_CLOCK select PLAT_VERSATILE_FPGA_IRQ select NEED_MACH_IO_H select NEED_MACH_MEMORY_H @@ -277,6 +278,7 @@ config ARCH_REALVIEW select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB select PLAT_VERSATILE + select PLAT_VERSATILE_CLOCK select PLAT_VERSATILE_CLCD select ARM_TIMER_SP804 select GPIO_PL061 if GPIOLIB @@ -295,6 +297,7 @@ config ARCH_VERSATILE select ARCH_WANT_OPTIONAL_GPIOLIB select NEED_MACH_IO_H if PCI select PLAT_VERSATILE + select PLAT_VERSATILE_CLOCK select PLAT_VERSATILE_CLCD select PLAT_VERSATILE_FPGA_IRQ select ARM_TIMER_SP804 @@ -314,6 +317,7 @@ config ARCH_VEXPRESS select ICST select NO_IOPORT select PLAT_VERSATILE + select PLAT_VERSATILE_CLOCK select PLAT_VERSATILE_CLCD help This enables support for the ARM Ltd Versatile Express boards. diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig index 81ee7cc34457..8d5c10a5084d 100644 --- a/arch/arm/plat-versatile/Kconfig +++ b/arch/arm/plat-versatile/Kconfig @@ -1,5 +1,8 @@ if PLAT_VERSATILE +config PLAT_VERSATILE_CLOCK + bool + config PLAT_VERSATILE_CLCD bool diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile index a5cb1945bdcc..272769a8a7d6 100644 --- a/arch/arm/plat-versatile/Makefile +++ b/arch/arm/plat-versatile/Makefile @@ -1,4 +1,4 @@ -obj-y := clock.o +obj-$(CONFIG_PLAT_VERSATILE_CLOCK) += clock.o obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o From d1b8a775fdb686c949d31e366a898b64147543e0 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Fri, 13 Jul 2012 11:48:16 +0100 Subject: [PATCH 4/9] ARM: vexpress: Initial common clock support This patch makes Versatile Express use the common clock framework instead of the plat-versatile implementation. It defines clock provider for VE's OSCs (clock generators) and registers all required fixed and variable clock sources (for both motherboard and core tile). This is a simple conversion of the existing state and will be extended (and migrated to drivers/clk) in the near future. Signed-off-by: Pawel Moll --- arch/arm/Kconfig | 3 +- arch/arm/mach-vexpress/ct-ca9x4.c | 55 +--- arch/arm/mach-vexpress/include/mach/clkdev.h | 15 -- .../mach-vexpress/include/mach/motherboard.h | 19 ++ arch/arm/mach-vexpress/v2m.c | 250 ++++++++---------- 5 files changed, 138 insertions(+), 204 deletions(-) delete mode 100644 arch/arm/mach-vexpress/include/mach/clkdev.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 17beb66c6fa1..6374a08a6cab 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -310,14 +310,13 @@ config ARCH_VEXPRESS select ARM_AMBA select ARM_TIMER_SP804 select CLKDEV_LOOKUP - select HAVE_MACH_CLKDEV + select COMMON_CLK select GENERIC_CLOCKEVENTS select HAVE_CLK select HAVE_PATA_PLATFORM select ICST select NO_IOPORT select PLAT_VERSATILE - select PLAT_VERSATILE_CLOCK select PLAT_VERSATILE_CLCD help This enables support for the ARM Ltd Versatile Express boards. diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index ab15a5515312..61c492403b05 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -112,45 +112,11 @@ static struct amba_device *ct_ca9x4_amba_devs[] __initdata = { }; -static long ct_round(struct clk *clk, unsigned long rate) -{ - return rate; -} - -static int ct_set(struct clk *clk, unsigned long rate) -{ - u32 site = v2m_get_master_site(); - - return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE(site) | 1, rate); -} - -static const struct clk_ops osc1_clk_ops = { - .round = ct_round, - .set = ct_set, -}; - -static struct clk osc1_clk = { - .ops = &osc1_clk_ops, - .rate = 24000000, -}; - -static struct clk ct_sp804_clk = { - .rate = 1000000, -}; - -static struct clk_lookup lookups[] = { - { /* CLCD */ - .dev_id = "ct:clcd", - .clk = &osc1_clk, - }, { /* SP804 timers */ - .dev_id = "sp804", - .con_id = "ct-timer0", - .clk = &ct_sp804_clk, - }, { /* SP804 timers */ - .dev_id = "sp804", - .con_id = "ct-timer1", - .clk = &ct_sp804_clk, - }, +static struct v2m_osc ct_osc1 = { + .osc = 1, + .rate_min = 10000000, + .rate_max = 80000000, + .rate_default = 23750000, }; static struct resource pmu_resources[] = { @@ -183,14 +149,10 @@ static struct platform_device pmu_device = { .resource = pmu_resources, }; -static void __init ct_ca9x4_init_early(void) -{ - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); -} - static void __init ct_ca9x4_init(void) { int i; + struct clk *clk; #ifdef CONFIG_CACHE_L2X0 void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K); @@ -202,6 +164,10 @@ static void __init ct_ca9x4_init(void) l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff); #endif + ct_osc1.site = v2m_get_master_site(); + clk = v2m_osc_register("ct:osc1", &ct_osc1); + clk_register_clkdev(clk, NULL, "ct:clcd"); + for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++) amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource); @@ -243,7 +209,6 @@ struct ct_desc ct_ca9x4_desc __initdata = { .id = V2M_CT_ID_CA9, .name = "CA9x4", .map_io = ct_ca9x4_map_io, - .init_early = ct_ca9x4_init_early, .init_irq = ct_ca9x4_init_irq, .init_tile = ct_ca9x4_init, #ifdef CONFIG_SMP diff --git a/arch/arm/mach-vexpress/include/mach/clkdev.h b/arch/arm/mach-vexpress/include/mach/clkdev.h deleted file mode 100644 index 3f8307d73cad..000000000000 --- a/arch/arm/mach-vexpress/include/mach/clkdev.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __ASM_MACH_CLKDEV_H -#define __ASM_MACH_CLKDEV_H - -#include - -struct clk { - const struct clk_ops *ops; - unsigned long rate; - const struct icst_params *params; -}; - -#define __clk_get(clk) ({ 1; }) -#define __clk_put(clk) do { } while (0) - -#endif diff --git a/arch/arm/mach-vexpress/include/mach/motherboard.h b/arch/arm/mach-vexpress/include/mach/motherboard.h index f004ec982d29..1e388c7bf4d7 100644 --- a/arch/arm/mach-vexpress/include/mach/motherboard.h +++ b/arch/arm/mach-vexpress/include/mach/motherboard.h @@ -1,6 +1,8 @@ #ifndef __MACH_MOTHERBOARD_H #define __MACH_MOTHERBOARD_H +#include + /* * Physical addresses, offset from V2M_PA_CS0-3 */ @@ -147,4 +149,21 @@ struct ct_desc { extern struct ct_desc *ct_desc; +/* + * OSC clock provider + */ +struct v2m_osc { + struct clk_hw hw; + u8 site; /* 0 = motherboard, 1 = site 1, 2 = site 2 */ + u8 stack; /* board stack position */ + u16 osc; + unsigned long rate_min; + unsigned long rate_max; + unsigned long rate_default; +}; + +#define to_v2m_osc(osc) container_of(osc, struct v2m_osc, hw) + +struct clk *v2m_osc_register(const char *name, struct v2m_osc *osc); + #endif diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index bb185921fce1..a3652a4ddc40 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -81,16 +82,6 @@ static void __init v2m_sp804_init(void __iomem *base, unsigned int irq) sp804_clockevents_init(base + TIMER_1_BASE, irq, "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 = { - .init = v2m_timer_init, -}; - static DEFINE_SPINLOCK(v2m_cfg_lock); @@ -326,87 +317,133 @@ static struct amba_device *v2m_amba_devs[] __initdata = { }; -static long v2m_osc_round(struct clk *clk, unsigned long rate) +static unsigned long v2m_osc_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) { + struct v2m_osc *osc = to_v2m_osc(hw); + + return !parent_rate ? osc->rate_default : parent_rate; +} + +static long v2m_osc_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct v2m_osc *osc = to_v2m_osc(hw); + + if (WARN_ON(rate < osc->rate_min)) + rate = osc->rate_min; + + if (WARN_ON(rate > osc->rate_max)) + rate = osc->rate_max; + return rate; } -static int v2m_osc1_set(struct clk *clk, unsigned long rate) +static int v2m_osc_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) { - return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE(SYS_CFG_SITE_MB) | 1, - rate); + struct v2m_osc *osc = to_v2m_osc(hw); + + v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE(osc->site) | + SYS_CFG_STACK(osc->stack) | osc->osc, rate); + + return 0; } -static const struct clk_ops osc1_clk_ops = { - .round = v2m_osc_round, - .set = v2m_osc1_set, +static struct clk_ops v2m_osc_ops = { + .recalc_rate = v2m_osc_recalc_rate, + .round_rate = v2m_osc_round_rate, + .set_rate = v2m_osc_set_rate, }; -static struct clk osc1_clk = { - .ops = &osc1_clk_ops, - .rate = 24000000, +struct clk * __init v2m_osc_register(const char *name, struct v2m_osc *osc) +{ + struct clk_init_data init; + + WARN_ON(osc->site > 2); + WARN_ON(osc->stack > 15); + WARN_ON(osc->osc > 4095); + + init.name = name; + init.ops = &v2m_osc_ops; + init.flags = CLK_IS_ROOT; + init.num_parents = 0; + + osc->hw.init = &init; + + return clk_register(NULL, &osc->hw); +} + +static struct v2m_osc v2m_mb_osc1 = { + .site = SYS_CFG_SITE_MB, + .osc = 1, + .rate_min = 23750000, + .rate_max = 63500000, + .rate_default = 23750000, }; -static struct clk osc2_clk = { - .rate = 24000000, +static const char *v2m_ref_clk_periphs[] __initconst = { + "mb:wdt", "1000f000.wdt", "1c0f0000.wdt", /* SP805 WDT */ }; -static struct clk v2m_sp804_clk = { - .rate = 1000000, +static const char *v2m_osc1_periphs[] __initconst = { + "mb:clcd", "1001f000.clcd", "1c1f0000.clcd", /* PL111 CLCD */ }; -static struct clk v2m_ref_clk = { - .rate = 32768, +static const char *v2m_osc2_periphs[] __initconst = { + "mb:mmci", "10005000.mmci", "1c050000.mmci", /* PL180 MMCI */ + "mb:kmi0", "10006000.kmi", "1c060000.kmi", /* PL050 KMI0 */ + "mb:kmi1", "10007000.kmi", "1c070000.kmi", /* PL050 KMI1 */ + "mb:uart0", "10009000.uart", "1c090000.uart", /* PL011 UART0 */ + "mb:uart1", "1000a000.uart", "1c0a0000.uart", /* PL011 UART1 */ + "mb:uart2", "1000b000.uart", "1c0b0000.uart", /* PL011 UART2 */ + "mb:uart3", "1000c000.uart", "1c0c0000.uart", /* PL011 UART3 */ }; -static struct clk dummy_apb_pclk; +static void __init v2m_clk_init(void) +{ + struct clk *clk; + int i; -static struct clk_lookup v2m_lookups[] = { - { /* AMBA bus clock */ - .con_id = "apb_pclk", - .clk = &dummy_apb_pclk, - }, { /* UART0 */ - .dev_id = "mb:uart0", - .clk = &osc2_clk, - }, { /* UART1 */ - .dev_id = "mb:uart1", - .clk = &osc2_clk, - }, { /* UART2 */ - .dev_id = "mb:uart2", - .clk = &osc2_clk, - }, { /* UART3 */ - .dev_id = "mb:uart3", - .clk = &osc2_clk, - }, { /* KMI0 */ - .dev_id = "mb:kmi0", - .clk = &osc2_clk, - }, { /* KMI1 */ - .dev_id = "mb:kmi1", - .clk = &osc2_clk, - }, { /* MMC0 */ - .dev_id = "mb:mmci", - .clk = &osc2_clk, - }, { /* CLCD */ - .dev_id = "mb:clcd", - .clk = &osc1_clk, - }, { /* SP805 WDT */ - .dev_id = "mb:wdt", - .clk = &v2m_ref_clk, - }, { /* SP804 timers */ - .dev_id = "sp804", - .con_id = "v2m-timer0", - .clk = &v2m_sp804_clk, - }, { /* SP804 timers */ - .dev_id = "sp804", - .con_id = "v2m-timer1", - .clk = &v2m_sp804_clk, - }, + clk = clk_register_fixed_rate(NULL, "dummy_apb_pclk", NULL, + CLK_IS_ROOT, 0); + WARN_ON(clk_register_clkdev(clk, "apb_pclk", NULL)); + + clk = clk_register_fixed_rate(NULL, "mb:ref_clk", NULL, + CLK_IS_ROOT, 32768); + for (i = 0; i < ARRAY_SIZE(v2m_ref_clk_periphs); i++) + WARN_ON(clk_register_clkdev(clk, NULL, v2m_ref_clk_periphs[i])); + + clk = clk_register_fixed_rate(NULL, "mb:sp804_clk", NULL, + CLK_IS_ROOT, 1000000); + WARN_ON(clk_register_clkdev(clk, "v2m-timer0", "sp804")); + WARN_ON(clk_register_clkdev(clk, "v2m-timer1", "sp804")); + + clk = v2m_osc_register("mb:osc1", &v2m_mb_osc1); + for (i = 0; i < ARRAY_SIZE(v2m_osc1_periphs); i++) + WARN_ON(clk_register_clkdev(clk, NULL, v2m_osc1_periphs[i])); + + clk = clk_register_fixed_rate(NULL, "mb:osc2", NULL, + CLK_IS_ROOT, 24000000); + for (i = 0; i < ARRAY_SIZE(v2m_osc2_periphs); i++) + WARN_ON(clk_register_clkdev(clk, NULL, v2m_osc2_periphs[i])); +} + +static void __init v2m_timer_init(void) +{ + v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K)); + v2m_clk_init(); + v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0); +} + +static struct sys_timer v2m_timer = { + .init = v2m_timer_init, }; static void __init v2m_init_early(void) { - ct_desc->init_early(); - clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups)); + if (ct_desc->init_early) + ct_desc->init_early(); versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000); } @@ -530,77 +567,6 @@ void __init v2m_dt_map_io(void) #endif } -static struct clk_lookup v2m_dt_lookups[] = { - { /* AMBA bus clock */ - .con_id = "apb_pclk", - .clk = &dummy_apb_pclk, - }, { /* SP804 timers */ - .dev_id = "sp804", - .con_id = "v2m-timer0", - .clk = &v2m_sp804_clk, - }, { /* SP804 timers */ - .dev_id = "sp804", - .con_id = "v2m-timer1", - .clk = &v2m_sp804_clk, - }, { /* PL180 MMCI */ - .dev_id = "mb:mmci", /* 10005000.mmci */ - .clk = &osc2_clk, - }, { /* PL050 KMI0 */ - .dev_id = "10006000.kmi", - .clk = &osc2_clk, - }, { /* PL050 KMI1 */ - .dev_id = "10007000.kmi", - .clk = &osc2_clk, - }, { /* PL011 UART0 */ - .dev_id = "10009000.uart", - .clk = &osc2_clk, - }, { /* PL011 UART1 */ - .dev_id = "1000a000.uart", - .clk = &osc2_clk, - }, { /* PL011 UART2 */ - .dev_id = "1000b000.uart", - .clk = &osc2_clk, - }, { /* PL011 UART3 */ - .dev_id = "1000c000.uart", - .clk = &osc2_clk, - }, { /* SP805 WDT */ - .dev_id = "1000f000.wdt", - .clk = &v2m_ref_clk, - }, { /* PL111 CLCD */ - .dev_id = "1001f000.clcd", - .clk = &osc1_clk, - }, - /* RS1 memory map */ - { /* PL180 MMCI */ - .dev_id = "mb:mmci", /* 1c050000.mmci */ - .clk = &osc2_clk, - }, { /* PL050 KMI0 */ - .dev_id = "1c060000.kmi", - .clk = &osc2_clk, - }, { /* PL050 KMI1 */ - .dev_id = "1c070000.kmi", - .clk = &osc2_clk, - }, { /* PL011 UART0 */ - .dev_id = "1c090000.uart", - .clk = &osc2_clk, - }, { /* PL011 UART1 */ - .dev_id = "1c0a0000.uart", - .clk = &osc2_clk, - }, { /* PL011 UART2 */ - .dev_id = "1c0b0000.uart", - .clk = &osc2_clk, - }, { /* PL011 UART3 */ - .dev_id = "1c0c0000.uart", - .clk = &osc2_clk, - }, { /* SP805 WDT */ - .dev_id = "1c0f0000.wdt", - .clk = &v2m_ref_clk, - }, { /* PL111 CLCD */ - .dev_id = "1c1f0000.clcd", - .clk = &osc1_clk, - }, -}; - void __init v2m_dt_init_early(void) { struct device_node *node; @@ -622,8 +588,6 @@ void __init v2m_dt_init_early(void) pr_warning("vexpress: DT HBI (%x) is not matching " "hardware (%x)!\n", dt_hbi, hbi); } - - clkdev_add_table(v2m_dt_lookups, ARRAY_SIZE(v2m_dt_lookups)); } static struct of_device_id vexpress_irq_match[] __initdata = { @@ -645,6 +609,8 @@ static void __init v2m_dt_timer_init(void) node = of_find_compatible_node(NULL, NULL, "arm,sp810"); v2m_sysctl_init(of_iomap(node, 0)); + v2m_clk_init(); + err = of_property_read_string(of_aliases, "arm,v2m_timer", &path); if (WARN_ON(err)) return; From b7541a950f27fc9237ce1fcb5c2284ee5c71efe3 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Wed, 4 Jul 2012 13:40:40 +0100 Subject: [PATCH 5/9] ARM: vexpress: Add missing SP804 interrupt in motherboard's DTS files Signed-off-by: Pawel Moll --- arch/arm/boot/dts/vexpress-v2m-rs1.dtsi | 1 + arch/arm/boot/dts/vexpress-v2m.dtsi | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi index 16076e2d0934..142c72a938d3 100644 --- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi +++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi @@ -157,6 +157,7 @@ v2m_timer23: timer@120000 { compatible = "arm,sp804", "arm,primecell"; reg = <0x120000 0x1000>; + interrupts = <3>; }; /* DVI I2C bus */ diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/vexpress-v2m.dtsi index a6c9c7c82d53..47ee30791f44 100644 --- a/arch/arm/boot/dts/vexpress-v2m.dtsi +++ b/arch/arm/boot/dts/vexpress-v2m.dtsi @@ -156,6 +156,7 @@ v2m_timer23: timer@12000 { compatible = "arm,sp804", "arm,primecell"; reg = <0x12000 0x1000>; + interrupts = <3>; }; /* DVI I2C bus */ From b2a54ff03ca80f11f3760f4eab9a955e7215f569 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Mon, 9 Jul 2012 11:33:47 +0100 Subject: [PATCH 6/9] ARM: vexpress: Add fixed regulator for SMSC SMSC driver requires "vdd33a" and "vddvario" regulator supplies now. Add fixed regulator describing 3V3 power line (in both motherboard's Device Trees and the non-DT code) and force fixed regulator config option if regulators framework is enabled. Signed-off-by: Pawel Moll --- arch/arm/Kconfig | 1 + arch/arm/boot/dts/vexpress-v2m-rs1.dtsi | 10 ++++++++++ arch/arm/boot/dts/vexpress-v2m.dtsi | 10 ++++++++++ arch/arm/mach-vexpress/v2m.c | 10 ++++++++++ 4 files changed, 31 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 6374a08a6cab..cb15fca4dd04 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -318,6 +318,7 @@ config ARCH_VEXPRESS select NO_IOPORT select PLAT_VERSATILE select PLAT_VERSATILE_CLCD + select REGULATOR_FIXED_VOLTAGE if REGULATOR help This enables support for the ARM Ltd Versatile Express boards. diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi index 142c72a938d3..d8a827bd2bf3 100644 --- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi +++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi @@ -55,6 +55,8 @@ reg-io-width = <4>; smsc,irq-active-high; smsc,irq-push-pull; + vdd33a-supply = <&v2m_fixed_3v3>; + vddvario-supply = <&v2m_fixed_3v3>; }; usb@2,03000000 { @@ -198,5 +200,13 @@ interrupts = <14>; }; }; + + v2m_fixed_3v3: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; }; }; diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/vexpress-v2m.dtsi index 47ee30791f44..dba53fd026bb 100644 --- a/arch/arm/boot/dts/vexpress-v2m.dtsi +++ b/arch/arm/boot/dts/vexpress-v2m.dtsi @@ -54,6 +54,8 @@ reg-io-width = <4>; smsc,irq-active-high; smsc,irq-push-pull; + vdd33a-supply = <&v2m_fixed_3v3>; + vddvario-supply = <&v2m_fixed_3v3>; }; usb@3,03000000 { @@ -197,5 +199,13 @@ interrupts = <14>; }; }; + + v2m_fixed_3v3: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; }; }; diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index a3652a4ddc40..37608f22ee31 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include @@ -199,6 +201,11 @@ static struct platform_device v2m_eth_device = { .dev.platform_data = &v2m_eth_config, }; +static struct regulator_consumer_supply v2m_eth_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x"), + REGULATOR_SUPPLY("vdd33a", "smsc911x"), +}; + static struct resource v2m_usb_resources[] = { { .start = V2M_ISP1761, @@ -503,6 +510,9 @@ static void __init v2m_init(void) { int i; + regulator_register_fixed(0, v2m_eth_supplies, + ARRAY_SIZE(v2m_eth_supplies)); + platform_device_register(&v2m_pcie_i2c_device); platform_device_register(&v2m_ddc_i2c_device); platform_device_register(&v2m_flash_device); From 5f8f5a62a60877ff796cb2b4657b04ffeec184cd Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Mon, 9 Jul 2012 13:47:22 +0100 Subject: [PATCH 7/9] ARM: vexpress: Convert V2P-CA15 Device Tree to 64 bit addresses ... to enable use of LPAE, which extends physical address space to 40 bits. Signed-off-by: Pawel Moll --- arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts | 36 ++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts index 7e1091d91af8..d12b34ca0568 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts @@ -14,8 +14,8 @@ arm,hbi = <0x237>; compatible = "arm,vexpress,v2p-ca15,tc1", "arm,vexpress,v2p-ca15", "arm,vexpress"; interrupt-parent = <&gic>; - #address-cells = <1>; - #size-cells = <1>; + #address-cells = <2>; + #size-cells = <2>; chosen { }; @@ -47,23 +47,23 @@ memory@80000000 { device_type = "memory"; - reg = <0x80000000 0x40000000>; + reg = <0 0x80000000 0 0x40000000>; }; hdlcd@2b000000 { compatible = "arm,hdlcd"; - reg = <0x2b000000 0x1000>; + reg = <0 0x2b000000 0 0x1000>; interrupts = <0 85 4>; }; memory-controller@2b0a0000 { compatible = "arm,pl341", "arm,primecell"; - reg = <0x2b0a0000 0x1000>; + reg = <0 0x2b0a0000 0 0x1000>; }; wdt@2b060000 { compatible = "arm,sp805", "arm,primecell"; - reg = <0x2b060000 0x1000>; + reg = <0 0x2b060000 0 0x1000>; interrupts = <98>; }; @@ -72,23 +72,23 @@ #interrupt-cells = <3>; #address-cells = <0>; interrupt-controller; - reg = <0x2c001000 0x1000>, - <0x2c002000 0x1000>, - <0x2c004000 0x2000>, - <0x2c006000 0x2000>; + reg = <0 0x2c001000 0 0x1000>, + <0 0x2c002000 0 0x1000>, + <0 0x2c004000 0 0x2000>, + <0 0x2c006000 0 0x2000>; interrupts = <1 9 0xf04>; }; memory-controller@7ffd0000 { compatible = "arm,pl354", "arm,primecell"; - reg = <0x7ffd0000 0x1000>; + reg = <0 0x7ffd0000 0 0x1000>; interrupts = <0 86 4>, <0 87 4>; }; dma@7ffb0000 { compatible = "arm,pl330", "arm,primecell"; - reg = <0x7ffb0000 0x1000>; + reg = <0 0x7ffb0000 0 0x1000>; interrupts = <0 92 4>, <0 88 4>, <0 89 4>, @@ -111,12 +111,12 @@ }; motherboard { - ranges = <0 0 0x08000000 0x04000000>, - <1 0 0x14000000 0x04000000>, - <2 0 0x18000000 0x04000000>, - <3 0 0x1c000000 0x04000000>, - <4 0 0x0c000000 0x04000000>, - <5 0 0x10000000 0x04000000>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; interrupt-map-mask = <0 0 63>; interrupt-map = <0 0 0 &gic 0 0 4>, From 375faa93cbd8062317d17ddfa6d8fea75f3bbf9b Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Tue, 10 Jul 2012 18:07:46 +0100 Subject: [PATCH 8/9] ARM: vexpress: Add Device Tree for V2P-CA15_CA7 core tile This patch adds Device Tree file for the CoreTile Express A15x2 A7x3 (V2P-CA15_CA7). Note that the A7 cpu nodes are commented out, as the big.LITTLE-relevant patches are not upstreamed yet. Till this time one can use the board with two A15 cores only, keeping the A7s in reset by adding the following setting to the board.txt file in Versatile Express configuration tree: SCC: 0x018 0x00001FFF Signed-off-by: Pawel Moll --- arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts | 188 +++++++++++++++++++++ arch/arm/mach-vexpress/Makefile.boot | 3 +- 2 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts new file mode 100644 index 000000000000..4890a81c5467 --- /dev/null +++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts @@ -0,0 +1,188 @@ +/* + * ARM Ltd. Versatile Express + * + * CoreTile Express A15x2 A7x3 + * Cortex-A15_A7 MPCore (V2P-CA15_A7) + * + * HBI-0249A + */ + +/dts-v1/; + +/ { + model = "V2P-CA15_CA7"; + arm,hbi = <0x249>; + compatible = "arm,vexpress,v2p-ca15_a7", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + i2c0 = &v2m_i2c_dvi; + i2c1 = &v2m_i2c_pcie; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <0>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <1>; + }; + +/* A7s disabled till big.LITTLE patches are available... + cpu2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0x100>; + }; + + cpu3: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0x101>; + }; + + cpu4: cpu@4 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0x102>; + }; +*/ + }; + + memory@80000000 { + device_type = "memory"; + reg = <0 0x80000000 0 0x40000000>; + }; + + wdt@2a490000 { + compatible = "arm,sp805", "arm,primecell"; + reg = <0 0x2a490000 0 0x1000>; + interrupts = <98>; + }; + + hdlcd@2b000000 { + compatible = "arm,hdlcd"; + reg = <0 0x2b000000 0 0x1000>; + interrupts = <0 85 4>; + }; + + memory-controller@2b0a0000 { + compatible = "arm,pl341", "arm,primecell"; + reg = <0 0x2b0a0000 0 0x1000>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0 0x2c001000 0 0x1000>, + <0 0x2c002000 0 0x1000>, + <0 0x2c004000 0 0x2000>, + <0 0x2c006000 0 0x2000>; + interrupts = <1 9 0xf04>; + }; + + memory-controller@7ffd0000 { + compatible = "arm,pl354", "arm,primecell"; + reg = <0 0x7ffd0000 0 0x1000>; + interrupts = <0 86 4>, + <0 87 4>; + }; + + dma@7ff00000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0 0x7ff00000 0 0x1000>; + interrupts = <0 92 4>, + <0 88 4>, + <0 89 4>, + <0 90 4>, + <0 91 4>; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupts = <1 13 0xf08>, + <1 14 0xf08>, + <1 11 0xf08>, + <1 10 0xf08>; + }; + + pmu { + compatible = "arm,cortex-a15-pmu", "arm,cortex-a9-pmu"; + interrupts = <0 68 4>, + <0 69 4>; + }; + + motherboard { + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + interrupt-map-mask = <0 0 63>; + interrupt-map = <0 0 0 &gic 0 0 4>, + <0 0 1 &gic 0 1 4>, + <0 0 2 &gic 0 2 4>, + <0 0 3 &gic 0 3 4>, + <0 0 4 &gic 0 4 4>, + <0 0 5 &gic 0 5 4>, + <0 0 6 &gic 0 6 4>, + <0 0 7 &gic 0 7 4>, + <0 0 8 &gic 0 8 4>, + <0 0 9 &gic 0 9 4>, + <0 0 10 &gic 0 10 4>, + <0 0 11 &gic 0 11 4>, + <0 0 12 &gic 0 12 4>, + <0 0 13 &gic 0 13 4>, + <0 0 14 &gic 0 14 4>, + <0 0 15 &gic 0 15 4>, + <0 0 16 &gic 0 16 4>, + <0 0 17 &gic 0 17 4>, + <0 0 18 &gic 0 18 4>, + <0 0 19 &gic 0 19 4>, + <0 0 20 &gic 0 20 4>, + <0 0 21 &gic 0 21 4>, + <0 0 22 &gic 0 22 4>, + <0 0 23 &gic 0 23 4>, + <0 0 24 &gic 0 24 4>, + <0 0 25 &gic 0 25 4>, + <0 0 26 &gic 0 26 4>, + <0 0 27 &gic 0 27 4>, + <0 0 28 &gic 0 28 4>, + <0 0 29 &gic 0 29 4>, + <0 0 30 &gic 0 30 4>, + <0 0 31 &gic 0 31 4>, + <0 0 32 &gic 0 32 4>, + <0 0 33 &gic 0 33 4>, + <0 0 34 &gic 0 34 4>, + <0 0 35 &gic 0 35 4>, + <0 0 36 &gic 0 36 4>, + <0 0 37 &gic 0 37 4>, + <0 0 38 &gic 0 38 4>, + <0 0 39 &gic 0 39 4>, + <0 0 40 &gic 0 40 4>, + <0 0 41 &gic 0 41 4>, + <0 0 42 &gic 0 42 4>; + }; +}; + +/include/ "vexpress-v2m-rs1.dtsi" diff --git a/arch/arm/mach-vexpress/Makefile.boot b/arch/arm/mach-vexpress/Makefile.boot index 909f85ebf5f4..318d308dfb93 100644 --- a/arch/arm/mach-vexpress/Makefile.boot +++ b/arch/arm/mach-vexpress/Makefile.boot @@ -6,4 +6,5 @@ initrd_phys-y := 0x60800000 dtb-$(CONFIG_ARCH_VEXPRESS_DT) += vexpress-v2p-ca5s.dtb \ vexpress-v2p-ca9.dtb \ - vexpress-v2p-ca15-tc1.dtb + vexpress-v2p-ca15-tc1.dtb \ + vexpress-v2p-ca15_a7.dtb From 1b820eaf42cde1df11d718909273611ee8e86ad0 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Wed, 11 Jul 2012 17:07:25 +0100 Subject: [PATCH 9/9] ARM: vexpress: Config option for early printk console Versatile Express platform can be used in different configurations, the console UART used by early printk may be located at different addresses in the address space. This patch makes it possible to select the base address of a PL011 UART to be used as a console output in the kernel configuration. The default behaviour is still the heuristic detecting memory map on Cortex-A core tiles. The zImage decompressor will use the same configuration values or print out nothing if DEBUG_LL is not enabled. Signed-off-by: Pawel Moll --- arch/arm/Kconfig.debug | 26 ++++++++++++ .../mach-vexpress/include/mach/debug-macro.S | 41 +++++++++++++++++++ .../mach-vexpress/include/mach/uncompress.h | 14 +++++++ 3 files changed, 81 insertions(+) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 01a134141216..a03b5a7059e2 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -310,6 +310,32 @@ choice The uncompressor code port configuration is now handled by CONFIG_S3C_LOWLEVEL_UART_PORT. + config DEBUG_VEXPRESS_UART0_DETECT + bool "Autodetect UART0 on Versatile Express Cortex-A core tiles" + depends on ARCH_VEXPRESS && CPU_CP15_MMU + help + This option enables a simple heuristic which tries to determine + the motherboard's memory map variant (original or RS1) and then + choose the relevant UART0 base address. + + Note that this will only work with standard A-class core tiles, + and may fail with non-standard SMM or custom software models. + + config DEBUG_VEXPRESS_UART0_CA9 + bool "Use PL011 UART0 at 0x10009000 (V2P-CA9 core tile)" + depends on ARCH_VEXPRESS + help + This option selects UART0 at 0x10009000. Except for custom models, + this applies only to the V2P-CA9 tile. + + config DEBUG_VEXPRESS_UART0_RS1 + bool "Use PL011 UART0 at 0x1c090000 (RS1 complaint tiles)" + depends on ARCH_VEXPRESS + help + This option selects UART0 at 0x1c090000. This applies to most + of the tiles using the RS1 memory map, including all new A-class + core tiles, FPGA-based SMMs and software models. + config DEBUG_LL_UART_NONE bool "No low-level debugging UART" help diff --git a/arch/arm/mach-vexpress/include/mach/debug-macro.S b/arch/arm/mach-vexpress/include/mach/debug-macro.S index fa8224794e0b..9f509f55d078 100644 --- a/arch/arm/mach-vexpress/include/mach/debug-macro.S +++ b/arch/arm/mach-vexpress/include/mach/debug-macro.S @@ -18,6 +18,8 @@ #define DEBUG_LL_VIRT_BASE 0xf8000000 +#if defined(CONFIG_DEBUG_VEXPRESS_UART0_DETECT) + .macro addruart,rp,rv,tmp @ Make an educated guess regarding the memory map: @@ -41,3 +43,42 @@ .endm #include + +#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_CA9) + + .macro addruart,rp,rv,tmp + mov \rp, #DEBUG_LL_UART_OFFSET + orr \rv, \rp, #DEBUG_LL_VIRT_BASE + orr \rp, \rp, #DEBUG_LL_PHYS_BASE + .endm + +#include + +#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_RS1) + + .macro addruart,rp,rv,tmp + mov \rp, #DEBUG_LL_UART_OFFSET_RS1 + orr \rv, \rp, #DEBUG_LL_VIRT_BASE + orr \rp, \rp, #DEBUG_LL_PHYS_BASE_RS1 + .endm + +#include + +#else /* CONFIG_DEBUG_LL_UART_NONE */ + + .macro addruart, rp, rv, tmp + /* Safe dummy values */ + mov \rp, #0 + mov \rv, #DEBUG_LL_VIRT_BASE + .endm + + .macro senduart,rd,rx + .endm + + .macro waituart,rd,rx + .endm + + .macro busyuart,rd,rx + .endm + +#endif diff --git a/arch/arm/mach-vexpress/include/mach/uncompress.h b/arch/arm/mach-vexpress/include/mach/uncompress.h index 7dab5596b868..1e472eb0bbdc 100644 --- a/arch/arm/mach-vexpress/include/mach/uncompress.h +++ b/arch/arm/mach-vexpress/include/mach/uncompress.h @@ -27,6 +27,7 @@ static unsigned long get_uart_base(void) { +#if defined(CONFIG_DEBUG_VEXPRESS_UART0_DETECT) unsigned long mpcore_periph; /* @@ -42,6 +43,13 @@ static unsigned long get_uart_base(void) return UART_BASE; else return UART_BASE_RS1; +#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_CA9) + return UART_BASE; +#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_RS1) + return UART_BASE_RS1; +#else + return 0; +#endif } /* @@ -51,6 +59,9 @@ static inline void putc(int c) { unsigned long base = get_uart_base(); + if (!base) + return; + while (AMBA_UART_FR(base) & (1 << 5)) barrier(); @@ -61,6 +72,9 @@ static inline void flush(void) { unsigned long base = get_uart_base(); + if (!base) + return; + while (AMBA_UART_FR(base) & (1 << 3)) barrier(); }