summaryrefslogtreecommitdiff
path: root/firmware/target/arm/pnx0101/system-pnx0101.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/pnx0101/system-pnx0101.c')
-rw-r--r--firmware/target/arm/pnx0101/system-pnx0101.c317
1 files changed, 0 insertions, 317 deletions
diff --git a/firmware/target/arm/pnx0101/system-pnx0101.c b/firmware/target/arm/pnx0101/system-pnx0101.c
deleted file mode 100644
index 63720d11be..0000000000
--- a/firmware/target/arm/pnx0101/system-pnx0101.c
+++ /dev/null
@@ -1,317 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2007 by Tomasz Malesinski
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include <stdlib.h>
23#include "pnx0101.h"
24#include "system.h"
25
26static struct
27{
28 unsigned char freq;
29 unsigned char sys_mult;
30 unsigned char sys_div;
31}
32perf_modes[3] ICONST_ATTR =
33{
34 {12, 4, 4},
35 {48, 4, 1},
36 {60, 5, 1}
37};
38
39static int performance_mode, bus_divider;
40
41static void cgu_set_sel_stage_input(int clock, int input)
42{
43 int s = CGU.base_ssr[clock];
44 if (s & 1)
45 CGU.base_fs2[clock] = input;
46 else
47 CGU.base_fs1[clock] = input;
48 CGU.base_scr[clock] = (s & 3) ^ 3;
49}
50
51static void cgu_reset_sel_stage_clocks(int first_esr, int n_esr,
52 int first_div, int n_div)
53{
54 int i;
55 for (i = 0; i < n_esr; i++)
56 CGU.clk_esr[first_esr + i] = 0;
57 for (i = 0; i < n_div; i++)
58 CGU.base_fdc[first_div + i] = 0;
59}
60
61static void cgu_configure_div(int div, int n, int m)
62{
63 int msub, madd, div_size, max_n;
64 unsigned long cfg;
65
66 if (n == m)
67 {
68 CGU.base_fdc[div] = CGU.base_fdc[div] & ~1;
69 return;
70 }
71
72 msub = -n;
73 madd = m - n;
74 div_size = (div == PNX0101_HIPREC_FDC) ? 10 : 8;
75 max_n = 1 << div_size;
76 while ((madd << 1) < max_n && (msub << 1) >= -max_n)
77 {
78 madd <<= 1;
79 msub <<= 1;
80 }
81 cfg = (((msub << div_size) | madd) << 3) | 4;
82 CGU.base_fdc[div] = CGU.base_fdc[div] & ~1;
83 CGU.base_fdc[div] = cfg | 2;
84 CGU.base_fdc[div] = cfg;
85 CGU.base_fdc[div] = cfg | 1;
86}
87
88static void cgu_connect_div_to_clock(int rel_div, int esr)
89{
90 CGU.clk_esr[esr] = (rel_div << 1) | 1;
91}
92
93static void cgu_enable_clock(int clock)
94{
95 CGU.clk_pcr[clock] |= 1;
96}
97
98static void cgu_start_sel_stage_dividers(int bcr)
99{
100 CGU.base_bcr[bcr] = 1;
101}
102
103/* Convert a pointer that points to IRAM (0x4xxxx) to a pointer that
104 points to the uncached page (0x0xxxx) that is also mapped to IRAM. */
105static inline void *noncached(void *p)
106{
107 return (void *)(((unsigned long)p) & 0xffff);
108}
109
110/* To avoid SRAM accesses while changing memory controller settings we
111 run this routine from uncached copy of IRAM. All times are in CPU
112 cycles. At CPU frequencies lower than 60 MHz we could use faster
113 settings, but since DMA may access SRAM at any time, changing
114 memory timings together with CPU frequency would be tricky. */
115static void do_set_mem_timings(void) ICODE_ATTR;
116static void do_set_mem_timings(void)
117{
118 int old_irq = disable_irq_save();
119 while ((EMC.status & 3) != 0);
120 EMC.control = 5;
121 EMCSTATIC0.waitrd = 6;
122 EMCSTATIC0.waitwr = 5;
123 EMCSTATIC1.waitrd = 5;
124 EMCSTATIC1.waitwr = 4; /* OF uses 5 here */
125 EMCSTATIC2.waitrd = 4;
126 EMCSTATIC2.waitwr = 3;
127 EMCSTATIC0.waitoen = 1;
128 EMCSTATIC1.waitoen = 1;
129 EMCSTATIC2.waitoen = 1;
130 /* Enable write buffers for SRAM. */
131#ifndef DEBUG
132 EMCSTATIC1.config = 0x80081;
133#endif
134 EMC.control = 1;
135 restore_irq(old_irq);
136}
137
138static void emc_set_mem_timings(void)
139{
140 void (*f)(void) = noncached(do_set_mem_timings);
141 (*f)();
142}
143
144static void cgu_set_sys_mult(int i)
145{
146 cgu_set_sel_stage_input(PNX0101_SEL_STAGE_SYS, PNX0101_MAIN_CLOCK_FAST);
147 cgu_set_sel_stage_input(PNX0101_SEL_STAGE_APB3, PNX0101_MAIN_CLOCK_FAST);
148
149 PLL.lppdn = 1;
150 PLL.lpfin = 1;
151 PLL.lpmbyp = 0;
152 PLL.lpdbyp = 0;
153 PLL.lppsel = 1;
154 PLL.lpmsel = i - 1;
155 PLL.lppdn = 0;
156 while (!PLL.lplock);
157
158 cgu_configure_div(PNX0101_FIRST_DIV_SYS + 1, 1, (i == 5) ? 15 : 12);
159 cgu_connect_div_to_clock(1, 0x11);
160 cgu_enable_clock(0x11);
161 cgu_start_sel_stage_dividers(PNX0101_BCR_SYS);
162
163 cgu_set_sel_stage_input(PNX0101_SEL_STAGE_SYS,
164 PNX0101_MAIN_CLOCK_MAIN_PLL);
165 cgu_set_sel_stage_input(PNX0101_SEL_STAGE_APB3,
166 PNX0101_MAIN_CLOCK_MAIN_PLL);
167}
168
169static void pnx0101_set_performance_mode(int mode)
170{
171 int old = performance_mode;
172 if (perf_modes[old].sys_mult != perf_modes[mode].sys_mult)
173 cgu_set_sys_mult(perf_modes[mode].sys_mult);
174 if (perf_modes[old].sys_div != perf_modes[mode].sys_div)
175 cgu_configure_div(bus_divider, 1, perf_modes[mode].sys_div);
176 performance_mode = mode;
177}
178
179static void pnx0101_init_clocks(void)
180{
181 bus_divider = PNX0101_FIRST_DIV_SYS + (CGU.clk_esr[0] >> 1);
182 performance_mode = 0;
183 emc_set_mem_timings();
184 pnx0101_set_performance_mode(2);
185
186 cgu_set_sel_stage_input(PNX0101_SEL_STAGE_APB1,
187 PNX0101_MAIN_CLOCK_FAST);
188 cgu_reset_sel_stage_clocks(PNX0101_FIRST_ESR_APB1, PNX0101_N_ESR_APB1,
189 PNX0101_FIRST_DIV_APB1, PNX0101_N_DIV_APB1);
190 cgu_configure_div(PNX0101_FIRST_DIV_APB1, 1, 4);
191 cgu_connect_div_to_clock(0, PNX0101_ESR_APB1);
192 cgu_connect_div_to_clock(0, PNX0101_ESR_T0);
193 cgu_connect_div_to_clock(0, PNX0101_ESR_T1);
194 cgu_connect_div_to_clock(0, PNX0101_ESR_I2C);
195 cgu_enable_clock(PNX0101_CLOCK_APB1);
196 cgu_enable_clock(PNX0101_CLOCK_T0);
197 cgu_enable_clock(PNX0101_CLOCK_T1);
198 cgu_enable_clock(PNX0101_CLOCK_I2C);
199}
200
201#ifdef HAVE_ADJUSTABLE_CPU_FREQ
202void set_cpu_frequency(long frequency)
203{
204 switch (frequency)
205 {
206 case CPUFREQ_MAX:
207 pnx0101_set_performance_mode(2);
208 cpu_frequency = CPUFREQ_MAX;
209 break;
210 case CPUFREQ_NORMAL:
211 pnx0101_set_performance_mode(1);
212 cpu_frequency = CPUFREQ_NORMAL;
213 break;
214 case CPUFREQ_DEFAULT:
215 default:
216 pnx0101_set_performance_mode(0);
217 cpu_frequency = CPUFREQ_DEFAULT;
218 break;
219 }
220
221}
222#endif
223
224interrupt_handler_t interrupt_vector[0x1d] __attribute__ ((section(".idata")));
225
226#define IRQ_READ(reg, dest) \
227 do { unsigned long v2; \
228 do { \
229 dest = (reg); \
230 v2 = (reg); \
231 } while ((dest != v2)); \
232 } while (0);
233
234#define IRQ_WRITE_WAIT(reg, val, cond) \
235 do { unsigned long v, v2; \
236 do { \
237 (reg) = (val); \
238 v = (reg); \
239 v2 = (reg); \
240 } while ((v != v2) || !(cond)); \
241 } while (0);
242
243static void undefined_int(void)
244{
245}
246
247void irq(void)
248{
249 unsigned long n;
250 IRQ_READ(INTVECTOR[0], n)
251 (*(interrupt_vector[n >> 3]))();
252}
253
254void fiq(void)
255{
256}
257
258void irq_enable_int(int n)
259{
260 IRQ_WRITE_WAIT(INTREQ[n], INTREQ_WEENABLE | INTREQ_ENABLE, v & 0x10000);
261}
262
263void irq_disable_int(int n)
264{
265 IRQ_WRITE_WAIT(INTREQ[n], INTREQ_WEENABLE, (v & 0x10000) == 0);
266}
267
268void irq_set_int_handler(int n, interrupt_handler_t handler)
269{
270 interrupt_vector[n] = handler;
271}
272
273void system_init(void)
274{
275 int i;
276
277 /* turn off watchdog */
278 (*(volatile unsigned long *)0x80002804) = 0;
279
280 /*
281 IRQ_WRITE_WAIT(INTVECTOR[0], 0, v == 0);
282 IRQ_WRITE_WAIT(INTVECTOR[1], 0, v == 0);
283 IRQ_WRITE_WAIT(INTPRIOMASK[0], 0, v == 0);
284 IRQ_WRITE_WAIT(INTPRIOMASK[1], 0, v == 0);
285 */
286
287 for (i = 1; i <= 0x1c; i++)
288 {
289 IRQ_WRITE_WAIT(INTREQ[i],
290 INTREQ_WEPRIO | INTREQ_WETARGET |
291 INTREQ_WEENABLE | INTREQ_WEACTVLO | 1,
292 (v & 0x3010f) == 1);
293 IRQ_WRITE_WAIT(INTREQ[i], INTREQ_WEENABLE, (v & 0x10000) == 0);
294 IRQ_WRITE_WAIT(INTREQ[i], INTREQ_WEPRIO | 1, (v & 0xf) == 1);
295 interrupt_vector[i] = undefined_int;
296 }
297 interrupt_vector[0] = undefined_int;
298 pnx0101_init_clocks();
299}
300
301
302void system_reboot(void)
303{
304 (*(volatile unsigned long *)0x80002804) = 1;
305 while (1);
306}
307
308void system_exception_wait(void)
309{
310 while (1);
311}
312
313int system_memory_guard(int newmode)
314{
315 (void)newmode;
316 return 0;
317}