aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2011-03-07 02:41:59 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-03-07 15:23:22 -0500
commita74022a55e44fe2044ac3660452cafecb300aece (patch)
treeebff5a97a61c4e5762a042a515459469993ed7e1
parent09173b589d547c002b6a2b560e150c4d7bb56c99 (diff)
USB: s3c2410_udc: Add common implementation for GPIO controlled pullups
Currently all boards using the s3c2410_udc driver use a GPIO to control the state of the pullup, as a result the same code is reimplemented in each board file. This patch adds support for using a GPIO to control the pullup state to the udc driver, so the boards can use a common implementation. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--arch/arm/plat-s3c24xx/include/plat/udc.h4
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c60
2 files changed, 55 insertions, 9 deletions
diff --git a/arch/arm/plat-s3c24xx/include/plat/udc.h b/arch/arm/plat-s3c24xx/include/plat/udc.h
index 546bb4008f49..80457c6414aa 100644
--- a/arch/arm/plat-s3c24xx/include/plat/udc.h
+++ b/arch/arm/plat-s3c24xx/include/plat/udc.h
@@ -27,6 +27,10 @@ enum s3c2410_udc_cmd_e {
27struct s3c2410_udc_mach_info { 27struct s3c2410_udc_mach_info {
28 void (*udc_command)(enum s3c2410_udc_cmd_e); 28 void (*udc_command)(enum s3c2410_udc_cmd_e);
29 void (*vbus_draw)(unsigned int ma); 29 void (*vbus_draw)(unsigned int ma);
30
31 unsigned int pullup_pin;
32 unsigned int pullup_pin_inverted;
33
30 unsigned int vbus_pin; 34 unsigned int vbus_pin;
31 unsigned char vbus_pin_inverted; 35 unsigned char vbus_pin_inverted;
32}; 36};
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index 2b025200a69a..6d8b04061d5d 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1481,7 +1481,9 @@ static int s3c2410_udc_set_pullup(struct s3c2410_udc *udc, int is_on)
1481{ 1481{
1482 dprintk(DEBUG_NORMAL, "%s()\n", __func__); 1482 dprintk(DEBUG_NORMAL, "%s()\n", __func__);
1483 1483
1484 if (udc_info && udc_info->udc_command) { 1484 if (udc_info && (udc_info->udc_command ||
1485 gpio_is_valid(udc_info->pullup_pin))) {
1486
1485 if (is_on) 1487 if (is_on)
1486 s3c2410_udc_enable(udc); 1488 s3c2410_udc_enable(udc);
1487 else { 1489 else {
@@ -1558,6 +1560,32 @@ static const struct usb_gadget_ops s3c2410_ops = {
1558 .vbus_draw = s3c2410_vbus_draw, 1560 .vbus_draw = s3c2410_vbus_draw,
1559}; 1561};
1560 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
1561/*------------------------- gadget driver handling---------------------------*/ 1589/*------------------------- gadget driver handling---------------------------*/
1562/* 1590/*
1563 * s3c2410_udc_disable 1591 * s3c2410_udc_disable
@@ -1579,8 +1607,7 @@ static void s3c2410_udc_disable(struct s3c2410_udc *dev)
1579 udc_write(0x1F, S3C2410_UDC_EP_INT_REG); 1607 udc_write(0x1F, S3C2410_UDC_EP_INT_REG);
1580 1608
1581 /* Good bye, cruel world */ 1609 /* Good bye, cruel world */
1582 if (udc_info && udc_info->udc_command) 1610 s3c2410_udc_command(S3C2410_UDC_P_DISABLE);
1583 udc_info->udc_command(S3C2410_UDC_P_DISABLE);
1584 1611
1585 /* Set speed to unknown */ 1612 /* Set speed to unknown */
1586 dev->gadget.speed = USB_SPEED_UNKNOWN; 1613 dev->gadget.speed = USB_SPEED_UNKNOWN;
@@ -1641,8 +1668,7 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev)
1641 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);
1642 1669
1643 /* time to say "hello, world" */ 1670 /* time to say "hello, world" */
1644 if (udc_info && udc_info->udc_command) 1671 s3c2410_udc_command(S3C2410_UDC_P_ENABLE);
1645 udc_info->udc_command(S3C2410_UDC_P_ENABLE);
1646} 1672}
1647 1673
1648/* 1674/*
@@ -1917,6 +1943,17 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
1917 udc->vbus = 1; 1943 udc->vbus = 1;
1918 } 1944 }
1919 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
1920 if (s3c2410_udc_debugfs_root) { 1957 if (s3c2410_udc_debugfs_root) {
1921 udc->regs_info = debugfs_create_file("registers", S_IRUGO, 1958 udc->regs_info = debugfs_create_file("registers", S_IRUGO,
1922 s3c2410_udc_debugfs_root, 1959 s3c2410_udc_debugfs_root,
@@ -1929,6 +1966,9 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
1929 1966
1930 return 0; 1967 return 0;
1931 1968
1969err_vbus_irq:
1970 if (udc_info && udc_info->vbus_pin > 0)
1971 free_irq(gpio_to_irq(udc_info->vbus_pin), udc);
1932err_gpio_claim: 1972err_gpio_claim:
1933 if (udc_info && udc_info->vbus_pin > 0) 1973 if (udc_info && udc_info->vbus_pin > 0)
1934 gpio_free(udc_info->vbus_pin); 1974 gpio_free(udc_info->vbus_pin);
@@ -1956,6 +1996,10 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
1956 1996
1957 debugfs_remove(udc->regs_info); 1997 debugfs_remove(udc->regs_info);
1958 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
1959 if (udc_info && udc_info->vbus_pin > 0) { 2003 if (udc_info && udc_info->vbus_pin > 0) {
1960 irq = gpio_to_irq(udc_info->vbus_pin); 2004 irq = gpio_to_irq(udc_info->vbus_pin);
1961 free_irq(irq, udc); 2005 free_irq(irq, udc);
@@ -1987,16 +2031,14 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
1987#ifdef CONFIG_PM 2031#ifdef CONFIG_PM
1988static 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)
1989{ 2033{
1990 if (udc_info && udc_info->udc_command) 2034 s3c2410_udc_command(S3C2410_UDC_P_DISABLE);
1991 udc_info->udc_command(S3C2410_UDC_P_DISABLE);
1992 2035
1993 return 0; 2036 return 0;
1994} 2037}
1995 2038
1996static int s3c2410_udc_resume(struct platform_device *pdev) 2039static int s3c2410_udc_resume(struct platform_device *pdev)
1997{ 2040{
1998 if (udc_info && udc_info->udc_command) 2041 s3c2410_udc_command(S3C2410_UDC_P_ENABLE);
1999 udc_info->udc_command(S3C2410_UDC_P_ENABLE);
2000 2042
2001 return 0; 2043 return 0;
2002} 2044}