mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 16:29:59 +00:00
[ARM] 4940/1: AT91: UDPHS driver: SAM9RL board and cpu integration.
Adds support for the USB High Speed Device Port on the AT91SAM9RL system on chip. The AT91SAM9RL uses the same UDPHS IP as the AVR32 and the AT91CAP9 (atmel_usba_udc driver). Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
6b71dbf65e
commit
ba45ca4350
5 changed files with 113 additions and 7 deletions
|
@ -25,6 +25,101 @@
|
|||
#include "generic.h"
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* USB HS Device (Gadget)
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
|
||||
|
||||
static struct resource usba_udc_resources[] = {
|
||||
[0] = {
|
||||
.start = AT91SAM9RL_UDPHS_FIFO,
|
||||
.end = AT91SAM9RL_UDPHS_FIFO + SZ_512K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT91SAM9RL_BASE_UDPHS,
|
||||
.end = AT91SAM9RL_BASE_UDPHS + SZ_1K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[2] = {
|
||||
.start = AT91SAM9RL_ID_UDPHS,
|
||||
.end = AT91SAM9RL_ID_UDPHS,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
#define EP(nam, idx, maxpkt, maxbk, dma, isoc) \
|
||||
[idx] = { \
|
||||
.name = nam, \
|
||||
.index = idx, \
|
||||
.fifo_size = maxpkt, \
|
||||
.nr_banks = maxbk, \
|
||||
.can_dma = dma, \
|
||||
.can_isoc = isoc, \
|
||||
}
|
||||
|
||||
static struct usba_ep_data usba_udc_ep[] __initdata = {
|
||||
EP("ep0", 0, 64, 1, 0, 0),
|
||||
EP("ep1", 1, 1024, 2, 1, 1),
|
||||
EP("ep2", 2, 1024, 2, 1, 1),
|
||||
EP("ep3", 3, 1024, 3, 1, 0),
|
||||
EP("ep4", 4, 1024, 3, 1, 0),
|
||||
EP("ep5", 5, 1024, 3, 1, 1),
|
||||
EP("ep6", 6, 1024, 3, 1, 1),
|
||||
};
|
||||
|
||||
#undef EP
|
||||
|
||||
/*
|
||||
* pdata doesn't have room for any endpoints, so we need to
|
||||
* append room for the ones we need right after it.
|
||||
*/
|
||||
static struct {
|
||||
struct usba_platform_data pdata;
|
||||
struct usba_ep_data ep[7];
|
||||
} usba_udc_data;
|
||||
|
||||
static struct platform_device at91_usba_udc_device = {
|
||||
.name = "atmel_usba_udc",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &usba_udc_data.pdata,
|
||||
},
|
||||
.resource = usba_udc_resources,
|
||||
.num_resources = ARRAY_SIZE(usba_udc_resources),
|
||||
};
|
||||
|
||||
void __init at91_add_device_usba(struct usba_platform_data *data)
|
||||
{
|
||||
/*
|
||||
* Invalid pins are 0 on AT91, but the usba driver is shared
|
||||
* with AVR32, which use negative values instead. Once/if
|
||||
* gpio_is_valid() is ported to AT91, revisit this code.
|
||||
*/
|
||||
usba_udc_data.pdata.vbus_pin = -EINVAL;
|
||||
usba_udc_data.pdata.num_ep = ARRAY_SIZE(usba_udc_ep);
|
||||
memcpy(usba_udc_data.ep, usba_udc_ep, sizeof(usba_udc_ep));;
|
||||
|
||||
if (data && data->vbus_pin > 0) {
|
||||
at91_set_gpio_input(data->vbus_pin, 0);
|
||||
at91_set_deglitch(data->vbus_pin, 1);
|
||||
usba_udc_data.pdata.vbus_pin = data->vbus_pin;
|
||||
}
|
||||
|
||||
/* Pullup pin is handled internally by USB device peripheral */
|
||||
|
||||
/* Clocks */
|
||||
at91_clock_associate("utmi_clk", &at91_usba_udc_device.dev, "hclk");
|
||||
at91_clock_associate("udphs_clk", &at91_usba_udc_device.dev, "pclk");
|
||||
|
||||
platform_device_register(&at91_usba_udc_device);
|
||||
}
|
||||
#else
|
||||
void __init at91_add_device_usba(struct usba_platform_data *data) {}
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* MMC / SD
|
||||
* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -55,6 +55,14 @@ static void __init ek_init_irq(void)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* USB HS Device port
|
||||
*/
|
||||
static struct usba_platform_data __initdata ek_usba_udc_data = {
|
||||
.vbus_pin = AT91_PIN_PA8,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* MCI (SD/MMC)
|
||||
*/
|
||||
|
@ -175,6 +183,8 @@ static void __init ek_board_init(void)
|
|||
{
|
||||
/* Serial */
|
||||
at91_add_device_serial();
|
||||
/* USB HS */
|
||||
at91_add_device_usba(&ek_usba_udc_data);
|
||||
/* I2C */
|
||||
at91_add_device_i2c(NULL, 0);
|
||||
/* NAND */
|
||||
|
|
|
@ -391,8 +391,9 @@ static int at91_clk_show(struct seq_file *s, void *unused)
|
|||
seq_printf(s, "MOR = %8x\n", at91_sys_read(AT91_CKGR_MOR));
|
||||
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())
|
||||
if (!cpu_is_at91sam9rl())
|
||||
seq_printf(s, "PLLB = %8x\n", at91_sys_read(AT91_CKGR_PLLBR));
|
||||
if (cpu_is_at91cap9() || cpu_is_at91sam9rl())
|
||||
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));
|
||||
|
@ -610,7 +611,7 @@ int __init at91_clock_init(unsigned long main_clock)
|
|||
/*
|
||||
* USB HS clock init
|
||||
*/
|
||||
if (cpu_is_at91cap9()) {
|
||||
if (cpu_is_at91cap9() || cpu_is_at91sam9rl()) {
|
||||
/*
|
||||
* multiplier is hard-wired to 40
|
||||
* (obtain the USB High Speed 480 MHz when input is 12 MHz)
|
||||
|
@ -635,7 +636,7 @@ 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())
|
||||
if (cpu_is_at91cap9() || cpu_is_at91sam9rl())
|
||||
list_add_tail(&utmi_clk.node, &clocks);
|
||||
|
||||
/* MCK and CPU clock are "always on" */
|
||||
|
|
|
@ -118,10 +118,10 @@ config USB_AMD5536UDC
|
|||
config USB_GADGET_ATMEL_USBA
|
||||
boolean "Atmel USBA"
|
||||
select USB_GADGET_DUALSPEED
|
||||
depends on AVR32 || ARCH_AT91CAP9
|
||||
depends on AVR32 || ARCH_AT91CAP9 || ARCH_AT91SAM9RL
|
||||
help
|
||||
USBA is the integrated high-speed USB Device controller on
|
||||
the AT32AP700x and AT91CAP9 processors from Atmel.
|
||||
the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
|
||||
|
||||
config USB_ATMEL_USBA
|
||||
tristate
|
||||
|
|
|
@ -110,6 +110,6 @@
|
|||
#define AT91SAM9RL_ROM_SIZE (2 * SZ_16K) /* Internal ROM size (32Kb) */
|
||||
|
||||
#define AT91SAM9RL_LCDC_BASE 0x00500000 /* LCD Controller */
|
||||
#define AT91SAM9RL_UDPHS_BASE 0x00600000 /* USB Device HS controller */
|
||||
#define AT91SAM9RL_UDPHS_FIFO 0x00600000 /* USB Device HS controller */
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue