[Gta04-owner] [PATCH 3.2] twl4030_usb: export status of id pin via sysfs

Andreas Kemnade andreas at kemnade.info
Fri Mar 30 10:35:02 CEST 2012


A file in sysfs is created:
/sys/bus/platform/devices/twl4030_usb/id
it shows 440k, 200k, 102k, floating or GND.

If none of the corresponding bits are set, unknown is shown.

Signed-off-by: Andreas Kemnade <andreas at kemnade.info>
---
 drivers/usb/otg/twl4030-usb.c |   40 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index b0a6a03..804ae3a 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -499,6 +499,43 @@ 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;
@@ -639,6 +676,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);
 
@@ -676,6 +715,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 */
-- 
1.7.2.5



More information about the Gta04-owner mailing list