Skip to contentSkip to conversation

ARM: AM43 (OMAP2+) boot support

RFC In review Afzal Mohammed 2 participants 11 messages Feb 18, 2013 – Feb 19, 2013

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

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
#1 lore raw

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
index f77ffc1..c3f89c0 100644
@@ -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
index 5f73f70..42d95d6 100644
@@ -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
index c092115..616268c 100644
@@ -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
#2 lore raw

RFC 2/8 ARM: twd: register clock event for 1 core SMP

In reply to 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 +3 -0
index 616268c..118f4f2 100644
@@ -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
#3 lore raw

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.

---
 arch/arm/kernel/smp_twd.c | 3 +++
 1 file changed, 3 insertions(+)
arch/arm/kernel/smp_twd.c +0 -0
index 616268c..118f4f2 100644

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 -0
 	return 0;
 
 out_irq:
#4 lore raw

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
index 616268c..118f4f2 100644
@@ -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 -0
 	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?

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
index d3a22be..2b6417d 100644
@@ -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
index 5f73f70..7431b77 100644
@@ -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
index 955d92d..eb023ee 100644
@@ -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

#5 lore raw

RFC 3/8 ARM: twd: clock rate from DT (if no DT clk tree)

In reply to Afzal Mohammed

Add 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
index 75b8610..fdafa4f 100644
@@ -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
index 118f4f2..aac0f9f 100644
@@ -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
#6 lore raw

RFC 4/8 ARM: am33xx: ll debug config help

In reply to Afzal Mohammed

Selecting 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
index acdddda..b717b78 100644
@@ -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
#7 lore raw

RFC 5/8 ARM: OMAP2+: am43: Kconfig

In reply to Afzal Mohammed

Add 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
index 49ac3df..683fbaa 100644
@@ -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
#8 lore raw

RFC 6/8 ARM: OMAP2+: am43: basic dt support

In reply to Afzal Mohammed

Describe 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
index 0274ff7..e083f08 100644
@@ -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
#9 lore raw

RFC 7/8 ARM: dts: am4372: initial support

In reply to Afzal Mohammed

DT 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
new file mode 100644
index 0000000..178c41f
@@ -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
#10 lore raw

RFC 8/8 ARM: dts: am43-pre-silicon support

In reply to Afzal Mohammed

AM43 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
index 94d88b9..b434344 100644
@@ -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
new file mode 100644
index 0000000..b9c6297
@@ -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