diff options
author | Sakethram Bommisetti <sakethram.bommisetti@stericsson.com> | 2011-12-06 10:50:32 +0530 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@stericsson.com> | 2012-05-22 11:03:12 +0200 |
commit | 9d4c65b12c05826f8380d6ed80b96a0b7b484b41 (patch) | |
tree | 6de5b52cefb4bad55d7fa356cb8f8fbda6c6a13a | |
parent | 9107c03b38b67ae82f905fecf582a9501fb48036 (diff) |
[Android]:USB:ab850:Correcting USB sysfs interface
The USB serial number which is exposed via sysfs is exposed at
the /sys/serial_number which is improper location. Sysfs
entries should be exposed from /sys/devices/platform/
using a kobject from the device struct.
Added a new sysfs entry for delaying the enumeration.
User space has to update the values in kernel space and then
the enumeration will start.
ST-Ericsson Linux next: NA
ST-Ericsson ID: 350337
ST-Ericsson FOSS-OUT ID: Trivial
Change-Id: I93dc5e1fe7bd51e53aa767f7832a4f8e77fe1317
Signed-off-by: Sakethram Bommisetti <sakethram.bommisetti@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/41158
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/42051
Reviewed-by: QABUILD
Reviewed-by: Rabin VINCENT <rabin.vincent@stericsson.com>
Tested-by: Axel FAGERSTEDT <axel.fagerstedt@stericsson.com>
-rw-r--r-- | drivers/usb/otg/ab8500-usb.c | 223 |
1 files changed, 123 insertions, 100 deletions
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c index f51ac3fe836..5c5b6a9dcdb 100644 --- a/drivers/usb/otg/ab8500-usb.c +++ b/drivers/usb/otg/ab8500-usb.c @@ -128,7 +128,7 @@ struct ab8500_usb { struct regulator *v_ulpi; struct abx500_usbgpio_platform_data *usb_gpio; struct delayed_work work_usb_workaround; - struct kobject *serial_number_kobj; + bool sysfs_flag; }; static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x) @@ -330,75 +330,77 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab) lsts = (reg >> 3) & 0x0F; - switch (lsts) { - case USB_LINK_ACA_RID_B: - event = USB_EVENT_RIDB; - case USB_LINK_NOT_CONFIGURED: - case USB_LINK_RESERVED: - case USB_LINK_NOT_VALID_LINK: - if (ab->mode == USB_HOST) - ab8500_usb_host_phy_dis(ab); - else if (ab->mode == USB_PERIPHERAL) - ab8500_usb_peri_phy_dis(ab); - ab->mode = USB_IDLE; - ab->phy.otg.default_a = false; - ab->vbus_draw = 0; - if (event != USB_EVENT_RIDB) - event = USB_EVENT_NONE; - break; - case USB_LINK_ACA_RID_C_NM: - case USB_LINK_ACA_RID_C_HS: - case USB_LINK_ACA_RID_C_HS_CHIRP: - event = USB_EVENT_RIDC; - case USB_LINK_STD_HOST_NC: - case USB_LINK_STD_HOST_C_NS: - case USB_LINK_STD_HOST_C_S: - case USB_LINK_HOST_CHG_NM: - case USB_LINK_HOST_CHG_HS: - case USB_LINK_HOST_CHG_HS_CHIRP: - if (ab->mode == USB_HOST) { - ab->mode = USB_PERIPHERAL; - ab8500_usb_host_phy_dis(ab); - ux500_restore_context(); - ab8500_usb_peri_phy_en(ab); - } - if (ab->mode == USB_IDLE) { - ab->mode = USB_PERIPHERAL; - ux500_restore_context(); - ab8500_usb_peri_phy_en(ab); - } - if (event != USB_EVENT_RIDC) - event = USB_EVENT_VBUS; - break; - - case USB_LINK_ACA_RID_A: - event = USB_EVENT_RIDA; - case USB_LINK_HM_IDGND: - if (ab->mode == USB_PERIPHERAL) { - ab->mode = USB_HOST; - ab8500_usb_peri_phy_dis(ab); - ux500_restore_context(); - ab8500_usb_host_phy_en(ab); + if (!(ab->sysfs_flag)) { + switch (lsts) { + case USB_LINK_ACA_RID_B: + event = USB_EVENT_RIDB; + case USB_LINK_NOT_CONFIGURED: + case USB_LINK_RESERVED: + case USB_LINK_NOT_VALID_LINK: + if (ab->mode == USB_HOST) + ab8500_usb_host_phy_dis(ab); + else if (ab->mode == USB_PERIPHERAL) + ab8500_usb_peri_phy_dis(ab); + ab->mode = USB_IDLE; + ab->phy.otg.default_a = false; + ab->vbus_draw = 0; + if (event != USB_EVENT_RIDB) + event = USB_EVENT_NONE; + break; + case USB_LINK_ACA_RID_C_NM: + case USB_LINK_ACA_RID_C_HS: + case USB_LINK_ACA_RID_C_HS_CHIRP: + event = USB_EVENT_RIDC; + case USB_LINK_STD_HOST_NC: + case USB_LINK_STD_HOST_C_NS: + case USB_LINK_STD_HOST_C_S: + case USB_LINK_HOST_CHG_NM: + case USB_LINK_HOST_CHG_HS: + case USB_LINK_HOST_CHG_HS_CHIRP: + if (ab->mode == USB_HOST) { + ab->mode = USB_PERIPHERAL; + ab8500_usb_host_phy_dis(ab); + ux500_restore_context(); + ab8500_usb_peri_phy_en(ab); + } + if (ab->mode == USB_IDLE) { + ab->mode = USB_PERIPHERAL; + ux500_restore_context(); + ab8500_usb_peri_phy_en(ab); + } + if (event != USB_EVENT_RIDC) + event = USB_EVENT_VBUS; + break; + + case USB_LINK_ACA_RID_A: + event = USB_EVENT_RIDA; + case USB_LINK_HM_IDGND: + if (ab->mode == USB_PERIPHERAL) { + ab->mode = USB_HOST; + ab8500_usb_peri_phy_dis(ab); + ux500_restore_context(); + ab8500_usb_host_phy_en(ab); + } + if (ab->mode == USB_IDLE) { + ab->mode = USB_HOST; + ux500_restore_context(); + ab8500_usb_host_phy_en(ab); + } + ab->phy.otg->default_a = true; + if (event != USB_EVENT_RIDA) + event = USB_EVENT_ID; + break; + + case USB_LINK_DEDICATED_CHG: + /* TODO: vbus_draw */ + ab->mode = USB_DEDICATED_CHG; + event = USB_EVENT_CHARGER; + break; } - if (ab->mode == USB_IDLE) { - ab->mode = USB_HOST; - ux500_restore_context(); - ab8500_usb_host_phy_en(ab); - } - ab->phy.otg->default_a = true; - if (event != USB_EVENT_RIDA) - event = USB_EVENT_ID; - break; - - case USB_LINK_DEDICATED_CHG: - /* TODO: vbus_draw */ - ab->mode = USB_DEDICATED_CHG; - event = USB_EVENT_CHARGER; - break; + atomic_notifier_call_chain(&ab->phy.notifier, event, + &ab->vbus_draw); } - atomic_notifier_call_chain(&ab->phy.notifier, event, &ab->vbus_draw); - return 0; } @@ -579,8 +581,6 @@ static int ab8500_usb_boot_detect(struct ab8500_usb *ab) AB8500_BIT_PHY_CTRL_HOST_EN, 0); - ab8500_usb_link_status_update(ab); - return 0; } @@ -713,8 +713,9 @@ irq_fail: } /* Sys interfaces */ -static ssize_t usb_serial_number - (struct kobject *kobj, struct attribute *attr, char *buf) +static ssize_t +serial_number_show(struct device *dev, + struct device_attribute *attr, char *buf) { u32 bufer[5]; void __iomem *backup_ram = NULL; @@ -734,27 +735,60 @@ static ssize_t usb_serial_number iounmap(backup_ram); } else - printk(KERN_ERR "$$ ioremap failed\n"); + dev_err(dev, "$$\n"); + + return strlen(buf); +} + +static DEVICE_ATTR(serial_number, 0644, serial_number_show, NULL); + +static ssize_t +boot_time_device_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ab8500_usb *ab = dev_get_drvdata(dev); + u8 val = ab->sysfs_flag; + + snprintf(buf, 2, "%d", val); return strlen(buf); } -static struct attribute usb_serial_number_attribute = \ - {.name = "serial_number", .mode = S_IRUGO}; +static ssize_t +boot_time_device_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t n) +{ + struct ab8500_usb *ab = dev_get_drvdata(dev); + + ab->sysfs_flag = false; + + ab8500_usb_link_status_update(ab); + + return n; +} +static DEVICE_ATTR(boot_time_device, 0644, + boot_time_device_show, boot_time_device_store); -static struct attribute *serial_number[] = { - &usb_serial_number_attribute, + +static struct attribute *ab8500_usb_attributes[] = { + &dev_attr_serial_number.attr, + &dev_attr_boot_time_device.attr, NULL }; - -const struct sysfs_ops usb_sysfs_ops = { - .show = usb_serial_number, +static const struct attribute_group ab8500_attr_group = { + .attrs = ab8500_usb_attributes, }; -static struct kobj_type ktype_serial_number = { - .sysfs_ops = &usb_sysfs_ops, - .default_attrs = serial_number, -}; +static int ab8500_create_sysfsentries(struct ab8500_usb *ab) +{ + int err; + + err = sysfs_create_group(&ab->dev->kobj, &ab8500_attr_group); + if (err) + sysfs_remove_group(&ab->dev->kobj, &ab8500_attr_group); + + return err; +} static int __devinit ab8500_usb_probe(struct platform_device *pdev) { @@ -798,9 +832,10 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev) otg->set_host = ab8500_usb_set_host; otg->set_peripheral = ab8500_usb_set_peripheral; ab->usb_gpio = ab8500_pdata->usb; + ab->sysfs_flag = true; platform_set_drvdata(pdev, ab); - + dev_set_drvdata(ab->dev, ab); ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier); /* v1: Wait for link status to become stable. @@ -882,22 +917,6 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev) /* Needed to enable ID detection. */ ab8500_usb_wd_workaround(ab); - ab->serial_number_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); - - if (ab->serial_number_kobj == NULL) - ret = -ENOMEM; - ab->serial_number_kobj->ktype = &ktype_serial_number; - kobject_init(ab->serial_number_kobj, ab->serial_number_kobj->ktype); - - ret = kobject_set_name(ab->serial_number_kobj, "usb_serial_number"); - if (ret) - kfree(ab->serial_number_kobj); - - ret = kobject_add(ab->serial_number_kobj, NULL, "usb_serial_number"); - if (ret) - kfree(ab->serial_number_kobj); - - err = ab->usb_gpio->get(ab->dev); if (err < 0) goto fail3; @@ -912,6 +931,10 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev) if (err < 0) goto fail3; + err = ab8500_create_sysfsentries(ab); + if (err) + goto fail3; + return 0; fail3: ab8500_usb_irq_free(ab); |