xref: /openbsd-src/sys/dev/fdt/sdhc_fdt.c (revision fc405d53b73a2d73393cb97f684863d17b583e38)
1 /*	$OpenBSD: sdhc_fdt.c,v 1.20 2023/04/08 05:40:54 jsg 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 const 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, "arasan,sdhci-8.9a") ||
130 	    OF_is_compatible(faa->fa_node, "brcm,bcm2711-emmc2") ||
131 	    OF_is_compatible(faa->fa_node, "brcm,bcm2835-sdhci") ||
132 	    OF_is_compatible(faa->fa_node, "marvell,armada-3700-sdhci") ||
133 	    OF_is_compatible(faa->fa_node, "marvell,armada-ap806-sdhci") ||
134 	    OF_is_compatible(faa->fa_node, "marvell,armada-cp110-sdhci"));
135 }
136 
137 void
138 sdhc_fdt_attach(struct device *parent, struct device *self, void *aux)
139 {
140 	struct sdhc_fdt_softc *sc = (struct sdhc_fdt_softc *)self;
141 	struct fdt_attach_args *faa = aux;
142 	struct regmap *rm = NULL;
143 	uint64_t capmask = 0, capset = 0;
144 	uint32_t reg, phandle, freq;
145 	char pad_type[16] = { 0 };
146 
147 	if (faa->fa_nreg < 1) {
148 		printf(": no registers\n");
149 		return;
150 	}
151 
152 	sc->sc_iot = faa->fa_iot;
153 	sc->sc_size = faa->fa_reg[0].size;
154 	sc->sc_node = faa->fa_node;
155 
156 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
157 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
158 		printf(": can't map registers\n");
159 		return;
160 	}
161 
162 	pinctrl_byname(faa->fa_node, "default");
163 
164 	clock_set_assigned(faa->fa_node);
165 	clock_enable_all(faa->fa_node);
166 	reset_deassert_all(faa->fa_node);
167 
168 	sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_BIO,
169 	    sdhc_intr, sc, sc->sc.sc_dev.dv_xname);
170 	if (sc->sc_ih == NULL) {
171 		printf(": can't establish interrupt\n");
172 		goto unmap;
173 	}
174 
175 	if (OF_getproplen(faa->fa_node, "cd-gpios") > 0 ||
176 	    OF_getproplen(faa->fa_node, "non-removable") == 0) {
177 		OF_getpropintarray(faa->fa_node, "cd-gpios", sc->sc_gpio,
178 		    sizeof(sc->sc_gpio));
179 		gpio_controller_config_pin(sc->sc_gpio, GPIO_CONFIG_INPUT);
180 		sc->sc.sc_card_detect = sdhc_fdt_card_detect;
181 	}
182 
183 	sc->sc_vqmmc = OF_getpropint(sc->sc_node, "vqmmc-supply", 0);
184 
185 	printf("\n");
186 
187 	sc->sc.sc_host = &sc->sc_host;
188 	sc->sc.sc_dmat = faa->fa_dmat;
189 
190 	/*
191 	 * Arasan controller always uses 1.8V and doesn't like an
192 	 * explicit switch.
193 	 */
194 	if (OF_is_compatible(faa->fa_node, "arasan,sdhci-5.1"))
195 		sc->sc.sc_signal_voltage = sdhc_fdt_signal_voltage;
196 
197 	/*
198 	 * Rockchip RK3399 PHY doesn't like being powered down at low
199 	 * clock speeds and needs to be powered up explicitly.
200 	 */
201 	if (OF_is_compatible(faa->fa_node, "rockchip,rk3399-sdhci-5.1")) {
202 		/*
203 		 * The eMMC core's clock multiplier is of no use, so we just
204 		 * clear it.  Also make sure to set the base clock frequency.
205 		 */
206 		freq = clock_get_frequency(faa->fa_node, "clk_xin");
207 		freq /= 1000 * 1000; /* in MHz */
208 		phandle = OF_getpropint(faa->fa_node,
209 		    "arasan,soc-ctl-syscon", 0);
210 		if (phandle)
211 			rm = regmap_byphandle(phandle);
212 		if (rm) {
213 			regmap_write_4(rm, GRF_EMMCCORE_CON11,
214 			    GRF_EMMCCORE_CON11_CLOCKMULT_CLR |
215 			    GRF_EMMCCORE_CON11_CLOCKMULT_VAL(0));
216 			regmap_write_4(rm, GRF_EMMCCORE_CON0_BASECLOCK,
217 			    GRF_EMMCCORE_CON0_BASECLOCK_CLR |
218 			    GRF_EMMCCORE_CON0_BASECLOCK_VAL(freq));
219 		}
220 		/* Provide base clock frequency for the PHY driver. */
221 		sc->sc_cd.cd_node = faa->fa_node;
222 		sc->sc_cd.cd_cookie = sc;
223 		sc->sc_cd.cd_get_frequency = sdhc_fdt_get_frequency;
224 		clock_register(&sc->sc_cd);
225 		/*
226 		 * Enable the PHY.  The PHY should be powered on/off in
227 		 * the bus_clock function, but it's good enough to just
228 		 * enable it here right away and to keep it powered on.
229 		 */
230 		phy_enable(faa->fa_node, "phy_arasan");
231 		sc->sc.sc_flags |= SDHC_F_NOPWR0;
232 
233 		/* XXX Doesn't work on Rockchip RK3399. */
234 		capmask |= (uint64_t)SDHC_DDR50_SUPP << 32;
235 	}
236 
237 	if (OF_is_compatible(faa->fa_node, "arasan,sdhci-8.9a")) {
238 		freq = clock_get_frequency(faa->fa_node, "clk_xin");
239 		sc->sc.sc_clkbase = freq / 1000;
240 	}
241 
242 	if (OF_is_compatible(faa->fa_node, "brcm,bcm2711-emmc2"))
243 		sc->sc.sc_flags |= SDHC_F_NOPWR0;
244 
245 	if (OF_is_compatible(faa->fa_node, "brcm,bcm2835-sdhci")) {
246 		capmask = 0xffffffff;
247 		capset = SDHC_VOLTAGE_SUPP_3_3V | SDHC_HIGH_SPEED_SUPP;
248 		capset |= SDHC_MAX_BLK_LEN_1024 << SDHC_MAX_BLK_LEN_SHIFT;
249 
250 		freq = clock_get_frequency(faa->fa_node, NULL);
251 		sc->sc.sc_clkbase = freq / 1000;
252 
253 		sc->sc.sc_flags |= SDHC_F_32BIT_ACCESS;
254 		sc->sc.sc_flags |= SDHC_F_NO_HS_BIT;
255 	}
256 
257 	if (OF_is_compatible(faa->fa_node, "marvell,armada-3700-sdhci") ||
258 	    OF_is_compatible(faa->fa_node, "marvell,armada-ap806-sdhci") ||
259 	    OF_is_compatible(faa->fa_node, "marvell,armada-cp110-sdhci")) {
260 		if (OF_is_compatible(faa->fa_node,
261 		    "marvell,armada-3700-sdhci")) {
262 			KASSERT(faa->fa_nreg > 1);
263 			if (bus_space_map(sc->sc_iot, faa->fa_reg[1].addr,
264 			    faa->fa_reg[1].size, 0, &sc->sc_pad_ioh)) {
265 				printf("%s: can't map registers\n",
266 				    sc->sc.sc_dev.dv_xname);
267 				return;
268 			}
269 			OF_getprop(faa->fa_node, "marvell,pad-type",
270 			    pad_type, sizeof(pad_type));
271 			if (!strcmp(pad_type, "fixed-1-8v")) {
272 				bus_space_write_4(sc->sc_iot, sc->sc_pad_ioh,
273 				    ARMADA_3700_SOC_PAD_CTL,
274 				    ARMADA_3700_SOC_PAD_CTL_1_8V);
275 			} else {
276 				bus_space_write_4(sc->sc_iot, sc->sc_pad_ioh,
277 				    ARMADA_3700_SOC_PAD_CTL,
278 				    ARMADA_3700_SOC_PAD_CTL_3_3V);
279 				regulator_set_voltage(sc->sc_vqmmc, 3300000);
280 			}
281 		}
282 
283 		if (OF_getpropint(faa->fa_node, "bus-width", 1) != 8)
284 			capmask |= SDHC_8BIT_MODE_SUPP;
285 		if (OF_getproplen(faa->fa_node, "no-1-8-v") == 0) {
286 			capmask |= SDHC_VOLTAGE_SUPP_1_8V;
287 			capmask |= (uint64_t)SDHC_DDR50_SUPP << 32;
288 		}
289 		if (OF_getproplen(faa->fa_node,
290 		    "marvell,xenon-phy-slow-mode") == 0)
291 			sc->sc_slow_mode = 1;
292 
293 		sc->sc_znr = OF_getpropint(faa->fa_node,
294 		    "marvell,xenon-phy-znr", 0xf);
295 		sc->sc_znr &= XENON_EMMC_PHY_PAD_CONTROL2_ZNR_MASK;
296 		sc->sc_zpr = OF_getpropint(faa->fa_node,
297 		    "marvell,xenon-phy-zpr", 0xf);
298 		sc->sc_zpr &= XENON_EMMC_PHY_PAD_CONTROL2_ZPR_MASK;
299 		sc->sc_sdhc_id = OF_getpropint(faa->fa_node,
300 		    "marvell,xenon-sdhc-id", 0);
301 
302 		reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
303 		    XENON_SYS_OP_CTRL);
304 		reg |= XENON_SYS_OP_CTRL_SLOT_ENABLE(sc->sc_sdhc_id);
305 		reg &= ~XENON_SYS_OP_CTRL_SDCLK_IDLEOFF_ENABLE(sc->sc_sdhc_id);
306 		reg &= ~XENON_SYS_OP_CTRL_AUTO_CLKGATE_DISABLE;
307 		bus_space_write_4(sc->sc_iot, sc->sc_ioh,
308 		    XENON_SYS_OP_CTRL, reg);
309 		reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
310 		    XENON_SYS_EXT_OP_CTRL);
311 		reg |= XENON_SYS_EXT_OP_CTRL_PARALLEL_TRAN(sc->sc_sdhc_id);
312 		reg |= XENON_SYS_EXT_OP_CTRL_MASK_CMD_CONFLICT_ERR;
313 		bus_space_write_4(sc->sc_iot, sc->sc_ioh,
314 		    XENON_SYS_EXT_OP_CTRL, reg);
315 
316 		freq = clock_get_frequency(faa->fa_node, NULL);
317 		sc->sc.sc_clkbase = freq / 1000;
318 		sc->sc.sc_bus_clock_post = sdhc_fdt_xenon_bus_clock_post;
319 	}
320 
321 	sdhc_host_found(&sc->sc, sc->sc_iot, sc->sc_ioh, sc->sc_size, 1,
322 	    capmask, capset);
323 	return;
324 
325 unmap:
326 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
327 }
328 
329 int
330 sdhc_fdt_card_detect(struct sdhc_softc *ssc)
331 {
332 	struct sdhc_fdt_softc *sc = (struct sdhc_fdt_softc *)ssc;
333 
334 	if (OF_getproplen(sc->sc_node, "non-removable") == 0)
335 		return 1;
336 
337 	return gpio_controller_get_pin(sc->sc_gpio);
338 }
339 
340 int
341 sdhc_fdt_signal_voltage(struct sdhc_softc *sc, int signal_voltage)
342 {
343 	switch (signal_voltage) {
344 	case SDMMC_SIGNAL_VOLTAGE_180:
345 		return 0;
346 	default:
347 		return EINVAL;
348 	}
349 }
350 
351 uint32_t
352 sdhc_fdt_get_frequency(void *cookie, uint32_t *cells)
353 {
354 	struct sdhc_fdt_softc *sc = cookie;
355 	return clock_get_frequency(sc->sc_cd.cd_node, "clk_xin");
356 }
357 
358 /* Marvell Xenon */
359 void
360 sdhc_fdt_xenon_bus_clock_post(struct sdhc_softc *ssc, int freq, int timing)
361 {
362 	struct sdhc_fdt_softc *sc = (struct sdhc_fdt_softc *)ssc;
363 	uint32_t reg;
364 	int i;
365 
366 	if (freq == 0)
367 		return;
368 
369 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
370 	    XENON_EMMC_PHY_PAD_CONTROL);
371 	reg |= (XENON_EMMC_PHY_PAD_CONTROL_FC_DQ_RECEN |
372 		XENON_EMMC_PHY_PAD_CONTROL_FC_CMD_RECEN |
373 		XENON_EMMC_PHY_PAD_CONTROL_FC_QSP_RECEN |
374 		XENON_EMMC_PHY_PAD_CONTROL_FC_QSN_RECEN |
375 		XENON_EMMC_PHY_PAD_CONTROL_FC_ALL_CMOS_RECVR);
376 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
377 	    XENON_EMMC_PHY_PAD_CONTROL, reg);
378 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
379 	    XENON_EMMC_PHY_PAD_CONTROL1);
380 	reg &= ~(XENON_EMMC_PHY_PAD_CONTROL1_FC_CMD_PD |
381 		XENON_EMMC_PHY_PAD_CONTROL1_FC_DQ_PD);
382 	reg |= (XENON_EMMC_PHY_PAD_CONTROL1_FC_CMD_PU |
383 		XENON_EMMC_PHY_PAD_CONTROL1_FC_DQ_PU);
384 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
385 	    XENON_EMMC_PHY_PAD_CONTROL1, reg);
386 
387 	if (timing == SDMMC_TIMING_LEGACY)
388 		goto phy_init;
389 
390 	/* TODO: check for SMF_IO_MODE and set flag */
391 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
392 	    XENON_EMMC_PHY_TIMING_ADJUST);
393 	reg &= ~XENON_EMMC_PHY_TIMING_ADJUST_SDIO_MODE;
394 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
395 	    XENON_EMMC_PHY_TIMING_ADJUST, reg);
396 
397 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
398 	    XENON_EMMC_PHY_PAD_CONTROL2);
399 	reg &= ~(XENON_EMMC_PHY_PAD_CONTROL2_ZPR_MASK <<
400 	    XENON_EMMC_PHY_PAD_CONTROL2_ZPR_SHIFT |
401 	    XENON_EMMC_PHY_PAD_CONTROL2_ZNR_MASK <<
402 	    XENON_EMMC_PHY_PAD_CONTROL2_ZNR_SHIFT);
403 	reg |= sc->sc_zpr << XENON_EMMC_PHY_PAD_CONTROL2_ZPR_SHIFT |
404 	     sc->sc_znr << XENON_EMMC_PHY_PAD_CONTROL2_ZNR_SHIFT;
405 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
406 	    XENON_EMMC_PHY_PAD_CONTROL2, 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_EMMC_PHY_FUNC_CONTROL);
414 	reg &= ~(XENON_EMMC_PHY_FUNC_CONTROL_DQ_DDR_MODE |
415 	     XENON_EMMC_PHY_FUNC_CONTROL_CMD_DDR_MODE);
416 	reg |= XENON_EMMC_PHY_FUNC_CONTROL_DQ_ASYNC_MODE;
417 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
418 	    XENON_EMMC_PHY_FUNC_CONTROL, reg);
419 
420 	reg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SDHC_CLOCK_CTL);
421 	reg |= SDHC_SDCLK_ENABLE;
422 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, SDHC_CLOCK_CTL, reg);
423 
424 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
425 	    XENON_SLOT_EMMC_CTRL);
426 	reg &= ~(XENON_SLOT_EMMC_CTRL_ENABLE_DATA_STROBE |
427 	    XENON_SLOT_EMMC_CTRL_ENABLE_RESP_STROBE);
428 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
429 	    XENON_SLOT_EMMC_CTRL, reg);
430 
431 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
432 	    XENON_EMMC_PHY_PAD_CONTROL1);
433 	reg &= ~(XENON_EMMC_PHY_PAD_CONTROL1_FC_QSP_PD |
434 		XENON_EMMC_PHY_PAD_CONTROL1_FC_QSP_PU);
435 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
436 	    XENON_EMMC_PHY_PAD_CONTROL1, reg);
437 
438 phy_init:
439 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
440 	    XENON_EMMC_PHY_TIMING_ADJUST);
441 	reg |= XENON_EMMC_PHY_TIMING_ADJUST_SAMPL_INV_QSP_PHASE_SELECT;
442 	reg &= ~XENON_EMMC_PHY_TIMING_ADJUST_SLOW_MODE;
443 	if (timing == SDMMC_TIMING_LEGACY ||
444 	    timing == SDMMC_TIMING_HIGHSPEED || sc->sc_slow_mode)
445 		reg |= XENON_EMMC_PHY_TIMING_ADJUST_SLOW_MODE;
446 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
447 	    XENON_EMMC_PHY_TIMING_ADJUST, reg);
448 
449 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
450 	    XENON_EMMC_PHY_TIMING_ADJUST);
451 	reg |= XENON_EMMC_PHY_TIMING_ADJUST_INIT;
452 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
453 	    XENON_EMMC_PHY_TIMING_ADJUST, reg);
454 
455 	for (i = 1000; i > 0; i--) {
456 		reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
457 		    XENON_EMMC_PHY_TIMING_ADJUST);
458 		if (!(reg & XENON_EMMC_PHY_TIMING_ADJUST_INIT))
459 			break;
460 		delay(10);
461 	}
462 	if (i == 0)
463 		printf("%s: phy initialization timeout\n",
464 		    sc->sc.sc_dev.dv_xname);
465 
466 	if (freq > SDMMC_SDCLK_400KHZ) {
467 		reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
468 		    XENON_SYS_OP_CTRL);
469 		reg |= XENON_SYS_OP_CTRL_SDCLK_IDLEOFF_ENABLE(sc->sc_sdhc_id);
470 		bus_space_write_4(sc->sc_iot, sc->sc_ioh,
471 		    XENON_SYS_OP_CTRL, reg);
472 	}
473 }
474