meson_sdhc.c revision 1.2 1 1.2 ryo /* $NetBSD: meson_sdhc.c,v 1.2 2021/01/15 18:42:40 ryo 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.2 ryo __KERNEL_RCSID(0, "$NetBSD: meson_sdhc.c,v 1.2 2021/01/15 18:42:40 ryo 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.1 jmcneill static const char * const compatible[] = {
154 1.1 jmcneill "amlogic,meson8b-sdhc",
155 1.1 jmcneill NULL
156 1.1 jmcneill };
157 1.1 jmcneill
158 1.1 jmcneill static const char * const slot_compatible[] = {
159 1.1 jmcneill "mmc-slot",
160 1.1 jmcneill NULL
161 1.1 jmcneill };
162 1.1 jmcneill
163 1.1 jmcneill static int
164 1.1 jmcneill meson_sdhc_match(device_t parent, cfdata_t cf, void *aux)
165 1.1 jmcneill {
166 1.1 jmcneill struct fdt_attach_args * const faa = aux;
167 1.1 jmcneill
168 1.1 jmcneill return of_match_compatible(faa->faa_phandle, compatible);
169 1.1 jmcneill }
170 1.1 jmcneill
171 1.1 jmcneill static void
172 1.1 jmcneill meson_sdhc_attach(device_t parent, device_t self, void *aux)
173 1.1 jmcneill {
174 1.1 jmcneill struct meson_sdhc_softc * const sc = device_private(self);
175 1.1 jmcneill struct fdt_attach_args * const faa = aux;
176 1.1 jmcneill const int phandle = faa->faa_phandle;
177 1.1 jmcneill char intrstr[128];
178 1.1 jmcneill struct clk *clk_clkin, *clk_core;
179 1.1 jmcneill bus_addr_t addr, port;
180 1.1 jmcneill bus_size_t size;
181 1.1 jmcneill int child;
182 1.1 jmcneill
183 1.1 jmcneill if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
184 1.1 jmcneill aprint_error(": couldn't get registers\n");
185 1.1 jmcneill return;
186 1.1 jmcneill }
187 1.1 jmcneill
188 1.1 jmcneill if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
189 1.1 jmcneill aprint_error(": failed to decode interrupt\n");
190 1.1 jmcneill return;
191 1.1 jmcneill }
192 1.1 jmcneill
193 1.1 jmcneill clk_core = fdtbus_clock_get(phandle, "core");
194 1.1 jmcneill if (clk_core == NULL || clk_enable(clk_core) != 0) {
195 1.1 jmcneill aprint_error(": failed to enable core clock\n");
196 1.1 jmcneill return;
197 1.1 jmcneill }
198 1.1 jmcneill
199 1.1 jmcneill clk_clkin = fdtbus_clock_get(phandle, "clkin");
200 1.1 jmcneill if (clk_clkin == NULL || clk_enable(clk_clkin) != 0) {
201 1.1 jmcneill aprint_error(": failed to get clkin clock\n");
202 1.1 jmcneill return;
203 1.1 jmcneill }
204 1.1 jmcneill
205 1.1 jmcneill sc->sc_dev = self;
206 1.1 jmcneill sc->sc_bst = faa->faa_bst;
207 1.1 jmcneill sc->sc_dmat = faa->faa_dmat;
208 1.1 jmcneill if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
209 1.1 jmcneill aprint_error(": failed to map registers\n");
210 1.1 jmcneill return;
211 1.1 jmcneill }
212 1.1 jmcneill mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
213 1.1 jmcneill cv_init(&sc->sc_intr_cv, "sdhcintr");
214 1.1 jmcneill sc->sc_signal_voltage = SDMMC_SIGNAL_VOLTAGE_330;
215 1.1 jmcneill
216 1.1 jmcneill sc->sc_port = -1;
217 1.1 jmcneill for (child = OF_child(phandle); child; child = OF_peer(child))
218 1.1 jmcneill if (of_match_compatible(child, slot_compatible) > 0) {
219 1.1 jmcneill if (fdtbus_get_reg(child, 0, &port, NULL) == 0) {
220 1.1 jmcneill sc->sc_slot_phandle = child;
221 1.1 jmcneill sc->sc_port = port;
222 1.1 jmcneill }
223 1.1 jmcneill break;
224 1.1 jmcneill }
225 1.1 jmcneill if (sc->sc_port == -1) {
226 1.1 jmcneill aprint_error(": couldn't get mmc slot\n");
227 1.1 jmcneill return;
228 1.1 jmcneill }
229 1.1 jmcneill
230 1.1 jmcneill aprint_naive("\n");
231 1.1 jmcneill aprint_normal(": SDHC controller (port %c)\n", sc->sc_port + 'A');
232 1.1 jmcneill
233 1.1 jmcneill sc->sc_reg_vmmc = fdtbus_regulator_acquire(sc->sc_slot_phandle, "vmmc-supply");
234 1.1 jmcneill sc->sc_reg_vqmmc = fdtbus_regulator_acquire(sc->sc_slot_phandle, "vqmmc-supply");
235 1.1 jmcneill
236 1.1 jmcneill sc->sc_gpio_cd = fdtbus_gpio_acquire(sc->sc_slot_phandle, "cd-gpios",
237 1.1 jmcneill GPIO_PIN_INPUT);
238 1.1 jmcneill sc->sc_gpio_wp = fdtbus_gpio_acquire(sc->sc_slot_phandle, "wp-gpios",
239 1.1 jmcneill GPIO_PIN_INPUT);
240 1.1 jmcneill
241 1.1 jmcneill sc->sc_gpio_cd_inverted = of_hasprop(sc->sc_slot_phandle, "cd-inverted");
242 1.1 jmcneill sc->sc_gpio_wp_inverted = of_hasprop(sc->sc_slot_phandle, "wp-inverted");
243 1.1 jmcneill
244 1.1 jmcneill sc->sc_non_removable = of_hasprop(sc->sc_slot_phandle, "non-removable");
245 1.1 jmcneill sc->sc_broken_cd = of_hasprop(sc->sc_slot_phandle, "broken-cd");
246 1.1 jmcneill
247 1.2 ryo sc->sc_ih = fdtbus_intr_establish_xname(phandle, 0, IPL_BIO, 0,
248 1.2 ryo meson_sdhc_intr, sc, device_xname(self));
249 1.1 jmcneill if (sc->sc_ih == NULL) {
250 1.1 jmcneill aprint_error_dev(self, "couldn't establish interrupt on %s\n",
251 1.1 jmcneill intrstr);
252 1.1 jmcneill return;
253 1.1 jmcneill }
254 1.1 jmcneill aprint_normal_dev(self, "interrupting on %s\n", intrstr);
255 1.1 jmcneill
256 1.1 jmcneill sc->sc_bus_freq = clk_get_rate(clk_clkin);
257 1.1 jmcneill
258 1.1 jmcneill aprint_normal_dev(self, "core %u Hz, clkin %u Hz\n", clk_get_rate(clk_core), clk_get_rate(clk_clkin));
259 1.1 jmcneill
260 1.1 jmcneill meson_sdhc_dmainit(sc);
261 1.1 jmcneill
262 1.1 jmcneill config_interrupts(self, meson_sdhc_attach_i);
263 1.1 jmcneill }
264 1.1 jmcneill
265 1.1 jmcneill static void
266 1.1 jmcneill meson_sdhc_attach_i(device_t self)
267 1.1 jmcneill {
268 1.1 jmcneill struct meson_sdhc_softc *sc = device_private(self);
269 1.1 jmcneill struct sdmmcbus_attach_args saa;
270 1.1 jmcneill u_int pll_freq;
271 1.1 jmcneill
272 1.1 jmcneill pll_freq = sc->sc_bus_freq / 1000;
273 1.1 jmcneill
274 1.1 jmcneill meson_sdhc_host_reset(sc);
275 1.1 jmcneill meson_sdhc_bus_width(sc, 1);
276 1.1 jmcneill
277 1.1 jmcneill memset(&saa, 0, sizeof(saa));
278 1.1 jmcneill saa.saa_busname = "sdmmc";
279 1.1 jmcneill saa.saa_sct = &meson_sdhc_chip_functions;
280 1.1 jmcneill saa.saa_dmat = sc->sc_dmat;
281 1.1 jmcneill saa.saa_sch = sc;
282 1.1 jmcneill saa.saa_clkmin = 400;
283 1.1 jmcneill saa.saa_clkmax = pll_freq;
284 1.1 jmcneill /* Do not advertise DMA capabilities, we handle DMA ourselves */
285 1.1 jmcneill saa.saa_caps = SMC_CAPS_4BIT_MODE|
286 1.1 jmcneill SMC_CAPS_SD_HIGHSPEED|
287 1.1 jmcneill SMC_CAPS_MMC_HIGHSPEED|
288 1.1 jmcneill SMC_CAPS_UHS_SDR50|
289 1.1 jmcneill SMC_CAPS_UHS_SDR104|
290 1.1 jmcneill SMC_CAPS_AUTO_STOP;
291 1.1 jmcneill
292 1.1 jmcneill if (sc->sc_port == SDHC_PORT_C) {
293 1.1 jmcneill saa.saa_caps |= SMC_CAPS_MMC_HS200;
294 1.1 jmcneill saa.saa_caps |= SMC_CAPS_8BIT_MODE;
295 1.1 jmcneill }
296 1.1 jmcneill
297 1.1 jmcneill sc->sc_sdmmc_dev = config_found(self, &saa, NULL);
298 1.1 jmcneill }
299 1.1 jmcneill
300 1.1 jmcneill static int
301 1.1 jmcneill meson_sdhc_intr(void *priv)
302 1.1 jmcneill {
303 1.1 jmcneill struct meson_sdhc_softc *sc = priv;
304 1.1 jmcneill uint32_t ista;
305 1.1 jmcneill
306 1.1 jmcneill mutex_enter(&sc->sc_intr_lock);
307 1.1 jmcneill ista = SDHC_READ(sc, SD_ISTA_REG);
308 1.1 jmcneill
309 1.1 jmcneill if (!ista) {
310 1.1 jmcneill mutex_exit(&sc->sc_intr_lock);
311 1.1 jmcneill return 0;
312 1.1 jmcneill }
313 1.1 jmcneill
314 1.1 jmcneill SDHC_WRITE(sc, SD_ISTA_REG, ista);
315 1.1 jmcneill
316 1.1 jmcneill sc->sc_intr_ista |= ista;
317 1.1 jmcneill cv_broadcast(&sc->sc_intr_cv);
318 1.1 jmcneill
319 1.1 jmcneill mutex_exit(&sc->sc_intr_lock);
320 1.1 jmcneill
321 1.1 jmcneill return 1;
322 1.1 jmcneill }
323 1.1 jmcneill
324 1.1 jmcneill static void
325 1.1 jmcneill meson_sdhc_dmainit(struct meson_sdhc_softc *sc)
326 1.1 jmcneill {
327 1.1 jmcneill int error, rseg;
328 1.1 jmcneill
329 1.1 jmcneill error = bus_dmamem_alloc(sc->sc_dmat, MAXPHYS, PAGE_SIZE, MAXPHYS,
330 1.1 jmcneill sc->sc_segs, 1, &rseg, BUS_DMA_WAITOK);
331 1.1 jmcneill if (error) {
332 1.1 jmcneill device_printf(sc->sc_dev, "bus_dmamem_alloc failed: %d\n", error);
333 1.1 jmcneill return;
334 1.1 jmcneill }
335 1.1 jmcneill KASSERT(rseg == 1);
336 1.1 jmcneill
337 1.1 jmcneill error = bus_dmamem_map(sc->sc_dmat, sc->sc_segs, rseg, MAXPHYS,
338 1.1 jmcneill &sc->sc_bbuf, BUS_DMA_WAITOK);
339 1.1 jmcneill if (error) {
340 1.1 jmcneill device_printf(sc->sc_dev, "bus_dmamem_map failed\n");
341 1.1 jmcneill return;
342 1.1 jmcneill }
343 1.1 jmcneill
344 1.1 jmcneill error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, 1, MAXPHYS, 0,
345 1.1 jmcneill BUS_DMA_WAITOK, &sc->sc_dmamap);
346 1.1 jmcneill if (error) {
347 1.1 jmcneill device_printf(sc->sc_dev, "bus_dmamap_create failed\n");
348 1.1 jmcneill return;
349 1.1 jmcneill }
350 1.1 jmcneill
351 1.1 jmcneill }
352 1.1 jmcneill
353 1.1 jmcneill static int
354 1.1 jmcneill meson_sdhc_default_rx_phase(struct meson_sdhc_softc *sc)
355 1.1 jmcneill {
356 1.1 jmcneill const u_int pll_freq = sc->sc_bus_freq / 1000;
357 1.1 jmcneill const u_int clkc = SDHC_READ(sc, SD_CLKC_REG);
358 1.1 jmcneill const u_int clk_div = __SHIFTOUT(clkc, SD_CLKC_CLK_DIV);
359 1.1 jmcneill const u_int act_freq = pll_freq / clk_div;
360 1.1 jmcneill
361 1.1 jmcneill if (act_freq > 90000) {
362 1.1 jmcneill return 1;
363 1.1 jmcneill } else if (act_freq > 45000) {
364 1.1 jmcneill if (sc->sc_signal_voltage == SDMMC_SIGNAL_VOLTAGE_330) {
365 1.1 jmcneill return 15;
366 1.1 jmcneill } else {
367 1.1 jmcneill return 11;
368 1.1 jmcneill }
369 1.1 jmcneill } else if (act_freq >= 25000) {
370 1.1 jmcneill return 15;
371 1.1 jmcneill } else if (act_freq > 5000) {
372 1.1 jmcneill return 23;
373 1.1 jmcneill } else if (act_freq > 1000) {
374 1.1 jmcneill return 55;
375 1.1 jmcneill } else {
376 1.1 jmcneill return 1061;
377 1.1 jmcneill }
378 1.1 jmcneill }
379 1.1 jmcneill
380 1.1 jmcneill static int
381 1.1 jmcneill meson_sdhc_set_clock(struct meson_sdhc_softc *sc, u_int freq)
382 1.1 jmcneill {
383 1.1 jmcneill uint32_t clkc;
384 1.1 jmcneill uint32_t clk2;
385 1.1 jmcneill u_int pll_freq, clk_div;
386 1.1 jmcneill
387 1.1 jmcneill clkc = SDHC_READ(sc, SD_CLKC_REG);
388 1.1 jmcneill clkc &= ~SD_CLKC_TX_CLK_ENABLE;
389 1.1 jmcneill clkc &= ~SD_CLKC_RX_CLK_ENABLE;
390 1.1 jmcneill clkc &= ~SD_CLKC_SD_CLK_ENABLE;
391 1.1 jmcneill SDHC_WRITE(sc, SD_CLKC_REG, clkc);
392 1.1 jmcneill clkc &= ~SD_CLKC_MOD_CLK_ENABLE;
393 1.1 jmcneill SDHC_WRITE(sc, SD_CLKC_REG, clkc);
394 1.1 jmcneill
395 1.1 jmcneill if (freq == 0)
396 1.1 jmcneill return 0;
397 1.1 jmcneill
398 1.1 jmcneill clkc &= ~SD_CLKC_CLK_DIV;
399 1.1 jmcneill clkc &= ~SD_CLKC_CLK_IN_SEL;
400 1.1 jmcneill
401 1.1 jmcneill clkc |= __SHIFTIN(SD_CLKC_CLK_IN_SEL_FCLK_DIV3,
402 1.1 jmcneill SD_CLKC_CLK_IN_SEL);
403 1.1 jmcneill
404 1.1 jmcneill pll_freq = sc->sc_bus_freq / 1000; /* 2.55GHz */
405 1.1 jmcneill clk_div = howmany(pll_freq, freq);
406 1.1 jmcneill
407 1.1 jmcneill clkc |= __SHIFTIN(clk_div - 1, SD_CLKC_CLK_DIV);
408 1.1 jmcneill
409 1.1 jmcneill SDHC_WRITE(sc, SD_CLKC_REG, clkc);
410 1.1 jmcneill
411 1.1 jmcneill clkc |= SD_CLKC_MOD_CLK_ENABLE;
412 1.1 jmcneill SDHC_WRITE(sc, SD_CLKC_REG, clkc);
413 1.1 jmcneill
414 1.1 jmcneill clkc |= SD_CLKC_TX_CLK_ENABLE;
415 1.1 jmcneill clkc |= SD_CLKC_RX_CLK_ENABLE;
416 1.1 jmcneill clkc |= SD_CLKC_SD_CLK_ENABLE;
417 1.1 jmcneill SDHC_WRITE(sc, SD_CLKC_REG, clkc);
418 1.1 jmcneill
419 1.1 jmcneill clk2 = SDHC_READ(sc, SD_CLK2_REG);
420 1.1 jmcneill clk2 &= ~SD_CLK2_SD_CLK_PHASE;
421 1.1 jmcneill clk2 |= __SHIFTIN(1, SD_CLK2_SD_CLK_PHASE);
422 1.1 jmcneill clk2 &= ~SD_CLK2_RX_CLK_PHASE;
423 1.1 jmcneill clk2 |= __SHIFTIN(meson_sdhc_default_rx_phase(sc),
424 1.1 jmcneill SD_CLK2_RX_CLK_PHASE);
425 1.1 jmcneill SDHC_WRITE(sc, SD_CLK2_REG, clk2);
426 1.1 jmcneill
427 1.1 jmcneill return 0;
428 1.1 jmcneill }
429 1.1 jmcneill
430 1.1 jmcneill static int
431 1.1 jmcneill meson_sdhc_wait_idle(struct meson_sdhc_softc *sc)
432 1.1 jmcneill {
433 1.1 jmcneill int i;
434 1.1 jmcneill
435 1.1 jmcneill for (i = 0; i < 1000000; i++) {
436 1.1 jmcneill const uint32_t stat = SDHC_READ(sc, SD_STAT_REG);
437 1.1 jmcneill const uint32_t esta = SDHC_READ(sc, SD_ESTA_REG);
438 1.1 jmcneill if ((stat & SD_STAT_BUSY) == 0 &&
439 1.1 jmcneill (esta & SD_ESTA_BUSY) == 0)
440 1.1 jmcneill return 0;
441 1.1 jmcneill delay(1);
442 1.1 jmcneill }
443 1.1 jmcneill
444 1.1 jmcneill return EBUSY;
445 1.1 jmcneill }
446 1.1 jmcneill
447 1.1 jmcneill static int
448 1.1 jmcneill meson_sdhc_wait_ista(struct meson_sdhc_softc *sc, uint32_t mask, int timeout)
449 1.1 jmcneill {
450 1.1 jmcneill int retry, error;
451 1.1 jmcneill
452 1.1 jmcneill KASSERT(mutex_owned(&sc->sc_intr_lock));
453 1.1 jmcneill
454 1.1 jmcneill if (sc->sc_intr_ista & mask)
455 1.1 jmcneill return 0;
456 1.1 jmcneill
457 1.1 jmcneill retry = timeout / hz;
458 1.1 jmcneill
459 1.1 jmcneill while (retry > 0) {
460 1.1 jmcneill error = cv_timedwait(&sc->sc_intr_cv, &sc->sc_intr_lock, hz);
461 1.1 jmcneill if (error && error != EWOULDBLOCK)
462 1.1 jmcneill return error;
463 1.1 jmcneill if (sc->sc_intr_ista & mask)
464 1.1 jmcneill return 0;
465 1.1 jmcneill --retry;
466 1.1 jmcneill }
467 1.1 jmcneill
468 1.1 jmcneill return ETIMEDOUT;
469 1.1 jmcneill }
470 1.1 jmcneill
471 1.1 jmcneill static int
472 1.1 jmcneill meson_sdhc_host_reset(sdmmc_chipset_handle_t sch)
473 1.1 jmcneill {
474 1.1 jmcneill struct meson_sdhc_softc *sc = sch;
475 1.1 jmcneill uint32_t enhc;
476 1.1 jmcneill
477 1.1 jmcneill SDHC_WRITE(sc, SD_SRST_REG,
478 1.1 jmcneill SD_SRST_MAIN_CTRL | SD_SRST_TX_FIFO | SD_SRST_RX_FIFO |
479 1.1 jmcneill SD_SRST_DPHY_TX | SD_SRST_DPHY_RX | SD_SRST_DMA_IF);
480 1.1 jmcneill
481 1.1 jmcneill delay(50);
482 1.1 jmcneill
483 1.1 jmcneill SDHC_WRITE(sc, SD_SRST_REG, 0);
484 1.1 jmcneill
485 1.1 jmcneill delay(10);
486 1.1 jmcneill
487 1.1 jmcneill SDHC_WRITE(sc, SD_CNTL_REG,
488 1.1 jmcneill __SHIFTIN(0x7, SD_CNTL_TX_ENDIAN_CTRL) |
489 1.1 jmcneill __SHIFTIN(0x7, SD_CNTL_RX_ENDIAN_CTRL) |
490 1.1 jmcneill __SHIFTIN(0xf, SD_CNTL_RX_PERIOD) |
491 1.1 jmcneill __SHIFTIN(0x7f, SD_CNTL_RX_TIMEOUT));
492 1.1 jmcneill
493 1.1 jmcneill SDHC_WRITE(sc, SD_CLKC_REG,
494 1.1 jmcneill SDHC_READ(sc, SD_CLKC_REG) & ~SD_CLKC_MEM_PWR);
495 1.1 jmcneill
496 1.1 jmcneill SDHC_WRITE(sc, SD_PDMA_REG,
497 1.1 jmcneill __SHIFTIN(7, SD_PDMA_TX_BURST_LEN) |
498 1.1 jmcneill __SHIFTIN(49, SD_PDMA_TXFIFO_THRESHOLD) |
499 1.1 jmcneill __SHIFTIN(15, SD_PDMA_RX_BURST_LEN) |
500 1.1 jmcneill __SHIFTIN(7, SD_PDMA_RXFIFO_THRESHOLD) |
501 1.1 jmcneill SD_PDMA_DMA_URGENT);
502 1.1 jmcneill
503 1.1 jmcneill SDHC_WRITE(sc, SD_MISC_REG,
504 1.1 jmcneill __SHIFTIN(7, SD_MISC_TXSTART_THRESHOLD) |
505 1.1 jmcneill __SHIFTIN(5, SD_MISC_WCRC_ERR_PATTERN) |
506 1.1 jmcneill __SHIFTIN(2, SD_MISC_WCRC_OK_PATTERN));
507 1.1 jmcneill
508 1.1 jmcneill enhc = SDHC_READ(sc, SD_ENHC_REG);
509 1.1 jmcneill enhc &= ~SD_ENHC_RXFIFO_THRESHOLD;
510 1.1 jmcneill enhc |= __SHIFTIN(63, SD_ENHC_RXFIFO_THRESHOLD);
511 1.1 jmcneill enhc &= ~SD_ENHC_DMA_RX_RESP;
512 1.1 jmcneill enhc |= SD_ENHC_DMA_TX_RESP;
513 1.1 jmcneill enhc &= ~SD_ENHC_SDIO_IRQ_PERIOD;
514 1.1 jmcneill enhc |= __SHIFTIN(12, SD_ENHC_SDIO_IRQ_PERIOD);
515 1.1 jmcneill enhc &= ~SD_ENHC_RX_TIMEOUT;
516 1.1 jmcneill enhc |= __SHIFTIN(0xff, SD_ENHC_RX_TIMEOUT);
517 1.1 jmcneill SDHC_WRITE(sc, SD_ENHC_REG, enhc);
518 1.1 jmcneill
519 1.1 jmcneill SDHC_WRITE(sc, SD_ICTL_REG, 0);
520 1.1 jmcneill SDHC_WRITE(sc, SD_ISTA_REG, SD_INT_CLEAR);
521 1.1 jmcneill
522 1.1 jmcneill return 0;
523 1.1 jmcneill }
524 1.1 jmcneill
525 1.1 jmcneill static uint32_t
526 1.1 jmcneill meson_sdhc_host_ocr(sdmmc_chipset_handle_t sch)
527 1.1 jmcneill {
528 1.1 jmcneill return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V |
529 1.1 jmcneill MMC_OCR_HCS | MMC_OCR_S18A;
530 1.1 jmcneill }
531 1.1 jmcneill
532 1.1 jmcneill static int
533 1.1 jmcneill meson_sdhc_host_maxblklen(sdmmc_chipset_handle_t sch)
534 1.1 jmcneill {
535 1.1 jmcneill return 512;
536 1.1 jmcneill }
537 1.1 jmcneill
538 1.1 jmcneill static int
539 1.1 jmcneill meson_sdhc_card_detect(sdmmc_chipset_handle_t sch)
540 1.1 jmcneill {
541 1.1 jmcneill struct meson_sdhc_softc *sc = sch;
542 1.1 jmcneill int val;
543 1.1 jmcneill
544 1.1 jmcneill if (sc->sc_non_removable || sc->sc_broken_cd) {
545 1.1 jmcneill return 1;
546 1.1 jmcneill } else if (sc->sc_gpio_cd != NULL) {
547 1.1 jmcneill val = fdtbus_gpio_read(sc->sc_gpio_cd);
548 1.1 jmcneill if (sc->sc_gpio_cd_inverted)
549 1.1 jmcneill val = !val;
550 1.1 jmcneill return val;
551 1.1 jmcneill } else {
552 1.1 jmcneill return 1;
553 1.1 jmcneill }
554 1.1 jmcneill }
555 1.1 jmcneill
556 1.1 jmcneill static int
557 1.1 jmcneill meson_sdhc_write_protect(sdmmc_chipset_handle_t sch)
558 1.1 jmcneill {
559 1.1 jmcneill struct meson_sdhc_softc *sc = sch;
560 1.1 jmcneill int val;
561 1.1 jmcneill
562 1.1 jmcneill if (sc->sc_gpio_wp != NULL) {
563 1.1 jmcneill val = fdtbus_gpio_read(sc->sc_gpio_wp);
564 1.1 jmcneill if (sc->sc_gpio_wp_inverted)
565 1.1 jmcneill val = !val;
566 1.1 jmcneill return val;
567 1.1 jmcneill }
568 1.1 jmcneill
569 1.1 jmcneill return 0;
570 1.1 jmcneill }
571 1.1 jmcneill
572 1.1 jmcneill static int
573 1.1 jmcneill meson_sdhc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
574 1.1 jmcneill {
575 1.1 jmcneill return 0;
576 1.1 jmcneill }
577 1.1 jmcneill
578 1.1 jmcneill static int
579 1.1 jmcneill meson_sdhc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
580 1.1 jmcneill {
581 1.1 jmcneill struct meson_sdhc_softc *sc = sch;
582 1.1 jmcneill
583 1.1 jmcneill return meson_sdhc_set_clock(sc, freq);
584 1.1 jmcneill }
585 1.1 jmcneill
586 1.1 jmcneill static int
587 1.1 jmcneill meson_sdhc_bus_width(sdmmc_chipset_handle_t sch, int width)
588 1.1 jmcneill {
589 1.1 jmcneill struct meson_sdhc_softc *sc = sch;
590 1.1 jmcneill uint32_t cntl;
591 1.1 jmcneill
592 1.1 jmcneill cntl = SDHC_READ(sc, SD_CNTL_REG);
593 1.1 jmcneill cntl &= ~SD_CNTL_DAT_TYPE;
594 1.1 jmcneill switch (width) {
595 1.1 jmcneill case 1:
596 1.1 jmcneill cntl |= __SHIFTIN(0, SD_CNTL_DAT_TYPE);
597 1.1 jmcneill break;
598 1.1 jmcneill case 4:
599 1.1 jmcneill cntl |= __SHIFTIN(1, SD_CNTL_DAT_TYPE);
600 1.1 jmcneill break;
601 1.1 jmcneill case 8:
602 1.1 jmcneill cntl |= __SHIFTIN(2, SD_CNTL_DAT_TYPE);
603 1.1 jmcneill break;
604 1.1 jmcneill default:
605 1.1 jmcneill return EINVAL;
606 1.1 jmcneill }
607 1.1 jmcneill
608 1.1 jmcneill SDHC_WRITE(sc, SD_CNTL_REG, cntl);
609 1.1 jmcneill
610 1.1 jmcneill return 0;
611 1.1 jmcneill }
612 1.1 jmcneill
613 1.1 jmcneill static int
614 1.1 jmcneill meson_sdhc_bus_rod(sdmmc_chipset_handle_t sch, int on)
615 1.1 jmcneill {
616 1.1 jmcneill return ENOTSUP;
617 1.1 jmcneill }
618 1.1 jmcneill
619 1.1 jmcneill static void
620 1.1 jmcneill meson_sdhc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
621 1.1 jmcneill {
622 1.1 jmcneill struct meson_sdhc_softc *sc = sch;
623 1.1 jmcneill uint32_t cmdval = 0, cntl, srst, pdma, ictl;
624 1.1 jmcneill bool use_bbuf = false;
625 1.1 jmcneill int i;
626 1.1 jmcneill
627 1.1 jmcneill KASSERT(cmd->c_blklen <= 512);
628 1.1 jmcneill
629 1.1 jmcneill mutex_enter(&sc->sc_intr_lock);
630 1.1 jmcneill
631 1.1 jmcneill /* Filter SDIO commands */
632 1.1 jmcneill switch (cmd->c_opcode) {
633 1.1 jmcneill case SD_IO_SEND_OP_COND:
634 1.1 jmcneill case SD_IO_RW_DIRECT:
635 1.1 jmcneill case SD_IO_RW_EXTENDED:
636 1.1 jmcneill cmd->c_error = EINVAL;
637 1.1 jmcneill goto done;
638 1.1 jmcneill }
639 1.1 jmcneill
640 1.1 jmcneill if (cmd->c_opcode == MMC_STOP_TRANSMISSION)
641 1.1 jmcneill cmdval |= SD_SEND_DATA_STOP;
642 1.1 jmcneill if (cmd->c_flags & SCF_RSP_PRESENT)
643 1.1 jmcneill cmdval |= SD_SEND_COMMAND_HAS_RESP;
644 1.1 jmcneill if (cmd->c_flags & SCF_RSP_136) {
645 1.1 jmcneill cmdval |= SD_SEND_RESPONSE_LENGTH;
646 1.1 jmcneill cmdval |= SD_SEND_RESPONSE_NO_CRC;
647 1.1 jmcneill }
648 1.1 jmcneill if ((cmd->c_flags & SCF_RSP_CRC) == 0)
649 1.1 jmcneill cmdval |= SD_SEND_RESPONSE_NO_CRC;
650 1.1 jmcneill
651 1.1 jmcneill SDHC_WRITE(sc, SD_ICTL_REG, 0);
652 1.1 jmcneill SDHC_WRITE(sc, SD_ISTA_REG, SD_INT_CLEAR);
653 1.1 jmcneill sc->sc_intr_ista = 0;
654 1.1 jmcneill
655 1.1 jmcneill ictl = SD_INT_ERROR;
656 1.1 jmcneill
657 1.1 jmcneill cntl = SDHC_READ(sc, SD_CNTL_REG);
658 1.1 jmcneill cntl &= ~SD_CNTL_PACK_LEN;
659 1.1 jmcneill if (cmd->c_datalen > 0) {
660 1.1 jmcneill unsigned int nblks;
661 1.1 jmcneill
662 1.1 jmcneill cmdval |= SD_SEND_COMMAND_HAS_DATA;
663 1.1 jmcneill if (!ISSET(cmd->c_flags, SCF_CMD_READ)) {
664 1.1 jmcneill cmdval |= SD_SEND_DATA_DIRECTION;
665 1.1 jmcneill }
666 1.1 jmcneill
667 1.1 jmcneill nblks = cmd->c_datalen / cmd->c_blklen;
668 1.1 jmcneill if (nblks == 0 || (cmd->c_datalen % cmd->c_blklen) != 0)
669 1.1 jmcneill ++nblks;
670 1.1 jmcneill
671 1.1 jmcneill cntl |= __SHIFTIN(cmd->c_blklen & 0x1ff, SD_CNTL_PACK_LEN);
672 1.1 jmcneill
673 1.1 jmcneill cmdval |= __SHIFTIN(nblks - 1, SD_SEND_TOTAL_PACK);
674 1.1 jmcneill
675 1.1 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
676 1.1 jmcneill ictl |= SD_INT_DATA_COMPLETE;
677 1.1 jmcneill } else {
678 1.1 jmcneill ictl |= SD_INT_DMA_DONE;
679 1.1 jmcneill }
680 1.1 jmcneill } else {
681 1.1 jmcneill ictl |= SD_INT_RESP_COMPLETE;
682 1.1 jmcneill }
683 1.1 jmcneill
684 1.1 jmcneill SDHC_WRITE(sc, SD_ICTL_REG, ictl);
685 1.1 jmcneill
686 1.1 jmcneill SDHC_WRITE(sc, SD_CNTL_REG, cntl);
687 1.1 jmcneill
688 1.1 jmcneill pdma = SDHC_READ(sc, SD_PDMA_REG);
689 1.1 jmcneill if (cmd->c_datalen > 0) {
690 1.1 jmcneill pdma |= SD_PDMA_DMA_MODE;
691 1.1 jmcneill } else {
692 1.1 jmcneill pdma &= ~SD_PDMA_DMA_MODE;
693 1.1 jmcneill }
694 1.1 jmcneill SDHC_WRITE(sc, SD_PDMA_REG, pdma);
695 1.1 jmcneill
696 1.1 jmcneill SDHC_WRITE(sc, SD_ARGU_REG, cmd->c_arg);
697 1.1 jmcneill
698 1.1 jmcneill cmd->c_error = meson_sdhc_wait_idle(sc);
699 1.1 jmcneill if (cmd->c_error) {
700 1.1 jmcneill goto done;
701 1.1 jmcneill }
702 1.1 jmcneill
703 1.1 jmcneill if (cmd->c_datalen > 0) {
704 1.1 jmcneill cmd->c_error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap,
705 1.1 jmcneill sc->sc_bbuf, MAXPHYS, NULL, BUS_DMA_WAITOK);
706 1.1 jmcneill if (cmd->c_error) {
707 1.1 jmcneill device_printf(sc->sc_dev, "bus_dmamap_load failed\n");
708 1.1 jmcneill goto done;
709 1.1 jmcneill }
710 1.1 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
711 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
712 1.1 jmcneill MAXPHYS, BUS_DMASYNC_PREREAD);
713 1.1 jmcneill } else {
714 1.1 jmcneill memcpy(sc->sc_bbuf, cmd->c_data, cmd->c_datalen);
715 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
716 1.1 jmcneill MAXPHYS, BUS_DMASYNC_PREWRITE);
717 1.1 jmcneill }
718 1.1 jmcneill SDHC_WRITE(sc, SD_ADDR_REG, sc->sc_dmamap->dm_segs[0].ds_addr);
719 1.1 jmcneill use_bbuf = true;
720 1.1 jmcneill }
721 1.1 jmcneill
722 1.1 jmcneill cmd->c_resid = cmd->c_datalen;
723 1.1 jmcneill SDHC_WRITE(sc, SD_SEND_REG, cmdval | cmd->c_opcode);
724 1.1 jmcneill
725 1.1 jmcneill if (cmd->c_datalen > 0) {
726 1.1 jmcneill uint32_t wbit = ISSET(cmd->c_flags, SCF_CMD_READ) ?
727 1.1 jmcneill SD_INT_DATA_COMPLETE : SD_INT_DMA_DONE;
728 1.1 jmcneill cmd->c_error = meson_sdhc_wait_ista(sc,
729 1.1 jmcneill SD_INT_ERROR | wbit, hz * 10);
730 1.1 jmcneill if (cmd->c_error == 0 &&
731 1.1 jmcneill (sc->sc_intr_ista & SD_INT_ERROR)) {
732 1.1 jmcneill cmd->c_error = ETIMEDOUT;
733 1.1 jmcneill }
734 1.1 jmcneill if (cmd->c_error) {
735 1.1 jmcneill goto done;
736 1.1 jmcneill }
737 1.1 jmcneill } else {
738 1.1 jmcneill cmd->c_error = meson_sdhc_wait_ista(sc,
739 1.1 jmcneill SD_INT_ERROR | SD_INT_RESP_COMPLETE, hz * 10);
740 1.1 jmcneill if (cmd->c_error == 0 && (sc->sc_intr_ista & SD_INT_ERROR)) {
741 1.1 jmcneill if (sc->sc_intr_ista & SD_INT_TIMEOUT) {
742 1.1 jmcneill cmd->c_error = ETIMEDOUT;
743 1.1 jmcneill } else {
744 1.1 jmcneill cmd->c_error = EIO;
745 1.1 jmcneill }
746 1.1 jmcneill }
747 1.1 jmcneill if (cmd->c_error) {
748 1.1 jmcneill goto done;
749 1.1 jmcneill }
750 1.1 jmcneill }
751 1.1 jmcneill
752 1.1 jmcneill SDHC_WRITE(sc, SD_ISTA_REG, sc->sc_intr_ista);
753 1.1 jmcneill
754 1.1 jmcneill if (cmd->c_flags & SCF_RSP_PRESENT) {
755 1.1 jmcneill pdma = SDHC_READ(sc, SD_PDMA_REG);
756 1.1 jmcneill pdma &= ~SD_PDMA_DMA_MODE;
757 1.1 jmcneill if (cmd->c_flags & SCF_RSP_136) {
758 1.1 jmcneill for (i = 4; i >= 1; i--) {
759 1.1 jmcneill pdma &= ~SD_PDMA_PIO_RDRESP;
760 1.1 jmcneill pdma |= __SHIFTIN(i, SD_PDMA_PIO_RDRESP);
761 1.1 jmcneill SDHC_WRITE(sc, SD_PDMA_REG, pdma);
762 1.1 jmcneill cmd->c_resp[i - 1] = SDHC_READ(sc, SD_ARGU_REG);
763 1.1 jmcneill
764 1.1 jmcneill }
765 1.1 jmcneill if (cmd->c_flags & SCF_RSP_CRC) {
766 1.1 jmcneill cmd->c_resp[0] = (cmd->c_resp[0] >> 8) |
767 1.1 jmcneill (cmd->c_resp[1] << 24);
768 1.1 jmcneill cmd->c_resp[1] = (cmd->c_resp[1] >> 8) |
769 1.1 jmcneill (cmd->c_resp[2] << 24);
770 1.1 jmcneill cmd->c_resp[2] = (cmd->c_resp[2] >> 8) |
771 1.1 jmcneill (cmd->c_resp[3] << 24);
772 1.1 jmcneill cmd->c_resp[3] = (cmd->c_resp[3] >> 8);
773 1.1 jmcneill }
774 1.1 jmcneill } else {
775 1.1 jmcneill pdma &= ~SD_PDMA_PIO_RDRESP;
776 1.1 jmcneill pdma |= __SHIFTIN(0, SD_PDMA_PIO_RDRESP);
777 1.1 jmcneill SDHC_WRITE(sc, SD_PDMA_REG, pdma);
778 1.1 jmcneill cmd->c_resp[0] = SDHC_READ(sc, SD_ARGU_REG);
779 1.1 jmcneill }
780 1.1 jmcneill }
781 1.1 jmcneill
782 1.1 jmcneill done:
783 1.1 jmcneill if (use_bbuf) {
784 1.1 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
785 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
786 1.1 jmcneill MAXPHYS, BUS_DMASYNC_POSTREAD);
787 1.1 jmcneill } else {
788 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
789 1.1 jmcneill MAXPHYS, BUS_DMASYNC_POSTWRITE);
790 1.1 jmcneill }
791 1.1 jmcneill bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamap);
792 1.1 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
793 1.1 jmcneill memcpy(cmd->c_data, sc->sc_bbuf, cmd->c_datalen);
794 1.1 jmcneill }
795 1.1 jmcneill }
796 1.1 jmcneill
797 1.1 jmcneill cmd->c_flags |= SCF_ITSDONE;
798 1.1 jmcneill
799 1.1 jmcneill SDHC_WRITE(sc, SD_ISTA_REG, SD_INT_CLEAR);
800 1.1 jmcneill SDHC_WRITE(sc, SD_ICTL_REG, 0);
801 1.1 jmcneill
802 1.1 jmcneill srst = SDHC_READ(sc, SD_SRST_REG);
803 1.1 jmcneill srst |= (SD_SRST_TX_FIFO | SD_SRST_RX_FIFO);
804 1.1 jmcneill SDHC_WRITE(sc, SD_SRST_REG, srst);
805 1.1 jmcneill
806 1.1 jmcneill mutex_exit(&sc->sc_intr_lock);
807 1.1 jmcneill }
808 1.1 jmcneill
809 1.1 jmcneill static void
810 1.1 jmcneill meson_sdhc_card_enable_intr(sdmmc_chipset_handle_t sch, int enable)
811 1.1 jmcneill {
812 1.1 jmcneill }
813 1.1 jmcneill
814 1.1 jmcneill static void
815 1.1 jmcneill meson_sdhc_card_intr_ack(sdmmc_chipset_handle_t sch)
816 1.1 jmcneill {
817 1.1 jmcneill }
818 1.1 jmcneill
819 1.1 jmcneill static int
820 1.1 jmcneill meson_sdhc_signal_voltage(sdmmc_chipset_handle_t sch, int signal_voltage)
821 1.1 jmcneill {
822 1.1 jmcneill struct meson_sdhc_softc *sc = sch;
823 1.1 jmcneill u_int uvol;
824 1.1 jmcneill int error;
825 1.1 jmcneill
826 1.1 jmcneill if (sc->sc_reg_vqmmc == NULL)
827 1.1 jmcneill return 0;
828 1.1 jmcneill
829 1.1 jmcneill switch (signal_voltage) {
830 1.1 jmcneill case SDMMC_SIGNAL_VOLTAGE_330:
831 1.1 jmcneill uvol = 3300000;
832 1.1 jmcneill break;
833 1.1 jmcneill case SDMMC_SIGNAL_VOLTAGE_180:
834 1.1 jmcneill uvol = 1800000;
835 1.1 jmcneill break;
836 1.1 jmcneill default:
837 1.1 jmcneill return EINVAL;
838 1.1 jmcneill }
839 1.1 jmcneill
840 1.1 jmcneill error = fdtbus_regulator_supports_voltage(sc->sc_reg_vqmmc, uvol, uvol);
841 1.1 jmcneill if (error != 0)
842 1.1 jmcneill return 0;
843 1.1 jmcneill
844 1.1 jmcneill error = fdtbus_regulator_set_voltage(sc->sc_reg_vqmmc, uvol, uvol);
845 1.1 jmcneill if (error != 0)
846 1.1 jmcneill return error;
847 1.1 jmcneill
848 1.1 jmcneill error = fdtbus_regulator_enable(sc->sc_reg_vqmmc);
849 1.1 jmcneill if (error != 0)
850 1.1 jmcneill return error;
851 1.1 jmcneill
852 1.1 jmcneill sc->sc_signal_voltage = signal_voltage;
853 1.1 jmcneill return 0;
854 1.1 jmcneill }
855 1.1 jmcneill
856 1.1 jmcneill static int
857 1.1 jmcneill meson_sdhc_execute_tuning(sdmmc_chipset_handle_t sch, int timing)
858 1.1 jmcneill {
859 1.1 jmcneill static const uint8_t tuning_blk_8bit[] = {
860 1.1 jmcneill 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
861 1.1 jmcneill 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
862 1.1 jmcneill 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
863 1.1 jmcneill 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
864 1.1 jmcneill 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
865 1.1 jmcneill 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
866 1.1 jmcneill 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
867 1.1 jmcneill 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
868 1.1 jmcneill 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
869 1.1 jmcneill 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
870 1.1 jmcneill 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
871 1.1 jmcneill 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
872 1.1 jmcneill 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
873 1.1 jmcneill 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
874 1.1 jmcneill 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
875 1.1 jmcneill 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
876 1.1 jmcneill };
877 1.1 jmcneill static const uint8_t tuning_blk_4bit[] = {
878 1.1 jmcneill 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
879 1.1 jmcneill 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
880 1.1 jmcneill 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
881 1.1 jmcneill 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
882 1.1 jmcneill 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
883 1.1 jmcneill 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
884 1.1 jmcneill 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
885 1.1 jmcneill 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
886 1.1 jmcneill };
887 1.1 jmcneill
888 1.1 jmcneill struct meson_sdhc_softc *sc = sch;
889 1.1 jmcneill struct sdmmc_command cmd;
890 1.1 jmcneill uint8_t data[sizeof(tuning_blk_8bit)];
891 1.1 jmcneill const uint8_t *tblk;
892 1.1 jmcneill size_t tsize;
893 1.1 jmcneill struct window_s {
894 1.1 jmcneill int start;
895 1.1 jmcneill u_int size;
896 1.1 jmcneill } best = { .start = -1, .size = 0 },
897 1.1 jmcneill curr = { .start = -1, .size = 0 },
898 1.1 jmcneill wrap = { .start = 0, .size = 0 };
899 1.1 jmcneill u_int ph, rx_phase, clk_div;
900 1.1 jmcneill int opcode;
901 1.1 jmcneill
902 1.1 jmcneill switch (timing) {
903 1.1 jmcneill case SDMMC_TIMING_MMC_HS200:
904 1.1 jmcneill tblk = tuning_blk_8bit;
905 1.1 jmcneill tsize = sizeof(tuning_blk_8bit);
906 1.1 jmcneill opcode = MMC_SEND_TUNING_BLOCK_HS200;
907 1.1 jmcneill break;
908 1.1 jmcneill case SDMMC_TIMING_UHS_SDR50:
909 1.1 jmcneill case SDMMC_TIMING_UHS_SDR104:
910 1.1 jmcneill tblk = tuning_blk_4bit;
911 1.1 jmcneill tsize = sizeof(tuning_blk_4bit);
912 1.1 jmcneill opcode = MMC_SEND_TUNING_BLOCK;
913 1.1 jmcneill break;
914 1.1 jmcneill default:
915 1.1 jmcneill return EINVAL;
916 1.1 jmcneill }
917 1.1 jmcneill
918 1.1 jmcneill const uint32_t clkc = SDHC_READ(sc, SD_CLKC_REG);
919 1.1 jmcneill clk_div = __SHIFTOUT(clkc, SD_CLKC_CLK_DIV);
920 1.1 jmcneill
921 1.1 jmcneill for (ph = 0; ph <= clk_div; ph++) {
922 1.1 jmcneill SDHC_SET_CLEAR(sc, SD_CLK2_REG,
923 1.1 jmcneill __SHIFTIN(ph, SD_CLK2_RX_CLK_PHASE), SD_CLK2_RX_CLK_PHASE);
924 1.1 jmcneill delay(10);
925 1.1 jmcneill
926 1.1 jmcneill u_int nmatch = 0;
927 1.1 jmcneill #define NUMTRIES 10
928 1.1 jmcneill for (u_int i = 0; i < NUMTRIES; i++) {
929 1.1 jmcneill memset(data, 0, tsize);
930 1.1 jmcneill memset(&cmd, 0, sizeof(cmd));
931 1.1 jmcneill cmd.c_data = data;
932 1.1 jmcneill cmd.c_datalen = cmd.c_blklen = tsize;
933 1.1 jmcneill cmd.c_opcode = opcode;
934 1.1 jmcneill cmd.c_arg = 0;
935 1.1 jmcneill cmd.c_flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1;
936 1.1 jmcneill meson_sdhc_exec_command(sc, &cmd);
937 1.1 jmcneill if (cmd.c_error == 0 && memcmp(data, tblk, tsize) == 0)
938 1.1 jmcneill nmatch++;
939 1.1 jmcneill }
940 1.1 jmcneill if (nmatch == NUMTRIES) { /* good phase value */
941 1.1 jmcneill if (wrap.start == 0)
942 1.1 jmcneill wrap.size++;
943 1.1 jmcneill if (curr.start == -1)
944 1.1 jmcneill curr.start = ph;
945 1.1 jmcneill curr.size++;
946 1.1 jmcneill } else {
947 1.1 jmcneill wrap.start = -1;
948 1.1 jmcneill if (curr.start != -1) { /* end of current window */
949 1.1 jmcneill if (best.start == -1 || best.size < curr.size)
950 1.1 jmcneill best = curr;
951 1.1 jmcneill curr = (struct window_s)
952 1.1 jmcneill { .start = -1, .size = 0 };
953 1.1 jmcneill }
954 1.1 jmcneill }
955 1.1 jmcneill #undef NUMTRIES
956 1.1 jmcneill }
957 1.1 jmcneill
958 1.1 jmcneill if (curr.start != -1) { /* the current window wraps around */
959 1.1 jmcneill curr.size += wrap.size;
960 1.1 jmcneill if (curr.size > ph)
961 1.1 jmcneill curr.size = ph;
962 1.1 jmcneill if (best.start == -1 || best.size < curr.size)
963 1.1 jmcneill best = curr;
964 1.1 jmcneill }
965 1.1 jmcneill
966 1.1 jmcneill if (best.start == -1) { /* no window - use default rx_phase */
967 1.1 jmcneill rx_phase = meson_sdhc_default_rx_phase(sc);
968 1.1 jmcneill } else {
969 1.1 jmcneill rx_phase = best.start + best.size / 2;
970 1.1 jmcneill if (rx_phase >= ph)
971 1.1 jmcneill rx_phase -= ph;
972 1.1 jmcneill }
973 1.1 jmcneill
974 1.1 jmcneill SDHC_SET_CLEAR(sc, SD_CLK2_REG,
975 1.1 jmcneill __SHIFTIN(rx_phase, SD_CLK2_RX_CLK_PHASE), SD_CLK2_RX_CLK_PHASE);
976 1.1 jmcneill
977 1.1 jmcneill return 0;
978 1.1 jmcneill }
979