xref: /linux/drivers/usb/chipidea/otg_fsm.c (revision 826cfe751f3e1faf4a63b65245f5ee3a7efeb763)
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