Commit 53d71680 authored by Stelian Pop's avatar Stelian Pop Committed by Russell King

[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: default avatarStelian Pop <stelian@popies.net>
Acked-by: default avatarHaavard Skinnemoen <hskinnemoen@atmel.com>
Acked-by: default avatarAndrew Victor <linux@maxim.org.za>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 19750336
......@@ -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);
......
......@@ -39,10 +39,14 @@
#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 */
......@@ -97,6 +101,7 @@
#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 */
......
......@@ -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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment