aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/s3c2410_udc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/s3c2410_udc.c')
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c76
1 files changed, 66 insertions, 10 deletions
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index c2448950a8d8..6d8b04061d5d 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -902,7 +902,7 @@ static irqreturn_t s3c2410_udc_irq(int dummy, void *_dev)
902 int pwr_reg; 902 int pwr_reg;
903 int ep0csr; 903 int ep0csr;
904 int i; 904 int i;
905 u32 idx; 905 u32 idx, idx2;
906 unsigned long flags; 906 unsigned long flags;
907 907
908 spin_lock_irqsave(&dev->lock, flags); 908 spin_lock_irqsave(&dev->lock, flags);
@@ -1017,6 +1017,20 @@ static irqreturn_t s3c2410_udc_irq(int dummy, void *_dev)
1017 } 1017 }
1018 } 1018 }
1019 1019
1020 /* what else causes this interrupt? a receive! who is it? */
1021 if (!usb_status && !usbd_status && !pwr_reg && !ep0csr) {
1022 for (i = 1; i < S3C2410_ENDPOINTS; i++) {
1023 idx2 = udc_read(S3C2410_UDC_INDEX_REG);
1024 udc_write(i, S3C2410_UDC_INDEX_REG);
1025
1026 if (udc_read(S3C2410_UDC_OUT_CSR1_REG) & 0x1)
1027 s3c2410_udc_handle_ep(&dev->ep[i]);
1028
1029 /* restore index */
1030 udc_write(idx2, S3C2410_UDC_INDEX_REG);
1031 }
1032 }
1033
1020 dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", IRQ_USBD); 1034 dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", IRQ_USBD);
1021 1035
1022 /* Restore old index */ 1036 /* Restore old index */
@@ -1467,7 +1481,9 @@ static int s3c2410_udc_set_pullup(struct s3c2410_udc *udc, int is_on)
1467{ 1481{
1468 dprintk(DEBUG_NORMAL, "%s()\n", __func__); 1482 dprintk(DEBUG_NORMAL, "%s()\n", __func__);
1469 1483
1470 if (udc_info && udc_info->udc_command) { 1484 if (udc_info && (udc_info->udc_command ||
1485 gpio_is_valid(udc_info->pullup_pin))) {
1486
1471 if (is_on) 1487 if (is_on)
1472 s3c2410_udc_enable(udc); 1488 s3c2410_udc_enable(udc);
1473 else { 1489 else {
@@ -1544,6 +1560,32 @@ static const struct usb_gadget_ops s3c2410_ops = {
1544 .vbus_draw = s3c2410_vbus_draw, 1560 .vbus_draw = s3c2410_vbus_draw,
1545}; 1561};
1546 1562
1563static void s3c2410_udc_command(enum s3c2410_udc_cmd_e cmd)
1564{
1565 if (!udc_info)
1566 return;
1567
1568 if (udc_info->udc_command) {
1569 udc_info->udc_command(S3C2410_UDC_P_DISABLE);
1570 } else if (gpio_is_valid(udc_info->pullup_pin)) {
1571 int value;
1572
1573 switch (cmd) {
1574 case S3C2410_UDC_P_ENABLE:
1575 value = 1;
1576 break;
1577 case S3C2410_UDC_P_DISABLE:
1578 value = 0;
1579 break;
1580 default:
1581 return;
1582 }
1583 value ^= udc_info->pullup_pin_inverted;
1584
1585 gpio_set_value(udc_info->pullup_pin, value);
1586 }
1587}
1588
1547/*------------------------- gadget driver handling---------------------------*/ 1589/*------------------------- gadget driver handling---------------------------*/
1548/* 1590/*
1549 * s3c2410_udc_disable 1591 * s3c2410_udc_disable
@@ -1565,8 +1607,7 @@ static void s3c2410_udc_disable(struct s3c2410_udc *dev)
1565 udc_write(0x1F, S3C2410_UDC_EP_INT_REG); 1607 udc_write(0x1F, S3C2410_UDC_EP_INT_REG);
1566 1608
1567 /* Good bye, cruel world */ 1609 /* Good bye, cruel world */
1568 if (udc_info && udc_info->udc_command) 1610 s3c2410_udc_command(S3C2410_UDC_P_DISABLE);
1569 udc_info->udc_command(S3C2410_UDC_P_DISABLE);
1570 1611
1571 /* Set speed to unknown */ 1612 /* Set speed to unknown */
1572 dev->gadget.speed = USB_SPEED_UNKNOWN; 1613 dev->gadget.speed = USB_SPEED_UNKNOWN;
@@ -1627,8 +1668,7 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev)
1627 udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_EN_REG); 1668 udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_EN_REG);
1628 1669
1629 /* time to say "hello, world" */ 1670 /* time to say "hello, world" */
1630 if (udc_info && udc_info->udc_command) 1671 s3c2410_udc_command(S3C2410_UDC_P_ENABLE);
1631 udc_info->udc_command(S3C2410_UDC_P_ENABLE);
1632} 1672}
1633 1673
1634/* 1674/*
@@ -1903,6 +1943,17 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
1903 udc->vbus = 1; 1943 udc->vbus = 1;
1904 } 1944 }
1905 1945
1946 if (udc_info && !udc_info->udc_command &&
1947 gpio_is_valid(udc_info->pullup_pin)) {
1948
1949 retval = gpio_request_one(udc_info->pullup_pin,
1950 udc_info->vbus_pin_inverted ?
1951 GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
1952 "udc pullup");
1953 if (retval)
1954 goto err_vbus_irq;
1955 }
1956
1906 if (s3c2410_udc_debugfs_root) { 1957 if (s3c2410_udc_debugfs_root) {
1907 udc->regs_info = debugfs_create_file("registers", S_IRUGO, 1958 udc->regs_info = debugfs_create_file("registers", S_IRUGO,
1908 s3c2410_udc_debugfs_root, 1959 s3c2410_udc_debugfs_root,
@@ -1915,6 +1966,9 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
1915 1966
1916 return 0; 1967 return 0;
1917 1968
1969err_vbus_irq:
1970 if (udc_info && udc_info->vbus_pin > 0)
1971 free_irq(gpio_to_irq(udc_info->vbus_pin), udc);
1918err_gpio_claim: 1972err_gpio_claim:
1919 if (udc_info && udc_info->vbus_pin > 0) 1973 if (udc_info && udc_info->vbus_pin > 0)
1920 gpio_free(udc_info->vbus_pin); 1974 gpio_free(udc_info->vbus_pin);
@@ -1942,6 +1996,10 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
1942 1996
1943 debugfs_remove(udc->regs_info); 1997 debugfs_remove(udc->regs_info);
1944 1998
1999 if (udc_info && !udc_info->udc_command &&
2000 gpio_is_valid(udc_info->pullup_pin))
2001 gpio_free(udc_info->pullup_pin);
2002
1945 if (udc_info && udc_info->vbus_pin > 0) { 2003 if (udc_info && udc_info->vbus_pin > 0) {
1946 irq = gpio_to_irq(udc_info->vbus_pin); 2004 irq = gpio_to_irq(udc_info->vbus_pin);
1947 free_irq(irq, udc); 2005 free_irq(irq, udc);
@@ -1973,16 +2031,14 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
1973#ifdef CONFIG_PM 2031#ifdef CONFIG_PM
1974static int s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message) 2032static int s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message)
1975{ 2033{
1976 if (udc_info && udc_info->udc_command) 2034 s3c2410_udc_command(S3C2410_UDC_P_DISABLE);
1977 udc_info->udc_command(S3C2410_UDC_P_DISABLE);
1978 2035
1979 return 0; 2036 return 0;
1980} 2037}
1981 2038
1982static int s3c2410_udc_resume(struct platform_device *pdev) 2039static int s3c2410_udc_resume(struct platform_device *pdev)
1983{ 2040{
1984 if (udc_info && udc_info->udc_command) 2041 s3c2410_udc_command(S3C2410_UDC_P_ENABLE);
1985 udc_info->udc_command(S3C2410_UDC_P_ENABLE);
1986 2042
1987 return 0; 2043 return 0;
1988} 2044}