[PATCH V4 20/23] at91: Make high speed USB gadget device common

Ryan Mallon ryan at bluewatersys.com
Mon May 2 20:03:34 EDT 2011


Replace the individual high-speed UDC code for each at91 variant with
a single implementation in devices.c

Signed-off-by: Ryan Mallon <ryan at bluewatersys.com>
---
 arch/arm/mach-at91/at91cap9_devices.c    |  114 ++++++------------------------
 arch/arm/mach-at91/at91sam9g45_devices.c |   94 ++++---------------------
 arch/arm/mach-at91/at91sam9rl_devices.c  |  100 ++++----------------------
 arch/arm/mach-at91/devices.c             |   64 +++++++++++++++++
 arch/arm/mach-at91/devices.h             |   20 +++++
 5 files changed, 135 insertions(+), 257 deletions(-)

diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index e6adc98..cb12e0c 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -51,105 +51,36 @@ static struct at91_dev_table_usb_ohci device_usbh_ohci __initdata = {
  *  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	= AT91CAP9_UDPHS_FIFO,
-		.end	= AT91CAP9_UDPHS_FIFO + SZ_512K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_BASE_UDPHS,
-		.end	= AT91CAP9_BASE_UDPHS + SZ_1K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= AT91CAP9_ID_UDPHS,
-		.end	= AT91CAP9_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[] = {
-	EP("ep0", 0,   64, 1, 0, 0),
-	EP("ep1", 1, 1024, 3, 1, 1),
-	EP("ep2", 2, 1024, 3, 1, 1),
-	EP("ep3", 3, 1024, 2, 1, 1),
-	EP("ep4", 4, 1024, 2, 1, 1),
-	EP("ep5", 5, 1024, 2, 1, 0),
-	EP("ep6", 6, 1024, 2, 1, 0),
-	EP("ep7", 7, 1024, 2, 0, 0),
-};
-
-#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[8];
-} 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)
+static void at91cap9_usba_init(void)
 {
 	if (cpu_is_at91cap9_revB()) {
 		irq_set_irq_type(AT91CAP9_ID_UDPHS, IRQ_TYPE_LEVEL_HIGH);
 		at91_sys_write(AT91_MATRIX_UDPHS, AT91_MATRIX_SELECT_UDPHS |
-						  AT91_MATRIX_UDPHS_BYPASS_LOCK);
-	}
-	else
+			       AT91_MATRIX_UDPHS_BYPASS_LOCK);
+	} else {
 		at91_sys_write(AT91_MATRIX_UDPHS, AT91_MATRIX_SELECT_UDPHS);
-
-	/*
-	 * 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
 
+static struct usba_ep_data usba_udc_ep[] = {
+	AT91_UDC_HS_EP("ep0", 0,   64, 1, 0, 0),
+	AT91_UDC_HS_EP("ep1", 1, 1024, 3, 1, 1),
+	AT91_UDC_HS_EP("ep2", 2, 1024, 3, 1, 1),
+	AT91_UDC_HS_EP("ep3", 3, 1024, 2, 1, 1),
+	AT91_UDC_HS_EP("ep4", 4, 1024, 2, 1, 1),
+	AT91_UDC_HS_EP("ep5", 5, 1024, 2, 1, 0),
+	AT91_UDC_HS_EP("ep6", 6, 1024, 2, 1, 0),
+	AT91_UDC_HS_EP("ep7", 7, 1024, 2, 0, 0),
+};
+
+static struct at91_dev_table_udc_hs device_udc_hs __initdata = {
+	.fifo_base	= AT91CAP9_UDPHS_FIFO,
+	.mmio_base	= AT91CAP9_BASE_UDPHS,
+	.irq		= AT91CAP9_ID_UDPHS,
+	.device_init	= at91cap9_usba_init,
+	.endpoints	= usba_udc_ep,
+	.nr_endpoints	= ARRAY_SIZE(usba_udc_ep),
+};
 
 /* --------------------------------------------------------------------
  *  Ethernet
@@ -480,6 +411,7 @@ static struct at91_device_table at91cap9_device_table __initdata = {
 	.ssc[1]		= &device_ssc1,
 	.ac97		= &device_ac97,
 	.lcdc		= &device_lcdc,
+	.udc_hs		= &device_udc_hs,
 };
 
 void __init at91cap9_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 3627c2e..0d6b2b0 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -66,91 +66,24 @@ static struct at91_dev_table_basic_device device_usb_ehci __initdata = {
  *  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	= AT91SAM9G45_UDPHS_FIFO,
-		.end	= AT91SAM9G45_UDPHS_FIFO + SZ_512K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_BASE_UDPHS,
-		.end	= AT91SAM9G45_BASE_UDPHS + SZ_1K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= AT91SAM9G45_ID_UDPHS,
-		.end	= AT91SAM9G45_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),
+	AT91_UDC_HS_EP("ep0", 0, 64, 1, 0, 0),
+	AT91_UDC_HS_EP("ep1", 1, 1024, 2, 1, 1),
+	AT91_UDC_HS_EP("ep2", 2, 1024, 2, 1, 1),
+	AT91_UDC_HS_EP("ep3", 3, 1024, 3, 1, 0),
+	AT91_UDC_HS_EP("ep4", 4, 1024, 3, 1, 0),
+	AT91_UDC_HS_EP("ep5", 5, 1024, 3, 1, 1),
+	AT91_UDC_HS_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),
+static struct at91_dev_table_udc_hs device_udc_hs __initdata = {
+	.fifo_base	= AT91SAM9G45_UDPHS_FIFO,
+	.mmio_base	= AT91SAM9G45_BASE_UDPHS,
+	.irq		= AT91SAM9G45_ID_UDPHS,
+	.endpoints	= usba_udc_ep,
+	.nr_endpoints	= ARRAY_SIZE(usba_udc_ep),
 };
 
-void __init at91_add_device_usba(struct usba_platform_data *data)
-{
-	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
-
-
 /* --------------------------------------------------------------------
  *  Ethernet
  * -------------------------------------------------------------------- */
@@ -543,6 +476,7 @@ static struct at91_device_table at91sam9g45_device_table __initdata = {
 	.lcdc		= &device_lcdc,
 	.tsadcc		= &device_tsadcc,
 	.hdmac		= &device_hdmac,
+	.udc_hs		= &device_udc_hs,
 };
 
 void __init at91sam9g45_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 2aa465b..74d4363 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -40,97 +40,24 @@ static struct at91_dev_table_hdmac device_hdmac __initdata = {
  *  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),
+	AT91_UDC_HS_EP("ep0", 0, 64, 1, 0, 0),
+	AT91_UDC_HS_EP("ep1", 1, 1024, 2, 1, 1),
+	AT91_UDC_HS_EP("ep2", 2, 1024, 2, 1, 1),
+	AT91_UDC_HS_EP("ep3", 3, 1024, 3, 1, 0),
+	AT91_UDC_HS_EP("ep4", 4, 1024, 3, 1, 0),
+	AT91_UDC_HS_EP("ep5", 5, 1024, 3, 1, 1),
+	AT91_UDC_HS_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),
+static struct at91_dev_table_udc_hs device_udc_hs __initdata = {
+	.fifo_base	= AT91SAM9RL_UDPHS_FIFO,
+	.mmio_base	= AT91SAM9RL_BASE_UDPHS,
+	.irq		= AT91SAM9RL_ID_UDPHS,
+	.endpoints	= usba_udc_ep,
+	.nr_endpoints	= ARRAY_SIZE(usba_udc_ep),
 };
 
