1 /* 2 * otg_fsm.c - ChipIdea USB IP core OTG FSM driver 3 * 4 * Copyright (C) 2014 Freescale Semiconductor, Inc. 5 * 6 * Author: Jun Li 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13 /* 14 * This file mainly handles OTG fsm, it includes OTG fsm operations 15 * for HNP and SRP. 16 */ 17 18 #include <linux/usb/otg.h> 19 #include <linux/usb/gadget.h> 20 #include <linux/usb/hcd.h> 21 #include <linux/usb/chipidea.h> 22 #include <linux/regulator/consumer.h> 23 24 #include "ci.h" 25 #include "bits.h" 26 #include "otg.h" 27 #include "otg_fsm.h" 28 29 /* 30 * Add timer to active timer list 31 */ 32 static void ci_otg_add_timer(struct ci_hdrc *ci, enum ci_otg_fsm_timer_index t) 33 { 34 struct ci_otg_fsm_timer *tmp_timer; 35 struct ci_otg_fsm_timer *timer = ci->fsm_timer->timer_list[t]; 36 struct list_head *active_timers = &ci->fsm_timer->active_timers; 37 38 if (t >= NUM_CI_OTG_FSM_TIMERS) 39 return; 40 41 /* 42 * Check if the timer is already in the active list, 43 * if so update timer count 44 */ 45 list_for_each_entry(tmp_timer, active_timers, list) 46 if (tmp_timer == timer) { 47 timer->count = timer->expires; 48 return; 49 } 50 51 timer->count = timer->expires; 52 list_add_tail(&timer->list, active_timers); 53 54 /* Enable 1ms irq */ 55 if (!(hw_read_otgsc(ci, OTGSC_1MSIE))) 56 hw_write_otgsc(ci, OTGSC_1MSIE, OTGSC_1MSIE); 57 } 58 59 /* 60 * Remove timer from active timer list 61 */ 62 static void ci_otg_del_timer(struct ci_hdrc *ci, enum ci_otg_fsm_timer_index t) 63 { 64 struct ci_otg_fsm_timer *tmp_timer, *del_tmp; 65 struct ci_otg_fsm_timer *timer = ci->fsm_timer->timer_list[t]; 66 struct list_head *active_timers = &ci->fsm_timer->active_timers; 67 68 if (t >= NUM_CI_OTG_FSM_TIMERS) 69 return; 70 71 list_for_each_entry_safe(tmp_timer, del_tmp, active_timers, list) 72 if (tmp_timer == timer) 73 list_del(&timer->list); 74 75 /* Disable 1ms irq if there is no any active timer */ 76 if (list_empty(active_timers)) 77 hw_write_otgsc(ci, OTGSC_1MSIE, 0); 78 } 79 80 /* -------------------------------------------------------------*/ 81 /* Operations that will be called from OTG Finite State Machine */ 82 /* -------------------------------------------------------------*/ 83 static void ci_otg_fsm_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer t) 84 { 85 struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm); 86 87 if (t < NUM_OTG_FSM_TIMERS) 88 ci_otg_add_timer(ci, t); 89 return; 90 } 91 92 static void ci_otg_fsm_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer t) 93 { 94 struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm); 95 96 if (t < NUM_OTG_FSM_TIMERS) 97 ci_otg_del_timer(ci, t); 98 return; 99 } 100 101 /* 102 * A-device drive vbus: turn on vbus regulator and enable port power 103 * Data pulse irq should be disabled while vbus is on. 104 */ 105 static void ci_otg_drv_vbus(struct otg_fsm *fsm, int on) 106 { 107 int ret; 108 struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm); 109 110 if (on) { 111 /* Enable power power */ 112 hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_PP, 113 PORTSC_PP); 114 if (ci->platdata->reg_vbus) { 115 ret = regulator_enable(ci->platdata->reg_vbus); 116 if (ret) { 117 dev_err(ci->dev, 118 "Failed to enable vbus regulator, ret=%d\n", 119 ret); 120 return; 121 } 122 } 123 /* Disable data pulse irq */ 124 hw_write_otgsc(ci, OTGSC_DPIE, 0); 125 126 fsm->a_srp_det = 0; 127 fsm->power_up = 0; 128 } else { 129 if (ci->platdata->reg_vbus) 130 regulator_disable(ci->platdata->reg_vbus); 131 132 fsm->a_bus_drop = 1; 133 fsm->a_bus_req = 0; 134 } 135 } 136 137 /* 138 * Control data line by Run Stop bit. 139 */ 140 static void ci_otg_loc_conn(struct otg_fsm *fsm, int on) 141 { 142 struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm); 143 144 if (on) 145 hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); 146 else 147 hw_write(ci, OP_USBCMD, USBCMD_RS, 0); 148 } 149 150 /* 151 * Generate SOF by host. 152 * This is controlled through suspend/resume the port. 153 * In host mode, controller will automatically send SOF. 154 * Suspend will block the data on the port. 155 */ 156 static void ci_otg_loc_sof(struct otg_fsm *fsm, int on) 157 { 158 struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm); 159 160 if (on) 161 hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_FPR, 162 PORTSC_FPR); 163 else 164 hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_SUSP, 165 PORTSC_SUSP); 166 } 167 168 /* 169 * Start SRP pulsing by data-line pulsing, 170 * no v-bus pulsing followed 171 */ 172 static void ci_otg_start_pulse(struct otg_fsm *fsm) 173 { 174 struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm); 175 176 /* Hardware Assistant Data pulse */ 177 hw_write_otgsc(ci, OTGSC_HADP, OTGSC_HADP); 178 179 ci_otg_add_timer(ci, B_DATA_PLS); 180 } 181 182 static int ci_otg_start_host(struct otg_fsm *fsm, int on) 183 { 184 struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm); 185 186 mutex_unlock(&fsm->lock); 187 if (on) { 188 ci_role_stop(ci); 189 ci_role_start(ci, CI_ROLE_HOST); 190 } else { 191 ci_role_stop(ci); 192 hw_device_reset(ci, USBMODE_CM_DC); 193 ci_role_start(ci, CI_ROLE_GADGET); 194 } 195 mutex_lock(&fsm->lock); 196 return 0; 197 } 198 199 static int ci_otg_start_gadget(struct otg_fsm *fsm, int on) 200 { 201 struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm); 202 203 mutex_unlock(&fsm->lock); 204 if (on) 205 usb_gadget_vbus_connect(&ci->gadget); 206 else 207 usb_gadget_vbus_disconnect(&ci->gadget); 208 mutex_lock(&fsm->lock); 209 210 return 0; 211 } 212 213 static struct otg_fsm_ops ci_otg_ops = { 214 .drv_vbus = ci_otg_drv_vbus, 215 .loc_conn = ci_otg_loc_conn, 216 .loc_sof = ci_otg_loc_sof, 217 .start_pulse = ci_otg_start_pulse, 218 .add_timer = ci_otg_fsm_add_timer, 219 .del_timer = ci_otg_fsm_del_timer, 220 .start_host = ci_otg_start_host, 221 .start_gadget = ci_otg_start_gadget, 222 }; 223 224 int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci) 225 { 226 struct usb_otg *otg; 227 228 otg = devm_kzalloc(ci->dev, 229 sizeof(struct usb_otg), GFP_KERNEL); 230 if (!otg) { 231 dev_err(ci->dev, 232 "Failed to allocate usb_otg structure for ci hdrc otg!\n"); 233 return -ENOMEM; 234 } 235 236 otg->phy = ci->transceiver; 237 otg->gadget = &ci->gadget; 238 ci->fsm.otg = otg; 239 ci->transceiver->otg = ci->fsm.otg; 240 ci->fsm.power_up = 1; 241 ci->fsm.id = hw_read_otgsc(ci, OTGSC_ID) ? 1 : 0; 242 ci->transceiver->state = OTG_STATE_UNDEFINED; 243 ci->fsm.ops = &ci_otg_ops; 244 245 mutex_init(&ci->fsm.lock); 246 247 /* Enable A vbus valid irq */ 248 hw_write_otgsc(ci, OTGSC_AVVIE, OTGSC_AVVIE); 249 250 if (ci->fsm.id) { 251 ci->fsm.b_ssend_srp = 252 hw_read_otgsc(ci, OTGSC_BSV) ? 0 : 1; 253 ci->fsm.b_sess_vld = 254 hw_read_otgsc(ci, OTGSC_BSV) ? 1 : 0; 255 /* Enable BSV irq */ 256 hw_write_otgsc(ci, OTGSC_BSVIE, OTGSC_BSVIE); 257 } 258 259 return 0; 260 } 261