xref: /openbsd/sys/dev/fdt/sdhc_fdt.c (revision 09467b48)
1 /*	$OpenBSD: sdhc_fdt.c,v 1.12 2020/05/31 11:47:09 kettenis Exp $	*/
2 /*
3  * Copyright (c) 2017 Mark Kettenis
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/malloc.h>
20 #include <sys/systm.h>
21 
22 #include <machine/bus.h>
23 #include <machine/fdt.h>
24 #include <machine/intr.h>
25 
26 #include <dev/ofw/openfirm.h>
27 #include <dev/ofw/ofw_clock.h>
28 #include <dev/ofw/ofw_gpio.h>
29 #include <dev/ofw/ofw_misc.h>
30 #include <dev/ofw/ofw_pinctrl.h>
31 #include <dev/ofw/ofw_regulator.h>
32 #include <dev/ofw/fdt.h>
33 
34 #include <dev/sdmmc/sdhcreg.h>
35 #include <dev/sdmmc/sdhcvar.h>
36 #include <dev/sdmmc/sdmmcvar.h>
37 
38 /* RK3399 */
39 #define GRF_EMMCCORE_CON0_BASECLOCK		0xf000
40 #define  GRF_EMMCCORE_CON0_BASECLOCK_CLR		(0xff << 24)
41 #define  GRF_EMMCCORE_CON0_BASECLOCK_VAL(x)		(((x) & 0xff) << 8)
42 #define GRF_EMMCCORE_CON11			0xf02c
43 #define  GRF_EMMCCORE_CON11_CLOCKMULT_CLR		(0xff << 16)
44 #define  GRF_EMMCCORE_CON11_CLOCKMULT_VAL(x)		(((x) & 0xff) << 0)
45 
46 /* Marvell Xenon */
47 #define XENON_SYS_OP_CTRL			0x108
48 #define  XENON_SYS_OP_CTRL_SLOT_ENABLE(x)		(1 << (x))
49 #define  XENON_SYS_OP_CTRL_SDCLK_IDLEOFF_ENABLE(x)	(1 << ((x) + 8))
50 #define  XENON_SYS_OP_CTRL_AUTO_CLKGATE_DISABLE		(1 << 20)
51 #define XENON_SYS_EXT_OP_CTRL			0x10c
52 #define  XENON_SYS_EXT_OP_CTRL_PARALLEL_TRAN(x)		(1 << (x))
53 #define  XENON_SYS_EXT_OP_CTRL_MASK_CMD_CONFLICT_ERR	(1 << 8)
54 #define XENON_SLOT_EMMC_CTRL			0x130
55 #define  XENON_SLOT_EMMC_CTRL_ENABLE_DATA_STROBE	(1 << 24)
56 #define  XENON_SLOT_EMMC_CTRL_ENABLE_RESP_STROBE	(1 << 25)
57 #define XENON_EMMC_PHY_TIMING_ADJUST		0x170
58 #define  XENON_EMMC_PHY_TIMING_ADJUST_SAMPL_INV_QSP_PHASE_SELECT (1 << 18)
59 #define  XENON_EMMC_PHY_TIMING_ADJUST_SDIO_MODE		(1 << 28)
60 #define  XENON_EMMC_PHY_TIMING_ADJUST_SLOW_MODE		(1 << 29)
61 #define  XENON_EMMC_PHY_TIMING_ADJUST_INIT		(1U << 31)
62 #define XENON_EMMC_PHY_FUNC_CONTROL		0x174
63 #define  XENON_EMMC_PHY_FUNC_CONTROL_DQ_ASYNC_MODE	(1 << 4)
64 #define  XENON_EMMC_PHY_FUNC_CONTROL_DQ_DDR_MODE	(0xff << 8)
65 #define  XENON_EMMC_PHY_FUNC_CONTROL_CMD_DDR_MODE	(1 << 16)
66 #define XENON_EMMC_PHY_PAD_CONTROL		0x178
67 #define  XENON_EMMC_PHY_PAD_CONTROL_FC_DQ_RECEN		(1 << 24)
68 #define  XENON_EMMC_PHY_PAD_CONTROL_FC_CMD_RECEN	(1 << 25)
69 #define  XENON_EMMC_PHY_PAD_CONTROL_FC_QSP_RECEN	(1 << 26)
70 #define  XENON_EMMC_PHY_PAD_CONTROL_FC_QSN_RECEN	(1 << 27)
71 #define  XENON_EMMC_PHY_PAD_CONTROL_FC_ALL_CMOS_RECVR	0xf000
72 #define XENON_EMMC_PHY_PAD_CONTROL1		0x17c
73 #define  XENON_EMMC_PHY_PAD_CONTROL1_FC_CMD_PD		(1 << 8)
74 #define  XENON_EMMC_PHY_PAD_CONTROL1_FC_QSP_PD		(1 << 9)
75 #define  XENON_EMMC_PHY_PAD_CONTROL1_FC_CMD_PU		(1 << 24)
76 #define  XENON_EMMC_PHY_PAD_CONTROL1_FC_QSP_PU		(1 << 25)
77 #define  XENON_EMMC_PHY_PAD_CONTROL1_FC_DQ_PD		0xff
78 #define  XENON_EMMC_PHY_PAD_CONTROL1_FC_DQ_PU		(0xff << 16)
79 #define XENON_EMMC_PHY_PAD_CONTROL2		0x180
80 #define  XENON_EMMC_PHY_PAD_CONTROL2_ZPR_SHIFT		0
81 #define  XENON_EMMC_PHY_PAD_CONTROL2_ZPR_MASK		0x1f
82 #define  XENON_EMMC_PHY_PAD_CONTROL2_ZNR_SHIFT		8
83 #define  XENON_EMMC_PHY_PAD_CONTROL2_ZNR_MASK		0x1f
84 
85 #define ARMADA_3700_SOC_PAD_CTL			0
86 #define  ARMADA_3700_SOC_PAD_CTL_3_3V			0
87 #define  ARMADA_3700_SOC_PAD_CTL_1_8V			1
88 
89 struct sdhc_fdt_softc {
90 	struct sdhc_softc 	sc;
91 	bus_space_tag_t		sc_iot;
92 	bus_space_handle_t	sc_ioh;
93 	bus_space_handle_t	sc_pad_ioh;
94 	bus_size_t		sc_size;
95 	void			*sc_ih;
96 	int			sc_node;
97 	uint32_t		sc_gpio[3];
98 	uint32_t		sc_vqmmc;
99 
100 	/* Marvell Xenon */
101 	int			sc_sdhc_id;
102 	int			sc_slow_mode;
103 	uint32_t		sc_znr;
104 	uint32_t		sc_zpr;
105 
106 	struct sdhc_host 	*sc_host;
107 	struct clock_device	sc_cd;
108 };
109 
110 int	sdhc_fdt_match(struct device *, void *, void *);
111 void	sdhc_fdt_attach(struct device *, struct device *, void *);
112 
113 struct cfattach sdhc_fdt_ca = {
114 	sizeof(struct sdhc_fdt_softc), sdhc_fdt_match, sdhc_fdt_attach
115 };
116 
117 int	sdhc_fdt_card_detect(struct sdhc_softc *);
118 int	sdhc_fdt_signal_voltage(struct sdhc_softc *, int);
119 uint32_t sdhc_fdt_get_frequency(void *, uint32_t *);
120 
121 void	sdhc_fdt_xenon_bus_clock_post(struct sdhc_softc *, int, int);
122 
123 int
124 sdhc_fdt_match(struct device *parent, void *match, void *aux)
125 {
126 	struct fdt_attach_args *faa = aux;
127 
128 	return (OF_is_compatible(faa->fa_node, "arasan,sdhci-5.1") ||
129 	    OF_is_compatible(faa->fa_node, "brcm,bcm2711-emmc2") ||
130 	    OF_is_compatible(faa->fa_node, "brcm,bcm2835-sdhci") ||
131 	    OF_is_compatible(faa->fa_node, "marvell,armada-3700-sdhci") ||
132 	    OF_is_compatible(faa->fa_node, "marvell,armada-ap806-sdhci") ||
133 	    OF_is_compatible(faa->fa_node, "marvell,armada-cp110-sdhci"));
134 }
135 
136 void
137 sdhc_fdt_attach(struct device *parent, struct device *self, void *aux)
138 {
139 	struct sdhc_fdt_softc *sc = (struct sdhc_fdt_softc *)self;
140 	struct fdt_attach_args *faa = aux;
141 	struct regmap *rm = NULL;
142 	uint32_t reg, phandle, freq, cap = 0;
143 	char pad_type[16] = { 0 };
144 
145 	if (faa->fa_nreg < 1) {
146 		printf(": no registers\n");
147 		return;
148 	}
149 
150 	sc->sc_iot = faa->fa_iot;
151 	sc->sc_size = faa->fa_reg[0].size;
152 	sc->sc_node = faa->fa_node;
153 
154 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
155 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
156 		printf(": can't map registers\n");
157 		return;
158 	}
159 
160 	pinctrl_byname(faa->fa_node, "default");
161 
162 	clock_set_assigned(faa->fa_node);
163 	clock_enable_all(faa->fa_node);
164 	reset_deassert_all(faa->fa_node);
165 
166 	sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_BIO,
167 	    sdhc_intr, sc, sc->sc.sc_dev.dv_xname);
168 	if (sc->sc_ih == NULL) {
169 		printf(": can't establish interrupt\n");
170 		goto unmap;
171 	}
172 
173 	if (OF_getproplen(faa->fa_node, "cd-gpios") > 0 ||
174 	    OF_getproplen(faa->fa_node, "non-removable") == 0) {
175 		OF_getpropintarray(faa->fa_node, "cd-gpios", sc->sc_gpio,
176 		    sizeof(sc->sc_gpio));
177 		gpio_controller_config_pin(sc->sc_gpio, GPIO_CONFIG_INPUT);
178 		sc->sc.sc_card_detect = sdhc_fdt_card_detect;
179 	}
180 
181 	sc->sc_vqmmc = OF_getpropint(sc->sc_node, "vqmmc-supply", 0);
182 
183 	printf("\n");
184 
185 	sc->sc.sc_host = &sc->sc_host;
186 	sc->sc.sc_dmat = faa->fa_dmat;
187 
188 	/*
189 	 * Arasan controller always uses 1.8V and doesn't like an
190 	 * explicit switch.
191 	 */
192 	if (OF_is_compatible(faa->fa_node, "arasan,sdhci-5.1"))
193 		sc->sc.sc_signal_voltage = sdhc_fdt_signal_voltage;
194 
195 	/*
196 	 * Rockchip RK3399 PHY doesn't like being powered down at low
197 	 * clock speeds and needs to be powered up explicitly.
198 	 */
199 	if (OF_is_compatible(faa->fa_node, "rockchip,rk3399-sdhci-5.1")) {
200 		/*
201 		 * The eMMC core's clock multiplier is of no use, so we just
202 		 * clear it.  Also make sure to set the base clock frequency.
203 		 */
204 		freq = clock_get_frequency(faa->fa_node, "clk_xin");
205 		freq /= 1000 * 1000; /* in MHz */
206 		phandle = OF_getpropint(faa->fa_node,
207 		    "arasan,soc-ctl-syscon", 0);
208 		if (phandle)
209 			rm = regmap_byphandle(phandle);
210 		if (rm) {
211 			regmap_write_4(rm, GRF_EMMCCORE_CON11,
212 			    GRF_EMMCCORE_CON11_CLOCKMULT_CLR |
213 			    GRF_EMMCCORE_CON11_CLOCKMULT_VAL(0));
214 			regmap_write_4(rm, GRF_EMMCCORE_CON0_BASECLOCK,
215 			    GRF_EMMCCORE_CON0_BASECLOCK_CLR |
216 			    GRF_EMMCCORE_CON0_BASECLOCK_VAL(freq));
217 		}
218 		/* Provide base clock frequency for the PHY driver. */
219 		sc->sc_cd.cd_node = faa->fa_node;
220 		sc->sc_cd.cd_cookie = sc;
221 		sc->sc_cd.cd_get_frequency = sdhc_fdt_get_frequency;
222 		clock_register(&sc->sc_cd);
223 		/*
224 		 * Enable the PHY.  The PHY should be powered on/off in
225 		 * the bus_clock function, but it's good enough to just
226 		 * enable it here right away and to keep it powered on.
227 		 */
228 		phy_enable(faa->fa_node, "phy_arasan");
229 		sc->sc.sc_flags |= SDHC_F_NOPWR0;
230 
231 		/* XXX Doesn't work on Rockchip RK3399. */
232 		sc->sc.sc_flags |= SDHC_F_NODDR50;
233 	}
234 
235 	if (OF_is_compatible(faa->fa_node, "brcm,bcm2711-emmc2"))
236 		sc->sc.sc_flags |= SDHC_F_NOPWR0;
237 
238 	if (OF_is_compatible(faa->fa_node, "brcm,bcm2835-sdhci")) {
239 		cap = SDHC_VOLTAGE_SUPP_3_3V | SDHC_HIGH_SPEED_SUPP;
240 		cap |= SDHC_MAX_BLK_LEN_1024 << SDHC_MAX_BLK_LEN_SHIFT;
241 
242 		freq = clock_get_frequency(faa->fa_node, NULL);
243 		sc->sc.sc_clkbase = freq / 1000;
244 
245 		sc->sc.sc_flags |= SDHC_F_32BIT_ACCESS;
246 	}
247 
248 	if (OF_is_compatible(faa->fa_node, "marvell,armada-3700-sdhci") ||
249 	    OF_is_compatible(faa->fa_node, "marvell,armada-ap806-sdhci") ||
250 	    OF_is_compatible(faa->fa_node, "marvell,armada-cp110-sdhci")) {
251 		if (OF_is_compatible(faa->fa_node,
252 		    "marvell,armada-3700-sdhci")) {
253 			KASSERT(faa->fa_nreg > 1);
254 			if (bus_space_map(sc->sc_iot, faa->fa_reg[1].addr,
255 			    faa->fa_reg[1].size, 0, &sc->sc_pad_ioh)) {
256 				printf("%s: can't map registers\n",
257 				    sc->sc.sc_dev.dv_xname);
258 				return;
259 			}
260 			OF_getprop(faa->fa_node, "marvell,pad-type",
261 			    pad_type, sizeof(pad_type));
262 			if (!strcmp(pad_type, "fixed-1-8v")) {
263 				bus_space_write_4(sc->sc_iot, sc->sc_pad_ioh,
264 				    ARMADA_3700_SOC_PAD_CTL,
265 				    ARMADA_3700_SOC_PAD_CTL_1_8V);
266 			} else {
267 				bus_space_write_4(sc->sc_iot, sc->sc_pad_ioh,
268 				    ARMADA_3700_SOC_PAD_CTL,
269 				    ARMADA_3700_SOC_PAD_CTL_3_3V);
270 				regulator_set_voltage(sc->sc_vqmmc, 3300000);
271 			}
272 		}
273 
274 		cap = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
275 		    SDHC_CAPABILITIES);
276 		if (OF_getpropint(faa->fa_node, "bus-width", 1) != 8)
277 			cap &= ~SDHC_8BIT_MODE_SUPP;
278 		if (OF_getproplen(faa->fa_node, "no-1-8-v") == 0)
279 			cap &= ~SDHC_VOLTAGE_SUPP_1_8V;
280 		if (OF_getproplen(faa->fa_node,
281 		    "marvell,xenon-phy-slow-mode") == 0)
282 			sc->sc_slow_mode = 1;
283 
284 		sc->sc_znr = OF_getpropint(faa->fa_node,
285 		    "marvell,xenon-phy-znr", 0xf);
286 		sc->sc_znr &= XENON_EMMC_PHY_PAD_CONTROL2_ZNR_MASK;
287 		sc->sc_zpr = OF_getpropint(faa->fa_node,
288 		    "marvell,xenon-phy-zpr", 0xf);
289 		sc->sc_zpr &= XENON_EMMC_PHY_PAD_CONTROL2_ZPR_MASK;
290 		sc->sc_sdhc_id = OF_getpropint(faa->fa_node,
291 		    "marvell,xenon-sdhc-id", 0);
292 
293 		reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
294 		    XENON_SYS_OP_CTRL);
295 		reg |= XENON_SYS_OP_CTRL_SLOT_ENABLE(sc->sc_sdhc_id);
296 		reg &= ~XENON_SYS_OP_CTRL_SDCLK_IDLEOFF_ENABLE(sc->sc_sdhc_id);
297 		reg &= ~XENON_SYS_OP_CTRL_AUTO_CLKGATE_DISABLE;
298 		bus_space_write_4(sc->sc_iot, sc->sc_ioh,
299 		    XENON_SYS_OP_CTRL, reg);
300 		reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
301 		    XENON_SYS_EXT_OP_CTRL);
302 		reg |= XENON_SYS_EXT_OP_CTRL_PARALLEL_TRAN(sc->sc_sdhc_id);
303 		reg |= XENON_SYS_EXT_OP_CTRL_MASK_CMD_CONFLICT_ERR;
304 		bus_space_write_4(sc->sc_iot, sc->sc_ioh,
305 		    XENON_SYS_EXT_OP_CTRL, reg);
306 
307 		freq = clock_get_frequency(faa->fa_node, NULL);
308 		sc->sc.sc_clkbase = freq / 1000;
309 		sc->sc.sc_bus_clock_post = sdhc_fdt_xenon_bus_clock_post;
310 	}
311 
312 	sdhc_host_found(&sc->sc, sc->sc_iot, sc->sc_ioh, sc->sc_size, 1, cap);
313 	return;
314 
315 unmap:
316 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
317 }
318 
319 int
320 sdhc_fdt_card_detect(struct sdhc_softc *ssc)
321 {
322 	struct sdhc_fdt_softc *sc = (struct sdhc_fdt_softc *)ssc;
323 
324 	if (OF_getproplen(sc->sc_node, "non-removable") == 0)
325 		return 1;
326 
327 	return gpio_controller_get_pin(sc->sc_gpio);
328 }
329 
330 int
331 sdhc_fdt_signal_voltage(struct sdhc_softc *sc, int signal_voltage)
332 {
333 	switch (signal_voltage) {
334 	case SDMMC_SIGNAL_VOLTAGE_180:
335 		return 0;
336 	default:
337 		return EINVAL;
338 	}
339 }
340 
341 uint32_t
342 sdhc_fdt_get_frequency(void *cookie, uint32_t *cells)
343 {
344 	struct sdhc_fdt_softc *sc = cookie;
345 	return clock_get_frequency(sc->sc_cd.cd_node, "clk_xin");
346 }
347 
348 /* Marvell Xenon */
349 void
350 sdhc_fdt_xenon_bus_clock_post(struct sdhc_softc *ssc, int freq, int timing)
351 {
352 	struct sdhc_fdt_softc *sc = (struct sdhc_fdt_softc *)ssc;
353 	uint32_t reg;
354 	int i;
355 
356 	if (freq == 0)
357 		return;
358 
359 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
360 	    XENON_EMMC_PHY_PAD_CONTROL);
361 	reg |= (XENON_EMMC_PHY_PAD_CONTROL_FC_DQ_RECEN |
362 		XENON_EMMC_PHY_PAD_CONTROL_FC_CMD_RECEN |
363 		XENON_EMMC_PHY_PAD_CONTROL_FC_QSP_RECEN |
364 		XENON_EMMC_PHY_PAD_CONTROL_FC_QSN_RECEN |
365 		XENON_EMMC_PHY_PAD_CONTROL_FC_ALL_CMOS_RECVR);
366 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
367 	    XENON_EMMC_PHY_PAD_CONTROL, reg);
368 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
369 	    XENON_EMMC_PHY_PAD_CONTROL1);
370 	reg &= ~(XENON_EMMC_PHY_PAD_CONTROL1_FC_CMD_PD |
371 		XENON_EMMC_PHY_PAD_CONTROL1_FC_DQ_PD);
372 	reg |= (XENON_EMMC_PHY_PAD_CONTROL1_FC_CMD_PU |
373 		XENON_EMMC_PHY_PAD_CONTROL1_FC_DQ_PU);
374 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
375 	    XENON_EMMC_PHY_PAD_CONTROL1, reg);
376 
377 	if (timing == SDMMC_TIMING_LEGACY)
378 		goto phy_init;
379 
380 	/* TODO: check for SMF_IO_MODE and set flag */
381 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
382 	    XENON_EMMC_PHY_TIMING_ADJUST);
383 	reg &= ~XENON_EMMC_PHY_TIMING_ADJUST_SDIO_MODE;
384 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
385 	    XENON_EMMC_PHY_TIMING_ADJUST, reg);
386 
387 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
388 	    XENON_EMMC_PHY_PAD_CONTROL2);
389 	reg &= ~(XENON_EMMC_PHY_PAD_CONTROL2_ZPR_MASK <<
390 	    XENON_EMMC_PHY_PAD_CONTROL2_ZPR_SHIFT |
391 	    XENON_EMMC_PHY_PAD_CONTROL2_ZNR_MASK <<
392 	    XENON_EMMC_PHY_PAD_CONTROL2_ZNR_SHIFT);
393 	reg |= sc->sc_zpr << XENON_EMMC_PHY_PAD_CONTROL2_ZPR_SHIFT |
394 	     sc->sc_znr << XENON_EMMC_PHY_PAD_CONTROL2_ZNR_SHIFT;
395 
396 	reg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SDHC_CLOCK_CTL);
397 	reg &= ~SDHC_SDCLK_ENABLE;
398 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, SDHC_CLOCK_CTL, reg);
399 
400 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
401 	    XENON_EMMC_PHY_FUNC_CONTROL);
402 	reg &= ~(XENON_EMMC_PHY_FUNC_CONTROL_DQ_DDR_MODE |
403 	     XENON_EMMC_PHY_FUNC_CONTROL_CMD_DDR_MODE);
404 	reg |= XENON_EMMC_PHY_FUNC_CONTROL_DQ_ASYNC_MODE;
405 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
406 	    XENON_EMMC_PHY_FUNC_CONTROL, reg);
407 
408 	reg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SDHC_CLOCK_CTL);
409 	reg |= SDHC_SDCLK_ENABLE;
410 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, SDHC_CLOCK_CTL, reg);
411 
412 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
413 	    XENON_SLOT_EMMC_CTRL);
414 	reg &= ~(XENON_SLOT_EMMC_CTRL_ENABLE_DATA_STROBE |
415 	    XENON_SLOT_EMMC_CTRL_ENABLE_RESP_STROBE);
416 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
417 	    XENON_SLOT_EMMC_CTRL, reg);
418 
419 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
420 	    XENON_EMMC_PHY_PAD_CONTROL1);
421 	reg &= ~(XENON_EMMC_PHY_PAD_CONTROL1_FC_QSP_PD |
422 		XENON_EMMC_PHY_PAD_CONTROL1_FC_QSP_PU);
423 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
424 	    XENON_EMMC_PHY_PAD_CONTROL1, reg);
425 
426 phy_init:
427 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
428 	    XENON_EMMC_PHY_TIMING_ADJUST);
429 	reg |= XENON_EMMC_PHY_TIMING_ADJUST_SAMPL_INV_QSP_PHASE_SELECT;
430 	reg &= ~XENON_EMMC_PHY_TIMING_ADJUST_SLOW_MODE;
431 	if (timing == SDMMC_TIMING_LEGACY ||
432 	    timing == SDMMC_TIMING_HIGHSPEED || sc->sc_slow_mode)
433 		reg |= XENON_EMMC_PHY_TIMING_ADJUST_SLOW_MODE;
434 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
435 	    XENON_EMMC_PHY_TIMING_ADJUST, reg);
436 
437 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
438 	    XENON_EMMC_PHY_TIMING_ADJUST);
439 	reg |= XENON_EMMC_PHY_TIMING_ADJUST_INIT;
440 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
441 	    XENON_EMMC_PHY_TIMING_ADJUST, reg);
442 
443 	for (i = 1000; i > 0; i--) {
444 		reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
445 		    XENON_EMMC_PHY_TIMING_ADJUST);
446 		if (!(reg & XENON_EMMC_PHY_TIMING_ADJUST_INIT))
447 			break;
448 		delay(10);
449 	}
450 	if (i == 0)
451 		printf("%s: phy initialization timeout\n",
452 		    sc->sc.sc_dev.dv_xname);
453 
454 	if (freq > SDMMC_SDCLK_400KHZ) {
455 		reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
456 		    XENON_SYS_OP_CTRL);
457 		reg |= XENON_SYS_OP_CTRL_SDCLK_IDLEOFF_ENABLE(sc->sc_sdhc_id);
458 		bus_space_write_4(sc->sc_iot, sc->sc_ioh,
459 		    XENON_SYS_OP_CTRL, reg);
460 	}
461 }
462