sunxi_nand.c revision 1.1 1 /* $NetBSD: sunxi_nand.c,v 1.1 2017/11/10 00:09:23 jmcneill Exp $ */
2
3 /*-
4 * Copyright (c) 2017 Jared 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: sunxi_nand.c,v 1.1 2017/11/10 00:09:23 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
38 #include <dev/fdt/fdtvar.h>
39
40 #include <dev/nand/nand.h>
41 #include <dev/nand/onfi.h>
42
43 #define NDFC_CTL 0x00
44 #define NDFC_CTL_CE_SEL __BITS(27,24)
45 #define NDFC_CTL_PAGE_SIZE __BITS(11,8)
46 #define NDFC_CTL_RB_SEL __BITS(4,3)
47 #define NDFC_CTL_BUS_WIDTH __BIT(2)
48 #define NDFC_CTL_RESET __BIT(1)
49 #define NDFC_CTL_EN __BIT(0)
50 #define NDFC_ST 0x04
51 #define NDFC_ST_RB_STATE(n) __BIT(8 + (n))
52 #define NDFC_ST_CMD_FIFO_STATUS __BIT(3)
53 #define NDFC_ST_CMD_INT_FLAG __BIT(1)
54 #define NDFC_INT 0x08
55 #define NDFC_TIMING_CTL 0x0c
56 #define NDFC_TIMING_CFG 0x10
57 #define NDFC_ADDR_LOW 0x14
58 #define NDFC_ADDR_HIGH 0x18
59 #define NDFC_BLOCK_NUM 0x1c
60 #define NDFC_CNT 0x20
61 #define NDFC_CNT_DATA_CNT __BITS(9,0)
62 #define NDFC_CMD 0x24
63 #define NDFC_CMD_DATA_METHOD __BIT(26)
64 #define NDFC_CMD_SEND_FIRST_CMD __BIT(22)
65 #define NDFC_CMD_DATA_TRANS __BIT(21)
66 #define NDFC_CMD_ACCESS_DIR __BIT(20)
67 #define NDFC_CMD_SEND_ADR __BIT(19)
68 #define NDFC_CMD_ADR_NUM __BITS(18,16)
69 #define NDFC_RCMD_SET 0x28
70 #define NDFC_WCMD_SET 0x2c
71 #define NDFC_IO_DATA 0x30
72 #define NDFC_ECC_CTL 0x34
73 #define NDFC_ECC_ST 0x38
74 #define NDFC_EFR 0x3c
75 #define NDFC_ERR_CNT0 0x40
76 #define NDFC_ERR_CNT1 0x44
77 #define NDFC_USER_DATA(n) (0x50 + 4 * (n))
78 #define NDFC_EFNAND_STA 0x90
79 #define NDFC_SPARE_AREA 0xa0
80 #define NDFC_PAT_ID 0xa4
81 #define NDFC_RDATA_STA_CTL 0xa8
82 #define NDFC_RDATA_STA_0 0xac
83 #define NDFC_RDATA_STA_1 0xb0
84 #define NDFC_MDMA_ADDR 0xc0
85 #define NDFC_MDMA_CNT 0xc4
86 #define NDFC_RAM0_BASE 0x400
87 #define NDFC_RAM1_BASE 0x800
88
89 #define NDFC_RAM_SIZE 1024
90
91 static const char * compatible[] = {
92 "allwinner,sun4i-a10-nand",
93 NULL
94 };
95
96 struct sunxi_nand_softc;
97
98 enum sunxi_nand_eccmode {
99 ECC_MODE_UNKNOWN,
100 ECC_MODE_HW,
101 ECC_MODE_HW_SYNDROME,
102 ECC_MODE_SOFT,
103 ECC_MODE_SOFT_BCH,
104 ECC_MODE_NONE
105 };
106
107 struct sunxi_nand_softc;
108
109 struct sunxi_nand_chip {
110 struct sunxi_nand_softc *chip_sc;
111 int chip_phandle;
112 device_t chip_dev;
113
114 u_int chip_cs;
115 enum sunxi_nand_eccmode chip_eccmode;
116 u_int chip_rb;
117 struct fdtbus_gpio_pin *chip_rb_pin;
118
119 struct nand_interface chip_nand;
120
121 bool chip_addr_pending;
122 u_int chip_addr_count;
123 uint32_t chip_addr[2];
124 };
125
126 struct sunxi_nand_softc {
127 device_t sc_dev;
128 int sc_phandle;
129 bus_space_tag_t sc_bst;
130 bus_space_handle_t sc_bsh;
131
132 struct clk *sc_clk_mod;
133 struct clk *sc_clk_ahb;
134 struct fdtbus_reset *sc_rst_ahb;
135
136 struct sunxi_nand_chip sc_chip;
137 };
138
139 #define NAND_READ(sc, reg) \
140 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
141 #define NAND_WRITE(sc, reg, val) \
142 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
143
144 static int
145 sunxi_nand_rb_state(struct sunxi_nand_softc *sc, struct sunxi_nand_chip *chip)
146 {
147 if (chip->chip_rb_pin != NULL)
148 return fdtbus_gpio_read(chip->chip_rb_pin);
149
150 const uint32_t status = NAND_READ(sc, NDFC_ST);
151 return __SHIFTOUT(status, NDFC_ST_RB_STATE(chip->chip_rb));
152 }
153
154 static int
155 sunxi_nand_wait_status(struct sunxi_nand_softc *sc, uint32_t mask, uint32_t val)
156 {
157 uint32_t status;
158 int retry;
159
160 for (retry = 1000000; retry > 0; retry--) {
161 status = NAND_READ(sc, NDFC_ST);
162 if ((status & mask) == val)
163 break;
164 delay(1);
165 }
166 if (retry == 0) {
167 #ifdef SUNXI_NAND_DEBUG
168 device_printf(sc->sc_dev,
169 "device timeout; status=%x mask=%x val=%x\n",
170 status, mask, val);
171 #endif
172 return ETIMEDOUT;
173 }
174
175 if (mask == NDFC_ST_CMD_INT_FLAG)
176 NAND_WRITE(sc, NDFC_ST, NDFC_ST_CMD_INT_FLAG);
177
178 return 0;
179 }
180
181 static void
182 sunxi_nand_send_address(struct sunxi_nand_softc *sc,
183 struct sunxi_nand_chip *chip)
184 {
185 if (chip->chip_addr_count == 0)
186 return;
187
188 /* Wait for space in the command FIFO */
189 sunxi_nand_wait_status(sc, NDFC_ST_CMD_FIFO_STATUS, 0);
190
191 NAND_WRITE(sc, NDFC_ADDR_LOW, chip->chip_addr[0]);
192 NAND_WRITE(sc, NDFC_ADDR_HIGH, chip->chip_addr[1]);
193 NAND_WRITE(sc, NDFC_CMD,
194 NDFC_CMD_SEND_ADR |
195 __SHIFTIN(chip->chip_addr_count - 1, NDFC_CMD_ADR_NUM));
196
197 /* Wait for the command to finish */
198 sunxi_nand_wait_status(sc, NDFC_ST_CMD_INT_FLAG, NDFC_ST_CMD_INT_FLAG);
199
200 chip->chip_addr[0] = 0;
201 chip->chip_addr[1] = 0;
202 chip->chip_addr_count = 0;
203 }
204
205 static int
206 sunxi_nand_read_buf_n(device_t dev, void *data, size_t len, int n)
207 {
208 struct sunxi_nand_softc * const sc = device_private(dev);
209 struct sunxi_nand_chip * const chip = &sc->sc_chip;
210 uint8_t *xfer_buf = data;
211 size_t resid = len;
212 int error;
213
214 KASSERT(n == 1 || n == 2);
215 KASSERT(len % n == 0);
216
217 sunxi_nand_send_address(sc, chip);
218
219 while (resid > 0) {
220 const size_t xfer = min(resid, NDFC_RAM_SIZE);
221
222 /* Wait for space in the command FIFO */
223 error = sunxi_nand_wait_status(sc, NDFC_ST_CMD_FIFO_STATUS, 0);
224 if (error != 0)
225 return error;
226
227 /* Start the transfer. */
228 NAND_WRITE(sc, NDFC_CNT, xfer);
229 NAND_WRITE(sc, NDFC_CMD,
230 NDFC_CMD_DATA_TRANS | NDFC_CMD_DATA_METHOD);
231
232 /* Wait for the command to finish */
233 error = sunxi_nand_wait_status(sc, NDFC_ST_CMD_INT_FLAG,
234 NDFC_ST_CMD_INT_FLAG);
235 if (error != 0)
236 return error;
237
238 /* Transfer data from FIFO RAM to buffer */
239 const int count = xfer / n;
240 if (n == 1) {
241 bus_space_read_region_1(sc->sc_bst, sc->sc_bsh,
242 NDFC_RAM0_BASE, (uint8_t *)xfer_buf, count);
243 } else if (n == 2) {
244 bus_space_read_region_2(sc->sc_bst, sc->sc_bsh,
245 NDFC_RAM0_BASE, (uint16_t *)xfer_buf, count);
246 }
247
248 resid -= xfer;
249 xfer_buf += xfer;
250 }
251
252 return 0;
253 }
254
255 static int
256 sunxi_nand_write_buf_n(device_t dev, const void *data, size_t len, int n)
257 {
258 struct sunxi_nand_softc * const sc = device_private(dev);
259 struct sunxi_nand_chip * const chip = &sc->sc_chip;
260 const uint8_t *xfer_buf = data;
261 size_t resid = len;
262 int error;
263
264 KASSERT(n == 1 || n == 2);
265 KASSERT(len % n == 0);
266
267 sunxi_nand_send_address(sc, chip);
268
269 while (resid > 0) {
270 const size_t xfer = min(resid, NDFC_RAM_SIZE);
271
272 /* Wait for space in the command FIFO */
273 error = sunxi_nand_wait_status(sc, NDFC_ST_CMD_FIFO_STATUS, 0);
274 if (error != 0)
275 return error;
276
277 /* Transfer data from buffer to FIFO RAM */
278 const int count = xfer / n;
279 if (n == 1) {
280 bus_space_write_region_1(sc->sc_bst, sc->sc_bsh,
281 NDFC_RAM0_BASE, (const uint8_t *)xfer_buf, count);
282 } else if (n == 2) {
283 bus_space_write_region_2(sc->sc_bst, sc->sc_bsh,
284 NDFC_RAM0_BASE, (const uint16_t *)xfer_buf, count);
285 }
286
287 /* Start the transfer. */
288 NAND_WRITE(sc, NDFC_CNT, xfer);
289 NAND_WRITE(sc, NDFC_CMD,
290 NDFC_CMD_DATA_TRANS | NDFC_CMD_DATA_METHOD |
291 NDFC_CMD_ACCESS_DIR);
292
293 /* Wait for the command to finish */
294 error = sunxi_nand_wait_status(sc, NDFC_ST_CMD_INT_FLAG,
295 NDFC_ST_CMD_INT_FLAG);
296 if (error != 0)
297 return error;
298
299 resid -= xfer;
300 xfer_buf += xfer;
301 }
302
303 return 0;
304 }
305
306 /*
307 * NAND interface
308 */
309
310 static void
311 sunxi_nand_select(device_t dev, bool enable)
312 {
313 struct sunxi_nand_softc * const sc = device_private(dev);
314 struct sunxi_nand_chip * const chip = &sc->sc_chip;
315 struct nand_softc * const nand_sc = device_private(chip->chip_dev);
316 struct nand_chip * const nc = nand_sc ? &nand_sc->sc_chip : NULL;
317 uint32_t ctl;
318
319 ctl = NAND_READ(sc, NDFC_CTL);
320 if (enable) {
321 ctl &= ~NDFC_CTL_CE_SEL;
322 ctl |= __SHIFTIN(chip->chip_cs, NDFC_CTL_CE_SEL);
323 ctl &= ~NDFC_CTL_RB_SEL;
324 ctl |= __SHIFTIN(chip->chip_rb, NDFC_CTL_RB_SEL);
325 ctl &= ~NDFC_CTL_PAGE_SIZE;
326 ctl &= ~NDFC_CTL_BUS_WIDTH;
327 ctl |= NDFC_CTL_EN;
328
329 if (nc) {
330 ctl |= __SHIFTIN(__builtin_ffs(nc->nc_page_size) - 11,
331 NDFC_CTL_PAGE_SIZE);
332 if (ISSET(nc->nc_flags, NC_BUSWIDTH_16))
333 ctl |= NDFC_CTL_BUS_WIDTH;
334
335 NAND_WRITE(sc, NDFC_SPARE_AREA, nc->nc_page_size);
336 }
337 } else {
338 ctl &= ~NDFC_CTL_EN;
339 }
340 NAND_WRITE(sc, NDFC_CTL, ctl);
341 }
342
343 static void
344 sunxi_nand_command(device_t dev, uint8_t command)
345 {
346 struct sunxi_nand_softc * const sc = device_private(dev);
347 struct sunxi_nand_chip * const chip = &sc->sc_chip;
348
349 sunxi_nand_send_address(sc, chip);
350
351 /* Wait for space in the command FIFO */
352 sunxi_nand_wait_status(sc, NDFC_ST_CMD_FIFO_STATUS, 0);
353
354 NAND_WRITE(sc, NDFC_CMD, NDFC_CMD_SEND_FIRST_CMD | command);
355
356 /* Wait for the command to finish */
357 sunxi_nand_wait_status(sc, NDFC_ST_CMD_INT_FLAG, NDFC_ST_CMD_INT_FLAG);
358 }
359
360 static void
361 sunxi_nand_address(device_t dev, uint8_t address)
362 {
363 struct sunxi_nand_softc * const sc = device_private(dev);
364 struct sunxi_nand_chip * const chip = &sc->sc_chip;
365 const u_int index = chip->chip_addr_count / 4;
366 const u_int shift = (chip->chip_addr_count & 3) * 8;
367
368 KASSERT(index < 2);
369
370 chip->chip_addr[index] |= ((uint32_t)address << shift);
371 chip->chip_addr_count++;
372 }
373
374 static void
375 sunxi_nand_busy(device_t dev)
376 {
377 struct sunxi_nand_softc * const sc = device_private(dev);
378 struct sunxi_nand_chip * const chip = &sc->sc_chip;
379
380 while (!sunxi_nand_rb_state(sc, chip))
381 delay(1);
382 }
383
384 static void
385 sunxi_nand_read_1(device_t dev, uint8_t *data)
386 {
387 sunxi_nand_read_buf_n(dev, data, 1, 1);
388 }
389
390 static void
391 sunxi_nand_read_2(device_t dev, uint16_t *data)
392 {
393 sunxi_nand_read_buf_n(dev, data, 2, 2);
394 }
395
396 static void
397 sunxi_nand_read_buf_1(device_t dev, void *data, size_t len)
398 {
399 sunxi_nand_read_buf_n(dev, data, len, 1);
400 }
401
402 static void
403 sunxi_nand_read_buf_2(device_t dev, void *data, size_t len)
404 {
405 sunxi_nand_read_buf_n(dev, data, len, 2);
406 }
407
408 static void
409 sunxi_nand_write_1(device_t dev, uint8_t data)
410 {
411 sunxi_nand_write_buf_n(dev, &data, 1, 1);
412 }
413
414 static void
415 sunxi_nand_write_2(device_t dev, uint16_t data)
416 {
417 sunxi_nand_write_buf_n(dev, &data, 2, 2);
418 }
419
420 static void
421 sunxi_nand_write_buf_1(device_t dev, const void *data, size_t len)
422 {
423 sunxi_nand_write_buf_n(dev, data, len, 1);
424 }
425
426 static void
427 sunxi_nand_write_buf_2(device_t dev, const void *data, size_t len)
428 {
429 sunxi_nand_write_buf_n(dev, data, len, 2);
430 }
431
432 static void
433 sunxi_nand_attach_chip(struct sunxi_nand_softc *sc,
434 struct sunxi_nand_chip *chip, int phandle)
435 {
436 struct nand_interface *nand = &chip->chip_nand;
437 const char *ecc_mode;
438
439 chip->chip_sc = sc;
440 chip->chip_phandle = phandle;
441
442 if (of_getprop_uint32(phandle, "reg", &chip->chip_cs) != 0) {
443 aprint_error_dev(sc->sc_dev,
444 "missing 'reg' property on chip node\n");
445 return;
446 }
447
448 if (of_getprop_uint32(phandle, "allwinner,rb", &chip->chip_rb) != 0) {
449 aprint_error_dev(sc->sc_dev,
450 "chip #%u: missing 'allwinner,rb' property\n",
451 chip->chip_cs);
452 return;
453 }
454
455 ecc_mode = fdtbus_get_string(phandle, "nand-ecc-mode");
456 if (ecc_mode == NULL)
457 ecc_mode = "none";
458
459 if (strcmp(ecc_mode, "none") == 0)
460 chip->chip_eccmode = ECC_MODE_NONE;
461 else if (strcmp(ecc_mode, "hw") == 0)
462 chip->chip_eccmode = ECC_MODE_HW;
463 else if (strcmp(ecc_mode, "hw_syndrome") == 0)
464 chip->chip_eccmode = ECC_MODE_HW_SYNDROME;
465 else if (strcmp(ecc_mode, "soft") == 0)
466 chip->chip_eccmode = ECC_MODE_SOFT;
467 else if (strcmp(ecc_mode, "soft_bch") == 0)
468 chip->chip_eccmode = ECC_MODE_SOFT_BCH;
469 else
470 chip->chip_eccmode = ECC_MODE_UNKNOWN;
471
472 /* Only HW mode is supported for now */
473 switch (chip->chip_eccmode) {
474 case ECC_MODE_HW:
475 break;
476 default:
477 return;
478 }
479
480 aprint_normal_dev(sc->sc_dev, "chip #%u: RB %u, ECC mode '%s'\n",
481 chip->chip_cs, chip->chip_rb, ecc_mode);
482
483 nand_init_interface(nand);
484 nand->select = sunxi_nand_select;
485 nand->command = sunxi_nand_command;
486 nand->address = sunxi_nand_address;
487 nand->read_buf_1 = sunxi_nand_read_buf_1;
488 nand->read_buf_2 = sunxi_nand_read_buf_2;
489 nand->read_1 = sunxi_nand_read_1;
490 nand->read_2 = sunxi_nand_read_2;
491 nand->write_buf_1 = sunxi_nand_write_buf_1;
492 nand->write_buf_2 = sunxi_nand_write_buf_2;
493 nand->write_1 = sunxi_nand_write_1;
494 nand->write_2 = sunxi_nand_write_2;
495 nand->busy = sunxi_nand_busy;
496
497 #if notyet
498 switch (chip->chip_eccmode) {
499 case ECC_MODE_HW:
500 nand->ecc_compute = sunxi_nand_ecc_compute;
501 nand->ecc_correct = sunxi_nand_ecc_correct;
502 nand->ecc_prepare = sunxi_nand_ecc_prepare;
503 nand->ecc.necc_code_size = 3;
504 nand->ecc.necc_block_size = 512;
505 nand->ecc.necc_type = NAND_ECC_TYPE_HW;
506 break;
507 default:
508 aprint_error_dev(sc->sc_dev,
509 "chip #%u: ECC mode not supported by driver\n",
510 chip->chip_cs);
511 return;
512 }
513 #else
514 nand->ecc.necc_code_size = 3;
515 nand->ecc.necc_block_size = 512;
516 #endif
517
518 chip->chip_dev = nand_attach_mi(nand, sc->sc_dev);
519 }
520
521 static int
522 sunxi_nand_init_resources(struct sunxi_nand_softc *sc)
523 {
524 int error;
525
526 /* Both "mod" and "ahb" clocks are required */
527 sc->sc_clk_mod = fdtbus_clock_get(sc->sc_phandle, "mod");
528 sc->sc_clk_ahb = fdtbus_clock_get(sc->sc_phandle, "ahb");
529 if (sc->sc_clk_mod == NULL || sc->sc_clk_ahb == NULL)
530 return ENXIO;
531
532 if ((error = clk_enable(sc->sc_clk_ahb)) != 0)
533 return error;
534 if ((error = clk_enable(sc->sc_clk_mod)) != 0)
535 return error;
536
537 /* Reset is optional */
538 sc->sc_rst_ahb = fdtbus_reset_get(sc->sc_phandle, "ahb");
539 if (sc->sc_rst_ahb != NULL) {
540 if ((error = fdtbus_reset_deassert(sc->sc_rst_ahb)) != 0)
541 return error;
542 }
543
544 return 0;
545 }
546
547 static int
548 sunxi_nand_match(device_t parent, cfdata_t cf, void *aux)
549 {
550 struct fdt_attach_args * const faa = aux;
551
552 return of_match_compatible(faa->faa_phandle, compatible);
553 }
554
555 static void
556 sunxi_nand_attach(device_t parent, device_t self, void *aux)
557 {
558 struct sunxi_nand_softc * const sc = device_private(self);
559 struct fdt_attach_args * const faa = aux;
560 const int phandle = faa->faa_phandle;
561 bus_addr_t addr;
562 bus_size_t size;
563 int child;
564
565 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
566 aprint_error(": couldn't get registers\n");
567 return;
568 }
569
570 sc->sc_dev = self;
571 sc->sc_phandle = phandle;
572 sc->sc_bst = faa->faa_bst;
573 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
574 aprint_error(": couldn't map registers\n");
575 return;
576 }
577
578 aprint_naive("\n");
579 aprint_normal(": NAND Flash Controller\n");
580
581 if (sunxi_nand_init_resources(sc) != 0) {
582 aprint_error_dev(self, "couldn't initialize resources\n");
583 return;
584 }
585
586 /* DT bindings allow for multiple chips but we only use the first */
587 child = OF_child(phandle);
588 if (!child)
589 return;
590
591 sunxi_nand_attach_chip(sc, &sc->sc_chip, child);
592 }
593
594 CFATTACH_DECL_NEW(sunxi_nand, sizeof(struct sunxi_nand_softc),
595 sunxi_nand_match, sunxi_nand_attach, NULL, NULL);
596
597