pl181.c revision 1.4.4.2 1 /* $NetBSD: pl181.c,v 1.4.4.2 2017/12/03 11:37:04 jdolecek Exp $ */
2
3 /*-
4 * Copyright (c) 2015 Jared D. McNeill <jmcneill (at) invisible.ca>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: pl181.c,v 1.4.4.2 2017/12/03 11:37:04 jdolecek Exp $");
31
32 #include <sys/param.h>
33 #include <sys/bus.h>
34 #include <sys/device.h>
35 #include <sys/intr.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38
39 #include <dev/sdmmc/sdmmcvar.h>
40 #include <dev/sdmmc/sdmmcchip.h>
41 #include <dev/sdmmc/sdmmc_ioreg.h>
42
43 #include <dev/ic/pl181reg.h>
44 #include <dev/ic/pl181var.h>
45
46 /*
47 * Data length register is 16 bits for a maximum of 65535 bytes. Round
48 * maximum transfer size down to the nearest sector.
49 */
50 #define PLMMC_MAXXFER rounddown(65535, SDMMC_SECTOR_SIZE)
51
52 static int plmmc_host_reset(sdmmc_chipset_handle_t);
53 static uint32_t plmmc_host_ocr(sdmmc_chipset_handle_t);
54 static int plmmc_host_maxblklen(sdmmc_chipset_handle_t);
55 static int plmmc_card_detect(sdmmc_chipset_handle_t);
56 static int plmmc_write_protect(sdmmc_chipset_handle_t);
57 static int plmmc_bus_power(sdmmc_chipset_handle_t, uint32_t);
58 static int plmmc_bus_clock(sdmmc_chipset_handle_t, int);
59 static int plmmc_bus_width(sdmmc_chipset_handle_t, int);
60 static int plmmc_bus_rod(sdmmc_chipset_handle_t, int);
61 static void plmmc_exec_command(sdmmc_chipset_handle_t,
62 struct sdmmc_command *);
63 static void plmmc_card_enable_intr(sdmmc_chipset_handle_t, int);
64 static void plmmc_card_intr_ack(sdmmc_chipset_handle_t);
65
66 static int plmmc_wait_status(struct plmmc_softc *, uint32_t, int);
67 static int plmmc_pio_wait(struct plmmc_softc *,
68 struct sdmmc_command *);
69 static int plmmc_pio_transfer(struct plmmc_softc *,
70 struct sdmmc_command *, int);
71
72 static struct sdmmc_chip_functions plmmc_chip_functions = {
73 .host_reset = plmmc_host_reset,
74 .host_ocr = plmmc_host_ocr,
75 .host_maxblklen = plmmc_host_maxblklen,
76 .card_detect = plmmc_card_detect,
77 .write_protect = plmmc_write_protect,
78 .bus_power = plmmc_bus_power,
79 .bus_clock = plmmc_bus_clock,
80 .bus_width = plmmc_bus_width,
81 .bus_rod = plmmc_bus_rod,
82 .exec_command = plmmc_exec_command,
83 .card_enable_intr = plmmc_card_enable_intr,
84 .card_intr_ack = plmmc_card_intr_ack,
85 };
86
87 #define MMCI_WRITE(sc, reg, val) \
88 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
89 #define MMCI_READ(sc, reg) \
90 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
91
92 void
93 plmmc_init(struct plmmc_softc *sc)
94 {
95 struct sdmmcbus_attach_args saa;
96
97 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
98 cv_init(&sc->sc_intr_cv, "plmmcirq");
99
100 #ifdef PLMMC_DEBUG
101 device_printf(sc->sc_dev, "PeriphID %#x %#x %#x %#x\n",
102 MMCI_READ(sc, MMCI_PERIPH_ID0_REG),
103 MMCI_READ(sc, MMCI_PERIPH_ID1_REG),
104 MMCI_READ(sc, MMCI_PERIPH_ID2_REG),
105 MMCI_READ(sc, MMCI_PERIPH_ID3_REG));
106 device_printf(sc->sc_dev, "PCellID %#x %#x %#x %#x\n",
107 MMCI_READ(sc, MMCI_PCELL_ID0_REG),
108 MMCI_READ(sc, MMCI_PCELL_ID1_REG),
109 MMCI_READ(sc, MMCI_PCELL_ID2_REG),
110 MMCI_READ(sc, MMCI_PCELL_ID3_REG));
111 #endif
112
113 plmmc_bus_clock(sc, 400);
114 MMCI_WRITE(sc, MMCI_POWER_REG, 0);
115 delay(10000);
116 MMCI_WRITE(sc, MMCI_POWER_REG, MMCI_POWER_CTRL_POWERUP);
117 delay(10000);
118 MMCI_WRITE(sc, MMCI_POWER_REG, MMCI_POWER_CTRL_POWERON);
119 plmmc_host_reset(sc);
120
121 memset(&saa, 0, sizeof(saa));
122 saa.saa_busname = "sdmmc";
123 saa.saa_sct = &plmmc_chip_functions;
124 saa.saa_sch = sc;
125 saa.saa_clkmin = 400;
126 saa.saa_clkmax = sc->sc_max_freq > 0 ?
127 sc->sc_max_freq / 1000 : sc->sc_clock_freq / 1000;
128 saa.saa_caps = SMC_CAPS_4BIT_MODE;
129
130 sc->sc_sdmmc_dev = config_found(sc->sc_dev, &saa, NULL);
131 }
132
133 int
134 plmmc_intr(void *priv)
135 {
136 struct plmmc_softc *sc = priv;
137 uint32_t status;
138
139 mutex_enter(&sc->sc_intr_lock);
140 status = MMCI_READ(sc, MMCI_STATUS_REG);
141 #ifdef PLMMC_DEBUG
142 printf("%s: MMCI_STATUS_REG = %#x\n", __func__, status);
143 #endif
144 if (!status) {
145 mutex_exit(&sc->sc_intr_lock);
146 return 0;
147 }
148
149 sc->sc_intr_status |= status;
150 cv_broadcast(&sc->sc_intr_cv);
151
152 mutex_exit(&sc->sc_intr_lock);
153
154 return 1;
155 }
156
157 static int
158 plmmc_wait_status(struct plmmc_softc *sc, uint32_t mask, int timeout)
159 {
160 int retry, error;
161
162 KASSERT(mutex_owned(&sc->sc_intr_lock));
163
164 if (sc->sc_intr_status & mask)
165 return 0;
166
167 retry = timeout / hz;
168 if (sc->sc_ih == NULL)
169 retry *= 1000;
170
171 while (retry > 0) {
172 if (sc->sc_ih == NULL) {
173 sc->sc_intr_status |= MMCI_READ(sc, MMCI_STATUS_REG);
174 if (sc->sc_intr_status & mask)
175 return 0;
176 delay(10000);
177 } else {
178 error = cv_timedwait(&sc->sc_intr_cv,
179 &sc->sc_intr_lock, hz);
180 if (error && error != EWOULDBLOCK) {
181 device_printf(sc->sc_dev,
182 "cv_timedwait returned %d\n", error);
183 return error;
184 }
185 if (sc->sc_intr_status & mask)
186 return 0;
187 }
188 --retry;
189 }
190
191 device_printf(sc->sc_dev, "%s timeout, MMCI_STATUS_REG = %#x\n",
192 __func__, MMCI_READ(sc, MMCI_STATUS_REG));
193
194 return ETIMEDOUT;
195 }
196
197 static int
198 plmmc_pio_wait(struct plmmc_softc *sc, struct sdmmc_command *cmd)
199 {
200 uint32_t bit = (cmd->c_flags & SCF_CMD_READ) ?
201 MMCI_INT_RX_DATA_AVAIL : MMCI_INT_TX_FIFO_EMPTY;
202
203 MMCI_WRITE(sc, MMCI_CLEAR_REG, bit);
204 const int error = plmmc_wait_status(sc,
205 bit | MMCI_INT_DATA_END | MMCI_INT_DATA_BLOCK_END, hz*2);
206 sc->sc_intr_status &= ~bit;
207
208 return error;
209 }
210
211 static int
212 plmmc_pio_transfer(struct plmmc_softc *sc, struct sdmmc_command *cmd,
213 int xferlen)
214 {
215 uint32_t *datap = (uint32_t *)cmd->c_buf;
216 int i;
217
218 for (i = 0; i < xferlen / 4; i++) {
219 if (plmmc_pio_wait(sc, cmd))
220 return ETIMEDOUT;
221 if (cmd->c_flags & SCF_CMD_READ) {
222 datap[i] = MMCI_READ(sc, MMCI_FIFO_REG);
223 } else {
224 MMCI_WRITE(sc, MMCI_FIFO_REG, datap[i]);
225 }
226 cmd->c_resid -= 4;
227 cmd->c_buf += 4;
228 }
229
230 return 0;
231 }
232
233 static int
234 plmmc_host_reset(sdmmc_chipset_handle_t sch)
235 {
236 struct plmmc_softc *sc = sch;
237
238 MMCI_WRITE(sc, MMCI_MASK0_REG, 0);
239 MMCI_WRITE(sc, MMCI_MASK1_REG, 0);
240 MMCI_WRITE(sc, MMCI_CLEAR_REG, 0xffffffff);
241
242 return 0;
243 }
244
245 static uint32_t
246 plmmc_host_ocr(sdmmc_chipset_handle_t sch)
247 {
248 return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V;
249 }
250
251 static int
252 plmmc_host_maxblklen(sdmmc_chipset_handle_t sch)
253 {
254 return 2048;
255 }
256
257 static int
258 plmmc_card_detect(sdmmc_chipset_handle_t sch)
259 {
260 return 1;
261 }
262
263 static int
264 plmmc_write_protect(sdmmc_chipset_handle_t sch)
265 {
266 return 0;
267 }
268
269 static int
270 plmmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
271 {
272 return 0;
273 }
274
275 static int
276 plmmc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
277 {
278 struct plmmc_softc *sc = sch;
279 u_int pll_freq, clk_div;
280 uint32_t clock;
281
282 clock = MMCI_CLOCK_PWRSAVE;
283 if (freq) {
284 pll_freq = sc->sc_clock_freq / 1000;
285 clk_div = (howmany(pll_freq, freq) >> 1) - 1;
286 clock |= __SHIFTIN(clk_div, MMCI_CLOCK_CLKDIV);
287 clock |= MMCI_CLOCK_ENABLE;
288 }
289 MMCI_WRITE(sc, MMCI_CLOCK_REG, clock);
290
291 return 0;
292 }
293
294 static int
295 plmmc_bus_width(sdmmc_chipset_handle_t sch, int width)
296 {
297 return 0;
298 }
299
300 static int
301 plmmc_bus_rod(sdmmc_chipset_handle_t sch, int on)
302 {
303 struct plmmc_softc *sc = sch;
304 uint32_t power;
305
306
307 power = MMCI_READ(sc, MMCI_POWER_REG);
308 if (on) {
309 power |= MMCI_POWER_ROD;
310 } else {
311 power &= ~MMCI_POWER_ROD;
312 }
313 MMCI_WRITE(sc, MMCI_POWER_REG, power);
314
315 return 0;
316 }
317
318 static void
319 plmmc_do_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
320 {
321 struct plmmc_softc *sc = sch;
322 uint32_t cmdval = MMCI_COMMAND_ENABLE;
323
324 KASSERT(mutex_owned(&sc->sc_intr_lock));
325
326 const int xferlen = min(cmd->c_resid, PLMMC_MAXXFER);
327
328 #ifdef PLMMC_DEBUG
329 device_printf(sc->sc_dev,
330 "opcode %d flags %#x datalen %d resid %d xferlen %d\n",
331 cmd->c_opcode, cmd->c_flags, cmd->c_datalen, cmd->c_resid, xferlen);
332 #endif
333
334 MMCI_WRITE(sc, MMCI_COMMAND_REG, 0);
335 MMCI_WRITE(sc, MMCI_MASK0_REG, 0);
336 MMCI_WRITE(sc, MMCI_CLEAR_REG, 0xffffffff);
337 MMCI_WRITE(sc, MMCI_MASK0_REG,
338 MMCI_INT_CMD_TIMEOUT | MMCI_INT_DATA_TIMEOUT |
339 MMCI_INT_RX_DATA_AVAIL | MMCI_INT_TX_FIFO_EMPTY |
340 MMCI_INT_DATA_END | MMCI_INT_DATA_BLOCK_END |
341 MMCI_INT_CMD_RESP_END | MMCI_INT_CMD_SENT);
342
343 sc->sc_intr_status = 0;
344
345 if (cmd->c_flags & SCF_RSP_PRESENT)
346 cmdval |= MMCI_COMMAND_RESPONSE;
347 if (cmd->c_flags & SCF_RSP_136)
348 cmdval |= MMCI_COMMAND_LONGRSP;
349
350 uint32_t arg = cmd->c_arg;
351
352 if (xferlen > 0) {
353 unsigned int nblks = xferlen / cmd->c_blklen;
354 if (nblks == 0 || (xferlen % cmd->c_blklen) != 0)
355 ++nblks;
356
357 const uint32_t dir = (cmd->c_flags & SCF_CMD_READ) ? 1 : 0;
358 const uint32_t blksize = ffs(cmd->c_blklen) - 1;
359
360 MMCI_WRITE(sc, MMCI_DATA_TIMER_REG, 0xffffffff);
361 MMCI_WRITE(sc, MMCI_DATA_LENGTH_REG, nblks * cmd->c_blklen);
362 MMCI_WRITE(sc, MMCI_DATA_CTRL_REG,
363 __SHIFTIN(dir, MMCI_DATA_CTRL_DIRECTION) |
364 __SHIFTIN(blksize, MMCI_DATA_CTRL_BLOCKSIZE) |
365 MMCI_DATA_CTRL_ENABLE);
366
367 /* Adjust blkno if necessary */
368 u_int blkoff =
369 (cmd->c_datalen - cmd->c_resid) / SDMMC_SECTOR_SIZE;
370 if (!ISSET(cmd->c_flags, SCF_XFER_SDHC))
371 blkoff <<= SDMMC_SECTOR_SIZE_SB;
372 arg += blkoff;
373 }
374
375 MMCI_WRITE(sc, MMCI_ARGUMENT_REG, arg);
376 MMCI_WRITE(sc, MMCI_COMMAND_REG, cmdval | cmd->c_opcode);
377
378 if (xferlen > 0) {
379 cmd->c_error = plmmc_pio_transfer(sc, cmd, xferlen);
380 if (cmd->c_error) {
381 device_printf(sc->sc_dev,
382 "error (%d) waiting for xfer\n", cmd->c_error);
383 goto done;
384 }
385 }
386
387 if ((cmd->c_flags & SCF_RSP_PRESENT) && cmd->c_resid == 0) {
388 cmd->c_error = plmmc_wait_status(sc,
389 MMCI_INT_CMD_RESP_END|MMCI_INT_CMD_TIMEOUT, hz * 2);
390 if (cmd->c_error == 0 &&
391 (sc->sc_intr_status & MMCI_INT_CMD_TIMEOUT)) {
392 cmd->c_error = ETIMEDOUT;
393 }
394 if (cmd->c_error) {
395 #ifdef PLMMC_DEBUG
396 device_printf(sc->sc_dev,
397 "error (%d) waiting for resp\n", cmd->c_error);
398 #endif
399 goto done;
400 }
401
402 if (cmd->c_flags & SCF_RSP_136) {
403 cmd->c_resp[3] = MMCI_READ(sc, MMCI_RESP0_REG);
404 cmd->c_resp[2] = MMCI_READ(sc, MMCI_RESP1_REG);
405 cmd->c_resp[1] = MMCI_READ(sc, MMCI_RESP2_REG);
406 cmd->c_resp[0] = MMCI_READ(sc, MMCI_RESP3_REG);
407 if (cmd->c_flags & SCF_RSP_CRC) {
408 cmd->c_resp[0] = (cmd->c_resp[0] >> 8) |
409 (cmd->c_resp[1] << 24);
410 cmd->c_resp[1] = (cmd->c_resp[1] >> 8) |
411 (cmd->c_resp[2] << 24);
412 cmd->c_resp[2] = (cmd->c_resp[2] >> 8) |
413 (cmd->c_resp[3] << 24);
414 cmd->c_resp[3] = (cmd->c_resp[3] >> 8);
415 }
416 } else {
417 cmd->c_resp[0] = MMCI_READ(sc, MMCI_RESP0_REG);
418 }
419 }
420
421 done:
422 MMCI_WRITE(sc, MMCI_COMMAND_REG, 0);
423 MMCI_WRITE(sc, MMCI_MASK0_REG, 0);
424 MMCI_WRITE(sc, MMCI_CLEAR_REG, 0xffffffff);
425 MMCI_WRITE(sc, MMCI_DATA_CNT_REG, 0);
426
427 #ifdef PLMMC_DEBUG
428 device_printf(sc->sc_dev, "MMCI_STATUS_REG = %#x\n",
429 MMCI_READ(sc, MMCI_STATUS_REG));
430 #endif
431 }
432
433 static void
434 plmmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
435 {
436 struct plmmc_softc *sc = sch;
437
438 #ifdef PLMMC_DEBUG
439 device_printf(sc->sc_dev, "opcode %d flags %#x data %p datalen %d\n",
440 cmd->c_opcode, cmd->c_flags, cmd->c_data, cmd->c_datalen);
441 #endif
442
443 mutex_enter(&sc->sc_intr_lock);
444 cmd->c_resid = cmd->c_datalen;
445 cmd->c_buf = cmd->c_data;
446 do {
447 plmmc_do_command(sch, cmd);
448
449 if (cmd->c_resid > 0 && cmd->c_error == 0) {
450 /*
451 * Multi block transfer and there is still data
452 * remaining. Send a stop cmd between transfers.
453 */
454 struct sdmmc_command stop_cmd;
455 memset(&stop_cmd, 0, sizeof(stop_cmd));
456 stop_cmd.c_opcode = MMC_STOP_TRANSMISSION;
457 stop_cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1B |
458 SCF_RSP_SPI_R1B;
459 plmmc_do_command(sch, &stop_cmd);
460 }
461 } while (cmd->c_resid > 0 && cmd->c_error == 0);
462 cmd->c_flags |= SCF_ITSDONE;
463 mutex_exit(&sc->sc_intr_lock);
464 }
465
466 static void
467 plmmc_card_enable_intr(sdmmc_chipset_handle_t sch, int enable)
468 {
469 }
470
471 static void
472 plmmc_card_intr_ack(sdmmc_chipset_handle_t sch)
473 {
474 }
475