| .. | .. |
|---|
| 103 | 103 | /*--------------------------------------------------------------------------*/ |
|---|
| 104 | 104 | |
|---|
| 105 | 105 | struct tmio_nand { |
|---|
| 106 | + struct nand_controller controller; |
|---|
| 106 | 107 | struct nand_chip chip; |
|---|
| 108 | + struct completion comp; |
|---|
| 107 | 109 | |
|---|
| 108 | 110 | struct platform_device *dev; |
|---|
| 109 | 111 | |
|---|
| .. | .. |
|---|
| 126 | 128 | |
|---|
| 127 | 129 | /*--------------------------------------------------------------------------*/ |
|---|
| 128 | 130 | |
|---|
| 129 | | -static void tmio_nand_hwcontrol(struct mtd_info *mtd, int cmd, |
|---|
| 130 | | - unsigned int ctrl) |
|---|
| 131 | +static void tmio_nand_hwcontrol(struct nand_chip *chip, int cmd, |
|---|
| 132 | + unsigned int ctrl) |
|---|
| 131 | 133 | { |
|---|
| 132 | | - struct tmio_nand *tmio = mtd_to_tmio(mtd); |
|---|
| 133 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
|---|
| 134 | + struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip)); |
|---|
| 134 | 135 | |
|---|
| 135 | 136 | if (ctrl & NAND_CTRL_CHANGE) { |
|---|
| 136 | 137 | u8 mode; |
|---|
| .. | .. |
|---|
| 156 | 157 | } |
|---|
| 157 | 158 | |
|---|
| 158 | 159 | if (cmd != NAND_CMD_NONE) |
|---|
| 159 | | - tmio_iowrite8(cmd, chip->IO_ADDR_W); |
|---|
| 160 | + tmio_iowrite8(cmd, chip->legacy.IO_ADDR_W); |
|---|
| 160 | 161 | } |
|---|
| 161 | 162 | |
|---|
| 162 | | -static int tmio_nand_dev_ready(struct mtd_info *mtd) |
|---|
| 163 | +static int tmio_nand_dev_ready(struct nand_chip *chip) |
|---|
| 163 | 164 | { |
|---|
| 164 | | - struct tmio_nand *tmio = mtd_to_tmio(mtd); |
|---|
| 165 | + struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip)); |
|---|
| 165 | 166 | |
|---|
| 166 | 167 | return !(tmio_ioread8(tmio->fcr + FCR_STATUS) & FCR_STATUS_BUSY); |
|---|
| 167 | 168 | } |
|---|
| .. | .. |
|---|
| 169 | 170 | static irqreturn_t tmio_irq(int irq, void *__tmio) |
|---|
| 170 | 171 | { |
|---|
| 171 | 172 | struct tmio_nand *tmio = __tmio; |
|---|
| 172 | | - struct nand_chip *nand_chip = &tmio->chip; |
|---|
| 173 | 173 | |
|---|
| 174 | 174 | /* disable RDYREQ interrupt */ |
|---|
| 175 | 175 | tmio_iowrite8(0x00, tmio->fcr + FCR_IMR); |
|---|
| 176 | + complete(&tmio->comp); |
|---|
| 176 | 177 | |
|---|
| 177 | | - if (unlikely(!waitqueue_active(&nand_chip->controller->wq))) |
|---|
| 178 | | - dev_warn(&tmio->dev->dev, "spurious interrupt\n"); |
|---|
| 179 | | - |
|---|
| 180 | | - wake_up(&nand_chip->controller->wq); |
|---|
| 181 | 178 | return IRQ_HANDLED; |
|---|
| 182 | 179 | } |
|---|
| 183 | 180 | |
|---|
| .. | .. |
|---|
| 187 | 184 | *erase and write, we enable it to wake us up. The irq handler |
|---|
| 188 | 185 | *disables the interrupt. |
|---|
| 189 | 186 | */ |
|---|
| 190 | | -static int |
|---|
| 191 | | -tmio_nand_wait(struct mtd_info *mtd, struct nand_chip *nand_chip) |
|---|
| 187 | +static int tmio_nand_wait(struct nand_chip *nand_chip) |
|---|
| 192 | 188 | { |
|---|
| 193 | | - struct tmio_nand *tmio = mtd_to_tmio(mtd); |
|---|
| 189 | + struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(nand_chip)); |
|---|
| 194 | 190 | long timeout; |
|---|
| 195 | 191 | u8 status; |
|---|
| 196 | 192 | |
|---|
| 197 | 193 | /* enable RDYREQ interrupt */ |
|---|
| 194 | + |
|---|
| 198 | 195 | tmio_iowrite8(0x0f, tmio->fcr + FCR_ISR); |
|---|
| 196 | + reinit_completion(&tmio->comp); |
|---|
| 199 | 197 | tmio_iowrite8(0x81, tmio->fcr + FCR_IMR); |
|---|
| 200 | 198 | |
|---|
| 201 | | - timeout = wait_event_timeout(nand_chip->controller->wq, |
|---|
| 202 | | - tmio_nand_dev_ready(mtd), |
|---|
| 203 | | - msecs_to_jiffies(nand_chip->state == FL_ERASING ? 400 : 20)); |
|---|
| 199 | + timeout = 400; |
|---|
| 200 | + timeout = wait_for_completion_timeout(&tmio->comp, |
|---|
| 201 | + msecs_to_jiffies(timeout)); |
|---|
| 204 | 202 | |
|---|
| 205 | | - if (unlikely(!tmio_nand_dev_ready(mtd))) { |
|---|
| 203 | + if (unlikely(!tmio_nand_dev_ready(nand_chip))) { |
|---|
| 206 | 204 | tmio_iowrite8(0x00, tmio->fcr + FCR_IMR); |
|---|
| 207 | | - dev_warn(&tmio->dev->dev, "still busy with %s after %d ms\n", |
|---|
| 208 | | - nand_chip->state == FL_ERASING ? "erase" : "program", |
|---|
| 209 | | - nand_chip->state == FL_ERASING ? 400 : 20); |
|---|
| 205 | + dev_warn(&tmio->dev->dev, "still busy after 400 ms\n"); |
|---|
| 210 | 206 | |
|---|
| 211 | 207 | } else if (unlikely(!timeout)) { |
|---|
| 212 | 208 | tmio_iowrite8(0x00, tmio->fcr + FCR_IMR); |
|---|
| .. | .. |
|---|
| 225 | 221 | *To prevent stale data from being read, tmio_nand_hwcontrol() clears |
|---|
| 226 | 222 | *tmio->read_good. |
|---|
| 227 | 223 | */ |
|---|
| 228 | | -static u_char tmio_nand_read_byte(struct mtd_info *mtd) |
|---|
| 224 | +static u_char tmio_nand_read_byte(struct nand_chip *chip) |
|---|
| 229 | 225 | { |
|---|
| 230 | | - struct tmio_nand *tmio = mtd_to_tmio(mtd); |
|---|
| 226 | + struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip)); |
|---|
| 231 | 227 | unsigned int data; |
|---|
| 232 | 228 | |
|---|
| 233 | 229 | if (tmio->read_good--) |
|---|
| .. | .. |
|---|
| 245 | 241 | *buffer functions. |
|---|
| 246 | 242 | */ |
|---|
| 247 | 243 | static void |
|---|
| 248 | | -tmio_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) |
|---|
| 244 | +tmio_nand_write_buf(struct nand_chip *chip, const u_char *buf, int len) |
|---|
| 249 | 245 | { |
|---|
| 250 | | - struct tmio_nand *tmio = mtd_to_tmio(mtd); |
|---|
| 246 | + struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip)); |
|---|
| 251 | 247 | |
|---|
| 252 | 248 | tmio_iowrite16_rep(tmio->fcr + FCR_DATA, buf, len >> 1); |
|---|
| 253 | 249 | } |
|---|
| 254 | 250 | |
|---|
| 255 | | -static void tmio_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) |
|---|
| 251 | +static void tmio_nand_read_buf(struct nand_chip *chip, u_char *buf, int len) |
|---|
| 256 | 252 | { |
|---|
| 257 | | - struct tmio_nand *tmio = mtd_to_tmio(mtd); |
|---|
| 253 | + struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip)); |
|---|
| 258 | 254 | |
|---|
| 259 | 255 | tmio_ioread16_rep(tmio->fcr + FCR_DATA, buf, len >> 1); |
|---|
| 260 | 256 | } |
|---|
| 261 | 257 | |
|---|
| 262 | | -static void tmio_nand_enable_hwecc(struct mtd_info *mtd, int mode) |
|---|
| 258 | +static void tmio_nand_enable_hwecc(struct nand_chip *chip, int mode) |
|---|
| 263 | 259 | { |
|---|
| 264 | | - struct tmio_nand *tmio = mtd_to_tmio(mtd); |
|---|
| 260 | + struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip)); |
|---|
| 265 | 261 | |
|---|
| 266 | 262 | tmio_iowrite8(FCR_MODE_HWECC_RESET, tmio->fcr + FCR_MODE); |
|---|
| 267 | 263 | tmio_ioread8(tmio->fcr + FCR_DATA); /* dummy read */ |
|---|
| 268 | 264 | tmio_iowrite8(FCR_MODE_HWECC_CALC, tmio->fcr + FCR_MODE); |
|---|
| 269 | 265 | } |
|---|
| 270 | 266 | |
|---|
| 271 | | -static int tmio_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, |
|---|
| 272 | | - u_char *ecc_code) |
|---|
| 267 | +static int tmio_nand_calculate_ecc(struct nand_chip *chip, const u_char *dat, |
|---|
| 268 | + u_char *ecc_code) |
|---|
| 273 | 269 | { |
|---|
| 274 | | - struct tmio_nand *tmio = mtd_to_tmio(mtd); |
|---|
| 270 | + struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip)); |
|---|
| 275 | 271 | unsigned int ecc; |
|---|
| 276 | 272 | |
|---|
| 277 | 273 | tmio_iowrite8(FCR_MODE_HWECC_RESULT, tmio->fcr + FCR_MODE); |
|---|
| .. | .. |
|---|
| 290 | 286 | return 0; |
|---|
| 291 | 287 | } |
|---|
| 292 | 288 | |
|---|
| 293 | | -static int tmio_nand_correct_data(struct mtd_info *mtd, unsigned char *buf, |
|---|
| 294 | | - unsigned char *read_ecc, unsigned char *calc_ecc) |
|---|
| 289 | +static int tmio_nand_correct_data(struct nand_chip *chip, unsigned char *buf, |
|---|
| 290 | + unsigned char *read_ecc, |
|---|
| 291 | + unsigned char *calc_ecc) |
|---|
| 295 | 292 | { |
|---|
| 296 | 293 | int r0, r1; |
|---|
| 297 | 294 | |
|---|
| 298 | 295 | /* assume ecc.size = 512 and ecc.bytes = 6 */ |
|---|
| 299 | | - r0 = __nand_correct_data(buf, read_ecc, calc_ecc, 256); |
|---|
| 296 | + r0 = __nand_correct_data(buf, read_ecc, calc_ecc, 256, false); |
|---|
| 300 | 297 | if (r0 < 0) |
|---|
| 301 | 298 | return r0; |
|---|
| 302 | | - r1 = __nand_correct_data(buf + 256, read_ecc + 3, calc_ecc + 3, 256); |
|---|
| 299 | + r1 = __nand_correct_data(buf + 256, read_ecc + 3, calc_ecc + 3, 256, |
|---|
| 300 | + false); |
|---|
| 303 | 301 | if (r1 < 0) |
|---|
| 304 | 302 | return r1; |
|---|
| 305 | 303 | return r0 + r1; |
|---|
| .. | .. |
|---|
| 358 | 356 | cell->disable(dev); |
|---|
| 359 | 357 | } |
|---|
| 360 | 358 | |
|---|
| 359 | +static int tmio_attach_chip(struct nand_chip *chip) |
|---|
| 360 | +{ |
|---|
| 361 | + if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) |
|---|
| 362 | + return 0; |
|---|
| 363 | + |
|---|
| 364 | + chip->ecc.size = 512; |
|---|
| 365 | + chip->ecc.bytes = 6; |
|---|
| 366 | + chip->ecc.strength = 2; |
|---|
| 367 | + chip->ecc.hwctl = tmio_nand_enable_hwecc; |
|---|
| 368 | + chip->ecc.calculate = tmio_nand_calculate_ecc; |
|---|
| 369 | + chip->ecc.correct = tmio_nand_correct_data; |
|---|
| 370 | + |
|---|
| 371 | + return 0; |
|---|
| 372 | +} |
|---|
| 373 | + |
|---|
| 374 | +static const struct nand_controller_ops tmio_ops = { |
|---|
| 375 | + .attach_chip = tmio_attach_chip, |
|---|
| 376 | +}; |
|---|
| 377 | + |
|---|
| 361 | 378 | static int tmio_probe(struct platform_device *dev) |
|---|
| 362 | 379 | { |
|---|
| 363 | 380 | struct tmio_nand_data *data = dev_get_platdata(&dev->dev); |
|---|
| .. | .. |
|---|
| 378 | 395 | if (!tmio) |
|---|
| 379 | 396 | return -ENOMEM; |
|---|
| 380 | 397 | |
|---|
| 398 | + init_completion(&tmio->comp); |
|---|
| 399 | + |
|---|
| 381 | 400 | tmio->dev = dev; |
|---|
| 382 | 401 | |
|---|
| 383 | 402 | platform_set_drvdata(dev, tmio); |
|---|
| .. | .. |
|---|
| 385 | 404 | mtd = nand_to_mtd(nand_chip); |
|---|
| 386 | 405 | mtd->name = "tmio-nand"; |
|---|
| 387 | 406 | mtd->dev.parent = &dev->dev; |
|---|
| 407 | + |
|---|
| 408 | + nand_controller_init(&tmio->controller); |
|---|
| 409 | + tmio->controller.ops = &tmio_ops; |
|---|
| 410 | + nand_chip->controller = &tmio->controller; |
|---|
| 388 | 411 | |
|---|
| 389 | 412 | tmio->ccr = devm_ioremap(&dev->dev, ccr->start, resource_size(ccr)); |
|---|
| 390 | 413 | if (!tmio->ccr) |
|---|
| .. | .. |
|---|
| 400 | 423 | return retval; |
|---|
| 401 | 424 | |
|---|
| 402 | 425 | /* Set address of NAND IO lines */ |
|---|
| 403 | | - nand_chip->IO_ADDR_R = tmio->fcr; |
|---|
| 404 | | - nand_chip->IO_ADDR_W = tmio->fcr; |
|---|
| 426 | + nand_chip->legacy.IO_ADDR_R = tmio->fcr; |
|---|
| 427 | + nand_chip->legacy.IO_ADDR_W = tmio->fcr; |
|---|
| 405 | 428 | |
|---|
| 406 | 429 | /* Set address of hardware control function */ |
|---|
| 407 | | - nand_chip->cmd_ctrl = tmio_nand_hwcontrol; |
|---|
| 408 | | - nand_chip->dev_ready = tmio_nand_dev_ready; |
|---|
| 409 | | - nand_chip->read_byte = tmio_nand_read_byte; |
|---|
| 410 | | - nand_chip->write_buf = tmio_nand_write_buf; |
|---|
| 411 | | - nand_chip->read_buf = tmio_nand_read_buf; |
|---|
| 412 | | - |
|---|
| 413 | | - /* set eccmode using hardware ECC */ |
|---|
| 414 | | - nand_chip->ecc.mode = NAND_ECC_HW; |
|---|
| 415 | | - nand_chip->ecc.size = 512; |
|---|
| 416 | | - nand_chip->ecc.bytes = 6; |
|---|
| 417 | | - nand_chip->ecc.strength = 2; |
|---|
| 418 | | - nand_chip->ecc.hwctl = tmio_nand_enable_hwecc; |
|---|
| 419 | | - nand_chip->ecc.calculate = tmio_nand_calculate_ecc; |
|---|
| 420 | | - nand_chip->ecc.correct = tmio_nand_correct_data; |
|---|
| 430 | + nand_chip->legacy.cmd_ctrl = tmio_nand_hwcontrol; |
|---|
| 431 | + nand_chip->legacy.dev_ready = tmio_nand_dev_ready; |
|---|
| 432 | + nand_chip->legacy.read_byte = tmio_nand_read_byte; |
|---|
| 433 | + nand_chip->legacy.write_buf = tmio_nand_write_buf; |
|---|
| 434 | + nand_chip->legacy.read_buf = tmio_nand_read_buf; |
|---|
| 421 | 435 | |
|---|
| 422 | 436 | if (data) |
|---|
| 423 | 437 | nand_chip->badblock_pattern = data->badblock_pattern; |
|---|
| 424 | 438 | |
|---|
| 425 | 439 | /* 15 us command delay time */ |
|---|
| 426 | | - nand_chip->chip_delay = 15; |
|---|
| 440 | + nand_chip->legacy.chip_delay = 15; |
|---|
| 427 | 441 | |
|---|
| 428 | 442 | retval = devm_request_irq(&dev->dev, irq, &tmio_irq, 0, |
|---|
| 429 | 443 | dev_name(&dev->dev), tmio); |
|---|
| .. | .. |
|---|
| 433 | 447 | } |
|---|
| 434 | 448 | |
|---|
| 435 | 449 | tmio->irq = irq; |
|---|
| 436 | | - nand_chip->waitfunc = tmio_nand_wait; |
|---|
| 450 | + nand_chip->legacy.waitfunc = tmio_nand_wait; |
|---|
| 437 | 451 | |
|---|
| 438 | 452 | /* Scan to find existence of the device */ |
|---|
| 439 | 453 | retval = nand_scan(nand_chip, 1); |
|---|
| .. | .. |
|---|
| 459 | 473 | static int tmio_remove(struct platform_device *dev) |
|---|
| 460 | 474 | { |
|---|
| 461 | 475 | struct tmio_nand *tmio = platform_get_drvdata(dev); |
|---|
| 476 | + struct nand_chip *chip = &tmio->chip; |
|---|
| 477 | + int ret; |
|---|
| 462 | 478 | |
|---|
| 463 | | - nand_release(&tmio->chip); |
|---|
| 479 | + ret = mtd_device_unregister(nand_to_mtd(chip)); |
|---|
| 480 | + WARN_ON(ret); |
|---|
| 481 | + nand_cleanup(chip); |
|---|
| 464 | 482 | tmio_hw_stop(dev, tmio); |
|---|
| 465 | 483 | return 0; |
|---|
| 466 | 484 | } |
|---|