ARM: OMAP2+: Add device-tree support for timers
Subsystems (4)
v3 cover ARM: OMAP2+: Add device-tree support for timers
This series adds device-tree support for the timers on OMAP2+ devices including AM33xx.
Testing:
1. I have booted tested this series on OMAP2420 H4, OMAP3430 Beagle, OMAP4430 Panda and AM335x Beagle Bone with/without ...
a). device-tree present
b). CONFIG_OMAP_32K_TIMER set
c). kernel boot parameter "clocksource=gp_timer" present
2. I have tested the all the timers (not used by the kernel as sys-timers) on OMAP2420 H4, OMAP3430 Beagle and OMAP4430 Panda with/without device-tree with this series. The testing includes ...
a. Configuring, starting a timer and checking the counter value is
incrementing.
b. Testing timer overflow interrupt when timer expires.
c. Using different clock sources to operate the timer with.
V3 changes:
- Removed definition "TIMER_PROP_ALWON" per Rob Herring's feedback
- Updated OMAP system timer (clock-events and clock-source) code so that HWMOD is NOT used for getting resource (memory and interrupt) information when device-tree is present.
V2 changes:
- Remove use of device-tree alias property
- Migrate OMAP timers to request timers by property instead of device ID
- Include OMAP2 support
Jon Hunter (5):
ARM: dts: OMAP: Add timer nodes
ARM: OMAP3: Dynamically disable secure timer nodes for secure devices
ARM: OMAP: Add function to request a timer by capability
ARM: OMAP3: Add generic machine descriptor for boards with OMAP3 GP
devices
ARM: OMAP: Add DT support for timer driver
.../devicetree/bindings/arm/omap/timer.txt | 29 ++++ arch/arm/boot/dts/am33xx.dtsi | 61 +++++++ arch/arm/boot/dts/omap2.dtsi | 86 ++++++++++ arch/arm/boot/dts/omap2420.dtsi | 8 + arch/arm/boot/dts/omap2430.dtsi | 8 + arch/arm/boot/dts/omap3.dtsi | 96 +++++++++++ arch/arm/boot/dts/omap4.dtsi | 86 ++++++++++ arch/arm/mach-omap2/board-generic.c | 17 ++ arch/arm/mach-omap2/timer.c | 174 ++++++++++++++++---- arch/arm/plat-omap/dmtimer.c | 93 ++++++++++- arch/arm/plat-omap/include/plat/dmtimer.h | 1 + 11 files changed, 622 insertions(+), 37 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/omap/timer.txt
Signature · 1 line
1.7.9.5
PATCH v3 1/5 ARM: dts: OMAP: Add timer nodes
Add the 12 GP timers nodes present in OMAP2.
Add the 12 GP timers nodes present in OMAP3.
Add the 11 GP timers nodes present in OMAP4.
Add the 7 GP timers nodes present in AM33xx.
Add documentation for timer properties specific to OMAP.
Please note that for OMAP2/3 devices, there is only one interrupt controller for the ARM CPU (which has the label "intc") and so globally define this as the interrupt parent to save duplicating the interrupt parent for all device nodes.
Thanks to Vaibhav Hiremath for creating the AM33xx timer nodes. I have modified Vaibhav's original nodes adding information on which timers support a PWM output.
--- .../devicetree/bindings/arm/omap/timer.txt | 29 ++++++ arch/arm/boot/dts/am33xx.dtsi | 61 +++++++++++++ arch/arm/boot/dts/omap2.dtsi | 86 ++++++++++++++++++ arch/arm/boot/dts/omap2420.dtsi | 8 ++ arch/arm/boot/dts/omap2430.dtsi | 8 ++ arch/arm/boot/dts/omap3.dtsi | 96 ++++++++++++++++++++ arch/arm/boot/dts/omap4.dtsi | 86 ++++++++++++++++++ 7 files changed, 374 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/omap/timer.txt
Documentation/devicetree/bindings/arm/omap/timer.txt new file +29 -0
@@ -0,0 +1,29 @@ +OMAP Timer bindings + +Required properties: +- compatible: Must be "ti,omap2-timer" for OMAP2+ controllers +- reg: Contains timer register address range (base address and length) +- interrupts: Contains the interrupt information for the timer. The format is + being dependent on which interrupt controller the OMAP device + uses. +- ti,hwmods: Name of the hwmod associated to the timer, "timer<X>", where + <X> is the instance number of the timer from the HW spec. + +Optional properties: +- ti,timer-alwon: Indicates the timer is in an alway-on power domain. +- ti,timer-dsp: Indicates the timer can interrupt the on-chip DSP in + addition to the ARM CPU. +- ti,timer-pwm: Indicates the timer can generate a PWM output. +- ti,timer-secure: Indicates the timer is reserved on a secure OMAP device + and therefore cannot be used by the kernel. + +Example: + +timer12: timer at 48304000 { + compatible = "ti,omap2-timer"; + reg = <0x48304000 0xfff>; + interrupts = <95>; + ti,hwmods = "timer12" + ti,timer-alwon; + ti,timer-secure; +};
arch/arm/boot/dts/am33xx.dtsi +61 -0
66 lines not on this page · raw message
arch/arm/boot/dts/omap2.dtsi +86 -0
97 lines not on this page · raw message
arch/arm/boot/dts/omap2420.dtsi +8 -0
@@ -44,5 +44,13 @@ interrupt-parent = <&intc>; ti,hwmods = "mcbsp2"; }; + + timer1: timer at 48028000 { + compatible = "ti,omap2-timer"; + reg = <0x48028000 0xfff>; + interrupts = <37>; + ti,hwmods = "timer1"; + ti,timer-alwon; + }; }; };
arch/arm/boot/dts/omap2430.dtsi +8 -0
@@ -88,5 +88,13 @@ ti,buffer-size = <128>; ti,hwmods = "mcbsp5"; }; + + timer1: timer at 49018000 { + compatible = "ti,omap2-timer"; + reg = <0x49018000 0xfff>; + interrupts = <37>; + ti,hwmods = "timer1"; + ti,timer-alwon; + }; }; };
arch/arm/boot/dts/omap3.dtsi +96 -0
107 lines not on this page · raw message
arch/arm/boot/dts/omap4.dtsi +86 -0
91 lines not on this page · raw message
Signature · 1 line
1.7.9.5
PATCH v3 1/5 ARM: dts: OMAP: Add timer nodes
Quoted 17 lines · Jon
Add the 12 GP timers nodes present in OMAP2.
Add the 12 GP timers nodes present in OMAP3.
Add the 11 GP timers nodes present in OMAP4.
Add the 7 GP timers nodes present in AM33xx.Add documentation for timer properties specific to OMAP.
Please note that for OMAP2/3 devices, there is only one interrupt controller for the ARM CPU (which has the label "intc") and so globally define this as the interrupt parent to save duplicating the interrupt parent for all device nodes.
Thanks to Vaibhav Hiremath for creating the AM33xx timer nodes. I have modified Vaibhav's original nodes adding information on which timers support a PWM output.
Cc Benoit Cousson <[email protected]>Signed-off-by Jon Hunter <[email protected]>
Quoted 11 lines
--- .../devicetree/bindings/arm/omap/timer.txt | 29 ++++++ arch/arm/boot/dts/am33xx.dtsi | 61 +++++++++++++ arch/arm/boot/dts/omap2.dtsi | 86 ++++++++++++++++++ arch/arm/boot/dts/omap2420.dtsi | 8 ++ arch/arm/boot/dts/omap2430.dtsi | 8 ++ arch/arm/boot/dts/omap3.dtsi | 96 ++++++++++++++++++++ arch/arm/boot/dts/omap4.dtsi | 86 ++++++++++++++++++ 7 files changed, 374 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/omap/timer.txt
Although I have not tested this version of patch series at my end, but whole patch-series Looks ok to me.
Thanks,
Vaibhav
Quoted 458 lines
Documentation/devicetree/bindings/arm/omap/timer.txt new file +29
-0@@ -0,0 +1,29 @@ +OMAP Timer bindings + +Required properties: +- compatible: Must be "ti,omap2-timer" for OMAP2+ controllers +- reg: Contains timer register address range (base address and length) +- interrupts: Contains the interrupt information for the timer. The format is + being dependent on which interrupt controller the OMAP device + uses. +- ti,hwmods: Name of the hwmod associated to the timer, "timer<X>", where + <X> is the instance number of the timer from the HW spec. + +Optional properties: +- ti,timer-alwon: Indicates the timer is in an alway-on power domain. +- ti,timer-dsp: Indicates the timer can interrupt the on-chip DSP in + addition to the ARM CPU. +- ti,timer-pwm: Indicates the timer can generate a PWM output. +- ti,timer-secure: Indicates the timer is reserved on a secure OMAP device + and therefore cannot be used by the kernel. + +Example: + +timer12: timer at 48304000 { + compatible = "ti,omap2-timer"; + reg = <0x48304000 0xfff>; + interrupts = <95>; + ti,hwmods = "timer12" + ti,timer-alwon; + ti,timer-secure; +};arch/arm/boot/dts/am33xx.dtsi +61
-0@@ -210,5 +210,66 @@ interrupt-parent = <&intc>; interrupts = <91>; }; + + timer1: timer at 44e31000 { + compatible = "ti,omap2-timer"; + reg = <0x44e31000 0x1000>; + interrupt-parent = <&intc>; + interrupts = <67>; + ti,hwmods = "timer1"; + ti,timer-alwon; + }; + + timer2: timer at 48040000 { + compatible = "ti,omap2-timer"; + reg = <0x48040000 0x1000>; + interrupt-parent = <&intc>; + interrupts = <68>; + ti,hwmods = "timer2"; + }; + + timer3: timer at 48042000 { + compatible = "ti,omap2-timer"; + reg = <0x48042000 0x1000>; + interrupt-parent = <&intc>; + interrupts = <69>; + ti,hwmods = "timer3"; + }; + + timer4: timer at 48044000 { + compatible = "ti,omap2-timer"; + reg = <0x48044000 0x1000>; + interrupt-parent = <&intc>; + interrupts = <92>; + ti,hwmods = "timer4"; + ti,timer-pwm; + }; + + timer5: timer at 48046000 { + compatible = "ti,omap2-timer"; + reg = <0x48046000 0x1000>; + interrupt-parent = <&intc>; + interrupts = <93>; + ti,hwmods = "timer5"; + ti,timer-pwm; + }; + + timer6: timer at 48048000 { + compatible = "ti,omap2-timer"; + reg = <0x48048000 0x1000>; + interrupt-parent = <&intc>; + interrupts = <94>; + ti,hwmods = "timer6"; + ti,timer-pwm; + }; + + timer7: timer at 4804a000 { + compatible = "ti,omap2-timer"; + reg = <0x4804a000 0x1000>; + interrupt-parent = <&intc>; + interrupts = <95>; + ti,hwmods = "timer7"; + ti,timer-pwm; + }; }; };arch/arm/boot/dts/omap2.dtsi +86
-0@@ -12,6 +12,7 @@ / { compatible = "ti,omap2430", "ti,omap2420", "ti,omap2"; + interrupt-parent = <&intc>; aliases { serial0 = &uart1;@@ -65,5 +66,90 @@ ti,hwmods = "uart3"; clock-frequency = <48000000>; }; + + timer2: timer at 4802a000 { + compatible = "ti,omap2-timer"; + reg = <0x4802a000 0xfff>; + interrupts = <38>; + ti,hwmods = "timer2"; + }; + + timer3: timer at 48078000 { + compatible = "ti,omap2-timer"; + reg = <0x48078000 0xfff>; + interrupts = <39>; + ti,hwmods = "timer3"; + }; + + timer4: timer at 4807a000 { + compatible = "ti,omap2-timer"; + reg = <0x4807a000 0xfff>; + interrupts = <40>; + ti,hwmods = "timer4"; + }; + + timer5: timer at 4807c000 { + compatible = "ti,omap2-timer"; + reg = <0x4807c000 0xfff>; + interrupts = <41>; + ti,hwmods = "timer5"; + ti,timer-dsp; + }; + + timer6: timer at 4807e000 { + compatible = "ti,omap2-timer"; + reg = <0x4807e000 0xfff>; + interrupts = <42>; + ti,hwmods = "timer6"; + ti,timer-dsp; + }; + + timer7: timer at 48080000 { + compatible = "ti,omap2-timer"; + reg = <0x48080000 0xfff>; + interrupts = <43>; + ti,hwmods = "timer7"; + ti,timer-dsp; + }; + + timer8: timer at 48082000 { + compatible = "ti,omap2-timer"; + reg = <0x48082000 0xfff>; + interrupts = <44>; + ti,hwmods = "timer8"; + ti,timer-dsp; + }; + + timer9: timer at 48084000 { + compatible = "ti,omap2-timer"; + reg = <0x48084000 0xfff>; + interrupts = <45>; + ti,hwmods = "timer9"; + ti,timer-pwm; + }; + + timer10: timer at 48086000 { + compatible = "ti,omap2-timer"; + reg = <0x48086000 0xfff>; + interrupts = <46>; + ti,hwmods = "timer10"; + ti,timer-pwm; + }; + + timer11: timer at 48088000 { + compatible = "ti,omap2-timer"; + reg = <0x48088000 0xfff>; + interrupts = <47>; + ti,hwmods = "timer11"; + ti,timer-pwm; + }; + + timer12: timer at 4808a000 { + compatible = "ti,omap2-timer"; + reg = <0x4808a000 0xfff>; + interrupts = <48>; + ti,hwmods = "timer12"; + ti,timer-pwm; + }; }; };arch/arm/boot/dts/omap2420.dtsi +8
-0@@ -44,5 +44,13 @@ interrupt-parent = <&intc>; ti,hwmods = "mcbsp2"; }; + + timer1: timer at 48028000 { + compatible = "ti,omap2-timer"; + reg = <0x48028000 0xfff>; + interrupts = <37>; + ti,hwmods = "timer1"; + ti,timer-alwon; + }; }; };arch/arm/boot/dts/omap2430.dtsi +8
-0@@ -88,5 +88,13 @@ ti,buffer-size = <128>; ti,hwmods = "mcbsp5"; }; + + timer1: timer at 49018000 { + compatible = "ti,omap2-timer"; + reg = <0x49018000 0xfff>; + interrupts = <37>; + ti,hwmods = "timer1"; + ti,timer-alwon; + }; }; };arch/arm/boot/dts/omap3.dtsi +96
-0@@ -12,6 +12,7 @@ / { compatible = "ti,omap3430", "ti,omap3"; + interrupt-parent = <&intc>; aliases { serial0 = &uart1;@@ -300,5 +301,100 @@ ti,buffer-size = <128>; ti,hwmods = "mcbsp5"; }; + + timer1: timer at 48318000 { + compatible = "ti,omap2-timer"; + reg = <0x48318000 0xfff>; + interrupts = <37>; + ti,hwmods = "timer1"; + ti,timer-alwon; + }; + + timer2: timer at 49032000 { + compatible = "ti,omap2-timer"; + reg = <0x49032000 0xfff>; + interrupts = <38>; + ti,hwmods = "timer2"; + }; + + timer3: timer at 49034000 { + compatible = "ti,omap2-timer"; + reg = <0x49034000 0xfff>; + interrupts = <39>; + ti,hwmods = "timer3"; + }; + + timer4: timer at 49036000 { + compatible = "ti,omap2-timer"; + reg = <0x49036000 0xfff>; + interrupts = <40>; + ti,hwmods = "timer4"; + }; + + timer5: timer at 49038000 { + compatible = "ti,omap2-timer"; + reg = <0x49038000 0xfff>; + interrupts = <41>; + ti,hwmods = "timer5"; + ti,timer-dsp; + }; + + timer6: timer at 4903a000 { + compatible = "ti,omap2-timer"; + reg = <0x4903a000 0xfff>; + interrupts = <42>; + ti,hwmods = "timer6"; + ti,timer-dsp; + }; + + timer7: timer at 4903c000 { + compatible = "ti,omap2-timer"; + reg = <0x4903c000 0xfff>; + interrupts = <43>; + ti,hwmods = "timer7"; + ti,timer-dsp; + }; + + timer8: timer at 4903e000 { + compatible = "ti,omap2-timer"; + reg = <0x4903e000 0xfff>; + interrupts = <44>; + ti,hwmods = "timer8"; + ti,timer-pwm; + ti,timer-dsp; + }; + + timer9: timer at 49040000 { + compatible = "ti,omap2-timer"; + reg = <0x49040000 0xfff>; + interrupts = <45>; + ti,hwmods = "timer9"; + ti,timer-pwm; + }; + + timer10: timer at 48086000 { + compatible = "ti,omap2-timer"; + reg = <0x48086000 0xfff>; + interrupts = <46>; + ti,hwmods = "timer10"; + ti,timer-pwm; + }; + + timer11: timer at 48088000 { + compatible = "ti,omap2-timer"; + reg = <0x48088000 0xfff>; + interrupts = <47>; + ti,hwmods = "timer11"; + ti,timer-pwm; + }; + + timer12: timer at 48304000 { + compatible = "ti,omap2-timer"; + reg = <0x48304000 0xfff>; + interrupts = <95>; + ti,hwmods = "timer12"; + ti,timer-alwon; + ti,timer-secure; + }; }; };arch/arm/boot/dts/omap4.dtsi +86
-0@@ -438,5 +438,91 @@ ranges; ti,hwmods = "ocp2scp_usb_phy"; }; + + timer1: timer at 4a318000 { + compatible = "ti,omap2-timer"; + reg = <0x4a318000 0x7f>; + interrupts = <0 37 0x4>; + ti,hwmods = "timer1"; + ti,timer-alwon; + }; + + timer2: timer at 48032000 { + compatible = "ti,omap2-timer"; + reg = <0x48032000 0x7f>; + interrupts = <0 38 0x4>; + ti,hwmods = "timer2"; + }; + + timer3: timer at 48034000 { + compatible = "ti,omap2-timer"; + reg = <0x48034000 0x7f>; + interrupts = <0 39 0x4>; + ti,hwmods = "timer3"; + }; + + timer4: timer at 48036000 { + compatible = "ti,omap2-timer"; + reg = <0x48036000 0x7f>; + interrupts = <0 40 0x4>; + ti,hwmods = "timer4"; + }; + + timer5: timer at 49038000 { + compatible = "ti,omap2-timer"; + reg = <0x49038000 0x7f>; + interrupts = <0 41 0x4>; + ti,hwmods = "timer5"; + ti,timer-dsp; + }; + + timer6: timer at 4903a000 { + compatible = "ti,omap2-timer"; + reg = <0x4903a000 0x7f>; + interrupts = <0 42 0x4>; + ti,hwmods = "timer6"; + ti,timer-dsp; + }; + + timer7: timer at 4903c000 { + compatible = "ti,omap2-timer"; + reg = <0x4903c000 0x7f>; + interrupts = <0 43 0x4>; + ti,hwmods = "timer7"; + ti,timer-dsp; + }; + + timer8: timer at 4903e000 { + compatible = "ti,omap2-timer"; + reg = <0x4903e000 0x7f>; + interrupts = <0 44 0x4>; + ti,hwmods = "timer8"; + ti,timer-pwm; + ti,timer-dsp; + }; + + timer9: timer at 4803e000 { + compatible = "ti,omap2-timer"; + reg = <0x4803e000 0x7f>; + interrupts = <0 45 0x4>; + ti,hwmods = "timer9"; + ti,timer-pwm; + }; + + timer10: timer at 48086000 { + compatible = "ti,omap2-timer"; + reg = <0x48086000 0x7f>; + interrupts = <0 46 0x4>; + ti,hwmods = "timer10"; + ti,timer-pwm; + }; + + timer11: timer at 48088000 { + compatible = "ti,omap2-timer"; + reg = <0x48088000 0x7f>; + interrupts = <0 47 0x4>; + ti,hwmods = "timer11"; + ti,timer-pwm; + }; }; };Signature · 1 line
1.7.9.5
PATCH v3 1/5 ARM: dts: OMAP: Add timer nodes
Quoted 30 lines · Vaibhav
Quoted 17 lines · Jon
Add the 12 GP timers nodes present in OMAP2.
Add the 12 GP timers nodes present in OMAP3.
Add the 11 GP timers nodes present in OMAP4.
Add the 7 GP timers nodes present in AM33xx.Add documentation for timer properties specific to OMAP.
Please note that for OMAP2/3 devices, there is only one interrupt controller for the ARM CPU (which has the label "intc") and so globally define this as the interrupt parent to save duplicating the interrupt parent for all device nodes.
Thanks to Vaibhav Hiremath for creating the AM33xx timer nodes. I have modified Vaibhav's original nodes adding information on which timers support a PWM output.
Cc Benoit Cousson <[email protected]>Signed-off-by Jon Hunter <[email protected]>Quoted 11 lines
--- .../devicetree/bindings/arm/omap/timer.txt | 29 ++++++ arch/arm/boot/dts/am33xx.dtsi | 61 +++++++++++++ arch/arm/boot/dts/omap2.dtsi | 86 ++++++++++++++++++ arch/arm/boot/dts/omap2420.dtsi | 8 ++ arch/arm/boot/dts/omap2430.dtsi | 8 ++ arch/arm/boot/dts/omap3.dtsi | 96 ++++++++++++++++++++ arch/arm/boot/dts/omap4.dtsi | 86 ++++++++++++++++++ 7 files changed, 374 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/omap/timer.txt
Quoted 4 lines
Although I have not tested this version of patch series at my end, but whole patch-series Looks ok to me.
Acked-by Vaibhav Hiremath <[email protected]>
Thanks. I made a couple cosmetic changes in V4 apart from the "interrupt-parent" addition which we are now dropping. Care to ACK patches 2-5 of V4?
Thanks
Jon
PATCH v3 1/5 ARM: dts: OMAP: Add timer nodes
Quoted 32 lines · Jon
Quoted 30 lines · Vaibhav
Quoted 28 lines · Jon
Add the 12 GP timers nodes present in OMAP2.
Add the 12 GP timers nodes present in OMAP3.
Add the 11 GP timers nodes present in OMAP4.
Add the 7 GP timers nodes present in AM33xx.Add documentation for timer properties specific to OMAP.
Please note that for OMAP2/3 devices, there is only one interrupt controller for the ARM CPU (which has the label "intc") and so globally define this as the interrupt parent to save duplicating the interrupt parent for all device nodes.
Thanks to Vaibhav Hiremath for creating the AM33xx timer nodes. I have modified Vaibhav's original nodes adding information on which timers support a PWM output.
Cc Benoit Cousson <[email protected]>Signed-off-by Jon Hunter <[email protected]>--- .../devicetree/bindings/arm/omap/timer.txt | 29 ++++++ arch/arm/boot/dts/am33xx.dtsi | 61 +++++++++++++ arch/arm/boot/dts/omap2.dtsi | 86 ++++++++++++++++++ arch/arm/boot/dts/omap2420.dtsi | 8 ++ arch/arm/boot/dts/omap2430.dtsi | 8 ++ arch/arm/boot/dts/omap3.dtsi | 96 ++++++++++++++++++++ arch/arm/boot/dts/omap4.dtsi | 86 ++++++++++++++++++ 7 files changed, 374 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/omap/timer.txt
Quoted 9 lines
Quoted 4 lines
Although I have not tested this version of patch series at my end, but whole patch-series Looks ok to me.
Acked-by Vaibhav Hiremath <[email protected]>Thanks. I made a couple cosmetic changes in V4 apart from the "interrupt-parent" addition which we are now dropping. Care to ACK patches 2-5 of V4?
Jon,
Good news, I could able to spend some time today on Timer issue on Am33xx and figure out what is going wrong there. The register context is loosing, which leads to failure of interrupt test cases.
Below log describes more on this,
[root at arago /]# echo 1 > /tmp/omap-test/timer/all
[ 9.156122] Testing 48042000.timer with 24000000 Hz clock ...
[root at arago /]#
[root at arago /]#
[root at arago /]#
[root at arago /]# [ 11.505497] Timer read test PASSED! No errors, 100 loops
[ 11.511493] omap_dm_timer_set_int_enable:664: irq_ena - 0 [ 11.517277] omap_dm_timer_set_int_enable:670: irq_ena - 2 [ 11.523095] omap_timer_interrupt_test:120: irq_ena - 0 [BOOOOOOOOM] [ 12.521111] Timer interrupt test FAILED! No interrupt occurred in 1 sec
I changed the Test code as below, and not with your Timer patches, I have tested all the timers without any issues.
So for all patch series,
Acked-Reviewed-&-Tested-By: Vaibhav Hiremath <[email protected]>
Test code diff:
===============
timer_test.c +9 -0
@@ -13,6 +13,7 @@#define OMAP1_NUM_TIMERS 8#define OMAP2_NUM_TIMERS 11 +#define AM33XX_NUM_TIMERS 7#define OMAP_MAX_NUM_TIMERS 12#define OMAP_TIMER_SRC_CLKS 2#define TIMER_TIMEOUT (msecs_to_jiffies(1000))
@@ -113,6 +114,9 @@ static int omap_timer_interrupt_test(struct omap_dm_timer *gptimer) irq_data.gptimer = gptimer;init_completion (&irq_data.complete); + +omap_dm_timer_enable (gptimer); +omap_dm_timer_set_int_enable (gptimer,OMAP_TIMER_INT_OVERFLOW );omap_dm_timer_set_load_start (gptimer,0 ,0xffffff00 );
@@ -128,6 +132,8 @@ static int omap_timer_interrupt_test(struct omap_dm_timer *gptimer)omap_dm_timer_stop (gptimer);omap_dm_timer_set_int_enable (gptimer,0 ); +omap_dm_timer_disable (gptimer); +free_irq (timer_irq, &irq_data);return r;
@@ -141,6 +147,8 @@ static u32 omap_timer_num_timers(void) max_num_timers =OMAP1_NUM_TIMERS ; else if (cpu_is_omap34xx() && (omap_type() == OMAP2_DEVICE_TYPE_GP)) max_num_timers =OMAP2_NUM_TIMERS +1 ; + else if (soc_is_am33xx()) + max_num_timers =AM33XX_NUM_TIMERS ; else max_num_timers =OMAP2_NUM_TIMERS ;
@@ -222,6 +230,7 @@ static int omap_timer_test_all(void) }for (i =0 ; i < count; i++) { +pr_info ("\n\n" ); r =omap_timer_run_tests (gptimers[i]);if (r) errors += r;
Thanks,
Vaibhav
PATCH v3 1/5 ARM: dts: OMAP: Add timer nodes
Quoted 43 lines · Vaibhav
Quoted 32 lines · Jon
Quoted 30 lines · Vaibhav
Quoted 28 lines · Jon
Add the 12 GP timers nodes present in OMAP2.
Add the 12 GP timers nodes present in OMAP3.
Add the 11 GP timers nodes present in OMAP4.
Add the 7 GP timers nodes present in AM33xx.Add documentation for timer properties specific to OMAP.
Please note that for OMAP2/3 devices, there is only one interrupt controller for the ARM CPU (which has the label "intc") and so globally define this as the interrupt parent to save duplicating the interrupt parent for all device nodes.
Thanks to Vaibhav Hiremath for creating the AM33xx timer nodes. I have modified Vaibhav's original nodes adding information on which timers support a PWM output.
Cc Benoit Cousson <[email protected]>Signed-off-by Jon Hunter <[email protected]>--- .../devicetree/bindings/arm/omap/timer.txt | 29 ++++++ arch/arm/boot/dts/am33xx.dtsi | 61 +++++++++++++ arch/arm/boot/dts/omap2.dtsi | 86 ++++++++++++++++++ arch/arm/boot/dts/omap2420.dtsi | 8 ++ arch/arm/boot/dts/omap2430.dtsi | 8 ++ arch/arm/boot/dts/omap3.dtsi | 96 ++++++++++++++++++++ arch/arm/boot/dts/omap4.dtsi | 86 ++++++++++++++++++ 7 files changed, 374 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/omap/timer.txtQuoted 9 lines
Quoted 4 lines
Although I have not tested this version of patch series at my end, but whole patch-series Looks ok to me.
Acked-by Vaibhav Hiremath <[email protected]>Thanks. I made a couple cosmetic changes in V4 apart from the "interrupt-parent" addition which we are now dropping. Care to ACK patches 2-5 of V4?
Quoted 5 lines
Jon,
Good news, I could able to spend some time today on Timer issue on Am33xx and figure out what is going wrong there. The register context is loosing, which leads to failure of interrupt test cases.
Thanks!
Quoted 15 lines
Below log describes more on this,
[root at arago /]# echo 1 >
/tmp/omap-test/timer/all[ 9.156122] Testing 48042000.timer with 24000000 Hz clock ...[root at arago /]#
[root at arago /]#
[root at arago /]#
[root at arago /]# [ 11.505497] Timer read test PASSED! No errors, 100 loops[ 11.511493] omap_dm_timer_set_int_enable:664: irq_ena - 0 [ 11.517277] omap_dm_timer_set_int_enable:670: irq_ena - 2 [ 11.523095] omap_timer_interrupt_test:120: irq_ena - 0 [BOOOOOOOOM] [ 12.521111] Timer interrupt test FAILED! No interrupt occurred in 1 sec
Quoted 6 lines
I changed the Test code as below, and not with your Timer patches, I have tested all the timers without any issues.
So for all patch series,
Acked-Reviewed-&-Tested-By: Vaibhav Hiremath <[email protected]>
Thanks!
Quoted 27 lines
Test code diff:
===============timer_test.c +4
-0@@ -13,6 +13,7 @@#define OMAP1_NUM_TIMERS 8#define OMAP2_NUM_TIMERS 11 +#define AM33XX_NUM_TIMERS 7#define OMAP_MAX_NUM_TIMERS 12#define OMAP_TIMER_SRC_CLKS 2#define TIMER_TIMEOUT (msecs_to_jiffies(1000))@@ -113,6 +114,9 @@ static int omap_timer_interrupt_test(struct omap_dm_timer *gptimer) irq_data.gptimer = gptimer;init_completion (&irq_data.complete); + +omap_dm_timer_enable (gptimer); +omap_dm_timer_set_int_enable (gptimer,OMAP_TIMER_INT_OVERFLOW );omap_dm_timer_set_load_start (gptimer,0 ,0xffffff00 );
timer_test.c static int omap_timer_interrupt_test(struct omap_dm_timer *gptimer) · line 136
Quoted 5 lines
timer_test.c +2
-0@@ -128,6 +132,8 @@ static int omap_timer_interrupt_test(struct omap_dm_timer *gptimer)omap_dm_timer_stop (gptimer);omap_dm_timer_set_int_enable (gptimer,0 ); +omap_dm_timer_disable (gptimer); +
Hmmm ... I am wondering if there is another bug lingering in the dmtimer driver. Ideally, the context should be preserved by the driver.
timer_test.c static u32 omap_timer_num_timers(void) · line 151
Quoted 9 lines
timer_test.c +2
-0free_irq (timer_irq, &irq_data);return r;@@ -141,6 +147,8 @@ static u32 omap_timer_num_timers(void) max_num_timers =OMAP1_NUM_TIMERS ; else if (cpu_is_omap34xx() && (omap_type() == OMAP2_DEVICE_TYPE_GP)) max_num_timers =OMAP2_NUM_TIMERS +1 ; + else if (soc_is_am33xx()) + max_num_timers =AM33XX_NUM_TIMERS ;
Thanks, I noticed that too when testing AM33xx.
Cheers
Jon
PATCH v3 1/5 ARM: dts: OMAP: Add timer nodes
On 10/25/2012 07:18 AM, Jon Hunter wrote:
...
Quoted 12 lines
Quoted 12 lines
timer_test.c +3
-0@@ -113,6 +114,9 @@ static int omap_timer_interrupt_test(struct omap_dm_timer *gptimer) irq_data.gptimer = gptimer;init_completion (&irq_data.complete); + +omap_dm_timer_enable (gptimer); +omap_dm_timer_set_int_enable (gptimer,OMAP_TIMER_INT_OVERFLOW );omap_dm_timer_set_load_start (gptimer,0 ,0xffffff00 );@@ -128,6 +132,8 @@ static int omap_timer_interrupt_test(struct omap_dm_timer *gptimer)
Quoted 7 lines
timer_test.c static int omap_timer_interrupt_test(struct omap_dm_timer *gptimer) · line 136
Quoted 4 lines
timer_test.c +2
-0omap_dm_timer_stop (gptimer);omap_dm_timer_set_int_enable (gptimer,0 ); +omap_dm_timer_disable (gptimer); +Hmmm ... I am wondering if there is another bug lingering in the dmtimer driver. Ideally, the context should be preserved by the driver.
Looking at omap_dm_timer_set_load_start() we have the following code to restore context ...
if (!(timer->capability & OMAP_TIMER_ALWON)) {
if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) !=
timer->ctx_loss_count)
omap_timer_restore_context(timer);
}Can you see if this is getting called for AM33xx for the failing timers? If not then it would suggest that we are not detecting context loss correctly and not restoring the context. With the above context restore code we should not need those extra omap_dm_timer_enable/disable calls.
Cheers
Jon
PATCH v3 1/5 ARM: dts: OMAP: Add timer nodes
Quoted 34 lines · Jon
On 10/25/2012 07:18 AM, Jon Hunter wrote:
...
Quoted 12 lines
Quoted 12 lines
timer_test.c +3
-0@@ -113,6 +114,9 @@ static int omap_timer_interrupt_test(struct omap_dm_timer *gptimer) irq_data.gptimer = gptimer;init_completion (&irq_data.complete); + +omap_dm_timer_enable (gptimer); +omap_dm_timer_set_int_enable (gptimer,OMAP_TIMER_INT_OVERFLOW );omap_dm_timer_set_load_start (gptimer,0 ,0xffffff00 );@@ -128,6 +132,8 @@ static int omap_timer_interrupt_test(struct omap_dm_timer *gptimer)Quoted 7 lines
timer_test.c static int omap_timer_interrupt_test(struct omap_dm_timer *gptimer) · line 136
Quoted 4 lines
timer_test.c +2
-0omap_dm_timer_stop (gptimer);omap_dm_timer_set_int_enable (gptimer,0 ); +omap_dm_timer_disable (gptimer); +Hmmm ... I am wondering if there is another bug lingering in the dmtimer driver. Ideally, the context should be preserved by the driver.
Looking at
omap_dm_timer_set_load_start()we have the following code to restore context ...if (!(timer->capability & OMAP_TIMER_ALWON)) { if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) != timer->ctx_loss_count) omap_timer_restore_context(timer); }
Quoted 5 lines
Can you see if this is getting called for AM33xx for the failing timers? If not then it would suggest that we are not detecting context loss correctly and not restoring the context. With the above context restore code we should not need those extra omap_dm_timer_enable/disable calls.
OK, below log explains all now,
----------------------
Testing 48042000.timer with 24000000 Hz clock ... omap_dm_timer_set_load_start:559 ctx_loss_count - 0, get_dev_context - 0 Timer read test PASSED! No errors, 100 loops omap_dm_timer_set_int_enable:665: irq_ena - 0 omap_dm_timer_set_int_enable:671: irq_ena - 2 omap_dm_timer_set_load_start:559 ctx_loss_count - 0, get_dev_context - 0 Timer interrupt test FAILED! No interrupt occurred in 1 sec omap_dm_timer_set_int_enable:665: irq_ena - 0 omap_dm_timer_set_int_enable:671: irq_ena - 0
Testing 48042000.timer with 32768 Hz clock ... omap_dm_timer_set_load_start:559 ctx_loss_count - 0, get_dev_context - 0
----------------------
So below condition is not passing for AM33xx which results into context loss.
if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) !=
timer->ctx_loss_count)
Let me debug on this, this looks something specific to am33xx missing from baseport.
Thanks,
Vaibhav
PATCH v3 1/5 ARM: dts: OMAP: Add timer nodes
In reply to Jon HunterQuoted 105 lines · Jon
Quoted 43 lines · Vaibhav
Quoted 32 lines · Jon
Quoted 30 lines · Vaibhav
Quoted 28 lines · Jon
Add the 12 GP timers nodes present in OMAP2.
Add the 12 GP timers nodes present in OMAP3.
Add the 11 GP timers nodes present in OMAP4.
Add the 7 GP timers nodes present in AM33xx.Add documentation for timer properties specific to OMAP.
Please note that for OMAP2/3 devices, there is only one interrupt controller for the ARM CPU (which has the label "intc") and so globally define this as the interrupt parent to save duplicating the interrupt parent for all device nodes.
Thanks to Vaibhav Hiremath for creating the AM33xx timer nodes. I have modified Vaibhav's original nodes adding information on which timers support a PWM output.
Cc Benoit Cousson <[email protected]>Signed-off-by Jon Hunter <[email protected]>--- .../devicetree/bindings/arm/omap/timer.txt | 29 ++++++ arch/arm/boot/dts/am33xx.dtsi | 61 +++++++++++++ arch/arm/boot/dts/omap2.dtsi | 86 ++++++++++++++++++ arch/arm/boot/dts/omap2420.dtsi | 8 ++ arch/arm/boot/dts/omap2430.dtsi | 8 ++ arch/arm/boot/dts/omap3.dtsi | 96 ++++++++++++++++++++ arch/arm/boot/dts/omap4.dtsi | 86 ++++++++++++++++++ 7 files changed, 374 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/omap/timer.txtQuoted 9 lines
Quoted 4 lines
Although I have not tested this version of patch series at my end, but whole patch-series Looks ok to me.
Acked-by Vaibhav Hiremath <[email protected]>Thanks. I made a couple cosmetic changes in V4 apart from the "interrupt-parent" addition which we are now dropping. Care to ACK patches 2-5 of V4?
Quoted 5 lines
Jon,
Good news, I could able to spend some time today on Timer issue on Am33xx and figure out what is going wrong there. The register context is loosing, which leads to failure of interrupt test cases.
Thanks!
Quoted 15 lines
Below log describes more on this,
[root at arago /]# echo 1 >
/tmp/omap-test/timer/all[ 9.156122] Testing 48042000.timer with 24000000 Hz clock ...[root at arago /]#
[root at arago /]#
[root at arago /]#
[root at arago /]# [ 11.505497] Timer read test PASSED! No errors, 100 loops[ 11.511493] omap_dm_timer_set_int_enable:664: irq_ena - 0 [ 11.517277] omap_dm_timer_set_int_enable:670: irq_ena - 2 [ 11.523095] omap_timer_interrupt_test:120: irq_ena - 0 [BOOOOOOOOM] [ 12.521111] Timer interrupt test FAILED! No interrupt occurred in 1 secQuoted 6 lines
I changed the Test code as below, and not with your Timer patches, I have tested all the timers without any issues.
So for all patch series,
Acked-Reviewed-&-Tested-By: Vaibhav Hiremath <[email protected]>
Thanks!
Quoted 28 lines
Test code diff:
===============timer_test.c +4
-0@@ -13,6 +13,7 @@#define OMAP1_NUM_TIMERS 8#define OMAP2_NUM_TIMERS 11 +#define AM33XX_NUM_TIMERS 7#define OMAP_MAX_NUM_TIMERS 12#define OMAP_TIMER_SRC_CLKS 2#define TIMER_TIMEOUT (msecs_to_jiffies(1000))@@ -113,6 +114,9 @@ static int omap_timer_interrupt_test(struct omap_dm_timer *gptimer) irq_data.gptimer = gptimer;init_completion (&irq_data.complete); + +omap_dm_timer_enable (gptimer); +omap_dm_timer_set_int_enable (gptimer,OMAP_TIMER_INT_OVERFLOW );omap_dm_timer_set_load_start (gptimer,0 ,0xffffff00 );@@ -128,6 +132,8 @@ static int omap_timer_interrupt_test(struct omap_dm_timer *gptimer)
Quoted 8 lines
timer_test.c static int omap_timer_interrupt_test(struct omap_dm_timer *gptimer) · line 136
Quoted 4 lines
timer_test.c +2
-0omap_dm_timer_stop (gptimer);omap_dm_timer_set_int_enable (gptimer,0 ); +omap_dm_timer_disable (gptimer); +Hmmm ... I am wondering if there is another bug lingering in the dmtimer driver. Ideally, the context should be preserved by the driver.
That's what I am going behind...
Quoted 12 lines
timer_test.c static u32 omap_timer_num_timers(void) · line 151
Quoted 9 lines
timer_test.c +2
-0free_irq (timer_irq, &irq_data);return r;@@ -141,6 +147,8 @@ static u32 omap_timer_num_timers(void) max_num_timers =OMAP1_NUM_TIMERS ; else if (cpu_is_omap34xx() && (omap_type() == OMAP2_DEVICE_TYPE_GP)) max_num_timers =OMAP2_NUM_TIMERS +1 ; + else if (soc_is_am33xx()) + max_num_timers =AM33XX_NUM_TIMERS ;Thanks, I noticed that too when testing AM33xx.
Can you merge it to your test module? I am thinking of pushing application to github for others to use. I believe you are ok with this. I am planning to push all the application there.
https://github.com/hvaibhav/sample-applications
Thanks,
Vaibhav
Quoted 3 lines
Cheers
Jon
PATCH v3 1/5 ARM: dts: OMAP: Add timer nodes
On 10/25/2012 10:27 AM, Hiremath, Vaibhav wrote:
...
Quoted 5 lines
Can you merge it to your test module? I am thinking of pushing application to github for others to use. I believe you are ok with this. I am planning to push all the application there.
Thanks. I have been meaning to do this. I have pushed my latest version here [1]. Should include the AM335x fix too. Let me know if this is working for you.
Cheers
Jon
PATCH v3 2/5 ARM: OMAP3: Dynamically disable secure timer nodes for secure devices
In reply to Jon HunterOMAP3 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
--- arch/arm/mach-omap2/timer.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
arch/arm/mach-omap2/timer.c +36 -0
@@ -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); \ }
Signature · 1 line
1.7.9.5
PATCH v3 3/5 ARM: OMAP: Add function to request a timer by capability
In reply to Jon HunterCurrently OMAP timers can be requested by requesting any available or by a numerical device ID. If a specific timer is required because it has a particular capability, such as can interrupt the on-chip DSP in addition to the ARM CPU, then the user needs to know the device ID of the timer with this feature. Therefore, add a new API called omap_dm_timer_request_by_cap() that allows drivers to request a timer by capability.
--- arch/arm/plat-omap/dmtimer.c | 52 +++++++++++++++++++++++++++++ arch/arm/plat-omap/include/plat/dmtimer.h | 1 + 2 files changed, 53 insertions(+)
arch/arm/plat-omap/dmtimer.c +52 -0
@@ -237,6 +237,58 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id) }EXPORT_SYMBOL_GPL (omap_dm_timer_request_specific); +/** +* omap_dm_timer_request_by_cap - Request a timer by capability +* @cap: Bit mask of capabilities to match +* +* Find a timer based upon capabilities bit mask. Callers of this function +* should use the definitions found in the plat/dmtimer.h file under the +* comment "timer capabilities used in hwmod database". Returns pointer to +* timer handle on success and a NULL pointer on failure. +*/ +struct omap_dm_timer *omap_dm_timer_request_by_cap (u32 cap) +{ +struct omap_dm_timer *timer =NULL , *t; +unsigned long flags; + +if (!cap) +return NULL ; + +spin_lock_irqsave (&dm_timer_lock, flags); +list_for_each_entry (t, &omap_timer_list, node) { +if ((!t->reserved) && ((t->capability & cap) == cap)) { +/* +* If timer is not NULL, we have already found one timer +* but it was not an exact match because it had more +* capabilites that what was required. Therefore, +* unreserve the last timer found and see if this one +* is a better match. +*/ +if (timer) + timer->reserved =0 ; + + timer = t; + timer->reserved =1 ; + +/* Exit loop early if we find an exact match */ +if (t->capability == cap) +break ; + } + } +spin_unlock_irqrestore (&dm_timer_lock, flags); + +if (timer &&omap_dm_timer_prepare (timer)) { + timer->reserved =0 ; + timer =NULL ; + } + +if (!timer) +pr_debug ("%s: timer request failed!\n" , __func__); + +return timer; +} +EXPORT_SYMBOL_GPL (omap_dm_timer_request_by_cap); +int omap_dm_timer_free (struct omap_dm_timer *timer) {if (unlikely (!timer))
arch/arm/plat-omap/include/plat/dmtimer.h +1 -0
@@ -99,6 +99,7 @@ struct dmtimer_platform_data {int omap_dm_timer_reserve_systimer (int id);struct omap_dm_timer *omap_dm_timer_request (void );struct omap_dm_timer *omap_dm_timer_request_specific (int timer_id); +struct omap_dm_timer *omap_dm_timer_request_by_cap (u32 cap);int omap_dm_timer_free (struct omap_dm_timer *timer);void omap_dm_timer_enable (struct omap_dm_timer *timer);void omap_dm_timer_disable (struct omap_dm_timer *timer);
Signature · 1 line
1.7.9.5
PATCH v3 4/5 ARM: OMAP3: Add generic machine descriptor for boards with OMAP3 GP devices
In reply to Jon HunterOMAP3 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).
Some OMAP3 boards, such as the OMAP3 beagle board, only use GP devices and for GP devices there is a 12th timer available on-chip that can operate at 32kHz. The clock for 12th timer is generated by an internal oscillator and is unique this timer. Boards such as the beagle board use this timer as a 32kHz based clock-events timer because early versions of the board had a hardware problem preventing them from using other on-chip timers clocked by a external 32kHz clock.
When booting with device-tree all OMAP3 devices use timer 1 by default for the clock-events timer. Therefore, add a generic machine descriptor for boards with OMAP3 GP devices so that they can use the 12th timer as the clock-events timer instead of the default.
--- arch/arm/mach-omap2/board-generic.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
arch/arm/mach-omap2/board-generic.c +17 -0
@@ -97,6 +97,23 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)") .dt_compat = omap3_boards_compat, .restart = omap_prcm_restart, MACHINE_END + +static const char *omap3_gp_boards_compat[] __initdata = { +"ti,omap3-beagle" , +NULL , +}; + +DT_MACHINE_START (OMAP3_GP_DT ,"Generic OMAP3-GP (Flattened Device Tree)" ) + .reserve = omap_reserve, + .map_io = omap3_map_io, + .init_early = omap3430_init_early, + .init_irq = omap_intc_of_init, + .handle_irq = omap3_intc_handle_irq, + .init_machine = omap_generic_init, + .timer = &omap3_secure_timer, + .dt_compat = omap3_gp_boards_compat, + .restart = omap_prcm_restart, +MACHINE_END#endif #ifdef CONFIG_SOC_AM33XX
Signature · 1 line
1.7.9.5
PATCH v3 5/5 ARM: OMAP: Add DT support for timer driver
In reply to Jon HunterIn order to add device-tree support to the timer driver the following changes were made ...
1. Allocate system timers (used for clock-events and clock-source) based upon timer properties rather than using an hard-coded timer instance ID. To allow this a new helper function called omap_dmtimer_find_by_property() has been added for finding a timer with the particular properties in the device-tree blob. Please note that this is an internal helper function for system timers only to find a timer in the device-tree blob. This cannot be used by device drivers, another API has been added for that (see below). Timers that are allocated for system timers are dynamically disabled at boot time by adding a status property with the value "disabled" to the timer's device-tree node.
Please note that when allocating system timers we now pass a timer ID and timer property. The timer ID is only be used for allocating a timer when booting without device-tree. Once device-tree migration is complete, all the timer ID references will be removed.
2. System timer resources (memory and interrupts) are directly obtained from the device-tree timer node when booting with device-tree, so that system timers are no longer reliant upon the OMAP HWMOD framework to provide these resources.
3. If DT blob is present, then let device-tree create the timer devices dynamically.
4. When device-tree is present the "id" field in the platform_device structure (pdev->id) is initialised to -1 and hence cannot be used to identify a timer instance. Due to this the following changes were made ...
a). The API omap_dm_timer_request_specific() is not supported when using
device-tree, because it uses the device ID to request a specific timer. This function will return an error if called when device-tree is present. Users of this API should use omap_dm_timer_request_by_cap() instead.
b). When removing the DMTIMER driver, the timer "id" was used to identify the
timer instance. The remove function has been modified to use the device name instead of the "id".
5. When device-tree is present the platform_data structure will be NULL and so check for this.
6. The OMAP timer device tree binding has the following optional parameters ...
a). ti,timer-alwon --> Timer is in an always-on power domain b). ti,timer-dsp --> Timer can generate an interrupt to the on-chip DSP c). ti,timer-pwm --> Timer can generate a PWM output
d). ti,timer-secure --> Timer is reserved on a secure OMAP device Search for the above parameters and set the appropriate timer attribute flags.
--- arch/arm/mach-omap2/timer.c | 146 ++++++++++++++++++++++++++++++++---------- arch/arm/plat-omap/dmtimer.c | 41 ++++++++++-- 2 files changed, 146 insertions(+), 41 deletions(-)
arch/arm/mach-omap2/timer.c +111 -35
@@ -37,6 +37,8 @@#include <linux/clockchips.h> #include <linux/slab.h> #include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <asm/mach/time.h> #include <asm/smp_twd.h>
@@ -66,11 +68,13 @@#define OMAP3_CLKEV_SOURCE OMAP3_32K_SOURCE#define OMAP4_CLKEV_SOURCE OMAP4_32K_SOURCE#define OMAP3_SECURE_TIMER 12 +#define TIMER_PROP_SECURE "ti,timer-secure"#else #define OMAP2_CLKEV_SOURCE OMAP2_MPU_SOURCE#define OMAP3_CLKEV_SOURCE OMAP3_MPU_SOURCE#define OMAP4_CLKEV_SOURCE OMAP4_MPU_SOURCE#define OMAP3_SECURE_TIMER 1 +#define TIMER_PROP_SECURE "ti,timer-alwon"#endif #define REALTIME_COUNTER_BASE 0x48243200
@@ -156,6 +160,40 @@ static struct of_device_id omap_timer_match[] __initdata = { };/** +* omap_get_timer_dt - get a timer using device-tree +* @match - device-tree match structure for matching a device type +* @property - optional timer property to match +* +* Helper function to get a timer during early boot using device-tree for use +* as kernel system timer. Optionally, the property argument can be used to +* select a timer with a specific property. Once a timer is found then mark +* the timer node in device-tree as disabled, to prevent the kernel from +* registering this timer as a platform device and so no one else can use it. +*/ +static struct device_node *__init omap_get_timer_dt (struct of_device_id *match, +const char *property) +{ +struct device_node *np; + +for_each_matching_node (np, match) { +if (!of_device_is_available (np)) { +of_node_put (np); +continue ; + } + +if (property && !of_get_property (np, property,NULL )) { +of_node_put (np); +continue ; + } + +prom_add_property (np, &device_disabled); +return np; + } + +return NULL ; +} + +/** * omap_dmtimer_init - initialisation function when device tree is used * * For secure OMAP3 devices, timers with device type "timer-secure" cannot
@@ -172,43 +210,71 @@ void __init omap_dmtimer_init(void)/* 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); - } + np =omap_get_timer_dt (omap_timer_match,"ti,timer-secure" ); +if (np) +of_node_put (np); } }static int __init omap_dm_timer_init_one (struct omap_dm_timer *timer,int gptimer_id, -const char *fck_source) +const char *fck_source, +const char *property) {char name[10 ];/* 10 = sizeof("gptXX_Xck0") */ +const char *oh_name; +struct device_node *np;struct omap_hwmod *oh;struct resource irq_rsrc, mem_rsrc;size_t size;int res =0 ;int r; -sprintf (name,"timer%d" , gptimer_id); -omap_hwmod_setup_one (name); - oh =omap_hwmod_lookup (name); +if (of_have_populated_dt ()) { + np =omap_get_timer_dt (omap_timer_match,NULL ); +if (!np) +return -ENODEV ; + +of_property_read_string_index (np,"ti,hwmods" ,0 , &oh_name); +if (!oh_name) +return -ENODEV ; + + timer->irq =irq_of_parse_and_map (np,0 ); +if (!timer->irq) +return -ENXIO ; + + timer->io_base =of_iomap (np,0 ); + +of_node_put (np); + }else { +sprintf (name,"timer%d" , gptimer_id); + oh_name = name; + } + +omap_hwmod_setup_one (oh_name); + oh =omap_hwmod_lookup (oh_name); +if (!oh)return -ENODEV ; - r =omap_hwmod_get_resource_byname (oh,IORESOURCE_IRQ ,NULL , &irq_rsrc); -if (r) -return -ENXIO ; - timer->irq = irq_rsrc.start; - - r =omap_hwmod_get_resource_byname (oh,IORESOURCE_MEM ,NULL , &mem_rsrc); -if (r) -return -ENXIO ; - timer->phys_base = mem_rsrc.start; - size = mem_rsrc.end - mem_rsrc.start; +if (!of_have_populated_dt ()) { + r =omap_hwmod_get_resource_byname (oh,IORESOURCE_IRQ ,NULL , + &irq_rsrc); +if (r) +return -ENXIO ; + timer->irq = irq_rsrc.start; + + r =omap_hwmod_get_resource_byname (oh,IORESOURCE_MEM ,NULL , + &mem_rsrc); +if (r) +return -ENXIO ; + timer->phys_base = mem_rsrc.start; + size = mem_rsrc.end - mem_rsrc.start; + +/* Static mapping, never released */ + timer->io_base =ioremap (timer->phys_base, size); + } -/* Static mapping, never released */ - timer->io_base =ioremap (timer->phys_base, size);if (!timer->io_base)return -ENXIO ;
@@ -219,9 +285,11 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,omap_hwmod_enable (oh); -if (omap_dm_timer_reserve_systimer (gptimer_id)) -return -ENODEV ; +if (!of_have_populated_dt ()) +if (omap_dm_timer_reserve_systimer (gptimer_id)) +return -ENODEV ; +/* FIXME: Need to remove hard-coded test on timer ID */ if (gptimer_id !=12 ) {struct clk *src;
@@ -231,8 +299,8 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, }else { res =__omap_dm_timer_set_source (timer->fclk, src);if (IS_ERR_VALUE (res)) -pr_warning ("%s: timer%i cannot set source\n" , - __func__, gptimer_id); +pr_warn ("%s: %s cannot set source\n" , + __func__, oh->name);clk_put (src); } }
@@ -248,11 +316,12 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, }static void __init omap2_gp_clockevent_init (int gptimer_id, -const char *fck_source) +const char *fck_source, +const char *property) {int res; - res =omap_dm_timer_init_one (&clkev, gptimer_id, fck_source); + res =omap_dm_timer_init_one (&clkev, gptimer_id, fck_source, property);BUG_ON (res); omap2_gp_timer_irq.dev_id = &clkev;
@@ -356,7 +425,7 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id, {int res; - res =omap_dm_timer_init_one (&clksrc, gptimer_id, fck_source); + res =omap_dm_timer_init_one (&clksrc, gptimer_id, fck_source,NULL );BUG_ON (res); __omap_dm_timer_load_start(&clksrc,
@@ -468,12 +537,12 @@ static inline void __init realtime_counter_init(void) {}#endif -#define OMAP_SYS_TIMER_INIT (name, clkev_nr, clkev_src, \ +#define OMAP_SYS_TIMER_INIT (name, clkev_nr, clkev_src, clkev_prop, \ clksrc_nr, clksrc_src) \ static void __init omap##name##_timer_init(void) \ { \ omap_dmtimer_init(); \ - omap2_gp_clockevent_init((clkev_nr), clkev_src); \ + omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \ omap2_clocksource_init((clksrc_nr), clksrc_src); \ }
@@ -483,20 +552,23 @@ struct sys_timer omap##name##_timer = { \ };#ifdef CONFIG_ARCH_OMAP2 -OMAP_SYS_TIMER_INIT(2, 1, OMAP2_CLKEV_SOURCE, 2, OMAP2_MPU_SOURCE) +OMAP_SYS_TIMER_INIT (2 ,1 ,OMAP2_CLKEV_SOURCE ,"ti,timer-alwon" , + 2, OMAP2_MPU_SOURCE) OMAP_SYS_TIMER(2)#endif #ifdef CONFIG_ARCH_OMAP3 -OMAP_SYS_TIMER_INIT(3, 1, OMAP3_CLKEV_SOURCE, 2, OMAP3_MPU_SOURCE) +OMAP_SYS_TIMER_INIT (3 ,1 ,OMAP3_CLKEV_SOURCE ,"ti,timer-alwon" , + 2, OMAP3_MPU_SOURCE) OMAP_SYS_TIMER(3) OMAP_SYS_TIMER_INIT(3_secure, OMAP3_SECURE_TIMER, OMAP3_CLKEV_SOURCE, - 2, OMAP3_MPU_SOURCE) + TIMER_PROP_SECURE, 2, OMAP3_MPU_SOURCE) OMAP_SYS_TIMER(3_secure)#endif #ifdef CONFIG_SOC_AM33XX -OMAP_SYS_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, 2, OMAP4_MPU_SOURCE) +OMAP_SYS_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, "ti,timer-alwon", + 2, OMAP4_MPU_SOURCE) OMAP_SYS_TIMER(3_am33xx)#endif
@@ -508,7 +580,7 @@ static DEFINE_TWD_LOCAL_TIMER(twd_local_timer,static void __init omap4_timer_init (void ) { -omap2_gp_clockevent_init (1 ,OMAP4_CLKEV_SOURCE ); +omap2_gp_clockevent_init (1 ,OMAP4_CLKEV_SOURCE ,"ti,timer-alwon" );omap2_clocksource_init (2 ,OMAP4_MPU_SOURCE );#ifdef CONFIG_LOCAL_TIMERS /* Local timers are not supprted on OMAP4430 ES1.0 */
@@ -534,7 +606,7 @@ static void __init omap5_timer_init(void) {int err; -omap2_gp_clockevent_init (1 ,OMAP4_CLKEV_SOURCE ); +omap2_gp_clockevent_init (1 ,OMAP4_CLKEV_SOURCE ,"ti,timer-alwon" );omap2_clocksource_init (2 ,OMAP4_MPU_SOURCE );realtime_counter_init ();
@@ -619,6 +691,10 @@ static int __init omap2_dm_timer_init(void) {int ret; +/* If dtb is there, the devices will be created dynamically */ +if (of_have_populated_dt ()) +return -ENODEV ; + ret =omap_hwmod_for_each_by_class ("timer" , omap_timer_init,NULL );if (unlikely (ret)) {pr_err ("%s: device registration failed.\n" , __func__);
arch/arm/plat-omap/dmtimer.c +35 -6
90 lines not on this page · raw message
Signature · 1 line
1.7.9.5
v3 cover ARM: OMAP2+: Add device-tree support for timers
In reply to Jon HunterQuoted 23 lines · Jon Hunter
This series adds device-tree support for the timers on OMAP2+ devices including AM33xx.
Testing:
1. I have booted tested this series on OMAP2420 H4, OMAP3430 Beagle, OMAP4430 Panda and AM335x Beagle Bone with/without ...
a). device-tree present
b).CONFIG_OMAP_32K_TIMERset
c). kernel boot parameter "clocksource=gp_timer" present
2. I have tested the all the timers (not used by the kernel as sys-timers) on OMAP2420 H4, OMAP3430 Beagle and OMAP4430 Panda with/without device-tree with this series. The testing includes ...
a. Configuring, starting a timer and checking the counter value is
incrementing.
b. Testing timer overflow interrupt when timer expires.
c. Using different clock sources to operate the timer with.V3 changes:
- Removed definition "TIMER_PROP_ALWON" per Rob Herring's feedback
- Updated OMAP system timer (clock-events and clock-source) code so that HWMOD is NOT used for getting resource (memory and interrupt) information when device-tree is present.
Quoted 4 lines
V2 changes:
- Remove use of device-tree alias property
- Migrate OMAP timers to request timers by property instead of device ID
- Include OMAP2 support
Forgot to mention that this is based on top of v3.7-rc1.
Cheers
Jon