diff options
author | Stelian Pop <stelian@popies.net> | 2008-04-05 21:14:03 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-06-02 15:08:07 +0100 |
commit | 53d7168026a440c4cba25468a3d926ddd7ab030a (patch) | |
tree | 19af804716cc899c1f911f6b1479d72072c318c8 /arch/arm/mach-at91 | |
parent | 19750336d4cc3a171a5aa5f9a258fb81066cc45e (diff) |
[ARM] 4933/1: AT91CAP9 UDPHS driver: generic AT91 parts.
This is patch 1 of 2 adding support for the USB High Speed Device Port
on the AT91CAP9 system on chip. The AT91CAP9 uses the same UDPHS IP
as the AVR32 and the AT91SAM9RL.
This patch makes the generic AT91 adaptations, mainly dealing with
the addition of the UDPHS UTMI clock.
Signed-off-by: Stelian Pop <stelian@popies.net>
Acked-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Acked-by: Andrew Victor <linux@maxim.org.za>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-at91')
-rw-r--r-- | arch/arm/mach-at91/clock.c | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index a33dfe450726..b87772cd3d32 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -112,12 +112,34 @@ static void pmc_sys_mode(struct clk *clk, int is_on) at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask); } +static void pmc_uckr_mode(struct clk *clk, int is_on) +{ + unsigned int uckr = at91_sys_read(AT91_CKGR_UCKR); + + if (is_on) { + is_on = AT91_PMC_LOCKU; + at91_sys_write(AT91_CKGR_UCKR, uckr | clk->pmc_mask); + } else + at91_sys_write(AT91_CKGR_UCKR, uckr & ~(clk->pmc_mask)); + + do { + cpu_relax(); + } while ((at91_sys_read(AT91_PMC_SR) & AT91_PMC_LOCKU) != is_on); +} + /* USB function clocks (PLLB must be 48 MHz) */ static struct clk udpck = { .name = "udpck", .parent = &pllb, .mode = pmc_sys_mode, }; +static struct clk utmi_clk = { + .name = "utmi_clk", + .parent = &main_clk, + .pmc_mask = AT91_PMC_UPLLEN, /* in CKGR_UCKR */ + .mode = pmc_uckr_mode, + .type = CLK_TYPE_PLL, +}; static struct clk uhpck = { .name = "uhpck", .parent = &pllb, @@ -361,7 +383,7 @@ static void __init init_programmable_clock(struct clk *clk) static int at91_clk_show(struct seq_file *s, void *unused) { - u32 scsr, pcsr, sr; + u32 scsr, pcsr, uckr = 0, sr; struct clk *clk; seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR)); @@ -370,6 +392,8 @@ static int at91_clk_show(struct seq_file *s, void *unused) seq_printf(s, "MCFR = %8x\n", at91_sys_read(AT91_CKGR_MCFR)); seq_printf(s, "PLLA = %8x\n", at91_sys_read(AT91_CKGR_PLLAR)); seq_printf(s, "PLLB = %8x\n", at91_sys_read(AT91_CKGR_PLLBR)); + if (cpu_is_at91cap9()) + seq_printf(s, "UCKR = %8x\n", uckr = at91_sys_read(AT91_CKGR_UCKR)); seq_printf(s, "MCKR = %8x\n", at91_sys_read(AT91_PMC_MCKR)); seq_printf(s, "SR = %8x\n", sr = at91_sys_read(AT91_PMC_SR)); @@ -382,6 +406,8 @@ static int at91_clk_show(struct seq_file *s, void *unused) state = (scsr & clk->pmc_mask) ? "on" : "off"; else if (clk->mode == pmc_periph_mode) state = (pcsr & clk->pmc_mask) ? "on" : "off"; + else if (clk->mode == pmc_uckr_mode) + state = (uckr & clk->pmc_mask) ? "on" : "off"; else if (clk->pmc_mask) state = (sr & clk->pmc_mask) ? "on" : "off"; else if (clk == &clk32k || clk == &main_clk) @@ -582,6 +608,17 @@ int __init at91_clock_init(unsigned long main_clock) uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init); /* + * USB HS clock init + */ + if (cpu_is_at91cap9()) { + /* + * multiplier is hard-wired to 40 + * (obtain the USB High Speed 480 MHz when input is 12 MHz) + */ + utmi_clk.rate_hz = 40 * utmi_clk.parent->rate_hz; + } + + /* * MCK and CPU derive from one of those primary clocks. * For now, assume this parentage won't change. */ @@ -598,6 +635,9 @@ int __init at91_clock_init(unsigned long main_clock) for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++) list_add_tail(&standard_pmc_clocks[i]->node, &clocks); + if (cpu_is_at91cap9()) + list_add_tail(&utmi_clk.node, &clocks); + /* MCK and CPU clock are "always on" */ clk_enable(&mck); |