pl181.c revision 1.3 1 /* $NetBSD: pl181.c,v 1.3 2017/06/02 11:01:15 jmcneill 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.3 2017/06/02 11:01:15 jmcneill 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 static int plmmc_host_reset(sdmmc_chipset_handle_t);
47 static uint32_t plmmc_host_ocr(sdmmc_chipset_handle_t);
48 static int plmmc_host_maxblklen(sdmmc_chipset_handle_t);
49 static int plmmc_card_detect(sdmmc_chipset_handle_t);
50 static int plmmc_write_protect(sdmmc_chipset_handle_t);
51 static int plmmc_bus_power(sdmmc_chipset_handle_t, uint32_t);
52 static int plmmc_bus_clock(sdmmc_chipset_handle_t, int);
53 static int plmmc_bus_width(sdmmc_chipset_handle_t, int);
54 static int plmmc_bus_rod(sdmmc_chipset_handle_t, int);
55 static void plmmc_exec_command(sdmmc_chipset_handle_t,
56 struct sdmmc_command *);
57 static void plmmc_card_enable_intr(sdmmc_chipset_handle_t, int);
58 static void plmmc_card_intr_ack(sdmmc_chipset_handle_t);
59
60 static int plmmc_wait_status(struct plmmc_softc *, uint32_t, int);
61 static int plmmc_pio_wait(struct plmmc_softc *,
62 struct sdmmc_command *);
63 static int plmmc_pio_transfer(struct plmmc_softc *,
64 struct sdmmc_command *);
65
66 static struct sdmmc_chip_functions plmmc_chip_functions = {
67 .host_reset = plmmc_host_reset,
68 .host_ocr = plmmc_host_ocr,
69 .host_maxblklen = plmmc_host_maxblklen,
70 .card_detect = plmmc_card_detect,
71 .write_protect = plmmc_write_protect,
72 .bus_power = plmmc_bus_power,
73 .bus_clock = plmmc_bus_clock,
74 .bus_width = plmmc_bus_width,
75 .bus_rod = plmmc_bus_rod,
76 .exec_command = plmmc_exec_command,
77 .card_enable_intr = plmmc_card_enable_intr,
78 .card_intr_ack = plmmc_card_intr_ack,
79 };
80
81 #define MMCI_WRITE(sc, reg, val) \
82 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
83 #define MMCI_READ(sc, reg) \
84 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
85
86 void
87 plmmc_init(struct plmmc_softc *sc)
88 {
89 struct sdmmcbus_attach_args saa;
90
91 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
92 cv_init(&sc->sc_intr_cv, "plmmcirq");
93
94 #ifdef PLMMC_DEBUG
95 device_printf(sc->sc_dev, "PeriphID %#x %#x %#x %#x\n",
96 MMCI_READ(sc, MMCI_PERIPH_ID0_REG),
97 MMCI_READ(sc, MMCI_PERIPH_ID1_REG),
98 MMCI_READ(sc, MMCI_PERIPH_ID2_REG),
99 MMCI_READ(sc, MMCI_PERIPH_ID3_REG));
100 device_printf(sc->sc_dev, "PCellID %#x %#x %#x %#x\n",
101 MMCI_READ(sc, MMCI_PCELL_ID0_REG),
102 MMCI_READ(sc, MMCI_PCELL_ID1_REG),
103 MMCI_READ(sc, MMCI_PCELL_ID2_REG),
104 MMCI_READ(sc, MMCI_PCELL_ID3_REG));
105 #endif
106
107 plmmc_bus_clock(sc, 400);
108 MMCI_WRITE(sc, MMCI_POWER_REG, 0);
109 delay(10000);
110 MMCI_WRITE(sc, MMCI_POWER_REG, MMCI_POWER_CTRL_POWERUP);
111 delay(10000);
112 MMCI_WRITE(sc, MMCI_POWER_REG, MMCI_POWER_CTRL_POWERON);
113 plmmc_host_reset(sc);
114
115 memset(&saa, 0, sizeof(saa));
116 saa.saa_busname = "sdmmc";
117 saa.saa_sct = &plmmc_chip_functions;
118 saa.saa_sch = sc;
119 saa.saa_clkmin = 400;
120 saa.saa_clkmax = sc->sc_max_freq > 0 ?
121 sc->sc_max_freq / 1000 : sc->sc_clock_freq / 1000;
122 saa.saa_caps = SMC_CAPS_4BIT_MODE | SMC_CAPS_SINGLE_ONLY;
123
124 sc->sc_sdmmc_dev = config_found(sc->sc_dev, &saa, NULL);
125 }
126
127 int
128 plmmc_intr(void *priv)
129 {
130 struct plmmc_softc *sc = priv;
131 uint32_t status;
132
133 mutex_enter(&sc->sc_intr_lock);
134 status = MMCI_READ(sc, MMCI_STATUS_REG);
135 #ifdef PLMMC_DEBUG
136 printf("%s: MMCI_STATUS_REG = %#x\n", __func__, status);
137 #endif
138 if (!status) {
139 mutex_exit(&sc->sc_intr_lock);
140 return 0;
141 }
142
143 sc->sc_intr_status |= status;
144 cv_broadcast(&sc->sc_intr_cv);
145
146 mutex_exit(&sc->sc_intr_lock);
147
148 return 1;
149 }
150
151 static int
152 plmmc_wait_status(struct plmmc_softc *sc, uint32_t mask, int timeout)
153 {
154 int retry, error;
155
156 KASSERT(mutex_owned(&sc->sc_intr_lock));
157
158 if (sc->sc_intr_status & mask)
159 return 0;
160
161 retry = timeout / hz;
162 if (sc->sc_ih == NULL)
163 retry *= 1000;
164
165 while (retry > 0) {
166 if (sc->sc_ih == NULL) {
167 sc->sc_intr_status |= MMCI_READ(sc, MMCI_STATUS_REG);
168 if (sc->sc_intr_status & mask)
169 return 0;
170 delay(10000);
171 } else {
172 error = cv_timedwait(&sc->sc_intr_cv,
173 &sc->sc_intr_lock, hz);
174 if (error && error != EWOULDBLOCK) {
175 device_printf(sc->sc_dev,
176 "cv_timedwait returned %d\n", error);
177 return error;
178 }
179 if (sc->sc_intr_status & mask)
180 return 0;
181 }
182 --retry;
183 }
184
185 device_printf(sc->sc_dev, "%s timeout, MMCI_STATUS_REG = %#x\n",
186 __func__, MMCI_READ(sc, MMCI_STATUS_REG));
187
188 return ETIMEDOUT;
189 }
190
191 static int
192 plmmc_pio_wait(struct plmmc_softc *sc, struct sdmmc_command *cmd)
193 {
194 uint32_t bit = (cmd->c_flags & SCF_CMD_READ) ?
195 MMCI_INT_RX_DATA_AVAIL : MMCI_INT_TX_FIFO_EMPTY;
196
197 MMCI_WRITE(sc, MMCI_CLEAR_REG, bit);
198 const int error = plmmc_wait_status(sc,
199 bit | MMCI_INT_DATA_END | MMCI_INT_DATA_BLOCK_END, hz*2);
200 sc->sc_intr_status &= ~bit;
201
202 return error;
203 }
204
205 static int
206 plmmc_pio_transfer(struct plmmc_softc *sc, struct sdmmc_command *cmd)
207 {
208 uint32_t *datap = (uint32_t *)cmd->c_data;
209 int i;
210
211 cmd->c_resid = cmd->c_datalen;
212 for (i = 0; i < (cmd->c_datalen >> 2); i++) {
213 if (plmmc_pio_wait(sc, cmd))
214 return ETIMEDOUT;
215 if (cmd->c_flags & SCF_CMD_READ) {
216 datap[i] = MMCI_READ(sc, MMCI_FIFO_REG);
217 } else {
218 MMCI_WRITE(sc, MMCI_FIFO_REG, datap[i]);
219 }
220 cmd->c_resid -= 4;
221 }
222
223 return 0;
224 }
225
226 static int
227 plmmc_host_reset(sdmmc_chipset_handle_t sch)
228 {
229 struct plmmc_softc *sc = sch;
230
231 MMCI_WRITE(sc, MMCI_MASK0_REG, 0);
232 MMCI_WRITE(sc, MMCI_MASK1_REG, 0);
233 MMCI_WRITE(sc, MMCI_CLEAR_REG, 0xffffffff);
234
235 return 0;
236 }
237
238 static uint32_t
239 plmmc_host_ocr(sdmmc_chipset_handle_t sch)
240 {
241 return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V;
242 }
243
244 static int
245 plmmc_host_maxblklen(sdmmc_chipset_handle_t sch)
246 {
247 return 2048;
248 }
249
250 static int
251 plmmc_card_detect(sdmmc_chipset_handle_t sch)
252 {
253 return 1;
254 }
255
256 static int
257 plmmc_write_protect(sdmmc_chipset_handle_t sch)
258 {
259 return 0;
260 }
261
262 static int
263 plmmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
264 {
265 return 0;
266 }
267
268 static int
269 plmmc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
270 {
271 struct plmmc_softc *sc = sch;
272 u_int pll_freq, clk_div;
273 uint32_t clock;
274
275 clock = MMCI_CLOCK_PWRSAVE;
276 if (freq) {
277 pll_freq = sc->sc_clock_freq / 1000;
278 clk_div = (howmany(pll_freq, freq) >> 1) - 1;
279 clock |= __SHIFTIN(clk_div, MMCI_CLOCK_CLKDIV);
280 clock |= MMCI_CLOCK_ENABLE;
281 }
282 MMCI_WRITE(sc, MMCI_CLOCK_REG, clock);
283
284 return 0;
285 }
286
287 static int
288 plmmc_bus_width(sdmmc_chipset_handle_t sch, int width)
289 {
290 return 0;
291 }
292
293 static int
294 plmmc_bus_rod(sdmmc_chipset_handle_t sch, int on)
295 {
296 struct plmmc_softc *sc = sch;
297 uint32_t power;
298
299
300 power = MMCI_READ(sc, MMCI_POWER_REG);
301 if (on) {
302 power |= MMCI_POWER_ROD;
303 } else {
304 power &= ~MMCI_POWER_ROD;
305 }
306 MMCI_WRITE(sc, MMCI_POWER_REG, power);
307
308 return 0;
309 }
310
311 static void
312 plmmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
313 {
314 struct plmmc_softc *sc = sch;
315 uint32_t cmdval = MMCI_COMMAND_ENABLE;
316
317 #ifdef PLMMC_DEBUG
318 device_printf(sc->sc_dev, "opcode %d flags %#x datalen %d\n",
319 cmd->c_opcode, cmd->c_flags, cmd->c_datalen);
320 #endif
321
322 mutex_enter(&sc->sc_intr_lock);
323
324 MMCI_WRITE(sc, MMCI_COMMAND_REG, 0);
325 MMCI_WRITE(sc, MMCI_MASK0_REG, 0);
326 MMCI_WRITE(sc, MMCI_CLEAR_REG, 0xffffffff);
327 MMCI_WRITE(sc, MMCI_MASK0_REG,
328 MMCI_INT_CMD_TIMEOUT | MMCI_INT_DATA_TIMEOUT |
329 MMCI_INT_RX_DATA_AVAIL | MMCI_INT_TX_FIFO_EMPTY |
330 MMCI_INT_DATA_END | MMCI_INT_DATA_BLOCK_END |
331 MMCI_INT_CMD_RESP_END | MMCI_INT_CMD_SENT);
332
333 sc->sc_intr_status = 0;
334
335 if (cmd->c_flags & SCF_RSP_PRESENT)
336 cmdval |= MMCI_COMMAND_RESPONSE;
337 if (cmd->c_flags & SCF_RSP_136)
338 cmdval |= MMCI_COMMAND_LONGRSP;
339
340 if (cmd->c_datalen > 0) {
341 unsigned int nblks = cmd->c_datalen / cmd->c_blklen;
342 if (nblks == 0 || (cmd->c_datalen % cmd->c_blklen) != 0)
343 ++nblks;
344
345 const uint32_t dir = (cmd->c_flags & SCF_CMD_READ) ? 1 : 0;
346 const uint32_t blksize = ffs(cmd->c_blklen) - 1;
347
348 MMCI_WRITE(sc, MMCI_DATA_TIMER_REG, 0xffffffff);
349 MMCI_WRITE(sc, MMCI_DATA_LENGTH_REG, nblks * cmd->c_blklen);
350 MMCI_WRITE(sc, MMCI_DATA_CTRL_REG,
351 __SHIFTIN(dir, MMCI_DATA_CTRL_DIRECTION) |
352 __SHIFTIN(blksize, MMCI_DATA_CTRL_BLOCKSIZE) |
353 MMCI_DATA_CTRL_ENABLE);
354 }
355
356 MMCI_WRITE(sc, MMCI_ARGUMENT_REG, cmd->c_arg);
357 MMCI_WRITE(sc, MMCI_COMMAND_REG, cmdval | cmd->c_opcode);
358
359 if (cmd->c_datalen > 0) {
360 cmd->c_error = plmmc_pio_transfer(sc, cmd);
361 if (cmd->c_error) {
362 device_printf(sc->sc_dev,
363 "error (%d) waiting for xfer\n", cmd->c_error);
364 goto done;
365 }
366 }
367
368 if (cmd->c_flags & SCF_RSP_PRESENT) {
369 cmd->c_error = plmmc_wait_status(sc,
370 MMCI_INT_CMD_RESP_END|MMCI_INT_CMD_TIMEOUT, hz * 2);
371 if (cmd->c_error == 0 &&
372 (sc->sc_intr_status & MMCI_INT_CMD_TIMEOUT)) {
373 cmd->c_error = ETIMEDOUT;
374 }
375 if (cmd->c_error) {
376 #ifdef PLMMC_DEBUG
377 device_printf(sc->sc_dev,
378 "error (%d) waiting for resp\n", cmd->c_error);
379 #endif
380 goto done;
381 }
382
383 if (cmd->c_flags & SCF_RSP_136) {
384 cmd->c_resp[3] = MMCI_READ(sc, MMCI_RESP0_REG);
385 cmd->c_resp[2] = MMCI_READ(sc, MMCI_RESP1_REG);
386 cmd->c_resp[1] = MMCI_READ(sc, MMCI_RESP2_REG);
387 cmd->c_resp[0] = MMCI_READ(sc, MMCI_RESP3_REG);
388 if (cmd->c_flags & SCF_RSP_CRC) {
389 cmd->c_resp[0] = (cmd->c_resp[0] >> 8) |
390 (cmd->c_resp[1] << 24);
391 cmd->c_resp[1] = (cmd->c_resp[1] >> 8) |
392 (cmd->c_resp[2] << 24);
393 cmd->c_resp[2] = (cmd->c_resp[2] >> 8) |
394 (cmd->c_resp[3] << 24);
395 cmd->c_resp[3] = (cmd->c_resp[3] >> 8);
396 }
397 } else {
398 cmd->c_resp[0] = MMCI_READ(sc, MMCI_RESP0_REG);
399 }
400 }
401
402 done:
403 cmd->c_flags |= SCF_ITSDONE;
404 MMCI_WRITE(sc, MMCI_COMMAND_REG, 0);
405 MMCI_WRITE(sc, MMCI_MASK0_REG, 0);
406 MMCI_WRITE(sc, MMCI_CLEAR_REG, 0xffffffff);
407 MMCI_WRITE(sc, MMCI_DATA_CNT_REG, 0);
408
409 #ifdef PLMMC_DEBUG
410 device_printf(sc->sc_dev, "MMCI_STATUS_REG = %#x\n",
411 MMCI_READ(sc, MMCI_STATUS_REG));
412 #endif
413 mutex_exit(&sc->sc_intr_lock);
414 }
415
416 static void
417 plmmc_card_enable_intr(sdmmc_chipset_handle_t sch, int enable)
418 {
419 }
420
421 static void
422 plmmc_card_intr_ack(sdmmc_chipset_handle_t sch)
423 {
424 }
425