summaryrefslogtreecommitdiff
path: root/firmware/target/arm/tms320dm320/system-dm320.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/tms320dm320/system-dm320.c')
-rw-r--r--firmware/target/arm/tms320dm320/system-dm320.c303
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
35static unsigned short clock_arm_slow = 0xFFFF;
36static 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
38void irq_handler(void) __attribute__((interrupt ("IRQ"), naked, section(".icode"))); 41void irq_handler(void) __attribute__((interrupt ("IRQ"), section(".icode")));
39void fiq_handler(void) __attribute__((interrupt ("FIQ"), naked, section(".icode"))); 42void fiq_handler(void) __attribute__((interrupt ("FIQ"), section(".icode")));
40 43
41default_interrupt(TIMER0); 44default_interrupt(TIMER0);
42default_interrupt(TIMER1); 45default_interrupt(TIMER1);
@@ -132,21 +135,12 @@ static void UIRQ(void)
132 135
133void irq_handler(void) 136void 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
152void fiq_handler(void) 146void 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
171void system_reboot(void) 159void system_reboot(void)
@@ -199,20 +187,13 @@ void system_exception_wait(void)
199 187
200void system_init(void) 188void 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
326int system_memory_guard(int newmode) 345int 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
333void set_cpu_frequency(long frequency) 352void 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 */
355void 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