aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/renesas_usbhs/mod.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/renesas_usbhs/mod.c')
-rw-r--r--drivers/usb/renesas_usbhs/mod.c81
1 files changed, 60 insertions, 21 deletions
diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c
index a577f8f4064..053f86d7000 100644
--- a/drivers/usb/renesas_usbhs/mod.c
+++ b/drivers/usb/renesas_usbhs/mod.c
@@ -58,7 +58,7 @@ void usbhs_mod_autonomy_mode(struct usbhs_priv *priv)
58 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); 58 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
59 59
60 info->irq_vbus = usbhsm_autonomy_irq_vbus; 60 info->irq_vbus = usbhsm_autonomy_irq_vbus;
61 priv->pfunc->get_vbus = usbhsm_autonomy_get_vbus; 61 priv->pfunc.get_vbus = usbhsm_autonomy_get_vbus;
62 62
63 usbhs_irq_callback_update(priv, NULL); 63 usbhs_irq_callback_update(priv, NULL);
64} 64}
@@ -93,8 +93,9 @@ struct usbhs_mod *usbhs_mod_get(struct usbhs_priv *priv, int id)
93 return ret; 93 return ret;
94} 94}
95 95
96int usbhs_mod_is_host(struct usbhs_priv *priv, struct usbhs_mod *mod) 96int usbhs_mod_is_host(struct usbhs_priv *priv)
97{ 97{
98 struct usbhs_mod *mod = usbhs_mod_get_current(priv);
98 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); 99 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
99 100
100 if (!mod) 101 if (!mod)
@@ -139,13 +140,17 @@ int usbhs_mod_probe(struct usbhs_priv *priv)
139 /* 140 /*
140 * install host/gadget driver 141 * install host/gadget driver
141 */ 142 */
142 ret = usbhs_mod_gadget_probe(priv); 143 ret = usbhs_mod_host_probe(priv);
143 if (ret < 0) 144 if (ret < 0)
144 return ret; 145 return ret;
145 146
147 ret = usbhs_mod_gadget_probe(priv);
148 if (ret < 0)
149 goto mod_init_host_err;
150
146 /* irq settings */ 151 /* irq settings */
147 ret = request_irq(priv->irq, usbhs_interrupt, 152 ret = request_irq(priv->irq, usbhs_interrupt,
148 IRQF_DISABLED, dev_name(dev), priv); 153 0, dev_name(dev), priv);
149 if (ret) { 154 if (ret) {
150 dev_err(dev, "irq request err\n"); 155 dev_err(dev, "irq request err\n");
151 goto mod_init_gadget_err; 156 goto mod_init_gadget_err;
@@ -155,12 +160,15 @@ int usbhs_mod_probe(struct usbhs_priv *priv)
155 160
156mod_init_gadget_err: 161mod_init_gadget_err:
157 usbhs_mod_gadget_remove(priv); 162 usbhs_mod_gadget_remove(priv);
163mod_init_host_err:
164 usbhs_mod_host_remove(priv);
158 165
159 return ret; 166 return ret;
160} 167}
161 168
162void usbhs_mod_remove(struct usbhs_priv *priv) 169void usbhs_mod_remove(struct usbhs_priv *priv)
163{ 170{
171 usbhs_mod_host_remove(priv);
164 usbhs_mod_gadget_remove(priv); 172 usbhs_mod_gadget_remove(priv);
165 free_irq(priv->irq, priv); 173 free_irq(priv->irq, priv);
166} 174}
@@ -168,20 +176,6 @@ void usbhs_mod_remove(struct usbhs_priv *priv)
168/* 176/*
169 * status functions 177 * status functions
170 */ 178 */
171int usbhs_status_get_usb_speed(struct usbhs_irq_state *irq_state)
172{
173 switch (irq_state->dvstctr & RHST) {
174 case RHST_LOW_SPEED:
175 return USB_SPEED_LOW;
176 case RHST_FULL_SPEED:
177 return USB_SPEED_FULL;
178 case RHST_HIGH_SPEED:
179 return USB_SPEED_HIGH;
180 }
181
182 return USB_SPEED_UNKNOWN;
183}
184
185int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state) 179int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state)
186{ 180{
187 int state = irq_state->intsts0 & DVSQ_MASK; 181 int state = irq_state->intsts0 & DVSQ_MASK;
@@ -221,8 +215,6 @@ static void usbhs_status_get_each_irq(struct usbhs_priv *priv,
221 state->intsts0 = usbhs_read(priv, INTSTS0); 215 state->intsts0 = usbhs_read(priv, INTSTS0);
222 state->intsts1 = usbhs_read(priv, INTSTS1); 216 state->intsts1 = usbhs_read(priv, INTSTS1);
223 217
224 state->dvstctr = usbhs_read(priv, DVSTCTR);
225
226 /* mask */ 218 /* mask */
227 if (mod) { 219 if (mod) {
228 state->brdysts = usbhs_read(priv, BRDYSTS); 220 state->brdysts = usbhs_read(priv, BRDYSTS);
@@ -269,6 +261,8 @@ static irqreturn_t usbhs_interrupt(int irq, void *data)
269 * see also 261 * see also
270 * usbhs_irq_setting_update 262 * usbhs_irq_setting_update
271 */ 263 */
264
265 /* INTSTS0 */
272 if (irq_state.intsts0 & VBINT) 266 if (irq_state.intsts0 & VBINT)
273 usbhs_mod_info_call(priv, irq_vbus, priv, &irq_state); 267 usbhs_mod_info_call(priv, irq_vbus, priv, &irq_state);
274 268
@@ -284,15 +278,38 @@ static irqreturn_t usbhs_interrupt(int irq, void *data)
284 if (irq_state.intsts0 & BRDY) 278 if (irq_state.intsts0 & BRDY)
285 usbhs_mod_call(priv, irq_ready, priv, &irq_state); 279 usbhs_mod_call(priv, irq_ready, priv, &irq_state);
286 280
281 /* INTSTS1 */
282 if (irq_state.intsts1 & ATTCH)
283 usbhs_mod_call(priv, irq_attch, priv, &irq_state);
284
285 if (irq_state.intsts1 & DTCH)
286 usbhs_mod_call(priv, irq_dtch, priv, &irq_state);
287
288 if (irq_state.intsts1 & SIGN)
289 usbhs_mod_call(priv, irq_sign, priv, &irq_state);
290
291 if (irq_state.intsts1 & SACK)
292 usbhs_mod_call(priv, irq_sack, priv, &irq_state);
293
287 return IRQ_HANDLED; 294 return IRQ_HANDLED;
288} 295}
289 296
290void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod) 297void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod)
291{ 298{
292 u16 intenb0 = 0; 299 u16 intenb0 = 0;
300 u16 intenb1 = 0;
293 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); 301 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
294 302
303 /*
304 * BEMPENB/BRDYENB are picky.
305 * below method is required
306 *
307 * - clear INTSTS0
308 * - update BEMPENB/BRDYENB
309 * - update INTSTS0
310 */
295 usbhs_write(priv, INTENB0, 0); 311 usbhs_write(priv, INTENB0, 0);
312 usbhs_write(priv, INTENB1, 0);
296 313
297 usbhs_write(priv, BEMPENB, 0); 314 usbhs_write(priv, BEMPENB, 0);
298 usbhs_write(priv, BRDYENB, 0); 315 usbhs_write(priv, BRDYENB, 0);
@@ -310,6 +327,9 @@ void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod)
310 intenb0 |= VBSE; 327 intenb0 |= VBSE;
311 328
312 if (mod) { 329 if (mod) {
330 /*
331 * INTSTS0
332 */
313 if (mod->irq_ctrl_stage) 333 if (mod->irq_ctrl_stage)
314 intenb0 |= CTRE; 334 intenb0 |= CTRE;
315 335
@@ -322,7 +342,26 @@ void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod)
322 usbhs_write(priv, BRDYENB, mod->irq_brdysts); 342 usbhs_write(priv, BRDYENB, mod->irq_brdysts);
323 intenb0 |= BRDYE; 343 intenb0 |= BRDYE;
324 } 344 }
345
346 /*
347 * INTSTS1
348 */
349 if (mod->irq_attch)
350 intenb1 |= ATTCHE;
351
352 if (mod->irq_attch)
353 intenb1 |= DTCHE;
354
355 if (mod->irq_sign)
356 intenb1 |= SIGNE;
357
358 if (mod->irq_sack)
359 intenb1 |= SACKE;
325 } 360 }
326 361
327 usbhs_write(priv, INTENB0, intenb0); 362 if (intenb0)
363 usbhs_write(priv, INTENB0, intenb0);
364
365 if (intenb1)
366 usbhs_write(priv, INTENB1, intenb1);
328} 367}