summaryrefslogtreecommitdiff
path: root/firmware/target/arm
diff options
context:
space:
mode:
authorCástor Muñoz <cmvidal@gmail.com>2014-11-10 02:39:16 +0100
committerMarcin Bukat <marcin.bukat@gmail.com>2014-11-16 14:18:32 +0100
commit57969698ced265492d2007d39e350b337e163ea4 (patch)
tree770911d70514598218e5b7790b5cfb4f07bd8d2c /firmware/target/arm
parent229a02a4eebb61332e8180692d4415a7d49303fd (diff)
downloadrockbox-57969698ced265492d2007d39e350b337e163ea4.tar.gz
rockbox-57969698ced265492d2007d39e350b337e163ea4.zip
iPod Classic: update timer API using 32-bit timers.
Change-Id: I49dab8ae955a339ad0a27402fa21caa411c4ecf6 Reviewed-on: http://gerrit.rockbox.org/1032 Reviewed-by: Marcin Bukat <marcin.bukat@gmail.com>
Diffstat (limited to 'firmware/target/arm')
-rw-r--r--firmware/target/arm/s5l8702/system-s5l8702.c27
-rw-r--r--firmware/target/arm/s5l8702/timer-s5l8702.c57
2 files changed, 39 insertions, 45 deletions
diff --git a/firmware/target/arm/s5l8702/system-s5l8702.c b/firmware/target/arm/s5l8702/system-s5l8702.c
index c3f20c506b..09aff3d84e 100644
--- a/firmware/target/arm/s5l8702/system-s5l8702.c
+++ b/firmware/target/arm/s5l8702/system-s5l8702.c
@@ -39,15 +39,14 @@ default_interrupt(INT_IRQ3);
39default_interrupt(INT_IRQ4); 39default_interrupt(INT_IRQ4);
40default_interrupt(INT_IRQ5); 40default_interrupt(INT_IRQ5);
41default_interrupt(INT_IRQ6); 41default_interrupt(INT_IRQ6);
42default_interrupt(INT_IRQ7); 42default_interrupt(INT_TIMERE); /* IRQ7: 32-bit timers */
43default_interrupt(INT_TIMERA);
44default_interrupt(INT_TIMERB);
45default_interrupt(INT_TIMERC);
46default_interrupt(INT_TIMERD);
47default_interrupt(INT_TIMERE);
48default_interrupt(INT_TIMERF); 43default_interrupt(INT_TIMERF);
49default_interrupt(INT_TIMERG); 44default_interrupt(INT_TIMERG);
50default_interrupt(INT_TIMERH); 45default_interrupt(INT_TIMERH);
46default_interrupt(INT_TIMERA); /* IRQ8: 16-bit timers */
47default_interrupt(INT_TIMERB);
48default_interrupt(INT_TIMERC);
49default_interrupt(INT_TIMERD);
51default_interrupt(INT_IRQ9); 50default_interrupt(INT_IRQ9);
52default_interrupt(INT_IRQ10); 51default_interrupt(INT_IRQ10);
53default_interrupt(INT_IRQ11); 52default_interrupt(INT_IRQ11);
@@ -129,9 +128,16 @@ void INT_TIMER()
129 if (TBCON & (TBCON >> 4) & 0x7000) INT_TIMERB(); 128 if (TBCON & (TBCON >> 4) & 0x7000) INT_TIMERB();
130 if (TCCON & (TCCON >> 4) & 0x7000) INT_TIMERC(); 129 if (TCCON & (TCCON >> 4) & 0x7000) INT_TIMERC();
131 if (TDCON & (TDCON >> 4) & 0x7000) INT_TIMERD(); 130 if (TDCON & (TDCON >> 4) & 0x7000) INT_TIMERD();
132 if (TFCON & (TFCON >> 4) & 0x7000) INT_TIMERF(); 131}
133 if (TGCON & (TGCON >> 4) & 0x7000) INT_TIMERG(); 132
134 if (THCON & (THCON >> 4) & 0x7000) INT_TIMERH(); 133void INT_TIMER32(void) ICODE_ATTR;
134void INT_TIMER32()
135{
136 uint32_t tstat = TSTAT;
137 /*if ((TECON >> 12) & 0x7 & (tstat >> 24)) INT_TIMERE();*/
138 if ((TFCON >> 12) & 0x7 & (tstat >> 16)) INT_TIMERF();
139 if ((TGCON >> 12) & 0x7 & (tstat >> 8)) INT_TIMERG();
140 if ((THCON >> 12) & 0x7 & tstat) INT_TIMERH();
135} 141}
136 142
137void INT_DMAC0(void) ICODE_ATTR; 143void INT_DMAC0(void) ICODE_ATTR;
@@ -164,7 +170,7 @@ void INT_DMAC1()
164 170
165static void (* const irqvector[])(void) = 171static void (* const irqvector[])(void) =
166{ 172{
167 INT_IRQ0,INT_IRQ1,INT_IRQ2,INT_IRQ3,INT_IRQ4,INT_IRQ5,INT_IRQ6,INT_IRQ7, 173 INT_IRQ0,INT_IRQ1,INT_IRQ2,INT_IRQ3,INT_IRQ4,INT_IRQ5,INT_IRQ6,INT_TIMER32,
168 INT_TIMER,INT_IRQ9,INT_IRQ10,INT_IRQ11,INT_IRQ12,INT_IRQ13,INT_IRQ14,INT_IRQ15, 174 INT_TIMER,INT_IRQ9,INT_IRQ10,INT_IRQ11,INT_IRQ12,INT_IRQ13,INT_IRQ14,INT_IRQ15,
169 INT_DMAC0,INT_DMAC1,INT_IRQ18,INT_USB_FUNC,INT_IRQ20,INT_IRQ21,INT_IRQ22,INT_WHEEL, 175 INT_DMAC0,INT_DMAC1,INT_IRQ18,INT_USB_FUNC,INT_IRQ20,INT_IRQ21,INT_IRQ22,INT_WHEEL,
170 INT_IRQ24,INT_IRQ25,INT_IRQ26,INT_IRQ27,INT_IRQ28,INT_ATA,INT_IRQ30,INT_IRQ31, 176 INT_IRQ24,INT_IRQ25,INT_IRQ26,INT_IRQ27,INT_IRQ28,INT_ATA,INT_IRQ30,INT_IRQ31,
@@ -220,6 +226,7 @@ void system_init(void)
220 VIC0INTENABLE = 1 << IRQ_WHEEL; 226 VIC0INTENABLE = 1 << IRQ_WHEEL;
221 VIC0INTENABLE = 1 << IRQ_ATA; 227 VIC0INTENABLE = 1 << IRQ_ATA;
222 VIC1INTENABLE = 1 << (IRQ_MMC - 32); 228 VIC1INTENABLE = 1 << (IRQ_MMC - 32);
229 VIC0INTENABLE = 1 << IRQ_TIMER32;
223} 230}
224 231
225void system_reboot(void) 232void system_reboot(void)
diff --git a/firmware/target/arm/s5l8702/timer-s5l8702.c b/firmware/target/arm/s5l8702/timer-s5l8702.c
index 61d4d590e4..7c69ab123a 100644
--- a/firmware/target/arm/s5l8702/timer-s5l8702.c
+++ b/firmware/target/arm/s5l8702/timer-s5l8702.c
@@ -26,13 +26,11 @@
26#include "system.h" 26#include "system.h"
27#include "timer.h" 27#include "timer.h"
28 28
29//TODO: This needs calibration once we figure out the clocking 29void INT_TIMERF(void)
30
31void INT_TIMERC(void)
32{ 30{
33 /* clear interrupt */ 31 /* clear interrupt */
34 TCCON = TCCON; 32 TSTAT = (0x07 << 16);
35 33
36 if (pfn_timer != NULL) { 34 if (pfn_timer != NULL) {
37 pfn_timer(); 35 pfn_timer();
38 } 36 }
@@ -40,12 +38,8 @@ void INT_TIMERC(void)
40 38
41bool timer_set(long cycles, bool start) 39bool timer_set(long cycles, bool start)
42{ 40{
43 static const int cs_table[] = {1, 2, 4, 6}; 41 /* stop timer */
44 int prescale, cs; 42 TFCMD = (0 << 0); /* TF_ENABLE */
45 long count;
46
47 /* stop and clear timer */
48 TCCMD = (1 << 1); /* TD_CLR */
49 43
50 /* optionally unregister any previously registered timer user */ 44 /* optionally unregister any previously registered timer user */
51 if (start) { 45 if (start) {
@@ -55,40 +49,33 @@ bool timer_set(long cycles, bool start)
55 } 49 }
56 } 50 }
57 51
58 /* scale the count down with the clock select */ 52 /* There is an odd behaviour when the 32-bit timers are launched
59 for (cs = 0; cs < 4; cs++) { 53 for the first time, the interrupt status bits are set and an
60 count = cycles >> cs_table[cs]; 54 unexpected interrupt is generated if they are enabled. A way to
61 if ((count < 65536) || (cs == 3)) { 55 workaround this is to write the data registers before clearing
62 break; 56 the counter. */
63 } 57 TFDATA0 = cycles;
64 } 58 TFCMD = (1 << 1); /* TF_CLR */
65
66 /* scale the count down with the prescaler */
67 prescale = 1;
68 while (count >= 65536) {
69 count >>= 1;
70 prescale <<= 1;
71 }
72 59
73 /* configure timer */ 60 /* configure timer */
74 TCCON = (1 << 12) | /* TD_INT0_EN */ 61 TFCON = (1 << 12) | /* TF_INT0_EN */
75 (cs << 8) | /* TS_CS */ 62 (4 << 8) | /* TF_CS, 4 = ECLK / 1 */
76 (0 << 4); /* TD_MODE_SEL, 0 = interval mode */ 63 (1 << 6) | /* use ECLK (12MHz) */
77 TCPRE = prescale - 1; 64 (0 << 4); /* TF_MODE_SEL, 0 = interval mode */
78 TCDATA0 = count; 65 TFPRE = 0; /* no prescaler */
79 TCCMD = (1 << 0); /* TD_ENABLE */ 66
80 67 TFCMD = (1 << 0); /* TF_ENABLE */
68
81 return true; 69 return true;
82} 70}
83 71
84bool timer_start(void) 72bool timer_start(void)
85{ 73{
86 TCCMD = (1 << 0); /* TD_ENABLE */ 74 TFCMD = (1 << 0); /* TF_ENABLE */
87 return true; 75 return true;
88} 76}
89 77
90void timer_stop(void) 78void timer_stop(void)
91{ 79{
92 TCCMD = (0 << 0); /* TD_ENABLE */ 80 TFCMD = (0 << 0); /* TF_ENABLE */
93} 81}
94