diff options
author | Li Jun <b47624@freescale.com> | 2014-03-17 23:09:49 -0400 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 12:02:36 -0400 |
commit | 4fd66dfc8cd648a1417d6c07d1c4e9b532b025eb (patch) | |
tree | 013fdf0c7ca09c75a0c20876fe161e685d73926c /drivers/usb/chipidea/otg_fsm.c | |
parent | b3cf01e5acd05132877c865cba91491baac97efd (diff) |
ENGR00307558-8 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: Li Jun <b47624@freescale.com>
Diffstat (limited to 'drivers/usb/chipidea/otg_fsm.c')
-rw-r--r-- | drivers/usb/chipidea/otg_fsm.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c index 5f523971ff14..fff809ca3a18 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 */ | ||
50 | static ssize_t | ||
51 | get_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 | |||
66 | static ssize_t | ||
67 | set_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 | } | ||
93 | static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req, set_a_bus_req); | ||
94 | |||
95 | static ssize_t | ||
96 | get_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 | |||
111 | static ssize_t | ||
112 | set_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 | } | ||
134 | static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR, get_a_bus_drop, | ||
135 | set_a_bus_drop); | ||
136 | |||
137 | static ssize_t | ||
138 | get_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 | |||
153 | static ssize_t | ||
154 | set_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 | } | ||
174 | static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUSR, get_b_bus_req, set_b_bus_req); | ||
175 | |||
176 | static ssize_t | ||
177 | set_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 | } | ||
195 | static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err); | ||
196 | |||
197 | static 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 | |||
205 | static 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 | */ |
@@ -679,6 +840,13 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci) | |||
679 | return retval; | 840 | return retval; |
680 | } | 841 | } |
681 | 842 | ||
843 | retval = sysfs_create_group(&ci->dev->kobj, &inputs_attr_group); | ||
844 | if (retval < 0) { | ||
845 | dev_dbg(ci->dev, | ||
846 | "Can't register sysfs attr group: %d\n", retval); | ||
847 | return retval; | ||
848 | } | ||
849 | |||
682 | /* Enable A vbus valid irq */ | 850 | /* Enable A vbus valid irq */ |
683 | hw_write_otgsc(ci, OTGSC_AVVIE, OTGSC_AVVIE); | 851 | hw_write_otgsc(ci, OTGSC_AVVIE, OTGSC_AVVIE); |
684 | 852 | ||
@@ -693,3 +861,8 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci) | |||
693 | 861 | ||
694 | return 0; | 862 | return 0; |
695 | } | 863 | } |
864 | |||
865 | void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci) | ||
866 | { | ||
867 | sysfs_remove_group(&ci->dev->kobj, &inputs_attr_group); | ||
868 | } | ||