ARM: AM43 (OMAP2+) boot support
Subsystems (5)
cover ARM: AM43 (OMAP2+) boot support
Hi,
This series adds minimal support to boot Linux on platforms having AM43 based SoC's.
This is being sent as an RFC to seek opinion about modification in twd to register percpu local timer clock event for scheduler tick in the case of one core SMP.
AM43 SoC's are based on ARM Cortex-A9. It is an ARM Cortex-A9 SMP configuration with one core (not uniprocessor configuration). AM43 is similar to AM335x in it's peripheral capabilities, with many of the peripheral register mapping's similar like that of uart.
AM43 is in pre-silicon stage and currently there are no public documents.
This series has been tested on a pre-silicon platform that emulates AM43 SoC, changes proposed here are minimal - to get it booting. Kernel was directly run without the help of bootloader - Images were directly loaded onto a pre-initialized RAM and ARM registers updated as required for booting.
Changes have been made over linux-next (next-20130213) with three "OF" related reverts (which otherwise causes problem in other platforms also) and compiled with omap2plus_defconfig. Multiplatform option was enabled, while most of CONFIG options were deselected for a faster boot. Beagle bone boots as earlier with these changes.
An interesting observation is that it may be possible to boot this platform to console without any platform specific modification to proper Kernel (by that I mean excluding DT sources) using Arnd's,
"[PATCH,RFC] default machine descriptor for multiplatform",
along with a "CLOCKSOURCE_OF_DECLARE" for smp twd.
But later on to make SoC do any really useful work or to get done things that the SoC is meant to do, platform changes like omap-hwmod, handling power management, clock tree, detecting SoC capabilities etc would have to be made, necessitating DT_MACHINE_START at least in the foreseeable future.
Patch - 8 that makes AM43 boot on pre-silicon platform would be replaced later by a one for original board.
Last but not least, thanks to Ankur Kishore <[email protected]> (who first made Linux to boot on AM43) for all the help that made Linux bringup easier.
Regards
Afzal
Afzal Mohammed (8):
ARM: localtimer: return percpu clkevt on register
ARM: twd: register clock event for 1 core SMP
ARM: twd: clock rate from DT (if no DT clk tree)
ARM: am33xx: ll debug config help
ARM: OMAP2+: am43: Kconfig
ARM: OMAP2+: am43: basic dt support
ARM: dts: am4372: initial support
ARM: dts: am43-pre-silicon support
Documentation/devicetree/bindings/arm/twd.txt | 7 +++- arch/arm/Kconfig.debug | 3 ++ arch/arm/boot/dts/Makefile | 3 +- arch/arm/boot/dts/am43-pre-silicon.dts | 31 +++++++++++++++ arch/arm/boot/dts/am4372.dtsi | 55 +++++++++++++++++++++++++++ arch/arm/include/asm/localtimer.h | 7 ++-- arch/arm/kernel/smp.c | 8 ++-- arch/arm/kernel/smp_twd.c | 16 +++++++- arch/arm/mach-omap2/Kconfig | 11 ++++++ arch/arm/mach-omap2/board-generic.c | 18 +++++++++ 10 files changed, 148 insertions(+), 11 deletions(-) create mode 100644 arch/arm/boot/dts/am43-pre-silicon.dts create mode 100644 arch/arm/boot/dts/am4372.dtsi
Signature · 1 line
1.7.12
RFC 1/8 ARM: localtimer: return percpu clkevt on register
Return percpu clock event on local timer register. It is the boot cpu that calls this and it can use the returned percpu clock event to register a clock event in the case of SMP configuration with one core. This helps to have a booting Kernel even if no other timer is registered for clock tick.
--- arch/arm/include/asm/localtimer.h | 7 ++++--- arch/arm/kernel/smp.c | 8 ++++---- arch/arm/kernel/smp_twd.c | 5 +++-- 3 files changed, 11 insertions(+), 9 deletions(-)
arch/arm/include/asm/localtimer.h +4 -3
@@ -23,11 +23,12 @@ struct local_timer_ops {/* * Register a local timer driver */ -int local_timer_register (struct local_timer_ops *); +struct clock_event_device *local_timer_register (struct local_timer_ops *);#else -static inline int local_timer_register (struct local_timer_ops *ops) +static inline +struct clock_event_device *local_timer_register (struct local_timer_ops *ops) { -return -ENXIO ; +return ERR_PTR (-ENXIO ); }#endif
arch/arm/kernel/smp.c +4 -4
@@ -491,16 +491,16 @@ static void __cpuinit broadcast_timer_setup(struct clock_event_device *evt)static struct local_timer_ops *lt_ops;#ifdef CONFIG_LOCAL_TIMERS -int local_timer_register (struct local_timer_ops *ops) +struct clock_event_device *local_timer_register (struct local_timer_ops *ops) {if (!is_smp () || !setup_max_cpus) -return -ENXIO ; +return ERR_PTR (-ENXIO );if (lt_ops) -return -EBUSY ; +return ERR_PTR (-EBUSY ); lt_ops = ops; -return 0 ; +return &per_cpu (percpu_clockevent,smp_processor_id ()); }#endif
arch/arm/kernel/smp_twd.c +3 -2
@@ -315,6 +315,7 @@ static struct local_timer_ops twd_lt_ops __cpuinitdata = {static int __init twd_local_timer_common_register (struct device_node *np) {int err; +struct clock_event_device *evt; twd_evt = alloc_percpu(struct clock_event_device *);if (!twd_evt) {
@@ -328,8 +329,8 @@ static int __init twd_local_timer_common_register(struct device_node *np) goto out_free; } - err =local_timer_register (&twd_lt_ops); -if (err) + evt =local_timer_register (&twd_lt_ops); +if (IS_ERR (evt)) goto out_irq;twd_get_clock (np);
Signature · 1 line
1.7.12
RFC 2/8 ARM: twd: register clock event for 1 core SMP
In reply to Afzal MohammedRegister percpu local timer for scheduler tick in the case of one core SMP configuration. In other cases - secondary cpu's as well as boot cpu's having more than one core, this is being registered as per existing boot flow, with a difference that they happens after delay calibration. Registering the clock for tick in case of one core should be done before Kernel calibrates delay (this is required to boot, unless local timer is the only one registered for tick). Registering twd local timer at init_time (which platforms are doing now) helps achieve that with the proposed change.
This helps in an almost booting Kernel (minimal) by only relying on ARM parts for an A9 one core SMP.
--- arch/arm/kernel/smp_twd.c | 3 +++ 1 file changed, 3 insertions(+)
arch/arm/kernel/smp_twd.c +3 -0
@@ -335,6 +335,9 @@ static int __init twd_local_timer_common_register(struct device_node *np)twd_get_clock (np); +if (num_possible_cpus () ==1 ) +twd_timer_setup (evt); +return 0 ; out_irq:
Signature · 1 line
1.7.12
Re: [RFC 2/8] ARM: twd: register clock event for 1 core SMP
Quoted 23 lines · Afzal Mohammed
Register percpu local timer for scheduler tick in the case of one core SMP configuration. In other cases - secondary cpu's as well as boot cpu's having more than one core, this is being registered as per existing boot flow, with a difference that they happens after delay calibration. Registering the clock for tick in case of one core should be done before Kernel calibrates delay (this is required to boot, unless local timer is the only one registered for tick). Registering twd local timer at
init_time(which platforms are doing now) helps achieve that with the proposed change.This helps in an almost booting Kernel (minimal) by only relying on ARM parts for an A9 one core SMP.
Signed-off-by Afzal Mohammed <[email protected]>--- arch/arm/kernel/smp_twd.c | 3 +++ 1 file changed, 3 insertions(+)arch/arm/kernel/smp_twd.c +0
-0
arch/arm/kernel/smp_twd.c static int __init twd_local_timer_common_register(struct device_node *np) · line 340
Quoted 6 lines
arch/arm/kernel/smp_twd.c +3
-0@@ -335,6 +335,9 @@ static int __init twd_local_timer_common_register(struct device_node *np)twd_get_clock (np); +if (num_possible_cpus () ==1 ) +twd_timer_setup (evt); +
Shouldn't this be fixed in the core code, so the same issue is fixed for all timers?
Rob
Quoted 4 lines
arch/arm/kernel/smp_twd.c +0
-0return 0 ; out_irq:
RE: [RFC 2/8] ARM: twd: register clock event for 1 core SMP
Hi Rob,
Quoted 24 lines · Rob Herring
Quoted 22 lines · Afzal Mohammed
Register percpu local timer for scheduler tick in the case of one core SMP configuration. In other cases - secondary cpu's as well as boot cpu's having more than one core, this is being registered as per existing boot flow, with a difference that they happens after delay calibration. Registering the clock for tick in case of one core should be done before Kernel calibrates delay (this is required to boot, unless local timer is the only one registered for tick). Registering twd local timer at
init_time(which platforms are doing now) helps achieve that with the proposed change.This helps in an almost booting Kernel (minimal) by only relying on ARM parts for an A9 one core SMP.
arch/arm/kernel/smp_twd.c | 3 +++ 1 file changed, 3 insertions(+)arch/arm/kernel/smp_twd.c +0
-0@@ -335,6 +335,9 @@ static int __init twd_local_timer_common_register(struct device_node *np)
Quoted 8 lines
arch/arm/kernel/smp_twd.c static int __init twd_local_timer_common_register(struct device_node *np) · line 340
Quoted 5 lines
arch/arm/kernel/smp_twd.c +3
-0twd_get_clock (np); +if (num_possible_cpus () ==1 ) +twd_timer_setup (evt); +Shouldn't this be fixed in the core code, so the same issue is fixed for all timers?
Is the following that you had in mind ? (with it, this patch as well as 1/8 would not be required),
arch/arm/include/asm/smp.h +2 -0
@@ -42,6 +42,8 @@ void handle_IPI(int ipinr, struct pt_regs *regs);*/ extern void smp_init_cpus (void ); +extern void smp_monocore_timer_setup (void ); +/* * Provide a function to raise an IPI cross call on CPUs in callmap.
arch/arm/kernel/smp.c +9 -0
@@ -504,6 +504,15 @@ int local_timer_register(struct local_timer_ops *ops) }#endif +void __init smp_monocore_timer_setup (void ) +{ +unsigned int cpu =smp_processor_id (); +struct clock_event_device *evt = &per_cpu (percpu_clockevent, cpu); + +if (!lt_ops) + lt_ops->setup (evt); +} +static void __cpuinit percpu_timer_setup (void ) {unsigned int cpu =smp_processor_id ();
arch/arm/kernel/time.c +1 -0
@@ -116,5 +116,6 @@ int __init register_persistent_clock(clock_access_fn read_boot,void __init time_init (void ) { machine_desc->init_time (); +smp_monocore_timer_setup ();sched_clock_postinit (); }
Regards
Afzal
RFC 3/8 ARM: twd: clock rate from DT (if no DT clk tree)
In reply to Afzal MohammedAdd an optional property to find clock-frequency from DT. This helps as a fallback mechanism in case there is no representation of clock tree in DT.
--- Documentation/devicetree/bindings/arm/twd.txt | 7 ++++++- arch/arm/kernel/smp_twd.c | 8 ++++++++ 2 files changed, 14 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/arm/twd.txt +6 -1
@@ -7,8 +7,9 @@ and watchdog. The TWD is usually attached to a GIC to deliver its two per-processor interrupts. -** Timer node required properties: +** Timer node properties: +Required properties: - compatible : Should be one of: "arm,cortex-a9-twd-timer" "arm,cortex-a5-twd-timer"
@@ -19,12 +20,16 @@ interrupts. - reg : Specify the base address and the size of the TWD timer register window. +Optional property: +- clock-frequency : frequency(Hz) of peripheral clock fed to timer + Example: twd-timer@2c000600 { compatible = "arm,arm11mp-twd-timer""; reg = <0x2c000600 0x20>; interrupts = <1 13 0xf01>; + clock-frequency = <300000000>; }; ** Watchdog node properties:
arch/arm/kernel/smp_twd.c +8 -0
@@ -247,7 +247,15 @@ static void twd_get_clock(struct device_node *np) twd_clk =clk_get_sys ("smp_twd" ,NULL );if (IS_ERR (twd_clk)) { +u32 freq; +pr_err ("smp_twd: clock not found %d\n" , (int )PTR_ERR (twd_clk)); + +/* If there is no representation of clock tree in DT, +provide a fallback option to obtain frequency +*/ +if (np && !of_property_read_u32 (np,"clock-frequency" , &freq)) + twd_timer_rate = freq;return ; }
Signature · 1 line
1.7.12
RFC 4/8 ARM: am33xx: ll debug config help
In reply to Afzal MohammedSelecting DEBUG_AM33XXUART1 routes low level debug messages to first UART instance of AM335x based SoC's. This selection is valid for upcoming AM43 based SoC's too. Make this information available upon configuring.
--- arch/arm/Kconfig.debug | 3 +++ 1 file changed, 3 insertions(+)
arch/arm/Kconfig.debug +3 -0
@@ -542,6 +542,9 @@ choice config DEBUG_AM33XXUART1 bool "AM33XX UART1" + help + Route low level debug messages to first uart instance + for boards based on am335 and am43 family of SoC's config DEBUG_ZOOM_UART bool "Zoom2/3 UART"
Signature · 1 line
1.7.12
RFC 5/8 ARM: OMAP2+: am43: Kconfig
In reply to Afzal MohammedAdd Kconfig option for AM43 family of SoC's, these are ARM Cortex A9 based (SMP configuration with 1 core).
--- arch/arm/mach-omap2/Kconfig | 11 +++++++++++ 1 file changed, 11 insertions(+)
arch/arm/mach-omap2/Kconfig +11 -0
@@ -141,6 +141,17 @@ config SOC_AM33XX select MULTI_IRQ_HANDLER select COMMON_CLK +config SOC_AM43 + bool "TI AM43" + depends on ARCH_OMAP2PLUS + default y + select CPU_V7 + select HAVE_SMP + select LOCAL_TIMERS if SMP + select MULTI_IRQ_HANDLER + select ARM_GIC + select COMMON_CLK + config OMAP_PACKAGE_ZAF bool
Signature · 1 line
1.7.12
RFC 6/8 ARM: OMAP2+: am43: basic dt support
In reply to Afzal MohammedDescribe minimal DT boot machine details for AM43 based SoC's. AM43 family of SoC's are ARM Cortex-A9 based with one core in SMP configuration. Low level debug could be achieved by selecting DEBUG_AM33XXUART1. To boot AM43 SoC, this change is sufficient w.r.t Kernel (considering the fact that strictly speaking DT sources does not classify as a part of Kernel). Here private timer of the one and only core is being used as clock event (as well as, as time source).
--- arch/arm/mach-omap2/board-generic.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
arch/arm/mach-omap2/board-generic.c +18 -0
@@ -15,7 +15,10 @@#include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/irqdomain.h> +#include <linux/irqchip.h> +#include <asm/mach/map.h> +#include <asm/smp_twd.h> #include <asm/mach/arch.h> #include "common.h"
@@ -182,3 +185,18 @@ DT_MACHINE_START(OMAP5_DT, "Generic OMAP5 (Flattened Device Tree)") .restart = omap44xx_restart, MACHINE_END#endif + +#ifdef CONFIG_SOC_AM43 +static const char *am43_boards_compat[]__initdata = { +"ti,am43" , +NULL , +}; + +DT_MACHINE_START (AM43_DT ,"Generic AM43 (Flattened Device Tree)" ) + .map_io = debug_ll_io_init, + .init_irq = irqchip_init, + .init_machine = omap_generic_init, + .init_time = twd_local_timer_of_register, + .dt_compat = am43_boards_compat, +MACHINE_END +#endif
Signature · 1 line
1.7.12
RFC 7/8 ARM: dts: am4372: initial support
In reply to Afzal MohammedDT source (minimal) for AM4372 SoC. Those represented here are the minimal DT nodes necessary to get kernel booting.
--- arch/arm/boot/dts/am4372.dtsi | 55 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 arch/arm/boot/dts/am4372.dtsi
arch/arm/boot/dts/am4372.dtsi new file +55 -0
@@ -0,0 +1,55 @@ +/* + * Device Tree Source for AM4372 SoC + * + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.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/ "skeleton.dtsi" + +/ { + compatible = "ti,am4372", "ti,am43"; + interrupt-parent = <&gic>; + + + aliases { + serial0 = &uart1; + }; + + cpus { + cpu@0 { + compatible = "arm,cortex-a9"; + }; + }; + + gic: interrupt-controller@48241000 { + compatible = "arm,cortex-a9-gic"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x48241000 0x1000>, + <0x48240100 0x0100>; + }; + + twd1: local-timer@0x48240600 { + compatible = "arm,cortex-a9-twd-timer"; + reg = <0x48240600 0x20>; + interrupts = <1 13 0x304>; + }; + + ocp { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + uart1: serial@44e09000 { + compatible = "ti,am4372-uart","ti,omap2-uart"; + clock-frequency = <48000000>; + reg = <0x44e09000 0x2000>; + interrupts = <0 72 0x4>; + }; + }; +};
Signature · 1 line
1.7.12
RFC 8/8 ARM: dts: am43-pre-silicon support
In reply to Afzal MohammedAM43 SoC is in pre-silicon stage, meanwhile it has been modelled in a pre-silicon platform. To validate and boot Linux in pre-silicon platform that emulates an AM43 SoC, add DT build support.
As bootloader is not used, bootargs is passed through DT.
Note: This would be replaced by an original board support.
--- arch/arm/boot/dts/Makefile | 3 ++- arch/arm/boot/dts/am43-pre-silicon.dts | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/am43-pre-silicon.dts
arch/arm/boot/dts/Makefile +2 -1
@@ -124,7 +124,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \ omap5-evm.dtb \ am335x-evm.dtb \ am335x-evmsk.dtb \ - am335x-bone.dtb + am335x-bone.dtb \ + am43-pre-silicon.dtb dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb dtb-$(CONFIG_ARCH_U8500) += snowball.dtb \
arch/arm/boot/dts/am43-pre-silicon.dts new file +31 -0
@@ -0,0 +1,31 @@ +/* + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.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. + */ + +/* AM43 Pre Silicon */ + +/dts-v1/; + +/include/ "am4372.dtsi" + +/ { + model = "TI AM43 Pre Silicon"; + compatible = "ti,am43-pre-silicon","ti,am4372","ti,am43"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + chosen { + bootargs = "console=ttyO0,115200n8 root=/dev/ram rw initrd=0x82000000,32MB earlyprintk"; + }; +}; + +&twd1 { + clock-frequency = <300000000>; +};
Signature · 1 line
1.7.12