X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=drivers%2Fusb%2Fotg%2Ftwl4030-usb.c;h=f5904763ac9f4ca296da3abd3681d79902faef24;hp=14f66c35862938adc5817c123233521c9ca1f925;hb=c91286a490a8b02ebd852e24a7c9fda9d37aa43d;hpb=73bcbac130a59f236ae78ed70ef7a05b45caa19e diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 14f66c358629..f5904763ac9f 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -281,6 +281,9 @@ static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl) dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", status, status, linkstat); + if (twl->otg.last_event == linkstat) + return linkstat; + twl->otg.last_event = linkstat; /* REVISIT this assumes host and peripheral controllers @@ -497,9 +500,47 @@ static ssize_t twl4030_usb_vbus_show(struct device *dev, } static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL); +static ssize_t twl4030_usb_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + int n = 0; + struct twl4030_usb *twl = dev_get_drvdata(dev); + twl4030_i2c_access(twl, 1); + ret = twl4030_usb_read(twl, ULPI_OTG_CTRL); + if ((ret < 0) || (!(ret & ULPI_OTG_ID_PULLUP))) { + /* + * enable ID pullup so that the id pin state can be measured, + * seems to be disabled sometimes for some reasons + */ + dev_dbg(dev, "ULPI_OTG_ID_PULLUP not set (%x)\n", ret); + twl4030_usb_set_bits(twl, ULPI_OTG_CTRL, ULPI_OTG_ID_PULLUP); + mdelay(100); + } + ret = twl4030_usb_read(twl, ID_STATUS); + twl4030_i2c_access(twl, 0); + if (ret < 0) + return ret; + if (ret & ID_RES_FLOAT) + n = scnprintf(buf, PAGE_SIZE, "%s\n", "floating"); + else if (ret & ID_RES_440K) + n = scnprintf(buf, PAGE_SIZE, "%s\n", "440k"); + else if (ret & ID_RES_200K) + n = scnprintf(buf, PAGE_SIZE, "%s\n", "200k"); + else if (ret & ID_RES_102K) + n = scnprintf(buf, PAGE_SIZE, "%s\n", "102k"); + else if (ret & ID_RES_GND) + n = scnprintf(buf, PAGE_SIZE, "%s\n", "GND"); + else + n = scnprintf(buf, PAGE_SIZE, "unknown: id=0x%x\n", ret); + return n; +} +static DEVICE_ATTR(id, 0444, twl4030_usb_id_show, NULL); + static irqreturn_t twl4030_usb_irq(int irq, void *_twl) { struct twl4030_usb *twl = _twl; + int status_old = twl->otg.last_event; int status; status = twl4030_usb_linkstat(twl); @@ -515,12 +556,8 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) * USB_LINK_VBUS state. musb_hdrc won't care until it * starts to handle softconnect right. */ - if (status == USB_EVENT_NONE) - twl4030_phy_suspend(twl, 0); - else - twl4030_phy_resume(twl); - - atomic_notifier_call_chain(&twl->otg.notifier, status, + if (status != status_old) + atomic_notifier_call_chain(&twl->otg.notifier, status, twl->otg.gadget); } sysfs_notify(&twl->dev->kobj, NULL, "vbus"); @@ -532,19 +569,18 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl) { int status; - status = twl4030_usb_linkstat(twl); - if (status >= 0) { - if (status == USB_EVENT_NONE) { - __twl4030_phy_power(twl, 0); - twl->asleep = 1; - } else { - __twl4030_phy_resume(twl); - twl->asleep = 0; - } + /* + * Start in sleep state, we'll get otg.set_suspend(false) call + * and power up when musb runtime_pm enable kicks in. + */ + __twl4030_phy_power(twl, 0); + twl->asleep = 1; + status = twl4030_usb_linkstat(twl); + if (status >= 0 && status != USB_EVENT_NONE) atomic_notifier_call_chain(&twl->otg.notifier, status, - twl->otg.gadget); - } + twl->otg.gadget); + sysfs_notify(&twl->dev->kobj, NULL, "vbus"); } @@ -631,6 +667,8 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) platform_set_drvdata(pdev, twl); if (device_create_file(&pdev->dev, &dev_attr_vbus)) dev_warn(&pdev->dev, "could not create sysfs file\n"); + if (device_create_file(&pdev->dev, &dev_attr_id)) + dev_warn(&pdev->dev, "could not create sysfs file\n"); ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier); @@ -653,9 +691,6 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) return status; } - /* Power down phy or make it work according to - * current link state. - */ twl4030_usb_phy_init(twl); dev_info(&pdev->dev, "Initialized TWL4030 USB module\n"); @@ -668,6 +703,7 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) int val; free_irq(twl->irq, twl); + device_remove_file(twl->dev, &dev_attr_id); device_remove_file(twl->dev, &dev_attr_vbus); /* set transceiver mode to power on defaults */