diff options
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/tms320dm320/system-dm320.c | 303 |
1 files changed, 126 insertions, 177 deletions
diff --git a/firmware/target/arm/tms320dm320/system-dm320.c b/firmware/target/arm/tms320dm320/system-dm320.c index 2d618a1b8b..03196f3d46 100644 --- a/firmware/target/arm/tms320dm320/system-dm320.c +++ b/firmware/target/arm/tms320dm320/system-dm320.c | |||
@@ -32,11 +32,14 @@ | |||
32 | #include "usb-mr500.h" | 32 | #include "usb-mr500.h" |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | static unsigned short clock_arm_slow = 0xFFFF; | ||
36 | static unsigned short clock_arm_fast = 0xFFFF; | ||
37 | |||
35 | #define default_interrupt(name) \ | 38 | #define default_interrupt(name) \ |
36 | extern __attribute__((weak,alias("UIRQ"))) void name (void) | 39 | extern __attribute__((weak,alias("UIRQ"))) void name (void) |
37 | 40 | ||
38 | void irq_handler(void) __attribute__((interrupt ("IRQ"), naked, section(".icode"))); | 41 | void irq_handler(void) __attribute__((interrupt ("IRQ"), section(".icode"))); |
39 | void fiq_handler(void) __attribute__((interrupt ("FIQ"), naked, section(".icode"))); | 42 | void fiq_handler(void) __attribute__((interrupt ("FIQ"), section(".icode"))); |
40 | 43 | ||
41 | default_interrupt(TIMER0); | 44 | default_interrupt(TIMER0); |
42 | default_interrupt(TIMER1); | 45 | default_interrupt(TIMER1); |
@@ -132,21 +135,12 @@ static void UIRQ(void) | |||
132 | 135 | ||
133 | void irq_handler(void) | 136 | void irq_handler(void) |
134 | { | 137 | { |
135 | /* | ||
136 | * Based on: linux/arch/arm/kernel/entry-armv.S and system-meg-fx.c | ||
137 | */ | ||
138 | |||
139 | asm volatile( "stmfd sp!, {r0-r7, ip, lr} \n" /* Store context */ | ||
140 | "sub sp, sp, #8 \n"); /* Reserve stack */ | ||
141 | unsigned short addr = IO_INTC_IRQENTRY0>>2; | 138 | unsigned short addr = IO_INTC_IRQENTRY0>>2; |
142 | if(addr != 0) | 139 | if(addr != 0) |
143 | { | 140 | { |
144 | addr--; | 141 | addr--; |
145 | irqvector[addr](); | 142 | irqvector[addr](); |
146 | } | 143 | } |
147 | asm volatile( "add sp, sp, #8 \n" /* Cleanup stack */ | ||
148 | "ldmfd sp!, {r0-r7, ip, lr} \n" /* Restore context */ | ||
149 | "subs pc, lr, #4 \n"); /* Return from IRQ */ | ||
150 | } | 144 | } |
151 | 145 | ||
152 | void fiq_handler(void) | 146 | void fiq_handler(void) |
@@ -154,18 +148,12 @@ void fiq_handler(void) | |||
154 | /* | 148 | /* |
155 | * Based on: linux/arch/arm/kernel/entry-armv.S and system-meg-fx.c | 149 | * Based on: linux/arch/arm/kernel/entry-armv.S and system-meg-fx.c |
156 | */ | 150 | */ |
157 | |||
158 | asm volatile( "stmfd sp!, {r0-r7, ip, lr} \n" /* Store context */ | ||
159 | "sub sp, sp, #8 \n"); /* Reserve stack */ | ||
160 | unsigned short addr = IO_INTC_FIQENTRY0>>2; | 151 | unsigned short addr = IO_INTC_FIQENTRY0>>2; |
161 | if(addr != 0) | 152 | if(addr != 0) |
162 | { | 153 | { |
163 | addr--; | 154 | addr--; |
164 | irqvector[addr](); | 155 | irqvector[addr](); |
165 | } | 156 | } |
166 | asm volatile( "add sp, sp, #8 \n" /* Cleanup stack */ | ||
167 | "ldmfd sp!, {r0-r7, ip, lr} \n" /* Restore context */ | ||
168 | "subs pc, lr, #4 \n"); /* Return from FIQ */ | ||
169 | } | 157 | } |
170 | 158 | ||
171 | void system_reboot(void) | 159 | void system_reboot(void) |
@@ -199,20 +187,13 @@ void system_exception_wait(void) | |||
199 | 187 | ||
200 | void system_init(void) | 188 | void system_init(void) |
201 | { | 189 | { |
190 | unsigned int vector_addr; | ||
202 | /* Pin 33 is connected to a buzzer, for an annoying sound set | 191 | /* Pin 33 is connected to a buzzer, for an annoying sound set |
203 | * PWM0C == 0x3264 | 192 | * PWM0C == 0x3264 |
204 | * PWM0H == 0x1932 | 193 | * PWM0H == 0x1932 |
205 | * Function to 1 | 194 | * Function to 1 |
206 | * Since this is not used in the FW, set it to a normal output at a zero | 195 | * Since this is not used in the FW, set it to a normal output at a zero |
207 | * level. */ | 196 | * level. */ |
208 | /* 33: output, non-inverted, no-irq, falling edge, no-chat, normal */ | ||
209 | dm320_set_io(33, false, false, false, false, false, 0x00); | ||
210 | IO_GIO_BITCLR2 = 1<<1; | ||
211 | |||
212 | /* Pin 1 is the power button. Right now it is setup without IRQ, but that | ||
213 | * may be needed for wakeup if a different shutdown method is used. */ | ||
214 | /* 1: input , non-inverted, no-irq, falling edge, no-chat, normal */ | ||
215 | dm320_set_io(1, true, false, false, false, false, 0x00); | ||
216 | 197 | ||
217 | /* taken from linux/arch/arm/mach-itdm320-20/irq.c */ | 198 | /* taken from linux/arch/arm/mach-itdm320-20/irq.c */ |
218 | 199 | ||
@@ -234,45 +215,118 @@ void system_init(void) | |||
234 | IO_INTC_FISEL0 = 0; | 215 | IO_INTC_FISEL0 = 0; |
235 | IO_INTC_FISEL1 = 0; | 216 | IO_INTC_FISEL1 = 0; |
236 | IO_INTC_FISEL2 = 0; | 217 | IO_INTC_FISEL2 = 0; |
218 | |||
219 | /* Only initially needed clocks should be turned on */ | ||
220 | IO_CLK_MOD0 = CLK_MOD0_HPIB | CLK_MOD0_DSP | CLK_MOD0_SDRAMC | | ||
221 | CLK_MOD0_EMIF | CLK_MOD0_INTC | CLK_MOD0_AIM | | ||
222 | CLK_MOD0_AHB | CLK_MOD0_BUSC | CLK_MOD0_ARM; | ||
223 | IO_CLK_MOD1 = CLK_MOD1_CPBUS; | ||
224 | IO_CLK_MOD2 = CLK_MOD2_GIO; | ||
225 | |||
226 | #if 0 | ||
227 | if (IO_BUSC_REVR == REVR_ES11) | ||
228 | { | ||
229 | /* Agressive clock setup for newer parts (ES11) - this is actually lower | ||
230 | * power also. | ||
231 | */ | ||
232 | |||
233 | /* Setup the EMIF interface timings */ | ||
234 | |||
235 | /* ATA interface: | ||
236 | * If this is the newer silicon the timings need to be slowed down some | ||
237 | * for reliable access due to the faster ARM clock. | ||
238 | */ | ||
239 | /* OE width, WE width, CS width, Cycle width */ | ||
240 | IO_EMIF_CS3CTRL1 = (8 << 12) | (8 << 8) | (14 << 4) | 15; | ||
241 | /* 14: Width (16), 12: Idles, 8: OE setup, 4: WE Setup, CS setup */ | ||
242 | IO_EMIF_CS3CTRL2 = (1<<14) | (1 << 12) | (3 << 8) | (3 << 4) | 1; | ||
243 | |||
244 | /* USB interface: | ||
245 | * The following EMIF timing values are from the OF: | ||
246 | * IO_EMIF_CS4CTRL1 = 0x66AB; | ||
247 | * IO_EMIF_CS4CTRL2 = 0x4220; | ||
248 | * | ||
249 | * More agressive numbers may be possible, but it depends on the clocking | ||
250 | * setup. | ||
251 | */ | ||
252 | IO_EMIF_CS4CTRL1 = 0x66AB; | ||
253 | IO_EMIF_CS4CTRL2 = 0x4220; | ||
254 | |||
255 | /* 27 MHz input clock: | ||
256 | * PLLA: 27 * 15 / 2 = 202.5 MHz | ||
257 | * PLLB: 27 * 9 / 2 = 121.5 MHz (off: bit 12) | ||
258 | */ | ||
259 | IO_CLK_PLLA = (14 << 4) | 1; | ||
260 | IO_CLK_PLLB = ( 1 << 12) | ( 8 << 4) | 1; | ||
261 | |||
262 | /* Set the slow and fast clock speeds used for boosting | ||
263 | * Slow Setup: | ||
264 | * ARM div = 4 ( 50.625 MHz ) | ||
265 | * AHB div = 1 ( 50.625 MHz ) | ||
266 | * Fast Setup: | ||
267 | * ARM div = 1 ( 202.5 MHz ) | ||
268 | * AHB div = 2 ( 101.25 MHz ) | ||
269 | */ | ||
270 | clock_arm_slow = (0 << 8) | 3; | ||
271 | clock_arm_fast = (1 << 8) | 0; | ||
272 | |||
273 | IO_CLK_DIV0 = clock_arm_slow; | ||
274 | |||
275 | /* SDRAM div= 2 ( 101.25 MHz ) | ||
276 | * AXL div = 1 ( 202.5 MHz ) | ||
277 | */ | ||
278 | IO_CLK_DIV1 = (0 << 8) | 1; | ||
279 | |||
280 | /* MS div = 15 ( 13.5 MHz ) | ||
281 | * DSP div = 4 ( 50.625 MHz - could be double, but this saves power) | ||
282 | */ | ||
283 | IO_CLK_DIV2 = (3 << 8) | 14; | ||
284 | |||
285 | /* MMC div = 256 ( slow ) | ||
286 | * VENC div = 32 ( 843.75 KHz ) | ||
287 | */ | ||
288 | IO_CLK_DIV3 = (31 << 8) | 255; | ||
289 | |||
290 | /* I2C div = 1 ( 48 MHz if M48XI is running ) | ||
291 | * VLNQ div = 32 | ||
292 | */ | ||
293 | IO_CLK_DIV4 = (31 << 8) | 0; | ||
294 | |||
295 | /* Feed everything from PLLA */ | ||
296 | IO_CLK_SEL0=0x007E; | ||
297 | IO_CLK_SEL1=0x1000; | ||
298 | IO_CLK_SEL2=0x0000; | ||
299 | } | ||
300 | else | ||
301 | #endif | ||
302 | { | ||
303 | /* Set the slow and fast clock speeds used for boosting | ||
304 | * Slow Setup: | ||
305 | * ARM div = 4 ( 87.5 MHz ) | ||
306 | * AHB div = 1 ( 87.5 MHz ) | ||
307 | * Fast Setup: | ||
308 | * ARM div = 2 ( 175 MHz ) | ||
309 | * AHB div = 2 ( 87.5 MHz ) | ||
310 | */ | ||
311 | clock_arm_slow = (0 << 8) | 3; | ||
312 | clock_arm_fast = (1 << 8) | 1; | ||
313 | } | ||
237 | 314 | ||
238 | /* setup the clocks */ | 315 | /* M48XI disabled, USB buffer powerdown */ |
239 | IO_CLK_DIV0=0x0003; | 316 | IO_CLK_LPCTL1 = 0x11; /* I2C wodn't work with this disabled */ |
240 | |||
241 | /* SDRAM Divide by 3 */ | ||
242 | IO_CLK_DIV1=0x0102; | ||
243 | IO_CLK_DIV2=0x021F; | ||
244 | IO_CLK_DIV3=0x1FFF; | ||
245 | IO_CLK_DIV4=0x1F00; | ||
246 | |||
247 | /* 27 MHz input clock: | ||
248 | * PLLA = 27*11/1 | ||
249 | */ | ||
250 | IO_CLK_PLLA=0x80A0; | ||
251 | IO_CLK_PLLB=0x80C0; | ||
252 | |||
253 | IO_CLK_SEL0=0x017E; | ||
254 | IO_CLK_SEL1=0x1000; | ||
255 | IO_CLK_SEL2=0x1001; | ||
256 | |||
257 | /* need to wait before bypassing */ | ||
258 | |||
259 | IO_CLK_BYP=0x0000; | ||
260 | |||
261 | /* turn off some unneeded modules */ | ||
262 | IO_CLK_MOD0 &= ~0x0018; | ||
263 | IO_CLK_MOD1 = 0x0918; | ||
264 | IO_CLK_MOD2 = ~0x7C58; | ||
265 | 317 | ||
266 | /* IRQENTRY only reflects enabled interrupts */ | 318 | /* IRQENTRY only reflects enabled interrupts */ |
267 | IO_INTC_RAW = 0; | 319 | IO_INTC_RAW = 0; |
268 | 320 | ||
269 | IO_INTC_ENTRY_TBA0 = 0; | 321 | vector_addr = (unsigned int) irqvector; |
270 | IO_INTC_ENTRY_TBA1 = 0; | 322 | IO_INTC_ENTRY_TBA0 = 0;//(short) vector_addr & ~0x000F; |
323 | IO_INTC_ENTRY_TBA1 = 0;//(short) (vector_addr >> 16); | ||
271 | 324 | ||
272 | int i; | 325 | int i; |
273 | /* Set interrupt priorities to predefined values */ | 326 | /* Set interrupt priorities to predefined values */ |
274 | for(i = 0; i < 23; i++) | 327 | for(i = 0; i < 23; i++) |
275 | DM320_REG(0x0540+i*2) = ((irqpriority[i*2+1] & 0x3F) << 8) | (irqpriority[i*2] & 0x3F); /* IO_INTC_PRIORITYx */ | 328 | DM320_REG(0x0540+i*2) = ((irqpriority[i*2+1] & 0x3F) << 8) | |
329 | (irqpriority[i*2] & 0x3F); /* IO_INTC_PRIORITYx */ | ||
276 | 330 | ||
277 | /* Turn off all timers */ | 331 | /* Turn off all timers */ |
278 | IO_TIMER0_TMMD = CONFIG_TIMER0_TMMD_STOP; | 332 | IO_TIMER0_TMMD = CONFIG_TIMER0_TMMD_STOP; |
@@ -280,47 +334,12 @@ void system_init(void) | |||
280 | IO_TIMER2_TMMD = CONFIG_TIMER2_TMMD_STOP; | 334 | IO_TIMER2_TMMD = CONFIG_TIMER2_TMMD_STOP; |
281 | IO_TIMER3_TMMD = CONFIG_TIMER3_TMMD_STOP; | 335 | IO_TIMER3_TMMD = CONFIG_TIMER3_TMMD_STOP; |
282 | 336 | ||
283 | #ifndef CREATIVE_ZVx | ||
284 | /* set GIO26 (reset pin) to output and low */ | ||
285 | IO_GIO_BITCLR1=(1<<10); | ||
286 | IO_GIO_DIR1&=~(1<<10); | ||
287 | #endif | ||
288 | |||
289 | uart_init(); | 337 | uart_init(); |
290 | spi_init(); | 338 | spi_init(); |
291 | 339 | ||
292 | #ifdef CREATIVE_ZVx | 340 | #ifdef CREATIVE_ZVx |
293 | dma_init(); | 341 | dma_init(); |
294 | #endif | 342 | #endif |
295 | |||
296 | #if !defined(LCD_NATIVE_WIDTH) && !defined(LCD_NATIVE_HEIGHT) | ||
297 | #define LCD_NATIVE_WIDTH LCD_WIDTH | ||
298 | #define LCD_NATIVE_HEIGHT LCD_HEIGHT | ||
299 | #endif | ||
300 | |||
301 | #define LCD_FUDGE LCD_NATIVE_WIDTH%32 | ||
302 | #define LCD_BUFFER_SIZE ((LCD_NATIVE_WIDTH+LCD_FUDGE)*LCD_NATIVE_HEIGHT*2) | ||
303 | #define LCD_TTB_AREA ((LCD_BUFFER_SIZE>>19)+1) | ||
304 | |||
305 | /* MMU initialization (Starts data and instruction cache) */ | ||
306 | ttb_init(); | ||
307 | /* Make sure everything is mapped on itself */ | ||
308 | map_section(0, 0, 0x1000, CACHE_NONE); | ||
309 | |||
310 | /* Enable caching for RAM */ | ||
311 | map_section(CONFIG_SDRAM_START, CONFIG_SDRAM_START, MEMORYSIZE, CACHE_ALL); | ||
312 | /* enable buffered writing for the framebuffer */ | ||
313 | map_section((int)FRAME, (int)FRAME, LCD_TTB_AREA, BUFFERED); | ||
314 | #ifdef CREATIVE_ZVx | ||
315 | /* mimic OF */ | ||
316 | map_section(0x00100000, 0x00100000, 4, CACHE_NONE); | ||
317 | map_section(0x04700000, 0x04700000, 2, BUFFERED); | ||
318 | map_section(0x40000000, 0x40000000, 16, CACHE_NONE); | ||
319 | map_section(0x50000000, 0x50000000, 16, CACHE_NONE); | ||
320 | map_section(0x60000000, 0x60000000, 16, CACHE_NONE); | ||
321 | map_section(0x80000000, 0x80000000, 1, CACHE_NONE); | ||
322 | #endif | ||
323 | enable_mmu(); | ||
324 | } | 343 | } |
325 | 344 | ||
326 | int system_memory_guard(int newmode) | 345 | int system_memory_guard(int newmode) |
@@ -332,10 +351,23 @@ int system_memory_guard(int newmode) | |||
332 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 351 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
333 | void set_cpu_frequency(long frequency) | 352 | void set_cpu_frequency(long frequency) |
334 | { | 353 | { |
335 | if (frequency == CPUFREQ_MAX) { | 354 | /* If these variables have not been changed since startup then boosting |
336 | IO_CLK_DIV0 = 0x0101; /* 175 MHz ARM */ | 355 | * should not be used. |
337 | } else { | 356 | */ |
338 | IO_CLK_DIV0 = 0x0003; /* 87.5 MHz ARM - not much savings, about 3 mA */ | 357 | if(clock_arm_slow == 0xFFFF || clock_arm_fast == 0xFFFF) |
358 | { | ||
359 | return; | ||
360 | } | ||
361 | |||
362 | if (frequency == CPUFREQ_MAX) | ||
363 | { | ||
364 | IO_CLK_DIV0 = clock_arm_fast; | ||
365 | FREQ = CPUFREQ_MAX; | ||
366 | } | ||
367 | else | ||
368 | { | ||
369 | IO_CLK_DIV0 = clock_arm_slow; | ||
370 | FREQ = CPUFREQ_NORMAL; | ||
339 | } | 371 | } |
340 | } | 372 | } |
341 | #endif | 373 | #endif |
@@ -351,87 +383,4 @@ void udelay(int usec) { | |||
351 | } | 383 | } |
352 | } | 384 | } |
353 | 385 | ||
354 | /* This function sets the specified pin up */ | ||
355 | void dm320_set_io (char pin_num, bool input, bool invert, bool irq, bool irqany, | ||
356 | bool chat, char func_num ) | ||
357 | { | ||
358 | volatile short *pio; | ||
359 | char reg_offset; /* Holds the offset to the register */ | ||
360 | char shift_val; /* Holds the shift offset to the GPIO bit(s) */ | ||
361 | short io_val; /* Used as an intermediary to prevent glitchy | ||
362 | * assignments. */ | ||
363 | |||
364 | /* Make sure this is a valid pin number */ | ||
365 | if( (unsigned) pin_num > 40 ) | ||
366 | return; | ||
367 | |||
368 | /* Clamp the function number */ | ||
369 | func_num &= 0x03; | ||
370 | |||
371 | /* Note that these are integer calculations */ | ||
372 | reg_offset = (pin_num / 16); | ||
373 | shift_val = (pin_num - (16 * reg_offset)); | ||
374 | |||
375 | /* Handle the direction */ | ||
376 | /* Calculate the pointer to the direction register */ | ||
377 | pio = &IO_GIO_DIR0 + reg_offset; | ||
378 | |||
379 | if(input) | ||
380 | *pio |= ( 1 << shift_val ); | ||
381 | else | ||
382 | *pio &= ~( 1 << shift_val ); | ||
383 | |||
384 | /* Handle the inversion */ | ||
385 | /* Calculate the pointer to the inversion register */ | ||
386 | pio = &IO_GIO_INV0 + reg_offset; | ||
387 | |||
388 | if(invert) | ||
389 | *pio |= ( 1 << shift_val ); | ||
390 | else | ||
391 | *pio &= ~( 1 << shift_val ); | ||
392 | |||
393 | /* Handle the chat */ | ||
394 | /* Calculate the pointer to the chat register */ | ||
395 | pio = &IO_GIO_CHAT0 + reg_offset; | ||
396 | |||
397 | if(chat) | ||
398 | *pio |= ( 1 << shift_val ); | ||
399 | else | ||
400 | *pio &= ~( 1 << shift_val ); | ||
401 | |||
402 | /* Handle interrupt configuration */ | ||
403 | if(pin_num < 16) | ||
404 | { | ||
405 | /* Sets whether the pin is an irq or not */ | ||
406 | if(irq) | ||
407 | IO_GIO_IRQPORT |= (1 << pin_num ); | ||
408 | else | ||
409 | IO_GIO_IRQPORT &= ~(1 << pin_num ); | ||
410 | |||
411 | /* Set whether this is a falling or any edge sensitive irq */ | ||
412 | if(irqany) | ||
413 | IO_GIO_IRQEDGE |= (1 << pin_num ); | ||
414 | else | ||
415 | IO_GIO_IRQEDGE &= ~(1 << pin_num ); | ||
416 | } | ||
417 | |||
418 | /* Handle the function number */ | ||
419 | /* Calculate the pointer to the function register */ | ||
420 | reg_offset = ( (pin_num - 9) / 8 ); | ||
421 | shift_val = ( ((pin_num - 9) - (8 * reg_offset)) * 2 ); | ||
422 | |||
423 | if( pin_num < 9 ) | ||
424 | { | ||
425 | reg_offset = 0; | ||
426 | shift_val = 0; | ||
427 | } | ||
428 | |||
429 | /* Calculate the pointer to the function register */ | ||
430 | pio = &IO_GIO_FSEL0 + reg_offset; | ||
431 | |||
432 | io_val = *pio; | ||
433 | io_val &= ~( 3 << shift_val ); /* zero previous value */ | ||
434 | io_val |= ( func_num << shift_val ); /* Store new value */ | ||
435 | *pio = io_val; | ||
436 | } | ||
437 | 386 | ||