diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/s5l8702/clocking-s5l8702.c | 121 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/clocking-s5l8702.h | 17 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/gpio-s5l8702.c | 19 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/gpio-s5l8702.h | 4 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/i2c-s5l8702.c | 28 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c | 109 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/ipod6g/pmu-target.h | 9 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/system-s5l8702.c | 121 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/system-target.h | 4 |
9 files changed, 428 insertions, 4 deletions
diff --git a/firmware/target/arm/s5l8702/clocking-s5l8702.c b/firmware/target/arm/s5l8702/clocking-s5l8702.c index 5293385453..3ef70ba1de 100644 --- a/firmware/target/arm/s5l8702/clocking-s5l8702.c +++ b/firmware/target/arm/s5l8702/clocking-s5l8702.c | |||
@@ -213,6 +213,125 @@ void set_clocking_level(int level) | |||
213 | udelay(50); /* TBC: probably not needed */ | 213 | udelay(50); /* TBC: probably not needed */ |
214 | } | 214 | } |
215 | 215 | ||
216 | #ifdef BOOTLOADER | ||
217 | int pll_config(int pll, int op_mode, int p, int m, int s, int lock_time) | ||
218 | { | ||
219 | PLLPMS(pll) = ((p & PLLPMS_PDIV_MSK) << PLLPMS_PDIV_POS) | ||
220 | | ((m & PLLPMS_MDIV_MSK) << PLLPMS_MDIV_POS) | ||
221 | | ((s & PLLPMS_SDIV_MSK) << PLLPMS_SDIV_POS); | ||
222 | |||
223 | /* lock_time are PClk ticks */ | ||
224 | PLLCNT(pll) = lock_time & PLLCNT_MSK; | ||
225 | |||
226 | if (pll < 2) | ||
227 | { | ||
228 | if (op_mode == PLLOP_MM) { | ||
229 | PLLMODE &= ~PLLMODE_PMSMOD_BIT(pll); /* MM */ | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | PLLMODE |= PLLMODE_PMSMOD_BIT(pll); | ||
234 | |||
235 | if (op_mode == PLLOP_DM) { | ||
236 | PLLMOD2 &= ~PLLMOD2_DMOSC_BIT(pll); /* DM */ | ||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | PLLMOD2 |= PLLMOD2_DMOSC_BIT(pll); | ||
241 | } | ||
242 | else | ||
243 | { | ||
244 | if (op_mode == PLLOP_MM) | ||
245 | return -1; /* PLL2 does not support MM */ | ||
246 | |||
247 | if (op_mode == PLLOP_DM) { | ||
248 | PLLMODE &= ~PLLMODE_PLL2DMOSC_BIT; /* DM */ | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | PLLMODE |= PLLMODE_PLL2DMOSC_BIT; | ||
253 | } | ||
254 | |||
255 | /* ALTOSCx */ | ||
256 | PLLMOD2 = (PLLMOD2 & ~PLLMOD2_ALTOSC_BIT(pll)) | | ||
257 | ((op_mode == PLLOP_ALT0) ? 0 : PLLMOD2_ALTOSC_BIT(pll)); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | int pll_onoff(int pll, bool onoff) | ||
263 | { | ||
264 | if (onoff) | ||
265 | { | ||
266 | PLLMODE |= PLLMODE_EN_BIT(pll); /* start PLL */ | ||
267 | while (!(PLLLOCK & PLLLOCK_LCK_BIT(pll))); /* locking... */ | ||
268 | PLLMODE |= PLLMODE_PLLOUT_BIT(pll); /* slow mode OFF */ | ||
269 | |||
270 | /* returns DMLCK status, only meaningful for Divisor Mode (DM) */ | ||
271 | return (PLLLOCK & PLLLOCK_DMLCK_BIT(pll)) ? 1 : 0; | ||
272 | } | ||
273 | else | ||
274 | { | ||
275 | PLLMODE &= ~PLLMODE_PLLOUT_BIT(pll); /* slow mode ON */ | ||
276 | udelay(50); /* TBC: needed when current F_in is 0 Hz */ | ||
277 | PLLMODE &= ~PLLMODE_EN_BIT(pll); /* stop PLL */ | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | } | ||
282 | |||
283 | /* configure and enable/disable 16-bit clockgate */ | ||
284 | void cg16_config(volatile uint16_t* cg16, | ||
285 | bool onoff, int clksel, int div1, int div2) | ||
286 | { | ||
287 | uint16_t val16 = ((clksel & CG16_SEL_MSK) << CG16_SEL_POS) | ||
288 | | (((div1 - 1) & CG16_DIV1_MSK) << CG16_DIV1_POS) | ||
289 | | (((div2 - 1) & CG16_DIV2_MSK) << CG16_DIV2_POS) | ||
290 | | (onoff ? 0 : CG16_DISABLE_BIT); | ||
291 | |||
292 | volatile uint32_t* reg32 = (uint32_t *)((int)cg16 & ~3); | ||
293 | int shift = ((int)cg16 & 2) << 3; | ||
294 | |||
295 | *reg32 = (*reg32 & (0xffff0000 >> shift)) | (val16 << shift); | ||
296 | |||
297 | /*udelay(100);*/ /* probably not needed */ | ||
298 | |||
299 | while (*cg16 != val16); | ||
300 | } | ||
301 | |||
302 | void clockgate_enable(int gate, bool enable) | ||
303 | { | ||
304 | int i = (gate >> 5) & 1; | ||
305 | uint32_t bit = 1 << (gate & 0x1f); | ||
306 | if (enable) PWRCON(i) &= ~bit; | ||
307 | else PWRCON(i) |= bit; | ||
308 | } | ||
309 | |||
310 | /* Configures EClk for USEC_TIMER. DRAM refresh also depends on EClk, | ||
311 | * this clock should be initialized by the bootloader, so USEC_TIMER | ||
312 | * is ready to use for RB. | ||
313 | */ | ||
314 | void usec_timer_init(void) | ||
315 | { | ||
316 | /* select OSC0 for CG16 SEL_OSC */ | ||
317 | PLLMODE &= ~PLLMODE_OSCSEL_BIT; | ||
318 | |||
319 | /* configure and enable ECLK */ | ||
320 | cg16_config(&CG16_RTIME, true, CG16_SEL_OSC, 1, 1); | ||
321 | |||
322 | /* unmask timer controller clock gate */ | ||
323 | clockgate_enable(CLOCKGATE_TIMER, true); | ||
324 | |||
325 | /* configure and start timer E */ | ||
326 | TECON = (4 << 8) | /* TE_CS = ECLK / 1 */ | ||
327 | (1 << 6) | /* select ECLK (12 MHz on Classic) */ | ||
328 | (0 << 4); /* TE_MODE_SEL = interval mode */ | ||
329 | TEPRE = (S5L8702_OSC0_HZ / 1000000) - 1; /* prescaler */ | ||
330 | TEDATA0 = ~0; | ||
331 | TECMD = (1 << 1) | /* TE_CLR = initialize timer */ | ||
332 | (1 << 0); /* TE_EN = enable */ | ||
333 | } | ||
334 | |||
216 | #if 0 | 335 | #if 0 |
217 | /* - This function is mainly to documment how s5l8702 ROMBOOT and iPod | 336 | /* - This function is mainly to documment how s5l8702 ROMBOOT and iPod |
218 | * Classic diagnostic OF detects primary external clock. | 337 | * Classic diagnostic OF detects primary external clock. |
@@ -228,3 +347,5 @@ unsigned soc_get_osc0(void) | |||
228 | return (PDAT3 & 0x20) ? 24000000 : 12000000; | 347 | return (PDAT3 & 0x20) ? 24000000 : 12000000; |
229 | } | 348 | } |
230 | #endif | 349 | #endif |
350 | |||
351 | #endif /* BOOTLOADER */ | ||
diff --git a/firmware/target/arm/s5l8702/clocking-s5l8702.h b/firmware/target/arm/s5l8702/clocking-s5l8702.h index e7e4fab3bd..f21c25929b 100644 --- a/firmware/target/arm/s5l8702/clocking-s5l8702.h +++ b/firmware/target/arm/s5l8702/clocking-s5l8702.h | |||
@@ -433,4 +433,21 @@ unsigned pll_get_out_freq(int pll); | |||
433 | unsigned soc_get_oscsel_freq(void); | 433 | unsigned soc_get_oscsel_freq(void); |
434 | int soc_get_hsdiv(void); | 434 | int soc_get_hsdiv(void); |
435 | 435 | ||
436 | #ifdef BOOTLOADER | ||
437 | #include <stdbool.h> | ||
438 | |||
439 | void usec_timer_init(void); | ||
440 | void clockgate_enable(int gate, bool enable); | ||
441 | |||
442 | void soc_set_system_divs(unsigned cdiv, unsigned hdiv, unsigned hprat); | ||
443 | unsigned soc_get_system_divs(unsigned *cdiv, unsigned *hdiv, unsigned *pdiv); | ||
444 | void soc_set_hsdiv(int hsdiv); | ||
445 | |||
446 | void cg16_config(volatile uint16_t* cg16, | ||
447 | bool onoff, int clksel, int div1, int div2); | ||
448 | |||
449 | int pll_config(int pll, int op_mode, int p, int m, int s, int lock_time); | ||
450 | int pll_onoff(int pll, bool onoff); | ||
451 | #endif | ||
452 | |||
436 | #endif /* __CLOCKING_S5L8702_H */ | 453 | #endif /* __CLOCKING_S5L8702_H */ |
diff --git a/firmware/target/arm/s5l8702/gpio-s5l8702.c b/firmware/target/arm/s5l8702/gpio-s5l8702.c index bd87005ad8..85033de78c 100644 --- a/firmware/target/arm/s5l8702/gpio-s5l8702.c +++ b/firmware/target/arm/s5l8702/gpio-s5l8702.c | |||
@@ -214,3 +214,22 @@ void ICODE_ATTR INT_EXT6(void) | |||
214 | gpio_handler(0); | 214 | gpio_handler(0); |
215 | } | 215 | } |
216 | #endif | 216 | #endif |
217 | |||
218 | #ifdef BOOTLOADER | ||
219 | static uint32_t gpio_data[16] = | ||
220 | { | ||
221 | 0x5322222F, 0xEEEEEE00, 0x2332EEEE, 0x3333E222, | ||
222 | 0x33333333, 0x33333333, 0x3F000E33, 0xEEEEEEEE, | ||
223 | 0xEEEEEEEE, 0xEEEEEEEE, 0xE0EEEEEE, 0xEE00EE0E, | ||
224 | 0xEEEE0EEE, 0xEEEEEEEE, 0xEE2222EE, 0xEEEE0EEE | ||
225 | }; | ||
226 | |||
227 | void gpio_preinit(void) | ||
228 | { | ||
229 | for (int i = 0; i < 16; i++) { | ||
230 | PCON(i) = gpio_data[i]; | ||
231 | PUNB(i) = 0; | ||
232 | PUNC(i) = 0; | ||
233 | } | ||
234 | } | ||
235 | #endif | ||
diff --git a/firmware/target/arm/s5l8702/gpio-s5l8702.h b/firmware/target/arm/s5l8702/gpio-s5l8702.h index 00f5ba18f3..108d8feb0d 100644 --- a/firmware/target/arm/s5l8702/gpio-s5l8702.h +++ b/firmware/target/arm/s5l8702/gpio-s5l8702.h | |||
@@ -142,4 +142,8 @@ void gpio_int_disable(int gpio_n); | |||
142 | uint32_t gpio_group_get(int group); | 142 | uint32_t gpio_group_get(int group); |
143 | void gpio_group_set(int group, uint32_t mask, uint32_t cfg); | 143 | void gpio_group_set(int group, uint32_t mask, uint32_t cfg); |
144 | 144 | ||
145 | #ifdef BOOTLOADER | ||
146 | void gpio_preinit(void); | ||
147 | #endif | ||
148 | |||
145 | #endif /* __GPIO_S5L8702_H__ */ | 149 | #endif /* __GPIO_S5L8702_H__ */ |
diff --git a/firmware/target/arm/s5l8702/i2c-s5l8702.c b/firmware/target/arm/s5l8702/i2c-s5l8702.c index 619768410a..13787d7357 100644 --- a/firmware/target/arm/s5l8702/i2c-s5l8702.c +++ b/firmware/target/arm/s5l8702/i2c-s5l8702.c | |||
@@ -179,3 +179,31 @@ int i2c_read(int bus, unsigned char slave, int address, int len, unsigned char * | |||
179 | mutex_unlock(&i2c_mtx[bus]); | 179 | mutex_unlock(&i2c_mtx[bus]); |
180 | return ret; | 180 | return ret; |
181 | } | 181 | } |
182 | |||
183 | #ifdef BOOTLOADER | ||
184 | #include "clocking-s5l8702.h" | ||
185 | |||
186 | static void wait_rdy(int bus) | ||
187 | { | ||
188 | while (IICUNK10(bus)); | ||
189 | } | ||
190 | |||
191 | void i2c_preinit(int bus) | ||
192 | { | ||
193 | clockgate_enable(I2CCLKGATE(bus), true); | ||
194 | wait_rdy(bus); | ||
195 | IICADD(bus) = 0x40; /* own slave address */ | ||
196 | wait_rdy(bus); | ||
197 | IICUNK14(bus) = 0; | ||
198 | wait_rdy(bus); | ||
199 | IICUNK18(bus) = 0; | ||
200 | wait_rdy(bus); | ||
201 | IICSTAT(bus) = 0x80; /* master Rx mode, Tx/Rx off */ | ||
202 | wait_rdy(bus); | ||
203 | IICCON(bus) = 0; | ||
204 | wait_rdy(bus); | ||
205 | IICSTAT(bus) = 0; /* slave Rx mode, Tx/Rx off */ | ||
206 | wait_rdy(bus); | ||
207 | clockgate_enable(I2CCLKGATE(bus), false); | ||
208 | } | ||
209 | #endif | ||
diff --git a/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c index 2a9236046c..9c3ec8e711 100644 --- a/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c +++ b/firmware/target/arm/s5l8702/ipod6g/pmu-ipod6g.c | |||
@@ -165,4 +165,113 @@ int pmu_wr(int address, unsigned char val) | |||
165 | { | 165 | { |
166 | return pmu_wr_multiple(address, 1, &val); | 166 | return pmu_wr_multiple(address, 1, &val); |
167 | } | 167 | } |
168 | |||
169 | void pmu_preinit(void) | ||
170 | { | ||
171 | static const char init_data[] = | ||
172 | { | ||
173 | /* reset OOC shutdown register */ | ||
174 | PCF5063X_REG_OOCSHDWN, 0x0, | ||
175 | |||
176 | /* LDO_UNK1: 3000 mV, enabled */ | ||
177 | PCF5063X_REG_LDO1OUT, 0x15, | ||
178 | PCF5063X_REG_LDO1ENA, 0x1, | ||
179 | |||
180 | /* LDO_UNK2: 3000 mV, enabled */ | ||
181 | PCF5063X_REG_LDO2OUT, 0x15, | ||
182 | PCF5063X_REG_LDO2ENA, 0x1, | ||
183 | |||
184 | /* LDO_LCD: 3000 mV, enabled */ | ||
185 | PCF5063X_REG_LDO3OUT, 0x15, | ||
186 | PCF5063X_REG_LDO3ENA, 0x1, | ||
187 | |||
188 | /* LDO_CODEC: 1800 mV, enabled */ | ||
189 | PCF5063X_REG_LDO4OUT, 0x9, | ||
190 | PCF5063X_REG_LDO4ENA, 0x1, | ||
191 | |||
192 | /* LDO_UNK5: 3000 mV, disabled */ | ||
193 | PCF5063X_REG_LDO5OUT, 0x15, | ||
194 | PCF5063X_REG_LDO5ENA, 0x0, | ||
195 | |||
196 | /* LDO_CWHEEL: 3000 mV, ON when GPIO2 High */ | ||
197 | PCF5063X_REG_LDO6OUT, 0x15, | ||
198 | PCF5063X_REG_LDO6ENA, 0x4, | ||
199 | |||
200 | /* LDO_ACCY: 3300 mV, disabled */ | ||
201 | PCF5063X_REG_HCLDOOUT, 0x18, | ||
202 | PCF5063X_REG_HCLDOENA, 0x0, | ||
203 | |||
204 | /* LDO_CWHEEL is ON in STANDBY state, | ||
205 | LDO_CWHEEL and MEMLDO are ON in UNKNOWN state (TBC) */ | ||
206 | PCF5063X_REG_STBYCTL1, 0x0, | ||
207 | PCF5063X_REG_STBYCTL2, 0x8c, | ||
208 | |||
209 | /* GPIO1,2 = input, GPIO3 = output */ | ||
210 | PCF5063X_REG_GPIOCTL, 0x3, | ||
211 | PCF5063X_REG_GPIO1CFG, 0x0, | ||
212 | PCF5063X_REG_GPIO2CFG, 0x0, | ||
213 | |||
214 | /* DOWN2 converter (SDRAM): 1800 mV, enabled, | ||
215 | startup current limit = 15mA*0x10 (TBC) */ | ||
216 | PCF5063X_REG_DOWN2OUT, 0x2f, | ||
217 | PCF5063X_REG_DOWN2ENA, 0x1, | ||
218 | PCF5063X_REG_DOWN2CTL, 0x0, | ||
219 | PCF5063X_REG_DOWN2MXC, 0x10, | ||
220 | |||
221 | /* MEMLDO: 1800 mV, enabled */ | ||
222 | PCF5063X_REG_MEMLDOOUT, 0x9, | ||
223 | PCF5063X_REG_MEMLDOENA, 0x1, | ||
224 | |||
225 | /* AUTOLDO (HDD): 3400 mV, disabled, | ||
226 | limit = 1000 mA (40mA*0x19), limit always active */ | ||
227 | PCF5063X_REG_AUTOOUT, 0x6f, | ||
228 | PCF5063X_REG_AUTOENA, 0x0, | ||
229 | PCF5063X_REG_AUTOCTL, 0x0, | ||
230 | PCF5063X_REG_AUTOMXC, 0x59, | ||
231 | |||
232 | /* Vsysok = 3100 mV */ | ||
233 | PCF5063X_REG_SVMCTL, 0x8, | ||
234 | |||
235 | /* Reserved */ | ||
236 | 0x58, 0x0, | ||
237 | |||
238 | /* Mask all PMU interrupts */ | ||
239 | PCF5063X_REG_INT1M, 0xff, | ||
240 | PCF5063X_REG_INT2M, 0xff, | ||
241 | PCF5063X_REG_INT3M, 0xff, | ||
242 | PCF5063X_REG_INT4M, 0xff, | ||
243 | PCF5063X_REG_INT5M, 0xff, | ||
244 | PCF50635_REG_INT6M, 0xff, | ||
245 | |||
246 | /* Wakeup on rising edge for EXTON1 and EXTON2, | ||
247 | wakeup on falling edge for EXTON3 and !ONKEY, | ||
248 | wakeup on RTC alarm, wakeup on adapter insert, | ||
249 | Vbat status has no effect in state machine */ | ||
250 | PCF5063X_REG_OOCWAKE, 0xdf, | ||
251 | PCF5063X_REG_OOCTIM1, 0xaa, | ||
252 | PCF5063X_REG_OOCTIM2, 0x4a, | ||
253 | PCF5063X_REG_OOCMODE, 0x5, | ||
254 | PCF5063X_REG_OOCCTL, 0x27, | ||
255 | |||
256 | /* GPO selection = LED external NFET drive signal */ | ||
257 | PCF5063X_REG_GPOCFG, 0x1, | ||
258 | /* LED converter OFF, overvoltage protection enabled, | ||
259 | OCP limit is 500 mA, led_dimstep = 16*0x6/32768 */ | ||
260 | PCF5063X_REG_LEDENA, 0x0, | ||
261 | PCF5063X_REG_LEDCTL, 0x5, | ||
262 | PCF5063X_REG_LEDDIM, 0x6, | ||
263 | |||
264 | /* end marker */ | ||
265 | 0 | ||
266 | }; | ||
267 | |||
268 | const char* ptr; | ||
269 | for (ptr = init_data; *ptr != 0; ptr += 2) | ||
270 | pmu_wr(ptr[0], ptr[1]); | ||
271 | |||
272 | /* clear PMU interrupts */ | ||
273 | unsigned char rd_buf[5]; | ||
274 | pmu_rd_multiple(PCF5063X_REG_INT1, 5, rd_buf); | ||
275 | pmu_rd(PCF50635_REG_INT6); | ||
276 | } | ||
168 | #endif /* BOOTLOADER */ | 277 | #endif /* BOOTLOADER */ |
diff --git a/firmware/target/arm/s5l8702/ipod6g/pmu-target.h b/firmware/target/arm/s5l8702/ipod6g/pmu-target.h index 3a90ad8789..e4bef6f47c 100644 --- a/firmware/target/arm/s5l8702/ipod6g/pmu-target.h +++ b/firmware/target/arm/s5l8702/ipod6g/pmu-target.h | |||
@@ -40,8 +40,8 @@ | |||
40 | #define LDO_UNK5 5 /* TBC: nano3g NAND */ | 40 | #define LDO_UNK5 5 /* TBC: nano3g NAND */ |
41 | #define LDO_CWHEEL 6 | 41 | #define LDO_CWHEEL 6 |
42 | #define LDO_ACCY 7 /* HCLDO */ | 42 | #define LDO_ACCY 7 /* HCLDO */ |
43 | 43 | /* | |
44 | /* Other LDOs: | 44 | * Other LDOs: |
45 | * AUTOLDO: Hard Disk | 45 | * AUTOLDO: Hard Disk |
46 | * DOWN1: CPU | 46 | * DOWN1: CPU |
47 | * DOWN2: SDRAM | 47 | * DOWN2: SDRAM |
@@ -50,9 +50,9 @@ | |||
50 | * EXTON inputs: | 50 | * EXTON inputs: |
51 | * EXTON1: button/holdswitch related (TBC) | 51 | * EXTON1: button/holdswitch related (TBC) |
52 | * EXTON2: USB Vbus (High when present) | 52 | * EXTON2: USB Vbus (High when present) |
53 | * EXTON3: ACCESORY (Low when present) | 53 | * EXTON3: ACCESSORY (Low when present) |
54 | * | 54 | * |
55 | * GPIO: | 55 | * PMU GPIO: |
56 | * GPIO1: input, Mikey (jack remote ctrl) interrupt (TBC) | 56 | * GPIO1: input, Mikey (jack remote ctrl) interrupt (TBC) |
57 | * GPIO2: input, hold switch (TBC) | 57 | * GPIO2: input, hold switch (TBC) |
58 | * GPIO3: output, unknown | 58 | * GPIO3: output, unknown |
@@ -82,6 +82,7 @@ unsigned char pmu_rd(int address); | |||
82 | int pmu_wr(int address, unsigned char val); | 82 | int pmu_wr(int address, unsigned char val); |
83 | int pmu_rd_multiple(int address, int count, unsigned char* buffer); | 83 | int pmu_rd_multiple(int address, int count, unsigned char* buffer); |
84 | int pmu_wr_multiple(int address, int count, unsigned char* buffer); | 84 | int pmu_wr_multiple(int address, int count, unsigned char* buffer); |
85 | void pmu_preinit(void); | ||
85 | #endif | 86 | #endif |
86 | 87 | ||
87 | #endif /* __PMU_TARGET_H__ */ | 88 | #endif /* __PMU_TARGET_H__ */ |
diff --git a/firmware/target/arm/s5l8702/system-s5l8702.c b/firmware/target/arm/s5l8702/system-s5l8702.c index fd3a464e2f..d285efde78 100644 --- a/firmware/target/arm/s5l8702/system-s5l8702.c +++ b/firmware/target/arm/s5l8702/system-s5l8702.c | |||
@@ -277,3 +277,124 @@ void memory_init(void) | |||
277 | set_page_tables(); | 277 | set_page_tables(); |
278 | enable_mmu(); | 278 | enable_mmu(); |
279 | } | 279 | } |
280 | |||
281 | #ifdef BOOTLOADER | ||
282 | #include "i2c-s5l8702.h" | ||
283 | |||
284 | static void syscon_preinit(void) | ||
285 | { | ||
286 | /* after ROM boot, CG16_SYS is using PLL0 @108 MHz | ||
287 | CClk = 108 MHz, HClk = 54 MHz, PClk = 27 MHz */ | ||
288 | |||
289 | CLKCON0 &= ~CLKCON0_SDR_DISABLE_BIT; | ||
290 | |||
291 | PLLMODE &= ~PLLMODE_OSCSEL_BIT; /* CG16_SEL_OSC = OSC0 */ | ||
292 | cg16_config(&CG16_SYS, true, CG16_SEL_OSC, 1, 1); | ||
293 | soc_set_system_divs(1, 1, 1); | ||
294 | |||
295 | /* stop all PLLs */ | ||
296 | for (int pll = 0; pll < 3; pll++) | ||
297 | pll_onoff(pll, false); | ||
298 | |||
299 | pll_config(2, PLLOP_DM, 1, 36, 1, 32400); | ||
300 | pll_onoff(2, true); | ||
301 | soc_set_system_divs(1, 2, 2 /*hprat*/); | ||
302 | cg16_config(&CG16_SYS, true, CG16_SEL_PLL2, 1, 1); | ||
303 | cg16_config(&CG16_2L, false, CG16_SEL_OSC, 1, 1); | ||
304 | cg16_config(&CG16_SVID, false, CG16_SEL_OSC, 1, 1); | ||
305 | cg16_config(&CG16_AUD0, false, CG16_SEL_OSC, 1, 1); | ||
306 | cg16_config(&CG16_AUD1, false, CG16_SEL_OSC, 1, 1); | ||
307 | cg16_config(&CG16_AUD2, false, CG16_SEL_OSC, 1, 1); | ||
308 | cg16_config(&CG16_RTIME, true, CG16_SEL_OSC, 1, 1); | ||
309 | cg16_config(&CG16_5L, false, CG16_SEL_OSC, 1, 1); | ||
310 | |||
311 | soc_set_hsdiv(1); | ||
312 | |||
313 | PWRCON_AHB = ~((1 << CLOCKGATE_SMx) | | ||
314 | (1 << CLOCKGATE_SM1)); | ||
315 | PWRCON_APB = ~((1 << (CLOCKGATE_TIMER - 32)) | | ||
316 | (1 << (CLOCKGATE_GPIO - 32))); | ||
317 | } | ||
318 | |||
319 | static void miu_preinit(bool selfrefreshing) | ||
320 | { | ||
321 | if (selfrefreshing) | ||
322 | MIUCON = 0x11; /* TBC: self-refresh -> IDLE */ | ||
323 | |||
324 | MIUCON = 0x80D; /* remap = 1 (IRAM mapped to 0x0), | ||
325 | TBC: SDRAM bank and column configuration */ | ||
326 | MIU_REG(0xF0) = 0x0; | ||
327 | |||
328 | MIUAREF = 0x6105D; /* Auto-Refresh enabled, | ||
329 | Row refresh interval = 0x5d/12MHz = 7.75 uS */ | ||
330 | MIUSDPARA = 0x1FB621; | ||
331 | |||
332 | MIU_REG(0x200) = 0x1845; | ||
333 | MIU_REG(0x204) = 0x1845; | ||
334 | MIU_REG(0x210) = 0x1800; | ||
335 | MIU_REG(0x214) = 0x1800; | ||
336 | MIU_REG(0x220) = 0x1845; | ||
337 | MIU_REG(0x224) = 0x1845; | ||
338 | MIU_REG(0x230) = 0x1885; | ||
339 | MIU_REG(0x234) = 0x1885; | ||
340 | MIU_REG(0x14) = 0x19; /* 2^19 = 0x2000000 = SDRAMSIZE (32Mb) */ | ||
341 | MIU_REG(0x18) = 0x19; /* 2^19 = 0x2000000 = SDRAMSIZE (32Mb) */ | ||
342 | MIU_REG(0x1C) = 0x790682B; | ||
343 | MIU_REG(0x314) &= ~0x10; | ||
344 | |||
345 | for (int i = 0; i < 0x24; i++) | ||
346 | MIU_REG(0x2C + i*4) &= ~(1 << 24); | ||
347 | |||
348 | MIU_REG(0x1CC) = 0x540; | ||
349 | MIU_REG(0x1D4) |= 0x80; | ||
350 | |||
351 | MIUCOM = 0x33; /* No action CMD */ | ||
352 | MIUCOM = 0x33; | ||
353 | MIUCOM = 0x233; /* Precharge all banks CMD */ | ||
354 | MIUCOM = 0x33; | ||
355 | MIUCOM = 0x33; | ||
356 | MIUCOM = 0x33; | ||
357 | MIUCOM = 0x333; /* Auto-refresh CMD */ | ||
358 | MIUCOM = 0x33; | ||
359 | MIUCOM = 0x33; | ||
360 | MIUCOM = 0x33; | ||
361 | MIUCOM = 0x333; /* Auto-refresh CMD */ | ||
362 | MIUCOM = 0x33; | ||
363 | MIUCOM = 0x33; | ||
364 | MIUCOM = 0x33; | ||
365 | |||
366 | if (!selfrefreshing) | ||
367 | { | ||
368 | MIUMRS = 0x33; /* MRS: Bust Length = 8, CAS = 3 */ | ||
369 | MIUCOM = 0x133; /* Mode Register Set CMD */ | ||
370 | MIUCOM = 0x33; | ||
371 | MIUCOM = 0x33; | ||
372 | MIUCOM = 0x33; | ||
373 | MIUMRS = 0x8040; /* EMRS: Strength = 1/4, Self refresh area = Full */ | ||
374 | MIUCOM = 0x133; /* Mode Register Set CMD */ | ||
375 | MIUCOM = 0x33; | ||
376 | MIUCOM = 0x33; | ||
377 | MIUCOM = 0x33; | ||
378 | } | ||
379 | |||
380 | MIUAREF |= 0x61000; /* Auto-refresh enabled */ | ||
381 | } | ||
382 | |||
383 | /* Preliminary HW initialization */ | ||
384 | void system_preinit(void) | ||
385 | { | ||
386 | bool gpio3out, coldboot; | ||
387 | |||
388 | syscon_preinit(); | ||
389 | gpio_preinit(); | ||
390 | i2c_preinit(0); | ||
391 | |||
392 | /* get (previously) configured output selection for GPIO3 */ | ||
393 | gpio3out = (pmu_rd(PCF5063X_REG_GPIO3CFG) & 7); | ||
394 | /* coldboot: when set, device has been in NoPower state */ | ||
395 | coldboot = (pmu_rd(PCF5063X_REG_OOCSHDWN) & PCF5063X_OOCSHDWN_COLDBOOT); | ||
396 | pmu_preinit(); | ||
397 | |||
398 | miu_preinit(!coldboot && !gpio3out); | ||
399 | } | ||
400 | #endif | ||
diff --git a/firmware/target/arm/s5l8702/system-target.h b/firmware/target/arm/s5l8702/system-target.h index 235e68e8ca..b40d563e46 100644 --- a/firmware/target/arm/s5l8702/system-target.h +++ b/firmware/target/arm/s5l8702/system-target.h | |||
@@ -47,4 +47,8 @@ static inline void udelay(unsigned usecs) | |||
47 | while (TIME_BEFORE(USEC_TIMER, stop)); | 47 | while (TIME_BEFORE(USEC_TIMER, stop)); |
48 | } | 48 | } |
49 | 49 | ||
50 | #ifdef BOOTLOADER | ||
51 | void system_preinit(void); | ||
52 | #endif | ||
53 | |||
50 | #endif /* SYSTEM_TARGET_H */ | 54 | #endif /* SYSTEM_TARGET_H */ |