summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCástor Muñoz <cmvidal@gmail.com>2015-09-26 01:35:15 +0200
committerCástor Muñoz <cmvidal@gmail.com>2015-12-17 07:05:53 +0100
commitf753b8ead1a798b90b6c2ecd0c62c2f4b6c4eea7 (patch)
tree9232929017de920020b47623c2eec05d8ca5ada2
parentad5e5c42fb00334ec0e9b0e9e8c69c4b7d05ac7a (diff)
downloadrockbox-f753b8ead1a798b90b6c2ecd0c62c2f4b6c4eea7.tar.gz
rockbox-f753b8ead1a798b90b6c2ecd0c62c2f4b6c4eea7.zip
iPod Classic: s5l8702 clocking rewrite+documentation
This is a rewrite of the clocking section, the resulting system frequencies are the same as the current git version. This pàtch uses fixed FClk and just one register is written to switch all system frequencies, it needs less steps than the current git version to reach the desired frequency, so it is faster and safer. Includes functions to step-up/down over a table of predefined set of frequencies. The major difference is that Vcore is decreased from 1050 to 1000 mV. See clocking-s5l8702.h for more information. Change-Id: I58ac6634e1996adbe1c0c0918a7ce94ad1917d8e
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/export/s5l8702.h108
-rw-r--r--firmware/target/arm/s5l8702/clocking-s5l8702.c230
-rw-r--r--firmware/target/arm/s5l8702/clocking-s5l8702.h436
-rw-r--r--firmware/target/arm/s5l8702/debug-s5l8702.c31
-rw-r--r--firmware/target/arm/s5l8702/system-s5l8702.c63
-rw-r--r--firmware/target/arm/s5l8702/system-target.h2
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
1600target/arm/s5l8702/gpio-s5l8702.c 1600target/arm/s5l8702/gpio-s5l8702.c
1601target/arm/s5l8702/pl080.c 1601target/arm/s5l8702/pl080.c
1602target/arm/s5l8702/dma-s5l8702.c 1602target/arm/s5l8702/dma-s5l8702.c
1603target/arm/s5l8702/clocking-s5l8702.c
1603target/arm/s5l8702/ipod6g/lcd-ipod6g.c 1604target/arm/s5l8702/ipod6g/lcd-ipod6g.c
1604target/arm/s5l8702/ipod6g/lcd-asm-ipod6g.S 1605target/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) */
29unsigned 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 */
63unsigned 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 */
77unsigned 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 */
84unsigned 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
107void 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
129unsigned 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
146unsigned 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
159void soc_set_hsdiv(int hsdiv)
160{
161 SM1_DIV = hsdiv - 1;
162}
163
164int soc_get_hsdiv(void)
165{
166 return (SM1_DIV & 0xf) + 1;
167}
168
169/* each target/app could define its own clk_modes table */
170struct clocking_mode *clk_modes;
171int cur_level = -1;
172
173void 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
188void 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 */
225unsigned 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 */
418struct 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
426void clocking_init(struct clocking_mode *modes, int init_level);
427void set_clocking_level(int level);
428unsigned get_system_freqs(unsigned *cclk, unsigned *hclk, unsigned *pclk);
429
430/* debug */
431unsigned pll_get_cfg_freq(int pll);
432unsigned pll_get_out_freq(int pll);
433unsigned soc_get_oscsel_freq(void);
434int 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
184static 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
194enum {
195 CLK_BOOST = 0,
196 CLK_UNBOOST = N_CLK_MODES - 1,
197};
183 198
184void system_init(void) 199void 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
227void set_cpu_frequency(long frequency) 242void 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