xref: /openbsd/sys/arch/octeon/dev/octxctl.c (revision 36fd90dc)
1*36fd90dcSjsg /*	$OpenBSD: octxctl.c,v 1.5 2021/03/11 11:16:59 jsg Exp $	*/
2029876c0Svisa 
3029876c0Svisa /*
4029876c0Svisa  * Copyright (c) 2017 Visa Hankala
5029876c0Svisa  *
6029876c0Svisa  * Permission to use, copy, modify, and distribute this software for any
7029876c0Svisa  * purpose with or without fee is hereby granted, provided that the above
8029876c0Svisa  * copyright notice and this permission notice appear in all copies.
9029876c0Svisa  *
10029876c0Svisa  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11029876c0Svisa  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12029876c0Svisa  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13029876c0Svisa  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14029876c0Svisa  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15029876c0Svisa  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16029876c0Svisa  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17029876c0Svisa  */
18029876c0Svisa 
19029876c0Svisa /*
20029876c0Svisa  * Driver for OCTEON USB3 controller bridge.
21029876c0Svisa  */
22029876c0Svisa 
23029876c0Svisa #include <sys/param.h>
24029876c0Svisa #include <sys/systm.h>
25029876c0Svisa #include <sys/device.h>
26029876c0Svisa #include <sys/malloc.h>
27029876c0Svisa 
28029876c0Svisa #include <machine/fdt.h>
29029876c0Svisa #include <machine/octeonvar.h>
30029876c0Svisa 
31029876c0Svisa #include <dev/ofw/fdt.h>
32989664a9Svisa #include <dev/ofw/ofw_gpio.h>
33029876c0Svisa #include <dev/ofw/openfirm.h>
34029876c0Svisa 
35029876c0Svisa #include <octeon/dev/iobusvar.h>
36029876c0Svisa #include <octeon/dev/octxctlreg.h>
37029876c0Svisa 
38029876c0Svisa #define XCTL_RD_8(sc, reg) \
39029876c0Svisa 	bus_space_read_8((sc)->sc_iot, (sc)->sc_ioh, (reg))
40029876c0Svisa #define XCTL_WR_8(sc, reg, val) \
41029876c0Svisa 	bus_space_write_8((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
42029876c0Svisa 
43029876c0Svisa struct octxctl_softc {
44029876c0Svisa 	struct device		sc_dev;
45029876c0Svisa 	bus_space_tag_t		sc_iot;
46029876c0Svisa 	bus_space_handle_t	sc_ioh;
47989664a9Svisa 	int			sc_power_gpio[3];
48989664a9Svisa 	int			sc_unit;
49029876c0Svisa };
50029876c0Svisa 
51029876c0Svisa int	 octxctl_match(struct device *, void *, void *);
52029876c0Svisa void	 octxctl_attach(struct device *, struct device *, void *);
53029876c0Svisa 
54029876c0Svisa int	 octxctl_dwc3_init(struct octxctl_softc *, struct fdt_reg *);
55029876c0Svisa void	 octxctl_uctl_init(struct octxctl_softc *, uint64_t, uint64_t);
56029876c0Svisa uint8_t	 octxctl_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t);
57029876c0Svisa uint16_t octxctl_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t);
58029876c0Svisa uint32_t octxctl_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t);
59029876c0Svisa void	 octxctl_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t,
60029876c0Svisa 	    uint8_t);
61029876c0Svisa void	 octxctl_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t,
62029876c0Svisa 	    uint16_t);
63029876c0Svisa void	 octxctl_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t,
64029876c0Svisa 	    uint32_t);
65029876c0Svisa 
66029876c0Svisa const struct cfattach octxctl_ca = {
67029876c0Svisa 	sizeof(struct octxctl_softc), octxctl_match, octxctl_attach
68029876c0Svisa };
69029876c0Svisa 
70029876c0Svisa struct cfdriver octxctl_cd = {
71029876c0Svisa 	NULL, "octxctl", DV_DULL
72029876c0Svisa };
73029876c0Svisa 
74029876c0Svisa bus_space_t octxctl_tag = {
75029876c0Svisa 	.bus_base = PHYS_TO_XKPHYS(0, CCA_NC),
76029876c0Svisa 	._space_read_1 = octxctl_read_1,
77029876c0Svisa 	._space_read_2 = octxctl_read_2,
78029876c0Svisa 	._space_read_4 = octxctl_read_4,
79029876c0Svisa 	._space_write_1 = octxctl_write_1,
80029876c0Svisa 	._space_write_2 = octxctl_write_2,
81029876c0Svisa 	._space_write_4 = octxctl_write_4,
82029876c0Svisa 	._space_map = iobus_space_map,
83029876c0Svisa 	._space_unmap = iobus_space_unmap,
84029876c0Svisa 	._space_subregion = generic_space_region,
85029876c0Svisa 	._space_vaddr = generic_space_vaddr
86029876c0Svisa };
87029876c0Svisa 
88029876c0Svisa int
octxctl_match(struct device * parent,void * match,void * aux)89029876c0Svisa octxctl_match(struct device *parent, void *match, void *aux)
90029876c0Svisa {
91029876c0Svisa 	struct fdt_attach_args *faa = aux;
92029876c0Svisa 	int child;
93029876c0Svisa 
94029876c0Svisa 	if (OF_is_compatible(faa->fa_node, "cavium,octeon-7130-usb-uctl") == 0)
95029876c0Svisa 		return 0;
96029876c0Svisa 	if ((child = OF_child(faa->fa_node)) == 0)
97029876c0Svisa 		return 0;
98029876c0Svisa 	return OF_is_compatible(child, "cavium,octeon-7130-xhci");
99029876c0Svisa }
100029876c0Svisa 
101029876c0Svisa void
octxctl_attach(struct device * parent,struct device * self,void * aux)102029876c0Svisa octxctl_attach(struct device *parent, struct device *self, void *aux)
103029876c0Svisa {
104029876c0Svisa 	char clock_type_hs[32];
105029876c0Svisa 	char clock_type_ss[32];
106029876c0Svisa 	struct fdt_reg child_reg;
107029876c0Svisa 	struct fdt_attach_args child_faa;
108029876c0Svisa 	struct fdt_attach_args *faa = aux;
109029876c0Svisa 	struct octxctl_softc *sc = (struct octxctl_softc *)self;
110029876c0Svisa 	uint64_t clock_freq, clock_sel;
111029876c0Svisa 	uint32_t reg[4];
112029876c0Svisa 	int child;
113029876c0Svisa 
114029876c0Svisa 	if (faa->fa_nreg != 1) {
115029876c0Svisa 		printf(": expected one IO space, got %d\n", faa->fa_nreg);
116029876c0Svisa 		return;
117029876c0Svisa 	}
118029876c0Svisa 
119029876c0Svisa 	child = OF_child(faa->fa_node);
120029876c0Svisa 	if (OF_getpropint(faa->fa_node, "#address-cells", 0) != 2 ||
121029876c0Svisa 	    OF_getpropint(faa->fa_node, "#size-cells", 0) != 2) {
122029876c0Svisa 		printf(": invalid fdt reg cells\n");
123029876c0Svisa 		return;
124029876c0Svisa 	}
125029876c0Svisa 	if (OF_getproplen(child, "reg") != sizeof(reg)) {
126029876c0Svisa 		printf(": invalid child fdt reg\n");
127029876c0Svisa 		return;
128029876c0Svisa 	}
129029876c0Svisa 	OF_getpropintarray(child, "reg", reg, sizeof(reg));
130029876c0Svisa 	child_reg.addr = ((uint64_t)reg[0] << 32) | reg[1];
131029876c0Svisa 	child_reg.size = ((uint64_t)reg[2] << 32) | reg[3];
132029876c0Svisa 
133029876c0Svisa 	clock_freq = OF_getpropint(faa->fa_node, "refclk-frequency", 0);
134029876c0Svisa 
135029876c0Svisa 	if (OF_getprop(faa->fa_node, "refclk-type-hs", clock_type_hs,
136029876c0Svisa 	    sizeof(clock_type_hs)) < 0)
137029876c0Svisa 		goto error;
138029876c0Svisa 	if (OF_getprop(faa->fa_node, "refclk-type-ss", clock_type_ss,
139029876c0Svisa 	    sizeof(clock_type_ss)) < 0)
140029876c0Svisa 		goto error;
141029876c0Svisa 	clock_sel = 0;
142029876c0Svisa 	if (strcmp(clock_type_ss, "dlmc_ref_clk1") == 0)
143029876c0Svisa 		clock_sel |= 1;
144029876c0Svisa 	if (strcmp(clock_type_hs, "pll_ref_clk") == 0)
145029876c0Svisa 		clock_sel |= 2;
146029876c0Svisa 
147989664a9Svisa 	OF_getpropintarray(faa->fa_node, "power", sc->sc_power_gpio,
148989664a9Svisa 	    sizeof(sc->sc_power_gpio));
149989664a9Svisa 
150989664a9Svisa 	sc->sc_unit = (faa->fa_reg[0].addr >> 24) & 0x1;
151029876c0Svisa 	sc->sc_iot = faa->fa_iot;
152029876c0Svisa 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size,
153029876c0Svisa 	    0, &sc->sc_ioh)) {
154029876c0Svisa 		printf(": could not map registers\n");
155029876c0Svisa 		goto error;
156029876c0Svisa 	}
157029876c0Svisa 
158029876c0Svisa 	octxctl_uctl_init(sc, clock_freq, clock_sel);
159029876c0Svisa 
160029876c0Svisa 	if (octxctl_dwc3_init(sc, &child_reg) != 0) {
161029876c0Svisa 		/* Error message has been printed already. */
162029876c0Svisa 		goto error;
163029876c0Svisa 	}
164029876c0Svisa 
165029876c0Svisa 	printf("\n");
166029876c0Svisa 
167029876c0Svisa 	memset(&child_faa, 0, sizeof(child_faa));
168029876c0Svisa 	child_faa.fa_name = "";
169029876c0Svisa 	child_faa.fa_node = child;
170029876c0Svisa 	child_faa.fa_iot = &octxctl_tag;
171029876c0Svisa 	child_faa.fa_dmat = faa->fa_dmat;
172029876c0Svisa 	child_faa.fa_reg = &child_reg;
173029876c0Svisa 	child_faa.fa_nreg = 1;
174029876c0Svisa 	/* child_faa.fa_intr is not utilized. */
175029876c0Svisa 
176029876c0Svisa 	config_found(self, &child_faa, NULL);
177029876c0Svisa 
178029876c0Svisa 	return;
179029876c0Svisa 
180029876c0Svisa error:
181029876c0Svisa 	if (sc->sc_ioh != 0)
182029876c0Svisa 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size);
183029876c0Svisa }
184029876c0Svisa 
185029876c0Svisa void
octxctl_uctl_init(struct octxctl_softc * sc,uint64_t clock_freq,uint64_t clock_sel)186029876c0Svisa octxctl_uctl_init(struct octxctl_softc *sc, uint64_t clock_freq,
187029876c0Svisa     uint64_t clock_sel)
188029876c0Svisa {
189029876c0Svisa 	static const uint32_t clock_divs[] = { 1, 2, 4, 6, 8, 16, 24, 32 };
190029876c0Svisa 	uint64_t i, val;
191029876c0Svisa 	uint64_t ioclock = octeon_ioclock_speed();
192029876c0Svisa 	uint64_t mpll_mult;
193029876c0Svisa 	uint64_t refclk_fsel;
194989664a9Svisa 	int output_sel;
195029876c0Svisa 
196029876c0Svisa 	/*
197029876c0Svisa 	 * Put the bridge controller, USB core, PHY, and clock divider
198029876c0Svisa 	 * into reset.
199029876c0Svisa 	 */
200029876c0Svisa 	val = XCTL_RD_8(sc, XCTL_CTL);
201029876c0Svisa 	val |= XCTL_CTL_UCTL_RST;
202029876c0Svisa 	val |= XCTL_CTL_UAHC_RST;
203029876c0Svisa 	val |= XCTL_CTL_UPHY_RST;
204029876c0Svisa 	XCTL_WR_8(sc, XCTL_CTL, val);
205029876c0Svisa 	val = XCTL_RD_8(sc, XCTL_CTL);
206029876c0Svisa 	val |= XCTL_CTL_CLKDIV_RST;
207029876c0Svisa 	XCTL_WR_8(sc, XCTL_CTL, val);
208029876c0Svisa 
209029876c0Svisa 	/* Select IO clock divisor. */
210029876c0Svisa 	for (i = 0; i < nitems(clock_divs); i++) {
211029876c0Svisa 		if (ioclock / clock_divs[i] < 300000000)
212029876c0Svisa 			break;
213029876c0Svisa 	}
214029876c0Svisa 
215029876c0Svisa 	/* Update the divisor and enable the clock. */
216029876c0Svisa 	val = XCTL_RD_8(sc, XCTL_CTL);
217029876c0Svisa 	val &= ~XCTL_CTL_CLKDIV_SEL;
218029876c0Svisa 	val |= (i << XCTL_CTL_CLKDIV_SEL_SHIFT) & XCTL_CTL_CLKDIV_SEL;
219029876c0Svisa 	val |= XCTL_CTL_CLK_EN;
220029876c0Svisa 	XCTL_WR_8(sc, XCTL_CTL, val);
221029876c0Svisa 
222029876c0Svisa 	/* Take the clock divider out of reset. */
223029876c0Svisa 	val = XCTL_RD_8(sc, XCTL_CTL);
224029876c0Svisa 	val &= ~XCTL_CTL_CLKDIV_RST;
225029876c0Svisa 	XCTL_WR_8(sc, XCTL_CTL, val);
226029876c0Svisa 
227029876c0Svisa 	/* Select the reference clock. */
228029876c0Svisa 	switch (clock_freq) {
229029876c0Svisa 	case 50000000:
230029876c0Svisa 		refclk_fsel = 0x07;
231029876c0Svisa 		mpll_mult = 0x32;
232029876c0Svisa 		break;
233029876c0Svisa 	case 125000000:
234029876c0Svisa 		refclk_fsel = 0x07;
235029876c0Svisa 		mpll_mult = 0x28;
236029876c0Svisa 		break;
237029876c0Svisa 	case 100000000:
238029876c0Svisa 	default:
239029876c0Svisa 		if (clock_sel < 2)
240029876c0Svisa 			refclk_fsel = 0x27;
241bff815e9Svisa 		else
242bff815e9Svisa 			refclk_fsel = 0x07;
243029876c0Svisa 		mpll_mult = 0x19;
244029876c0Svisa 		break;
245029876c0Svisa 	}
246029876c0Svisa 
247029876c0Svisa 	/* Set the clock and power up PHYs. */
248029876c0Svisa 	val = XCTL_RD_8(sc, XCTL_CTL);
249029876c0Svisa 	val &= ~XCTL_CTL_REFCLK_SEL;
250029876c0Svisa 	val |= clock_sel << XCTL_CTL_REFCLK_SEL_SHIFT;
251029876c0Svisa 	val &= ~XCTL_CTL_REFCLK_DIV2;
252029876c0Svisa 	val &= ~XCTL_CTL_REFCLK_FSEL;
253029876c0Svisa 	val |= refclk_fsel << XCTL_CTL_REFCLK_FSEL_SHIFT;
254029876c0Svisa 	val &= ~XCTL_CTL_MPLL_MULT;
255029876c0Svisa 	val |= mpll_mult << XCTL_CTL_MPLL_MULT_SHIFT;
256029876c0Svisa 	val |= XCTL_CTL_SSC_EN;
257029876c0Svisa 	val |= XCTL_CTL_REFCLK_SSP_EN;
258029876c0Svisa 	val |= XCTL_CTL_SSPOWER_EN;
259029876c0Svisa 	val |= XCTL_CTL_HSPOWER_EN;
260029876c0Svisa 	XCTL_WR_8(sc, XCTL_CTL, val);
261029876c0Svisa 
262029876c0Svisa 	delay(100);
263029876c0Svisa 
264029876c0Svisa 	/* Take the bridge out of reset. */
265029876c0Svisa 	val = XCTL_RD_8(sc, XCTL_CTL);
266029876c0Svisa 	val &= ~XCTL_CTL_UCTL_RST;
267029876c0Svisa 	XCTL_WR_8(sc, XCTL_CTL, val);
268029876c0Svisa 
269029876c0Svisa 	delay(100);
270029876c0Svisa 
271989664a9Svisa 	if (sc->sc_power_gpio[0] != 0) {
272989664a9Svisa 		if (sc->sc_unit == 0)
273989664a9Svisa 			output_sel = GPIO_CONFIG_MD_USB0_VBUS_CTRL;
274989664a9Svisa 		else
275989664a9Svisa 			output_sel = GPIO_CONFIG_MD_USB1_VBUS_CTRL;
276989664a9Svisa 		gpio_controller_config_pin(sc->sc_power_gpio,
277989664a9Svisa 		    GPIO_CONFIG_OUTPUT | output_sel);
278989664a9Svisa 
279989664a9Svisa 		/* Enable port power control. */
280989664a9Svisa 		val = XCTL_RD_8(sc, XCTL_HOST_CFG);
281989664a9Svisa 		val |= XCTL_HOST_CFG_PPC_EN;
282989664a9Svisa 		if (sc->sc_power_gpio[2] & GPIO_ACTIVE_LOW)
283989664a9Svisa 			val &= ~XCTL_HOST_CFG_PPC_ACTIVE_HIGH_EN;
284989664a9Svisa 		else
285989664a9Svisa 			val |= XCTL_HOST_CFG_PPC_ACTIVE_HIGH_EN;
286989664a9Svisa 		XCTL_WR_8(sc, XCTL_HOST_CFG, val);
287989664a9Svisa 	} else {
288029876c0Svisa 		/* Disable port power control. */
289029876c0Svisa 		val = XCTL_RD_8(sc, XCTL_HOST_CFG);
290029876c0Svisa 		val &= ~XCTL_HOST_CFG_PPC_EN;
291029876c0Svisa 		XCTL_WR_8(sc, XCTL_HOST_CFG, val);
292989664a9Svisa 	}
293029876c0Svisa 
294029876c0Svisa 	/* Enable host-only mode. */
295029876c0Svisa 	val = XCTL_RD_8(sc, XCTL_CTL);
296029876c0Svisa 	val &= ~XCTL_CTL_DRD_MODE;
297029876c0Svisa 	XCTL_WR_8(sc, XCTL_CTL, val);
298029876c0Svisa 
299029876c0Svisa 	delay(100);
300029876c0Svisa 
301029876c0Svisa 	/* Take the USB core out of reset. */
302029876c0Svisa 	val = XCTL_RD_8(sc, XCTL_CTL);
303029876c0Svisa 	val &= ~XCTL_CTL_UAHC_RST;
304029876c0Svisa 	XCTL_WR_8(sc, XCTL_CTL, val);
305029876c0Svisa 
306029876c0Svisa 	delay(100);
307029876c0Svisa 
308029876c0Svisa 	val = XCTL_RD_8(sc, XCTL_CTL);
309029876c0Svisa 	val |= XCTL_CTL_CSCLK_EN;
310029876c0Svisa 	XCTL_WR_8(sc, XCTL_CTL, val);
311029876c0Svisa 
312029876c0Svisa 	/* Take the PHY out of reset. */
313029876c0Svisa 	val = XCTL_RD_8(sc, XCTL_CTL);
314029876c0Svisa 	val &= ~XCTL_CTL_UPHY_RST;
315029876c0Svisa 	XCTL_WR_8(sc, XCTL_CTL, val);
316029876c0Svisa 	(void)XCTL_RD_8(sc, XCTL_CTL);
317029876c0Svisa 
318*36fd90dcSjsg 	/* Fix endianness. */
319029876c0Svisa 	val = XCTL_RD_8(sc, XCTL_SHIM_CFG);
320029876c0Svisa 	val &= ~XCTL_SHIM_CFG_CSR_BYTE_SWAP;
321029876c0Svisa 	val &= ~XCTL_SHIM_CFG_DMA_BYTE_SWAP;
322029876c0Svisa 	val |= 3ull << XCTL_SHIM_CFG_CSR_BYTE_SWAP_SHIFT;
323029876c0Svisa 	val |= 1ull << XCTL_SHIM_CFG_DMA_BYTE_SWAP_SHIFT;
324029876c0Svisa 	XCTL_WR_8(sc, XCTL_SHIM_CFG, val);
325029876c0Svisa 	(void)XCTL_RD_8(sc, XCTL_SHIM_CFG);
326029876c0Svisa }
327029876c0Svisa 
328029876c0Svisa int
octxctl_dwc3_init(struct octxctl_softc * sc,struct fdt_reg * reg)329029876c0Svisa octxctl_dwc3_init(struct octxctl_softc *sc, struct fdt_reg *reg)
330029876c0Svisa {
331029876c0Svisa 	bus_space_handle_t ioh;
332029876c0Svisa 	uint32_t rev;
333029876c0Svisa 	uint32_t val;
334029876c0Svisa 	int error = 0;
335029876c0Svisa 
336029876c0Svisa 	if (bus_space_map(sc->sc_iot, reg->addr, reg->size, 0, &ioh) != 0) {
337029876c0Svisa 		printf(": could not map USB3 core registers\n");
338029876c0Svisa 		return EIO;
339029876c0Svisa 	}
340029876c0Svisa 
341029876c0Svisa 	val = bus_space_read_4(sc->sc_iot, ioh, DWC3_GSNPSID);
342029876c0Svisa 	if ((val & 0xffff0000u) != 0x55330000u) {
343029876c0Svisa 		printf(": no DWC3 core\n");
344029876c0Svisa 		error = EIO;
345029876c0Svisa 		goto out;
346029876c0Svisa 	}
347029876c0Svisa 	rev = val & 0xffffu;
348029876c0Svisa 	printf(": DWC3 rev 0x%04x", rev);
349029876c0Svisa 
350029876c0Svisa 	val = bus_space_read_4(sc->sc_iot, ioh, DWC3_GUSB3PIPECTL(0));
351029876c0Svisa 	val &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX;
352029876c0Svisa 	val |= DWC3_GUSB3PIPECTL_SUSPHY;
353029876c0Svisa 	bus_space_write_4(sc->sc_iot, ioh, DWC3_GUSB3PIPECTL(0), val);
354029876c0Svisa 
355029876c0Svisa 	val = bus_space_read_4(sc->sc_iot, ioh, DWC3_GUSB2PHYCFG(0));
356029876c0Svisa 	val |= DWC3_GUSB2PHYCFG_SUSPHY;
357029876c0Svisa 	bus_space_write_4(sc->sc_iot, ioh, DWC3_GUSB2PHYCFG(0), val);
358029876c0Svisa 
359029876c0Svisa 	/* Set the controller into host mode. */
360029876c0Svisa 	val = bus_space_read_4(sc->sc_iot, ioh, DWC3_GCTL);
361029876c0Svisa 	val &= ~DWC3_GCTL_PRTCAP_MASK;
362029876c0Svisa 	val |= DWC3_GCTL_PRTCAP_HOST;
363029876c0Svisa 	bus_space_write_4(sc->sc_iot, ioh, DWC3_GCTL, val);
364029876c0Svisa 
365029876c0Svisa 	val = bus_space_read_4(sc->sc_iot, ioh, DWC3_GCTL);
366029876c0Svisa 	val &= ~DWC3_GCTL_SCALEDOWN_MASK;
367029876c0Svisa 	val &= ~DWC3_GCTL_DISSCRAMBLE;
368029876c0Svisa 	if (rev >= DWC3_REV_210A && rev <= DWC3_REV_250A)
369029876c0Svisa 		val |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC;
370029876c0Svisa 	else
371029876c0Svisa 		val &= ~DWC3_GCTL_DSBLCLKGTNG;
372029876c0Svisa 	bus_space_write_4(sc->sc_iot, ioh, DWC3_GCTL, val);
373029876c0Svisa 
374029876c0Svisa out:
375029876c0Svisa 	bus_space_unmap(sc->sc_iot, ioh, reg->size);
376029876c0Svisa 
377bb7d75aeSvisa 	return error;
378029876c0Svisa }
379029876c0Svisa 
380029876c0Svisa /*
381029876c0Svisa  * Bus access routines for xhci(4).
382029876c0Svisa  */
383029876c0Svisa 
384029876c0Svisa uint8_t
octxctl_read_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)385029876c0Svisa octxctl_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
386029876c0Svisa {
387029876c0Svisa 	return *(volatile uint8_t *)(h + (o ^ 3));
388029876c0Svisa }
389029876c0Svisa 
390029876c0Svisa uint16_t
octxctl_read_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)391029876c0Svisa octxctl_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
392029876c0Svisa {
393029876c0Svisa 	return *(volatile uint16_t *)(h + (o ^ 2));
394029876c0Svisa }
395029876c0Svisa 
396029876c0Svisa uint32_t
octxctl_read_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)397029876c0Svisa octxctl_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
398029876c0Svisa {
399029876c0Svisa 	return *(volatile uint32_t *)(h + o);
400029876c0Svisa }
401029876c0Svisa 
402029876c0Svisa void
octxctl_write_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint8_t v)403029876c0Svisa octxctl_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
404029876c0Svisa     uint8_t v)
405029876c0Svisa {
406029876c0Svisa 	*(volatile uint8_t *)(h + (o ^ 3)) = v;
407029876c0Svisa }
408029876c0Svisa 
409029876c0Svisa void
octxctl_write_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint16_t v)410029876c0Svisa octxctl_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
411029876c0Svisa     uint16_t v)
412029876c0Svisa {
413029876c0Svisa 	*(volatile uint16_t *)(h + (o ^ 2)) = v;
414029876c0Svisa }
415029876c0Svisa 
416029876c0Svisa void
octxctl_write_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint32_t v)417029876c0Svisa octxctl_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
418029876c0Svisa     uint32_t v)
419029876c0Svisa {
420029876c0Svisa 	*(volatile uint32_t *)(h + o) = v;
421029876c0Svisa }
422