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