[ARM] 4933/1: AT91CAP9 UDPHS driver: generic AT91 parts.
authorStelian Pop <stelian@popies.net>
Sat, 5 Apr 2008 20:14:03 +0000 (21:14 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Mon, 2 Jun 2008 14:08:07 +0000 (15:08 +0100)
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>
arch/arm/mach-at91/clock.c
include/asm-arm/arch-at91/at91_pmc.h
include/asm-arm/arch-at91/board.h

index a33dfe4507264bb9e2943f1a04699ccf7f155d76..b87772cd3d322d6dc70e56c4fb8649437e72782f 100644 (file)
@@ -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)
@@ -581,6 +607,17 @@ int __init at91_clock_init(unsigned long main_clock)
        udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
        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);
 
index c2b13c2801557c83490eee49e8d524db9793b638..2001e81f226780b0764bbf7fc9bb7d30ee06593b 100644 (file)
 #define        AT91_PMC_PCSR           (AT91_PMC + 0x18)       /* Peripheral Clock Status Register */
 
 #define        AT91_CKGR_UCKR          (AT91_PMC + 0x1C)       /* UTMI Clock Register [SAM9RL, CAP9] */
+#define                AT91_PMC_UPLLEN         (1   << 16)             /* UTMI PLL Enable */
+#define                AT91_PMC_UPLLCOUNT      (0xf << 20)             /* UTMI PLL Start-up Time */
+#define                AT91_PMC_BIASEN         (1   << 24)             /* UTMI BIAS Enable */
+#define                AT91_PMC_BIASCOUNT      (0xf << 28)             /* UTMI PLL Start-up Time */
 
 #define        AT91_CKGR_MOR           (AT91_PMC + 0x20)       /* Main Oscillator Register [not on SAM9RL] */
 #define                AT91_PMC_MOSCEN         (1    << 0)             /* Main Oscillator Enable */
-#define                AT91_PMC_OSCBYPASS      (1    << 1)             /* Oscillator Bypass [AT91SAM926x only] */
+#define                AT91_PMC_OSCBYPASS      (1    << 1)             /* Oscillator Bypass [SAM9x, CAP9] */
 #define                AT91_PMC_OSCOUNT        (0xff << 8)             /* Main Oscillator Start-up Time */
 
 #define        AT91_CKGR_MCFR          (AT91_PMC + 0x24)       /* Main Clock Frequency Register */
 #define                AT91_PMC_LOCKA          (1 <<  1)               /* PLLA Lock */
 #define                AT91_PMC_LOCKB          (1 <<  2)               /* PLLB Lock */
 #define                AT91_PMC_MCKRDY         (1 <<  3)               /* Master Clock */
+#define                AT91_PMC_LOCKU          (1 <<  6)               /* UPLL Lock [AT91CAP9 only] */
 #define                AT91_PMC_PCK0RDY        (1 <<  8)               /* Programmable Clock 0 */
 #define                AT91_PMC_PCK1RDY        (1 <<  9)               /* Programmable Clock 1 */
 #define                AT91_PMC_PCK2RDY        (1 << 10)               /* Programmable Clock 2 */
index dc189f01c5b3c969071057484e75b4d72df236db..1f247028686d9d894d7dc5021ea266518b0c26a7 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/i2c.h>
 #include <linux/leds.h>
 #include <linux/spi/spi.h>
+#include <linux/usb/atmel_usba_udc.h>
 
  /* USB Device */
 struct at91_udc_data {
@@ -45,6 +46,9 @@ struct at91_udc_data {
 };
 extern void __init at91_add_device_udc(struct at91_udc_data *data);
 
+ /* USB High Speed Device */
+extern void __init at91_add_device_usba(struct usba_platform_data *data);
+
  /* Compact Flash */
 struct at91_cf_data {
        u8      irq_pin;                /* I/O IRQ */