diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2012-04-24 05:07:47 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2012-05-12 16:24:21 -0400 |
commit | fcca3f0f007d97f095a3ebe8f209021b517309d2 (patch) | |
tree | 606581d906b70802ec3c64b2a3e81fadf9ed2279 /arch/arm/mach-shmobile/clock-r8a7740.c | |
parent | 7ee8948d158946e52ea21562f2ceef268439f36e (diff) |
ARM: mach-shmobile: clock-r8a7740: add USB clock
R8A7740 USB needs many clocks for workaround,
and it has confusing name "usb24s" and "usb24".
This "usb24s" will be used by other clocks.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tested-by: Simon Horman <horms@verge.net.au>
Acked-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'arch/arm/mach-shmobile/clock-r8a7740.c')
-rw-r--r-- | arch/arm/mach-shmobile/clock-r8a7740.c | 118 |
1 files changed, 116 insertions, 2 deletions
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c index b6fa1b77a15b..b9b1d73ab9e1 100644 --- a/arch/arm/mach-shmobile/clock-r8a7740.c +++ b/arch/arm/mach-shmobile/clock-r8a7740.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #define PLLC01CR 0xe6150028 | 47 | #define PLLC01CR 0xe6150028 |
48 | 48 | ||
49 | #define SUBCKCR 0xe6150080 | 49 | #define SUBCKCR 0xe6150080 |
50 | #define USBCKCR 0xe615008c | ||
50 | 51 | ||
51 | #define MSTPSR0 0xe6150030 | 52 | #define MSTPSR0 0xe6150030 |
52 | #define MSTPSR1 0xe6150038 | 53 | #define MSTPSR1 0xe6150038 |
@@ -181,6 +182,100 @@ static struct clk pllc1_div2_clk = { | |||
181 | .parent = &pllc1_clk, | 182 | .parent = &pllc1_clk, |
182 | }; | 183 | }; |
183 | 184 | ||
185 | /* USB clock */ | ||
186 | static struct clk *usb24s_parents[] = { | ||
187 | [0] = &system_clk, | ||
188 | [1] = &extal2_clk | ||
189 | }; | ||
190 | |||
191 | static unsigned long usb24s_recalc(struct clk *clk) | ||
192 | { | ||
193 | return clk->parent->rate; | ||
194 | }; | ||
195 | |||
196 | static int usb24s_enable(struct clk *clk) | ||
197 | { | ||
198 | __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR); | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static void usb24s_disable(struct clk *clk) | ||
204 | { | ||
205 | __raw_writel(__raw_readl(USBCKCR) | (1 << 8), USBCKCR); | ||
206 | } | ||
207 | |||
208 | static int usb24s_set_parent(struct clk *clk, struct clk *parent) | ||
209 | { | ||
210 | int i, ret; | ||
211 | u32 val; | ||
212 | |||
213 | if (!clk->parent_table || !clk->parent_num) | ||
214 | return -EINVAL; | ||
215 | |||
216 | /* Search the parent */ | ||
217 | for (i = 0; i < clk->parent_num; i++) | ||
218 | if (clk->parent_table[i] == parent) | ||
219 | break; | ||
220 | |||
221 | if (i == clk->parent_num) | ||
222 | return -ENODEV; | ||
223 | |||
224 | ret = clk_reparent(clk, parent); | ||
225 | if (ret < 0) | ||
226 | return ret; | ||
227 | |||
228 | val = __raw_readl(USBCKCR); | ||
229 | val &= ~(1 << 7); | ||
230 | val |= i << 7; | ||
231 | __raw_writel(val, USBCKCR); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static struct sh_clk_ops usb24s_clk_ops = { | ||
237 | .recalc = usb24s_recalc, | ||
238 | .enable = usb24s_enable, | ||
239 | .disable = usb24s_disable, | ||
240 | .set_parent = usb24s_set_parent, | ||
241 | }; | ||
242 | |||
243 | static struct clk usb24s_clk = { | ||
244 | .ops = &usb24s_clk_ops, | ||
245 | .parent_table = usb24s_parents, | ||
246 | .parent_num = ARRAY_SIZE(usb24s_parents), | ||
247 | .parent = &system_clk, | ||
248 | }; | ||
249 | |||
250 | static unsigned long usb24_recalc(struct clk *clk) | ||
251 | { | ||
252 | return clk->parent->rate / | ||
253 | ((__raw_readl(USBCKCR) & (1 << 6)) ? 1 : 2); | ||
254 | }; | ||
255 | |||
256 | static int usb24_set_rate(struct clk *clk, unsigned long rate) | ||
257 | { | ||
258 | u32 val; | ||
259 | |||
260 | /* closer to which ? parent->rate or parent->rate/2 */ | ||
261 | val = __raw_readl(USBCKCR); | ||
262 | val &= ~(1 << 6); | ||
263 | val |= (rate > (clk->parent->rate / 4) * 3) << 6; | ||
264 | __raw_writel(val, USBCKCR); | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static struct sh_clk_ops usb24_clk_ops = { | ||
270 | .recalc = usb24_recalc, | ||
271 | .set_rate = usb24_set_rate, | ||
272 | }; | ||
273 | |||
274 | static struct clk usb24_clk = { | ||
275 | .ops = &usb24_clk_ops, | ||
276 | .parent = &usb24s_clk, | ||
277 | }; | ||
278 | |||
184 | struct clk *main_clks[] = { | 279 | struct clk *main_clks[] = { |
185 | &extalr_clk, | 280 | &extalr_clk, |
186 | &extal1_clk, | 281 | &extal1_clk, |
@@ -196,6 +291,8 @@ struct clk *main_clks[] = { | |||
196 | &pllc0_clk, | 291 | &pllc0_clk, |
197 | &pllc1_clk, | 292 | &pllc1_clk, |
198 | &pllc1_div2_clk, | 293 | &pllc1_div2_clk, |
294 | &usb24s_clk, | ||
295 | &usb24_clk, | ||
199 | }; | 296 | }; |
200 | 297 | ||
201 | static void div4_kick(struct clk *clk) | 298 | static void div4_kick(struct clk *clk) |
@@ -223,7 +320,7 @@ static struct clk_div4_table div4_table = { | |||
223 | 320 | ||
224 | enum { | 321 | enum { |
225 | DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP, | 322 | DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP, |
226 | DIV4_HPP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, | 323 | DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, |
227 | DIV4_NR | 324 | DIV4_NR |
228 | }; | 325 | }; |
229 | 326 | ||
@@ -234,6 +331,7 @@ struct clk div4_clks[DIV4_NR] = { | |||
234 | [DIV4_M1] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT), | 331 | [DIV4_M1] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT), |
235 | [DIV4_HP] = SH_CLK_DIV4(&pllc1_clk, FRQCRB, 4, 0x6fff, 0), | 332 | [DIV4_HP] = SH_CLK_DIV4(&pllc1_clk, FRQCRB, 4, 0x6fff, 0), |
236 | [DIV4_HPP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0), | 333 | [DIV4_HPP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0), |
334 | [DIV4_USBP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0), | ||
237 | [DIV4_S] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0), | 335 | [DIV4_S] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0), |
238 | [DIV4_ZB] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 8, 0x6fff, 0), | 336 | [DIV4_ZB] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 8, 0x6fff, 0), |
239 | [DIV4_M3] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 4, 0x6fff, 0), | 337 | [DIV4_M3] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 4, 0x6fff, 0), |
@@ -257,7 +355,9 @@ enum { | |||
257 | MSTP222, | 355 | MSTP222, |
258 | MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, | 356 | MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, |
259 | 357 | ||
260 | MSTP329, MSTP328, MSTP323, | 358 | MSTP329, MSTP328, MSTP323, MSTP320, |
359 | |||
360 | MSTP416, MSTP407, MSTP406, | ||
261 | 361 | ||
262 | MSTP_NR | 362 | MSTP_NR |
263 | }; | 363 | }; |
@@ -282,6 +382,11 @@ static struct clk mstp_clks[MSTP_NR] = { | |||
282 | [MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ | 382 | [MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ |
283 | [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */ | 383 | [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */ |
284 | [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ | 384 | [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ |
385 | [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */ | ||
386 | |||
387 | [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */ | ||
388 | [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-Func */ | ||
389 | [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 6, 0), /* USB Phy */ | ||
285 | }; | 390 | }; |
286 | 391 | ||
287 | static struct clk_lookup lookups[] = { | 392 | static struct clk_lookup lookups[] = { |
@@ -300,6 +405,7 @@ static struct clk_lookup lookups[] = { | |||
300 | CLKDEV_CON_ID("pllc0_clk", &pllc0_clk), | 405 | CLKDEV_CON_ID("pllc0_clk", &pllc0_clk), |
301 | CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), | 406 | CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), |
302 | CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), | 407 | CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), |
408 | CLKDEV_CON_ID("usb24s", &usb24s_clk), | ||
303 | 409 | ||
304 | /* DIV4 clocks */ | 410 | /* DIV4 clocks */ |
305 | CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), | 411 | CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), |
@@ -337,6 +443,14 @@ static struct clk_lookup lookups[] = { | |||
337 | CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), | 443 | CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), |
338 | CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), | 444 | CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), |
339 | CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), | 445 | CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), |
446 | CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]), | ||
447 | |||
448 | /* ICK */ | ||
449 | CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]), | ||
450 | CLKDEV_ICK_ID("func", "renesas_usbhs", &mstp_clks[MSTP407]), | ||
451 | CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]), | ||
452 | CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]), | ||
453 | CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk), | ||
340 | }; | 454 | }; |
341 | 455 | ||
342 | void __init r8a7740_clock_init(u8 md_ck) | 456 | void __init r8a7740_clock_init(u8 md_ck) |