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