From 026032f06d162a3ca82cd8ce5ec4f8562707daca Mon Sep 17 00:00:00 2001 From: Tomasz Malesinski Date: Thu, 20 Sep 2007 22:13:48 +0000 Subject: PNX0101: new register names and polishing support for Clock Generation Unit git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14792 a1c6a512-1295-4272-9138-f99709370657 --- firmware/export/pnx0101.h | 38 +++++++++ firmware/target/arm/pnx0101/system-pnx0101.c | 111 +++++++++------------------ 2 files changed, 73 insertions(+), 76 deletions(-) diff --git a/firmware/export/pnx0101.h b/firmware/export/pnx0101.h index 766f3dd2ff..e344f0466e 100644 --- a/firmware/export/pnx0101.h +++ b/firmware/export/pnx0101.h @@ -220,6 +220,44 @@ struct pnx0101_timer { #define INTREQ_WEACTVLO 0x02000000 #define INTREQ_ENABLE 0x00010000 +/* General purpose DMA */ + +struct pnx0101_dma_channel { + unsigned long source; + unsigned long dest; + unsigned long length; + unsigned long config; + unsigned long enable; + unsigned long pad1; + unsigned long pad2; + unsigned long count; +}; + +#define DMACHANNEL ((volatile struct pnx0101_dma_channel *)0x80104800) + +struct pnx0101_dma { + unsigned long enable; + unsigned long stat; + unsigned long irqmask; + unsigned long softint; +}; + +#define DMA (*(volatile struct pnx0101_dma *)0x80104c00) + +struct pnx0101_audio { + unsigned long pad1; + unsigned long siocr; + unsigned long pad2; + unsigned long pad3; + unsigned long pad4; + unsigned long pad5; + unsigned long ddacctrl; + unsigned long ddacstat; + unsigned long ddacset; +}; + +#define AUDIO (*(volatile struct pnx0101_audio *)0x80200380) + #endif /* ASM */ #endif diff --git a/firmware/target/arm/pnx0101/system-pnx0101.c b/firmware/target/arm/pnx0101/system-pnx0101.c index 5708168b51..da94f397ca 100644 --- a/firmware/target/arm/pnx0101/system-pnx0101.c +++ b/firmware/target/arm/pnx0101/system-pnx0101.c @@ -26,13 +26,12 @@ static struct unsigned char freq; unsigned char sys_mult; unsigned char sys_div; - unsigned char mem_conf[10]; } perf_modes[3] ICONST_ATTR = { - {12, 4, 4, {2, 1, 1, 1, 1, 1, 1, 1, 1, 0}}, - {48, 4, 1, {5, 4, 1, 4, 4, 1, 3, 3, 1, 0}}, - {60, 5, 1, {6, 5, 1, 5, 5, 1, 4, 3, 1, 1}} + {12, 4, 4}, + {48, 4, 1}, + {60, 5, 1} }; static int performance_mode, bus_divider; @@ -89,11 +88,6 @@ static void cgu_connect_div_to_clock(int rel_div, int esr) CGU.clk_esr[esr] = (rel_div << 1) | 1; } -static void cgu_disconnect_div_from_clock(int esr) -{ - CGU.clk_esr[esr] = 0; -} - static void cgu_enable_clock(int clock) { CGU.clk_pcr[clock] |= 1; @@ -106,63 +100,43 @@ static void cgu_start_sel_stage_dividers(int bcr) /* Convert a pointer that points to IRAM (0x4xxxx) to a pointer that points to the uncached page (0x0xxxx) that is also mapped to IRAM. */ -static inline void *noncached(void *p) { +static inline void *noncached(void *p) +{ return (void *)(((unsigned long)p) & 0xffff); } -/* TODO: if it works, then comment it */ -static void do_set_mem_timings(int mode) ICODE_ATTR; -static void do_set_mem_timings(int mode) +/* To avoid SRAM accesses while changing memory controller settings we + run this routine from uncached copy of IRAM. All times are in CPU + cycles. At CPU frequencies lower than 60 MHz we could use faster + settings, but since DMA may access SRAM at any time, changing + memory timings together with CPU frequency would be tricky. */ +static void do_set_mem_timings(void) ICODE_ATTR; +static void do_set_mem_timings(void) { - unsigned char *mem_conf = noncached(perf_modes[mode].mem_conf); int old_irq = set_irq_level(HIGHEST_IRQ_LEVEL); while ((EMC.status & 3) != 0); EMC.control = 5; - EMCSTATIC0.waitrd = mem_conf[0]; - EMCSTATIC0.waitwr = mem_conf[1]; - EMCSTATIC1.waitrd = mem_conf[3]; - EMCSTATIC1.waitwr = mem_conf[4]; - EMCSTATIC2.waitrd = mem_conf[6]; - EMCSTATIC2.waitwr = mem_conf[7]; - EMCSTATIC0.waitoen = mem_conf[2]; - EMCSTATIC1.waitoen = mem_conf[5]; - EMCSTATIC2.waitoen = mem_conf[8]; + EMCSTATIC0.waitrd = 6; + EMCSTATIC0.waitwr = 5; + EMCSTATIC1.waitrd = 5; + EMCSTATIC1.waitwr = 4; /* OF uses 5 here */ + EMCSTATIC2.waitrd = 4; + EMCSTATIC2.waitwr = 3; + EMCSTATIC0.waitoen = 1; + EMCSTATIC1.waitoen = 1; + EMCSTATIC2.waitoen = 1; + /* Enable write buffers for SRAM. */ #ifndef DEBUG - EMCSTATIC1.config = mem_conf[9] ? 0x80081 : 0x81; + EMCSTATIC1.config = 0x80081; #endif EMC.control = 1; set_irq_level(old_irq); } -static void emc_set_mem_timings(int mode) { - void (*f)(int) = noncached(do_set_mem_timings); - (*f)(mode); -} - -/* -static void do_enable_write_buffers(int on) ICODE_ATTR; -static void do_enable_write_buffers(int on) { - int old_irq = set_irq_level(HIGHEST_IRQ_LEVEL); - while ((EMC.status & 3) != 0); - EMC.control = 5; - EMCSTATIC1.config = on ? 0x80081 : 0x81; - EMC.control = 1; - set_irq_level(old_irq); -} - -void emc_enable_write_buffers(int on) { - void (*f)(int) = noncached(do_enable_write_buffers); - (*f)(on); -} -*/ - -/* can it be replaced? */ -static void cgu_busy_wait(int n) +static void emc_set_mem_timings(void) { - while (n > 0) - { - n--; - } + void (*f)(void) = noncached(do_set_mem_timings); + (*f)(); } static void cgu_set_sys_mult(int i) @@ -193,22 +167,10 @@ static void cgu_set_sys_mult(int i) static void pnx0101_set_performance_mode(int mode) { int old = performance_mode; - if (perf_modes[old].freq < perf_modes[mode].freq) - { - emc_set_mem_timings(mode); - if (perf_modes[old].sys_mult != perf_modes[mode].sys_mult) - cgu_set_sys_mult(perf_modes[mode].sys_mult); - if (perf_modes[old].sys_div != perf_modes[mode].sys_div) - cgu_configure_div(bus_divider, 1, perf_modes[mode].sys_div); - } - else if (perf_modes[old].freq > perf_modes[mode].freq) - { - if (perf_modes[old].sys_mult != perf_modes[mode].sys_mult) - cgu_set_sys_mult(perf_modes[mode].sys_mult); - if (perf_modes[old].sys_div != perf_modes[mode].sys_div) - cgu_configure_div(bus_divider, 1, perf_modes[mode].sys_div); - emc_set_mem_timings(mode); - } + if (perf_modes[old].sys_mult != perf_modes[mode].sys_mult) + cgu_set_sys_mult(perf_modes[mode].sys_mult); + if (perf_modes[old].sys_div != perf_modes[mode].sys_div) + cgu_configure_div(bus_divider, 1, perf_modes[mode].sys_div); performance_mode = mode; } @@ -216,12 +178,9 @@ static void pnx0101_init_clocks(void) { bus_divider = PNX0101_FIRST_DIV_SYS + (CGU.clk_esr[0] >> 1); performance_mode = 0; + emc_set_mem_timings(); pnx0101_set_performance_mode(2); -/* -#ifndef DEBUG - emc_enable_write_buffers(1); -#endif -*/ + cgu_set_sel_stage_input(PNX0101_SEL_STAGE_APB1, PNX0101_MAIN_CLOCK_FAST); cgu_reset_sel_stage_clocks(PNX0101_FIRST_ESR_APB1, PNX0101_N_ESR_APB1, @@ -285,7 +244,7 @@ static void undefined_int(void) void irq(void) { - int n; + unsigned long n; IRQ_READ(INTVECTOR[0], n) (*(interrupt_vector[n >> 3]))(); } @@ -323,7 +282,7 @@ void system_init(void) IRQ_WRITE_WAIT(INTPRIOMASK[1], 0, v == 0); */ - for (i = 0; i < 0x1c; i++) + for (i = 1; i <= 0x1c; i++) { IRQ_WRITE_WAIT(INTREQ[i], INTREQ_WEPRIO | INTREQ_WETARGET | @@ -331,7 +290,7 @@ void system_init(void) (v & 0x3010f) == 1); IRQ_WRITE_WAIT(INTREQ[i], INTREQ_WEENABLE, (v & 0x10000) == 0); IRQ_WRITE_WAIT(INTREQ[i], INTREQ_WEPRIO | 1, (v & 0xf) == 1); - interrupt_vector[i + 1] = undefined_int; + interrupt_vector[i] = undefined_int; } interrupt_vector[0] = undefined_int; pnx0101_init_clocks(); -- cgit v1.2.3