aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-shmobile/clock-r8a7740.c
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2012-04-24 05:07:47 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2012-05-12 16:24:21 -0400
commitfcca3f0f007d97f095a3ebe8f209021b517309d2 (patch)
tree606581d906b70802ec3c64b2a3e81fadf9ed2279 /arch/arm/mach-shmobile/clock-r8a7740.c
parent7ee8948d158946e52ea21562f2ceef268439f36e (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.c118
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 */
186static struct clk *usb24s_parents[] = {
187 [0] = &system_clk,
188 [1] = &extal2_clk
189};
190
191static unsigned long usb24s_recalc(struct clk *clk)
192{
193 return clk->parent->rate;
194};
195
196static int usb24s_enable(struct clk *clk)
197{
198 __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR);
199
200 return 0;
201}
202
203static void usb24s_disable(struct clk *clk)
204{
205 __raw_writel(__raw_readl(USBCKCR) | (1 << 8), USBCKCR);
206}
207
208static 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
236static 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
243static 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
250static unsigned long usb24_recalc(struct clk *clk)
251{
252 return clk->parent->rate /
253 ((__raw_readl(USBCKCR) & (1 << 6)) ? 1 : 2);
254};
255
256static 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
269static struct sh_clk_ops usb24_clk_ops = {
270 .recalc = usb24_recalc,
271 .set_rate = usb24_set_rate,
272};
273
274static struct clk usb24_clk = {
275 .ops = &usb24_clk_ops,
276 .parent = &usb24s_clk,
277};
278
184struct clk *main_clks[] = { 279struct 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
201static void div4_kick(struct clk *clk) 298static void div4_kick(struct clk *clk)
@@ -223,7 +320,7 @@ static struct clk_div4_table div4_table = {
223 320
224enum { 321enum {
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
287static struct clk_lookup lookups[] = { 392static 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
342void __init r8a7740_clock_init(u8 md_ck) 456void __init r8a7740_clock_init(u8 md_ck)