summaryrefslogtreecommitdiff
path: root/firmware/target/arm
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm')
-rw-r--r--firmware/target/arm/tcc780x/cowond2/lcd-cowond2.c38
-rw-r--r--firmware/target/arm/tcc780x/kernel-tcc780x.c9
-rw-r--r--firmware/target/arm/tcc780x/system-target.h6
-rw-r--r--firmware/target/arm/tcc780x/system-tcc780x.c7
-rw-r--r--firmware/target/arm/tcc780x/timer-target.h4
-rw-r--r--firmware/target/arm/tcc780x/timer-tcc780x.c62
6 files changed, 74 insertions, 52 deletions
diff --git a/firmware/target/arm/tcc780x/cowond2/lcd-cowond2.c b/firmware/target/arm/tcc780x/cowond2/lcd-cowond2.c
index 7b64493c0a..d0b7e9214e 100644
--- a/firmware/target/arm/tcc780x/cowond2/lcd-cowond2.c
+++ b/firmware/target/arm/tcc780x/cowond2/lcd-cowond2.c
@@ -116,33 +116,11 @@ static void lcd_write_reg(unsigned char reg, unsigned short val)
116 restore_irq(level); 116 restore_irq(level);
117} 117}
118 118
119
120/*
121 TEMP: Rough millisecond delay routine used by the LCD panel init sequence.
122 PCK_TCT must first have been initialised to 2Mhz by calling clock_init().
123*/
124static void sleep_ms(unsigned int ms)
125{
126 /* disable timer */
127 TCFG1 = 0;
128
129 /* set Timer1 reference value based on 125kHz tick */
130 TREF1 = ms * 125;
131
132 /* single count, zero the counter, divider = 16 [2^(3+1)], enable */
133 TCFG1 = (1<<9) | (1<<8) | (3<<4) | 1;
134
135 /* wait until Timer1 ref reached */
136 while (!(TIREQ & TF1)) {};
137}
138
139
140static void lcd_display_on(void) 119static void lcd_display_on(void)
141{ 120{
142 /* power on sequence as per the D2 firmware */ 121 /* power on sequence as per the D2 firmware */
143 GPIOA_SET = (1<<16); 122 GPIOA_SET = (1<<16);
144 123 udelay(10000);
145 sleep_ms(10);
146 124
147 lcd_write_reg(1, 0x1D); 125 lcd_write_reg(1, 0x1D);
148 lcd_write_reg(2, 0x0); 126 lcd_write_reg(2, 0x0);
@@ -164,14 +142,14 @@ static void lcd_display_on(void)
164 lcd_write_reg(23, 0x0); 142 lcd_write_reg(23, 0x0);
165 lcd_write_reg(24, 0x0); 143 lcd_write_reg(24, 0x0);
166 lcd_write_reg(25, 0x0); 144 lcd_write_reg(25, 0x0);
167 sleep_ms(10); 145 udelay(10000);
168 146
169 lcd_write_reg(9, 0x4055); 147 lcd_write_reg(9, 0x4055);
170 lcd_write_reg(10, 0x0); 148 lcd_write_reg(10, 0x0);
171 sleep_ms(40); 149 udelay(40000);
172 150
173 lcd_write_reg(10, 0x2000); 151 lcd_write_reg(10, 0x2000);
174 sleep_ms(40); 152 udelay(40000);
175 153
176 lcd_write_reg(1, 0xC01D); 154 lcd_write_reg(1, 0xC01D);
177 lcd_write_reg(2, 0x204); 155 lcd_write_reg(2, 0x204);
@@ -191,11 +169,11 @@ static void lcd_display_on(void)
191 lcd_write_reg(23, 0x406); 169 lcd_write_reg(23, 0x406);
192 lcd_write_reg(24, 0x2); 170 lcd_write_reg(24, 0x2);
193 lcd_write_reg(25, 0x0); 171 lcd_write_reg(25, 0x0);
194 sleep_ms(60); 172 udelay(60000);
195 173
196 lcd_write_reg(9, 0xA55); 174 lcd_write_reg(9, 0xA55);
197 lcd_write_reg(10, 0x111F); 175 lcd_write_reg(10, 0x111F);
198 sleep_ms(10); 176 udelay(10000);
199 177
200 /* tell that we're on now */ 178 /* tell that we're on now */
201 display_on = true; 179 display_on = true;
@@ -210,10 +188,10 @@ static void lcd_display_off(void)
210 lcd_write_reg(9, 0x55); 188 lcd_write_reg(9, 0x55);
211 lcd_write_reg(10, 0x1417); 189 lcd_write_reg(10, 0x1417);
212 lcd_write_reg(5, 0x4003); 190 lcd_write_reg(5, 0x4003);
213 sleep_ms(10); 191 udelay(10000);
214 192
215 lcd_write_reg(9, 0x0); 193 lcd_write_reg(9, 0x0);
216 sleep_ms(10); 194 udelay(10000);
217 195
218 /* kill power to LCD panel (unconfirmed) */ 196 /* kill power to LCD panel (unconfirmed) */
219 GPIOA_CLEAR = (1<<16); 197 GPIOA_CLEAR = (1<<16);
diff --git a/firmware/target/arm/tcc780x/kernel-tcc780x.c b/firmware/target/arm/tcc780x/kernel-tcc780x.c
index e5d96d288a..dee5e040e2 100644
--- a/firmware/target/arm/tcc780x/kernel-tcc780x.c
+++ b/firmware/target/arm/tcc780x/kernel-tcc780x.c
@@ -29,16 +29,13 @@
29void tick_start(unsigned int interval_in_ms) 29void tick_start(unsigned int interval_in_ms)
30{ 30{
31 /* disable Timer0 */ 31 /* disable Timer0 */
32 TCFG0 &= ~1; 32 TCFG(0) &= ~TCFG_EN;
33 33
34 /* set counter reference value based on 1Mhz tick */ 34 /* set counter reference value based on 1Mhz tick */
35 TREF0 = interval_in_ms * 1000; 35 TREF(0) = interval_in_ms * 1000;
36 36
37 /* Timer0 = reset to 0, divide=2, IRQ enable, enable (continuous) */ 37 /* Timer0 = reset to 0, divide=2, IRQ enable, enable (continuous) */
38 TCFG0 = (1<<8) | (0<<4) | (1<<3) | 1; 38 TCFG(0) = TCFG_CLEAR | (0 << TCFG_SEL) | TCFG_IEN | TCFG_EN;
39
40 /* Unmask timer IRQ */
41 IEN |= TIMER0_IRQ_MASK;
42} 39}
43 40
44/* NB: Since we are using a single timer IRQ, tick tasks are dispatched as 41/* NB: Since we are using a single timer IRQ, tick tasks are dispatched as
diff --git a/firmware/target/arm/tcc780x/system-target.h b/firmware/target/arm/tcc780x/system-target.h
index 0802bb92e0..6e2e7be980 100644
--- a/firmware/target/arm/tcc780x/system-target.h
+++ b/firmware/target/arm/tcc780x/system-target.h
@@ -35,10 +35,12 @@
35#define outw(a,b) (*(volatile unsigned short *) (b) = (a)) 35#define outw(a,b) (*(volatile unsigned short *) (b) = (a))
36 36
37/* TC32 is configured to 1MHz in clock_init() */ 37/* TC32 is configured to 1MHz in clock_init() */
38#define USEC_TIMER TC32MCNT
39
38static inline void udelay(unsigned usecs) 40static inline void udelay(unsigned usecs)
39{ 41{
40 unsigned stop = TC32MCNT + usecs; 42 unsigned stop = USEC_TIMER + usecs;
41 while (TIME_BEFORE(TC32MCNT, stop)); 43 while (TIME_BEFORE(USEC_TIMER, stop));
42} 44}
43 45
44#endif /* SYSTEM_TARGET_H */ 46#endif /* SYSTEM_TARGET_H */
diff --git a/firmware/target/arm/tcc780x/system-tcc780x.c b/firmware/target/arm/tcc780x/system-tcc780x.c
index 77ae3a4cd9..ab8a6cf218 100644
--- a/firmware/target/arm/tcc780x/system-tcc780x.c
+++ b/firmware/target/arm/tcc780x/system-tcc780x.c
@@ -229,11 +229,14 @@ static void clock_init(void)
229 "nop \n\t" 229 "nop \n\t"
230 ); 230 );
231 231
232 /* configure PCK_TCT to 2Mhz (clock source 4 (Xin) divided by 6) */ 232 /* Configure PCK_TCT to 2Mhz (Xin divided by 6) */
233 PCLK_TCT = PCK_EN | (CKSEL_XIN<<24) | 5; 233 PCLK_TCT = PCK_EN | (CKSEL_XIN<<24) | 5;
234 234
235 /* set TC32 timer to XIN divided by 12 (1MHz) */ 235 /* Set TC32 timer to be our USEC_TIMER (Xin divided by 12 = 1MHz) */
236 TC32EN = (1<<24) | 11; 236 TC32EN = (1<<24) | 11;
237
238 /* Unmask common timer IRQ (shared by tick and user timer) */
239 IEN |= TIMER0_IRQ_MASK;
237} 240}
238#endif 241#endif
239 242
diff --git a/firmware/target/arm/tcc780x/timer-target.h b/firmware/target/arm/tcc780x/timer-target.h
index 991d949447..10090ceddc 100644
--- a/firmware/target/arm/tcc780x/timer-target.h
+++ b/firmware/target/arm/tcc780x/timer-target.h
@@ -21,8 +21,8 @@
21#ifndef TIMER_TARGET_H 21#ifndef TIMER_TARGET_H
22#define TIMER_TARGET_H 22#define TIMER_TARGET_H
23 23
24/* timers are based on XIN (12Mhz) */ 24/* Timer is based on PCK_TCT (set to 2Mhz in system.c) */
25#define TIMER_FREQ (12000000) 25#define TIMER_FREQ (2000000)
26 26
27bool __timer_set(long cycles, bool set); 27bool __timer_set(long cycles, bool set);
28bool __timer_register(void); 28bool __timer_register(void);
diff --git a/firmware/target/arm/tcc780x/timer-tcc780x.c b/firmware/target/arm/tcc780x/timer-tcc780x.c
index 17956131c0..ca6613a3ff 100644
--- a/firmware/target/arm/tcc780x/timer-tcc780x.c
+++ b/firmware/target/arm/tcc780x/timer-tcc780x.c
@@ -25,40 +25,82 @@
25#include "timer.h" 25#include "timer.h"
26#include "logf.h" 26#include "logf.h"
27 27
28/* Use the TC32 counter [sourced by Xin:12Mhz] for this timer, as it's the 28static const int prescale_shifts[] = {1, 2, 3, 4, 5, 10, 12};
29 only one that allows a 32-bit counter (Timer0-5 are 16/20 bit only). */
30 29
31bool __timer_set(long cycles, bool start) 30bool __timer_set(long cycles, bool start)
32{ 31{
33 (void)cycles; 32 bool found = false;
34 (void)start; 33
35 return false; 34 int prescale_option = 0;
35 int actual_cycles = 0;
36
37 /* Use the first prescale that fits Timer4's 20-bit counter */
38 while (!found && prescale_option < 7)
39 {
40 actual_cycles = cycles >> prescale_shifts[prescale_option];
41
42 if (actual_cycles < 0x100000)
43 found = true;
44 else
45 prescale_option++;
46 }
47
48 if (!found)
49 return false;
50
51 /* Stop the timer and set new prescale & ref count */
52 TCFG(4) &= ~TCFG_EN;
53 TCFG(4) = prescale_option << TCFG_SEL;
54 TREF(4) = actual_cycles;
55
56 if (start && pfn_unregister != NULL)
57 {
58 pfn_unregister();
59 pfn_unregister = NULL;
60 }
61
62 return true;
36} 63}
37 64
38bool __timer_register(void) 65bool __timer_register(void)
39{ 66{
40 return false; 67 int oldstatus = disable_interrupt_save(IRQ_STATUS);
68
69 TCFG(4) |= TCFG_CLEAR | TCFG_IEN | TCFG_EN;
70
71 restore_interrupt(oldstatus);
72
73 return true;
41} 74}
42 75
43void __timer_unregister(void) 76void __timer_unregister(void)
44{ 77{
78 int oldstatus = disable_interrupt_save(IRQ_STATUS);
79
80 TCFG(4) &= ~TCFG_EN;
81
82 restore_interrupt(oldstatus);
45} 83}
46 84
47 85
48/* Timer interrupt processing - all timers (inc. tick) have a single IRQ */ 86/* Timer interrupt processing - all timers (inc. tick) have a single IRQ */
49void TIMER0(void) 87void TIMER0(void)
50{ 88{
51 if (TIREQ & TF0) /* Timer0 reached ref value */ 89 if (TIREQ & TIREQ_TF0) /* Timer0 reached ref value */
52 { 90 {
53 /* Run through the list of tick tasks */ 91 /* Run through the list of tick tasks */
54 call_tick_tasks(); 92 call_tick_tasks();
55 93
56 /* reset Timer 0 IRQ & ref flags */ 94 /* reset Timer 0 IRQ & ref flags */
57 TIREQ |= TI0 | TF0; 95 TIREQ = TIREQ_TI0 | TIREQ_TF0;
58 } 96 }
59 97
60 if (TC32IRQ & (1<<3)) /* end of TC32 prescale */ 98 if (TIREQ & TIREQ_TF4) /* Timer4 reached ref value */
61 { 99 {
62 /* dispatch timer */ 100 /* dispatch user timer */
101 if (pfn_timer != NULL)
102 pfn_timer();
103
104 TIREQ = TIREQ_TI4 | TIREQ_TF4;
63 } 105 }
64} 106}