diff options
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap700x.c | 50 | ||||
-rw-r--r-- | drivers/usb/gadget/atmel_usba_udc.c | 71 | ||||
-rw-r--r-- | include/asm-avr32/arch-at32ap/board.h | 4 | ||||
-rw-r--r-- | include/linux/usb/atmel_usba_udc.h | 22 |
4 files changed, 105 insertions, 42 deletions
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index 7678fee9a885..cb47afc9fffc 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/platform_device.h> | 11 | #include <linux/platform_device.h> |
12 | #include <linux/dma-mapping.h> | 12 | #include <linux/dma-mapping.h> |
13 | #include <linux/spi/spi.h> | 13 | #include <linux/spi/spi.h> |
14 | #include <linux/usb/atmel_usba_udc.h> | ||
14 | 15 | ||
15 | #include <asm/io.h> | 16 | #include <asm/io.h> |
16 | #include <asm/irq.h> | 17 | #include <asm/irq.h> |
@@ -1351,9 +1352,39 @@ static struct clk usba0_hclk = { | |||
1351 | .index = 6, | 1352 | .index = 6, |
1352 | }; | 1353 | }; |
1353 | 1354 | ||
1355 | #define EP(nam, idx, maxpkt, maxbk, dma, isoc) \ | ||
1356 | [idx] = { \ | ||
1357 | .name = nam, \ | ||
1358 | .index = idx, \ | ||
1359 | .fifo_size = maxpkt, \ | ||
1360 | .nr_banks = maxbk, \ | ||
1361 | .can_dma = dma, \ | ||
1362 | .can_isoc = isoc, \ | ||
1363 | } | ||
1364 | |||
1365 | static struct usba_ep_data at32_usba_ep[] __initdata = { | ||
1366 | EP("ep0", 0, 64, 1, 0, 0), | ||
1367 | EP("ep1", 1, 512, 2, 1, 1), | ||
1368 | EP("ep2", 2, 512, 2, 1, 1), | ||
1369 | EP("ep3-int", 3, 64, 3, 1, 0), | ||
1370 | EP("ep4-int", 4, 64, 3, 1, 0), | ||
1371 | EP("ep5", 5, 1024, 3, 1, 1), | ||
1372 | EP("ep6", 6, 1024, 3, 1, 1), | ||
1373 | }; | ||
1374 | |||
1375 | #undef EP | ||
1376 | |||
1354 | struct platform_device *__init | 1377 | struct platform_device *__init |
1355 | at32_add_device_usba(unsigned int id, struct usba_platform_data *data) | 1378 | at32_add_device_usba(unsigned int id, struct usba_platform_data *data) |
1356 | { | 1379 | { |
1380 | /* | ||
1381 | * pdata doesn't have room for any endpoints, so we need to | ||
1382 | * append room for the ones we need right after it. | ||
1383 | */ | ||
1384 | struct { | ||
1385 | struct usba_platform_data pdata; | ||
1386 | struct usba_ep_data ep[7]; | ||
1387 | } usba_data; | ||
1357 | struct platform_device *pdev; | 1388 | struct platform_device *pdev; |
1358 | 1389 | ||
1359 | if (id != 0) | 1390 | if (id != 0) |
@@ -1367,13 +1398,20 @@ at32_add_device_usba(unsigned int id, struct usba_platform_data *data) | |||
1367 | ARRAY_SIZE(usba0_resource))) | 1398 | ARRAY_SIZE(usba0_resource))) |
1368 | goto out_free_pdev; | 1399 | goto out_free_pdev; |
1369 | 1400 | ||
1370 | if (data) { | 1401 | if (data) |
1371 | if (platform_device_add_data(pdev, data, sizeof(*data))) | 1402 | usba_data.pdata.vbus_pin = data->vbus_pin; |
1372 | goto out_free_pdev; | 1403 | else |
1404 | usba_data.pdata.vbus_pin = -EINVAL; | ||
1373 | 1405 | ||
1374 | if (data->vbus_pin != GPIO_PIN_NONE) | 1406 | data = &usba_data.pdata; |
1375 | at32_select_gpio(data->vbus_pin, 0); | 1407 | data->num_ep = ARRAY_SIZE(at32_usba_ep); |
1376 | } | 1408 | memcpy(data->ep, at32_usba_ep, sizeof(at32_usba_ep)); |
1409 | |||
1410 | if (platform_device_add_data(pdev, data, sizeof(usba_data))) | ||
1411 | goto out_free_pdev; | ||
1412 | |||
1413 | if (data->vbus_pin >= 0) | ||
1414 | at32_select_gpio(data->vbus_pin, 0); | ||
1377 | 1415 | ||
1378 | usba0_pclk.dev = &pdev->dev; | 1416 | usba0_pclk.dev = &pdev->dev; |
1379 | usba0_hclk.dev = &pdev->dev; | 1417 | usba0_hclk.dev = &pdev->dev; |
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 39d187fb038a..71d3c5171f89 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/usb/ch9.h> | 19 | #include <linux/usb/ch9.h> |
20 | #include <linux/usb/gadget.h> | 20 | #include <linux/usb/gadget.h> |
21 | #include <linux/usb/atmel_usba_udc.h> | ||
21 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
22 | 23 | ||
23 | #include <asm/gpio.h> | 24 | #include <asm/gpio.h> |
@@ -27,6 +28,7 @@ | |||
27 | 28 | ||
28 | 29 | ||
29 | static struct usba_udc the_udc; | 30 | static struct usba_udc the_udc; |
31 | static struct usba_ep *usba_ep; | ||
30 | 32 | ||
31 | #ifdef CONFIG_USB_GADGET_DEBUG_FS | 33 | #ifdef CONFIG_USB_GADGET_DEBUG_FS |
32 | #include <linux/debugfs.h> | 34 | #include <linux/debugfs.h> |
@@ -982,33 +984,6 @@ static const struct usb_gadget_ops usba_udc_ops = { | |||
982 | .set_selfpowered = usba_udc_set_selfpowered, | 984 | .set_selfpowered = usba_udc_set_selfpowered, |
983 | }; | 985 | }; |
984 | 986 | ||
985 | #define EP(nam, idx, maxpkt, maxbk, dma, isoc) \ | ||
986 | { \ | ||
987 | .ep = { \ | ||
988 | .ops = &usba_ep_ops, \ | ||
989 | .name = nam, \ | ||
990 | .maxpacket = maxpkt, \ | ||
991 | }, \ | ||
992 | .udc = &the_udc, \ | ||
993 | .queue = LIST_HEAD_INIT(usba_ep[idx].queue), \ | ||
994 | .fifo_size = maxpkt, \ | ||
995 | .nr_banks = maxbk, \ | ||
996 | .index = idx, \ | ||
997 | .can_dma = dma, \ | ||
998 | .can_isoc = isoc, \ | ||
999 | } | ||
1000 | |||
1001 | static struct usba_ep usba_ep[] = { | ||
1002 | EP("ep0", 0, 64, 1, 0, 0), | ||
1003 | EP("ep1", 1, 512, 2, 1, 1), | ||
1004 | EP("ep2", 2, 512, 2, 1, 1), | ||
1005 | EP("ep3-int", 3, 64, 3, 1, 0), | ||
1006 | EP("ep4-int", 4, 64, 3, 1, 0), | ||
1007 | EP("ep5", 5, 1024, 3, 1, 1), | ||
1008 | EP("ep6", 6, 1024, 3, 1, 1), | ||
1009 | }; | ||
1010 | #undef EP | ||
1011 | |||
1012 | static struct usb_endpoint_descriptor usba_ep0_desc = { | 987 | static struct usb_endpoint_descriptor usba_ep0_desc = { |
1013 | .bLength = USB_DT_ENDPOINT_SIZE, | 988 | .bLength = USB_DT_ENDPOINT_SIZE, |
1014 | .bDescriptorType = USB_DT_ENDPOINT, | 989 | .bDescriptorType = USB_DT_ENDPOINT, |
@@ -1027,7 +1002,6 @@ static void nop_release(struct device *dev) | |||
1027 | static struct usba_udc the_udc = { | 1002 | static struct usba_udc the_udc = { |
1028 | .gadget = { | 1003 | .gadget = { |
1029 | .ops = &usba_udc_ops, | 1004 | .ops = &usba_udc_ops, |
1030 | .ep0 = &usba_ep[0].ep, | ||
1031 | .ep_list = LIST_HEAD_INIT(the_udc.gadget.ep_list), | 1005 | .ep_list = LIST_HEAD_INIT(the_udc.gadget.ep_list), |
1032 | .is_dualspeed = 1, | 1006 | .is_dualspeed = 1, |
1033 | .name = "atmel_usba_udc", | 1007 | .name = "atmel_usba_udc", |
@@ -1861,7 +1835,7 @@ static int __init usba_udc_probe(struct platform_device *pdev) | |||
1861 | 1835 | ||
1862 | regs = platform_get_resource(pdev, IORESOURCE_MEM, CTRL_IOMEM_ID); | 1836 | regs = platform_get_resource(pdev, IORESOURCE_MEM, CTRL_IOMEM_ID); |
1863 | fifo = platform_get_resource(pdev, IORESOURCE_MEM, FIFO_IOMEM_ID); | 1837 | fifo = platform_get_resource(pdev, IORESOURCE_MEM, FIFO_IOMEM_ID); |
1864 | if (!regs || !fifo) | 1838 | if (!regs || !fifo || !pdata) |
1865 | return -ENXIO; | 1839 | return -ENXIO; |
1866 | 1840 | ||
1867 | irq = platform_get_irq(pdev, 0); | 1841 | irq = platform_get_irq(pdev, 0); |
@@ -1909,16 +1883,44 @@ static int __init usba_udc_probe(struct platform_device *pdev) | |||
1909 | usba_writel(udc, CTRL, 0); | 1883 | usba_writel(udc, CTRL, 0); |
1910 | clk_disable(pclk); | 1884 | clk_disable(pclk); |
1911 | 1885 | ||
1886 | usba_ep = kmalloc(sizeof(struct usba_ep) * pdata->num_ep, | ||
1887 | GFP_KERNEL); | ||
1888 | if (!usba_ep) | ||
1889 | goto err_alloc_ep; | ||
1890 | |||
1891 | the_udc.gadget.ep0 = &usba_ep[0].ep; | ||
1892 | |||
1912 | INIT_LIST_HEAD(&usba_ep[0].ep.ep_list); | 1893 | INIT_LIST_HEAD(&usba_ep[0].ep.ep_list); |
1913 | usba_ep[0].ep_regs = udc->regs + USBA_EPT_BASE(0); | 1894 | usba_ep[0].ep_regs = udc->regs + USBA_EPT_BASE(0); |
1914 | usba_ep[0].dma_regs = udc->regs + USBA_DMA_BASE(0); | 1895 | usba_ep[0].dma_regs = udc->regs + USBA_DMA_BASE(0); |
1915 | usba_ep[0].fifo = udc->fifo + USBA_FIFO_BASE(0); | 1896 | usba_ep[0].fifo = udc->fifo + USBA_FIFO_BASE(0); |
1916 | for (i = 1; i < ARRAY_SIZE(usba_ep); i++) { | 1897 | usba_ep[0].ep.ops = &usba_ep_ops; |
1898 | usba_ep[0].ep.name = pdata->ep[0].name; | ||
1899 | usba_ep[0].ep.maxpacket = pdata->ep[0].fifo_size; | ||
1900 | usba_ep[0].udc = &the_udc; | ||
1901 | INIT_LIST_HEAD(&usba_ep[0].queue); | ||
1902 | usba_ep[0].fifo_size = pdata->ep[0].fifo_size; | ||
1903 | usba_ep[0].nr_banks = pdata->ep[0].nr_banks; | ||
1904 | usba_ep[0].index = pdata->ep[0].index; | ||
1905 | usba_ep[0].can_dma = pdata->ep[0].can_dma; | ||
1906 | usba_ep[0].can_isoc = pdata->ep[0].can_isoc; | ||
1907 | |||
1908 | for (i = 1; i < pdata->num_ep; i++) { | ||
1917 | struct usba_ep *ep = &usba_ep[i]; | 1909 | struct usba_ep *ep = &usba_ep[i]; |
1918 | 1910 | ||
1919 | ep->ep_regs = udc->regs + USBA_EPT_BASE(i); | 1911 | ep->ep_regs = udc->regs + USBA_EPT_BASE(i); |
1920 | ep->dma_regs = udc->regs + USBA_DMA_BASE(i); | 1912 | ep->dma_regs = udc->regs + USBA_DMA_BASE(i); |
1921 | ep->fifo = udc->fifo + USBA_FIFO_BASE(i); | 1913 | ep->fifo = udc->fifo + USBA_FIFO_BASE(i); |
1914 | ep->ep.ops = &usba_ep_ops; | ||
1915 | ep->ep.name = pdata->ep[i].name; | ||
1916 | ep->ep.maxpacket = pdata->ep[i].fifo_size; | ||
1917 | ep->udc = &the_udc; | ||
1918 | INIT_LIST_HEAD(&ep->queue); | ||
1919 | ep->fifo_size = pdata->ep[i].fifo_size; | ||
1920 | ep->nr_banks = pdata->ep[i].nr_banks; | ||
1921 | ep->index = pdata->ep[i].index; | ||
1922 | ep->can_dma = pdata->ep[i].can_dma; | ||
1923 | ep->can_isoc = pdata->ep[i].can_isoc; | ||
1922 | 1924 | ||
1923 | list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); | 1925 | list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); |
1924 | } | 1926 | } |
@@ -1937,7 +1939,7 @@ static int __init usba_udc_probe(struct platform_device *pdev) | |||
1937 | goto err_device_add; | 1939 | goto err_device_add; |
1938 | } | 1940 | } |
1939 | 1941 | ||
1940 | if (pdata && pdata->vbus_pin >= 0) { | 1942 | if (pdata->vbus_pin >= 0) { |
1941 | if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) { | 1943 | if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) { |
1942 | udc->vbus_pin = pdata->vbus_pin; | 1944 | udc->vbus_pin = pdata->vbus_pin; |
1943 | 1945 | ||
@@ -1957,7 +1959,7 @@ static int __init usba_udc_probe(struct platform_device *pdev) | |||
1957 | } | 1959 | } |
1958 | 1960 | ||
1959 | usba_init_debugfs(udc); | 1961 | usba_init_debugfs(udc); |
1960 | for (i = 1; i < ARRAY_SIZE(usba_ep); i++) | 1962 | for (i = 1; i < pdata->num_ep; i++) |
1961 | usba_ep_init_debugfs(udc, &usba_ep[i]); | 1963 | usba_ep_init_debugfs(udc, &usba_ep[i]); |
1962 | 1964 | ||
1963 | return 0; | 1965 | return 0; |
@@ -1965,6 +1967,8 @@ static int __init usba_udc_probe(struct platform_device *pdev) | |||
1965 | err_device_add: | 1967 | err_device_add: |
1966 | free_irq(irq, udc); | 1968 | free_irq(irq, udc); |
1967 | err_request_irq: | 1969 | err_request_irq: |
1970 | kfree(usba_ep); | ||
1971 | err_alloc_ep: | ||
1968 | iounmap(udc->fifo); | 1972 | iounmap(udc->fifo); |
1969 | err_map_fifo: | 1973 | err_map_fifo: |
1970 | iounmap(udc->regs); | 1974 | iounmap(udc->regs); |
@@ -1982,10 +1986,11 @@ static int __exit usba_udc_remove(struct platform_device *pdev) | |||
1982 | { | 1986 | { |
1983 | struct usba_udc *udc; | 1987 | struct usba_udc *udc; |
1984 | int i; | 1988 | int i; |
1989 | struct usba_platform_data *pdata = pdev->dev.platform_data; | ||
1985 | 1990 | ||
1986 | udc = platform_get_drvdata(pdev); | 1991 | udc = platform_get_drvdata(pdev); |
1987 | 1992 | ||
1988 | for (i = 1; i < ARRAY_SIZE(usba_ep); i++) | 1993 | for (i = 1; i < pdata->num_ep; i++) |
1989 | usba_ep_cleanup_debugfs(&usba_ep[i]); | 1994 | usba_ep_cleanup_debugfs(&usba_ep[i]); |
1990 | usba_cleanup_debugfs(udc); | 1995 | usba_cleanup_debugfs(udc); |
1991 | 1996 | ||
diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h index 7597b0bd2f01..3fea2004f7db 100644 --- a/include/asm-avr32/arch-at32ap/board.h +++ b/include/asm-avr32/arch-at32ap/board.h | |||
@@ -38,9 +38,7 @@ struct platform_device * | |||
38 | at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, | 38 | at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, |
39 | unsigned long fbmem_start, unsigned long fbmem_len); | 39 | unsigned long fbmem_start, unsigned long fbmem_len); |
40 | 40 | ||
41 | struct usba_platform_data { | 41 | struct usba_platform_data; |
42 | int vbus_pin; | ||
43 | }; | ||
44 | struct platform_device * | 42 | struct platform_device * |
45 | at32_add_device_usba(unsigned int id, struct usba_platform_data *data); | 43 | at32_add_device_usba(unsigned int id, struct usba_platform_data *data); |
46 | 44 | ||
diff --git a/include/linux/usb/atmel_usba_udc.h b/include/linux/usb/atmel_usba_udc.h new file mode 100644 index 000000000000..6311fa2d9f82 --- /dev/null +++ b/include/linux/usb/atmel_usba_udc.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Platform data definitions for Atmel USBA gadget driver. | ||
3 | */ | ||
4 | #ifndef __LINUX_USB_USBA_H | ||
5 | #define __LINUX_USB_USBA_H | ||
6 | |||
7 | struct usba_ep_data { | ||
8 | char *name; | ||
9 | int index; | ||
10 | int fifo_size; | ||
11 | int nr_banks; | ||
12 | int can_dma; | ||
13 | int can_isoc; | ||
14 | }; | ||
15 | |||
16 | struct usba_platform_data { | ||
17 | int vbus_pin; | ||
18 | int num_ep; | ||
19 | struct usba_ep_data ep[0]; | ||
20 | }; | ||
21 | |||
22 | #endif /* __LINUX_USB_USBA_H */ | ||