meson_sdhc.c revision 1.6 1 1.6 jmcneill /* $NetBSD: meson_sdhc.c,v 1.6 2021/11/07 17:11:58 jmcneill Exp $ */
2 1.1 jmcneill
3 1.1 jmcneill /*-
4 1.1 jmcneill * Copyright (c) 2015-2019 Jared McNeill <jmcneill (at) invisible.ca>
5 1.1 jmcneill * All rights reserved.
6 1.1 jmcneill *
7 1.1 jmcneill * Redistribution and use in source and binary forms, with or without
8 1.1 jmcneill * modification, are permitted provided that the following conditions
9 1.1 jmcneill * are met:
10 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright
11 1.1 jmcneill * notice, this list of conditions and the following disclaimer.
12 1.1 jmcneill * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 jmcneill * notice, this list of conditions and the following disclaimer in the
14 1.1 jmcneill * documentation and/or other materials provided with the distribution.
15 1.1 jmcneill *
16 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.1 jmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.1 jmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.1 jmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.1 jmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 1.1 jmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 1.1 jmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 1.1 jmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 1.1 jmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 1.1 jmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 1.1 jmcneill * SUCH DAMAGE.
27 1.1 jmcneill */
28 1.1 jmcneill
29 1.1 jmcneill #include <sys/cdefs.h>
30 1.6 jmcneill __KERNEL_RCSID(0, "$NetBSD: meson_sdhc.c,v 1.6 2021/11/07 17:11:58 jmcneill Exp $");
31 1.1 jmcneill
32 1.1 jmcneill #include <sys/param.h>
33 1.1 jmcneill #include <sys/bus.h>
34 1.1 jmcneill #include <sys/device.h>
35 1.1 jmcneill #include <sys/intr.h>
36 1.1 jmcneill #include <sys/systm.h>
37 1.1 jmcneill #include <sys/kernel.h>
38 1.1 jmcneill #include <sys/gpio.h>
39 1.1 jmcneill
40 1.1 jmcneill #include <dev/sdmmc/sdmmcvar.h>
41 1.1 jmcneill #include <dev/sdmmc/sdmmcchip.h>
42 1.1 jmcneill #include <dev/sdmmc/sdmmc_ioreg.h>
43 1.1 jmcneill
44 1.1 jmcneill #include <dev/fdt/fdtvar.h>
45 1.1 jmcneill
46 1.1 jmcneill #include <arm/amlogic/meson_sdhcreg.h>
47 1.1 jmcneill
48 1.1 jmcneill enum {
49 1.1 jmcneill SDHC_PORT_A = 0,
50 1.1 jmcneill SDHC_PORT_B = 1,
51 1.1 jmcneill SDHC_PORT_C = 2
52 1.1 jmcneill };
53 1.1 jmcneill
54 1.1 jmcneill static int meson_sdhc_match(device_t, cfdata_t, void *);
55 1.1 jmcneill static void meson_sdhc_attach(device_t, device_t, void *);
56 1.1 jmcneill static void meson_sdhc_attach_i(device_t);
57 1.1 jmcneill
58 1.1 jmcneill static int meson_sdhc_intr(void *);
59 1.1 jmcneill
60 1.1 jmcneill struct meson_sdhc_softc {
61 1.1 jmcneill device_t sc_dev;
62 1.1 jmcneill bus_space_tag_t sc_bst;
63 1.1 jmcneill bus_space_handle_t sc_bsh;
64 1.1 jmcneill bus_dma_tag_t sc_dmat;
65 1.1 jmcneill void *sc_ih;
66 1.1 jmcneill
67 1.1 jmcneill device_t sc_sdmmc_dev;
68 1.1 jmcneill kmutex_t sc_intr_lock;
69 1.1 jmcneill kcondvar_t sc_intr_cv;
70 1.1 jmcneill
71 1.1 jmcneill uint32_t sc_intr_ista;
72 1.1 jmcneill
73 1.1 jmcneill bus_dmamap_t sc_dmamap;
74 1.1 jmcneill bus_dma_segment_t sc_segs[1];
75 1.1 jmcneill void *sc_bbuf;
76 1.1 jmcneill
77 1.1 jmcneill u_int sc_bus_freq;
78 1.1 jmcneill
79 1.1 jmcneill struct fdtbus_gpio_pin *sc_gpio_cd;
80 1.1 jmcneill int sc_gpio_cd_inverted;
81 1.1 jmcneill struct fdtbus_gpio_pin *sc_gpio_wp;
82 1.1 jmcneill int sc_gpio_wp_inverted;
83 1.1 jmcneill
84 1.1 jmcneill struct fdtbus_regulator *sc_reg_vmmc;
85 1.1 jmcneill struct fdtbus_regulator *sc_reg_vqmmc;
86 1.1 jmcneill
87 1.1 jmcneill bool sc_non_removable;
88 1.1 jmcneill bool sc_broken_cd;
89 1.1 jmcneill
90 1.1 jmcneill int sc_port;
91 1.1 jmcneill int sc_slot_phandle;
92 1.1 jmcneill int sc_signal_voltage;
93 1.1 jmcneill };
94 1.1 jmcneill
95 1.1 jmcneill CFATTACH_DECL_NEW(meson_sdhc, sizeof(struct meson_sdhc_softc),
96 1.1 jmcneill meson_sdhc_match, meson_sdhc_attach, NULL, NULL);
97 1.1 jmcneill
98 1.1 jmcneill static int meson_sdhc_host_reset(sdmmc_chipset_handle_t);
99 1.1 jmcneill static uint32_t meson_sdhc_host_ocr(sdmmc_chipset_handle_t);
100 1.1 jmcneill static int meson_sdhc_host_maxblklen(sdmmc_chipset_handle_t);
101 1.1 jmcneill static int meson_sdhc_card_detect(sdmmc_chipset_handle_t);
102 1.1 jmcneill static int meson_sdhc_write_protect(sdmmc_chipset_handle_t);
103 1.1 jmcneill static int meson_sdhc_bus_power(sdmmc_chipset_handle_t, uint32_t);
104 1.1 jmcneill static int meson_sdhc_bus_clock(sdmmc_chipset_handle_t, int);
105 1.1 jmcneill static int meson_sdhc_bus_width(sdmmc_chipset_handle_t, int);
106 1.1 jmcneill static int meson_sdhc_bus_rod(sdmmc_chipset_handle_t, int);
107 1.1 jmcneill static void meson_sdhc_exec_command(sdmmc_chipset_handle_t,
108 1.1 jmcneill struct sdmmc_command *);
109 1.1 jmcneill static void meson_sdhc_card_enable_intr(sdmmc_chipset_handle_t, int);
110 1.1 jmcneill static void meson_sdhc_card_intr_ack(sdmmc_chipset_handle_t);
111 1.1 jmcneill static int meson_sdhc_signal_voltage(sdmmc_chipset_handle_t, int);
112 1.1 jmcneill static int meson_sdhc_execute_tuning(sdmmc_chipset_handle_t, int);
113 1.1 jmcneill
114 1.1 jmcneill static int meson_sdhc_default_rx_phase(struct meson_sdhc_softc *);
115 1.1 jmcneill static int meson_sdhc_set_clock(struct meson_sdhc_softc *, u_int);
116 1.1 jmcneill static int meson_sdhc_wait_idle(struct meson_sdhc_softc *);
117 1.1 jmcneill static int meson_sdhc_wait_ista(struct meson_sdhc_softc *, uint32_t, int);
118 1.1 jmcneill
119 1.1 jmcneill static void meson_sdhc_dmainit(struct meson_sdhc_softc *);
120 1.1 jmcneill
121 1.1 jmcneill static struct sdmmc_chip_functions meson_sdhc_chip_functions = {
122 1.1 jmcneill .host_reset = meson_sdhc_host_reset,
123 1.1 jmcneill .host_ocr = meson_sdhc_host_ocr,
124 1.1 jmcneill .host_maxblklen = meson_sdhc_host_maxblklen,
125 1.1 jmcneill .card_detect = meson_sdhc_card_detect,
126 1.1 jmcneill .write_protect = meson_sdhc_write_protect,
127 1.1 jmcneill .bus_power = meson_sdhc_bus_power,
128 1.1 jmcneill .bus_clock = meson_sdhc_bus_clock,
129 1.1 jmcneill .bus_width = meson_sdhc_bus_width,
130 1.1 jmcneill .bus_rod = meson_sdhc_bus_rod,
131 1.1 jmcneill .exec_command = meson_sdhc_exec_command,
132 1.1 jmcneill .card_enable_intr = meson_sdhc_card_enable_intr,
133 1.1 jmcneill .card_intr_ack = meson_sdhc_card_intr_ack,
134 1.1 jmcneill .signal_voltage = meson_sdhc_signal_voltage,
135 1.1 jmcneill .execute_tuning = meson_sdhc_execute_tuning,
136 1.1 jmcneill };
137 1.1 jmcneill
138 1.1 jmcneill #define SDHC_WRITE(sc, reg, val) \
139 1.1 jmcneill bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
140 1.1 jmcneill #define SDHC_READ(sc, reg) \
141 1.1 jmcneill bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
142 1.1 jmcneill #define SDHC_SET_CLEAR meson_sdhc_set_clear
143 1.1 jmcneill
144 1.1 jmcneill static inline void
145 1.1 jmcneill meson_sdhc_set_clear(struct meson_sdhc_softc *sc, bus_addr_t reg, uint32_t set, uint32_t clr)
146 1.1 jmcneill {
147 1.1 jmcneill const uint32_t old = SDHC_READ(sc, reg);
148 1.1 jmcneill const uint32_t new = set | (old & ~clr);
149 1.1 jmcneill if (old != new)
150 1.1 jmcneill SDHC_WRITE(sc, reg, new);
151 1.1 jmcneill }
152 1.1 jmcneill
153 1.3 thorpej static const struct device_compatible_entry compat_data[] = {
154 1.6 jmcneill { .compat = "amlogic,meson8-sdhc" },
155 1.6 jmcneill { .compat = "amlogic,meson8b-sdhc" }, /* DTCOMPAT */
156 1.3 thorpej DEVICE_COMPAT_EOL
157 1.1 jmcneill };
158 1.1 jmcneill
159 1.3 thorpej static const struct device_compatible_entry slot_compat_data[] = {
160 1.3 thorpej { .compat = "mmc-slot" },
161 1.3 thorpej DEVICE_COMPAT_EOL
162 1.1 jmcneill };
163 1.1 jmcneill
164 1.1 jmcneill static int
165 1.1 jmcneill meson_sdhc_match(device_t parent, cfdata_t cf, void *aux)
166 1.1 jmcneill {
167 1.1 jmcneill struct fdt_attach_args * const faa = aux;
168 1.1 jmcneill
169 1.3 thorpej return of_compatible_match(faa->faa_phandle, compat_data);
170 1.1 jmcneill }
171 1.1 jmcneill
172 1.1 jmcneill static void
173 1.1 jmcneill meson_sdhc_attach(device_t parent, device_t self, void *aux)
174 1.1 jmcneill {
175 1.1 jmcneill struct meson_sdhc_softc * const sc = device_private(self);
176 1.1 jmcneill struct fdt_attach_args * const faa = aux;
177 1.1 jmcneill const int phandle = faa->faa_phandle;
178 1.1 jmcneill char intrstr[128];
179 1.1 jmcneill struct clk *clk_clkin, *clk_core;
180 1.1 jmcneill bus_addr_t addr, port;
181 1.1 jmcneill bus_size_t size;
182 1.1 jmcneill int child;
183 1.1 jmcneill
184 1.1 jmcneill if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
185 1.1 jmcneill aprint_error(": couldn't get registers\n");
186 1.1 jmcneill return;
187 1.1 jmcneill }
188 1.1 jmcneill
189 1.1 jmcneill if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
190 1.1 jmcneill aprint_error(": failed to decode interrupt\n");
191 1.1 jmcneill return;
192 1.1 jmcneill }
193 1.1 jmcneill
194 1.1 jmcneill clk_core = fdtbus_clock_get(phandle, "core");
195 1.6 jmcneill if (clk_core == NULL) {
196 1.6 jmcneill clk_core = fdtbus_clock_get(phandle, "pclk");
197 1.6 jmcneill }
198 1.1 jmcneill if (clk_core == NULL || clk_enable(clk_core) != 0) {
199 1.6 jmcneill aprint_error(": failed to enable core/pclk clock\n");
200 1.1 jmcneill return;
201 1.1 jmcneill }
202 1.1 jmcneill
203 1.1 jmcneill clk_clkin = fdtbus_clock_get(phandle, "clkin");
204 1.6 jmcneill if (clk_clkin == NULL) {
205 1.6 jmcneill clk_clkin = fdtbus_clock_get(phandle, "clkin2");
206 1.6 jmcneill }
207 1.1 jmcneill if (clk_clkin == NULL || clk_enable(clk_clkin) != 0) {
208 1.6 jmcneill aprint_error(": failed to get clkin/clkin2 clock\n");
209 1.1 jmcneill return;
210 1.1 jmcneill }
211 1.1 jmcneill
212 1.1 jmcneill sc->sc_dev = self;
213 1.1 jmcneill sc->sc_bst = faa->faa_bst;
214 1.1 jmcneill sc->sc_dmat = faa->faa_dmat;
215 1.1 jmcneill if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
216 1.1 jmcneill aprint_error(": failed to map registers\n");
217 1.1 jmcneill return;
218 1.1 jmcneill }
219 1.1 jmcneill mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
220 1.1 jmcneill cv_init(&sc->sc_intr_cv, "sdhcintr");
221 1.1 jmcneill sc->sc_signal_voltage = SDMMC_SIGNAL_VOLTAGE_330;
222 1.1 jmcneill
223 1.1 jmcneill sc->sc_port = -1;
224 1.1 jmcneill for (child = OF_child(phandle); child; child = OF_peer(child))
225 1.3 thorpej if (of_compatible_match(child, slot_compat_data)) {
226 1.1 jmcneill if (fdtbus_get_reg(child, 0, &port, NULL) == 0) {
227 1.1 jmcneill sc->sc_slot_phandle = child;
228 1.1 jmcneill sc->sc_port = port;
229 1.1 jmcneill }
230 1.1 jmcneill break;
231 1.1 jmcneill }
232 1.1 jmcneill if (sc->sc_port == -1) {
233 1.1 jmcneill aprint_error(": couldn't get mmc slot\n");
234 1.1 jmcneill return;
235 1.1 jmcneill }
236 1.1 jmcneill
237 1.1 jmcneill aprint_naive("\n");
238 1.1 jmcneill aprint_normal(": SDHC controller (port %c)\n", sc->sc_port + 'A');
239 1.1 jmcneill
240 1.1 jmcneill sc->sc_reg_vmmc = fdtbus_regulator_acquire(sc->sc_slot_phandle, "vmmc-supply");
241 1.1 jmcneill sc->sc_reg_vqmmc = fdtbus_regulator_acquire(sc->sc_slot_phandle, "vqmmc-supply");
242 1.1 jmcneill
243 1.1 jmcneill sc->sc_gpio_cd = fdtbus_gpio_acquire(sc->sc_slot_phandle, "cd-gpios",
244 1.1 jmcneill GPIO_PIN_INPUT);
245 1.1 jmcneill sc->sc_gpio_wp = fdtbus_gpio_acquire(sc->sc_slot_phandle, "wp-gpios",
246 1.1 jmcneill GPIO_PIN_INPUT);
247 1.1 jmcneill
248 1.1 jmcneill sc->sc_gpio_cd_inverted = of_hasprop(sc->sc_slot_phandle, "cd-inverted");
249 1.1 jmcneill sc->sc_gpio_wp_inverted = of_hasprop(sc->sc_slot_phandle, "wp-inverted");
250 1.1 jmcneill
251 1.1 jmcneill sc->sc_non_removable = of_hasprop(sc->sc_slot_phandle, "non-removable");
252 1.1 jmcneill sc->sc_broken_cd = of_hasprop(sc->sc_slot_phandle, "broken-cd");
253 1.1 jmcneill
254 1.2 ryo sc->sc_ih = fdtbus_intr_establish_xname(phandle, 0, IPL_BIO, 0,
255 1.2 ryo meson_sdhc_intr, sc, device_xname(self));
256 1.1 jmcneill if (sc->sc_ih == NULL) {
257 1.1 jmcneill aprint_error_dev(self, "couldn't establish interrupt on %s\n",
258 1.1 jmcneill intrstr);
259 1.1 jmcneill return;
260 1.1 jmcneill }
261 1.1 jmcneill aprint_normal_dev(self, "interrupting on %s\n", intrstr);
262 1.1 jmcneill
263 1.1 jmcneill sc->sc_bus_freq = clk_get_rate(clk_clkin);
264 1.1 jmcneill
265 1.1 jmcneill aprint_normal_dev(self, "core %u Hz, clkin %u Hz\n", clk_get_rate(clk_core), clk_get_rate(clk_clkin));
266 1.1 jmcneill
267 1.1 jmcneill meson_sdhc_dmainit(sc);
268 1.1 jmcneill
269 1.1 jmcneill config_interrupts(self, meson_sdhc_attach_i);
270 1.1 jmcneill }
271 1.1 jmcneill
272 1.1 jmcneill static void
273 1.1 jmcneill meson_sdhc_attach_i(device_t self)
274 1.1 jmcneill {
275 1.1 jmcneill struct meson_sdhc_softc *sc = device_private(self);
276 1.1 jmcneill struct sdmmcbus_attach_args saa;
277 1.1 jmcneill u_int pll_freq;
278 1.1 jmcneill
279 1.1 jmcneill pll_freq = sc->sc_bus_freq / 1000;
280 1.1 jmcneill
281 1.1 jmcneill meson_sdhc_host_reset(sc);
282 1.1 jmcneill meson_sdhc_bus_width(sc, 1);
283 1.1 jmcneill
284 1.1 jmcneill memset(&saa, 0, sizeof(saa));
285 1.1 jmcneill saa.saa_busname = "sdmmc";
286 1.1 jmcneill saa.saa_sct = &meson_sdhc_chip_functions;
287 1.1 jmcneill saa.saa_dmat = sc->sc_dmat;
288 1.1 jmcneill saa.saa_sch = sc;
289 1.1 jmcneill saa.saa_clkmin = 400;
290 1.1 jmcneill saa.saa_clkmax = pll_freq;
291 1.1 jmcneill /* Do not advertise DMA capabilities, we handle DMA ourselves */
292 1.1 jmcneill saa.saa_caps = SMC_CAPS_4BIT_MODE|
293 1.1 jmcneill SMC_CAPS_SD_HIGHSPEED|
294 1.1 jmcneill SMC_CAPS_MMC_HIGHSPEED|
295 1.1 jmcneill SMC_CAPS_UHS_SDR50|
296 1.1 jmcneill SMC_CAPS_UHS_SDR104|
297 1.1 jmcneill SMC_CAPS_AUTO_STOP;
298 1.1 jmcneill
299 1.1 jmcneill if (sc->sc_port == SDHC_PORT_C) {
300 1.1 jmcneill saa.saa_caps |= SMC_CAPS_MMC_HS200;
301 1.1 jmcneill saa.saa_caps |= SMC_CAPS_8BIT_MODE;
302 1.1 jmcneill }
303 1.1 jmcneill
304 1.5 thorpej sc->sc_sdmmc_dev = config_found(self, &saa, NULL, CFARGS_NONE);
305 1.1 jmcneill }
306 1.1 jmcneill
307 1.1 jmcneill static int
308 1.1 jmcneill meson_sdhc_intr(void *priv)
309 1.1 jmcneill {
310 1.1 jmcneill struct meson_sdhc_softc *sc = priv;
311 1.1 jmcneill uint32_t ista;
312 1.1 jmcneill
313 1.1 jmcneill mutex_enter(&sc->sc_intr_lock);
314 1.1 jmcneill ista = SDHC_READ(sc, SD_ISTA_REG);
315 1.1 jmcneill
316 1.1 jmcneill if (!ista) {
317 1.1 jmcneill mutex_exit(&sc->sc_intr_lock);
318 1.1 jmcneill return 0;
319 1.1 jmcneill }
320 1.1 jmcneill
321 1.1 jmcneill SDHC_WRITE(sc, SD_ISTA_REG, ista);
322 1.1 jmcneill
323 1.1 jmcneill sc->sc_intr_ista |= ista;
324 1.1 jmcneill cv_broadcast(&sc->sc_intr_cv);
325 1.1 jmcneill
326 1.1 jmcneill mutex_exit(&sc->sc_intr_lock);
327 1.1 jmcneill
328 1.1 jmcneill return 1;
329 1.1 jmcneill }
330 1.1 jmcneill
331 1.1 jmcneill static void
332 1.1 jmcneill meson_sdhc_dmainit(struct meson_sdhc_softc *sc)
333 1.1 jmcneill {
334 1.1 jmcneill int error, rseg;
335 1.1 jmcneill
336 1.1 jmcneill error = bus_dmamem_alloc(sc->sc_dmat, MAXPHYS, PAGE_SIZE, MAXPHYS,
337 1.1 jmcneill sc->sc_segs, 1, &rseg, BUS_DMA_WAITOK);
338 1.1 jmcneill if (error) {
339 1.1 jmcneill device_printf(sc->sc_dev, "bus_dmamem_alloc failed: %d\n", error);
340 1.1 jmcneill return;
341 1.1 jmcneill }
342 1.1 jmcneill KASSERT(rseg == 1);
343 1.1 jmcneill
344 1.1 jmcneill error = bus_dmamem_map(sc->sc_dmat, sc->sc_segs, rseg, MAXPHYS,
345 1.1 jmcneill &sc->sc_bbuf, BUS_DMA_WAITOK);
346 1.1 jmcneill if (error) {
347 1.1 jmcneill device_printf(sc->sc_dev, "bus_dmamem_map failed\n");
348 1.1 jmcneill return;
349 1.1 jmcneill }
350 1.1 jmcneill
351 1.1 jmcneill error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, 1, MAXPHYS, 0,
352 1.1 jmcneill BUS_DMA_WAITOK, &sc->sc_dmamap);
353 1.1 jmcneill if (error) {
354 1.1 jmcneill device_printf(sc->sc_dev, "bus_dmamap_create failed\n");
355 1.1 jmcneill return;
356 1.1 jmcneill }
357 1.1 jmcneill
358 1.1 jmcneill }
359 1.1 jmcneill
360 1.1 jmcneill static int
361 1.1 jmcneill meson_sdhc_default_rx_phase(struct meson_sdhc_softc *sc)
362 1.1 jmcneill {
363 1.1 jmcneill const u_int pll_freq = sc->sc_bus_freq / 1000;
364 1.1 jmcneill const u_int clkc = SDHC_READ(sc, SD_CLKC_REG);
365 1.1 jmcneill const u_int clk_div = __SHIFTOUT(clkc, SD_CLKC_CLK_DIV);
366 1.1 jmcneill const u_int act_freq = pll_freq / clk_div;
367 1.1 jmcneill
368 1.1 jmcneill if (act_freq > 90000) {
369 1.1 jmcneill return 1;
370 1.1 jmcneill } else if (act_freq > 45000) {
371 1.1 jmcneill if (sc->sc_signal_voltage == SDMMC_SIGNAL_VOLTAGE_330) {
372 1.1 jmcneill return 15;
373 1.1 jmcneill } else {
374 1.1 jmcneill return 11;
375 1.1 jmcneill }
376 1.1 jmcneill } else if (act_freq >= 25000) {
377 1.1 jmcneill return 15;
378 1.1 jmcneill } else if (act_freq > 5000) {
379 1.1 jmcneill return 23;
380 1.1 jmcneill } else if (act_freq > 1000) {
381 1.1 jmcneill return 55;
382 1.1 jmcneill } else {
383 1.1 jmcneill return 1061;
384 1.1 jmcneill }
385 1.1 jmcneill }
386 1.1 jmcneill
387 1.1 jmcneill static int
388 1.1 jmcneill meson_sdhc_set_clock(struct meson_sdhc_softc *sc, u_int freq)
389 1.1 jmcneill {
390 1.1 jmcneill uint32_t clkc;
391 1.1 jmcneill uint32_t clk2;
392 1.1 jmcneill u_int pll_freq, clk_div;
393 1.1 jmcneill
394 1.1 jmcneill clkc = SDHC_READ(sc, SD_CLKC_REG);
395 1.1 jmcneill clkc &= ~SD_CLKC_TX_CLK_ENABLE;
396 1.1 jmcneill clkc &= ~SD_CLKC_RX_CLK_ENABLE;
397 1.1 jmcneill clkc &= ~SD_CLKC_SD_CLK_ENABLE;
398 1.1 jmcneill SDHC_WRITE(sc, SD_CLKC_REG, clkc);
399 1.1 jmcneill clkc &= ~SD_CLKC_MOD_CLK_ENABLE;
400 1.1 jmcneill SDHC_WRITE(sc, SD_CLKC_REG, clkc);
401 1.1 jmcneill
402 1.1 jmcneill if (freq == 0)
403 1.1 jmcneill return 0;
404 1.1 jmcneill
405 1.1 jmcneill clkc &= ~SD_CLKC_CLK_DIV;
406 1.1 jmcneill clkc &= ~SD_CLKC_CLK_IN_SEL;
407 1.1 jmcneill
408 1.1 jmcneill clkc |= __SHIFTIN(SD_CLKC_CLK_IN_SEL_FCLK_DIV3,
409 1.1 jmcneill SD_CLKC_CLK_IN_SEL);
410 1.1 jmcneill
411 1.1 jmcneill pll_freq = sc->sc_bus_freq / 1000; /* 2.55GHz */
412 1.1 jmcneill clk_div = howmany(pll_freq, freq);
413 1.1 jmcneill
414 1.1 jmcneill clkc |= __SHIFTIN(clk_div - 1, SD_CLKC_CLK_DIV);
415 1.1 jmcneill
416 1.1 jmcneill SDHC_WRITE(sc, SD_CLKC_REG, clkc);
417 1.1 jmcneill
418 1.1 jmcneill clkc |= SD_CLKC_MOD_CLK_ENABLE;
419 1.1 jmcneill SDHC_WRITE(sc, SD_CLKC_REG, clkc);
420 1.1 jmcneill
421 1.1 jmcneill clkc |= SD_CLKC_TX_CLK_ENABLE;
422 1.1 jmcneill clkc |= SD_CLKC_RX_CLK_ENABLE;
423 1.1 jmcneill clkc |= SD_CLKC_SD_CLK_ENABLE;
424 1.1 jmcneill SDHC_WRITE(sc, SD_CLKC_REG, clkc);
425 1.1 jmcneill
426 1.1 jmcneill clk2 = SDHC_READ(sc, SD_CLK2_REG);
427 1.1 jmcneill clk2 &= ~SD_CLK2_SD_CLK_PHASE;
428 1.1 jmcneill clk2 |= __SHIFTIN(1, SD_CLK2_SD_CLK_PHASE);
429 1.1 jmcneill clk2 &= ~SD_CLK2_RX_CLK_PHASE;
430 1.1 jmcneill clk2 |= __SHIFTIN(meson_sdhc_default_rx_phase(sc),
431 1.1 jmcneill SD_CLK2_RX_CLK_PHASE);
432 1.1 jmcneill SDHC_WRITE(sc, SD_CLK2_REG, clk2);
433 1.1 jmcneill
434 1.1 jmcneill return 0;
435 1.1 jmcneill }
436 1.1 jmcneill
437 1.1 jmcneill static int
438 1.1 jmcneill meson_sdhc_wait_idle(struct meson_sdhc_softc *sc)
439 1.1 jmcneill {
440 1.1 jmcneill int i;
441 1.1 jmcneill
442 1.1 jmcneill for (i = 0; i < 1000000; i++) {
443 1.1 jmcneill const uint32_t stat = SDHC_READ(sc, SD_STAT_REG);
444 1.1 jmcneill const uint32_t esta = SDHC_READ(sc, SD_ESTA_REG);
445 1.1 jmcneill if ((stat & SD_STAT_BUSY) == 0 &&
446 1.1 jmcneill (esta & SD_ESTA_BUSY) == 0)
447 1.1 jmcneill return 0;
448 1.1 jmcneill delay(1);
449 1.1 jmcneill }
450 1.1 jmcneill
451 1.1 jmcneill return EBUSY;
452 1.1 jmcneill }
453 1.1 jmcneill
454 1.1 jmcneill static int
455 1.1 jmcneill meson_sdhc_wait_ista(struct meson_sdhc_softc *sc, uint32_t mask, int timeout)
456 1.1 jmcneill {
457 1.1 jmcneill int retry, error;
458 1.1 jmcneill
459 1.1 jmcneill KASSERT(mutex_owned(&sc->sc_intr_lock));
460 1.1 jmcneill
461 1.1 jmcneill if (sc->sc_intr_ista & mask)
462 1.1 jmcneill return 0;
463 1.1 jmcneill
464 1.1 jmcneill retry = timeout / hz;
465 1.1 jmcneill
466 1.1 jmcneill while (retry > 0) {
467 1.1 jmcneill error = cv_timedwait(&sc->sc_intr_cv, &sc->sc_intr_lock, hz);
468 1.1 jmcneill if (error && error != EWOULDBLOCK)
469 1.1 jmcneill return error;
470 1.1 jmcneill if (sc->sc_intr_ista & mask)
471 1.1 jmcneill return 0;
472 1.1 jmcneill --retry;
473 1.1 jmcneill }
474 1.1 jmcneill
475 1.1 jmcneill return ETIMEDOUT;
476 1.1 jmcneill }
477 1.1 jmcneill
478 1.1 jmcneill static int
479 1.1 jmcneill meson_sdhc_host_reset(sdmmc_chipset_handle_t sch)
480 1.1 jmcneill {
481 1.1 jmcneill struct meson_sdhc_softc *sc = sch;
482 1.1 jmcneill uint32_t enhc;
483 1.1 jmcneill
484 1.1 jmcneill SDHC_WRITE(sc, SD_SRST_REG,
485 1.1 jmcneill SD_SRST_MAIN_CTRL | SD_SRST_TX_FIFO | SD_SRST_RX_FIFO |
486 1.1 jmcneill SD_SRST_DPHY_TX | SD_SRST_DPHY_RX | SD_SRST_DMA_IF);
487 1.1 jmcneill
488 1.1 jmcneill delay(50);
489 1.1 jmcneill
490 1.1 jmcneill SDHC_WRITE(sc, SD_SRST_REG, 0);
491 1.1 jmcneill
492 1.1 jmcneill delay(10);
493 1.1 jmcneill
494 1.1 jmcneill SDHC_WRITE(sc, SD_CNTL_REG,
495 1.1 jmcneill __SHIFTIN(0x7, SD_CNTL_TX_ENDIAN_CTRL) |
496 1.1 jmcneill __SHIFTIN(0x7, SD_CNTL_RX_ENDIAN_CTRL) |
497 1.1 jmcneill __SHIFTIN(0xf, SD_CNTL_RX_PERIOD) |
498 1.1 jmcneill __SHIFTIN(0x7f, SD_CNTL_RX_TIMEOUT));
499 1.1 jmcneill
500 1.1 jmcneill SDHC_WRITE(sc, SD_CLKC_REG,
501 1.1 jmcneill SDHC_READ(sc, SD_CLKC_REG) & ~SD_CLKC_MEM_PWR);
502 1.1 jmcneill
503 1.1 jmcneill SDHC_WRITE(sc, SD_PDMA_REG,
504 1.1 jmcneill __SHIFTIN(7, SD_PDMA_TX_BURST_LEN) |
505 1.1 jmcneill __SHIFTIN(49, SD_PDMA_TXFIFO_THRESHOLD) |
506 1.1 jmcneill __SHIFTIN(15, SD_PDMA_RX_BURST_LEN) |
507 1.1 jmcneill __SHIFTIN(7, SD_PDMA_RXFIFO_THRESHOLD) |
508 1.1 jmcneill SD_PDMA_DMA_URGENT);
509 1.1 jmcneill
510 1.1 jmcneill SDHC_WRITE(sc, SD_MISC_REG,
511 1.1 jmcneill __SHIFTIN(7, SD_MISC_TXSTART_THRESHOLD) |
512 1.1 jmcneill __SHIFTIN(5, SD_MISC_WCRC_ERR_PATTERN) |
513 1.1 jmcneill __SHIFTIN(2, SD_MISC_WCRC_OK_PATTERN));
514 1.1 jmcneill
515 1.1 jmcneill enhc = SDHC_READ(sc, SD_ENHC_REG);
516 1.1 jmcneill enhc &= ~SD_ENHC_RXFIFO_THRESHOLD;
517 1.1 jmcneill enhc |= __SHIFTIN(63, SD_ENHC_RXFIFO_THRESHOLD);
518 1.1 jmcneill enhc &= ~SD_ENHC_DMA_RX_RESP;
519 1.1 jmcneill enhc |= SD_ENHC_DMA_TX_RESP;
520 1.1 jmcneill enhc &= ~SD_ENHC_SDIO_IRQ_PERIOD;
521 1.1 jmcneill enhc |= __SHIFTIN(12, SD_ENHC_SDIO_IRQ_PERIOD);
522 1.1 jmcneill enhc &= ~SD_ENHC_RX_TIMEOUT;
523 1.1 jmcneill enhc |= __SHIFTIN(0xff, SD_ENHC_RX_TIMEOUT);
524 1.1 jmcneill SDHC_WRITE(sc, SD_ENHC_REG, enhc);
525 1.1 jmcneill
526 1.1 jmcneill SDHC_WRITE(sc, SD_ICTL_REG, 0);
527 1.1 jmcneill SDHC_WRITE(sc, SD_ISTA_REG, SD_INT_CLEAR);
528 1.1 jmcneill
529 1.1 jmcneill return 0;
530 1.1 jmcneill }
531 1.1 jmcneill
532 1.1 jmcneill static uint32_t
533 1.1 jmcneill meson_sdhc_host_ocr(sdmmc_chipset_handle_t sch)
534 1.1 jmcneill {
535 1.1 jmcneill return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V |
536 1.1 jmcneill MMC_OCR_HCS | MMC_OCR_S18A;
537 1.1 jmcneill }
538 1.1 jmcneill
539 1.1 jmcneill static int
540 1.1 jmcneill meson_sdhc_host_maxblklen(sdmmc_chipset_handle_t sch)
541 1.1 jmcneill {
542 1.1 jmcneill return 512;
543 1.1 jmcneill }
544 1.1 jmcneill
545 1.1 jmcneill static int
546 1.1 jmcneill meson_sdhc_card_detect(sdmmc_chipset_handle_t sch)
547 1.1 jmcneill {
548 1.1 jmcneill struct meson_sdhc_softc *sc = sch;
549 1.1 jmcneill int val;
550 1.1 jmcneill
551 1.1 jmcneill if (sc->sc_non_removable || sc->sc_broken_cd) {
552 1.1 jmcneill return 1;
553 1.1 jmcneill } else if (sc->sc_gpio_cd != NULL) {
554 1.1 jmcneill val = fdtbus_gpio_read(sc->sc_gpio_cd);
555 1.1 jmcneill if (sc->sc_gpio_cd_inverted)
556 1.1 jmcneill val = !val;
557 1.1 jmcneill return val;
558 1.1 jmcneill } else {
559 1.1 jmcneill return 1;
560 1.1 jmcneill }
561 1.1 jmcneill }
562 1.1 jmcneill
563 1.1 jmcneill static int
564 1.1 jmcneill meson_sdhc_write_protect(sdmmc_chipset_handle_t sch)
565 1.1 jmcneill {
566 1.1 jmcneill struct meson_sdhc_softc *sc = sch;
567 1.1 jmcneill int val;
568 1.1 jmcneill
569 1.1 jmcneill if (sc->sc_gpio_wp != NULL) {
570 1.1 jmcneill val = fdtbus_gpio_read(sc->sc_gpio_wp);
571 1.1 jmcneill if (sc->sc_gpio_wp_inverted)
572 1.1 jmcneill val = !val;
573 1.1 jmcneill return val;
574 1.1 jmcneill }
575 1.1 jmcneill
576 1.1 jmcneill return 0;
577 1.1 jmcneill }
578 1.1 jmcneill
579 1.1 jmcneill static int
580 1.1 jmcneill meson_sdhc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
581 1.1 jmcneill {
582 1.1 jmcneill return 0;
583 1.1 jmcneill }
584 1.1 jmcneill
585 1.1 jmcneill static int
586 1.1 jmcneill meson_sdhc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
587 1.1 jmcneill {
588 1.1 jmcneill struct meson_sdhc_softc *sc = sch;
589 1.1 jmcneill
590 1.1 jmcneill return meson_sdhc_set_clock(sc, freq);
591 1.1 jmcneill }
592 1.1 jmcneill
593 1.1 jmcneill static int
594 1.1 jmcneill meson_sdhc_bus_width(sdmmc_chipset_handle_t sch, int width)
595 1.1 jmcneill {
596 1.1 jmcneill struct meson_sdhc_softc *sc = sch;
597 1.1 jmcneill uint32_t cntl;
598 1.1 jmcneill
599 1.1 jmcneill cntl = SDHC_READ(sc, SD_CNTL_REG);
600 1.1 jmcneill cntl &= ~SD_CNTL_DAT_TYPE;
601 1.1 jmcneill switch (width) {
602 1.1 jmcneill case 1:
603 1.1 jmcneill cntl |= __SHIFTIN(0, SD_CNTL_DAT_TYPE);
604 1.1 jmcneill break;
605 1.1 jmcneill case 4:
606 1.1 jmcneill cntl |= __SHIFTIN(1, SD_CNTL_DAT_TYPE);
607 1.1 jmcneill break;
608 1.1 jmcneill case 8:
609 1.1 jmcneill cntl |= __SHIFTIN(2, SD_CNTL_DAT_TYPE);
610 1.1 jmcneill break;
611 1.1 jmcneill default:
612 1.1 jmcneill return EINVAL;
613 1.1 jmcneill }
614 1.1 jmcneill
615 1.1 jmcneill SDHC_WRITE(sc, SD_CNTL_REG, cntl);
616 1.1 jmcneill
617 1.1 jmcneill return 0;
618 1.1 jmcneill }
619 1.1 jmcneill
620 1.1 jmcneill static int
621 1.1 jmcneill meson_sdhc_bus_rod(sdmmc_chipset_handle_t sch, int on)
622 1.1 jmcneill {
623 1.1 jmcneill return ENOTSUP;
624 1.1 jmcneill }
625 1.1 jmcneill
626 1.1 jmcneill static void
627 1.1 jmcneill meson_sdhc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
628 1.1 jmcneill {
629 1.1 jmcneill struct meson_sdhc_softc *sc = sch;
630 1.1 jmcneill uint32_t cmdval = 0, cntl, srst, pdma, ictl;
631 1.1 jmcneill bool use_bbuf = false;
632 1.1 jmcneill int i;
633 1.1 jmcneill
634 1.1 jmcneill KASSERT(cmd->c_blklen <= 512);
635 1.1 jmcneill
636 1.1 jmcneill mutex_enter(&sc->sc_intr_lock);
637 1.1 jmcneill
638 1.1 jmcneill /* Filter SDIO commands */
639 1.1 jmcneill switch (cmd->c_opcode) {
640 1.1 jmcneill case SD_IO_SEND_OP_COND:
641 1.1 jmcneill case SD_IO_RW_DIRECT:
642 1.1 jmcneill case SD_IO_RW_EXTENDED:
643 1.1 jmcneill cmd->c_error = EINVAL;
644 1.1 jmcneill goto done;
645 1.1 jmcneill }
646 1.1 jmcneill
647 1.1 jmcneill if (cmd->c_opcode == MMC_STOP_TRANSMISSION)
648 1.1 jmcneill cmdval |= SD_SEND_DATA_STOP;
649 1.1 jmcneill if (cmd->c_flags & SCF_RSP_PRESENT)
650 1.1 jmcneill cmdval |= SD_SEND_COMMAND_HAS_RESP;
651 1.1 jmcneill if (cmd->c_flags & SCF_RSP_136) {
652 1.1 jmcneill cmdval |= SD_SEND_RESPONSE_LENGTH;
653 1.1 jmcneill cmdval |= SD_SEND_RESPONSE_NO_CRC;
654 1.1 jmcneill }
655 1.1 jmcneill if ((cmd->c_flags & SCF_RSP_CRC) == 0)
656 1.1 jmcneill cmdval |= SD_SEND_RESPONSE_NO_CRC;
657 1.1 jmcneill
658 1.1 jmcneill SDHC_WRITE(sc, SD_ICTL_REG, 0);
659 1.1 jmcneill SDHC_WRITE(sc, SD_ISTA_REG, SD_INT_CLEAR);
660 1.1 jmcneill sc->sc_intr_ista = 0;
661 1.1 jmcneill
662 1.1 jmcneill ictl = SD_INT_ERROR;
663 1.1 jmcneill
664 1.1 jmcneill cntl = SDHC_READ(sc, SD_CNTL_REG);
665 1.1 jmcneill cntl &= ~SD_CNTL_PACK_LEN;
666 1.1 jmcneill if (cmd->c_datalen > 0) {
667 1.1 jmcneill unsigned int nblks;
668 1.1 jmcneill
669 1.1 jmcneill cmdval |= SD_SEND_COMMAND_HAS_DATA;
670 1.1 jmcneill if (!ISSET(cmd->c_flags, SCF_CMD_READ)) {
671 1.1 jmcneill cmdval |= SD_SEND_DATA_DIRECTION;
672 1.1 jmcneill }
673 1.1 jmcneill
674 1.1 jmcneill nblks = cmd->c_datalen / cmd->c_blklen;
675 1.1 jmcneill if (nblks == 0 || (cmd->c_datalen % cmd->c_blklen) != 0)
676 1.1 jmcneill ++nblks;
677 1.1 jmcneill
678 1.1 jmcneill cntl |= __SHIFTIN(cmd->c_blklen & 0x1ff, SD_CNTL_PACK_LEN);
679 1.1 jmcneill
680 1.1 jmcneill cmdval |= __SHIFTIN(nblks - 1, SD_SEND_TOTAL_PACK);
681 1.1 jmcneill
682 1.1 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
683 1.1 jmcneill ictl |= SD_INT_DATA_COMPLETE;
684 1.1 jmcneill } else {
685 1.1 jmcneill ictl |= SD_INT_DMA_DONE;
686 1.1 jmcneill }
687 1.1 jmcneill } else {
688 1.1 jmcneill ictl |= SD_INT_RESP_COMPLETE;
689 1.1 jmcneill }
690 1.1 jmcneill
691 1.1 jmcneill SDHC_WRITE(sc, SD_ICTL_REG, ictl);
692 1.1 jmcneill
693 1.1 jmcneill SDHC_WRITE(sc, SD_CNTL_REG, cntl);
694 1.1 jmcneill
695 1.1 jmcneill pdma = SDHC_READ(sc, SD_PDMA_REG);
696 1.1 jmcneill if (cmd->c_datalen > 0) {
697 1.1 jmcneill pdma |= SD_PDMA_DMA_MODE;
698 1.1 jmcneill } else {
699 1.1 jmcneill pdma &= ~SD_PDMA_DMA_MODE;
700 1.1 jmcneill }
701 1.1 jmcneill SDHC_WRITE(sc, SD_PDMA_REG, pdma);
702 1.1 jmcneill
703 1.1 jmcneill SDHC_WRITE(sc, SD_ARGU_REG, cmd->c_arg);
704 1.1 jmcneill
705 1.1 jmcneill cmd->c_error = meson_sdhc_wait_idle(sc);
706 1.1 jmcneill if (cmd->c_error) {
707 1.1 jmcneill goto done;
708 1.1 jmcneill }
709 1.1 jmcneill
710 1.1 jmcneill if (cmd->c_datalen > 0) {
711 1.1 jmcneill cmd->c_error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap,
712 1.1 jmcneill sc->sc_bbuf, MAXPHYS, NULL, BUS_DMA_WAITOK);
713 1.1 jmcneill if (cmd->c_error) {
714 1.1 jmcneill device_printf(sc->sc_dev, "bus_dmamap_load failed\n");
715 1.1 jmcneill goto done;
716 1.1 jmcneill }
717 1.1 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
718 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
719 1.1 jmcneill MAXPHYS, BUS_DMASYNC_PREREAD);
720 1.1 jmcneill } else {
721 1.1 jmcneill memcpy(sc->sc_bbuf, cmd->c_data, cmd->c_datalen);
722 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
723 1.1 jmcneill MAXPHYS, BUS_DMASYNC_PREWRITE);
724 1.1 jmcneill }
725 1.1 jmcneill SDHC_WRITE(sc, SD_ADDR_REG, sc->sc_dmamap->dm_segs[0].ds_addr);
726 1.1 jmcneill use_bbuf = true;
727 1.1 jmcneill }
728 1.1 jmcneill
729 1.1 jmcneill cmd->c_resid = cmd->c_datalen;
730 1.1 jmcneill SDHC_WRITE(sc, SD_SEND_REG, cmdval | cmd->c_opcode);
731 1.1 jmcneill
732 1.1 jmcneill if (cmd->c_datalen > 0) {
733 1.1 jmcneill uint32_t wbit = ISSET(cmd->c_flags, SCF_CMD_READ) ?
734 1.1 jmcneill SD_INT_DATA_COMPLETE : SD_INT_DMA_DONE;
735 1.1 jmcneill cmd->c_error = meson_sdhc_wait_ista(sc,
736 1.1 jmcneill SD_INT_ERROR | wbit, hz * 10);
737 1.1 jmcneill if (cmd->c_error == 0 &&
738 1.1 jmcneill (sc->sc_intr_ista & SD_INT_ERROR)) {
739 1.1 jmcneill cmd->c_error = ETIMEDOUT;
740 1.1 jmcneill }
741 1.1 jmcneill if (cmd->c_error) {
742 1.1 jmcneill goto done;
743 1.1 jmcneill }
744 1.1 jmcneill } else {
745 1.1 jmcneill cmd->c_error = meson_sdhc_wait_ista(sc,
746 1.1 jmcneill SD_INT_ERROR | SD_INT_RESP_COMPLETE, hz * 10);
747 1.1 jmcneill if (cmd->c_error == 0 && (sc->sc_intr_ista & SD_INT_ERROR)) {
748 1.1 jmcneill if (sc->sc_intr_ista & SD_INT_TIMEOUT) {
749 1.1 jmcneill cmd->c_error = ETIMEDOUT;
750 1.1 jmcneill } else {
751 1.1 jmcneill cmd->c_error = EIO;
752 1.1 jmcneill }
753 1.1 jmcneill }
754 1.1 jmcneill if (cmd->c_error) {
755 1.1 jmcneill goto done;
756 1.1 jmcneill }
757 1.1 jmcneill }
758 1.1 jmcneill
759 1.1 jmcneill SDHC_WRITE(sc, SD_ISTA_REG, sc->sc_intr_ista);
760 1.1 jmcneill
761 1.1 jmcneill if (cmd->c_flags & SCF_RSP_PRESENT) {
762 1.1 jmcneill pdma = SDHC_READ(sc, SD_PDMA_REG);
763 1.1 jmcneill pdma &= ~SD_PDMA_DMA_MODE;
764 1.1 jmcneill if (cmd->c_flags & SCF_RSP_136) {
765 1.1 jmcneill for (i = 4; i >= 1; i--) {
766 1.1 jmcneill pdma &= ~SD_PDMA_PIO_RDRESP;
767 1.1 jmcneill pdma |= __SHIFTIN(i, SD_PDMA_PIO_RDRESP);
768 1.1 jmcneill SDHC_WRITE(sc, SD_PDMA_REG, pdma);
769 1.1 jmcneill cmd->c_resp[i - 1] = SDHC_READ(sc, SD_ARGU_REG);
770 1.1 jmcneill
771 1.1 jmcneill }
772 1.1 jmcneill if (cmd->c_flags & SCF_RSP_CRC) {
773 1.1 jmcneill cmd->c_resp[0] = (cmd->c_resp[0] >> 8) |
774 1.1 jmcneill (cmd->c_resp[1] << 24);
775 1.1 jmcneill cmd->c_resp[1] = (cmd->c_resp[1] >> 8) |
776 1.1 jmcneill (cmd->c_resp[2] << 24);
777 1.1 jmcneill cmd->c_resp[2] = (cmd->c_resp[2] >> 8) |
778 1.1 jmcneill (cmd->c_resp[3] << 24);
779 1.1 jmcneill cmd->c_resp[3] = (cmd->c_resp[3] >> 8);
780 1.1 jmcneill }
781 1.1 jmcneill } else {
782 1.1 jmcneill pdma &= ~SD_PDMA_PIO_RDRESP;
783 1.1 jmcneill pdma |= __SHIFTIN(0, SD_PDMA_PIO_RDRESP);
784 1.1 jmcneill SDHC_WRITE(sc, SD_PDMA_REG, pdma);
785 1.1 jmcneill cmd->c_resp[0] = SDHC_READ(sc, SD_ARGU_REG);
786 1.1 jmcneill }
787 1.1 jmcneill }
788 1.1 jmcneill
789 1.1 jmcneill done:
790 1.1 jmcneill if (use_bbuf) {
791 1.1 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
792 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
793 1.1 jmcneill MAXPHYS, BUS_DMASYNC_POSTREAD);
794 1.1 jmcneill } else {
795 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
796 1.1 jmcneill MAXPHYS, BUS_DMASYNC_POSTWRITE);
797 1.1 jmcneill }
798 1.1 jmcneill bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamap);
799 1.1 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
800 1.1 jmcneill memcpy(cmd->c_data, sc->sc_bbuf, cmd->c_datalen);
801 1.1 jmcneill }
802 1.1 jmcneill }
803 1.1 jmcneill
804 1.1 jmcneill cmd->c_flags |= SCF_ITSDONE;
805 1.1 jmcneill
806 1.1 jmcneill SDHC_WRITE(sc, SD_ISTA_REG, SD_INT_CLEAR);
807 1.1 jmcneill SDHC_WRITE(sc, SD_ICTL_REG, 0);
808 1.1 jmcneill
809 1.1 jmcneill srst = SDHC_READ(sc, SD_SRST_REG);
810 1.1 jmcneill srst |= (SD_SRST_TX_FIFO | SD_SRST_RX_FIFO);
811 1.1 jmcneill SDHC_WRITE(sc, SD_SRST_REG, srst);
812 1.1 jmcneill
813 1.1 jmcneill mutex_exit(&sc->sc_intr_lock);
814 1.1 jmcneill }
815 1.1 jmcneill
816 1.1 jmcneill static void
817 1.1 jmcneill meson_sdhc_card_enable_intr(sdmmc_chipset_handle_t sch, int enable)
818 1.1 jmcneill {
819 1.1 jmcneill }
820 1.1 jmcneill
821 1.1 jmcneill static void
822 1.1 jmcneill meson_sdhc_card_intr_ack(sdmmc_chipset_handle_t sch)
823 1.1 jmcneill {
824 1.1 jmcneill }
825 1.1 jmcneill
826 1.1 jmcneill static int
827 1.1 jmcneill meson_sdhc_signal_voltage(sdmmc_chipset_handle_t sch, int signal_voltage)
828 1.1 jmcneill {
829 1.1 jmcneill struct meson_sdhc_softc *sc = sch;
830 1.1 jmcneill u_int uvol;
831 1.1 jmcneill int error;
832 1.1 jmcneill
833 1.1 jmcneill if (sc->sc_reg_vqmmc == NULL)
834 1.1 jmcneill return 0;
835 1.1 jmcneill
836 1.1 jmcneill switch (signal_voltage) {
837 1.1 jmcneill case SDMMC_SIGNAL_VOLTAGE_330:
838 1.1 jmcneill uvol = 3300000;
839 1.1 jmcneill break;
840 1.1 jmcneill case SDMMC_SIGNAL_VOLTAGE_180:
841 1.1 jmcneill uvol = 1800000;
842 1.1 jmcneill break;
843 1.1 jmcneill default:
844 1.1 jmcneill return EINVAL;
845 1.1 jmcneill }
846 1.1 jmcneill
847 1.1 jmcneill error = fdtbus_regulator_supports_voltage(sc->sc_reg_vqmmc, uvol, uvol);
848 1.1 jmcneill if (error != 0)
849 1.1 jmcneill return 0;
850 1.1 jmcneill
851 1.1 jmcneill error = fdtbus_regulator_set_voltage(sc->sc_reg_vqmmc, uvol, uvol);
852 1.1 jmcneill if (error != 0)
853 1.1 jmcneill return error;
854 1.1 jmcneill
855 1.1 jmcneill error = fdtbus_regulator_enable(sc->sc_reg_vqmmc);
856 1.1 jmcneill if (error != 0)
857 1.1 jmcneill return error;
858 1.1 jmcneill
859 1.1 jmcneill sc->sc_signal_voltage = signal_voltage;
860 1.1 jmcneill return 0;
861 1.1 jmcneill }
862 1.1 jmcneill
863 1.1 jmcneill static int
864 1.1 jmcneill meson_sdhc_execute_tuning(sdmmc_chipset_handle_t sch, int timing)
865 1.1 jmcneill {
866 1.1 jmcneill static const uint8_t tuning_blk_8bit[] = {
867 1.1 jmcneill 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
868 1.1 jmcneill 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
869 1.1 jmcneill 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
870 1.1 jmcneill 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
871 1.1 jmcneill 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
872 1.1 jmcneill 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
873 1.1 jmcneill 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
874 1.1 jmcneill 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
875 1.1 jmcneill 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
876 1.1 jmcneill 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
877 1.1 jmcneill 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
878 1.1 jmcneill 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
879 1.1 jmcneill 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
880 1.1 jmcneill 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
881 1.1 jmcneill 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
882 1.1 jmcneill 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
883 1.1 jmcneill };
884 1.1 jmcneill static const uint8_t tuning_blk_4bit[] = {
885 1.1 jmcneill 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
886 1.1 jmcneill 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
887 1.1 jmcneill 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
888 1.1 jmcneill 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
889 1.1 jmcneill 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
890 1.1 jmcneill 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
891 1.1 jmcneill 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
892 1.1 jmcneill 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
893 1.1 jmcneill };
894 1.1 jmcneill
895 1.1 jmcneill struct meson_sdhc_softc *sc = sch;
896 1.1 jmcneill struct sdmmc_command cmd;
897 1.1 jmcneill uint8_t data[sizeof(tuning_blk_8bit)];
898 1.1 jmcneill const uint8_t *tblk;
899 1.1 jmcneill size_t tsize;
900 1.1 jmcneill struct window_s {
901 1.1 jmcneill int start;
902 1.1 jmcneill u_int size;
903 1.1 jmcneill } best = { .start = -1, .size = 0 },
904 1.1 jmcneill curr = { .start = -1, .size = 0 },
905 1.1 jmcneill wrap = { .start = 0, .size = 0 };
906 1.1 jmcneill u_int ph, rx_phase, clk_div;
907 1.1 jmcneill int opcode;
908 1.1 jmcneill
909 1.1 jmcneill switch (timing) {
910 1.1 jmcneill case SDMMC_TIMING_MMC_HS200:
911 1.1 jmcneill tblk = tuning_blk_8bit;
912 1.1 jmcneill tsize = sizeof(tuning_blk_8bit);
913 1.1 jmcneill opcode = MMC_SEND_TUNING_BLOCK_HS200;
914 1.1 jmcneill break;
915 1.1 jmcneill case SDMMC_TIMING_UHS_SDR50:
916 1.1 jmcneill case SDMMC_TIMING_UHS_SDR104:
917 1.1 jmcneill tblk = tuning_blk_4bit;
918 1.1 jmcneill tsize = sizeof(tuning_blk_4bit);
919 1.1 jmcneill opcode = MMC_SEND_TUNING_BLOCK;
920 1.1 jmcneill break;
921 1.1 jmcneill default:
922 1.1 jmcneill return EINVAL;
923 1.1 jmcneill }
924 1.1 jmcneill
925 1.1 jmcneill const uint32_t clkc = SDHC_READ(sc, SD_CLKC_REG);
926 1.1 jmcneill clk_div = __SHIFTOUT(clkc, SD_CLKC_CLK_DIV);
927 1.1 jmcneill
928 1.1 jmcneill for (ph = 0; ph <= clk_div; ph++) {
929 1.1 jmcneill SDHC_SET_CLEAR(sc, SD_CLK2_REG,
930 1.1 jmcneill __SHIFTIN(ph, SD_CLK2_RX_CLK_PHASE), SD_CLK2_RX_CLK_PHASE);
931 1.1 jmcneill delay(10);
932 1.1 jmcneill
933 1.1 jmcneill u_int nmatch = 0;
934 1.1 jmcneill #define NUMTRIES 10
935 1.1 jmcneill for (u_int i = 0; i < NUMTRIES; i++) {
936 1.1 jmcneill memset(data, 0, tsize);
937 1.1 jmcneill memset(&cmd, 0, sizeof(cmd));
938 1.1 jmcneill cmd.c_data = data;
939 1.1 jmcneill cmd.c_datalen = cmd.c_blklen = tsize;
940 1.1 jmcneill cmd.c_opcode = opcode;
941 1.1 jmcneill cmd.c_arg = 0;
942 1.1 jmcneill cmd.c_flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1;
943 1.1 jmcneill meson_sdhc_exec_command(sc, &cmd);
944 1.1 jmcneill if (cmd.c_error == 0 && memcmp(data, tblk, tsize) == 0)
945 1.1 jmcneill nmatch++;
946 1.1 jmcneill }
947 1.1 jmcneill if (nmatch == NUMTRIES) { /* good phase value */
948 1.1 jmcneill if (wrap.start == 0)
949 1.1 jmcneill wrap.size++;
950 1.1 jmcneill if (curr.start == -1)
951 1.1 jmcneill curr.start = ph;
952 1.1 jmcneill curr.size++;
953 1.1 jmcneill } else {
954 1.1 jmcneill wrap.start = -1;
955 1.1 jmcneill if (curr.start != -1) { /* end of current window */
956 1.1 jmcneill if (best.start == -1 || best.size < curr.size)
957 1.1 jmcneill best = curr;
958 1.1 jmcneill curr = (struct window_s)
959 1.1 jmcneill { .start = -1, .size = 0 };
960 1.1 jmcneill }
961 1.1 jmcneill }
962 1.1 jmcneill #undef NUMTRIES
963 1.1 jmcneill }
964 1.1 jmcneill
965 1.1 jmcneill if (curr.start != -1) { /* the current window wraps around */
966 1.1 jmcneill curr.size += wrap.size;
967 1.1 jmcneill if (curr.size > ph)
968 1.1 jmcneill curr.size = ph;
969 1.1 jmcneill if (best.start == -1 || best.size < curr.size)
970 1.1 jmcneill best = curr;
971 1.1 jmcneill }
972 1.1 jmcneill
973 1.1 jmcneill if (best.start == -1) { /* no window - use default rx_phase */
974 1.1 jmcneill rx_phase = meson_sdhc_default_rx_phase(sc);
975 1.1 jmcneill } else {
976 1.1 jmcneill rx_phase = best.start + best.size / 2;
977 1.1 jmcneill if (rx_phase >= ph)
978 1.1 jmcneill rx_phase -= ph;
979 1.1 jmcneill }
980 1.1 jmcneill
981 1.1 jmcneill SDHC_SET_CLEAR(sc, SD_CLK2_REG,
982 1.1 jmcneill __SHIFTIN(rx_phase, SD_CLK2_RX_CLK_PHASE), SD_CLK2_RX_CLK_PHASE);
983 1.1 jmcneill
984 1.1 jmcneill return 0;
985 1.1 jmcneill }
986