xref: /openbmc/linux/drivers/usb/renesas_usbhs/mod.c (revision ae213c44)
1 // SPDX-License-Identifier: GPL-1.0+
2 /*
3  * Renesas USB driver
4  *
5  * Copyright (C) 2011 Renesas Solutions Corp.
6  * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
7  */
8 #include <linux/interrupt.h>
9 
10 #include "common.h"
11 #include "mod.h"
12 
13 #define usbhs_priv_to_modinfo(priv) (&priv->mod_info)
14 #define usbhs_mod_info_call(priv, func, param...)	\
15 ({						\
16 	struct usbhs_mod_info *info;		\
17 	info = usbhs_priv_to_modinfo(priv);	\
18 	!info->func ? 0 :			\
19 	 info->func(param);			\
20 })
21 
22 /*
23  *		autonomy
24  *
25  * these functions are used if platform doesn't have external phy.
26  *  -> there is no "notify_hotplug" callback from platform
27  *  -> call "notify_hotplug" by itself
28  *  -> use own interrupt to connect/disconnect
29  *  -> it mean module clock is always ON
30  *             ~~~~~~~~~~~~~~~~~~~~~~~~~
31  */
32 static int usbhsm_autonomy_get_vbus(struct platform_device *pdev)
33 {
34 	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
35 
36 	return  VBSTS & usbhs_read(priv, INTSTS0);
37 }
38 
39 static int usbhsm_autonomy_irq_vbus(struct usbhs_priv *priv,
40 				    struct usbhs_irq_state *irq_state)
41 {
42 	struct platform_device *pdev = usbhs_priv_to_pdev(priv);
43 
44 	renesas_usbhs_call_notify_hotplug(pdev);
45 
46 	return 0;
47 }
48 
49 void usbhs_mod_autonomy_mode(struct usbhs_priv *priv)
50 {
51 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
52 
53 	info->irq_vbus		= usbhsm_autonomy_irq_vbus;
54 	priv->pfunc.get_vbus	= usbhsm_autonomy_get_vbus;
55 
56 	usbhs_irq_callback_update(priv, NULL);
57 }
58 
59 /*
60  *		host / gadget functions
61  *
62  * renesas_usbhs host/gadget can register itself by below functions.
63  * these functions are called when probe
64  *
65  */
66 void usbhs_mod_register(struct usbhs_priv *priv, struct usbhs_mod *mod, int id)
67 {
68 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
69 
70 	info->mod[id]	= mod;
71 	mod->priv	= priv;
72 }
73 
74 struct usbhs_mod *usbhs_mod_get(struct usbhs_priv *priv, int id)
75 {
76 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
77 	struct usbhs_mod *ret = NULL;
78 
79 	switch (id) {
80 	case USBHS_HOST:
81 	case USBHS_GADGET:
82 		ret = info->mod[id];
83 		break;
84 	}
85 
86 	return ret;
87 }
88 
89 int usbhs_mod_is_host(struct usbhs_priv *priv)
90 {
91 	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
92 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
93 
94 	if (!mod)
95 		return -EINVAL;
96 
97 	return info->mod[USBHS_HOST] == mod;
98 }
99 
100 struct usbhs_mod *usbhs_mod_get_current(struct usbhs_priv *priv)
101 {
102 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
103 
104 	return info->curt;
105 }
106 
107 int usbhs_mod_change(struct usbhs_priv *priv, int id)
108 {
109 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
110 	struct usbhs_mod *mod = NULL;
111 	int ret = 0;
112 
113 	/* id < 0 mean no current */
114 	switch (id) {
115 	case USBHS_HOST:
116 	case USBHS_GADGET:
117 		mod = info->mod[id];
118 		break;
119 	default:
120 		ret = -EINVAL;
121 	}
122 	info->curt = mod;
123 
124 	return ret;
125 }
126 
127 static irqreturn_t usbhs_interrupt(int irq, void *data);
128 int usbhs_mod_probe(struct usbhs_priv *priv)
129 {
130 	struct device *dev = usbhs_priv_to_dev(priv);
131 	int ret;
132 
133 	/*
134 	 * install host/gadget driver
135 	 */
136 	ret = usbhs_mod_host_probe(priv);
137 	if (ret < 0)
138 		return ret;
139 
140 	ret = usbhs_mod_gadget_probe(priv);
141 	if (ret < 0)
142 		goto mod_init_host_err;
143 
144 	/* irq settings */
145 	ret = devm_request_irq(dev, priv->irq, usbhs_interrupt,
146 			  priv->irqflags, dev_name(dev), priv);
147 	if (ret) {
148 		dev_err(dev, "irq request err\n");
149 		goto mod_init_gadget_err;
150 	}
151 
152 	return ret;
153 
154 mod_init_gadget_err:
155 	usbhs_mod_gadget_remove(priv);
156 mod_init_host_err:
157 	usbhs_mod_host_remove(priv);
158 
159 	return ret;
160 }
161 
162 void usbhs_mod_remove(struct usbhs_priv *priv)
163 {
164 	usbhs_mod_host_remove(priv);
165 	usbhs_mod_gadget_remove(priv);
166 }
167 
168 /*
169  *		status functions
170  */
171 int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state)
172 {
173 	int state = irq_state->intsts0 & DVSQ_MASK;
174 
175 	switch (state) {
176 	case POWER_STATE:
177 	case DEFAULT_STATE:
178 	case ADDRESS_STATE:
179 	case CONFIGURATION_STATE:
180 		return state;
181 	}
182 
183 	return -EIO;
184 }
185 
186 int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state)
187 {
188 	/*
189 	 * return value
190 	 *
191 	 * IDLE_SETUP_STAGE
192 	 * READ_DATA_STAGE
193 	 * READ_STATUS_STAGE
194 	 * WRITE_DATA_STAGE
195 	 * WRITE_STATUS_STAGE
196 	 * NODATA_STATUS_STAGE
197 	 * SEQUENCE_ERROR
198 	 */
199 	return (int)irq_state->intsts0 & CTSQ_MASK;
200 }
201 
202 static int usbhs_status_get_each_irq(struct usbhs_priv *priv,
203 				     struct usbhs_irq_state *state)
204 {
205 	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
206 	u16 intenb0, intenb1;
207 	unsigned long flags;
208 
209 	/********************  spin lock ********************/
210 	usbhs_lock(priv, flags);
211 	state->intsts0 = usbhs_read(priv, INTSTS0);
212 	intenb0 = usbhs_read(priv, INTENB0);
213 
214 	if (usbhs_mod_is_host(priv)) {
215 		state->intsts1 = usbhs_read(priv, INTSTS1);
216 		intenb1 = usbhs_read(priv, INTENB1);
217 	} else {
218 		state->intsts1 = intenb1 = 0;
219 	}
220 
221 	/* mask */
222 	if (mod) {
223 		state->brdysts = usbhs_read(priv, BRDYSTS);
224 		state->nrdysts = usbhs_read(priv, NRDYSTS);
225 		state->bempsts = usbhs_read(priv, BEMPSTS);
226 
227 		state->bempsts &= mod->irq_bempsts;
228 		state->brdysts &= mod->irq_brdysts;
229 	}
230 	usbhs_unlock(priv, flags);
231 	/********************  spin unlock ******************/
232 
233 	/*
234 	 * Check whether the irq enable registers and the irq status are set
235 	 * when IRQF_SHARED is set.
236 	 */
237 	if (priv->irqflags & IRQF_SHARED) {
238 		if (!(intenb0 & state->intsts0) &&
239 		    !(intenb1 & state->intsts1) &&
240 		    !(state->bempsts) &&
241 		    !(state->brdysts))
242 			return -EIO;
243 	}
244 
245 	return 0;
246 }
247 
248 /*
249  *		interrupt
250  */
251 #define INTSTS0_MAGIC 0xF800 /* acknowledge magical interrupt sources */
252 #define INTSTS1_MAGIC 0xA870 /* acknowledge magical interrupt sources */
253 static irqreturn_t usbhs_interrupt(int irq, void *data)
254 {
255 	struct usbhs_priv *priv = data;
256 	struct usbhs_irq_state irq_state;
257 
258 	if (usbhs_status_get_each_irq(priv, &irq_state) < 0)
259 		return IRQ_NONE;
260 
261 	/*
262 	 * clear interrupt
263 	 *
264 	 * The hardware is _very_ picky to clear interrupt bit.
265 	 * Especially INTSTS0_MAGIC, INTSTS1_MAGIC value.
266 	 *
267 	 * see
268 	 *	"Operation"
269 	 *	 - "Control Transfer (DCP)"
270 	 *	   - Function :: VALID bit should 0
271 	 */
272 	usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC);
273 	if (usbhs_mod_is_host(priv))
274 		usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC);
275 
276 	/*
277 	 * The driver should not clear the xxxSTS after the line of
278 	 * "call irq callback functions" because each "if" statement is
279 	 * possible to call the callback function for avoiding any side effects.
280 	 */
281 	if (irq_state.intsts0 & BRDY)
282 		usbhs_write(priv, BRDYSTS, ~irq_state.brdysts);
283 	usbhs_write(priv, NRDYSTS, ~irq_state.nrdysts);
284 	if (irq_state.intsts0 & BEMP)
285 		usbhs_write(priv, BEMPSTS, ~irq_state.bempsts);
286 
287 	/*
288 	 * call irq callback functions
289 	 * see also
290 	 *	usbhs_irq_setting_update
291 	 */
292 
293 	/* INTSTS0 */
294 	if (irq_state.intsts0 & VBINT)
295 		usbhs_mod_info_call(priv, irq_vbus, priv, &irq_state);
296 
297 	if (irq_state.intsts0 & DVST)
298 		usbhs_mod_call(priv, irq_dev_state, priv, &irq_state);
299 
300 	if (irq_state.intsts0 & CTRT)
301 		usbhs_mod_call(priv, irq_ctrl_stage, priv, &irq_state);
302 
303 	if (irq_state.intsts0 & BEMP)
304 		usbhs_mod_call(priv, irq_empty, priv, &irq_state);
305 
306 	if (irq_state.intsts0 & BRDY)
307 		usbhs_mod_call(priv, irq_ready, priv, &irq_state);
308 
309 	if (usbhs_mod_is_host(priv)) {
310 		/* INTSTS1 */
311 		if (irq_state.intsts1 & ATTCH)
312 			usbhs_mod_call(priv, irq_attch, priv, &irq_state);
313 
314 		if (irq_state.intsts1 & DTCH)
315 			usbhs_mod_call(priv, irq_dtch, priv, &irq_state);
316 
317 		if (irq_state.intsts1 & SIGN)
318 			usbhs_mod_call(priv, irq_sign, priv, &irq_state);
319 
320 		if (irq_state.intsts1 & SACK)
321 			usbhs_mod_call(priv, irq_sack, priv, &irq_state);
322 	}
323 	return IRQ_HANDLED;
324 }
325 
326 void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod)
327 {
328 	u16 intenb0 = 0;
329 	u16 intenb1 = 0;
330 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
331 
332 	/*
333 	 * BEMPENB/BRDYENB are picky.
334 	 * below method is required
335 	 *
336 	 *  - clear  INTSTS0
337 	 *  - update BEMPENB/BRDYENB
338 	 *  - update INTSTS0
339 	 */
340 	usbhs_write(priv, INTENB0, 0);
341 	if (usbhs_mod_is_host(priv))
342 		usbhs_write(priv, INTENB1, 0);
343 
344 	usbhs_write(priv, BEMPENB, 0);
345 	usbhs_write(priv, BRDYENB, 0);
346 
347 	/*
348 	 * see also
349 	 *	usbhs_interrupt
350 	 */
351 
352 	/*
353 	 * it don't enable DVSE (intenb0) here
354 	 * but "mod->irq_dev_state" will be called.
355 	 */
356 	if (info->irq_vbus)
357 		intenb0 |= VBSE;
358 
359 	if (mod) {
360 		/*
361 		 * INTSTS0
362 		 */
363 		if (mod->irq_ctrl_stage)
364 			intenb0 |= CTRE;
365 
366 		if (mod->irq_empty && mod->irq_bempsts) {
367 			usbhs_write(priv, BEMPENB, mod->irq_bempsts);
368 			intenb0 |= BEMPE;
369 		}
370 
371 		if (mod->irq_ready && mod->irq_brdysts) {
372 			usbhs_write(priv, BRDYENB, mod->irq_brdysts);
373 			intenb0 |= BRDYE;
374 		}
375 
376 		if (usbhs_mod_is_host(priv)) {
377 			/*
378 			 * INTSTS1
379 			 */
380 			if (mod->irq_attch)
381 				intenb1 |= ATTCHE;
382 
383 			if (mod->irq_dtch)
384 				intenb1 |= DTCHE;
385 
386 			if (mod->irq_sign)
387 				intenb1 |= SIGNE;
388 
389 			if (mod->irq_sack)
390 				intenb1 |= SACKE;
391 		}
392 	}
393 
394 	if (intenb0)
395 		usbhs_write(priv, INTENB0, intenb0);
396 
397 	if (usbhs_mod_is_host(priv) && intenb1)
398 		usbhs_write(priv, INTENB1, intenb1);
399 }
400