xref: /openbsd-src/sys/dev/fdt/imxehci.c (revision 54fbbda3b5f8c42357b8601b12a514e2d25a2771)
1*54fbbda3Sjsg /*	$OpenBSD: imxehci.c,v 1.7 2024/09/01 03:08:56 jsg Exp $ */
2831bc68bSpatrick /*
3831bc68bSpatrick  * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se>
4831bc68bSpatrick  *
5831bc68bSpatrick  * Permission to use, copy, modify, and distribute this software for any
6831bc68bSpatrick  * purpose with or without fee is hereby granted, provided that the above
7831bc68bSpatrick  * copyright notice and this permission notice appear in all copies.
8831bc68bSpatrick  *
9831bc68bSpatrick  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10831bc68bSpatrick  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11831bc68bSpatrick  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12831bc68bSpatrick  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13831bc68bSpatrick  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14831bc68bSpatrick  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15831bc68bSpatrick  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16831bc68bSpatrick  */
17831bc68bSpatrick 
18831bc68bSpatrick #include <sys/param.h>
19831bc68bSpatrick #include <sys/systm.h>
20831bc68bSpatrick #include <sys/device.h>
21831bc68bSpatrick #include <sys/kernel.h>
22831bc68bSpatrick #include <sys/rwlock.h>
23831bc68bSpatrick #include <sys/timeout.h>
24831bc68bSpatrick 
25831bc68bSpatrick #include <machine/intr.h>
26831bc68bSpatrick #include <machine/bus.h>
27831bc68bSpatrick #include <machine/fdt.h>
28831bc68bSpatrick 
29831bc68bSpatrick #include <dev/usb/usb.h>
30831bc68bSpatrick #include <dev/usb/usbdi.h>
31831bc68bSpatrick #include <dev/usb/usbdivar.h>
32831bc68bSpatrick #include <dev/usb/usb_mem.h>
33831bc68bSpatrick 
34831bc68bSpatrick #include <dev/ofw/openfirm.h>
35831bc68bSpatrick #include <dev/ofw/ofw_clock.h>
36831bc68bSpatrick #include <dev/ofw/ofw_gpio.h>
37831bc68bSpatrick #include <dev/ofw/ofw_misc.h>
38831bc68bSpatrick #include <dev/ofw/ofw_pinctrl.h>
39cdce981fSpatrick #include <dev/ofw/ofw_power.h>
40831bc68bSpatrick #include <dev/ofw/ofw_regulator.h>
41831bc68bSpatrick #include <dev/ofw/fdt.h>
42831bc68bSpatrick 
43831bc68bSpatrick #include <dev/usb/ehcireg.h>
44831bc68bSpatrick #include <dev/usb/ehcivar.h>
45831bc68bSpatrick 
46831bc68bSpatrick /* usb phy */
47831bc68bSpatrick #define USBPHY_PWD			0x00
48831bc68bSpatrick #define USBPHY_CTRL			0x30
49831bc68bSpatrick #define USBPHY_CTRL_SET			0x34
50831bc68bSpatrick #define USBPHY_CTRL_CLR			0x38
51831bc68bSpatrick #define USBPHY_CTRL_TOG			0x3c
52831bc68bSpatrick 
53831bc68bSpatrick #define USBPHY_CTRL_ENUTMILEVEL2	(1 << 14)
54831bc68bSpatrick #define USBPHY_CTRL_ENUTMILEVEL3	(1 << 15)
55831bc68bSpatrick #define USBPHY_CTRL_CLKGATE		(1 << 30)
56831bc68bSpatrick #define USBPHY_CTRL_SFTRST		(1U << 31)
57831bc68bSpatrick 
58831bc68bSpatrick /* ehci */
59831bc68bSpatrick #define USB_EHCI_OFFSET			0x100
60831bc68bSpatrick 
61831bc68bSpatrick #define EHCI_PS_PTS_UTMI_MASK	((1 << 25) | (3 << 30))
62831bc68bSpatrick 
63831bc68bSpatrick /* usb non-core */
64831bc68bSpatrick #define USBNC_USB_OTG_CTRL		0x00
65831bc68bSpatrick #define USBNC_USB_UH1_CTRL		0x04
66831bc68bSpatrick 
672b724d3dSpatrick #define USBNC_USB_CTRL_PWR_POL		(1 << 9)
682b724d3dSpatrick #define USBNC_USB_CTRL_OVER_CUR_POL	(1 << 8)
692b724d3dSpatrick #define USBNC_USB_CTRL_OVER_CUR_DIS	(1 << 7)
702b724d3dSpatrick #define USBNC_USB_CTRL_NON_BURST	(1 << 1)
71831bc68bSpatrick 
72831bc68bSpatrick /* anatop */
73831bc68bSpatrick #define ANALOG_USB1_CHRG_DETECT			0x1b0
74831bc68bSpatrick #define ANALOG_USB1_CHRG_DETECT_SET		0x1b4
75831bc68bSpatrick #define ANALOG_USB1_CHRG_DETECT_CLR		0x1b8
76831bc68bSpatrick #define  ANALOG_USB1_CHRG_DETECT_CHK_CHRG_B		(1 << 19)
77831bc68bSpatrick #define  ANALOG_USB1_CHRG_DETECT_EN_B			(1 << 20)
78831bc68bSpatrick #define ANALOG_USB2_CHRG_DETECT			0x210
79831bc68bSpatrick #define ANALOG_USB2_CHRG_DETECT_SET		0x214
80831bc68bSpatrick #define ANALOG_USB2_CHRG_DETECT_CLR		0x218
81831bc68bSpatrick #define  ANALOG_USB2_CHRG_DETECT_CHK_CHRG_B		(1 << 19)
82831bc68bSpatrick #define  ANALOG_USB2_CHRG_DETECT_EN_B			(1 << 20)
83831bc68bSpatrick 
84831bc68bSpatrick int	imxehci_match(struct device *, void *, void *);
85831bc68bSpatrick void	imxehci_attach(struct device *, struct device *, void *);
86831bc68bSpatrick int	imxehci_detach(struct device *, int);
87831bc68bSpatrick 
88831bc68bSpatrick struct imxehci_softc {
89831bc68bSpatrick 	struct ehci_softc	sc;
90831bc68bSpatrick 	void			*sc_ih;
91831bc68bSpatrick 	bus_space_handle_t	uh_ioh;
92831bc68bSpatrick 	bus_space_handle_t	ph_ioh;
93831bc68bSpatrick 	bus_space_handle_t	nc_ioh;
94831bc68bSpatrick 	uint32_t		sc_unit;
95831bc68bSpatrick };
96831bc68bSpatrick 
97471aeecfSnaddy const struct cfattach imxehci_ca = {
98831bc68bSpatrick 	sizeof (struct imxehci_softc), imxehci_match, imxehci_attach,
99831bc68bSpatrick 	imxehci_detach
100831bc68bSpatrick };
101831bc68bSpatrick 
102831bc68bSpatrick struct cfdriver imxehci_cd = {
103831bc68bSpatrick 	NULL, "imxehci", DV_DULL
104831bc68bSpatrick };
105831bc68bSpatrick 
106831bc68bSpatrick void	imxehci_init_phy(struct imxehci_softc *, uint32_t *);
107831bc68bSpatrick 
108831bc68bSpatrick int
109831bc68bSpatrick imxehci_match(struct device *parent, void *match, void *aux)
110831bc68bSpatrick {
111831bc68bSpatrick 	struct fdt_attach_args *faa = aux;
112831bc68bSpatrick 
1134c4c1cbeSpatrick 	return (OF_is_compatible(faa->fa_node, "fsl,imx27-usb") ||
1144c4c1cbeSpatrick 	    OF_is_compatible(faa->fa_node, "fsl,imx7d-usb"));
115831bc68bSpatrick }
116831bc68bSpatrick 
117831bc68bSpatrick void
118831bc68bSpatrick imxehci_attach(struct device *parent, struct device *self, void *aux)
119831bc68bSpatrick {
120831bc68bSpatrick 	struct imxehci_softc *sc = (struct imxehci_softc *)self;
121831bc68bSpatrick 	struct fdt_attach_args *faa = aux;
122831bc68bSpatrick 	usbd_status r;
123831bc68bSpatrick 	char *devname = sc->sc.sc_bus.bdev.dv_xname;
124831bc68bSpatrick 	uint32_t phy[1], misc[2];
125831bc68bSpatrick 	uint32_t misc_reg[2];
1262b724d3dSpatrick 	uint32_t off, reg;
127831bc68bSpatrick 	uint32_t vbus;
128831bc68bSpatrick 	int misc_node;
129831bc68bSpatrick 
130831bc68bSpatrick 	if (faa->fa_nreg < 1)
131831bc68bSpatrick 		return;
132831bc68bSpatrick 
13389fbac9fSpatrick 	if (OF_getpropintarray(faa->fa_node, "phys",
13489fbac9fSpatrick 	    phy, sizeof(phy)) != sizeof(phy)) {
135831bc68bSpatrick 		if (OF_getpropintarray(faa->fa_node, "fsl,usbphy",
136831bc68bSpatrick 		    phy, sizeof(phy)) != sizeof(phy))
137831bc68bSpatrick 			return;
13889fbac9fSpatrick 	}
139831bc68bSpatrick 
140831bc68bSpatrick 	if (OF_getpropintarray(faa->fa_node, "fsl,usbmisc",
141831bc68bSpatrick 	    misc, sizeof(misc)) != sizeof(misc))
142831bc68bSpatrick 		return;
143831bc68bSpatrick 
144831bc68bSpatrick 	misc_node = OF_getnodebyphandle(misc[0]);
145831bc68bSpatrick 	if (misc_node == 0)
146831bc68bSpatrick 		return;
147831bc68bSpatrick 
148831bc68bSpatrick 	if (OF_getpropintarray(misc_node, "reg", misc_reg,
149831bc68bSpatrick 	    sizeof(misc_reg)) != sizeof(misc_reg))
150831bc68bSpatrick 		return;
151831bc68bSpatrick 
152831bc68bSpatrick 	sc->sc.iot = faa->fa_iot;
153831bc68bSpatrick 	sc->sc.sc_bus.dmatag = faa->fa_dmat;
154831bc68bSpatrick 	sc->sc.sc_size = faa->fa_reg[0].size - USB_EHCI_OFFSET;
155831bc68bSpatrick 	sc->sc.sc_flags = EHCIF_USBMODE;
156831bc68bSpatrick 	sc->sc_unit = misc[1];
157831bc68bSpatrick 
158831bc68bSpatrick 	/* Map I/O space */
159831bc68bSpatrick 	if (bus_space_map(sc->sc.iot, faa->fa_reg[0].addr,
160831bc68bSpatrick 	    faa->fa_reg[0].size, 0, &sc->uh_ioh)) {
161831bc68bSpatrick 		printf(": cannot map mem space\n");
162831bc68bSpatrick 		goto out;
163831bc68bSpatrick 	}
164831bc68bSpatrick 	if (bus_space_subregion(sc->sc.iot, sc->uh_ioh, USB_EHCI_OFFSET,
165831bc68bSpatrick 	    sc->sc.sc_size, &sc->sc.ioh)) {
166831bc68bSpatrick 		printf(": cannot map mem space\n");
167831bc68bSpatrick 		goto mem0;
168831bc68bSpatrick 	}
169831bc68bSpatrick 
170831bc68bSpatrick 	if (bus_space_map(sc->sc.iot, misc_reg[0],
171831bc68bSpatrick 	    misc_reg[1], 0, &sc->nc_ioh)) {
172831bc68bSpatrick 		printf(": cannot map mem space\n");
173831bc68bSpatrick 		goto mem1;
174831bc68bSpatrick 	}
175831bc68bSpatrick 
176831bc68bSpatrick 	printf("\n");
177831bc68bSpatrick 
178831bc68bSpatrick 	pinctrl_byname(faa->fa_node, "default");
179cdce981fSpatrick 	power_domain_enable(faa->fa_node);
180cdce981fSpatrick 	clock_set_assigned(faa->fa_node);
181831bc68bSpatrick 	clock_enable(faa->fa_node, NULL);
182831bc68bSpatrick 	delay(1000);
183831bc68bSpatrick 
184831bc68bSpatrick 	/* over current and polarity setting */
185831bc68bSpatrick 	switch (misc[1]) {
186831bc68bSpatrick 	case 0:
1872b724d3dSpatrick 		off = USBNC_USB_OTG_CTRL;
188831bc68bSpatrick 		break;
189831bc68bSpatrick 	case 1:
1902b724d3dSpatrick 		off = USBNC_USB_UH1_CTRL;
191831bc68bSpatrick 		break;
1922b724d3dSpatrick 	default:
1932b724d3dSpatrick 		printf("%s: invalid usbmisc property\n", devname);
1942b724d3dSpatrick 		return;
195831bc68bSpatrick 	}
196831bc68bSpatrick 
1972b724d3dSpatrick 	reg = bus_space_read_4(sc->sc.iot, sc->nc_ioh, off);
1982b724d3dSpatrick 	reg &= ~USBNC_USB_CTRL_OVER_CUR_DIS;
1992b724d3dSpatrick 	if (OF_getproplen(faa->fa_node, "disable-over-current") == 0)
2002b724d3dSpatrick 		reg |= USBNC_USB_CTRL_OVER_CUR_DIS;
2012b724d3dSpatrick 	if (OF_getproplen(faa->fa_node, "over-current-active-low") == 0)
2022b724d3dSpatrick 		reg |= USBNC_USB_CTRL_OVER_CUR_POL;
2032b724d3dSpatrick 	else if (OF_getproplen(faa->fa_node, "over-current-active-high") == 0)
2042b724d3dSpatrick 		reg &= ~USBNC_USB_CTRL_OVER_CUR_POL;
2052b724d3dSpatrick 	if (OF_getproplen(faa->fa_node, "power-active-high") == 0)
2062b724d3dSpatrick 		reg |= USBNC_USB_CTRL_PWR_POL;
2072b724d3dSpatrick 	reg |= USBNC_USB_CTRL_NON_BURST;
2082b724d3dSpatrick 	bus_space_write_4(sc->sc.iot, sc->nc_ioh, off, reg);
2092b724d3dSpatrick 
210831bc68bSpatrick 	/* enable usb bus power */
211831bc68bSpatrick 	vbus = OF_getpropint(faa->fa_node, "vbus-supply", 0);
212831bc68bSpatrick 	if (vbus)
213831bc68bSpatrick 		regulator_enable(vbus);
214831bc68bSpatrick 
215831bc68bSpatrick 	/* Disable interrupts, so we don't get any spurious ones. */
216831bc68bSpatrick 	sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH);
217831bc68bSpatrick 	EOWRITE2(&sc->sc, EHCI_USBINTR, 0);
218831bc68bSpatrick 
219831bc68bSpatrick 	/* Stop then Reset */
220831bc68bSpatrick 	uint32_t val = EOREAD4(&sc->sc, EHCI_USBCMD);
221831bc68bSpatrick 	val &= ~EHCI_CMD_RS;
222831bc68bSpatrick 	EOWRITE4(&sc->sc, EHCI_USBCMD, val);
223831bc68bSpatrick 
224831bc68bSpatrick 	while (EOREAD4(&sc->sc, EHCI_USBCMD) & EHCI_CMD_RS)
225831bc68bSpatrick 		;
226831bc68bSpatrick 
227831bc68bSpatrick 	val = EOREAD4(&sc->sc, EHCI_USBCMD);
228831bc68bSpatrick 	val |= EHCI_CMD_HCRESET;
229831bc68bSpatrick 	EOWRITE4(&sc->sc, EHCI_USBCMD, val);
230831bc68bSpatrick 
231831bc68bSpatrick 	while (EOREAD4(&sc->sc, EHCI_USBCMD) & EHCI_CMD_HCRESET)
232831bc68bSpatrick 		;
233831bc68bSpatrick 
234831bc68bSpatrick 	/* power up PHY */
235831bc68bSpatrick 	imxehci_init_phy(sc, phy);
236831bc68bSpatrick 
237831bc68bSpatrick 	/* set host mode */
238831bc68bSpatrick 	EOWRITE4(&sc->sc, EHCI_USBMODE,
239831bc68bSpatrick 	    EOREAD4(&sc->sc, EHCI_USBMODE) | EHCI_USBMODE_CM_HOST);
240831bc68bSpatrick 
241831bc68bSpatrick 	/* set to UTMI mode */
242831bc68bSpatrick 	EOWRITE4(&sc->sc, EHCI_PORTSC(1),
243831bc68bSpatrick 	    EOREAD4(&sc->sc, EHCI_PORTSC(1)) & ~EHCI_PS_PTS_UTMI_MASK);
244831bc68bSpatrick 
245831bc68bSpatrick 	sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_USB,
246831bc68bSpatrick 	    ehci_intr, &sc->sc, devname);
247831bc68bSpatrick 	if (sc->sc_ih == NULL) {
248831bc68bSpatrick 		printf(": unable to establish interrupt\n");
249831bc68bSpatrick 		goto mem2;
250831bc68bSpatrick 	}
251831bc68bSpatrick 
252831bc68bSpatrick 	strlcpy(sc->sc.sc_vendor, "i.MX", sizeof(sc->sc.sc_vendor));
253831bc68bSpatrick 	r = ehci_init(&sc->sc);
254831bc68bSpatrick 	if (r != USBD_NORMAL_COMPLETION) {
255831bc68bSpatrick 		printf("%s: init failed, error=%d\n", devname, r);
256831bc68bSpatrick 		goto intr;
257831bc68bSpatrick 	}
258831bc68bSpatrick 
259831bc68bSpatrick 	config_found(self, &sc->sc.sc_bus, usbctlprint);
260831bc68bSpatrick 
261831bc68bSpatrick 	goto out;
262831bc68bSpatrick 
263831bc68bSpatrick intr:
264831bc68bSpatrick 	fdt_intr_disestablish(sc->sc_ih);
265831bc68bSpatrick 	sc->sc_ih = NULL;
266831bc68bSpatrick mem2:
267831bc68bSpatrick 	bus_space_unmap(sc->sc.iot, sc->nc_ioh, misc_reg[1]);
268831bc68bSpatrick mem1:
269831bc68bSpatrick mem0:
270831bc68bSpatrick 	bus_space_unmap(sc->sc.iot, sc->sc.ioh, faa->fa_reg[0].size);
271831bc68bSpatrick 	sc->sc.sc_size = 0;
272831bc68bSpatrick out:
273831bc68bSpatrick 	return;
274831bc68bSpatrick }
275831bc68bSpatrick 
276831bc68bSpatrick int
277831bc68bSpatrick imxehci_detach(struct device *self, int flags)
278831bc68bSpatrick {
279831bc68bSpatrick 	struct imxehci_softc		*sc = (struct imxehci_softc *)self;
280831bc68bSpatrick 	int				rv;
281831bc68bSpatrick 
282831bc68bSpatrick 	rv = ehci_detach(self, flags);
283831bc68bSpatrick 	if (rv)
284831bc68bSpatrick 		return (rv);
285831bc68bSpatrick 
286831bc68bSpatrick 	if (sc->sc_ih != NULL) {
287831bc68bSpatrick 		fdt_intr_disestablish(sc->sc_ih);
288831bc68bSpatrick 		sc->sc_ih = NULL;
289831bc68bSpatrick 	}
290831bc68bSpatrick 
291831bc68bSpatrick 	if (sc->sc.sc_size) {
292831bc68bSpatrick 		bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
293831bc68bSpatrick 		sc->sc.sc_size = 0;
294831bc68bSpatrick 	}
295831bc68bSpatrick 
296831bc68bSpatrick 	return (0);
297831bc68bSpatrick }
298831bc68bSpatrick 
299831bc68bSpatrick /*
300831bc68bSpatrick  * PHY initialization.
301831bc68bSpatrick  */
302831bc68bSpatrick 
303831bc68bSpatrick struct imxehci_phy {
304831bc68bSpatrick 	const char *compat;
305831bc68bSpatrick 	void (*init)(struct imxehci_softc *, uint32_t *);
306831bc68bSpatrick };
307831bc68bSpatrick 
308831bc68bSpatrick void imx23_usb_init(struct imxehci_softc *, uint32_t *);
309831bc68bSpatrick static void nop_xceiv_init(struct imxehci_softc *, uint32_t *);
310831bc68bSpatrick 
311831bc68bSpatrick struct imxehci_phy imxehci_phys[] = {
312831bc68bSpatrick 	{ "fsl,imx23-usbphy", imx23_usb_init },
313831bc68bSpatrick 	{ "usb-nop-xceiv", nop_xceiv_init },
314831bc68bSpatrick };
315831bc68bSpatrick 
316831bc68bSpatrick void
317831bc68bSpatrick imxehci_init_phy(struct imxehci_softc *sc, uint32_t *cells)
318831bc68bSpatrick {
319831bc68bSpatrick 	int node;
320831bc68bSpatrick 	int i;
321831bc68bSpatrick 
322831bc68bSpatrick 	node = OF_getnodebyphandle(cells[0]);
323831bc68bSpatrick 	if (node == 0)
324831bc68bSpatrick 		return;
325831bc68bSpatrick 
326831bc68bSpatrick 	for (i = 0; i < nitems(imxehci_phys); i++) {
327831bc68bSpatrick 		if (OF_is_compatible(node, imxehci_phys[i].compat)) {
328831bc68bSpatrick 			imxehci_phys[i].init(sc, cells);
329831bc68bSpatrick 			return;
330831bc68bSpatrick 		}
331831bc68bSpatrick 	}
332831bc68bSpatrick }
333831bc68bSpatrick 
334831bc68bSpatrick /*
335831bc68bSpatrick  * i.MX5/6 PHYs.
336831bc68bSpatrick  */
337831bc68bSpatrick 
338831bc68bSpatrick void
339831bc68bSpatrick imx23_usb_init(struct imxehci_softc *sc, uint32_t *cells)
340831bc68bSpatrick {
341831bc68bSpatrick 	struct regmap *rm = NULL;
342831bc68bSpatrick 	uint32_t phy_reg[2];
343831bc68bSpatrick 	uint32_t anatop[1];
344831bc68bSpatrick 	int node;
345831bc68bSpatrick 
346831bc68bSpatrick 	node = OF_getnodebyphandle(cells[0]);
347831bc68bSpatrick 	KASSERT(node != 0);
348831bc68bSpatrick 
349831bc68bSpatrick 	if (OF_getpropintarray(node, "reg", phy_reg,
350831bc68bSpatrick 	    sizeof(phy_reg)) != sizeof(phy_reg))
351831bc68bSpatrick 		return;
352831bc68bSpatrick 
353831bc68bSpatrick 	if (bus_space_map(sc->sc.iot, phy_reg[0],
354831bc68bSpatrick 	    phy_reg[1], 0, &sc->ph_ioh)) {
355831bc68bSpatrick 		printf("%s: can't map PHY registers\n",
356831bc68bSpatrick 		    sc->sc.sc_bus.bdev.dv_xname);
357831bc68bSpatrick 		return;
358831bc68bSpatrick 	}
359831bc68bSpatrick 
360831bc68bSpatrick 	if (OF_getpropintarray(node, "fsl,anatop",
361831bc68bSpatrick 	    anatop, sizeof(anatop)) == sizeof(anatop))
362831bc68bSpatrick 		rm = regmap_byphandle(anatop[0]);
363831bc68bSpatrick 
364*54fbbda3Sjsg 	/* Disable the charger detection, else signal on DP will be poor */
365831bc68bSpatrick 	switch (sc->sc_unit) {
366831bc68bSpatrick 	case 0:
367831bc68bSpatrick 		if (rm != NULL)
368831bc68bSpatrick 			regmap_write_4(rm, ANALOG_USB1_CHRG_DETECT_SET,
369831bc68bSpatrick 			    ANALOG_USB1_CHRG_DETECT_CHK_CHRG_B |
370831bc68bSpatrick 			    ANALOG_USB1_CHRG_DETECT_EN_B);
371831bc68bSpatrick 		break;
372831bc68bSpatrick 	case 1:
373831bc68bSpatrick 		if (rm != NULL)
374831bc68bSpatrick 			regmap_write_4(rm, ANALOG_USB2_CHRG_DETECT_SET,
375831bc68bSpatrick 			    ANALOG_USB2_CHRG_DETECT_CHK_CHRG_B |
376831bc68bSpatrick 			    ANALOG_USB2_CHRG_DETECT_EN_B);
377831bc68bSpatrick 		break;
378831bc68bSpatrick 	}
379831bc68bSpatrick 
380831bc68bSpatrick 	clock_enable(node, NULL);
381831bc68bSpatrick 
382831bc68bSpatrick 	/* Reset USBPHY module */
383831bc68bSpatrick 	bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_SET,
384831bc68bSpatrick 	    USBPHY_CTRL_SFTRST);
385831bc68bSpatrick 
386831bc68bSpatrick 	delay(10);
387831bc68bSpatrick 
388831bc68bSpatrick 	/* Remove CLKGATE and SFTRST */
389831bc68bSpatrick 	bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_CLR,
390831bc68bSpatrick 	    USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST);
391831bc68bSpatrick 
392831bc68bSpatrick 	delay(10);
393831bc68bSpatrick 
394831bc68bSpatrick 	/* Power up the PHY */
395831bc68bSpatrick 	bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_PWD, 0);
396831bc68bSpatrick 
397831bc68bSpatrick 	/* enable FS/LS device */
398831bc68bSpatrick 	bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_SET,
399831bc68bSpatrick 	    USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3);
400831bc68bSpatrick }
401831bc68bSpatrick 
402831bc68bSpatrick /*
403831bc68bSpatrick  * i.MX7 PHYs.
404831bc68bSpatrick  */
405831bc68bSpatrick 
406831bc68bSpatrick static void
407831bc68bSpatrick nop_xceiv_init(struct imxehci_softc *sc, uint32_t *cells)
408831bc68bSpatrick {
409831bc68bSpatrick 	int node;
410831bc68bSpatrick 
411831bc68bSpatrick 	node = OF_getnodebyphandle(cells[0]);
412831bc68bSpatrick 	KASSERT(node != 0);
413831bc68bSpatrick 
414cdce981fSpatrick 	clock_set_assigned(node);
415831bc68bSpatrick 	clock_enable(node, NULL);
416831bc68bSpatrick }
417