Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: driver for the TMIO NAND controller

This patch adds support for the NAND controller commonly found in
TMIO based MFDs.

Signed-off-by: Ian Molton <spyro@f2s.com>
Acked-By: David Woodhouse <David.Woodhouse@intel.com>
Signed-off-by: Samuel Ortiz <sameo@openedhand.com>

authored by

Ian Molton and committed by
Samuel Ortiz
ec43b816 8a4fbe01

+564
+7
drivers/mtd/nand/Kconfig
··· 351 351 Enables support for NAND Flash interface on PA Semi PWRficient 352 352 based boards 353 353 354 + config MTD_NAND_TMIO 355 + tristate "NAND Flash device on Toshiba Mobile IO Controller" 356 + depends on MTD_NAND && MFD_CORE 357 + help 358 + Support for NAND flash connected to a Toshiba Mobile IO 359 + Controller in some PDAs, including the Sharp SL6000x. 360 + 354 361 config MTD_NAND_NANDSIM 355 362 tristate "Support for NAND Flash Simulator" 356 363 depends on MTD_PARTITIONS
+1
drivers/mtd/nand/Makefile
··· 27 27 obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o 28 28 obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o 29 29 obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o 30 + obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o 30 31 obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o 31 32 obj-$(CONFIG_MTD_ALAUDA) += alauda.o 32 33 obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o
+556
drivers/mtd/nand/tmio_nand.c
··· 1 + /* 2 + * Toshiba TMIO NAND flash controller driver 3 + * 4 + * Slightly murky pre-git history of the driver: 5 + * 6 + * Copyright (c) Ian Molton 2004, 2005, 2008 7 + * Original work, independant of sharps code. Included hardware ECC support. 8 + * Hard ECC did not work for writes in the early revisions. 9 + * Copyright (c) Dirk Opfer 2005. 10 + * Modifications developed from sharps code but 11 + * NOT containing any, ported onto Ians base. 12 + * Copyright (c) Chris Humbert 2005 13 + * Copyright (c) Dmitry Baryshkov 2008 14 + * Minor fixes 15 + * 16 + * Parts copyright Sebastian Carlier 17 + * 18 + * This file is licensed under 19 + * the terms of the GNU General Public License version 2. This program 20 + * is licensed "as is" without any warranty of any kind, whether express 21 + * or implied. 22 + * 23 + */ 24 + 25 + 26 + #include <linux/kernel.h> 27 + #include <linux/module.h> 28 + #include <linux/platform_device.h> 29 + #include <linux/mfd/core.h> 30 + #include <linux/mfd/tmio.h> 31 + #include <linux/delay.h> 32 + #include <linux/io.h> 33 + #include <linux/irq.h> 34 + #include <linux/interrupt.h> 35 + #include <linux/ioport.h> 36 + #include <linux/mtd/mtd.h> 37 + #include <linux/mtd/nand.h> 38 + #include <linux/mtd/nand_ecc.h> 39 + #include <linux/mtd/partitions.h> 40 + 41 + /*--------------------------------------------------------------------------*/ 42 + 43 + /* 44 + * NAND Flash Host Controller Configuration Register 45 + */ 46 + #define CCR_COMMAND 0x04 /* w Command */ 47 + #define CCR_BASE 0x10 /* l NAND Flash Control Reg Base Addr */ 48 + #define CCR_INTP 0x3d /* b Interrupt Pin */ 49 + #define CCR_INTE 0x48 /* b Interrupt Enable */ 50 + #define CCR_EC 0x4a /* b Event Control */ 51 + #define CCR_ICC 0x4c /* b Internal Clock Control */ 52 + #define CCR_ECCC 0x5b /* b ECC Control */ 53 + #define CCR_NFTC 0x60 /* b NAND Flash Transaction Control */ 54 + #define CCR_NFM 0x61 /* b NAND Flash Monitor */ 55 + #define CCR_NFPSC 0x62 /* b NAND Flash Power Supply Control */ 56 + #define CCR_NFDC 0x63 /* b NAND Flash Detect Control */ 57 + 58 + /* 59 + * NAND Flash Control Register 60 + */ 61 + #define FCR_DATA 0x00 /* bwl Data Register */ 62 + #define FCR_MODE 0x04 /* b Mode Register */ 63 + #define FCR_STATUS 0x05 /* b Status Register */ 64 + #define FCR_ISR 0x06 /* b Interrupt Status Register */ 65 + #define FCR_IMR 0x07 /* b Interrupt Mask Register */ 66 + 67 + /* FCR_MODE Register Command List */ 68 + #define FCR_MODE_DATA 0x94 /* Data Data_Mode */ 69 + #define FCR_MODE_COMMAND 0x95 /* Data Command_Mode */ 70 + #define FCR_MODE_ADDRESS 0x96 /* Data Address_Mode */ 71 + 72 + #define FCR_MODE_HWECC_CALC 0xB4 /* HW-ECC Data */ 73 + #define FCR_MODE_HWECC_RESULT 0xD4 /* HW-ECC Calc result Read_Mode */ 74 + #define FCR_MODE_HWECC_RESET 0xF4 /* HW-ECC Reset */ 75 + 76 + #define FCR_MODE_POWER_ON 0x0C /* Power Supply ON to SSFDC card */ 77 + #define FCR_MODE_POWER_OFF 0x08 /* Power Supply OFF to SSFDC card */ 78 + 79 + #define FCR_MODE_LED_OFF 0x00 /* LED OFF */ 80 + #define FCR_MODE_LED_ON 0x04 /* LED ON */ 81 + 82 + #define FCR_MODE_EJECT_ON 0x68 /* Ejection events active */ 83 + #define FCR_MODE_EJECT_OFF 0x08 /* Ejection events ignored */ 84 + 85 + #define FCR_MODE_LOCK 0x6C /* Lock_Mode. Eject Switch Invalid */ 86 + #define FCR_MODE_UNLOCK 0x0C /* UnLock_Mode. Eject Switch is valid */ 87 + 88 + #define FCR_MODE_CONTROLLER_ID 0x40 /* Controller ID Read */ 89 + #define FCR_MODE_STANDBY 0x00 /* SSFDC card Changes Standby State */ 90 + 91 + #define FCR_MODE_WE 0x80 92 + #define FCR_MODE_ECC1 0x40 93 + #define FCR_MODE_ECC0 0x20 94 + #define FCR_MODE_CE 0x10 95 + #define FCR_MODE_PCNT1 0x08 96 + #define FCR_MODE_PCNT0 0x04 97 + #define FCR_MODE_ALE 0x02 98 + #define FCR_MODE_CLE 0x01 99 + 100 + #define FCR_STATUS_BUSY 0x80 101 + 102 + /*--------------------------------------------------------------------------*/ 103 + 104 + struct tmio_nand { 105 + struct mtd_info mtd; 106 + struct nand_chip chip; 107 + 108 + struct platform_device *dev; 109 + 110 + void __iomem *ccr; 111 + void __iomem *fcr; 112 + unsigned long fcr_phys; 113 + 114 + unsigned int irq; 115 + 116 + /* for tmio_nand_read_byte */ 117 + u8 read; 118 + unsigned read_good:1; 119 + }; 120 + 121 + #define mtd_to_tmio(m) container_of(m, struct tmio_nand, mtd) 122 + 123 + #ifdef CONFIG_MTD_CMDLINE_PARTS 124 + static const char *part_probes[] = { "cmdlinepart", NULL }; 125 + #endif 126 + 127 + /*--------------------------------------------------------------------------*/ 128 + 129 + static void tmio_nand_hwcontrol(struct mtd_info *mtd, int cmd, 130 + unsigned int ctrl) 131 + { 132 + struct tmio_nand *tmio = mtd_to_tmio(mtd); 133 + struct nand_chip *chip = mtd->priv; 134 + 135 + if (ctrl & NAND_CTRL_CHANGE) { 136 + u8 mode; 137 + 138 + if (ctrl & NAND_NCE) { 139 + mode = FCR_MODE_DATA; 140 + 141 + if (ctrl & NAND_CLE) 142 + mode |= FCR_MODE_CLE; 143 + else 144 + mode &= ~FCR_MODE_CLE; 145 + 146 + if (ctrl & NAND_ALE) 147 + mode |= FCR_MODE_ALE; 148 + else 149 + mode &= ~FCR_MODE_ALE; 150 + } else { 151 + mode = FCR_MODE_STANDBY; 152 + } 153 + 154 + tmio_iowrite8(mode, tmio->fcr + FCR_MODE); 155 + tmio->read_good = 0; 156 + } 157 + 158 + if (cmd != NAND_CMD_NONE) 159 + tmio_iowrite8(cmd, chip->IO_ADDR_W); 160 + } 161 + 162 + static int tmio_nand_dev_ready(struct mtd_info *mtd) 163 + { 164 + struct tmio_nand *tmio = mtd_to_tmio(mtd); 165 + 166 + return !(tmio_ioread8(tmio->fcr + FCR_STATUS) & FCR_STATUS_BUSY); 167 + } 168 + 169 + static irqreturn_t tmio_irq(int irq, void *__tmio) 170 + { 171 + struct tmio_nand *tmio = __tmio; 172 + struct nand_chip *nand_chip = &tmio->chip; 173 + 174 + /* disable RDYREQ interrupt */ 175 + tmio_iowrite8(0x00, tmio->fcr + FCR_IMR); 176 + 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 + return IRQ_HANDLED; 182 + } 183 + 184 + /* 185 + *The TMIO core has a RDYREQ interrupt on the posedge of #SMRB. 186 + *This interrupt is normally disabled, but for long operations like 187 + *erase and write, we enable it to wake us up. The irq handler 188 + *disables the interrupt. 189 + */ 190 + static int 191 + tmio_nand_wait(struct mtd_info *mtd, struct nand_chip *nand_chip) 192 + { 193 + struct tmio_nand *tmio = mtd_to_tmio(mtd); 194 + long timeout; 195 + 196 + /* enable RDYREQ interrupt */ 197 + tmio_iowrite8(0x0f, tmio->fcr + FCR_ISR); 198 + tmio_iowrite8(0x81, tmio->fcr + FCR_IMR); 199 + 200 + timeout = wait_event_timeout(nand_chip->controller->wq, 201 + tmio_nand_dev_ready(mtd), 202 + msecs_to_jiffies(nand_chip->state == FL_ERASING ? 400 : 20)); 203 + 204 + if (unlikely(!tmio_nand_dev_ready(mtd))) { 205 + tmio_iowrite8(0x00, tmio->fcr + FCR_IMR); 206 + dev_warn(&tmio->dev->dev, "still busy with %s after %d ms\n", 207 + nand_chip->state == FL_ERASING ? "erase" : "program", 208 + nand_chip->state == FL_ERASING ? 400 : 20); 209 + 210 + } else if (unlikely(!timeout)) { 211 + tmio_iowrite8(0x00, tmio->fcr + FCR_IMR); 212 + dev_warn(&tmio->dev->dev, "timeout waiting for interrupt\n"); 213 + } 214 + 215 + nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); 216 + return nand_chip->read_byte(mtd); 217 + } 218 + 219 + /* 220 + *The TMIO controller combines two 8-bit data bytes into one 16-bit 221 + *word. This function separates them so nand_base.c works as expected, 222 + *especially its NAND_CMD_READID routines. 223 + * 224 + *To prevent stale data from being read, tmio_nand_hwcontrol() clears 225 + *tmio->read_good. 226 + */ 227 + static u_char tmio_nand_read_byte(struct mtd_info *mtd) 228 + { 229 + struct tmio_nand *tmio = mtd_to_tmio(mtd); 230 + unsigned int data; 231 + 232 + if (tmio->read_good--) 233 + return tmio->read; 234 + 235 + data = tmio_ioread16(tmio->fcr + FCR_DATA); 236 + tmio->read = data >> 8; 237 + return data; 238 + } 239 + 240 + /* 241 + *The TMIO controller converts an 8-bit NAND interface to a 16-bit 242 + *bus interface, so all data reads and writes must be 16-bit wide. 243 + *Thus, we implement 16-bit versions of the read, write, and verify 244 + *buffer functions. 245 + */ 246 + static void 247 + tmio_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) 248 + { 249 + struct tmio_nand *tmio = mtd_to_tmio(mtd); 250 + 251 + tmio_iowrite16_rep(tmio->fcr + FCR_DATA, buf, len >> 1); 252 + } 253 + 254 + static void tmio_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) 255 + { 256 + struct tmio_nand *tmio = mtd_to_tmio(mtd); 257 + 258 + tmio_ioread16_rep(tmio->fcr + FCR_DATA, buf, len >> 1); 259 + } 260 + 261 + static int 262 + tmio_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) 263 + { 264 + struct tmio_nand *tmio = mtd_to_tmio(mtd); 265 + u16 *p = (u16 *) buf; 266 + 267 + for (len >>= 1; len; len--) 268 + if (*(p++) != tmio_ioread16(tmio->fcr + FCR_DATA)) 269 + return -EFAULT; 270 + return 0; 271 + } 272 + 273 + static void tmio_nand_enable_hwecc(struct mtd_info *mtd, int mode) 274 + { 275 + struct tmio_nand *tmio = mtd_to_tmio(mtd); 276 + 277 + tmio_iowrite8(FCR_MODE_HWECC_RESET, tmio->fcr + FCR_MODE); 278 + tmio_ioread8(tmio->fcr + FCR_DATA); /* dummy read */ 279 + tmio_iowrite8(FCR_MODE_HWECC_CALC, tmio->fcr + FCR_MODE); 280 + } 281 + 282 + static int tmio_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, 283 + u_char *ecc_code) 284 + { 285 + struct tmio_nand *tmio = mtd_to_tmio(mtd); 286 + unsigned int ecc; 287 + 288 + tmio_iowrite8(FCR_MODE_HWECC_RESULT, tmio->fcr + FCR_MODE); 289 + 290 + ecc = tmio_ioread16(tmio->fcr + FCR_DATA); 291 + ecc_code[1] = ecc; /* 000-255 LP7-0 */ 292 + ecc_code[0] = ecc >> 8; /* 000-255 LP15-8 */ 293 + ecc = tmio_ioread16(tmio->fcr + FCR_DATA); 294 + ecc_code[2] = ecc; /* 000-255 CP5-0,11b */ 295 + ecc_code[4] = ecc >> 8; /* 256-511 LP7-0 */ 296 + ecc = tmio_ioread16(tmio->fcr + FCR_DATA); 297 + ecc_code[3] = ecc; /* 256-511 LP15-8 */ 298 + ecc_code[5] = ecc >> 8; /* 256-511 CP5-0,11b */ 299 + 300 + tmio_iowrite8(FCR_MODE_DATA, tmio->fcr + FCR_MODE); 301 + return 0; 302 + } 303 + 304 + static int tmio_hw_init(struct platform_device *dev, struct tmio_nand *tmio) 305 + { 306 + struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; 307 + int ret; 308 + 309 + if (cell->enable) { 310 + ret = cell->enable(dev); 311 + if (ret) 312 + return ret; 313 + } 314 + 315 + /* (4Ch) CLKRUN Enable 1st spcrunc */ 316 + tmio_iowrite8(0x81, tmio->ccr + CCR_ICC); 317 + 318 + /* (10h)BaseAddress 0x1000 spba.spba2 */ 319 + tmio_iowrite16(tmio->fcr_phys, tmio->ccr + CCR_BASE); 320 + tmio_iowrite16(tmio->fcr_phys >> 16, tmio->ccr + CCR_BASE + 16); 321 + 322 + /* (04h)Command Register I/O spcmd */ 323 + tmio_iowrite8(0x02, tmio->ccr + CCR_COMMAND); 324 + 325 + /* (62h) Power Supply Control ssmpwc */ 326 + /* HardPowerOFF - SuspendOFF - PowerSupplyWait_4MS */ 327 + tmio_iowrite8(0x02, tmio->ccr + CCR_NFPSC); 328 + 329 + /* (63h) Detect Control ssmdtc */ 330 + tmio_iowrite8(0x02, tmio->ccr + CCR_NFDC); 331 + 332 + /* Interrupt status register clear sintst */ 333 + tmio_iowrite8(0x0f, tmio->fcr + FCR_ISR); 334 + 335 + /* After power supply, Media are reset smode */ 336 + tmio_iowrite8(FCR_MODE_POWER_ON, tmio->fcr + FCR_MODE); 337 + tmio_iowrite8(FCR_MODE_COMMAND, tmio->fcr + FCR_MODE); 338 + tmio_iowrite8(NAND_CMD_RESET, tmio->fcr + FCR_DATA); 339 + 340 + /* Standby Mode smode */ 341 + tmio_iowrite8(FCR_MODE_STANDBY, tmio->fcr + FCR_MODE); 342 + 343 + mdelay(5); 344 + 345 + return 0; 346 + } 347 + 348 + static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio) 349 + { 350 + struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; 351 + 352 + tmio_iowrite8(FCR_MODE_POWER_OFF, tmio->fcr + FCR_MODE); 353 + if (cell->disable) 354 + cell->disable(dev); 355 + } 356 + 357 + static int tmio_probe(struct platform_device *dev) 358 + { 359 + struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; 360 + struct tmio_nand_data *data = cell->driver_data; 361 + struct resource *fcr = platform_get_resource(dev, 362 + IORESOURCE_MEM, 0); 363 + struct resource *ccr = platform_get_resource(dev, 364 + IORESOURCE_MEM, 1); 365 + int irq = platform_get_irq(dev, 0); 366 + struct tmio_nand *tmio; 367 + struct mtd_info *mtd; 368 + struct nand_chip *nand_chip; 369 + #ifdef CONFIG_MTD_PARTITIONS 370 + struct mtd_partition *parts; 371 + int nbparts = 0; 372 + #endif 373 + int retval; 374 + 375 + if (data == NULL) 376 + dev_warn(&dev->dev, "NULL platform data!\n"); 377 + 378 + tmio = kzalloc(sizeof *tmio, GFP_KERNEL); 379 + if (!tmio) { 380 + retval = -ENOMEM; 381 + goto err_kzalloc; 382 + } 383 + 384 + tmio->dev = dev; 385 + 386 + platform_set_drvdata(dev, tmio); 387 + mtd = &tmio->mtd; 388 + nand_chip = &tmio->chip; 389 + mtd->priv = nand_chip; 390 + mtd->name = "tmio-nand"; 391 + 392 + tmio->ccr = ioremap(ccr->start, ccr->end - ccr->start + 1); 393 + if (!tmio->ccr) { 394 + retval = -EIO; 395 + goto err_iomap_ccr; 396 + } 397 + 398 + tmio->fcr_phys = (unsigned long)fcr->start; 399 + tmio->fcr = ioremap(fcr->start, fcr->end - fcr->start + 1); 400 + if (!tmio->fcr) { 401 + retval = -EIO; 402 + goto err_iomap_fcr; 403 + } 404 + 405 + retval = tmio_hw_init(dev, tmio); 406 + if (retval) 407 + goto err_hwinit; 408 + 409 + /* Set address of NAND IO lines */ 410 + nand_chip->IO_ADDR_R = tmio->fcr; 411 + nand_chip->IO_ADDR_W = tmio->fcr; 412 + 413 + /* Set address of hardware control function */ 414 + nand_chip->cmd_ctrl = tmio_nand_hwcontrol; 415 + nand_chip->dev_ready = tmio_nand_dev_ready; 416 + nand_chip->read_byte = tmio_nand_read_byte; 417 + nand_chip->write_buf = tmio_nand_write_buf; 418 + nand_chip->read_buf = tmio_nand_read_buf; 419 + nand_chip->verify_buf = tmio_nand_verify_buf; 420 + 421 + /* set eccmode using hardware ECC */ 422 + nand_chip->ecc.mode = NAND_ECC_HW; 423 + nand_chip->ecc.size = 512; 424 + nand_chip->ecc.bytes = 6; 425 + nand_chip->ecc.hwctl = tmio_nand_enable_hwecc; 426 + nand_chip->ecc.calculate = tmio_nand_calculate_ecc; 427 + nand_chip->ecc.correct = nand_correct_data; 428 + 429 + if (data) 430 + nand_chip->badblock_pattern = data->badblock_pattern; 431 + 432 + /* 15 us command delay time */ 433 + nand_chip->chip_delay = 15; 434 + 435 + retval = request_irq(irq, &tmio_irq, 436 + IRQF_DISABLED, dev->dev.bus_id, tmio); 437 + if (retval) { 438 + dev_err(&dev->dev, "request_irq error %d\n", retval); 439 + goto err_irq; 440 + } 441 + 442 + tmio->irq = irq; 443 + nand_chip->waitfunc = tmio_nand_wait; 444 + 445 + /* Scan to find existence of the device */ 446 + if (nand_scan(mtd, 1)) { 447 + retval = -ENODEV; 448 + goto err_scan; 449 + } 450 + /* Register the partitions */ 451 + #ifdef CONFIG_MTD_PARTITIONS 452 + #ifdef CONFIG_MTD_CMDLINE_PARTS 453 + nbparts = parse_mtd_partitions(mtd, part_probes, &parts, 0); 454 + #endif 455 + if (nbparts <= 0 && data) { 456 + parts = data->partition; 457 + nbparts = data->num_partitions; 458 + } 459 + 460 + if (nbparts) 461 + retval = add_mtd_partitions(mtd, parts, nbparts); 462 + else 463 + #endif 464 + retval = add_mtd_device(mtd); 465 + 466 + if (!retval) 467 + return retval; 468 + 469 + nand_release(mtd); 470 + 471 + err_scan: 472 + if (tmio->irq) 473 + free_irq(tmio->irq, tmio); 474 + err_irq: 475 + tmio_hw_stop(dev, tmio); 476 + err_hwinit: 477 + iounmap(tmio->fcr); 478 + err_iomap_fcr: 479 + iounmap(tmio->ccr); 480 + err_iomap_ccr: 481 + kfree(tmio); 482 + err_kzalloc: 483 + return retval; 484 + } 485 + 486 + static int tmio_remove(struct platform_device *dev) 487 + { 488 + struct tmio_nand *tmio = platform_get_drvdata(dev); 489 + 490 + nand_release(&tmio->mtd); 491 + if (tmio->irq) 492 + free_irq(tmio->irq, tmio); 493 + tmio_hw_stop(dev, tmio); 494 + iounmap(tmio->fcr); 495 + iounmap(tmio->ccr); 496 + kfree(tmio); 497 + return 0; 498 + } 499 + 500 + #ifdef CONFIG_PM 501 + static int tmio_suspend(struct platform_device *dev, pm_message_t state) 502 + { 503 + struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; 504 + 505 + if (cell->suspend) 506 + cell->suspend(dev); 507 + 508 + tmio_hw_stop(dev, platform_get_drvdata(dev)); 509 + return 0; 510 + } 511 + 512 + static int tmio_resume(struct platform_device *dev) 513 + { 514 + struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; 515 + 516 + /* FIXME - is this required or merely another attack of the broken 517 + * SHARP platform? Looks suspicious. 518 + */ 519 + tmio_hw_init(dev, platform_get_drvdata(dev)); 520 + 521 + if (cell->resume) 522 + cell->resume(dev); 523 + 524 + return 0; 525 + } 526 + #else 527 + #define tmio_suspend NULL 528 + #define tmio_resume NULL 529 + #endif 530 + 531 + static struct platform_driver tmio_driver = { 532 + .driver.name = "tmio-nand", 533 + .driver.owner = THIS_MODULE, 534 + .probe = tmio_probe, 535 + .remove = tmio_remove, 536 + .suspend = tmio_suspend, 537 + .resume = tmio_resume, 538 + }; 539 + 540 + static int __init tmio_init(void) 541 + { 542 + return platform_driver_register(&tmio_driver); 543 + } 544 + 545 + static void __exit tmio_exit(void) 546 + { 547 + platform_driver_unregister(&tmio_driver); 548 + } 549 + 550 + module_init(tmio_init); 551 + module_exit(tmio_exit); 552 + 553 + MODULE_LICENSE("GPL v2"); 554 + MODULE_AUTHOR("Ian Molton, Dirk Opfer, Chris Humbert, Dmitry Baryshkov"); 555 + MODULE_DESCRIPTION("NAND flash driver on Toshiba Mobile IO controller"); 556 + MODULE_ALIAS("platform:tmio-nand");