-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
  * -------------------------------------------------------------------- */
@@ -419,6 +346,7 @@ static struct at91_device_table at91sam9rl_device_table __initdata = {
 	.lcdc		= &device_lcdc,
 	.tsadcc		= &device_tsadcc,
 	.hdmac		= &device_hdmac,
+	.udc_hs		= &device_udc_hs,
 };
 
 void __init at91sam9rl_init_devices(void)
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 0d06e63..8828ccb 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -1254,6 +1254,70 @@ static void __init at91_add_device_rtc(void)
 static void __init at91_add_device_rtc(void) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  USB HS Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
+/*
+ * pdata doesn't have room for any endpoints, so we need to
+ * append room for the ones we need right after it.
+ */
+struct usba_udc_data {
+	struct usba_platform_data	pdata;
+	struct usba_ep_data		ep[8];
+};
+
+static struct platform_device at91_usba_udc_device = {
+	.name	= "atmel_usba_udc",
+	.id	= -1,
+};
+
+void __init at91_add_device_usba(struct usba_platform_data *data)
+{
+	struct at91_dev_table_udc_hs *info = devices->udc_hs;
+	struct resource resources[3] = {{0}};
+	struct usba_udc_data usba_udc_data;
+
+	BUG_ON(!info);
+	init_resource_mem(&resources[0], info->fifo_base, SZ_512K);
+	init_resource_mem(&resources[1], info->mmio_base, SZ_1K);
+	init_resource_irq(&resources[2], info->irq);
+
+	/* Custom platform initialisation */
+	if (info->device_init)
+		info->device_init();
+
+	/*
+	 * 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 = info->nr_endpoints;
+	memcpy(usba_udc_data.ep, info->endpoints,
+	       info->nr_endpoints * sizeof(struct usba_ep_data));
+
+	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");
+
+	at91_add_platform_device(&at91_usba_udc_device, resources,
+				 ARRAY_SIZE(resources), &usba_udc_data,
+				 sizeof(usba_udc_data));
+}
+#else
+void __init at91_add_device_usba(struct usba_platform_data *data) {}
+#endif
+
 static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_tc();
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index 417c959..a1374fa 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -170,6 +170,25 @@ struct at91_dev_table_hdmac {
 	int			have_slave;
 };
 
+#define AT91_UDC_HS_EP(nam, idx, maxpkt, maxbk, dma, isoc)	\
+	[idx] = {						\
+		.name		= nam,				\
+		.index		= idx,				\
+		.fifo_size	= maxpkt,			\
+		.nr_banks	= maxbk,			\
+		.can_dma	= dma,				\
+		.can_isoc	= isoc,				\
+	}
+
+struct at91_dev_table_udc_hs {
+	unsigned		fifo_base;
+	unsigned		mmio_base;
+	int			irq;
+	void			(*device_init)(void);
+	struct usba_ep_data	*endpoints;
+	int			nr_endpoints;
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
@@ -189,6 +208,7 @@ struct at91_device_table {
 	struct at91_dev_table_lcdc		*lcdc;
 	struct at91_dev_table_tsadcc		*tsadcc;
 	struct at91_dev_table_hdmac		*hdmac;
+	struct at91_dev_table_udc_hs		*udc_hs;
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4




More information about the linux-arm-kernel mailing list