Skip to content

Commit

Permalink
ARM: mach-shmobile: clock-r8a7740: add USB clock
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Kuninori Morimoto authored and Rafael J. Wysocki committed May 12, 2012
1 parent 7ee8948 commit fcca3f0
Showing 1 changed file with 116 additions and 2 deletions.
118 changes: 116 additions & 2 deletions arch/arm/mach-shmobile/clock-r8a7740.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#define PLLC01CR 0xe6150028

#define SUBCKCR 0xe6150080
#define USBCKCR 0xe615008c

#define MSTPSR0 0xe6150030
#define MSTPSR1 0xe6150038
Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand Down Expand Up @@ -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
};

Expand All @@ -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),
Expand All @@ -257,7 +355,9 @@ enum {
MSTP222,
MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,

MSTP329, MSTP328, MSTP323,
MSTP329, MSTP328, MSTP323, MSTP320,

MSTP416, MSTP407, MSTP406,

MSTP_NR
};
Expand All @@ -282,6 +382,11 @@ static struct clk mstp_clks[MSTP_NR] = {
[MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
[MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */
[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[] = {
Expand All @@ -300,6 +405,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]),
Expand Down Expand Up @@ -337,6 +443,14 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]),
CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]),
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)
Expand Down

0 comments on commit fcca3f0

Please sign in to comment.