xref: /openbmc/linux/drivers/usb/renesas_usbhs/mod.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-1.0+
2f1407d5cSKuninori Morimoto /*
3f1407d5cSKuninori Morimoto  * Renesas USB driver
4f1407d5cSKuninori Morimoto  *
5f1407d5cSKuninori Morimoto  * Copyright (C) 2011 Renesas Solutions Corp.
60966648dSYoshihiro Shimoda  * Copyright (C) 2019 Renesas Electronics Corporation
7f1407d5cSKuninori Morimoto  * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
8f1407d5cSKuninori Morimoto  */
9f1407d5cSKuninori Morimoto #include <linux/interrupt.h>
10f1407d5cSKuninori Morimoto 
11cc502bb7SPaul Bolle #include "common.h"
12cc502bb7SPaul Bolle #include "mod.h"
13f1407d5cSKuninori Morimoto 
14b002ff6eSKuninori Morimoto /*
15b002ff6eSKuninori Morimoto  *		autonomy
16b002ff6eSKuninori Morimoto  *
17b002ff6eSKuninori Morimoto  * these functions are used if platform doesn't have external phy.
18b002ff6eSKuninori Morimoto  *  -> there is no "notify_hotplug" callback from platform
19b002ff6eSKuninori Morimoto  *  -> call "notify_hotplug" by itself
20b002ff6eSKuninori Morimoto  *  -> use own interrupt to connect/disconnect
21b002ff6eSKuninori Morimoto  *  -> it mean module clock is always ON
22b002ff6eSKuninori Morimoto  *             ~~~~~~~~~~~~~~~~~~~~~~~~~
23b002ff6eSKuninori Morimoto  */
usbhsm_autonomy_get_vbus(struct platform_device * pdev)24b002ff6eSKuninori Morimoto static int usbhsm_autonomy_get_vbus(struct platform_device *pdev)
25b002ff6eSKuninori Morimoto {
26b002ff6eSKuninori Morimoto 	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
27b002ff6eSKuninori Morimoto 
28b002ff6eSKuninori Morimoto 	return  VBSTS & usbhs_read(priv, INTSTS0);
29b002ff6eSKuninori Morimoto }
30b002ff6eSKuninori Morimoto 
usbhsm_autonomy_irq_vbus(struct usbhs_priv * priv,struct usbhs_irq_state * irq_state)31b002ff6eSKuninori Morimoto static int usbhsm_autonomy_irq_vbus(struct usbhs_priv *priv,
32b002ff6eSKuninori Morimoto 				    struct usbhs_irq_state *irq_state)
33b002ff6eSKuninori Morimoto {
34b002ff6eSKuninori Morimoto 	struct platform_device *pdev = usbhs_priv_to_pdev(priv);
35b002ff6eSKuninori Morimoto 
360966648dSYoshihiro Shimoda 	usbhsc_schedule_notify_hotplug(pdev);
37b4fcea2aSKuninori Morimoto 
38b4fcea2aSKuninori Morimoto 	return 0;
39b002ff6eSKuninori Morimoto }
40b002ff6eSKuninori Morimoto 
usbhs_mod_autonomy_mode(struct usbhs_priv * priv)41b002ff6eSKuninori Morimoto void usbhs_mod_autonomy_mode(struct usbhs_priv *priv)
42b002ff6eSKuninori Morimoto {
43b002ff6eSKuninori Morimoto 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
44b002ff6eSKuninori Morimoto 
45b002ff6eSKuninori Morimoto 	info->irq_vbus = usbhsm_autonomy_irq_vbus;
46ccc3264cSYoshihiro Shimoda 	info->get_vbus = usbhsm_autonomy_get_vbus;
47b002ff6eSKuninori Morimoto 
48b002ff6eSKuninori Morimoto 	usbhs_irq_callback_update(priv, NULL);
49b002ff6eSKuninori Morimoto }
50f1407d5cSKuninori Morimoto 
usbhs_mod_non_autonomy_mode(struct usbhs_priv * priv)51ccc3264cSYoshihiro Shimoda void usbhs_mod_non_autonomy_mode(struct usbhs_priv *priv)
52ccc3264cSYoshihiro Shimoda {
53ccc3264cSYoshihiro Shimoda 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
54ccc3264cSYoshihiro Shimoda 
55426d3ff2SYoshihiro Shimoda 	info->get_vbus = priv->pfunc->get_vbus;
56ccc3264cSYoshihiro Shimoda }
57ccc3264cSYoshihiro Shimoda 
58f1407d5cSKuninori Morimoto /*
59f1407d5cSKuninori Morimoto  *		host / gadget functions
60f1407d5cSKuninori Morimoto  *
61f1407d5cSKuninori Morimoto  * renesas_usbhs host/gadget can register itself by below functions.
62f1407d5cSKuninori Morimoto  * these functions are called when probe
63f1407d5cSKuninori Morimoto  *
64f1407d5cSKuninori Morimoto  */
usbhs_mod_register(struct usbhs_priv * priv,struct usbhs_mod * mod,int id)65f1407d5cSKuninori Morimoto void usbhs_mod_register(struct usbhs_priv *priv, struct usbhs_mod *mod, int id)
66f1407d5cSKuninori Morimoto {
67f1407d5cSKuninori Morimoto 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
68f1407d5cSKuninori Morimoto 
69f1407d5cSKuninori Morimoto 	info->mod[id]	= mod;
70f1407d5cSKuninori Morimoto 	mod->priv	= priv;
71f1407d5cSKuninori Morimoto }
72f1407d5cSKuninori Morimoto 
usbhs_mod_get(struct usbhs_priv * priv,int id)73f1407d5cSKuninori Morimoto struct usbhs_mod *usbhs_mod_get(struct usbhs_priv *priv, int id)
74f1407d5cSKuninori Morimoto {
75f1407d5cSKuninori Morimoto 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
76f1407d5cSKuninori Morimoto 	struct usbhs_mod *ret = NULL;
77f1407d5cSKuninori Morimoto 
78f1407d5cSKuninori Morimoto 	switch (id) {
79f1407d5cSKuninori Morimoto 	case USBHS_HOST:
80f1407d5cSKuninori Morimoto 	case USBHS_GADGET:
81f1407d5cSKuninori Morimoto 		ret = info->mod[id];
82f1407d5cSKuninori Morimoto 		break;
83f1407d5cSKuninori Morimoto 	}
84f1407d5cSKuninori Morimoto 
85f1407d5cSKuninori Morimoto 	return ret;
86f1407d5cSKuninori Morimoto }
87f1407d5cSKuninori Morimoto 
usbhs_mod_is_host(struct usbhs_priv * priv)880deb3e77SKuninori Morimoto int usbhs_mod_is_host(struct usbhs_priv *priv)
89f1407d5cSKuninori Morimoto {
900deb3e77SKuninori Morimoto 	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
91f1407d5cSKuninori Morimoto 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
92f1407d5cSKuninori Morimoto 
93f1407d5cSKuninori Morimoto 	if (!mod)
94f1407d5cSKuninori Morimoto 		return -EINVAL;
95f1407d5cSKuninori Morimoto 
96f1407d5cSKuninori Morimoto 	return info->mod[USBHS_HOST] == mod;
97f1407d5cSKuninori Morimoto }
98f1407d5cSKuninori Morimoto 
usbhs_mod_get_current(struct usbhs_priv * priv)99f1407d5cSKuninori Morimoto struct usbhs_mod *usbhs_mod_get_current(struct usbhs_priv *priv)
100f1407d5cSKuninori Morimoto {
101f1407d5cSKuninori Morimoto 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
102f1407d5cSKuninori Morimoto 
103f1407d5cSKuninori Morimoto 	return info->curt;
104f1407d5cSKuninori Morimoto }
105f1407d5cSKuninori Morimoto 
usbhs_mod_change(struct usbhs_priv * priv,int id)106f1407d5cSKuninori Morimoto int usbhs_mod_change(struct usbhs_priv *priv, int id)
107f1407d5cSKuninori Morimoto {
108f1407d5cSKuninori Morimoto 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
109f1407d5cSKuninori Morimoto 	struct usbhs_mod *mod = NULL;
110f1407d5cSKuninori Morimoto 	int ret = 0;
111f1407d5cSKuninori Morimoto 
112f1407d5cSKuninori Morimoto 	/* id < 0 mean no current */
113f1407d5cSKuninori Morimoto 	switch (id) {
114f1407d5cSKuninori Morimoto 	case USBHS_HOST:
115f1407d5cSKuninori Morimoto 	case USBHS_GADGET:
116f1407d5cSKuninori Morimoto 		mod = info->mod[id];
117f1407d5cSKuninori Morimoto 		break;
118f1407d5cSKuninori Morimoto 	default:
119f1407d5cSKuninori Morimoto 		ret = -EINVAL;
120f1407d5cSKuninori Morimoto 	}
121f1407d5cSKuninori Morimoto 	info->curt = mod;
122f1407d5cSKuninori Morimoto 
123f1407d5cSKuninori Morimoto 	return ret;
124f1407d5cSKuninori Morimoto }
125f1407d5cSKuninori Morimoto 
126f1407d5cSKuninori Morimoto static irqreturn_t usbhs_interrupt(int irq, void *data);
usbhs_mod_probe(struct usbhs_priv * priv)127f1407d5cSKuninori Morimoto int usbhs_mod_probe(struct usbhs_priv *priv)
128f1407d5cSKuninori Morimoto {
129f1407d5cSKuninori Morimoto 	struct device *dev = usbhs_priv_to_dev(priv);
130f1407d5cSKuninori Morimoto 	int ret;
131f1407d5cSKuninori Morimoto 
1322f98382dSKuninori Morimoto 	/*
1332f98382dSKuninori Morimoto 	 * install host/gadget driver
1342f98382dSKuninori Morimoto 	 */
135034d7c13SKuninori Morimoto 	ret = usbhs_mod_host_probe(priv);
1362f98382dSKuninori Morimoto 	if (ret < 0)
1372f98382dSKuninori Morimoto 		return ret;
1382f98382dSKuninori Morimoto 
139034d7c13SKuninori Morimoto 	ret = usbhs_mod_gadget_probe(priv);
140034d7c13SKuninori Morimoto 	if (ret < 0)
141034d7c13SKuninori Morimoto 		goto mod_init_host_err;
142034d7c13SKuninori Morimoto 
143f1407d5cSKuninori Morimoto 	/* irq settings */
144797b4e14SKuninori Morimoto 	ret = devm_request_irq(dev, priv->irq, usbhs_interrupt,
145*22ae6415SLad Prabhakar 			       0, dev_name(dev), priv);
1462f98382dSKuninori Morimoto 	if (ret) {
147f1407d5cSKuninori Morimoto 		dev_err(dev, "irq request err\n");
1482f98382dSKuninori Morimoto 		goto mod_init_gadget_err;
1492f98382dSKuninori Morimoto 	}
1502f98382dSKuninori Morimoto 
1512f98382dSKuninori Morimoto 	return ret;
1522f98382dSKuninori Morimoto 
1532f98382dSKuninori Morimoto mod_init_gadget_err:
1542f98382dSKuninori Morimoto 	usbhs_mod_gadget_remove(priv);
155034d7c13SKuninori Morimoto mod_init_host_err:
156034d7c13SKuninori Morimoto 	usbhs_mod_host_remove(priv);
157f1407d5cSKuninori Morimoto 
158f1407d5cSKuninori Morimoto 	return ret;
159f1407d5cSKuninori Morimoto }
160f1407d5cSKuninori Morimoto 
usbhs_mod_remove(struct usbhs_priv * priv)161f1407d5cSKuninori Morimoto void usbhs_mod_remove(struct usbhs_priv *priv)
162f1407d5cSKuninori Morimoto {
163034d7c13SKuninori Morimoto 	usbhs_mod_host_remove(priv);
1642f98382dSKuninori Morimoto 	usbhs_mod_gadget_remove(priv);
165f1407d5cSKuninori Morimoto }
166f1407d5cSKuninori Morimoto 
167f1407d5cSKuninori Morimoto /*
168f1407d5cSKuninori Morimoto  *		status functions
169f1407d5cSKuninori Morimoto  */
usbhs_status_get_device_state(struct usbhs_irq_state * irq_state)170f1407d5cSKuninori Morimoto int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state)
171f1407d5cSKuninori Morimoto {
1725022204aSEugeniu Rosca 	return (int)irq_state->intsts0 & DVSQ_MASK;
173f1407d5cSKuninori Morimoto }
174f1407d5cSKuninori Morimoto 
usbhs_status_get_ctrl_stage(struct usbhs_irq_state * irq_state)175f1407d5cSKuninori Morimoto int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state)
176f1407d5cSKuninori Morimoto {
177f1407d5cSKuninori Morimoto 	/*
178f1407d5cSKuninori Morimoto 	 * return value
179f1407d5cSKuninori Morimoto 	 *
180f1407d5cSKuninori Morimoto 	 * IDLE_SETUP_STAGE
181f1407d5cSKuninori Morimoto 	 * READ_DATA_STAGE
182f1407d5cSKuninori Morimoto 	 * READ_STATUS_STAGE
183f1407d5cSKuninori Morimoto 	 * WRITE_DATA_STAGE
184f1407d5cSKuninori Morimoto 	 * WRITE_STATUS_STAGE
185f1407d5cSKuninori Morimoto 	 * NODATA_STATUS_STAGE
186f1407d5cSKuninori Morimoto 	 * SEQUENCE_ERROR
187f1407d5cSKuninori Morimoto 	 */
188f1407d5cSKuninori Morimoto 	return (int)irq_state->intsts0 & CTSQ_MASK;
189f1407d5cSKuninori Morimoto }
190f1407d5cSKuninori Morimoto 
usbhs_status_get_each_irq(struct usbhs_priv * priv,struct usbhs_irq_state * state)191697d5c00SShimoda, Yoshihiro static int usbhs_status_get_each_irq(struct usbhs_priv *priv,
192f1407d5cSKuninori Morimoto 				     struct usbhs_irq_state *state)
193f1407d5cSKuninori Morimoto {
194f1407d5cSKuninori Morimoto 	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
195697d5c00SShimoda, Yoshihiro 	u16 intenb0, intenb1;
196c4d8199bSYoshihiro Shimoda 	unsigned long flags;
197f1407d5cSKuninori Morimoto 
198c4d8199bSYoshihiro Shimoda 	/********************  spin lock ********************/
199c4d8199bSYoshihiro Shimoda 	usbhs_lock(priv, flags);
200f1407d5cSKuninori Morimoto 	state->intsts0 = usbhs_read(priv, INTSTS0);
201697d5c00SShimoda, Yoshihiro 	intenb0 = usbhs_read(priv, INTENB0);
20288a25e02SNobuhiro Iwamatsu 
20388a25e02SNobuhiro Iwamatsu 	if (usbhs_mod_is_host(priv)) {
20488a25e02SNobuhiro Iwamatsu 		state->intsts1 = usbhs_read(priv, INTSTS1);
205697d5c00SShimoda, Yoshihiro 		intenb1 = usbhs_read(priv, INTENB1);
206672bfdaaSArnd Bergmann 	} else {
207672bfdaaSArnd Bergmann 		state->intsts1 = intenb1 = 0;
20888a25e02SNobuhiro Iwamatsu 	}
209697d5c00SShimoda, Yoshihiro 
2105ea68d54SKuninori Morimoto 	/* mask */
2115ea68d54SKuninori Morimoto 	if (mod) {
212f1407d5cSKuninori Morimoto 		state->brdysts = usbhs_read(priv, BRDYSTS);
213f1407d5cSKuninori Morimoto 		state->nrdysts = usbhs_read(priv, NRDYSTS);
214f1407d5cSKuninori Morimoto 		state->bempsts = usbhs_read(priv, BEMPSTS);
215f1407d5cSKuninori Morimoto 
216f1407d5cSKuninori Morimoto 		state->bempsts &= mod->irq_bempsts;
217f1407d5cSKuninori Morimoto 		state->brdysts &= mod->irq_brdysts;
218f1407d5cSKuninori Morimoto 	}
219c4d8199bSYoshihiro Shimoda 	usbhs_unlock(priv, flags);
220c4d8199bSYoshihiro Shimoda 	/********************  spin unlock ******************/
221697d5c00SShimoda, Yoshihiro 
222697d5c00SShimoda, Yoshihiro 	return 0;
2235ea68d54SKuninori Morimoto }
224f1407d5cSKuninori Morimoto 
225f1407d5cSKuninori Morimoto /*
226f1407d5cSKuninori Morimoto  *		interrupt
227f1407d5cSKuninori Morimoto  */
228f1407d5cSKuninori Morimoto #define INTSTS0_MAGIC 0xF800 /* acknowledge magical interrupt sources */
229f1407d5cSKuninori Morimoto #define INTSTS1_MAGIC 0xA870 /* acknowledge magical interrupt sources */
usbhs_interrupt(int irq,void * data)230f1407d5cSKuninori Morimoto static irqreturn_t usbhs_interrupt(int irq, void *data)
231f1407d5cSKuninori Morimoto {
232f1407d5cSKuninori Morimoto 	struct usbhs_priv *priv = data;
233f1407d5cSKuninori Morimoto 	struct usbhs_irq_state irq_state;
234f1407d5cSKuninori Morimoto 
235697d5c00SShimoda, Yoshihiro 	if (usbhs_status_get_each_irq(priv, &irq_state) < 0)
236697d5c00SShimoda, Yoshihiro 		return IRQ_NONE;
237f1407d5cSKuninori Morimoto 
238f1407d5cSKuninori Morimoto 	/*
239f1407d5cSKuninori Morimoto 	 * clear interrupt
240f1407d5cSKuninori Morimoto 	 *
241f1407d5cSKuninori Morimoto 	 * The hardware is _very_ picky to clear interrupt bit.
242f1407d5cSKuninori Morimoto 	 * Especially INTSTS0_MAGIC, INTSTS1_MAGIC value.
243f1407d5cSKuninori Morimoto 	 *
244f1407d5cSKuninori Morimoto 	 * see
245f1407d5cSKuninori Morimoto 	 *	"Operation"
246f1407d5cSKuninori Morimoto 	 *	 - "Control Transfer (DCP)"
247f1407d5cSKuninori Morimoto 	 *	   - Function :: VALID bit should 0
248f1407d5cSKuninori Morimoto 	 */
249f1407d5cSKuninori Morimoto 	usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC);
25088a25e02SNobuhiro Iwamatsu 	if (usbhs_mod_is_host(priv))
251f1407d5cSKuninori Morimoto 		usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC);
252f1407d5cSKuninori Morimoto 
253519d8bd4SYoshihiro Shimoda 	/*
254519d8bd4SYoshihiro Shimoda 	 * The driver should not clear the xxxSTS after the line of
255519d8bd4SYoshihiro Shimoda 	 * "call irq callback functions" because each "if" statement is
256519d8bd4SYoshihiro Shimoda 	 * possible to call the callback function for avoiding any side effects.
257519d8bd4SYoshihiro Shimoda 	 */
258519d8bd4SYoshihiro Shimoda 	if (irq_state.intsts0 & BRDY)
259d5c6a1e0SKuninori Morimoto 		usbhs_write(priv, BRDYSTS, ~irq_state.brdysts);
260d5c6a1e0SKuninori Morimoto 	usbhs_write(priv, NRDYSTS, ~irq_state.nrdysts);
261519d8bd4SYoshihiro Shimoda 	if (irq_state.intsts0 & BEMP)
262d5c6a1e0SKuninori Morimoto 		usbhs_write(priv, BEMPSTS, ~irq_state.bempsts);
263f1407d5cSKuninori Morimoto 
264f1407d5cSKuninori Morimoto 	/*
265f1407d5cSKuninori Morimoto 	 * call irq callback functions
266f1407d5cSKuninori Morimoto 	 * see also
267f1407d5cSKuninori Morimoto 	 *	usbhs_irq_setting_update
268f1407d5cSKuninori Morimoto 	 */
26989c1d2e7SKuninori Morimoto 
27089c1d2e7SKuninori Morimoto 	/* INTSTS0 */
271b002ff6eSKuninori Morimoto 	if (irq_state.intsts0 & VBINT)
272b002ff6eSKuninori Morimoto 		usbhs_mod_info_call(priv, irq_vbus, priv, &irq_state);
273b002ff6eSKuninori Morimoto 
274f1407d5cSKuninori Morimoto 	if (irq_state.intsts0 & DVST)
275f1407d5cSKuninori Morimoto 		usbhs_mod_call(priv, irq_dev_state, priv, &irq_state);
276f1407d5cSKuninori Morimoto 
277f1407d5cSKuninori Morimoto 	if (irq_state.intsts0 & CTRT)
278f1407d5cSKuninori Morimoto 		usbhs_mod_call(priv, irq_ctrl_stage, priv, &irq_state);
279f1407d5cSKuninori Morimoto 
280f1407d5cSKuninori Morimoto 	if (irq_state.intsts0 & BEMP)
281f1407d5cSKuninori Morimoto 		usbhs_mod_call(priv, irq_empty, priv, &irq_state);
282f1407d5cSKuninori Morimoto 
283f1407d5cSKuninori Morimoto 	if (irq_state.intsts0 & BRDY)
284f1407d5cSKuninori Morimoto 		usbhs_mod_call(priv, irq_ready, priv, &irq_state);
285f1407d5cSKuninori Morimoto 
28688a25e02SNobuhiro Iwamatsu 	if (usbhs_mod_is_host(priv)) {
28789c1d2e7SKuninori Morimoto 		/* INTSTS1 */
28889c1d2e7SKuninori Morimoto 		if (irq_state.intsts1 & ATTCH)
28989c1d2e7SKuninori Morimoto 			usbhs_mod_call(priv, irq_attch, priv, &irq_state);
29089c1d2e7SKuninori Morimoto 
29189c1d2e7SKuninori Morimoto 		if (irq_state.intsts1 & DTCH)
29289c1d2e7SKuninori Morimoto 			usbhs_mod_call(priv, irq_dtch, priv, &irq_state);
29389c1d2e7SKuninori Morimoto 
29489c1d2e7SKuninori Morimoto 		if (irq_state.intsts1 & SIGN)
29589c1d2e7SKuninori Morimoto 			usbhs_mod_call(priv, irq_sign, priv, &irq_state);
29689c1d2e7SKuninori Morimoto 
29789c1d2e7SKuninori Morimoto 		if (irq_state.intsts1 & SACK)
29889c1d2e7SKuninori Morimoto 			usbhs_mod_call(priv, irq_sack, priv, &irq_state);
29988a25e02SNobuhiro Iwamatsu 	}
300f1407d5cSKuninori Morimoto 	return IRQ_HANDLED;
301f1407d5cSKuninori Morimoto }
302f1407d5cSKuninori Morimoto 
usbhs_irq_callback_update(struct usbhs_priv * priv,struct usbhs_mod * mod)303f1407d5cSKuninori Morimoto void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod)
304f1407d5cSKuninori Morimoto {
305f1407d5cSKuninori Morimoto 	u16 intenb0 = 0;
30689c1d2e7SKuninori Morimoto 	u16 intenb1 = 0;
307b002ff6eSKuninori Morimoto 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
308f1407d5cSKuninori Morimoto 
309651f5e49SKuninori Morimoto 	/*
310651f5e49SKuninori Morimoto 	 * BEMPENB/BRDYENB are picky.
311651f5e49SKuninori Morimoto 	 * below method is required
312651f5e49SKuninori Morimoto 	 *
313651f5e49SKuninori Morimoto 	 *  - clear  INTSTS0
314651f5e49SKuninori Morimoto 	 *  - update BEMPENB/BRDYENB
315651f5e49SKuninori Morimoto 	 *  - update INTSTS0
316651f5e49SKuninori Morimoto 	 */
317f1407d5cSKuninori Morimoto 	usbhs_write(priv, INTENB0, 0);
31888a25e02SNobuhiro Iwamatsu 	if (usbhs_mod_is_host(priv))
31989c1d2e7SKuninori Morimoto 		usbhs_write(priv, INTENB1, 0);
320f1407d5cSKuninori Morimoto 
321f1407d5cSKuninori Morimoto 	usbhs_write(priv, BEMPENB, 0);
322f1407d5cSKuninori Morimoto 	usbhs_write(priv, BRDYENB, 0);
323f1407d5cSKuninori Morimoto 
324f1407d5cSKuninori Morimoto 	/*
325f1407d5cSKuninori Morimoto 	 * see also
326f1407d5cSKuninori Morimoto 	 *	usbhs_interrupt
327f1407d5cSKuninori Morimoto 	 */
328f1407d5cSKuninori Morimoto 
329b002ff6eSKuninori Morimoto 	if (info->irq_vbus)
330b002ff6eSKuninori Morimoto 		intenb0 |= VBSE;
331f1407d5cSKuninori Morimoto 
3325ea68d54SKuninori Morimoto 	if (mod) {
33389c1d2e7SKuninori Morimoto 		/*
33489c1d2e7SKuninori Morimoto 		 * INTSTS0
33589c1d2e7SKuninori Morimoto 		 */
336f1407d5cSKuninori Morimoto 		if (mod->irq_ctrl_stage)
337f1407d5cSKuninori Morimoto 			intenb0 |= CTRE;
338f1407d5cSKuninori Morimoto 
339fef22636SEugeniu Rosca 		if (mod->irq_dev_state)
340fef22636SEugeniu Rosca 			intenb0 |= DVSE;
341fef22636SEugeniu Rosca 
342f1407d5cSKuninori Morimoto 		if (mod->irq_empty && mod->irq_bempsts) {
343f1407d5cSKuninori Morimoto 			usbhs_write(priv, BEMPENB, mod->irq_bempsts);
344f1407d5cSKuninori Morimoto 			intenb0 |= BEMPE;
345f1407d5cSKuninori Morimoto 		}
346f1407d5cSKuninori Morimoto 
347f1407d5cSKuninori Morimoto 		if (mod->irq_ready && mod->irq_brdysts) {
348f1407d5cSKuninori Morimoto 			usbhs_write(priv, BRDYENB, mod->irq_brdysts);
349f1407d5cSKuninori Morimoto 			intenb0 |= BRDYE;
350f1407d5cSKuninori Morimoto 		}
35189c1d2e7SKuninori Morimoto 
35288a25e02SNobuhiro Iwamatsu 		if (usbhs_mod_is_host(priv)) {
35389c1d2e7SKuninori Morimoto 			/*
35489c1d2e7SKuninori Morimoto 			 * INTSTS1
35589c1d2e7SKuninori Morimoto 			 */
35689c1d2e7SKuninori Morimoto 			if (mod->irq_attch)
35789c1d2e7SKuninori Morimoto 				intenb1 |= ATTCHE;
35889c1d2e7SKuninori Morimoto 
359b95eb747SKuninori Morimoto 			if (mod->irq_dtch)
36089c1d2e7SKuninori Morimoto 				intenb1 |= DTCHE;
36189c1d2e7SKuninori Morimoto 
36289c1d2e7SKuninori Morimoto 			if (mod->irq_sign)
36389c1d2e7SKuninori Morimoto 				intenb1 |= SIGNE;
36489c1d2e7SKuninori Morimoto 
36589c1d2e7SKuninori Morimoto 			if (mod->irq_sack)
36689c1d2e7SKuninori Morimoto 				intenb1 |= SACKE;
3675ea68d54SKuninori Morimoto 		}
36888a25e02SNobuhiro Iwamatsu 	}
369f1407d5cSKuninori Morimoto 
370651f5e49SKuninori Morimoto 	if (intenb0)
371f1407d5cSKuninori Morimoto 		usbhs_write(priv, INTENB0, intenb0);
37289c1d2e7SKuninori Morimoto 
37388a25e02SNobuhiro Iwamatsu 	if (usbhs_mod_is_host(priv) && intenb1)
37489c1d2e7SKuninori Morimoto 		usbhs_write(priv, INTENB1, intenb1);
375f1407d5cSKuninori Morimoto }
376