1 /* $NetBSD: rmixl_nand.c,v 1.7 2011/07/01 19:01:31 dyoung Exp $ */ 2 3 /*- 4 * Copyright (c) 2010 Department of Software Engineering, 5 * University of Szeged, Hungary 6 * Copyright (c) 2010 Adam Hoka <ahoka@NetBSD.org> 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by the Department of Software Engineering, University of Szeged, Hungary 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 /* 35 * Device driver for the RMI XLS NAND controller 36 */ 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: rmixl_nand.c,v 1.7 2011/07/01 19:01:31 dyoung Exp $"); 40 41 #include "opt_flash.h" 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/cdefs.h> 46 #include <sys/device.h> 47 #include <sys/endian.h> 48 49 #include <sys/bus.h> 50 51 #include <mips/rmi/rmixlreg.h> 52 #include <mips/rmi/rmixlvar.h> 53 #include <mips/rmi/rmixl_iobusvar.h> 54 #include <mips/rmi/rmixl_intr.h> 55 56 #include <dev/nand/nand.h> 57 #include <dev/nand/onfi.h> 58 59 60 static int rmixl_nand_match(device_t, cfdata_t, void *); 61 static void rmixl_nand_attach(device_t, device_t, void *); 62 static int rmixl_nand_detach(device_t, int); 63 static void rmixl_nand_command(device_t, uint8_t); 64 static void rmixl_nand_address(device_t, uint8_t); 65 static void rmixl_nand_busy(device_t); 66 static void rmixl_nand_read_1(device_t, uint8_t *); 67 static void rmixl_nand_write_1(device_t, uint8_t); 68 static void rmixl_nand_read_2(device_t, uint16_t *); 69 static void rmixl_nand_write_2(device_t, uint16_t); 70 static void rmixl_nand_read_buf(device_t, void *, size_t); 71 static void rmixl_nand_write_buf(device_t, const void *, size_t); 72 73 74 struct rmixl_nand_softc { 75 device_t sc_dev; 76 device_t sc_nanddev; 77 struct iobus_softc *sc_iobus_sc; 78 79 int sc_cs; /* chip select index */ 80 int sc_buswidth; /* in bytes */ 81 82 struct nand_interface sc_nand_if; 83 84 bus_space_tag_t sc_obio_bst; 85 bus_space_handle_t sc_obio_bsh; 86 u_long sc_cmd_reg; 87 u_long sc_addr_reg; 88 89 bus_addr_t sc_iobus_addr; 90 bus_size_t sc_iobus_size; 91 bus_space_tag_t sc_iobus_bst; 92 bus_space_handle_t sc_iobus_bsh; 93 u_long sc_data_reg; 94 95 }; 96 97 CFATTACH_DECL_NEW(rmixl_nand, sizeof(struct rmixl_nand_softc), rmixl_nand_match, 98 rmixl_nand_attach, rmixl_nand_detach, NULL); 99 100 static int 101 rmixl_nand_match(device_t parent, cfdata_t match, void *aux) 102 { 103 struct rmixl_iobus_attach_args *ia = aux; 104 bus_space_handle_t bsh; 105 volatile uint32_t *vaddr; 106 int err; 107 int rv; 108 109 if ((ia->ia_dev_parm & RMIXL_FLASH_CSDEV_NANDEN) == 0) 110 return 0; /* not NAND */ 111 112 if (cpu_rmixlp(mips_options.mips_cpu)) { 113 aprint_error("%s: NAND not yet supported on XLP", __func__); 114 return 0; 115 } 116 117 if (! cpu_rmixls(mips_options.mips_cpu)) { 118 aprint_error("%s: NAND not supported on this processor", 119 __func__); 120 return 0; 121 } 122 123 /* 124 * probe for NAND -- this may be redundant 125 * if the device isn't there, the NANDEN test (above) 126 * should have failed 127 */ 128 err = bus_space_map(ia->ia_iobus_bst, ia->ia_iobus_addr, 129 sizeof(uint32_t), 0, &bsh); 130 if (err != 0) { 131 aprint_debug("%s: bus_space_map err %d, " 132 "iobus space addr %#" PRIxBUSADDR "\n", 133 __func__, err, ia->ia_iobus_addr); 134 return 0; 135 } 136 137 vaddr = bus_space_vaddr(ia->ia_iobus_bst, bsh); 138 rv = rmixl_probe_4(vaddr); 139 if (rv == 0) 140 aprint_debug("%s: rmixl_probe_4 failed, vaddr %p\n", 141 __func__, vaddr); 142 143 bus_space_unmap(ia->ia_iobus_bst, bsh, sizeof(uint32_t)); 144 145 return rv; 146 } 147 148 static void 149 rmixl_nand_attach(device_t parent, device_t self, void *aux) 150 { 151 struct rmixl_nand_softc *sc = device_private(self); 152 sc->sc_iobus_sc = device_private(parent); 153 struct rmixl_iobus_attach_args *ia = aux; 154 uint32_t val; 155 int err; 156 157 aprint_normal("\n"); 158 159 sc->sc_dev = self; 160 sc->sc_obio_bst = ia->ia_obio_bst; 161 sc->sc_obio_bsh = ia->ia_obio_bsh; 162 sc->sc_iobus_bst = ia->ia_iobus_bst; 163 sc->sc_iobus_addr = ia->ia_iobus_addr; 164 sc->sc_iobus_size = sizeof(uint32_t); 165 sc->sc_cs = ia->ia_cs; 166 167 sc->sc_cmd_reg = RMIXL_NAND_CLEn(ia->ia_cs); 168 sc->sc_addr_reg = RMIXL_NAND_ALEn(ia->ia_cs); 169 170 aprint_debug_dev(self, "CS#%d cstime_parma %#x, cstime_parmb %#x\n", 171 ia->ia_cs, 172 bus_space_read_4(sc->sc_obio_bst, sc->sc_obio_bsh, 173 RMIXL_FLASH_CSTIME_PARMAn(ia->ia_cs)), 174 bus_space_read_4(sc->sc_obio_bst, sc->sc_obio_bsh, 175 RMIXL_FLASH_CSTIME_PARMBn(ia->ia_cs))); 176 177 err = bus_space_map(sc->sc_iobus_bst, sc->sc_iobus_addr, 178 sc->sc_iobus_size, 0, &sc->sc_iobus_bsh); 179 if (err != 0) { 180 aprint_error_dev(self, 181 "bus space map err %d, iobus space\n", err); 182 return; 183 } 184 185 /* 186 * determine buswidth 187 */ 188 val = ia->ia_dev_parm; 189 val &= RMIXL_FLASH_CSDEV_DWIDTH; 190 val >>= RMIXL_FLASH_CSDEV_DWIDTH_SHFT; 191 switch(val) { 192 case 0: /* FALLTHROUGH */ 193 case 3: 194 sc->sc_buswidth = 1; /* 8 bit */ 195 break; 196 case 1: 197 sc->sc_buswidth = 2; /* 16 bit */ 198 break; 199 case 2: 200 sc->sc_buswidth = 4; /* 32 bit */ 201 break; 202 } 203 aprint_debug_dev(self, "bus width %d bits\n", 8 * sc->sc_buswidth); 204 205 nand_init_interface(&sc->sc_nand_if); 206 207 sc->sc_nand_if.command = rmixl_nand_command; 208 sc->sc_nand_if.address = rmixl_nand_address; 209 sc->sc_nand_if.read_buf_1 = rmixl_nand_read_buf; 210 sc->sc_nand_if.read_buf_2 = rmixl_nand_read_buf; 211 sc->sc_nand_if.read_1 = rmixl_nand_read_1; 212 sc->sc_nand_if.read_2 = rmixl_nand_read_2; 213 sc->sc_nand_if.write_buf_1 = rmixl_nand_write_buf; 214 sc->sc_nand_if.write_buf_2 = rmixl_nand_write_buf; 215 sc->sc_nand_if.write_1 = rmixl_nand_write_1; 216 sc->sc_nand_if.write_2 = rmixl_nand_write_2; 217 sc->sc_nand_if.busy = rmixl_nand_busy; 218 219 sc->sc_nand_if.ecc.necc_code_size = 3; 220 sc->sc_nand_if.ecc.necc_block_size = 256; 221 222 /* 223 * reset to get NAND into known state 224 */ 225 rmixl_nand_command(self, ONFI_RESET); 226 rmixl_nand_busy(self); 227 228 if (! pmf_device_register1(self, NULL, NULL, NULL)) 229 aprint_error_dev(self, "couldn't establish power handler\n"); 230 231 sc->sc_nanddev = nand_attach_mi(&sc->sc_nand_if, self); 232 } 233 234 static int 235 rmixl_nand_detach(device_t self, int flags) 236 { 237 struct rmixl_nand_softc *sc = device_private(self); 238 int rv = 0; 239 240 pmf_device_deregister(self); 241 242 if (sc->sc_nanddev != NULL) 243 rv = config_detach(sc->sc_nanddev, flags); 244 245 bus_space_unmap(sc->sc_iobus_bst, sc->sc_iobus_bsh, sc->sc_iobus_size); 246 247 return rv; 248 } 249 250 static void 251 rmixl_nand_command(device_t self, uint8_t command) 252 { 253 struct rmixl_nand_softc *sc = device_private(self); 254 255 bus_space_write_4(sc->sc_obio_bst, sc->sc_obio_bsh, 256 sc->sc_cmd_reg, command); 257 } 258 259 static void 260 rmixl_nand_address(device_t self, uint8_t address) 261 { 262 struct rmixl_nand_softc *sc = device_private(self); 263 264 bus_space_write_4(sc->sc_obio_bst, sc->sc_obio_bsh, 265 sc->sc_addr_reg, address); 266 } 267 268 static void 269 rmixl_nand_busy(device_t self) 270 { 271 struct rmixl_nand_softc *sc = device_private(self); 272 uint32_t istatus; 273 274 for(u_int count=100000; count--;) { 275 istatus = bus_space_read_4(sc->sc_obio_bst, sc->sc_obio_bsh, 276 RMIXL_FLASH_INT_STATUS); 277 if ((istatus & __BIT(8)) != 0) 278 return; 279 DELAY(1); 280 } 281 #ifdef DEBUG 282 printf("%s: timed out, istatus=%#x\n", __func__, istatus); 283 #ifdef DDB 284 Debugger(); 285 #endif 286 #endif 287 } 288 289 static void 290 rmixl_nand_read_1(device_t self, uint8_t *data) 291 { 292 struct rmixl_nand_softc *sc = device_private(self); 293 294 *data = bus_space_read_1(sc->sc_iobus_bst, sc->sc_iobus_bsh, 0); 295 } 296 297 static void 298 rmixl_nand_write_1(device_t self, uint8_t data) 299 { 300 struct rmixl_nand_softc *sc = device_private(self); 301 302 bus_space_write_1(sc->sc_iobus_bst, sc->sc_iobus_bsh, 0, data); 303 } 304 305 static void 306 rmixl_nand_read_2(device_t self, uint16_t *data) 307 { 308 struct rmixl_nand_softc *sc = device_private(self); 309 310 *data = bus_space_read_2(sc->sc_iobus_bst, sc->sc_iobus_bsh, 0); 311 } 312 313 static void 314 rmixl_nand_write_2(device_t self, uint16_t data) 315 { 316 struct rmixl_nand_softc *sc = device_private(self); 317 318 bus_space_write_2(sc->sc_iobus_bst, sc->sc_iobus_bsh, 0, data); 319 } 320 321 static void 322 rmixl_nand_read_buf(device_t self, void *buf, size_t len) 323 { 324 struct rmixl_nand_softc *sc = device_private(self); 325 uintptr_t addr = (uintptr_t)buf; 326 size_t sz; 327 328 /* leading byte alignment */ 329 if ((len >= 1) && ((addr & 1) != 0)) { 330 *((uint8_t *)addr) = bus_space_read_1(sc->sc_iobus_bst, 331 sc->sc_iobus_bsh, 0); 332 addr += 1; 333 len -= 1; 334 } 335 336 /* leading short alignment */ 337 if ((len >= 2) && ((addr & 2) != 0)) { 338 *((uint16_t *)addr) = bus_space_read_2(sc->sc_iobus_bst, 339 sc->sc_iobus_bsh, 0); 340 addr += 2; 341 len -= 2; 342 } 343 344 /* word alignment */ 345 sz = len >> 2; 346 if (sz != 0) { 347 bus_space_read_multi_4(sc->sc_iobus_bst, sc->sc_iobus_bsh, 348 0, (uint32_t *)addr, sz); 349 sz <<= 2; 350 addr += sz; 351 len -= sz; 352 } 353 354 /* trailing short alignment */ 355 if (len >= 2) { 356 *((uint16_t *)addr) = bus_space_read_2(sc->sc_iobus_bst, 357 sc->sc_iobus_bsh, 0); 358 addr += 2; 359 len -= 2; 360 } 361 362 /* trailing byte alignment */ 363 if (len != 0) 364 *((uint8_t *)addr) = bus_space_read_1(sc->sc_iobus_bst, 365 sc->sc_iobus_bsh, 0); 366 } 367 368 static void 369 rmixl_nand_write_buf(device_t self, const void *buf, size_t len) 370 { 371 struct rmixl_nand_softc *sc = device_private(self); 372 uintptr_t addr = (uintptr_t)buf; 373 size_t sz; 374 375 /* leading byte alignment */ 376 if ((len >= 1) && ((addr & 1) != 0)) { 377 bus_space_write_1(sc->sc_iobus_bst, sc->sc_iobus_bsh, 0, 378 *((uint8_t *)addr)); 379 addr += 1; 380 len -= 1; 381 } 382 383 /* leading short alignment */ 384 if ((len >= 2) && ((addr & 2) != 0)) { 385 bus_space_write_2(sc->sc_iobus_bst, sc->sc_iobus_bsh, 0, 386 *((uint16_t *)addr)); 387 addr += 2; 388 len -= 2; 389 } 390 391 /* word alignment */ 392 sz = len >> 2; 393 if (sz != 0) { 394 bus_space_write_multi_4(sc->sc_iobus_bst, sc->sc_iobus_bsh, 395 0, (uint32_t *)addr, sz); 396 sz <<= 2; 397 addr += sz; 398 len -= sz; 399 } 400 401 /* trailing short alignment */ 402 if (len >= 2) { 403 bus_space_write_2(sc->sc_iobus_bst, sc->sc_iobus_bsh, 0, 404 *((uint16_t *)addr)); 405 addr += 2; 406 len -= 2; 407 } 408 409 /* trailing byte alignment */ 410 if (len != 0) 411 bus_space_write_1(sc->sc_iobus_bst, sc->sc_iobus_bsh, 0, 412 *((uint8_t *)addr)); 413 } 414