aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/chipidea/otg_fsm.c
diff options
context:
space:
mode:
authorLi Jun <b47624@freescale.com>2014-04-23 03:56:51 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-04-24 15:56:35 -0400
commit15f75defacd3da412d4c9823d4a9c9f410923766 (patch)
tree297e0ef987b934927671eeba88eb67339dba471b /drivers/usb/chipidea/otg_fsm.c
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/otg_fsm.c')
-rw-r--r--drivers/usb/chipidea/otg_fsm.c173
1 files changed, 173 insertions, 0 deletions
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
46 return timer; 46 return timer;
47} 47}
48 48
49/* Add for otg: interact with user space app */
50static ssize_t
51get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
52{
53 char *next;
54 unsigned size, t;
55 struct ci_hdrc *ci = dev_get_drvdata(dev);
56
57 next = buf;
58 size = PAGE_SIZE;
59 t = scnprintf(next, size, "%d\n", ci->fsm.a_bus_req);
60 size -= t;
61 next += t;
62
63 return PAGE_SIZE - size;
64}
65
66static ssize_t
67set_a_bus_req(struct device *dev, struct device_attribute *attr,
68 const char *buf, size_t count)
69{
70 struct ci_hdrc *ci = dev_get_drvdata(dev);
71
72 if (count > 2)
73 return -1;
74
75 mutex_lock(&ci->fsm.lock);
76 if (buf[0] == '0') {
77 ci->fsm.a_bus_req = 0;
78 } else if (buf[0] == '1') {
79 /* If a_bus_drop is TRUE, a_bus_req can't be set */
80 if (ci->fsm.a_bus_drop) {
81 mutex_unlock(&ci->fsm.lock);
82 return count;
83 }
84 ci->fsm.a_bus_req = 1;
85 }
86
87 disable_irq_nosync(ci->irq);
88 queue_work(ci->wq, &ci->work);
89 mutex_unlock(&ci->fsm.lock);
90
91 return count;
92}
93static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req, set_a_bus_req);
94
95static ssize_t
96get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf)
97{
98 char *next;
99 unsigned size, t;
100 struct ci_hdrc *ci = dev_get_drvdata(dev);
101
102 next = buf;
103 size = PAGE_SIZE;
104 t = scnprintf(next, size, "%d\n", ci->fsm.a_bus_drop);
105 size -= t;
106 next += t;
107
108 return PAGE_SIZE - size;
109}
110
111static ssize_t
112set_a_bus_drop(struct device *dev, struct device_attribute *attr,
113 const char *buf, size_t count)
114{
115 struct ci_hdrc *ci = dev_get_drvdata(dev);
116
117 if (count > 2)
118 return -1;
119
120 mutex_lock(&ci->fsm.lock);
121 if (buf[0] == '0') {
122 ci->fsm.a_bus_drop = 0;
123 } else if (buf[0] == '1') {
124 ci->fsm.a_bus_drop = 1;
125 ci->fsm.a_bus_req = 0;
126 }
127
128 disable_irq_nosync(ci->irq);
129 queue_work(ci->wq, &ci->work);
130 mutex_unlock(&ci->fsm.lock);
131
132 return count;
133}
134static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR, get_a_bus_drop,
135 set_a_bus_drop);
136
137static ssize_t
138get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
139{
140 char *next;
141 unsigned size, t;
142 struct ci_hdrc *ci = dev_get_drvdata(dev);
143
144 next = buf;
145 size = PAGE_SIZE;
146 t = scnprintf(next, size, "%d\n", ci->fsm.b_bus_req);
147 size -= t;
148 next += t;
149
150 return PAGE_SIZE - size;
151}
152
153static ssize_t
154set_b_bus_req(struct device *dev, struct device_attribute *attr,
155 const char *buf, size_t count)
156{
157 struct ci_hdrc *ci = dev_get_drvdata(dev);
158
159 if (count > 2)
160 return -1;
161
162 mutex_lock(&ci->fsm.lock);
163 if (buf[0] == '0')
164 ci->fsm.b_bus_req = 0;
165 else if (buf[0] == '1')
166 ci->fsm.b_bus_req = 1;
167
168 disable_irq_nosync(ci->irq);
169 queue_work(ci->wq, &ci->work);
170 mutex_unlock(&ci->fsm.lock);
171
172 return count;
173}
174static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUSR, get_b_bus_req, set_b_bus_req);
175
176static ssize_t
177set_a_clr_err(struct device *dev, struct device_attribute *attr,
178 const char *buf, size_t count)
179{
180 struct ci_hdrc *ci = dev_get_drvdata(dev);
181
182 if (count > 2)
183 return -1;
184
185 mutex_lock(&ci->fsm.lock);
186 if (buf[0] == '1')
187 ci->fsm.a_clr_err = 1;
188
189 disable_irq_nosync(ci->irq);
190 queue_work(ci->wq, &ci->work);
191 mutex_unlock(&ci->fsm.lock);
192
193 return count;
194}
195static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err);
196
197static struct attribute *inputs_attrs[] = {
198 &dev_attr_a_bus_req.attr,
199 &dev_attr_a_bus_drop.attr,
200 &dev_attr_b_bus_req.attr,
201 &dev_attr_a_clr_err.attr,
202 NULL,
203};
204
205static struct attribute_group inputs_attr_group = {
206 .name = "inputs",
207 .attrs = inputs_attrs,
208};
209
49/* 210/*
50 * Add timer to active timer list 211 * Add timer to active timer list
51 */ 212 */
@@ -676,6 +837,13 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci)
676 return retval; 837 return retval;
677 } 838 }
678 839
840 retval = sysfs_create_group(&ci->dev->kobj, &inputs_attr_group);
841 if (retval < 0) {
842 dev_dbg(ci->dev,
843 "Can't register sysfs attr group: %d\n", retval);
844 return retval;
845 }
846
679 /* Enable A vbus valid irq */ 847 /* Enable A vbus valid irq */
680 hw_write_otgsc(ci, OTGSC_AVVIE, OTGSC_AVVIE); 848 hw_write_otgsc(ci, OTGSC_AVVIE, OTGSC_AVVIE);
681 849
@@ -690,3 +858,8 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci)
690 858
691 return 0; 859 return 0;
692} 860}
861
862void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci)
863{
864 sysfs_remove_group(&ci->dev->kobj, &inputs_attr_group);
865}