From ad24bde8f1025da014108493b595bed22d989efb Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 20 Jun 2012 15:55:24 -0500 Subject: [PATCH] ARM: OMAP3: Dynamically disable secure timer nodes for secure devices OMAP3 devices may or may not have security features enabled. Security enabled devices are known as high-secure (HS) and devices without security are known as general purpose (GP). For OMAP3 devices there are 12 general purpose timers available. On secure devices the 12th timer is reserved for secure usage and so cannot be used by the kernel, where as for a GP device it is available. We can detect the OMAP device type, secure or GP, at runtime via an on-chip register. Today, when not using DT, we do not register the 12th timer as a linux device if the device is secure. When using device tree, device tree is going to register all the timer devices it finds in the device tree blob. To prevent device tree from registering 12th timer on a secure OMAP3 device we can add a status property to the timer binding with the value "disabled" at boot time. Note that timer 12 on a OMAP3 device has a property "ti,timer-secure" to indicate that it will not be available on a secure device and so for secure OMAP3 devices, we search for timers with this property and then disable them. Using the prom_add_property() function to dynamically add a property was a recommended approach suggested by Rob Herring [1]. I have tested this on an OMAP3 GP device and faking it to pretend to be a secure device to ensure that any timers marked with "ti,timer-secure" are not registered on boot. I have also made sure that all timers are registered as expected on a GP device by default. [1] http://comments.gmane.org/gmane.linux.ports.arm.omap/79203 Signed-off-by: Jon Hunter --- arch/arm/mach-omap2/timer.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 69e46631a7cd..def9a0ebe42d 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -144,6 +144,41 @@ static struct clock_event_device clockevent_gpt = { .set_mode = omap2_gp_timer_set_mode, }; +static struct property device_disabled = { + .name = "status", + .length = sizeof("disabled"), + .value = "disabled", +}; + +static struct of_device_id omap_timer_match[] __initdata = { + { .compatible = "ti,omap2-timer", }, + { } +}; + +/** + * omap_dmtimer_init - initialisation function when device tree is used + * + * For secure OMAP3 devices, timers with device type "timer-secure" cannot + * be used by the kernel as they are reserved. Therefore, to prevent the + * kernel registering these devices remove them dynamically from the device + * tree on boot. + */ +void __init omap_dmtimer_init(void) +{ + struct device_node *np; + + if (!cpu_is_omap34xx()) + return; + + /* If we are a secure device, remove any secure timer nodes */ + if ((omap_type() != OMAP2_DEVICE_TYPE_GP)) { + for_each_matching_node(np, omap_timer_match) { + if (of_get_property(np, "ti,timer-secure", NULL)) + prom_add_property(np, &device_disabled); + } + } +} + static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, int gptimer_id, const char *fck_source) @@ -437,6 +472,7 @@ static inline void __init realtime_counter_init(void) clksrc_nr, clksrc_src) \ static void __init omap##name##_timer_init(void) \ { \ + omap_dmtimer_init(); \ omap2_gp_clockevent_init((clkev_nr), clkev_src); \ omap2_clocksource_init((clksrc_nr), clksrc_src); \ } -- 2.39.5