diff options
-rw-r--r-- | firmware/export/tcc780x.h | 41 | ||||
-rw-r--r-- | firmware/target/arm/tcc780x/cowond2/lcd-cowond2.c | 38 | ||||
-rw-r--r-- | firmware/target/arm/tcc780x/kernel-tcc780x.c | 9 | ||||
-rw-r--r-- | firmware/target/arm/tcc780x/system-target.h | 6 | ||||
-rw-r--r-- | firmware/target/arm/tcc780x/system-tcc780x.c | 7 | ||||
-rw-r--r-- | firmware/target/arm/tcc780x/timer-target.h | 4 | ||||
-rw-r--r-- | firmware/target/arm/tcc780x/timer-tcc780x.c | 62 |
7 files changed, 103 insertions, 64 deletions
diff --git a/firmware/export/tcc780x.h b/firmware/export/tcc780x.h index b10b311fed..3ff910fce7 100644 --- a/firmware/export/tcc780x.h +++ b/firmware/export/tcc780x.h | |||
@@ -132,20 +132,37 @@ | |||
132 | 132 | ||
133 | /* Timer / Counters */ | 133 | /* Timer / Counters */ |
134 | 134 | ||
135 | #define TCFG0 (*(volatile unsigned long *)0xF3003000) | 135 | /* Note: Timers 0-3 have a 16 bit counter, 4-5 have 20 bits */ |
136 | #define TCNT0 (*(volatile unsigned long *)0xF3003004) | 136 | #define TCFG(_x_) (*(volatile unsigned int *)(0xF3003000+0x10*(_x_))) |
137 | #define TREF0 (*(volatile unsigned long *)0xF3003008) | 137 | #define TCNT(_x_) (*(volatile unsigned int *)(0xF3003004+0x10*(_x_))) |
138 | #define TCFG1 (*(volatile unsigned long *)0xF3003010) | 138 | #define TREF(_x_) (*(volatile unsigned int *)(0xF3003008+0x10*(_x_))) |
139 | #define TCNT1 (*(volatile unsigned long *)0xF3003014) | 139 | |
140 | #define TREF1 (*(volatile unsigned long *)0xF3003018) | 140 | #define TIREQ (*(volatile unsigned long *)0xF3003060) |
141 | 141 | ||
142 | #define TIREQ (*(volatile unsigned long *)0xF3003060) | 142 | /* TCFG flags */ |
143 | #define TCFG_EN (1<<0) /* enable timer */ | ||
144 | #define TCFG_CONT (1<<1) /* continue from zero once TREF is reached */ | ||
145 | #define TCFG_PWM (1<<2) /* PWM mode */ | ||
146 | #define TCFG_IEN (1<<3) /* IRQ enable */ | ||
147 | #define TCFG_SEL (1<<4) /* clock source & divider */ | ||
148 | #define TCFG_POL (1<<7) /* polarity */ | ||
149 | #define TCFG_CLEAR (1<<8) /* reset TCNT to zero */ | ||
150 | #define TCFG_STOP (1<<9) /* stop counting once TREF reached */ | ||
143 | 151 | ||
144 | /* TIREQ flags */ | 152 | /* TIREQ flags */ |
145 | #define TF0 (1<<8) /* Timer 0 reference value reached */ | 153 | #define TIREQ_TI0 (1<<0) /* Timer N IRQ flag */ |
146 | #define TF1 (1<<9) /* Timer 1 reference value reached */ | 154 | #define TIREQ_TI1 (1<<1) |
147 | #define TI0 (1<<0) /* Timer 0 IRQ flag */ | 155 | #define TIREQ_TI2 (1<<2) |
148 | #define TI1 (1<<1) /* Timer 1 IRQ flag */ | 156 | #define TIREQ_TI3 (1<<3) |
157 | #define TIREQ_TI4 (1<<4) | ||
158 | #define TIREQ_TI5 (1<<5) | ||
159 | |||
160 | #define TIREQ_TF0 (1<<8) /* Timer N reference value reached */ | ||
161 | #define TIREQ_TF1 (1<<9) | ||
162 | #define TIREQ_TF2 (1<<10) | ||
163 | #define TIREQ_TF3 (1<<11) | ||
164 | #define TIREQ_TF4 (1<<12) | ||
165 | #define TIREQ_TF5 (1<<13) | ||
149 | 166 | ||
150 | #define TC32EN (*(volatile unsigned long *)0xF3003080) | 167 | #define TC32EN (*(volatile unsigned long *)0xF3003080) |
151 | #define TC32LDV (*(volatile unsigned long *)0xF3003084) | 168 | #define TC32LDV (*(volatile unsigned long *)0xF3003084) |
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 | */ | ||
124 | static 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 | |||
140 | static void lcd_display_on(void) | 119 | static 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 @@ | |||
29 | void tick_start(unsigned int interval_in_ms) | 29 | void 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 | |||
38 | static inline void udelay(unsigned usecs) | 40 | static 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 | ||
27 | bool __timer_set(long cycles, bool set); | 27 | bool __timer_set(long cycles, bool set); |
28 | bool __timer_register(void); | 28 | bool __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 | 28 | static 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 | ||
31 | bool __timer_set(long cycles, bool start) | 30 | bool __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 | ||
38 | bool __timer_register(void) | 65 | bool __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 | ||
43 | void __timer_unregister(void) | 76 | void __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 */ |
49 | void TIMER0(void) | 87 | void 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 | } |