1/*- 2 * Copyright (C) 2009-2012 Semihalf 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/11/sys/dev/nand/nand_cdev.c 350226 2019-07-22 20:33:19Z emaste $"); 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/conf.h> 33#include <sys/bus.h> 34#include <sys/malloc.h> 35#include <sys/uio.h> 36#include <sys/bio.h> 37 38#include <dev/nand/nand.h> 39#include <dev/nand/nandbus.h> 40#include <dev/nand/nand_dev.h> 41#include "nand_if.h" 42#include "nandbus_if.h" 43 44static int nand_page_stat(struct nand_chip *, struct page_stat_io *); 45static int nand_block_stat(struct nand_chip *, struct block_stat_io *); 46 47static d_ioctl_t nand_ioctl; 48static d_open_t nand_open; 49static d_strategy_t nand_strategy; 50 51static struct cdevsw nand_cdevsw = { 52 .d_version = D_VERSION, 53 .d_name = "nand", 54 .d_open = nand_open, 55 .d_read = physread, 56 .d_write = physwrite, 57 .d_ioctl = nand_ioctl, 58 .d_strategy = nand_strategy, 59}; 60 61static int 62offset_to_page(struct chip_geom *cg, uint32_t offset) 63{ 64 65 return (offset / cg->page_size); 66} 67 68static int 69offset_to_page_off(struct chip_geom *cg, uint32_t offset) 70{ 71 72 return (offset % cg->page_size); 73} 74 75int 76nand_make_dev(struct nand_chip *chip) 77{ 78 struct nandbus_ivar *ivar; 79 device_t parent, nandbus; 80 int parent_unit, unit; 81 char *name; 82 83 ivar = device_get_ivars(chip->dev); 84 nandbus = device_get_parent(chip->dev); 85 86 if (ivar->chip_cdev_name) { 87 name = ivar->chip_cdev_name; 88 89 /* 90 * If we got distinct name for chip device we can enumarete it 91 * based on contoller number. 92 */ 93 parent = device_get_parent(nandbus); 94 } else { 95 name = "nand"; 96 parent = nandbus; 97 } 98 99 parent_unit = device_get_unit(parent); 100 unit = parent_unit * 4 + chip->num; 101 chip->cdev = make_dev(&nand_cdevsw, unit, UID_ROOT, GID_WHEEL, 102 0640, "%s%d.%d", name, parent_unit, chip->num); 103 104 if (chip->cdev == NULL) 105 return (ENXIO); 106 107 if (bootverbose) 108 device_printf(chip->dev, "Created cdev %s%d.%d for chip " 109 "[0x%0x, 0x%0x]\n", name, parent_unit, chip->num, 110 ivar->man_id, ivar->dev_id); 111 112 chip->cdev->si_drv1 = chip; 113 114 return (0); 115} 116 117void 118nand_destroy_dev(struct nand_chip *chip) 119{ 120 121 if (chip->cdev) 122 destroy_dev(chip->cdev); 123} 124 125static int 126nand_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 127{ 128 129 return (0); 130} 131 132static int 133nand_read(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len) 134{ 135 struct chip_geom *cg; 136 device_t nandbus; 137 int start_page, count, off, err = 0; 138 uint8_t *ptr, *tmp; 139 140 nand_debug(NDBG_CDEV, "Read from chip%d [%p] at %d\n", chip->num, 141 chip, offset); 142 143 nandbus = device_get_parent(chip->dev); 144 NANDBUS_LOCK(nandbus); 145 NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num); 146 147 cg = &chip->chip_geom; 148 start_page = offset_to_page(cg, offset); 149 off = offset_to_page_off(cg, offset); 150 count = (len > cg->page_size - off) ? cg->page_size - off : len; 151 152 ptr = (uint8_t *)buf; 153 while (len > 0) { 154 if (len < cg->page_size) { 155 tmp = malloc(cg->page_size, M_NAND, M_WAITOK); 156 if (!tmp) { 157 err = ENOMEM; 158 break; 159 } 160 err = NAND_READ_PAGE(chip->dev, start_page, 161 tmp, cg->page_size, 0); 162 if (err) { 163 free(tmp, M_NAND); 164 break; 165 } 166 bcopy(tmp + off, ptr, count); 167 free(tmp, M_NAND); 168 } else { 169 err = NAND_READ_PAGE(chip->dev, start_page, 170 ptr, cg->page_size, 0); 171 if (err) 172 break; 173 } 174 175 len -= count; 176 start_page++; 177 ptr += count; 178 count = (len > cg->page_size) ? cg->page_size : len; 179 off = 0; 180 } 181 182 NANDBUS_UNLOCK(nandbus); 183 return (err); 184} 185 186static int 187nand_write(struct nand_chip *chip, uint32_t offset, void* buf, uint32_t len) 188{ 189 struct chip_geom *cg; 190 device_t nandbus; 191 int off, start_page, err = 0; 192 uint8_t *ptr; 193 194 nand_debug(NDBG_CDEV, "Write to chip %d [%p] at %d\n", chip->num, 195 chip, offset); 196 197 nandbus = device_get_parent(chip->dev); 198 NANDBUS_LOCK(nandbus); 199 NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num); 200 201 cg = &chip->chip_geom; 202 start_page = offset_to_page(cg, offset); 203 off = offset_to_page_off(cg, offset); 204 205 if (off != 0 || (len % cg->page_size) != 0) { 206 printf("Not aligned write start [0x%08x] size [0x%08x]\n", 207 off, len); 208 NANDBUS_UNLOCK(nandbus); 209 return (EINVAL); 210 } 211 212 ptr = (uint8_t *)buf; 213 while (len > 0) { 214 err = NAND_PROGRAM_PAGE(chip->dev, start_page, ptr, 215 cg->page_size, 0); 216 if (err) 217 break; 218 219 len -= cg->page_size; 220 start_page++; 221 ptr += cg->page_size; 222 } 223 224 NANDBUS_UNLOCK(nandbus); 225 return (err); 226} 227 228static void 229nand_strategy(struct bio *bp) 230{ 231 struct nand_chip *chip; 232 struct cdev *dev; 233 int err = 0; 234 235 dev = bp->bio_dev; 236 chip = dev->si_drv1; 237 238 nand_debug(NDBG_CDEV, "Strategy %s on chip %d [%p]\n", 239 bp->bio_cmd == BIO_READ ? "READ" : "WRITE", 240 chip->num, chip); 241 242 if (bp->bio_cmd == BIO_READ) { 243 err = nand_read(chip, 244 bp->bio_offset & 0xffffffff, 245 bp->bio_data, bp->bio_bcount); 246 } else { 247 err = nand_write(chip, 248 bp->bio_offset & 0xffffffff, 249 bp->bio_data, bp->bio_bcount); 250 } 251 252 if (err == 0) 253 bp->bio_resid = 0; 254 else { 255 bp->bio_error = EIO; 256 bp->bio_flags |= BIO_ERROR; 257 bp->bio_resid = bp->bio_bcount; 258 } 259 260 biodone(bp); 261} 262 263static int 264nand_oob_access(struct nand_chip *chip, uint32_t page, uint32_t offset, 265 uint32_t len, uint8_t *data, uint8_t write) 266{ 267 struct chip_geom *cg; 268 uint8_t *buf = NULL; 269 int ret = 0; 270 271 cg = &chip->chip_geom; 272 273 buf = malloc(cg->oob_size, M_NAND, M_WAITOK); 274 if (!buf) 275 return (ENOMEM); 276 277 memset(buf, 0xff, cg->oob_size); 278 279 if (!write) { 280 ret = nand_read_oob(chip, page, buf, cg->oob_size); 281 copyout(buf, data, len); 282 } else { 283 copyin(data, buf, len); 284 ret = nand_prog_oob(chip, page, buf, cg->oob_size); 285 } 286 287 free(buf, M_NAND); 288 289 return (ret); 290} 291 292static int 293nand_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, 294 struct thread *td) 295{ 296 struct nand_chip *chip; 297 struct chip_geom *cg; 298 struct nand_oob_rw *oob_rw = NULL; 299 struct nand_raw_rw *raw_rw = NULL; 300 device_t nandbus; 301 size_t bufsize = 0, len = 0; 302 size_t raw_size; 303 off_t off; 304 uint8_t *buf = NULL; 305 int ret = 0; 306 uint8_t status; 307 308 chip = (struct nand_chip *)dev->si_drv1; 309 cg = &chip->chip_geom; 310 nandbus = device_get_parent(chip->dev); 311 312 if ((cmd == NAND_IO_RAW_READ) || (cmd == NAND_IO_RAW_PROG)) { 313 raw_rw = (struct nand_raw_rw *)data; 314 raw_size = cg->pgs_per_blk * (cg->page_size + cg->oob_size); 315 316 /* Check if len is not bigger than chip size */ 317 if (raw_rw->len > raw_size) 318 return (EFBIG); 319 320 /* 321 * Do not ask for too much memory, in case of large transfers 322 * read/write in 16-pages chunks 323 */ 324 bufsize = 16 * (cg->page_size + cg->oob_size); 325 if (raw_rw->len < bufsize) 326 bufsize = raw_rw->len; 327 328 buf = malloc(bufsize, M_NAND, M_WAITOK); 329 len = raw_rw->len; 330 off = 0; 331 } 332 switch(cmd) { 333 case NAND_IO_ERASE: 334 ret = nand_erase_blocks(chip, ((off_t *)data)[0], 335 ((off_t *)data)[1]); 336 break; 337 338 case NAND_IO_OOB_READ: 339 oob_rw = (struct nand_oob_rw *)data; 340 ret = nand_oob_access(chip, oob_rw->page, 0, 341 oob_rw->len, oob_rw->data, 0); 342 break; 343 344 case NAND_IO_OOB_PROG: 345 oob_rw = (struct nand_oob_rw *)data; 346 ret = nand_oob_access(chip, oob_rw->page, 0, 347 oob_rw->len, oob_rw->data, 1); 348 break; 349 350 case NAND_IO_GET_STATUS: 351 NANDBUS_LOCK(nandbus); 352 ret = NANDBUS_GET_STATUS(nandbus, &status); 353 if (ret == 0) 354 *(uint8_t *)data = status; 355 NANDBUS_UNLOCK(nandbus); 356 break; 357 358 case NAND_IO_RAW_PROG: 359 while (len > 0) { 360 if (len < bufsize) 361 bufsize = len; 362 ret = copyin(raw_rw->data + off, buf, bufsize); 363 if (ret) 364 break; 365 ret = nand_prog_pages_raw(chip, raw_rw->off + off, buf, 366 bufsize); 367 if (ret) 368 break; 369 len -= bufsize; 370 off += bufsize; 371 } 372 break; 373 374 case NAND_IO_RAW_READ: 375 while (len > 0) { 376 if (len < bufsize) 377 bufsize = len; 378 379 ret = nand_read_pages_raw(chip, raw_rw->off + off, buf, 380 bufsize); 381 if (ret) 382 break; 383 384 ret = copyout(buf, raw_rw->data + off, bufsize); 385 if (ret) 386 break; 387 len -= bufsize; 388 off += bufsize; 389 } 390 break; 391 392 case NAND_IO_PAGE_STAT: 393 ret = nand_page_stat(chip, (struct page_stat_io *)data); 394 break; 395 396 case NAND_IO_BLOCK_STAT: 397 ret = nand_block_stat(chip, (struct block_stat_io *)data); 398 break; 399 400 case NAND_IO_GET_CHIP_PARAM: 401 nand_get_chip_param(chip, (struct chip_param_io *)data); 402 break; 403 404 default: 405 printf("Unknown nand_ioctl request \n"); 406 ret = EIO; 407 } 408 409 if (buf) 410 free(buf, M_NAND); 411 412 return (ret); 413} 414 415static int 416nand_page_stat(struct nand_chip *chip, struct page_stat_io *page_stat) 417{ 418 struct chip_geom *cg; 419 struct page_stat *stat; 420 int num_pages; 421 422 cg = &chip->chip_geom; 423 num_pages = cg->pgs_per_blk * cg->blks_per_lun * cg->luns; 424 if (page_stat->page_num >= num_pages) 425 return (EINVAL); 426 427 stat = &chip->pg_stat[page_stat->page_num]; 428 page_stat->page_read = stat->page_read; 429 page_stat->page_written = stat->page_written; 430 page_stat->page_raw_read = stat->page_raw_read; 431 page_stat->page_raw_written = stat->page_raw_written; 432 page_stat->ecc_succeded = stat->ecc_stat.ecc_succeded; 433 page_stat->ecc_corrected = stat->ecc_stat.ecc_corrected; 434 page_stat->ecc_failed = stat->ecc_stat.ecc_failed; 435 436 return (0); 437} 438 439static int 440nand_block_stat(struct nand_chip *chip, struct block_stat_io *block_stat) 441{ 442 struct chip_geom *cg; 443 uint32_t block_num = block_stat->block_num; 444 445 cg = &chip->chip_geom; 446 if (block_num >= cg->blks_per_lun * cg->luns) 447 return (EINVAL); 448 449 block_stat->block_erased = chip->blk_stat[block_num].block_erased; 450 451 return (0); 452} 453