summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Malesinski <tomal@rockbox.org>2007-09-20 22:13:48 +0000
committerTomasz Malesinski <tomal@rockbox.org>2007-09-20 22:13:48 +0000
commit026032f06d162a3ca82cd8ce5ec4f8562707daca (patch)
treee73f65643c40bfbb386c813d771f8fe4b6142201
parentd14d6246c09861cd7cdb9b54ff202a8e89aa3f16 (diff)
downloadrockbox-026032f06d162a3ca82cd8ce5ec4f8562707daca.tar.gz
rockbox-026032f06d162a3ca82cd8ce5ec4f8562707daca.zip
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
-rw-r--r--firmware/export/pnx0101.h38
-rw-r--r--firmware/target/arm/pnx0101/system-pnx0101.c111
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();