blob: 540472abb23a55572b18e8e51177f78660234403 [file] [log] [blame]
Greg Kroah-Hartman5fd54ac2017-11-03 11:28:30 +01001// SPDX-License-Identifier: GPL-1.0+
Kuninori Morimotof1407d52011-04-04 13:44:59 +09002/*
3 * Renesas USB driver
4 *
5 * Copyright (C) 2011 Renesas Solutions Corp.
Yoshihiro Shimoda09666482019-06-25 14:38:46 +09006 * Copyright (C) 2019 Renesas Electronics Corporation
Kuninori Morimotof1407d52011-04-04 13:44:59 +09007 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Kuninori Morimotof1407d52011-04-04 13:44:59 +09008 */
9#include <linux/interrupt.h>
10
Paul Bollecc502bb2012-06-03 18:39:13 +020011#include "common.h"
12#include "mod.h"
Kuninori Morimotof1407d52011-04-04 13:44:59 +090013
14#define usbhs_priv_to_modinfo(priv) (&priv->mod_info)
Kuninori Morimotob002ff62011-04-28 16:41:20 +090015#define usbhs_mod_info_call(priv, func, param...) \
16({ \
17 struct usbhs_mod_info *info; \
18 info = usbhs_priv_to_modinfo(priv); \
19 !info->func ? 0 : \
20 info->func(param); \
21})
22
23/*
24 * autonomy
25 *
26 * these functions are used if platform doesn't have external phy.
27 * -> there is no "notify_hotplug" callback from platform
28 * -> call "notify_hotplug" by itself
29 * -> use own interrupt to connect/disconnect
30 * -> it mean module clock is always ON
31 * ~~~~~~~~~~~~~~~~~~~~~~~~~
32 */
33static int usbhsm_autonomy_get_vbus(struct platform_device *pdev)
34{
35 struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
36
37 return VBSTS & usbhs_read(priv, INTSTS0);
38}
39
40static int usbhsm_autonomy_irq_vbus(struct usbhs_priv *priv,
41 struct usbhs_irq_state *irq_state)
42{
43 struct platform_device *pdev = usbhs_priv_to_pdev(priv);
44
Yoshihiro Shimoda09666482019-06-25 14:38:46 +090045 usbhsc_schedule_notify_hotplug(pdev);
Kuninori Morimotob4fcea22011-10-24 02:25:48 -070046
47 return 0;
Kuninori Morimotob002ff62011-04-28 16:41:20 +090048}
49
50void usbhs_mod_autonomy_mode(struct usbhs_priv *priv)
51{
52 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
53
54 info->irq_vbus = usbhsm_autonomy_irq_vbus;
Kuninori Morimoto48298202011-10-12 21:02:22 -070055 priv->pfunc.get_vbus = usbhsm_autonomy_get_vbus;
Kuninori Morimotob002ff62011-04-28 16:41:20 +090056
57 usbhs_irq_callback_update(priv, NULL);
58}
Kuninori Morimotof1407d52011-04-04 13:44:59 +090059
60/*
61 * host / gadget functions
62 *
63 * renesas_usbhs host/gadget can register itself by below functions.
64 * these functions are called when probe
65 *
66 */
67void usbhs_mod_register(struct usbhs_priv *priv, struct usbhs_mod *mod, int id)
68{
69 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
70
71 info->mod[id] = mod;
72 mod->priv = priv;
73}
74
75struct usbhs_mod *usbhs_mod_get(struct usbhs_priv *priv, int id)
76{
77 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
78 struct usbhs_mod *ret = NULL;
79
80 switch (id) {
81 case USBHS_HOST:
82 case USBHS_GADGET:
83 ret = info->mod[id];
84 break;
85 }
86
87 return ret;
88}
89
Kuninori Morimoto0deb3e72011-10-10 22:02:45 -070090int usbhs_mod_is_host(struct usbhs_priv *priv)
Kuninori Morimotof1407d52011-04-04 13:44:59 +090091{
Kuninori Morimoto0deb3e72011-10-10 22:02:45 -070092 struct usbhs_mod *mod = usbhs_mod_get_current(priv);
Kuninori Morimotof1407d52011-04-04 13:44:59 +090093 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
94
95 if (!mod)
96 return -EINVAL;
97
98 return info->mod[USBHS_HOST] == mod;
99}
100
101struct usbhs_mod *usbhs_mod_get_current(struct usbhs_priv *priv)
102{
103 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
104
105 return info->curt;
106}
107
108int usbhs_mod_change(struct usbhs_priv *priv, int id)
109{
110 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
111 struct usbhs_mod *mod = NULL;
112 int ret = 0;
113
114 /* id < 0 mean no current */
115 switch (id) {
116 case USBHS_HOST:
117 case USBHS_GADGET:
118 mod = info->mod[id];
119 break;
120 default:
121 ret = -EINVAL;
122 }
123 info->curt = mod;
124
125 return ret;
126}
127
128static irqreturn_t usbhs_interrupt(int irq, void *data);
129int usbhs_mod_probe(struct usbhs_priv *priv)
130{
131 struct device *dev = usbhs_priv_to_dev(priv);
132 int ret;
133
Kuninori Morimoto2f983822011-04-05 11:40:54 +0900134 /*
135 * install host/gadget driver
136 */
Kuninori Morimoto034d7c12011-10-10 22:07:40 -0700137 ret = usbhs_mod_host_probe(priv);
Kuninori Morimoto2f983822011-04-05 11:40:54 +0900138 if (ret < 0)
139 return ret;
140
Kuninori Morimoto034d7c12011-10-10 22:07:40 -0700141 ret = usbhs_mod_gadget_probe(priv);
142 if (ret < 0)
143 goto mod_init_host_err;
144
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900145 /* irq settings */
Kuninori Morimoto797b4e12012-10-29 00:44:41 -0700146 ret = devm_request_irq(dev, priv->irq, usbhs_interrupt,
Shimoda, Yoshihiro53069af2012-01-05 15:37:18 +0900147 priv->irqflags, dev_name(dev), priv);
Kuninori Morimoto2f983822011-04-05 11:40:54 +0900148 if (ret) {
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900149 dev_err(dev, "irq request err\n");
Kuninori Morimoto2f983822011-04-05 11:40:54 +0900150 goto mod_init_gadget_err;
151 }
152
153 return ret;
154
155mod_init_gadget_err:
156 usbhs_mod_gadget_remove(priv);
Kuninori Morimoto034d7c12011-10-10 22:07:40 -0700157mod_init_host_err:
158 usbhs_mod_host_remove(priv);
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900159
160 return ret;
161}
162
163void usbhs_mod_remove(struct usbhs_priv *priv)
164{
Kuninori Morimoto034d7c12011-10-10 22:07:40 -0700165 usbhs_mod_host_remove(priv);
Kuninori Morimoto2f983822011-04-05 11:40:54 +0900166 usbhs_mod_gadget_remove(priv);
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900167}
168
169/*
170 * status functions
171 */
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900172int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state)
173{
174 int state = irq_state->intsts0 & DVSQ_MASK;
175
176 switch (state) {
177 case POWER_STATE:
178 case DEFAULT_STATE:
179 case ADDRESS_STATE:
180 case CONFIGURATION_STATE:
181 return state;
182 }
183
184 return -EIO;
185}
186
187int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state)
188{
189 /*
190 * return value
191 *
192 * IDLE_SETUP_STAGE
193 * READ_DATA_STAGE
194 * READ_STATUS_STAGE
195 * WRITE_DATA_STAGE
196 * WRITE_STATUS_STAGE
197 * NODATA_STATUS_STAGE
198 * SEQUENCE_ERROR
199 */
200 return (int)irq_state->intsts0 & CTSQ_MASK;
201}
202
Shimoda, Yoshihiro697d5c02012-08-20 18:39:23 +0900203static int usbhs_status_get_each_irq(struct usbhs_priv *priv,
204 struct usbhs_irq_state *state)
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900205{
206 struct usbhs_mod *mod = usbhs_mod_get_current(priv);
Shimoda, Yoshihiro697d5c02012-08-20 18:39:23 +0900207 u16 intenb0, intenb1;
Yoshihiro Shimodac4d81992014-08-22 20:14:00 +0900208 unsigned long flags;
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900209
Yoshihiro Shimodac4d81992014-08-22 20:14:00 +0900210 /******************** spin lock ********************/
211 usbhs_lock(priv, flags);
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900212 state->intsts0 = usbhs_read(priv, INTSTS0);
Shimoda, Yoshihiro697d5c02012-08-20 18:39:23 +0900213 intenb0 = usbhs_read(priv, INTENB0);
Nobuhiro Iwamatsu88a25e02015-01-09 09:28:41 +0900214
215 if (usbhs_mod_is_host(priv)) {
216 state->intsts1 = usbhs_read(priv, INTSTS1);
217 intenb1 = usbhs_read(priv, INTENB1);
Arnd Bergmann672bfda2015-05-22 13:06:35 +0200218 } else {
219 state->intsts1 = intenb1 = 0;
Nobuhiro Iwamatsu88a25e02015-01-09 09:28:41 +0900220 }
Shimoda, Yoshihiro697d5c02012-08-20 18:39:23 +0900221
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900222 /* mask */
Kuninori Morimoto5ea68d52011-04-28 16:41:07 +0900223 if (mod) {
224 state->brdysts = usbhs_read(priv, BRDYSTS);
225 state->nrdysts = usbhs_read(priv, NRDYSTS);
226 state->bempsts = usbhs_read(priv, BEMPSTS);
227
228 state->bempsts &= mod->irq_bempsts;
229 state->brdysts &= mod->irq_brdysts;
230 }
Yoshihiro Shimodac4d81992014-08-22 20:14:00 +0900231 usbhs_unlock(priv, flags);
232 /******************** spin unlock ******************/
Shimoda, Yoshihiro697d5c02012-08-20 18:39:23 +0900233
234 /*
235 * Check whether the irq enable registers and the irq status are set
236 * when IRQF_SHARED is set.
237 */
238 if (priv->irqflags & IRQF_SHARED) {
239 if (!(intenb0 & state->intsts0) &&
240 !(intenb1 & state->intsts1) &&
241 !(state->bempsts) &&
242 !(state->brdysts))
243 return -EIO;
244 }
245
246 return 0;
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900247}
248
249/*
250 * interrupt
251 */
252#define INTSTS0_MAGIC 0xF800 /* acknowledge magical interrupt sources */
253#define INTSTS1_MAGIC 0xA870 /* acknowledge magical interrupt sources */
254static irqreturn_t usbhs_interrupt(int irq, void *data)
255{
256 struct usbhs_priv *priv = data;
257 struct usbhs_irq_state irq_state;
258
Shimoda, Yoshihiro697d5c02012-08-20 18:39:23 +0900259 if (usbhs_status_get_each_irq(priv, &irq_state) < 0)
260 return IRQ_NONE;
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900261
262 /*
263 * clear interrupt
264 *
265 * The hardware is _very_ picky to clear interrupt bit.
266 * Especially INTSTS0_MAGIC, INTSTS1_MAGIC value.
267 *
268 * see
269 * "Operation"
270 * - "Control Transfer (DCP)"
271 * - Function :: VALID bit should 0
272 */
273 usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC);
Nobuhiro Iwamatsu88a25e02015-01-09 09:28:41 +0900274 if (usbhs_mod_is_host(priv))
275 usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC);
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900276
Yoshihiro Shimoda519d8bd2016-08-29 18:00:38 +0900277 /*
278 * The driver should not clear the xxxSTS after the line of
279 * "call irq callback functions" because each "if" statement is
280 * possible to call the callback function for avoiding any side effects.
281 */
282 if (irq_state.intsts0 & BRDY)
283 usbhs_write(priv, BRDYSTS, ~irq_state.brdysts);
Kuninori Morimotod5c6a1e2012-10-11 21:49:38 -0700284 usbhs_write(priv, NRDYSTS, ~irq_state.nrdysts);
Yoshihiro Shimoda519d8bd2016-08-29 18:00:38 +0900285 if (irq_state.intsts0 & BEMP)
286 usbhs_write(priv, BEMPSTS, ~irq_state.bempsts);
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900287
288 /*
289 * call irq callback functions
290 * see also
291 * usbhs_irq_setting_update
292 */
Kuninori Morimoto89c1d2e2011-10-10 22:06:57 -0700293
294 /* INTSTS0 */
Kuninori Morimotob002ff62011-04-28 16:41:20 +0900295 if (irq_state.intsts0 & VBINT)
296 usbhs_mod_info_call(priv, irq_vbus, priv, &irq_state);
297
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900298 if (irq_state.intsts0 & DVST)
299 usbhs_mod_call(priv, irq_dev_state, priv, &irq_state);
300
301 if (irq_state.intsts0 & CTRT)
302 usbhs_mod_call(priv, irq_ctrl_stage, priv, &irq_state);
303
304 if (irq_state.intsts0 & BEMP)
305 usbhs_mod_call(priv, irq_empty, priv, &irq_state);
306
307 if (irq_state.intsts0 & BRDY)
308 usbhs_mod_call(priv, irq_ready, priv, &irq_state);
309
Nobuhiro Iwamatsu88a25e02015-01-09 09:28:41 +0900310 if (usbhs_mod_is_host(priv)) {
311 /* INTSTS1 */
312 if (irq_state.intsts1 & ATTCH)
313 usbhs_mod_call(priv, irq_attch, priv, &irq_state);
Kuninori Morimoto89c1d2e2011-10-10 22:06:57 -0700314
Nobuhiro Iwamatsu88a25e02015-01-09 09:28:41 +0900315 if (irq_state.intsts1 & DTCH)
316 usbhs_mod_call(priv, irq_dtch, priv, &irq_state);
Kuninori Morimoto89c1d2e2011-10-10 22:06:57 -0700317
Nobuhiro Iwamatsu88a25e02015-01-09 09:28:41 +0900318 if (irq_state.intsts1 & SIGN)
319 usbhs_mod_call(priv, irq_sign, priv, &irq_state);
Kuninori Morimoto89c1d2e2011-10-10 22:06:57 -0700320
Nobuhiro Iwamatsu88a25e02015-01-09 09:28:41 +0900321 if (irq_state.intsts1 & SACK)
322 usbhs_mod_call(priv, irq_sack, priv, &irq_state);
323 }
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900324 return IRQ_HANDLED;
325}
326
327void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod)
328{
329 u16 intenb0 = 0;
Kuninori Morimoto89c1d2e2011-10-10 22:06:57 -0700330 u16 intenb1 = 0;
Kuninori Morimotob002ff62011-04-28 16:41:20 +0900331 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900332
Kuninori Morimoto651f5e42011-10-10 22:01:15 -0700333 /*
334 * BEMPENB/BRDYENB are picky.
335 * below method is required
336 *
337 * - clear INTSTS0
338 * - update BEMPENB/BRDYENB
339 * - update INTSTS0
340 */
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900341 usbhs_write(priv, INTENB0, 0);
Nobuhiro Iwamatsu88a25e02015-01-09 09:28:41 +0900342 if (usbhs_mod_is_host(priv))
343 usbhs_write(priv, INTENB1, 0);
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900344
345 usbhs_write(priv, BEMPENB, 0);
346 usbhs_write(priv, BRDYENB, 0);
347
348 /*
349 * see also
350 * usbhs_interrupt
351 */
352
353 /*
354 * it don't enable DVSE (intenb0) here
355 * but "mod->irq_dev_state" will be called.
356 */
Kuninori Morimotob002ff62011-04-28 16:41:20 +0900357 if (info->irq_vbus)
358 intenb0 |= VBSE;
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900359
Kuninori Morimoto5ea68d52011-04-28 16:41:07 +0900360 if (mod) {
Kuninori Morimoto89c1d2e2011-10-10 22:06:57 -0700361 /*
362 * INTSTS0
363 */
Kuninori Morimoto5ea68d52011-04-28 16:41:07 +0900364 if (mod->irq_ctrl_stage)
365 intenb0 |= CTRE;
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900366
Kuninori Morimoto5ea68d52011-04-28 16:41:07 +0900367 if (mod->irq_empty && mod->irq_bempsts) {
368 usbhs_write(priv, BEMPENB, mod->irq_bempsts);
369 intenb0 |= BEMPE;
370 }
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900371
Kuninori Morimoto5ea68d52011-04-28 16:41:07 +0900372 if (mod->irq_ready && mod->irq_brdysts) {
373 usbhs_write(priv, BRDYENB, mod->irq_brdysts);
374 intenb0 |= BRDYE;
375 }
Kuninori Morimoto89c1d2e2011-10-10 22:06:57 -0700376
Nobuhiro Iwamatsu88a25e02015-01-09 09:28:41 +0900377 if (usbhs_mod_is_host(priv)) {
378 /*
379 * INTSTS1
380 */
381 if (mod->irq_attch)
382 intenb1 |= ATTCHE;
Kuninori Morimoto89c1d2e2011-10-10 22:06:57 -0700383
Nobuhiro Iwamatsu88a25e02015-01-09 09:28:41 +0900384 if (mod->irq_dtch)
385 intenb1 |= DTCHE;
Kuninori Morimoto89c1d2e2011-10-10 22:06:57 -0700386
Nobuhiro Iwamatsu88a25e02015-01-09 09:28:41 +0900387 if (mod->irq_sign)
388 intenb1 |= SIGNE;
Kuninori Morimoto89c1d2e2011-10-10 22:06:57 -0700389
Nobuhiro Iwamatsu88a25e02015-01-09 09:28:41 +0900390 if (mod->irq_sack)
391 intenb1 |= SACKE;
392 }
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900393 }
394
Kuninori Morimoto651f5e42011-10-10 22:01:15 -0700395 if (intenb0)
396 usbhs_write(priv, INTENB0, intenb0);
Kuninori Morimoto89c1d2e2011-10-10 22:06:57 -0700397
Nobuhiro Iwamatsu88a25e02015-01-09 09:28:41 +0900398 if (usbhs_mod_is_host(priv) && intenb1)
Kuninori Morimoto89c1d2e2011-10-10 22:06:57 -0700399 usbhs_write(priv, INTENB1, intenb1);
Kuninori Morimotof1407d52011-04-04 13:44:59 +0900400}