aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/chipidea
diff options
context:
space:
mode:
authorLi Jun2014-04-23 15:56:51 +0800
committerGreg Kroah-Hartman2014-04-24 12:56:35 -0700
commit15f75defacd3da412d4c9823d4a9c9f410923766 (patch)
tree297e0ef987b934927671eeba88eb67339dba471b /drivers/usb/chipidea
parent4dcf720c5d40b27c916e7115ad75b335c9c1e264 (diff)
usb: chipidea: add sys inputs for OTG fsm input
This patch adds sys input to control and show OTG fsm inputs by application, user can do host and preipheral role switch by change these inputs. Signed-off-by: Peter Chen <peter.chen@freescale.com> Signed-off-by: Li Jun <b47624@freescale.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/chipidea')
-rw-r--r--drivers/usb/chipidea/otg.c2
-rw-r--r--drivers/usb/chipidea/otg_fsm.c173
-rw-r--r--drivers/usb/chipidea/otg_fsm.h6
3 files changed, 181 insertions, 0 deletions
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
index 38e340cba1f9..a048b08b9d4d 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -141,4 +141,6 @@ void ci_hdrc_otg_destroy(struct ci_hdrc *ci)
/* Disable all OTG irq and clear status */
hw_write_otgsc(ci, OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS,
OTGSC_INT_STATUS_BITS);
+ if (ci_otg_is_fsm_mode(ci))
+ ci_hdrc_otg_fsm_remove(ci);
}
diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c
index 67902a16cb74..8d4c33dea12e 100644
--- a/drivers/usb/chipidea/otg_fsm.c
+++ b/drivers/usb/chipidea/otg_fsm.c
@@ -46,6 +46,167 @@ static struct ci_otg_fsm_timer *otg_timer_initializer
return timer;
}
+/* Add for otg: interact with user space app */
+static ssize_t
+get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ char *next;
+ unsigned size, t;
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+
+ next = buf;
+ size = PAGE_SIZE;
+ t = scnprintf(next, size, "%d\n", ci->fsm.a_bus_req);
+ size -= t;
+ next += t;
+
+ return PAGE_SIZE - size;
+}
+
+static ssize_t
+set_a_bus_req(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+
+ if (count > 2)
+ return -1;
+
+ mutex_lock(&ci->fsm.lock);
+ if (buf[0] == '0') {
+ ci->fsm.a_bus_req = 0;
+ } else if (buf[0] == '1') {
+ /* If a_bus_drop is TRUE, a_bus_req can't be set */
+ if (ci->fsm.a_bus_drop) {
+ mutex_unlock(&ci->fsm.lock);
+ return count;
+ }
+ ci->fsm.a_bus_req = 1;
+ }
+
+ disable_irq_nosync(ci->irq);
+ queue_work(ci->wq, &ci->work);
+ mutex_unlock(&ci->fsm.lock);
+
+ return count;
+}
+static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req, set_a_bus_req);
+
+static ssize_t
+get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ char *next;
+ unsigned size, t;
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+
+ next = buf;
+ size = PAGE_SIZE;
+ t = scnprintf(next, size, "%d\n", ci->fsm.a_bus_drop);
+ size -= t;
+ next += t;
+
+ return PAGE_SIZE - size;
+}
+
+static ssize_t
+set_a_bus_drop(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+
+ if (count > 2)
+ return -1;
+
+ mutex_lock(&ci->fsm.lock);
+ if (buf[0] == '0') {
+ ci->fsm.a_bus_drop = 0;
+ } else if (buf[0] == '1') {
+ ci->fsm.a_bus_drop = 1;
+ ci->fsm.a_bus_req = 0;
+ }
+
+ disable_irq_nosync(ci->irq);
+ queue_work(ci->wq, &ci->work);
+ mutex_unlock(&ci->fsm.lock);
+
+ return count;
+}
+static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR, get_a_bus_drop,
+ set_a_bus_drop);
+
+static ssize_t
+get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ char *next;
+ unsigned size, t;
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+
+ next = buf;
+ size = PAGE_SIZE;
+ t = scnprintf(next, size, "%d\n", ci->fsm.b_bus_req);
+ size -= t;
+ next += t;
+
+ return PAGE_SIZE - size;
+}
+
+static ssize_t
+set_b_bus_req(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+
+ if (count > 2)
+ return -1;
+
+ mutex_lock(&ci->fsm.lock);
+ if (buf[0] == '0')
+ ci->fsm.b_bus_req = 0;
+ else if (buf[0] == '1')
+ ci->fsm.b_bus_req = 1;
+
+ disable_irq_nosync(ci->irq);
+ queue_work(ci->wq, &ci->work);
+ mutex_unlock(&ci->fsm.lock);
+
+ return count;
+}
+static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUSR, get_b_bus_req, set_b_bus_req);
+
+static ssize_t
+set_a_clr_err(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+
+ if (count > 2)
+ return -1;
+
+ mutex_lock(&ci->fsm.lock);
+ if (buf[0] == '1')
+ ci->fsm.a_clr_err = 1;
+
+ disable_irq_nosync(ci->irq);
+ queue_work(ci->wq, &ci->work);
+ mutex_unlock(&ci->fsm.lock);
+
+ return count;
+}
+static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err);
+
+static struct attribute *inputs_attrs[] = {
+ &dev_attr_a_bus_req.attr,
+ &dev_attr_a_bus_drop.attr,
+ &dev_attr_b_bus_req.attr,
+ &dev_attr_a_clr_err.attr,
+ NULL,
+};
+
+static struct attribute_group inputs_attr_group = {
+ .name = "inputs",
+ .attrs = inputs_attrs,
+};
+
/*
* Add timer to active timer list
*/
@@ -676,6 +837,13 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci)
return retval;
}
+ retval = sysfs_create_group(&ci->dev->kobj, &inputs_attr_group);
+ if (retval < 0) {
+ dev_dbg(ci->dev,
+ "Can't register sysfs attr group: %d\n", retval);
+ return retval;
+ }
+
/* Enable A vbus valid irq */
hw_write_otgsc(ci, OTGSC_AVVIE, OTGSC_AVVIE);
@@ -690,3 +858,8 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci)
return 0;
}
+
+void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci)
+{
+ sysfs_remove_group(&ci->dev->kobj, &inputs_attr_group);
+}
diff --git a/drivers/usb/chipidea/otg_fsm.h b/drivers/usb/chipidea/otg_fsm.h
index 6ec8247d8179..94c085f456a9 100644
--- a/drivers/usb/chipidea/otg_fsm.h
+++ b/drivers/usb/chipidea/otg_fsm.h
@@ -95,6 +95,7 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci);
int ci_otg_fsm_work(struct ci_hdrc *ci);
irqreturn_t ci_otg_fsm_irq(struct ci_hdrc *ci);
void ci_hdrc_otg_fsm_start(struct ci_hdrc *ci);
+void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci);
#else
@@ -118,6 +119,11 @@ static inline void ci_hdrc_otg_fsm_start(struct ci_hdrc *ci)
}
+static inline void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci)
+{
+
+}
+
#endif
#endif /* __DRIVERS_USB_CHIPIDEA_OTG_FSM_H */