diff options
Diffstat (limited to 'drivers/usb/chipidea/otg_fsm.c')
-rw-r--r-- | drivers/usb/chipidea/otg_fsm.c | 389 |
1 files changed, 188 insertions, 201 deletions
diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c index 562e581f6765..083acf45ad5a 100644 --- a/drivers/usb/chipidea/otg_fsm.c +++ b/drivers/usb/chipidea/otg_fsm.c | |||
@@ -30,22 +30,6 @@ | |||
30 | #include "otg.h" | 30 | #include "otg.h" |
31 | #include "otg_fsm.h" | 31 | #include "otg_fsm.h" |
32 | 32 | ||
33 | static struct ci_otg_fsm_timer *otg_timer_initializer | ||
34 | (struct ci_hdrc *ci, void (*function)(void *, unsigned long), | ||
35 | unsigned long expires, unsigned long data) | ||
36 | { | ||
37 | struct ci_otg_fsm_timer *timer; | ||
38 | |||
39 | timer = devm_kzalloc(ci->dev, sizeof(struct ci_otg_fsm_timer), | ||
40 | GFP_KERNEL); | ||
41 | if (!timer) | ||
42 | return NULL; | ||
43 | timer->function = function; | ||
44 | timer->expires = expires; | ||
45 | timer->data = data; | ||
46 | return timer; | ||
47 | } | ||
48 | |||
49 | /* Add for otg: interact with user space app */ | 33 | /* Add for otg: interact with user space app */ |
50 | static ssize_t | 34 | static ssize_t |
51 | get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf) | 35 | get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -204,229 +188,227 @@ static struct attribute_group inputs_attr_group = { | |||
204 | }; | 188 | }; |
205 | 189 | ||
206 | /* | 190 | /* |
191 | * Keep this list in the same order as timers indexed | ||
192 | * by enum otg_fsm_timer in include/linux/usb/otg-fsm.h | ||
193 | */ | ||
194 | static unsigned otg_timer_ms[] = { | ||
195 | TA_WAIT_VRISE, | ||
196 | TA_WAIT_VFALL, | ||
197 | TA_WAIT_BCON, | ||
198 | TA_AIDL_BDIS, | ||
199 | TB_ASE0_BRST, | ||
200 | TA_BIDL_ADIS, | ||
201 | TB_SE0_SRP, | ||
202 | TB_SRP_FAIL, | ||
203 | 0, | ||
204 | TB_DATA_PLS, | ||
205 | TB_SSEND_SRP, | ||
206 | }; | ||
207 | |||
208 | /* | ||
207 | * Add timer to active timer list | 209 | * Add timer to active timer list |
208 | */ | 210 | */ |
209 | static void ci_otg_add_timer(struct ci_hdrc *ci, enum ci_otg_fsm_timer_index t) | 211 | static void ci_otg_add_timer(struct ci_hdrc *ci, enum otg_fsm_timer t) |
210 | { | 212 | { |
211 | struct ci_otg_fsm_timer *tmp_timer; | 213 | unsigned long flags, timer_sec, timer_nsec; |
212 | struct ci_otg_fsm_timer *timer = ci->fsm_timer->timer_list[t]; | ||
213 | struct list_head *active_timers = &ci->fsm_timer->active_timers; | ||
214 | 214 | ||
215 | if (t >= NUM_CI_OTG_FSM_TIMERS) | 215 | if (t >= NUM_OTG_FSM_TIMERS) |
216 | return; | 216 | return; |
217 | 217 | ||
218 | /* | 218 | spin_lock_irqsave(&ci->lock, flags); |
219 | * Check if the timer is already in the active list, | 219 | timer_sec = otg_timer_ms[t] / MSEC_PER_SEC; |
220 | * if so update timer count | 220 | timer_nsec = (otg_timer_ms[t] % MSEC_PER_SEC) * NSEC_PER_MSEC; |
221 | */ | 221 | ci->hr_timeouts[t] = ktime_add(ktime_get(), |
222 | list_for_each_entry(tmp_timer, active_timers, list) | 222 | ktime_set(timer_sec, timer_nsec)); |
223 | if (tmp_timer == timer) { | 223 | ci->enabled_otg_timer_bits |= (1 << t); |
224 | timer->count = timer->expires; | 224 | if ((ci->next_otg_timer == NUM_OTG_FSM_TIMERS) || |
225 | return; | 225 | (ci->hr_timeouts[ci->next_otg_timer].tv64 > |
226 | } | 226 | ci->hr_timeouts[t].tv64)) { |
227 | 227 | ci->next_otg_timer = t; | |
228 | timer->count = timer->expires; | 228 | hrtimer_start_range_ns(&ci->otg_fsm_hrtimer, |
229 | list_add_tail(&timer->list, active_timers); | 229 | ci->hr_timeouts[t], NSEC_PER_MSEC, |
230 | 230 | HRTIMER_MODE_ABS); | |
231 | /* Enable 1ms irq */ | 231 | } |
232 | if (!(hw_read_otgsc(ci, OTGSC_1MSIE))) | 232 | spin_unlock_irqrestore(&ci->lock, flags); |
233 | hw_write_otgsc(ci, OTGSC_1MSIE, OTGSC_1MSIE); | ||
234 | } | 233 | } |
235 | 234 | ||
236 | /* | 235 | /* |
237 | * Remove timer from active timer list | 236 | * Remove timer from active timer list |
238 | */ | 237 | */ |
239 | static void ci_otg_del_timer(struct ci_hdrc *ci, enum ci_otg_fsm_timer_index t) | 238 | static void ci_otg_del_timer(struct ci_hdrc *ci, enum otg_fsm_timer t) |
240 | { | 239 | { |
241 | struct ci_otg_fsm_timer *tmp_timer, *del_tmp; | 240 | unsigned long flags, enabled_timer_bits; |
242 | struct ci_otg_fsm_timer *timer = ci->fsm_timer->timer_list[t]; | 241 | enum otg_fsm_timer cur_timer, next_timer = NUM_OTG_FSM_TIMERS; |
243 | struct list_head *active_timers = &ci->fsm_timer->active_timers; | ||
244 | 242 | ||
245 | if (t >= NUM_CI_OTG_FSM_TIMERS) | 243 | if ((t >= NUM_OTG_FSM_TIMERS) || |
244 | !(ci->enabled_otg_timer_bits & (1 << t))) | ||
246 | return; | 245 | return; |
247 | 246 | ||
248 | list_for_each_entry_safe(tmp_timer, del_tmp, active_timers, list) | 247 | spin_lock_irqsave(&ci->lock, flags); |
249 | if (tmp_timer == timer) | 248 | ci->enabled_otg_timer_bits &= ~(1 << t); |
250 | list_del(&timer->list); | 249 | if (ci->next_otg_timer == t) { |
251 | 250 | if (ci->enabled_otg_timer_bits == 0) { | |
252 | /* Disable 1ms irq if there is no any active timer */ | 251 | /* No enabled timers after delete it */ |
253 | if (list_empty(active_timers)) | 252 | hrtimer_cancel(&ci->otg_fsm_hrtimer); |
254 | hw_write_otgsc(ci, OTGSC_1MSIE, 0); | 253 | ci->next_otg_timer = NUM_OTG_FSM_TIMERS; |
255 | } | 254 | } else { |
256 | 255 | /* Find the next timer */ | |
257 | /* | 256 | enabled_timer_bits = ci->enabled_otg_timer_bits; |
258 | * Reduce timer count by 1, and find timeout conditions. | 257 | for_each_set_bit(cur_timer, &enabled_timer_bits, |
259 | * Called by otg 1ms timer interrupt | 258 | NUM_OTG_FSM_TIMERS) { |
260 | */ | 259 | if ((next_timer == NUM_OTG_FSM_TIMERS) || |
261 | static inline int ci_otg_tick_timer(struct ci_hdrc *ci) | 260 | (ci->hr_timeouts[next_timer].tv64 < |
262 | { | 261 | ci->hr_timeouts[cur_timer].tv64)) |
263 | struct ci_otg_fsm_timer *tmp_timer, *del_tmp; | 262 | next_timer = cur_timer; |
264 | struct list_head *active_timers = &ci->fsm_timer->active_timers; | 263 | } |
265 | int expired = 0; | ||
266 | |||
267 | list_for_each_entry_safe(tmp_timer, del_tmp, active_timers, list) { | ||
268 | tmp_timer->count--; | ||
269 | /* check if timer expires */ | ||
270 | if (!tmp_timer->count) { | ||
271 | list_del(&tmp_timer->list); | ||
272 | tmp_timer->function(ci, tmp_timer->data); | ||
273 | expired = 1; | ||
274 | } | 264 | } |
275 | } | 265 | } |
276 | 266 | if (next_timer != NUM_OTG_FSM_TIMERS) { | |
277 | /* disable 1ms irq if there is no any timer active */ | 267 | ci->next_otg_timer = next_timer; |
278 | if ((expired == 1) && list_empty(active_timers)) | 268 | hrtimer_start_range_ns(&ci->otg_fsm_hrtimer, |
279 | hw_write_otgsc(ci, OTGSC_1MSIE, 0); | 269 | ci->hr_timeouts[next_timer], NSEC_PER_MSEC, |
280 | 270 | HRTIMER_MODE_ABS); | |
281 | return expired; | 271 | } |
272 | spin_unlock_irqrestore(&ci->lock, flags); | ||
282 | } | 273 | } |
283 | 274 | ||
284 | /* The timeout callback function to set time out bit */ | 275 | /* OTG FSM timer handlers */ |
285 | static void set_tmout(void *ptr, unsigned long indicator) | 276 | static int a_wait_vrise_tmout(struct ci_hdrc *ci) |
286 | { | 277 | { |
287 | *(int *)indicator = 1; | 278 | ci->fsm.a_wait_vrise_tmout = 1; |
279 | return 0; | ||
288 | } | 280 | } |
289 | 281 | ||
290 | static void set_tmout_and_fsm(void *ptr, unsigned long indicator) | 282 | static int a_wait_vfall_tmout(struct ci_hdrc *ci) |
291 | { | 283 | { |
292 | struct ci_hdrc *ci = (struct ci_hdrc *)ptr; | 284 | ci->fsm.a_wait_vfall_tmout = 1; |
293 | 285 | return 0; | |
294 | set_tmout(ci, indicator); | ||
295 | |||
296 | ci_otg_queue_work(ci); | ||
297 | } | 286 | } |
298 | 287 | ||
299 | static void a_wait_vfall_tmout_func(void *ptr, unsigned long indicator) | 288 | static int a_wait_bcon_tmout(struct ci_hdrc *ci) |
300 | { | 289 | { |
301 | struct ci_hdrc *ci = (struct ci_hdrc *)ptr; | 290 | ci->fsm.a_wait_bcon_tmout = 1; |
302 | 291 | return 0; | |
303 | set_tmout(ci, indicator); | ||
304 | /* Disable port power */ | ||
305 | hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_PP, 0); | ||
306 | /* Clear existing DP irq */ | ||
307 | hw_write_otgsc(ci, OTGSC_DPIS, OTGSC_DPIS); | ||
308 | /* Enable data pulse irq */ | ||
309 | hw_write_otgsc(ci, OTGSC_DPIE, OTGSC_DPIE); | ||
310 | ci_otg_queue_work(ci); | ||
311 | } | 292 | } |
312 | 293 | ||
313 | static void b_ase0_brst_tmout_func(void *ptr, unsigned long indicator) | 294 | static int a_aidl_bdis_tmout(struct ci_hdrc *ci) |
314 | { | 295 | { |
315 | struct ci_hdrc *ci = (struct ci_hdrc *)ptr; | 296 | ci->fsm.a_aidl_bdis_tmout = 1; |
316 | 297 | return 0; | |
317 | set_tmout(ci, indicator); | ||
318 | if (!hw_read_otgsc(ci, OTGSC_BSV)) | ||
319 | ci->fsm.b_sess_vld = 0; | ||
320 | |||
321 | ci_otg_queue_work(ci); | ||
322 | } | 298 | } |
323 | 299 | ||
324 | static void b_ssend_srp_tmout_func(void *ptr, unsigned long indicator) | 300 | static int b_ase0_brst_tmout(struct ci_hdrc *ci) |
325 | { | 301 | { |
326 | struct ci_hdrc *ci = (struct ci_hdrc *)ptr; | 302 | ci->fsm.b_ase0_brst_tmout = 1; |
327 | 303 | return 0; | |
328 | set_tmout(ci, indicator); | ||
329 | |||
330 | /* only vbus fall below B_sess_vld in b_idle state */ | ||
331 | if (ci->fsm.otg->state == OTG_STATE_B_IDLE) | ||
332 | ci_otg_queue_work(ci); | ||
333 | } | 304 | } |
334 | 305 | ||
335 | static void b_sess_vld_tmout_func(void *ptr, unsigned long indicator) | 306 | static int a_bidl_adis_tmout(struct ci_hdrc *ci) |
336 | { | 307 | { |
337 | struct ci_hdrc *ci = (struct ci_hdrc *)ptr; | 308 | ci->fsm.a_bidl_adis_tmout = 1; |
309 | return 0; | ||
310 | } | ||
338 | 311 | ||
339 | /* Check if A detached */ | 312 | static int b_se0_srp_tmout(struct ci_hdrc *ci) |
340 | if (!(hw_read_otgsc(ci, OTGSC_BSV))) { | 313 | { |
341 | ci->fsm.b_sess_vld = 0; | 314 | ci->fsm.b_se0_srp = 1; |
342 | ci_otg_add_timer(ci, B_SSEND_SRP); | 315 | return 0; |
343 | ci_otg_queue_work(ci); | ||
344 | } | ||
345 | } | 316 | } |
346 | 317 | ||
347 | static void b_data_pulse_end(void *ptr, unsigned long indicator) | 318 | static int b_srp_fail_tmout(struct ci_hdrc *ci) |
348 | { | 319 | { |
349 | struct ci_hdrc *ci = (struct ci_hdrc *)ptr; | 320 | ci->fsm.b_srp_done = 1; |
321 | return 1; | ||
322 | } | ||
350 | 323 | ||
324 | static int b_data_pls_tmout(struct ci_hdrc *ci) | ||
325 | { | ||
351 | ci->fsm.b_srp_done = 1; | 326 | ci->fsm.b_srp_done = 1; |
352 | ci->fsm.b_bus_req = 0; | 327 | ci->fsm.b_bus_req = 0; |
353 | if (ci->fsm.power_up) | 328 | if (ci->fsm.power_up) |
354 | ci->fsm.power_up = 0; | 329 | ci->fsm.power_up = 0; |
355 | |||
356 | hw_write_otgsc(ci, OTGSC_HABA, 0); | 330 | hw_write_otgsc(ci, OTGSC_HABA, 0); |
331 | pm_runtime_put(ci->dev); | ||
332 | return 0; | ||
333 | } | ||
357 | 334 | ||
358 | ci_otg_queue_work(ci); | 335 | static int b_ssend_srp_tmout(struct ci_hdrc *ci) |
336 | { | ||
337 | ci->fsm.b_ssend_srp = 1; | ||
338 | /* only vbus fall below B_sess_vld in b_idle state */ | ||
339 | if (ci->fsm.otg->state == OTG_STATE_B_IDLE) | ||
340 | return 0; | ||
341 | else | ||
342 | return 1; | ||
343 | } | ||
344 | |||
345 | /* | ||
346 | * Keep this list in the same order as timers indexed | ||
347 | * by enum otg_fsm_timer in include/linux/usb/otg-fsm.h | ||
348 | */ | ||
349 | static int (*otg_timer_handlers[])(struct ci_hdrc *) = { | ||
350 | a_wait_vrise_tmout, /* A_WAIT_VRISE */ | ||
351 | a_wait_vfall_tmout, /* A_WAIT_VFALL */ | ||
352 | a_wait_bcon_tmout, /* A_WAIT_BCON */ | ||
353 | a_aidl_bdis_tmout, /* A_AIDL_BDIS */ | ||
354 | b_ase0_brst_tmout, /* B_ASE0_BRST */ | ||
355 | a_bidl_adis_tmout, /* A_BIDL_ADIS */ | ||
356 | b_se0_srp_tmout, /* B_SE0_SRP */ | ||
357 | b_srp_fail_tmout, /* B_SRP_FAIL */ | ||
358 | NULL, /* A_WAIT_ENUM */ | ||
359 | b_data_pls_tmout, /* B_DATA_PLS */ | ||
360 | b_ssend_srp_tmout, /* B_SSEND_SRP */ | ||
361 | }; | ||
362 | |||
363 | /* | ||
364 | * Enable the next nearest enabled timer if have | ||
365 | */ | ||
366 | static enum hrtimer_restart ci_otg_hrtimer_func(struct hrtimer *t) | ||
367 | { | ||
368 | struct ci_hdrc *ci = container_of(t, struct ci_hdrc, otg_fsm_hrtimer); | ||
369 | ktime_t now, *timeout; | ||
370 | unsigned long enabled_timer_bits; | ||
371 | unsigned long flags; | ||
372 | enum otg_fsm_timer cur_timer, next_timer = NUM_OTG_FSM_TIMERS; | ||
373 | int ret = -EINVAL; | ||
374 | |||
375 | spin_lock_irqsave(&ci->lock, flags); | ||
376 | enabled_timer_bits = ci->enabled_otg_timer_bits; | ||
377 | ci->next_otg_timer = NUM_OTG_FSM_TIMERS; | ||
378 | |||
379 | now = ktime_get(); | ||
380 | for_each_set_bit(cur_timer, &enabled_timer_bits, NUM_OTG_FSM_TIMERS) { | ||
381 | if (now.tv64 >= ci->hr_timeouts[cur_timer].tv64) { | ||
382 | ci->enabled_otg_timer_bits &= ~(1 << cur_timer); | ||
383 | if (otg_timer_handlers[cur_timer]) | ||
384 | ret = otg_timer_handlers[cur_timer](ci); | ||
385 | } else { | ||
386 | if ((next_timer == NUM_OTG_FSM_TIMERS) || | ||
387 | (ci->hr_timeouts[cur_timer].tv64 < | ||
388 | ci->hr_timeouts[next_timer].tv64)) | ||
389 | next_timer = cur_timer; | ||
390 | } | ||
391 | } | ||
392 | /* Enable the next nearest timer */ | ||
393 | if (next_timer < NUM_OTG_FSM_TIMERS) { | ||
394 | timeout = &ci->hr_timeouts[next_timer]; | ||
395 | hrtimer_start_range_ns(&ci->otg_fsm_hrtimer, *timeout, | ||
396 | NSEC_PER_MSEC, HRTIMER_MODE_ABS); | ||
397 | ci->next_otg_timer = next_timer; | ||
398 | } | ||
399 | spin_unlock_irqrestore(&ci->lock, flags); | ||
400 | |||
401 | if (!ret) | ||
402 | ci_otg_queue_work(ci); | ||
403 | |||
404 | return HRTIMER_NORESTART; | ||
359 | } | 405 | } |
360 | 406 | ||
361 | /* Initialize timers */ | 407 | /* Initialize timers */ |
362 | static int ci_otg_init_timers(struct ci_hdrc *ci) | 408 | static int ci_otg_init_timers(struct ci_hdrc *ci) |
363 | { | 409 | { |
364 | struct otg_fsm *fsm = &ci->fsm; | 410 | hrtimer_init(&ci->otg_fsm_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
365 | 411 | ci->otg_fsm_hrtimer.function = ci_otg_hrtimer_func; | |
366 | /* FSM used timers */ | ||
367 | ci->fsm_timer->timer_list[A_WAIT_VRISE] = | ||
368 | otg_timer_initializer(ci, &set_tmout_and_fsm, TA_WAIT_VRISE, | ||
369 | (unsigned long)&fsm->a_wait_vrise_tmout); | ||
370 | if (ci->fsm_timer->timer_list[A_WAIT_VRISE] == NULL) | ||
371 | return -ENOMEM; | ||
372 | |||
373 | ci->fsm_timer->timer_list[A_WAIT_VFALL] = | ||
374 | otg_timer_initializer(ci, &a_wait_vfall_tmout_func, | ||
375 | TA_WAIT_VFALL, (unsigned long)&fsm->a_wait_vfall_tmout); | ||
376 | if (ci->fsm_timer->timer_list[A_WAIT_VFALL] == NULL) | ||
377 | return -ENOMEM; | ||
378 | |||
379 | ci->fsm_timer->timer_list[A_WAIT_BCON] = | ||
380 | otg_timer_initializer(ci, &set_tmout_and_fsm, TA_WAIT_BCON, | ||
381 | (unsigned long)&fsm->a_wait_bcon_tmout); | ||
382 | if (ci->fsm_timer->timer_list[A_WAIT_BCON] == NULL) | ||
383 | return -ENOMEM; | ||
384 | |||
385 | ci->fsm_timer->timer_list[A_AIDL_BDIS] = | ||
386 | otg_timer_initializer(ci, &set_tmout_and_fsm, TA_AIDL_BDIS, | ||
387 | (unsigned long)&fsm->a_aidl_bdis_tmout); | ||
388 | if (ci->fsm_timer->timer_list[A_AIDL_BDIS] == NULL) | ||
389 | return -ENOMEM; | ||
390 | |||
391 | ci->fsm_timer->timer_list[A_BIDL_ADIS] = | ||
392 | otg_timer_initializer(ci, &set_tmout_and_fsm, TA_BIDL_ADIS, | ||
393 | (unsigned long)&fsm->a_bidl_adis_tmout); | ||
394 | if (ci->fsm_timer->timer_list[A_BIDL_ADIS] == NULL) | ||
395 | return -ENOMEM; | ||
396 | |||
397 | ci->fsm_timer->timer_list[B_ASE0_BRST] = | ||
398 | otg_timer_initializer(ci, &b_ase0_brst_tmout_func, TB_ASE0_BRST, | ||
399 | (unsigned long)&fsm->b_ase0_brst_tmout); | ||
400 | if (ci->fsm_timer->timer_list[B_ASE0_BRST] == NULL) | ||
401 | return -ENOMEM; | ||
402 | |||
403 | ci->fsm_timer->timer_list[B_SE0_SRP] = | ||
404 | otg_timer_initializer(ci, &set_tmout_and_fsm, TB_SE0_SRP, | ||
405 | (unsigned long)&fsm->b_se0_srp); | ||
406 | if (ci->fsm_timer->timer_list[B_SE0_SRP] == NULL) | ||
407 | return -ENOMEM; | ||
408 | |||
409 | ci->fsm_timer->timer_list[B_SSEND_SRP] = | ||
410 | otg_timer_initializer(ci, &b_ssend_srp_tmout_func, TB_SSEND_SRP, | ||
411 | (unsigned long)&fsm->b_ssend_srp); | ||
412 | if (ci->fsm_timer->timer_list[B_SSEND_SRP] == NULL) | ||
413 | return -ENOMEM; | ||
414 | |||
415 | ci->fsm_timer->timer_list[B_SRP_FAIL] = | ||
416 | otg_timer_initializer(ci, &set_tmout, TB_SRP_FAIL, | ||
417 | (unsigned long)&fsm->b_srp_done); | ||
418 | if (ci->fsm_timer->timer_list[B_SRP_FAIL] == NULL) | ||
419 | return -ENOMEM; | ||
420 | |||
421 | ci->fsm_timer->timer_list[B_DATA_PLS] = | ||
422 | otg_timer_initializer(ci, &b_data_pulse_end, TB_DATA_PLS, 0); | ||
423 | if (ci->fsm_timer->timer_list[B_DATA_PLS] == NULL) | ||
424 | return -ENOMEM; | ||
425 | |||
426 | ci->fsm_timer->timer_list[B_SESS_VLD] = otg_timer_initializer(ci, | ||
427 | &b_sess_vld_tmout_func, TB_SESS_VLD, 0); | ||
428 | if (ci->fsm_timer->timer_list[B_SESS_VLD] == NULL) | ||
429 | return -ENOMEM; | ||
430 | 412 | ||
431 | return 0; | 413 | return 0; |
432 | } | 414 | } |
@@ -530,6 +512,7 @@ static void ci_otg_start_pulse(struct otg_fsm *fsm) | |||
530 | /* Hardware Assistant Data pulse */ | 512 | /* Hardware Assistant Data pulse */ |
531 | hw_write_otgsc(ci, OTGSC_HADP, OTGSC_HADP); | 513 | hw_write_otgsc(ci, OTGSC_HADP, OTGSC_HADP); |
532 | 514 | ||
515 | pm_runtime_get(ci->dev); | ||
533 | ci_otg_add_timer(ci, B_DATA_PLS); | 516 | ci_otg_add_timer(ci, B_DATA_PLS); |
534 | } | 517 | } |
535 | 518 | ||
@@ -585,6 +568,7 @@ int ci_otg_fsm_work(struct ci_hdrc *ci) | |||
585 | ci->fsm.otg->state < OTG_STATE_A_IDLE) | 568 | ci->fsm.otg->state < OTG_STATE_A_IDLE) |
586 | return 0; | 569 | return 0; |
587 | 570 | ||
571 | pm_runtime_get_sync(ci->dev); | ||
588 | if (otg_statemachine(&ci->fsm)) { | 572 | if (otg_statemachine(&ci->fsm)) { |
589 | if (ci->fsm.otg->state == OTG_STATE_A_IDLE) { | 573 | if (ci->fsm.otg->state == OTG_STATE_A_IDLE) { |
590 | /* | 574 | /* |
@@ -596,8 +580,15 @@ int ci_otg_fsm_work(struct ci_hdrc *ci) | |||
596 | * a_idle to a_wait_vrise when power up | 580 | * a_idle to a_wait_vrise when power up |
597 | */ | 581 | */ |
598 | if ((ci->fsm.id) || (ci->id_event) || | 582 | if ((ci->fsm.id) || (ci->id_event) || |
599 | (ci->fsm.power_up)) | 583 | (ci->fsm.power_up)) { |
600 | ci_otg_queue_work(ci); | 584 | ci_otg_queue_work(ci); |
585 | } else { | ||
586 | /* Enable data pulse irq */ | ||
587 | hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | | ||
588 | PORTSC_PP, 0); | ||
589 | hw_write_otgsc(ci, OTGSC_DPIS, OTGSC_DPIS); | ||
590 | hw_write_otgsc(ci, OTGSC_DPIE, OTGSC_DPIE); | ||
591 | } | ||
601 | if (ci->id_event) | 592 | if (ci->id_event) |
602 | ci->id_event = false; | 593 | ci->id_event = false; |
603 | } else if (ci->fsm.otg->state == OTG_STATE_B_IDLE) { | 594 | } else if (ci->fsm.otg->state == OTG_STATE_B_IDLE) { |
@@ -609,8 +600,13 @@ int ci_otg_fsm_work(struct ci_hdrc *ci) | |||
609 | */ | 600 | */ |
610 | ci_otg_queue_work(ci); | 601 | ci_otg_queue_work(ci); |
611 | } | 602 | } |
603 | } else if (ci->fsm.otg->state == OTG_STATE_A_HOST) { | ||
604 | pm_runtime_mark_last_busy(ci->dev); | ||
605 | pm_runtime_put_autosuspend(ci->dev); | ||
606 | return 0; | ||
612 | } | 607 | } |
613 | } | 608 | } |
609 | pm_runtime_put_sync(ci->dev); | ||
614 | return 0; | 610 | return 0; |
615 | } | 611 | } |
616 | 612 | ||
@@ -655,7 +651,6 @@ static void ci_otg_fsm_event(struct ci_hdrc *ci) | |||
655 | fsm->a_conn = 0; | 651 | fsm->a_conn = 0; |
656 | fsm->b_bus_req = 0; | 652 | fsm->b_bus_req = 0; |
657 | ci_otg_queue_work(ci); | 653 | ci_otg_queue_work(ci); |
658 | ci_otg_add_timer(ci, B_SESS_VLD); | ||
659 | } | 654 | } |
660 | break; | 655 | break; |
661 | case OTG_STATE_A_PERIPHERAL: | 656 | case OTG_STATE_A_PERIPHERAL: |
@@ -725,11 +720,7 @@ irqreturn_t ci_otg_fsm_irq(struct ci_hdrc *ci) | |||
725 | fsm->id = (otgsc & OTGSC_ID) ? 1 : 0; | 720 | fsm->id = (otgsc & OTGSC_ID) ? 1 : 0; |
726 | 721 | ||
727 | if (otg_int_src) { | 722 | if (otg_int_src) { |
728 | if (otg_int_src & OTGSC_1MSIS) { | 723 | if (otg_int_src & OTGSC_DPIS) { |
729 | hw_write_otgsc(ci, OTGSC_1MSIS, OTGSC_1MSIS); | ||
730 | retval = ci_otg_tick_timer(ci); | ||
731 | return IRQ_HANDLED; | ||
732 | } else if (otg_int_src & OTGSC_DPIS) { | ||
733 | hw_write_otgsc(ci, OTGSC_DPIS, OTGSC_DPIS); | 724 | hw_write_otgsc(ci, OTGSC_DPIS, OTGSC_DPIS); |
734 | fsm->a_srp_det = 1; | 725 | fsm->a_srp_det = 1; |
735 | fsm->a_bus_drop = 0; | 726 | fsm->a_bus_drop = 0; |
@@ -793,17 +784,13 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci) | |||
793 | 784 | ||
794 | mutex_init(&ci->fsm.lock); | 785 | mutex_init(&ci->fsm.lock); |
795 | 786 | ||
796 | ci->fsm_timer = devm_kzalloc(ci->dev, | ||
797 | sizeof(struct ci_otg_fsm_timer_list), GFP_KERNEL); | ||
798 | if (!ci->fsm_timer) | ||
799 | return -ENOMEM; | ||
800 | |||
801 | INIT_LIST_HEAD(&ci->fsm_timer->active_timers); | ||
802 | retval = ci_otg_init_timers(ci); | 787 | retval = ci_otg_init_timers(ci); |
803 | if (retval) { | 788 | if (retval) { |
804 | dev_err(ci->dev, "Couldn't init OTG timers\n"); | 789 | dev_err(ci->dev, "Couldn't init OTG timers\n"); |
805 | return retval; | 790 | return retval; |
806 | } | 791 | } |
792 | ci->enabled_otg_timer_bits = 0; | ||
793 | ci->next_otg_timer = NUM_OTG_FSM_TIMERS; | ||
807 | 794 | ||
808 | retval = sysfs_create_group(&ci->dev->kobj, &inputs_attr_group); | 795 | retval = sysfs_create_group(&ci->dev->kobj, &inputs_attr_group); |
809 | if (retval < 0) { | 796 | if (retval < 0) { |