diff options
-rw-r--r-- | firmware/SOURCES | 1 | ||||
-rw-r--r-- | firmware/export/s5l8702.h | 108 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/clocking-s5l8702.c | 230 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/clocking-s5l8702.h | 436 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/debug-s5l8702.c | 31 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/system-s5l8702.c | 63 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/system-target.h | 2 |
7 files changed, 792 insertions, 79 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index 091b3b1da7..cd1bf492d8 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES | |||
@@ -1600,6 +1600,7 @@ target/arm/s5l8702/system-s5l8702.c | |||
1600 | target/arm/s5l8702/gpio-s5l8702.c | 1600 | target/arm/s5l8702/gpio-s5l8702.c |
1601 | target/arm/s5l8702/pl080.c | 1601 | target/arm/s5l8702/pl080.c |
1602 | target/arm/s5l8702/dma-s5l8702.c | 1602 | target/arm/s5l8702/dma-s5l8702.c |
1603 | target/arm/s5l8702/clocking-s5l8702.c | ||
1603 | target/arm/s5l8702/ipod6g/lcd-ipod6g.c | 1604 | target/arm/s5l8702/ipod6g/lcd-ipod6g.c |
1604 | target/arm/s5l8702/ipod6g/lcd-asm-ipod6g.S | 1605 | target/arm/s5l8702/ipod6g/lcd-asm-ipod6g.S |
1605 | #if 0 //TODO | 1606 | #if 0 //TODO |
diff --git a/firmware/export/s5l8702.h b/firmware/export/s5l8702.h index 1a59d47036..6ec59eaf37 100644 --- a/firmware/export/s5l8702.h +++ b/firmware/export/s5l8702.h | |||
@@ -39,6 +39,12 @@ | |||
39 | #define TTB_SIZE 0x4000 | 39 | #define TTB_SIZE 0x4000 |
40 | #define TTB_BASE_ADDR (DRAM_ORIG + DRAM_SIZE - TTB_SIZE) | 40 | #define TTB_BASE_ADDR (DRAM_ORIG + DRAM_SIZE - TTB_SIZE) |
41 | 41 | ||
42 | #define IRAM0_ORIG 0x22000000 | ||
43 | #define IRAM0_SIZE 0x20000 | ||
44 | #define IRAM1_ORIG 0x22020000 | ||
45 | #define IRAM1_SIZE 0x20000 | ||
46 | |||
47 | |||
42 | /////SYSTEM CONTROLLER///// | 48 | /////SYSTEM CONTROLLER///// |
43 | #define CLKCON0 (*((volatile uint32_t*)(0x3C500000))) | 49 | #define CLKCON0 (*((volatile uint32_t*)(0x3C500000))) |
44 | #define CLKCON1 (*((volatile uint32_t*)(0x3C500004))) | 50 | #define CLKCON1 (*((volatile uint32_t*)(0x3C500004))) |
@@ -151,6 +157,9 @@ | |||
151 | 157 | ||
152 | 158 | ||
153 | /////I2C///// | 159 | /////I2C///// |
160 | #define I2CCLKGATE(i) ((i) == 1 ? CLOCKGATE_I2C1 : \ | ||
161 | CLOCKGATE_I2C0) | ||
162 | |||
154 | #define IICCON(bus) (*((uint32_t volatile*)(0x3C600000 + 0x300000 * (bus)))) | 163 | #define IICCON(bus) (*((uint32_t volatile*)(0x3C600000 + 0x300000 * (bus)))) |
155 | #define IICSTAT(bus) (*((uint32_t volatile*)(0x3C600004 + 0x300000 * (bus)))) | 164 | #define IICSTAT(bus) (*((uint32_t volatile*)(0x3C600004 + 0x300000 * (bus)))) |
156 | #define IICADD(bus) (*((uint32_t volatile*)(0x3C600008 + 0x300000 * (bus)))) | 165 | #define IICADD(bus) (*((uint32_t volatile*)(0x3C600008 + 0x300000 * (bus)))) |
@@ -374,9 +383,9 @@ | |||
374 | #define SPIBASE(i) ((i) == 2 ? 0x3d200000 : \ | 383 | #define SPIBASE(i) ((i) == 2 ? 0x3d200000 : \ |
375 | (i) == 1 ? 0x3ce00000 : \ | 384 | (i) == 1 ? 0x3ce00000 : \ |
376 | 0x3c300000) | 385 | 0x3c300000) |
377 | #define SPICLKGATE(i) ((i) == 2 ? 0x2f : \ | 386 | #define SPICLKGATE(i) ((i) == 2 ? CLOCKGATE_SPI2 : \ |
378 | (i) == 1 ? 0x2b : \ | 387 | (i) == 1 ? CLOCKGATE_SPI1 : \ |
379 | 0x22) | 388 | CLOCKGATE_SPI0) |
380 | #define SPIDMA(i) ((i) == 2 ? 0xd : \ | 389 | #define SPIDMA(i) ((i) == 2 ? 0xd : \ |
381 | (i) == 1 ? 0xf : \ | 390 | (i) == 1 ? 0xf : \ |
382 | 0x5) | 391 | 0x5) |
@@ -658,6 +667,10 @@ | |||
658 | 667 | ||
659 | 668 | ||
660 | /////I2S///// | 669 | /////I2S///// |
670 | #define I2SCLKGATE(i) ((i) == 2 ? CLOCKGATE_I2S2 : \ | ||
671 | (i) == 1 ? CLOCKGATE_I2S1 : \ | ||
672 | CLOCKGATE_I2S0) | ||
673 | |||
661 | #define I2SCLKCON (*((volatile uint32_t*)(0x3CA00000))) | 674 | #define I2SCLKCON (*((volatile uint32_t*)(0x3CA00000))) |
662 | #define I2STXCON (*((volatile uint32_t*)(0x3CA00004))) | 675 | #define I2STXCON (*((volatile uint32_t*)(0x3CA00004))) |
663 | #define I2STXCOM (*((volatile uint32_t*)(0x3CA00008))) | 676 | #define I2STXCOM (*((volatile uint32_t*)(0x3CA00008))) |
@@ -676,38 +689,67 @@ | |||
676 | 689 | ||
677 | 690 | ||
678 | /////CLOCK GATES///// | 691 | /////CLOCK GATES///// |
679 | #define CLOCKGATE_USB_1 2 | 692 | #define CLOCKGATE_SHA 0 |
680 | #define CLOCKGATE_USB_2 35 | 693 | #define CLOCKGATE_LCD 1 |
681 | #define CLOCKGATE_DMAC0 25 | 694 | #define CLOCKGATE_USBOTG 2 |
682 | #define CLOCKGATE_DMAC1 26 | 695 | #define CLOCKGATE_SMx 3 |
683 | #define CLOCKGATE_UART 41 | 696 | #define CLOCKGATE_SM1 4 |
697 | #define CLOCKGATE_ATA 5 | ||
698 | #define CLOCKGATE_SDCI 9 | ||
699 | #define CLOCKGATE_AES 10 | ||
700 | #define CLOCKGATE_DMAC0 25 | ||
701 | #define CLOCKGATE_DMAC1 26 | ||
702 | #define CLOCKGATE_ROM 30 | ||
703 | |||
704 | #define CLOCKGATE_RTC 32 | ||
705 | #define CLOCKGATE_CWHEEL 33 | ||
706 | #define CLOCKGATE_SPI0 34 | ||
707 | #define CLOCKGATE_USBPHY 35 | ||
708 | #define CLOCKGATE_I2C0 36 | ||
709 | #define CLOCKGATE_TIMER 37 | ||
710 | #define CLOCKGATE_I2C1 38 | ||
711 | #define CLOCKGATE_I2S0 39 | ||
712 | #define CLOCKGATE_UART 41 | ||
713 | #define CLOCKGATE_I2S1 42 | ||
714 | #define CLOCKGATE_SPI1 43 | ||
715 | #define CLOCKGATE_GPIO 44 | ||
716 | #define CLOCKGATE_CHIPID 46 | ||
717 | #define CLOCKGATE_I2S2 47 | ||
718 | #define CLOCKGATE_SPI2 48 | ||
684 | 719 | ||
685 | 720 | ||
686 | /////INTERRUPTS///// | 721 | /////INTERRUPTS///// |
687 | #define IRQ_TIMER32 7 | 722 | #define IRQ_TIMER32 7 |
688 | #define IRQ_TIMER 8 | 723 | #define IRQ_TIMER 8 |
689 | #define IRQ_USB_FUNC 19 | 724 | #define IRQ_SPI(i) (9+i) /* TBC */ |
690 | #define IRQ_DMAC(d) 16 + d | 725 | #define IRQ_SPI0 9 |
691 | #define IRQ_DMAC0 16 | 726 | #define IRQ_SPI1 10 |
692 | #define IRQ_DMAC1 17 | 727 | #define IRQ_SPI2 11 |
693 | #define IRQ_WHEEL 23 | 728 | #define IRQ_LCD 14 |
694 | #define IRQ_ATA 29 | 729 | #define IRQ_DMAC(d) (16+d) |
695 | #define IRQ_MMC 44 | 730 | #define IRQ_DMAC0 16 |
696 | 731 | #define IRQ_DMAC1 17 | |
697 | #define IRQ_UART(i) (24+i) | 732 | #define IRQ_USB_FUNC 19 |
698 | #define IRQ_UART0 24 | 733 | #define IRQ_I2C 21 /* TBC */ |
699 | #define IRQ_UART1 25 | 734 | #define IRQ_WHEEL 23 |
700 | #define IRQ_UART2 26 | 735 | #define IRQ_UART(i) (24+i) |
701 | #define IRQ_UART3 27 | 736 | #define IRQ_UART0 24 |
702 | #define IRQ_UART4 28 /* obsolete/not implemented on s5l8702 ??? */ | 737 | #define IRQ_UART1 25 |
703 | 738 | #define IRQ_UART2 26 | |
704 | #define IRQ_EXT0 0 | 739 | #define IRQ_UART3 27 |
705 | #define IRQ_EXT1 1 | 740 | #define IRQ_UART4 28 /* obsolete/not implemented on s5l8702 ??? */ |
706 | #define IRQ_EXT2 2 | 741 | #define IRQ_ATA 29 |
707 | #define IRQ_EXT3 3 | 742 | #define IRQ_SBOOT 36 |
708 | #define IRQ_EXT4 31 | 743 | #define IRQ_AES 39 |
709 | #define IRQ_EXT5 32 | 744 | #define IRQ_SHA 40 |
710 | #define IRQ_EXT6 33 | 745 | #define IRQ_MMC 44 |
746 | |||
747 | #define IRQ_EXT0 0 | ||
748 | #define IRQ_EXT1 1 | ||
749 | #define IRQ_EXT2 2 | ||
750 | #define IRQ_EXT3 3 | ||
751 | #define IRQ_EXT4 31 | ||
752 | #define IRQ_EXT5 32 | ||
753 | #define IRQ_EXT6 33 | ||
711 | 754 | ||
712 | #endif | 755 | #endif |
713 | |||
diff --git a/firmware/target/arm/s5l8702/clocking-s5l8702.c b/firmware/target/arm/s5l8702/clocking-s5l8702.c new file mode 100644 index 0000000000..5293385453 --- /dev/null +++ b/firmware/target/arm/s5l8702/clocking-s5l8702.c | |||
@@ -0,0 +1,230 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: | ||
9 | * | ||
10 | * Copyright (C) 2015 by Cástor Muñoz | ||
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 | #include <stdbool.h> | ||
22 | |||
23 | #include "config.h" | ||
24 | #include "system.h" /* udelay() */ | ||
25 | #include "s5l8702.h" | ||
26 | #include "clocking-s5l8702.h" | ||
27 | |||
28 | /* returns configured frequency (PLLxFreq, when locked) */ | ||
29 | unsigned pll_get_cfg_freq(int pll) | ||
30 | { | ||
31 | unsigned pdiv, mdiv, sdiv, f_in; | ||
32 | uint32_t pllpms; | ||
33 | |||
34 | pllpms = PLLPMS(pll); | ||
35 | |||
36 | pdiv = (pllpms >> PLLPMS_PDIV_POS) & PLLPMS_PDIV_MSK; | ||
37 | if (pdiv == 0) return 0; | ||
38 | mdiv = (pllpms >> PLLPMS_MDIV_POS) & PLLPMS_MDIV_MSK; | ||
39 | sdiv = (pllpms >> PLLPMS_SDIV_POS) & PLLPMS_SDIV_MSK; | ||
40 | |||
41 | /* experimental results sugests that the HW is working this way */ | ||
42 | if (mdiv < 2) mdiv += 256; | ||
43 | |||
44 | if (GET_PMSMOD(pll) == PMSMOD_DIV) | ||
45 | { | ||
46 | f_in = (GET_DMOSC(pll)) | ||
47 | ? ((PLLMOD2 & PLLMOD2_ALTOSC_BIT(pll)) | ||
48 | ? S5L8702_ALTOSC1_HZ | ||
49 | : S5L8702_ALTOSC0_HZ) | ||
50 | : S5L8702_OSC0_HZ; | ||
51 | |||
52 | return (f_in * mdiv / pdiv) >> sdiv; /* divide */ | ||
53 | } | ||
54 | else | ||
55 | { | ||
56 | /* XXX: overflows for high f_in, safe for 32768 Hz */ | ||
57 | f_in = S5L8702_OSC1_HZ; | ||
58 | return (f_in * mdiv * pdiv) >> sdiv; /* multiply */ | ||
59 | } | ||
60 | } | ||
61 | |||
62 | /* returns PLLxClk */ | ||
63 | unsigned pll_get_out_freq(int pll) | ||
64 | { | ||
65 | uint32_t pllmode = PLLMODE; | ||
66 | |||
67 | if ((pllmode & PLLMODE_PLLOUT_BIT(pll)) == 0) | ||
68 | return S5L8702_OSC1_HZ; /* slow mode */ | ||
69 | |||
70 | if ((pllmode & PLLMODE_EN_BIT(pll)) == 0) | ||
71 | return 0; | ||
72 | |||
73 | return pll_get_cfg_freq(pll); | ||
74 | } | ||
75 | |||
76 | /* returns selected oscillator for CG16_SEL_OSC source */ | ||
77 | unsigned soc_get_oscsel_freq(void) | ||
78 | { | ||
79 | return (PLLMODE & PLLMODE_OSCSEL_BIT) ? S5L8702_OSC1_HZ | ||
80 | : S5L8702_OSC0_HZ; | ||
81 | } | ||
82 | |||
83 | /* returns output frequency */ | ||
84 | unsigned cg16_get_freq(volatile uint16_t* cg16) | ||
85 | { | ||
86 | unsigned sel, freq; | ||
87 | uint16_t val16 = *cg16; | ||
88 | |||
89 | if (val16 & CG16_DISABLE_BIT) | ||
90 | return 0; | ||
91 | |||
92 | sel = (val16 >> CG16_SEL_POS) & CG16_SEL_MSK; | ||
93 | |||
94 | if (val16 & CG16_UNKOSC_BIT) | ||
95 | freq = S5L8702_UNKOSC_HZ; | ||
96 | else if (sel == CG16_SEL_OSC) | ||
97 | freq = soc_get_oscsel_freq(); | ||
98 | else | ||
99 | freq = pll_get_out_freq(--sel); | ||
100 | |||
101 | freq /= (((val16 >> CG16_DIV1_POS) & CG16_DIV1_MSK) + 1) * | ||
102 | (((val16 >> CG16_DIV2_POS) & CG16_DIV2_MSK) + 1); | ||
103 | |||
104 | return freq; | ||
105 | } | ||
106 | |||
107 | void soc_set_system_divs(unsigned cdiv, unsigned hdiv, unsigned hprat) | ||
108 | { | ||
109 | uint32_t val = 0; | ||
110 | unsigned pdiv = hdiv * hprat; | ||
111 | |||
112 | if (cdiv > 1) | ||
113 | val |= CLKCON1_CDIV_EN_BIT | | ||
114 | ((((cdiv >> 1) - 1) & CLKCON1_CDIV_MSK) << CLKCON1_CDIV_POS); | ||
115 | if (hdiv > 1) | ||
116 | val |= CLKCON1_HDIV_EN_BIT | | ||
117 | ((((hdiv >> 1) - 1) & CLKCON1_HDIV_MSK) << CLKCON1_HDIV_POS); | ||
118 | if (pdiv > 1) | ||
119 | val |= CLKCON1_PDIV_EN_BIT | | ||
120 | ((((pdiv >> 1) - 1) & CLKCON1_PDIV_MSK) << CLKCON1_PDIV_POS); | ||
121 | |||
122 | val |= ((hprat - 1) & CLKCON1_HPRAT_MSK) << CLKCON1_HPRAT_POS; | ||
123 | |||
124 | CLKCON1 = val; | ||
125 | |||
126 | while ((CLKCON1 >> 8) != (val >> 8)); | ||
127 | } | ||
128 | |||
129 | unsigned soc_get_system_divs(unsigned *cdiv, unsigned *hdiv, unsigned *pdiv) | ||
130 | { | ||
131 | uint32_t val = CLKCON1; | ||
132 | |||
133 | if (cdiv) | ||
134 | *cdiv = !(val & CLKCON1_CDIV_EN_BIT) ? 1 : | ||
135 | (((val >> CLKCON1_CDIV_POS) & CLKCON1_CDIV_MSK) + 1) << 1; | ||
136 | if (hdiv) | ||
137 | *hdiv = !(val & CLKCON1_HDIV_EN_BIT) ? 1 : | ||
138 | (((val >> CLKCON1_HDIV_POS) & CLKCON1_HDIV_MSK) + 1) << 1; | ||
139 | if (pdiv) | ||
140 | *pdiv = !(val & CLKCON1_PDIV_EN_BIT) ? 1 : | ||
141 | (((val >> CLKCON1_PDIV_POS) & CLKCON1_PDIV_MSK) + 1) << 1; | ||
142 | |||
143 | return cg16_get_freq(&CG16_SYS); /* FClk */ | ||
144 | } | ||
145 | |||
146 | unsigned get_system_freqs(unsigned *cclk, unsigned *hclk, unsigned *pclk) | ||
147 | { | ||
148 | unsigned fclk, cdiv, hdiv, pdiv; | ||
149 | |||
150 | fclk = soc_get_system_divs(&cdiv, &hdiv, &pdiv); | ||
151 | |||
152 | if (cclk) *cclk = fclk / cdiv; | ||
153 | if (hclk) *hclk = fclk / hdiv; | ||
154 | if (pclk) *pclk = fclk / pdiv; | ||
155 | |||
156 | return fclk; | ||
157 | } | ||
158 | |||
159 | void soc_set_hsdiv(int hsdiv) | ||
160 | { | ||
161 | SM1_DIV = hsdiv - 1; | ||
162 | } | ||
163 | |||
164 | int soc_get_hsdiv(void) | ||
165 | { | ||
166 | return (SM1_DIV & 0xf) + 1; | ||
167 | } | ||
168 | |||
169 | /* each target/app could define its own clk_modes table */ | ||
170 | struct clocking_mode *clk_modes; | ||
171 | int cur_level = -1; | ||
172 | |||
173 | void clocking_init(struct clocking_mode *modes, int level) | ||
174 | { | ||
175 | /* at this point, CK16_SYS should be already configured | ||
176 | and enabled by emCORE/bootloader */ | ||
177 | |||
178 | /* initialize global clocking */ | ||
179 | clk_modes = modes; | ||
180 | cur_level = level; | ||
181 | |||
182 | /* start initial level */ | ||
183 | struct clocking_mode *m = clk_modes + cur_level; | ||
184 | soc_set_hsdiv(m->hsdiv); | ||
185 | soc_set_system_divs(m->cdiv, m->hdiv, m->hprat); | ||
186 | } | ||
187 | |||
188 | void set_clocking_level(int level) | ||
189 | { | ||
190 | struct clocking_mode *cur, *next; | ||
191 | |||
192 | int step = (level < cur_level) ? -1 : 1; | ||
193 | |||
194 | while (cur_level != level) | ||
195 | { | ||
196 | cur = clk_modes + cur_level; | ||
197 | next = cur + step; | ||
198 | |||
199 | /* step-up */ | ||
200 | if (next->hsdiv > cur->hsdiv) | ||
201 | soc_set_hsdiv(next->hsdiv); | ||
202 | |||
203 | /* step up/down */ | ||
204 | soc_set_system_divs(next->cdiv, next->hdiv, next->hprat); | ||
205 | |||
206 | /* step-down */ | ||
207 | if (next->hsdiv < cur->hsdiv) | ||
208 | soc_set_hsdiv(next->hsdiv); | ||
209 | |||
210 | cur_level += step; | ||
211 | } | ||
212 | |||
213 | udelay(50); /* TBC: probably not needed */ | ||
214 | } | ||
215 | |||
216 | #if 0 | ||
217 | /* - This function is mainly to documment how s5l8702 ROMBOOT and iPod | ||
218 | * Classic diagnostic OF detects primary external clock. | ||
219 | * - ATM it is unknown if 24 MHz are used on other targets (i.e. Nano 3G), | ||
220 | * other SoC (ROMBOOT identifies itself as s5l8900/s5l8702), a Classic | ||
221 | * prototype, or (probably) never used... | ||
222 | * - This function should be called only at boot time, GPIO3.5 is also | ||
223 | * used for ATA controller. | ||
224 | */ | ||
225 | unsigned soc_get_osc0(void) | ||
226 | { | ||
227 | GPIOCMD = 0x30500; /* configure GPIO3.5 as input */ | ||
228 | return (PDAT3 & 0x20) ? 24000000 : 12000000; | ||
229 | } | ||
230 | #endif | ||
diff --git a/firmware/target/arm/s5l8702/clocking-s5l8702.h b/firmware/target/arm/s5l8702/clocking-s5l8702.h new file mode 100644 index 0000000000..e7e4fab3bd --- /dev/null +++ b/firmware/target/arm/s5l8702/clocking-s5l8702.h | |||
@@ -0,0 +1,436 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: | ||
9 | * | ||
10 | * Copyright (C) 2015 by Cástor Muñoz | ||
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 | #ifndef __CLOCKING_S5L8702_H | ||
22 | #define __CLOCKING_S5L8702_H | ||
23 | |||
24 | /* | ||
25 | * - This is work in progress, results are mainly based on experimental | ||
26 | * tests using emCORE and/or iPod Classic OF reverse engineering. | ||
27 | * - Things marked as TBC are 'somewhat' speculations, so might be | ||
28 | * inconplete, inaccurate or erroneous. | ||
29 | * - Things not marked as TBC could be also incomplete, inaccurate or | ||
30 | * erroneous. | ||
31 | */ | ||
32 | |||
33 | /* S5L8702 _figured_ clocking: | ||
34 | * | ||
35 | * CG16_SEL | ||
36 | * CG16_UNKOSC_BIT | ||
37 | * || | ||
38 | * || | ||
39 | * UNKOSC || | ||
40 | * OSCSEL ------>|| | ||
41 | * |\ || | ||
42 | * OSC0 -+--------------->| | OSCClk || | ||
43 | * | | |--------------->|| ______ | ||
44 | * OSC1 -)+-------------->| | || | | FClk | ||
45 | * || |/ ||---->| DIV1 |----------------> | ||
46 | * || ______ || |______| | ||
47 | * || | | Pll0Freq |\ || CG16_SYS | ||
48 | * ++===>| PMS0 |--------->| | || | ||
49 | * || |______| | | PLL0Clk || ____________ | ||
50 | * || PLL0 | |-------->|| | | U2L_Clk | ||
51 | * || OSC1 | | ||---->| DIV1,UNK14 |----------> | ||
52 | * |+--------------------->| | || |____________| | ||
53 | * || |/ || CG16_2L | ||
54 | * || PLLOUT0 || | ||
55 | * || || ______ | ||
56 | * || ______ || | | SVID_Clk | ||
57 | * || | | Pll1Freq |\ ||---->| DIV1 |----------------> | ||
58 | * ++===>| PMS1 |--------->| | || |______| | ||
59 | * | |______| | | PLL1Clk || CG16_SVID (TBC) | ||
60 | * | PLL1 | |-------->|| | ||
61 | * | OSC1 | | || ___________ | ||
62 | * +--------------------->| | || | | AUDx_Clk | ||
63 | * | |/ ||---->| DIV1,DIV2 |-----------> | ||
64 | * | PLLOUT1 || |___________| | ||
65 | * | || CG16_AUDx | ||
66 | * | ______ || | ||
67 | * | | | Pll2Freq |\ || ___________ | ||
68 | * +--->| PMS2 |--------->| | || | | EClk | ||
69 | * | |______| | | PLL2Clk ||---->| DIV1,DIV2 |--+--------> | ||
70 | * | PLL2 | |-------->|| |___________| | | ||
71 | * | OSC1 | | || CG16_RTIME | MIU_Clk | ||
72 | * +--------------------->| | || +--------> | ||
73 | * |/ || ______ | ||
74 | * PLLOUT2 || | | U5L_Clk | ||
75 | * ||---->| DIV1 |----------------> | ||
76 | * || |______| | ||
77 | * || CG16_5L | ||
78 | * | ||
79 | * ______ | ||
80 | * | | CClk | ||
81 | * FClk --+--->| CDIV |------------> ARM_Clk | ||
82 | * | |______| | ||
83 | * | | ||
84 | * | ______ | ||
85 | * | | | HClk | ||
86 | * +--->| HDIV |---------> CLKCON0[31] --> SDR_Clk | ||
87 | * | |______| | | ||
88 | * | | PWRCON_AHB | ||
89 | * | +-----> [0] ----> Clk_SHA1 | ||
90 | * | [1] ----> Clk_LCD | ||
91 | * | [2] ----> Clk_USBOTG | ||
92 | * | [3] ----> Clk_SMx TBC: Static Memory | ||
93 | * | [4] ----> Clk_SM1 (ctrl) related | ||
94 | * | [5] ----> Clk_ATA | ||
95 | * | [6] ----> Clk_UNK | ||
96 | * | [7] ----> Clk_UNK | ||
97 | * | [8] ----> Clk_NAND TBC | ||
98 | * | [9] ----> Clk_SDCI | ||
99 | * | [10] ---> Clk_AES | ||
100 | * | [11] ---> Clk_UNK | ||
101 | * | [12] ---> Clk_ECC TBC | ||
102 | * | [13] ---> Clk_UNK | ||
103 | * | [14] ---> Clk_EV0 TBC: Ext. Video | ||
104 | * | [15] ---> Clk_EV1 TBC: Ext. Video | ||
105 | * | [16] ---> Clk_EV2 TBC: Ext. Video | ||
106 | * | [17] ---> Clk_UNK | ||
107 | * | [18] ---> Clk_UNK | ||
108 | * | [19] ---> Clk_UNK | ||
109 | * | [20] ---> Clk_UNK | ||
110 | * | [21] ---> Clk_UNK | ||
111 | * | [22] ---> Clk_UNK | ||
112 | * | [23] ---> Clk_UNK | ||
113 | * | [24] ---> Clk_UNK | ||
114 | * | [25] ---> Clk_DMA0 | ||
115 | * | [26] ---> Clk_DMA1 | ||
116 | * | [27] ---> Clk_UNK | ||
117 | * | [28] ---> Clk_UNK | ||
118 | * | [29] ---> Clk_UNK | ||
119 | * | [30] ---> Clk_ROM | ||
120 | * | [31] ---> Clk_UNK | ||
121 | * | | ||
122 | * | ______ | ||
123 | * | | | PClk PWRCON_APB | ||
124 | * +--->| PDIV |------------> [0] ----> Clk_RTC | ||
125 | * |______| [1] ----> Clk_CWHEEL | ||
126 | * [2] ----> Clk_SPI0 | ||
127 | * [3] ----> Clk_USBPHY | ||
128 | * [4] ----> Clk_I2C0 | ||
129 | * [5] ----> Clk_TIMER 16/32-bit timer | ||
130 | * [6] ----> Clk_I2C1 | ||
131 | * [7] ----> Clk_I2S0 | ||
132 | * [8] ----> Clk_UNK TBC: SPDIF Out | ||
133 | * [9] ----> Clk_UART | ||
134 | * [10] ---> Clk_I2S1 | ||
135 | * [11] ---> Clk_SPI1 | ||
136 | * [12] ---> Clk_GPIO | ||
137 | * [13] ---> Clk_SBOOT TBC: Secure Boot | ||
138 | * [14] ---> Clk_CHIPID | ||
139 | * [15] ---> Clk_SPI2 | ||
140 | * [16] ---> Clk_I2S2 | ||
141 | * [17] ---> Clk_UNK | ||
142 | * | ||
143 | * IRAM notes: | ||
144 | * - IRAM0 (1st. 128 Kb) and IRAM1 (2nd. 128 Kb) uses diferent clocks, | ||
145 | * maximum rd/wr speed for IRAM1 is about a half of maximum rd/wr | ||
146 | * speed for IRAM0, it is unknown but probably they are different | ||
147 | * HW memory. | ||
148 | * - masking Clk_SMx disables access to IRAM0 and IRAM1 | ||
149 | * - masking Clk_SM1 disables access to IRAM1 | ||
150 | * - IRAM1 rd/wr speed is scaled by SM1_DIV, so it could be related | ||
151 | * with Clk_SM1 (TBC) | ||
152 | */ | ||
153 | |||
154 | #include <inttypes.h> | ||
155 | #include "config.h" | ||
156 | |||
157 | #define CLOCKING_DEBUG | ||
158 | |||
159 | #if defined(IPOD_6G) | ||
160 | /* iPod Classic target */ | ||
161 | #define S5L8702_OSC0_HZ 12000000 /* external OSC */ | ||
162 | #define S5L8702_OSC1_HZ 32768 /* from PMU */ | ||
163 | |||
164 | #define S5L8702_ALTOSC0_HZ 0 /* TBC */ | ||
165 | #define S5L8702_ALTOSC1_HZ 0 /* TBC */ | ||
166 | |||
167 | /* this clock is selected when CG16_UNKOSC_BIT is set, | ||
168 | ignoring PLLMODE_CLKSEL and CG16_SEL settings */ | ||
169 | /* TBC: OSC0*2 ???, 24 MHz Xtal ???, USB ??? */ | ||
170 | #define S5L8702_UNKOSC_HZ 24000000 | ||
171 | |||
172 | #else | ||
173 | /* s5l8702 ROMBOOT */ | ||
174 | #define S5L8702_OSC0_HZ (soc_get_osc0()) /* external OSC */ | ||
175 | #define S5L8702_OSC1_HZ 32768 /* from PMU */ | ||
176 | |||
177 | #define S5L8702_ALTOSC0_HZ 1800000 | ||
178 | #define S5L8702_ALTOSC1_HZ 27000000 | ||
179 | #endif | ||
180 | |||
181 | /* TODO: join all these definitions in an unique place */ | ||
182 | #if 1 | ||
183 | #include "s5l8702.h" | ||
184 | #else | ||
185 | #define CLKCON0 (*((volatile uint32_t*)(0x3C500000))) | ||
186 | #define CLKCON1 (*((volatile uint32_t*)(0x3C500004))) | ||
187 | #define CLKCON2 (*((volatile uint32_t*)(0x3C500008))) | ||
188 | #define CLKCON3 (*((volatile uint32_t*)(0x3C50000C))) | ||
189 | #define CLKCON4 (*((volatile uint32_t*)(0x3C500010))) | ||
190 | #define CLKCON5 (*((volatile uint32_t*)(0x3C500014))) | ||
191 | #define PLL0PMS (*((volatile uint32_t*)(0x3C500020))) | ||
192 | #define PLL1PMS (*((volatile uint32_t*)(0x3C500024))) | ||
193 | #define PLL2PMS (*((volatile uint32_t*)(0x3C500028))) | ||
194 | #define PLL0LCNT (*((volatile uint32_t*)(0x3C500030))) | ||
195 | #define PLL1LCNT (*((volatile uint32_t*)(0x3C500034))) | ||
196 | #define PLL2LCNT (*((volatile uint32_t*)(0x3C500038))) | ||
197 | #define PLLLOCK (*((volatile uint32_t*)(0x3C500040))) | ||
198 | #define PLLMODE (*((volatile uint32_t*)(0x3C500044))) | ||
199 | #define PWRCON(i) (*((volatile uint32_t*)(0x3C500048 + ((i)*4)))) /*i=1,2*/ | ||
200 | #endif | ||
201 | |||
202 | /* TBC: ATM i am assuming that PWRCON_AHB/APB registers are clockgates | ||
203 | * for SoC internal controllers sitting on AHB/APB buses, this is based | ||
204 | * on other similar SoC documentation and experimental results for many | ||
205 | * (not all) s5l8702 controllers. | ||
206 | */ | ||
207 | #define PWRCON_AHB (*((uint32_t volatile*)(0x3C500048))) | ||
208 | #define PWRCON_APB (*((uint32_t volatile*)(0x3C50004c))) | ||
209 | |||
210 | #define PLLPMS(i) (*((volatile uint32_t*)(0x3C500020 + ((i) * 4)))) | ||
211 | #define PLLCNT(i) (*((volatile uint32_t*)(0x3C500030 + ((i) * 4)))) | ||
212 | #define PLLMOD2 (*((volatile uint32_t*)(0x3C500060))) | ||
213 | #define PLLCNT_MSK 0x3fffff | ||
214 | |||
215 | /* TBC: Clk_SM1 = HClk / (SM1_DIV[3:0] + 1) */ | ||
216 | #define SM1_DIV (*((volatile uint32_t*)(0x38501000))) | ||
217 | |||
218 | |||
219 | /* CG16_x: for readability and debug, these gates are defined as | ||
220 | * 16-bit registers, on HW they are really halves of 32-bit registers. | ||
221 | * Some functionallity is not available on all CG16 gates (when so, | ||
222 | * related bits are read-only and fixed to 0). | ||
223 | * | ||
224 | * CLKCONx DIV1 DIV2 UNKOSC UNK14 | ||
225 | * CG16_SYS 0L + | ||
226 | * CG16_2L 2L + +(TBC) +(TBC) | ||
227 | * CG16_SVID 2H + +(TBC) | ||
228 | * CG16_AUD0 3L + + | ||
229 | * CG16_AUD1 3H + + | ||
230 | * CG16_AUD2 4L + + | ||
231 | * CG16_RTIME 4H + + + | ||
232 | * CG16_5L 5L + | ||
233 | * | ||
234 | * Not all gates are fully tested, this information is mainly based | ||
235 | * on experimental test using emCORE: | ||
236 | * - CG16_SYS and CG16_RTIME were tested mainly using time benchs. | ||
237 | * - EClk is used as a fixed clock (not depending on CPU/AHB/APB | ||
238 | * settings) for the timer contrller. MIU_Clk is used by the MIU | ||
239 | * controller to generate the DRAM refresh signals. | ||
240 | * - AUDxClk are a source selection for I2Sx modules, so they can | ||
241 | * can be scaled and routed to the I2S GPIO ports, where they | ||
242 | * were sampled (using emCORE) to inspect how they behave. | ||
243 | * - CG16_SVID seem to be used for external video, this info is | ||
244 | * based on OF diagnostics reverse engineering. | ||
245 | * - CG16_2L an CG16_5L usage is unknown. | ||
246 | */ | ||
247 | #define CG16_SYS (*((volatile uint16_t*)(0x3C500000))) | ||
248 | #define CG16_2L (*((volatile uint16_t*)(0x3C500008))) | ||
249 | #define CG16_SVID (*((volatile uint16_t*)(0x3C50000A))) | ||
250 | #define CG16_AUD0 (*((volatile uint16_t*)(0x3C50000C))) | ||
251 | #define CG16_AUD1 (*((volatile uint16_t*)(0x3C50000E))) | ||
252 | #define CG16_AUD2 (*((volatile uint16_t*)(0x3C500010))) | ||
253 | #define CG16_RTIME (*((volatile uint16_t*)(0x3C500012))) | ||
254 | #define CG16_5L (*((volatile uint16_t*)(0x3C500014))) | ||
255 | |||
256 | /* CG16 output frequency = | ||
257 | !DISABLE_BIT * SEL_x frequency / DIV1+1 / DIV2+1 */ | ||
258 | #define CG16_DISABLE_BIT (1 << 15) /* mask clock output */ | ||
259 | #define CG16_UNK14_BIT (1 << 14) /* writable on CG16_2L */ | ||
260 | |||
261 | #define CG16_SEL_POS 12 /* source clock selection */ | ||
262 | #define CG16_SEL_MSK 0x3 | ||
263 | #define CG16_SEL_OSC 0 | ||
264 | #define CG16_SEL_PLL0 1 | ||
265 | #define CG16_SEL_PLL1 2 | ||
266 | #define CG16_SEL_PLL2 3 | ||
267 | |||
268 | #define CG16_UNKOSC_BIT (1 << 11) | ||
269 | |||
270 | #define CG16_DIV2_POS 4 /* 2nd divisor */ | ||
271 | #define CG16_DIV2_MSK 0xf | ||
272 | |||
273 | #define CG16_DIV1_POS 0 /* 1st divisor */ | ||
274 | #define CG16_DIV1_MSK 0xf | ||
275 | |||
276 | /* | ||
277 | * CLKCON0 | ||
278 | */ | ||
279 | #define CLKCON0_SDR_DISABLE_BIT (1 << 31) | ||
280 | |||
281 | /* | ||
282 | * CLKCON1 | ||
283 | */ | ||
284 | /* CPU/AHB/APB real_divisor = | ||
285 | xDIV_EN_BIT ? 2*(reg_value+1) : 1 */ | ||
286 | #define CLKCON1_CDIV_POS 24 | ||
287 | #define CLKCON1_CDIV_MSK 0x1f | ||
288 | #define CLKCON1_CDIV_EN_BIT (1 << 30) | ||
289 | |||
290 | #define CLKCON1_HDIV_POS 16 | ||
291 | #define CLKCON1_HDIV_MSK 0x1f | ||
292 | #define CLKCON1_HDIV_EN_BIT (1 << 22) | ||
293 | |||
294 | #define CLKCON1_PDIV_POS 8 | ||
295 | #define CLKCON1_PDIV_MSK 0x1f | ||
296 | #define CLKCON1_PDIV_EN_BIT (1 << 14) | ||
297 | |||
298 | /* AHB/APB ratio: must be written when HDIV and/or PDIV | ||
299 | are modified, real_ratio = reg_value + 1 */ | ||
300 | #define CLKCON1_HPRAT_POS 0 | ||
301 | #define CLKCON1_HPRAT_MSK 0x3f | ||
302 | |||
303 | /* | ||
304 | * CLKCON5 | ||
305 | */ | ||
306 | /* TBC: this bit selects a clock routed (at least) to all I2S modules | ||
307 | * (AUDAUX_Clk, see i2s-s5l8702.h), it can be selected as a source | ||
308 | * for CODEC_CLK (MCLK), on iPod Classic AUDAUX_Clk is: | ||
309 | * 0 -> 12 MHz (TBC: OSC0 ???) | ||
310 | * 1 -> 24 MHz (TBC: 2*OSC0 ???) | ||
311 | */ | ||
312 | #define CLKCON5_AUDAUXCLK_BIT (1 << 31) | ||
313 | |||
314 | /* | ||
315 | * PLLnPMS | ||
316 | */ | ||
317 | #define PLLPMS_PDIV_POS 24 /* pre-divider */ | ||
318 | #define PLLPMS_PDIV_MSK 0x3f | ||
319 | #define PLLPMS_MDIV_POS 8 /* main divider */ | ||
320 | #define PLLPMS_MDIV_MSK 0xff | ||
321 | #define PLLPMS_SDIV_POS 0 /* post-divider (2^S) */ | ||
322 | #define PLLPMS_SDIV_MSK 0x7 | ||
323 | |||
324 | /* | ||
325 | * PLLLOCK | ||
326 | */ | ||
327 | /* Start status: | ||
328 | 0 -> in progress, 1 -> locked */ | ||
329 | #define PLLLOCK_LCK_BIT(n) (1 << (n)) | ||
330 | |||
331 | /* Lock status for Divisor Mode (DM): | ||
332 | 0 -> DM unlocked, 1 -> DM locked */ | ||
333 | #define PLLLOCK_DMLCK_BIT(n) (1 << (4 + (n))) | ||
334 | |||
335 | /* | ||
336 | * PLLMODE | ||
337 | */ | ||
338 | /* Enable PLL0,1,2: | ||
339 | 0 -> turned off, 1 -> turned on */ | ||
340 | #define PLLMODE_EN_BIT(n) (1 << (n)) | ||
341 | |||
342 | /* Select PMS mode for PLL0,1: | ||
343 | 0 -> mutiply mode (MM), 1 -> divide mode (DM) */ | ||
344 | #define PLLMODE_PMSMOD_BIT(n) (1 << (4 + (n))) | ||
345 | |||
346 | /* Select DMOSC for PLL2: | ||
347 | 0 -> DMOSC_STD, 1 -> DMOSC_ALT */ | ||
348 | #define PLLMODE_PLL2DMOSC_BIT (1 << 6) | ||
349 | |||
350 | /* Select oscilator for CG16_SEL_OSC source: | ||
351 | 0 -> S5L8702_OSC0, 1 -> S5L8702_OSC1 */ | ||
352 | #define PLLMODE_OSCSEL_BIT (1 << 8) | ||
353 | |||
354 | /* Select PLLxClk (a.k.a. "slow mode" (see s3c2440-DS) for PLL0,1,2: | ||
355 | O -> S5L8702_OSC1, 1 -> PLLxFreq */ | ||
356 | #define PLLMODE_PLLOUT_BIT(n) (1 << (16 + (n))) | ||
357 | |||
358 | /* | ||
359 | * PLLMOD2 | ||
360 | */ | ||
361 | /* Selects ALTOSCx for PLL0,1,2 when DMOSC == DMOSC_ALT: | ||
362 | 0 -> S5L8702_ALTOSC0, 1 -> S5L8702_ALTOSC1 */ | ||
363 | #define PLLMOD2_ALTOSC_BIT(n) (1 << (n)) | ||
364 | |||
365 | /* Selects DMOSC for PLL0,1: | ||
366 | 0 -> DMOSC_STD, 1 -> DMOSC_ALT */ | ||
367 | #define PLLMOD2_DMOSC_BIT(n) (1 << (4 + (n))) | ||
368 | |||
369 | |||
370 | /* See s3c2440-DS (figure 7.2) for similar SoC reference. | ||
371 | * | ||
372 | * There are two different PMS modes, PLLxFreq is: | ||
373 | * Divide Mode (DM): (F_in * MDIV / PDIV) / 2^SDIV | ||
374 | * Multiply Mode (MM): (F_in * MDIV * PDIV) / 2^SDIV | ||
375 | * | ||
376 | * PLL0 and PLL1 supports DM and MM, PLL2 only supports DM. | ||
377 | * | ||
378 | * MM uses S5L8702_OSC1. DM oscillator is selected using DMOSC_BIT | ||
379 | * and ALTOSC_BIT. | ||
380 | * | ||
381 | * PLLLOCK_LCK_BIT is not enabled when PLL gets locked, and being | ||
382 | * enabled doesn't meant that the PLL is locked. When using MULTIPLY | ||
383 | * mode, there is no (known) way to verify that the PLL is locked. | ||
384 | * On DIVIDE mode, PLLLOCK_DMLCK_BIT is enabled when the PLL is | ||
385 | * locked at the correct frequency. | ||
386 | * PLLLOCK_LCK_BIT is enabled only when lock_time expires, lock_time | ||
387 | * is configured in PLLCNT as ticks of PClk. The maximum needed time | ||
388 | * to get a good lock is ~300nS (TBC). | ||
389 | * | ||
390 | * TODO: F_vco notes | ||
391 | */ | ||
392 | #define PMSMOD_MUL 0 | ||
393 | #define PMSMOD_DIV 1 | ||
394 | #define GET_PMSMOD(pll) (((pll) == 2) \ | ||
395 | ? PMSMOD_DIV \ | ||
396 | : ((PLLMODE & PLLMODE_PMSMOD_BIT(pll)) ? PMSMOD_DIV \ | ||
397 | : PMSMOD_MUL)) | ||
398 | |||
399 | #define DMOSC_STD 0 | ||
400 | #define DMOSC_ALT 1 | ||
401 | #define GET_DMOSC(pll) ((((pll) == 2) \ | ||
402 | ? (PLLMODE & PLLMODE_PLL2DMOSC_BIT) \ | ||
403 | : (PLLMOD2 & PLLMOD2_DMOSC_BIT(pll))) ? DMOSC_ALT \ | ||
404 | : DMOSC_STD) | ||
405 | |||
406 | /* available PLL operation modes */ | ||
407 | #define PLLOP_MM 0 /* Multiply Mode, F_in = S5L8702_OSC1 */ | ||
408 | #define PLLOP_DM 1 /* Divisor Mode, F_in = S5L8702_OSC0 */ | ||
409 | #define PLLOP_ALT0 2 /* Divisor Mode, F_in = S5L8702_ALTOSC0 */ | ||
410 | #define PLLOP_ALT1 3 /* Divisor Mode, F_in = S5L8702_ALTOSC1 */ | ||
411 | |||
412 | |||
413 | /* These are real clock divisor values, to be encoded into registers | ||
414 | * as required. We are using fixed FClk: | ||
415 | * FClk = CG16_SYS_SEL / fdiv, fdiv >= 1 | ||
416 | * On Classic CG16_SYS_SEL = 216 MHz from PLL2, fdiv = 1. | ||
417 | */ | ||
418 | struct clocking_mode | ||
419 | { | ||
420 | uint8_t cdiv; /* CClk = FClk / cdiv, cdiv = 1,2,4,6,.. */ | ||
421 | uint8_t hdiv; /* HClk = FClk / hdiv, hdiv = 1,2,4,6,.. */ | ||
422 | uint8_t hprat; /* PClk = HClk / hprat, hprat >= 1 */ | ||
423 | uint8_t hsdiv; /* TBC: SM1_Clk = HClk / hsdiv, hsdiv >= 1 */ | ||
424 | }; | ||
425 | |||
426 | void clocking_init(struct clocking_mode *modes, int init_level); | ||
427 | void set_clocking_level(int level); | ||
428 | unsigned get_system_freqs(unsigned *cclk, unsigned *hclk, unsigned *pclk); | ||
429 | |||
430 | /* debug */ | ||
431 | unsigned pll_get_cfg_freq(int pll); | ||
432 | unsigned pll_get_out_freq(int pll); | ||
433 | unsigned soc_get_oscsel_freq(void); | ||
434 | int soc_get_hsdiv(void); | ||
435 | |||
436 | #endif /* __CLOCKING_S5L8702_H */ | ||
diff --git a/firmware/target/arm/s5l8702/debug-s5l8702.c b/firmware/target/arm/s5l8702/debug-s5l8702.c index a2c6c0b193..fe2044690d 100644 --- a/firmware/target/arm/s5l8702/debug-s5l8702.c +++ b/firmware/target/arm/s5l8702/debug-s5l8702.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #ifdef HAVE_SERIAL | 33 | #ifdef HAVE_SERIAL |
34 | #include "uc8702.h" | 34 | #include "uc8702.h" |
35 | #endif | 35 | #endif |
36 | #include "clocking-s5l8702.h" | ||
36 | 37 | ||
37 | #define DEBUG_CANCEL BUTTON_MENU | 38 | #define DEBUG_CANCEL BUTTON_MENU |
38 | 39 | ||
@@ -66,9 +67,10 @@ bool dbg_hw_info(void) | |||
66 | 67 | ||
67 | if(state == 0) | 68 | if(state == 0) |
68 | { | 69 | { |
70 | unsigned cpu_hz; | ||
71 | get_system_freqs(&cpu_hz, NULL, NULL); | ||
69 | _DEBUG_PRINTF("CPU:"); | 72 | _DEBUG_PRINTF("CPU:"); |
70 | _DEBUG_PRINTF("speed: %d MHz", ((CLKCON0 & 1) ? | 73 | _DEBUG_PRINTF("speed: %d MHz", cpu_hz / 1000000); |
71 | CPUFREQ_NORMAL : CPUFREQ_MAX) / 1000000); | ||
72 | _DEBUG_PRINTF("current_tick: %d", (unsigned int)current_tick); | 74 | _DEBUG_PRINTF("current_tick: %d", (unsigned int)current_tick); |
73 | uint32_t __res; | 75 | uint32_t __res; |
74 | asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r"(__res)); | 76 | asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r"(__res)); |
@@ -82,6 +84,31 @@ bool dbg_hw_info(void) | |||
82 | 84 | ||
83 | _DEBUG_PRINTF("capture HW: %d", rec_hw_ver); | 85 | _DEBUG_PRINTF("capture HW: %d", rec_hw_ver); |
84 | line++; | 86 | line++; |
87 | |||
88 | #ifdef CLOCKING_DEBUG | ||
89 | /* show all clocks */ | ||
90 | unsigned f_clk, c_clk, h_clk, p_clk, l_clk, s_clk; | ||
91 | |||
92 | f_clk = get_system_freqs(&c_clk, &h_clk, &p_clk); | ||
93 | s_clk = h_clk / soc_get_hsdiv(); | ||
94 | l_clk = h_clk >> ((LCD_CONFIG & 7) + 1); /* div = 2^(val+1) */ | ||
95 | |||
96 | #define MHZ 1000000 | ||
97 | #define TMHZ 100000 | ||
98 | _DEBUG_PRINTF("Clocks (MHz):"); | ||
99 | _DEBUG_PRINTF(" FClk: %d.%d", f_clk / MHZ, (f_clk % MHZ) / TMHZ); | ||
100 | _DEBUG_PRINTF(" CPU: %d.%d", c_clk / MHZ, (c_clk % MHZ) / TMHZ); | ||
101 | _DEBUG_PRINTF(" AHB: %d.%d", h_clk / MHZ, (h_clk % MHZ) / TMHZ); | ||
102 | _DEBUG_PRINTF(" SM1: %d.%d", s_clk / MHZ, (s_clk % MHZ) / TMHZ); | ||
103 | _DEBUG_PRINTF(" LCD: %d.%d", l_clk / MHZ, (l_clk % MHZ) / TMHZ); | ||
104 | _DEBUG_PRINTF(" APB: %d.%d", p_clk / MHZ, (p_clk % MHZ) / TMHZ); | ||
105 | line++; | ||
106 | _DEBUG_PRINTF("CG16_SEL_x (Hz):"); | ||
107 | _DEBUG_PRINTF(" OSC: %d", soc_get_oscsel_freq()); | ||
108 | for (int i = 0; i < 3; i++) | ||
109 | _DEBUG_PRINTF(" PLL%d: %d (%d)", i, | ||
110 | pll_get_out_freq(i), pll_get_cfg_freq(i)); | ||
111 | #endif | ||
85 | } | 112 | } |
86 | else if(state==1) | 113 | else if(state==1) |
87 | { | 114 | { |
diff --git a/firmware/target/arm/s5l8702/system-s5l8702.c b/firmware/target/arm/s5l8702/system-s5l8702.c index 014ed910de..3e84e5cf54 100644 --- a/firmware/target/arm/s5l8702/system-s5l8702.c +++ b/firmware/target/arm/s5l8702/system-s5l8702.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "gpio-s5l8702.h" | 27 | #include "gpio-s5l8702.h" |
28 | #include "dma-s5l8702.h" | 28 | #include "dma-s5l8702.h" |
29 | #include "uart-s5l8702.h" | 29 | #include "uart-s5l8702.h" |
30 | #include "clocking-s5l8702.h" | ||
30 | 31 | ||
31 | #define default_interrupt(name) \ | 32 | #define default_interrupt(name) \ |
32 | extern __attribute__((weak,alias("UIRQ"))) void name (void) | 33 | extern __attribute__((weak,alias("UIRQ"))) void name (void) |
@@ -180,9 +181,24 @@ void fiq_dummy(void) | |||
180 | ); | 181 | ); |
181 | } | 182 | } |
182 | 183 | ||
184 | static struct clocking_mode clk_modes[] = | ||
185 | { | ||
186 | /* cdiv hdiv hprat hsdiv */ /* CClk HClk PClk SM1Clk FPS */ | ||
187 | { 1, 2, 2, 4 }, /* 216 108 54 27 42 */ | ||
188 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | ||
189 | { 4, 4, 2, 2 }, /* 54 54 27 27 21 */ | ||
190 | #endif | ||
191 | }; | ||
192 | #define N_CLK_MODES (sizeof(clk_modes) / sizeof(struct clocking_mode)) | ||
193 | |||
194 | enum { | ||
195 | CLK_BOOST = 0, | ||
196 | CLK_UNBOOST = N_CLK_MODES - 1, | ||
197 | }; | ||
183 | 198 | ||
184 | void system_init(void) | 199 | void system_init(void) |
185 | { | 200 | { |
201 | clocking_init(clk_modes, 0); | ||
186 | gpio_init(); | 202 | gpio_init(); |
187 | pmu_init(); | 203 | pmu_init(); |
188 | dma_init(); | 204 | dma_init(); |
@@ -223,61 +239,22 @@ int system_memory_guard(int newmode) | |||
223 | } | 239 | } |
224 | 240 | ||
225 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 241 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
226 | |||
227 | void set_cpu_frequency(long frequency) | 242 | void set_cpu_frequency(long frequency) |
228 | { | 243 | { |
229 | if (cpu_frequency == frequency) | 244 | if (cpu_frequency == frequency) |
230 | return; | 245 | return; |
231 | 246 | ||
232 | /* | ||
233 | * CPU scaling parameters: | ||
234 | * CPUFREQ_MAX: CPU = 216MHz, AHB = 108MHz, Vcore = 1.200V | ||
235 | * CPUFREQ_NORMAL: CPU = 54MHz, AHB = 54MHz, Vcore = 1.050V | ||
236 | * | ||
237 | * CLKCON0 sets PLL2->FCLK divider (CPU clock) | ||
238 | * CLKCON1 sets FCLK->HCLK divider (AHB clock) | ||
239 | * | ||
240 | * HCLK is derived from FCLK, the system goes unstable if HCLK | ||
241 | * is out of the range 54-108 MHz, so two stages are required to | ||
242 | * switch FCLK (216 MHz <-> 54 MHz), adjusting HCLK in between | ||
243 | * to ensure system stability. | ||
244 | */ | ||
245 | if (frequency == CPUFREQ_MAX) | 247 | if (frequency == CPUFREQ_MAX) |
246 | { | 248 | { |
247 | /* Vcore = 1.200V */ | 249 | pmu_write(0x1e, 0x13); /* Vcore = 1100 mV */ |
248 | pmu_write(0x1e, 0x17); | 250 | set_clocking_level(CLK_BOOST); |
249 | |||
250 | /* FCLK = PLL2 / 2 (FCLK = 108MHz, HCLK = 108MHz) */ | ||
251 | CLKCON0 = 0x3011; | ||
252 | udelay(50); | ||
253 | |||
254 | /* HCLK = FCLK / 2 (HCLK = 54MHz) */ | ||
255 | CLKCON1 = 0x404101; | ||
256 | udelay(50); | ||
257 | |||
258 | /* FCLK = PLL2 (FCLK = 216MHz, HCLK = 108MHz) */ | ||
259 | CLKCON0 = 0x3000; | ||
260 | udelay(100); | ||
261 | } | 251 | } |
262 | else | 252 | else |
263 | { | 253 | { |
264 | /* FCLK = PLL2 / 2 (FCLK = 108MHz, HCLK = 54MHz) */ | 254 | set_clocking_level(CLK_UNBOOST); |
265 | CLKCON0 = 0x3011; | 255 | pmu_write(0x1e, 0xf); /* Vcore = 1000 mV */ |
266 | udelay(50); | ||
267 | |||
268 | /* HCLK = FCLK (HCLK = 108MHz) */ | ||
269 | CLKCON1 = 0x4001; | ||
270 | udelay(50); | ||
271 | |||
272 | /* FCLK = PLL2 / 4 (FCLK = 54MHz, HCLK = 54MHz) */ | ||
273 | CLKCON0 = 0x3013; | ||
274 | udelay(100); | ||
275 | |||
276 | /* Vcore = 1.050V */ | ||
277 | pmu_write(0x1e, 0x11); | ||
278 | } | 256 | } |
279 | 257 | ||
280 | cpu_frequency = frequency; | 258 | cpu_frequency = frequency; |
281 | } | 259 | } |
282 | |||
283 | #endif | 260 | #endif |
diff --git a/firmware/target/arm/s5l8702/system-target.h b/firmware/target/arm/s5l8702/system-target.h index ba05c2f6fb..43ab28d37b 100644 --- a/firmware/target/arm/s5l8702/system-target.h +++ b/firmware/target/arm/s5l8702/system-target.h | |||
@@ -24,7 +24,7 @@ | |||
24 | #include "system-arm.h" | 24 | #include "system-arm.h" |
25 | #include "mmu-arm.h" | 25 | #include "mmu-arm.h" |
26 | 26 | ||
27 | #define CPUFREQ_SLEEP 32768 | 27 | #define CPUFREQ_SLEEP 32768 |
28 | #define CPUFREQ_MAX 216000000 | 28 | #define CPUFREQ_MAX 216000000 |
29 | #define CPUFREQ_DEFAULT 54000000 | 29 | #define CPUFREQ_DEFAULT 54000000 |
30 | #define CPUFREQ_NORMAL 54000000 | 30 | #define CPUFREQ_NORMAL 54000000 |