1f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto/*
2f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto * Renesas USB driver
3f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto *
4f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto * Copyright (C) 2011 Renesas Solutions Corp.
5f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto *
7f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto * This program is distributed in the hope that it will be useful,
8f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto * but WITHOUT ANY WARRANTY; without even the implied warranty of
9f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto * GNU General Public License for more details.
11f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto *
12f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto * You should have received a copy of the GNU General Public License
13f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto * along with this program; if not, write to the Free Software
14f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
15f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto *
16f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto */
17f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto#include <linux/interrupt.h>
18f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
19f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto#include "./common.h"
20f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto#include "./mod.h"
21f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
22f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto#define usbhs_priv_to_modinfo(priv) (&priv->mod_info)
23b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto#define usbhs_mod_info_call(priv, func, param...)	\
24b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto({						\
25b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto	struct usbhs_mod_info *info;		\
26b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto	info = usbhs_priv_to_modinfo(priv);	\
27b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto	!info->func ? 0 :			\
28b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto	 info->func(param);			\
29b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto})
30b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto
31b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto/*
32b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto *		autonomy
33b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto *
34b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto * these functions are used if platform doesn't have external phy.
35b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto *  -> there is no "notify_hotplug" callback from platform
36b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto *  -> call "notify_hotplug" by itself
37b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto *  -> use own interrupt to connect/disconnect
38b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto *  -> it mean module clock is always ON
39b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto *             ~~~~~~~~~~~~~~~~~~~~~~~~~
40b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto */
41b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimotostatic int usbhsm_autonomy_get_vbus(struct platform_device *pdev)
42b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto{
43b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
44b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto
45b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto	return  VBSTS & usbhs_read(priv, INTSTS0);
46b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto}
47b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto
48b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimotostatic int usbhsm_autonomy_irq_vbus(struct usbhs_priv *priv,
49b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto				    struct usbhs_irq_state *irq_state)
50b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto{
51b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto	struct platform_device *pdev = usbhs_priv_to_pdev(priv);
52b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto
53b4fcea2a71cafc59a749fa3ef88e51af8c2e3b37Kuninori Morimoto	renesas_usbhs_call_notify_hotplug(pdev);
54b4fcea2a71cafc59a749fa3ef88e51af8c2e3b37Kuninori Morimoto
55b4fcea2a71cafc59a749fa3ef88e51af8c2e3b37Kuninori Morimoto	return 0;
56b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto}
57b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto
58b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimotovoid usbhs_mod_autonomy_mode(struct usbhs_priv *priv)
59b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto{
60b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
61b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto
62b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto	info->irq_vbus		= usbhsm_autonomy_irq_vbus;
63482982062f1bc25ffb5383ab724d73d1a7af07cfKuninori Morimoto	priv->pfunc.get_vbus	= usbhsm_autonomy_get_vbus;
64b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto
65b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto	usbhs_irq_callback_update(priv, NULL);
66b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto}
67f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
68f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto/*
69f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto *		host / gadget functions
70f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto *
71f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto * renesas_usbhs host/gadget can register itself by below functions.
72f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto * these functions are called when probe
73f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto *
74f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto */
75f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimotovoid usbhs_mod_register(struct usbhs_priv *priv, struct usbhs_mod *mod, int id)
76f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto{
77f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
78f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
79f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	info->mod[id]	= mod;
80f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	mod->priv	= priv;
81f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto}
82f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
83f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimotostruct usbhs_mod *usbhs_mod_get(struct usbhs_priv *priv, int id)
84f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto{
85f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
86f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	struct usbhs_mod *ret = NULL;
87f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
88f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	switch (id) {
89f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	case USBHS_HOST:
90f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	case USBHS_GADGET:
91f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto		ret = info->mod[id];
92f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto		break;
93f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	}
94f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
95f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	return ret;
96f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto}
97f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
980deb3e77025688e0650e1af672d3e42e15cd8916Kuninori Morimotoint usbhs_mod_is_host(struct usbhs_priv *priv)
99f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto{
1000deb3e77025688e0650e1af672d3e42e15cd8916Kuninori Morimoto	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
101f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
102f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
103f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	if (!mod)
104f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto		return -EINVAL;
105f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
106f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	return info->mod[USBHS_HOST] == mod;
107f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto}
108f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
109f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimotostruct usbhs_mod *usbhs_mod_get_current(struct usbhs_priv *priv)
110f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto{
111f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
112f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
113f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	return info->curt;
114f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto}
115f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
116f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimotoint usbhs_mod_change(struct usbhs_priv *priv, int id)
117f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto{
118f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
119f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	struct usbhs_mod *mod = NULL;
120f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	int ret = 0;
121f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
122f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	/* id < 0 mean no current */
123f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	switch (id) {
124f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	case USBHS_HOST:
125f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	case USBHS_GADGET:
126f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto		mod = info->mod[id];
127f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto		break;
128f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	default:
129f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto		ret = -EINVAL;
130f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	}
131f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	info->curt = mod;
132f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
133f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	return ret;
134f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto}
135f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
136f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimotostatic irqreturn_t usbhs_interrupt(int irq, void *data);
137f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimotoint usbhs_mod_probe(struct usbhs_priv *priv)
138f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto{
139f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	struct device *dev = usbhs_priv_to_dev(priv);
140f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	int ret;
141f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
1422f98382dcdfe1f0048b447da35f34507ffb514dcKuninori Morimoto	/*
1432f98382dcdfe1f0048b447da35f34507ffb514dcKuninori Morimoto	 * install host/gadget driver
1442f98382dcdfe1f0048b447da35f34507ffb514dcKuninori Morimoto	 */
145034d7c13a79c67d3b52dd782d68e6c324613878aKuninori Morimoto	ret = usbhs_mod_host_probe(priv);
1462f98382dcdfe1f0048b447da35f34507ffb514dcKuninori Morimoto	if (ret < 0)
1472f98382dcdfe1f0048b447da35f34507ffb514dcKuninori Morimoto		return ret;
1482f98382dcdfe1f0048b447da35f34507ffb514dcKuninori Morimoto
149034d7c13a79c67d3b52dd782d68e6c324613878aKuninori Morimoto	ret = usbhs_mod_gadget_probe(priv);
150034d7c13a79c67d3b52dd782d68e6c324613878aKuninori Morimoto	if (ret < 0)
151034d7c13a79c67d3b52dd782d68e6c324613878aKuninori Morimoto		goto mod_init_host_err;
152034d7c13a79c67d3b52dd782d68e6c324613878aKuninori Morimoto
153f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	/* irq settings */
154f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	ret = request_irq(priv->irq, usbhs_interrupt,
15553069af3fa8ba2849cd4785160690873995d4f39Shimoda, Yoshihiro			  priv->irqflags, dev_name(dev), priv);
1562f98382dcdfe1f0048b447da35f34507ffb514dcKuninori Morimoto	if (ret) {
157f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto		dev_err(dev, "irq request err\n");
1582f98382dcdfe1f0048b447da35f34507ffb514dcKuninori Morimoto		goto mod_init_gadget_err;
1592f98382dcdfe1f0048b447da35f34507ffb514dcKuninori Morimoto	}
1602f98382dcdfe1f0048b447da35f34507ffb514dcKuninori Morimoto
1612f98382dcdfe1f0048b447da35f34507ffb514dcKuninori Morimoto	return ret;
1622f98382dcdfe1f0048b447da35f34507ffb514dcKuninori Morimoto
1632f98382dcdfe1f0048b447da35f34507ffb514dcKuninori Morimotomod_init_gadget_err:
1642f98382dcdfe1f0048b447da35f34507ffb514dcKuninori Morimoto	usbhs_mod_gadget_remove(priv);
165034d7c13a79c67d3b52dd782d68e6c324613878aKuninori Morimotomod_init_host_err:
166034d7c13a79c67d3b52dd782d68e6c324613878aKuninori Morimoto	usbhs_mod_host_remove(priv);
167f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
168f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	return ret;
169f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto}
170f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
171f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimotovoid usbhs_mod_remove(struct usbhs_priv *priv)
172f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto{
173034d7c13a79c67d3b52dd782d68e6c324613878aKuninori Morimoto	usbhs_mod_host_remove(priv);
1742f98382dcdfe1f0048b447da35f34507ffb514dcKuninori Morimoto	usbhs_mod_gadget_remove(priv);
175f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	free_irq(priv->irq, priv);
176f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto}
177f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
178f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto/*
179f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto *		status functions
180f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto */
181f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimotoint usbhs_status_get_device_state(struct usbhs_irq_state *irq_state)
182f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto{
183f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	int state = irq_state->intsts0 & DVSQ_MASK;
184f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
185f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	switch (state) {
186f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	case POWER_STATE:
187f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	case DEFAULT_STATE:
188f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	case ADDRESS_STATE:
189f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	case CONFIGURATION_STATE:
190f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto		return state;
191f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	}
192f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
193f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	return -EIO;
194f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto}
195f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
196f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimotoint usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state)
197f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto{
198f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	/*
199f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * return value
200f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 *
201f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * IDLE_SETUP_STAGE
202f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * READ_DATA_STAGE
203f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * READ_STATUS_STAGE
204f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * WRITE_DATA_STAGE
205f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * WRITE_STATUS_STAGE
206f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * NODATA_STATUS_STAGE
207f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * SEQUENCE_ERROR
208f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 */
209f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	return (int)irq_state->intsts0 & CTSQ_MASK;
210f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto}
211f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
212f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimotostatic void usbhs_status_get_each_irq(struct usbhs_priv *priv,
213f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto				      struct usbhs_irq_state *state)
214f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto{
215f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
216f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
217f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	state->intsts0 = usbhs_read(priv, INTSTS0);
218f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	state->intsts1 = usbhs_read(priv, INTSTS1);
219f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
220f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	/* mask */
2215ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto	if (mod) {
2225ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto		state->brdysts = usbhs_read(priv, BRDYSTS);
2235ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto		state->nrdysts = usbhs_read(priv, NRDYSTS);
2245ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto		state->bempsts = usbhs_read(priv, BEMPSTS);
2255ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto
2265ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto		state->bempsts &= mod->irq_bempsts;
2275ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto		state->brdysts &= mod->irq_brdysts;
2285ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto	}
229f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto}
230f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
231f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto/*
232f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto *		interrupt
233f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto */
234f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto#define INTSTS0_MAGIC 0xF800 /* acknowledge magical interrupt sources */
235f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto#define INTSTS1_MAGIC 0xA870 /* acknowledge magical interrupt sources */
236f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimotostatic irqreturn_t usbhs_interrupt(int irq, void *data)
237f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto{
238f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	struct usbhs_priv *priv = data;
239f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	struct usbhs_irq_state irq_state;
240f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
241f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	usbhs_status_get_each_irq(priv, &irq_state);
242f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
243f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	/*
244f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * clear interrupt
245f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 *
246f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * The hardware is _very_ picky to clear interrupt bit.
247f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * Especially INTSTS0_MAGIC, INTSTS1_MAGIC value.
248f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 *
249f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * see
250f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 *	"Operation"
251f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 *	 - "Control Transfer (DCP)"
252f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 *	   - Function :: VALID bit should 0
253f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 */
254f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC);
255f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC);
256f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
257f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	usbhs_write(priv, BRDYSTS, 0);
258f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	usbhs_write(priv, NRDYSTS, 0);
259f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	usbhs_write(priv, BEMPSTS, 0);
260f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
261f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	/*
262f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * call irq callback functions
263f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * see also
264f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 *	usbhs_irq_setting_update
265f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 */
26689c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto
26789c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto	/* INTSTS0 */
268b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto	if (irq_state.intsts0 & VBINT)
269b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto		usbhs_mod_info_call(priv, irq_vbus, priv, &irq_state);
270b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto
271f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	if (irq_state.intsts0 & DVST)
272f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto		usbhs_mod_call(priv, irq_dev_state, priv, &irq_state);
273f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
274f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	if (irq_state.intsts0 & CTRT)
275f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto		usbhs_mod_call(priv, irq_ctrl_stage, priv, &irq_state);
276f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
277f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	if (irq_state.intsts0 & BEMP)
278f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto		usbhs_mod_call(priv, irq_empty, priv, &irq_state);
279f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
280f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	if (irq_state.intsts0 & BRDY)
281f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto		usbhs_mod_call(priv, irq_ready, priv, &irq_state);
282f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
28389c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto	/* INTSTS1 */
28489c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto	if (irq_state.intsts1 & ATTCH)
28589c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto		usbhs_mod_call(priv, irq_attch, priv, &irq_state);
28689c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto
28789c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto	if (irq_state.intsts1 & DTCH)
28889c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto		usbhs_mod_call(priv, irq_dtch, priv, &irq_state);
28989c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto
29089c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto	if (irq_state.intsts1 & SIGN)
29189c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto		usbhs_mod_call(priv, irq_sign, priv, &irq_state);
29289c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto
29389c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto	if (irq_state.intsts1 & SACK)
29489c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto		usbhs_mod_call(priv, irq_sack, priv, &irq_state);
29589c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto
296f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	return IRQ_HANDLED;
297f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto}
298f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
299f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimotovoid usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod)
300f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto{
301f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	u16 intenb0 = 0;
30289c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto	u16 intenb1 = 0;
303b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
304f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
305651f5e49dd3d369711bd622f4bc72c2fa30a3cf9Kuninori Morimoto	/*
306651f5e49dd3d369711bd622f4bc72c2fa30a3cf9Kuninori Morimoto	 * BEMPENB/BRDYENB are picky.
307651f5e49dd3d369711bd622f4bc72c2fa30a3cf9Kuninori Morimoto	 * below method is required
308651f5e49dd3d369711bd622f4bc72c2fa30a3cf9Kuninori Morimoto	 *
309651f5e49dd3d369711bd622f4bc72c2fa30a3cf9Kuninori Morimoto	 *  - clear  INTSTS0
310651f5e49dd3d369711bd622f4bc72c2fa30a3cf9Kuninori Morimoto	 *  - update BEMPENB/BRDYENB
311651f5e49dd3d369711bd622f4bc72c2fa30a3cf9Kuninori Morimoto	 *  - update INTSTS0
312651f5e49dd3d369711bd622f4bc72c2fa30a3cf9Kuninori Morimoto	 */
313f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	usbhs_write(priv, INTENB0, 0);
31489c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto	usbhs_write(priv, INTENB1, 0);
315f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
316f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	usbhs_write(priv, BEMPENB, 0);
317f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	usbhs_write(priv, BRDYENB, 0);
318f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
319f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	/*
320f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * see also
321f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 *	usbhs_interrupt
322f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 */
323f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
324f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	/*
325f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * it don't enable DVSE (intenb0) here
326f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 * but "mod->irq_dev_state" will be called.
327f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	 */
328b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto	if (info->irq_vbus)
329b002ff6e268b6024d6927a1ce330a14ca162b6abKuninori Morimoto		intenb0 |= VBSE;
330f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
3315ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto	if (mod) {
33289c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto		/*
33389c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto		 * INTSTS0
33489c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto		 */
3355ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto		if (mod->irq_ctrl_stage)
3365ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto			intenb0 |= CTRE;
337f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
3385ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto		if (mod->irq_empty && mod->irq_bempsts) {
3395ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto			usbhs_write(priv, BEMPENB, mod->irq_bempsts);
3405ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto			intenb0 |= BEMPE;
3415ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto		}
342f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
3435ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto		if (mod->irq_ready && mod->irq_brdysts) {
3445ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto			usbhs_write(priv, BRDYENB, mod->irq_brdysts);
3455ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto			intenb0 |= BRDYE;
3465ea68d541df200d10a373c06f945f98225c2486bKuninori Morimoto		}
34789c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto
34889c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto		/*
34989c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto		 * INTSTS1
35089c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto		 */
35189c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto		if (mod->irq_attch)
35289c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto			intenb1 |= ATTCHE;
35389c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto
354b95eb7476e7224baae34f67ae9a09042521e97ffKuninori Morimoto		if (mod->irq_dtch)
35589c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto			intenb1 |= DTCHE;
35689c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto
35789c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto		if (mod->irq_sign)
35889c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto			intenb1 |= SIGNE;
35989c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto
36089c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto		if (mod->irq_sack)
36189c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto			intenb1 |= SACKE;
362f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto	}
363f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto
364651f5e49dd3d369711bd622f4bc72c2fa30a3cf9Kuninori Morimoto	if (intenb0)
365651f5e49dd3d369711bd622f4bc72c2fa30a3cf9Kuninori Morimoto		usbhs_write(priv, INTENB0, intenb0);
36689c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto
36789c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto	if (intenb1)
36889c1d2e7b5993db33805b42e3675289920812f6fKuninori Morimoto		usbhs_write(priv, INTENB1, intenb1);
369f1407d5c66240b33d11a7f1a41d55ccf6a9d7647Kuninori Morimoto}
370