| From 30534687e4e814095198494bc946a63c55731d43 Mon Sep 17 00:00:00 2001 |
| From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
| Date: Tue, 24 Apr 2012 02:07:47 -0700 |
| Subject: 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> |
| Signed-off-by: Simon Horman <horms@verge.net.au> |
| --- |
| arch/arm/mach-shmobile/clock-r8a7740.c | 118 ++++++++++++++++++++++++++++++++- |
| 1 file changed, 116 insertions(+), 2 deletions(-) |
| |
| diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c |
| index 99c4d74..30535f4 100644 |
| --- a/arch/arm/mach-shmobile/clock-r8a7740.c |
| +++ b/arch/arm/mach-shmobile/clock-r8a7740.c |
| @@ -47,6 +47,7 @@ |
| #define PLLC01CR 0xe6150028 |
| |
| #define SUBCKCR 0xe6150080 |
| +#define USBCKCR 0xe615008c |
| |
| #define MSTPSR0 0xe6150030 |
| #define MSTPSR1 0xe6150038 |
| @@ -181,6 +182,100 @@ static struct clk pllc1_div2_clk = { |
| .parent = &pllc1_clk, |
| }; |
| |
| +/* USB clock */ |
| +static struct clk *usb24s_parents[] = { |
| + [0] = &system_clk, |
| + [1] = &extal2_clk |
| +}; |
| + |
| +static unsigned long usb24s_recalc(struct clk *clk) |
| +{ |
| + return clk->parent->rate; |
| +}; |
| + |
| +static int usb24s_enable(struct clk *clk) |
| +{ |
| + __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR); |
| + |
| + return 0; |
| +} |
| + |
| +static void usb24s_disable(struct clk *clk) |
| +{ |
| + __raw_writel(__raw_readl(USBCKCR) | (1 << 8), USBCKCR); |
| +} |
| + |
| +static int usb24s_set_parent(struct clk *clk, struct clk *parent) |
| +{ |
| + int i, ret; |
| + u32 val; |
| + |
| + if (!clk->parent_table || !clk->parent_num) |
| + return -EINVAL; |
| + |
| + /* Search the parent */ |
| + for (i = 0; i < clk->parent_num; i++) |
| + if (clk->parent_table[i] == parent) |
| + break; |
| + |
| + if (i == clk->parent_num) |
| + return -ENODEV; |
| + |
| + ret = clk_reparent(clk, parent); |
| + if (ret < 0) |
| + return ret; |
| + |
| + val = __raw_readl(USBCKCR); |
| + val &= ~(1 << 7); |
| + val |= i << 7; |
| + __raw_writel(val, USBCKCR); |
| + |
| + return 0; |
| +} |
| + |
| +static struct sh_clk_ops usb24s_clk_ops = { |
| + .recalc = usb24s_recalc, |
| + .enable = usb24s_enable, |
| + .disable = usb24s_disable, |
| + .set_parent = usb24s_set_parent, |
| +}; |
| + |
| +static struct clk usb24s_clk = { |
| + .ops = &usb24s_clk_ops, |
| + .parent_table = usb24s_parents, |
| + .parent_num = ARRAY_SIZE(usb24s_parents), |
| + .parent = &system_clk, |
| +}; |
| + |
| +static unsigned long usb24_recalc(struct clk *clk) |
| +{ |
| + return clk->parent->rate / |
| + ((__raw_readl(USBCKCR) & (1 << 6)) ? 1 : 2); |
| +}; |
| + |
| +static int usb24_set_rate(struct clk *clk, unsigned long rate) |
| +{ |
| + u32 val; |
| + |
| + /* closer to which ? parent->rate or parent->rate/2 */ |
| + val = __raw_readl(USBCKCR); |
| + val &= ~(1 << 6); |
| + val |= (rate > (clk->parent->rate / 4) * 3) << 6; |
| + __raw_writel(val, USBCKCR); |
| + |
| + return 0; |
| +} |
| + |
| +static struct sh_clk_ops usb24_clk_ops = { |
| + .recalc = usb24_recalc, |
| + .set_rate = usb24_set_rate, |
| +}; |
| + |
| +static struct clk usb24_clk = { |
| + .ops = &usb24_clk_ops, |
| + .parent = &usb24s_clk, |
| +}; |
| + |
| struct clk *main_clks[] = { |
| &extalr_clk, |
| &extal1_clk, |
| @@ -196,6 +291,8 @@ struct clk *main_clks[] = { |
| &pllc0_clk, |
| &pllc1_clk, |
| &pllc1_div2_clk, |
| + &usb24s_clk, |
| + &usb24_clk, |
| }; |
| |
| static void div4_kick(struct clk *clk) |
| @@ -223,7 +320,7 @@ static struct clk_div4_table div4_table = { |
| |
| enum { |
| DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP, |
| - DIV4_HPP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, |
| + DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, |
| DIV4_NR |
| }; |
| |
| @@ -234,6 +331,7 @@ struct clk div4_clks[DIV4_NR] = { |
| [DIV4_M1] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT), |
| [DIV4_HP] = SH_CLK_DIV4(&pllc1_clk, FRQCRB, 4, 0x6fff, 0), |
| [DIV4_HPP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0), |
| + [DIV4_USBP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0), |
| [DIV4_S] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0), |
| [DIV4_ZB] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 8, 0x6fff, 0), |
| [DIV4_M3] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 4, 0x6fff, 0), |
| @@ -257,7 +355,9 @@ enum { |
| MSTP222, |
| MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, |
| |
| - MSTP329, MSTP323, |
| + MSTP329, MSTP323, MSTP320, |
| + |
| + MSTP416, MSTP407, MSTP406, |
| |
| MSTP_NR |
| }; |
| @@ -281,6 +381,11 @@ static struct clk mstp_clks[MSTP_NR] = { |
| |
| [MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ |
| [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ |
| + [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */ |
| + |
| + [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */ |
| + [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-Func */ |
| + [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 6, 0), /* USB Phy */ |
| }; |
| |
| static struct clk_lookup lookups[] = { |
| @@ -299,6 +404,7 @@ static struct clk_lookup lookups[] = { |
| CLKDEV_CON_ID("pllc0_clk", &pllc0_clk), |
| CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), |
| CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), |
| + CLKDEV_CON_ID("usb24s", &usb24s_clk), |
| |
| /* DIV4 clocks */ |
| CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), |
| @@ -335,6 +441,14 @@ static struct clk_lookup lookups[] = { |
| |
| CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), |
| CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), |
| + CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]), |
| + |
| + /* ICK */ |
| + CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]), |
| + CLKDEV_ICK_ID("func", "renesas_usbhs", &mstp_clks[MSTP407]), |
| + CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]), |
| + CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]), |
| + CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk), |
| }; |
| |
| void __init r8a7740_clock_init(u8 md_ck) |
| -- |
| 1.7.10.2.565.gbd578b5 |
| |