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