diff options
| author | Huang Shijie <b32955@freescale.com> | 2012-05-04 21:42:05 -0400 |
|---|---|---|
| committer | David Woodhouse <David.Woodhouse@intel.com> | 2012-05-14 00:22:19 -0400 |
| commit | e10db1f00a5e3c2ec04d7fe26c7444dc55a59b19 (patch) | |
| tree | 4e92b7759d1a7ab888fa4ed39c81d44a00b89fa1 | |
| parent | 279f08d4ef6548be4e2fa638245adebc77436e54 (diff) | |
mtd: gpmi: add device tree support to gpmi-nand
This patch just adds the DT support to gpmi-nand.
Signed-off-by: Huang Shijie <b32955@freescale.com>
Signed-off-by: Huang Shijie <shijie8@gmail.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
| -rw-r--r-- | Documentation/devicetree/bindings/mtd/gpmi-nand.txt | 33 | ||||
| -rw-r--r-- | drivers/mtd/nand/gpmi-nand/gpmi-lib.c | 7 | ||||
| -rw-r--r-- | drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 126 | ||||
| -rw-r--r-- | drivers/mtd/nand/gpmi-nand/gpmi-nand.h | 4 | ||||
| -rw-r--r-- | include/linux/mtd/gpmi-nand.h | 8 |
5 files changed, 105 insertions, 73 deletions
diff --git a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt new file mode 100644 index 000000000000..1a5bbd346d22 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | * Freescale General-Purpose Media Interface (GPMI) | ||
| 2 | |||
| 3 | The GPMI nand controller provides an interface to control the | ||
| 4 | NAND flash chips. We support only one NAND chip now. | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | - compatible : should be "fsl,<chip>-gpmi-nand" | ||
| 8 | - reg : should contain registers location and length for gpmi and bch. | ||
| 9 | - reg-names: Should contain the reg names "gpmi-nand" and "bch" | ||
| 10 | - interrupts : The first is the DMA interrupt number for GPMI. | ||
| 11 | The second is the BCH interrupt number. | ||
| 12 | - interrupt-names : The interrupt names "gpmi-dma", "bch"; | ||
| 13 | - fsl,gpmi-dma-channel : Should contain the dma channel it uses. | ||
| 14 | |||
| 15 | The device tree may optionally contain sub-nodes describing partitions of the | ||
| 16 | address space. See partition.txt for more detail. | ||
| 17 | |||
| 18 | Examples: | ||
| 19 | |||
| 20 | gpmi-nand@8000c000 { | ||
| 21 | compatible = "fsl,imx28-gpmi-nand"; | ||
| 22 | #address-cells = <1>; | ||
| 23 | #size-cells = <1>; | ||
| 24 | reg = <0x8000c000 2000>, <0x8000a000 2000>; | ||
| 25 | reg-names = "gpmi-nand", "bch"; | ||
| 26 | interrupts = <88>, <41>; | ||
| 27 | interrupt-names = "gpmi-dma", "bch"; | ||
| 28 | fsl,gpmi-dma-channel = <4>; | ||
| 29 | |||
| 30 | partition@0 { | ||
| 31 | ... | ||
| 32 | }; | ||
| 33 | }; | ||
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index fa5200b8c895..5c55c717fe14 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c | |||
| @@ -256,11 +256,12 @@ static unsigned int ns_to_cycles(unsigned int time, | |||
| 256 | return max(k, min); | 256 | return max(k, min); |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | #define DEF_MIN_PROP_DELAY 5 | ||
| 260 | #define DEF_MAX_PROP_DELAY 9 | ||
| 259 | /* Apply timing to current hardware conditions. */ | 261 | /* Apply timing to current hardware conditions. */ |
| 260 | static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this, | 262 | static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this, |
| 261 | struct gpmi_nfc_hardware_timing *hw) | 263 | struct gpmi_nfc_hardware_timing *hw) |
| 262 | { | 264 | { |
| 263 | struct gpmi_nand_platform_data *pdata = this->pdata; | ||
| 264 | struct timing_threshod *nfc = &timing_default_threshold; | 265 | struct timing_threshod *nfc = &timing_default_threshold; |
| 265 | struct nand_chip *nand = &this->nand; | 266 | struct nand_chip *nand = &this->nand; |
| 266 | struct nand_timing target = this->timing; | 267 | struct nand_timing target = this->timing; |
| @@ -277,8 +278,8 @@ static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this, | |||
| 277 | int ideal_sample_delay_in_ns; | 278 | int ideal_sample_delay_in_ns; |
| 278 | unsigned int sample_delay_factor; | 279 | unsigned int sample_delay_factor; |
| 279 | int tEYE; | 280 | int tEYE; |
| 280 | unsigned int min_prop_delay_in_ns = pdata->min_prop_delay_in_ns; | 281 | unsigned int min_prop_delay_in_ns = DEF_MIN_PROP_DELAY; |
| 281 | unsigned int max_prop_delay_in_ns = pdata->max_prop_delay_in_ns; | 282 | unsigned int max_prop_delay_in_ns = DEF_MAX_PROP_DELAY; |
| 282 | 283 | ||
| 283 | /* | 284 | /* |
| 284 | * If there are multiple chips, we need to relax the timings to allow | 285 | * If there are multiple chips, we need to relax the timings to allow |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 7e8a035d444a..d9dc4c874ffa 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c | |||
| @@ -24,6 +24,8 @@ | |||
| 24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 25 | #include <linux/mtd/gpmi-nand.h> | 25 | #include <linux/mtd/gpmi-nand.h> |
| 26 | #include <linux/mtd/partitions.h> | 26 | #include <linux/mtd/partitions.h> |
| 27 | #include <linux/of.h> | ||
| 28 | #include <linux/of_device.h> | ||
| 27 | #include "gpmi-nand.h" | 29 | #include "gpmi-nand.h" |
| 28 | 30 | ||
| 29 | /* add our owner bbt descriptor */ | 31 | /* add our owner bbt descriptor */ |
| @@ -386,7 +388,7 @@ static void release_bch_irq(struct gpmi_nand_data *this) | |||
| 386 | static bool gpmi_dma_filter(struct dma_chan *chan, void *param) | 388 | static bool gpmi_dma_filter(struct dma_chan *chan, void *param) |
| 387 | { | 389 | { |
| 388 | struct gpmi_nand_data *this = param; | 390 | struct gpmi_nand_data *this = param; |
| 389 | struct resource *r = this->private; | 391 | int dma_channel = (int)this->private; |
| 390 | 392 | ||
| 391 | if (!mxs_dma_is_apbh(chan)) | 393 | if (!mxs_dma_is_apbh(chan)) |
| 392 | return false; | 394 | return false; |
| @@ -398,7 +400,7 @@ static bool gpmi_dma_filter(struct dma_chan *chan, void *param) | |||
| 398 | * for mx28 : MX28_DMA_GPMI0 ~ MX28_DMA_GPMI7 | 400 | * for mx28 : MX28_DMA_GPMI0 ~ MX28_DMA_GPMI7 |
| 399 | * (These eight channels share the same IRQ!) | 401 | * (These eight channels share the same IRQ!) |
| 400 | */ | 402 | */ |
| 401 | if (r->start <= chan->chan_id && chan->chan_id <= r->end) { | 403 | if (dma_channel == chan->chan_id) { |
| 402 | chan->private = &this->dma_data; | 404 | chan->private = &this->dma_data; |
| 403 | return true; | 405 | return true; |
| 404 | } | 406 | } |
| @@ -418,57 +420,45 @@ static void release_dma_channels(struct gpmi_nand_data *this) | |||
| 418 | static int __devinit acquire_dma_channels(struct gpmi_nand_data *this) | 420 | static int __devinit acquire_dma_channels(struct gpmi_nand_data *this) |
| 419 | { | 421 | { |
| 420 | struct platform_device *pdev = this->pdev; | 422 | struct platform_device *pdev = this->pdev; |
| 421 | struct gpmi_nand_platform_data *pdata = this->pdata; | 423 | struct resource *r_dma; |
| 422 | struct resources *res = &this->resources; | 424 | struct device_node *dn; |
| 423 | struct resource *r, *r_dma; | 425 | int dma_channel; |
| 424 | unsigned int i; | 426 | unsigned int ret; |
| 427 | struct dma_chan *dma_chan; | ||
| 428 | dma_cap_mask_t mask; | ||
| 429 | |||
| 430 | /* dma channel, we only use the first one. */ | ||
| 431 | dn = pdev->dev.of_node; | ||
| 432 | ret = of_property_read_u32(dn, "fsl,gpmi-dma-channel", &dma_channel); | ||
| 433 | if (ret) { | ||
| 434 | pr_err("unable to get DMA channel from dt.\n"); | ||
| 435 | goto acquire_err; | ||
| 436 | } | ||
| 437 | this->private = (void *)dma_channel; | ||
| 425 | 438 | ||
| 426 | r = platform_get_resource_byname(pdev, IORESOURCE_DMA, | 439 | /* gpmi dma interrupt */ |
| 427 | GPMI_NAND_DMA_CHANNELS_RES_NAME); | ||
| 428 | r_dma = platform_get_resource_byname(pdev, IORESOURCE_IRQ, | 440 | r_dma = platform_get_resource_byname(pdev, IORESOURCE_IRQ, |
| 429 | GPMI_NAND_DMA_INTERRUPT_RES_NAME); | 441 | GPMI_NAND_DMA_INTERRUPT_RES_NAME); |
| 430 | if (!r || !r_dma) { | 442 | if (!r_dma) { |
| 431 | pr_err("Can't get resource for DMA\n"); | 443 | pr_err("Can't get resource for DMA\n"); |
| 432 | return -ENXIO; | 444 | goto acquire_err; |
| 433 | } | 445 | } |
| 446 | this->dma_data.chan_irq = r_dma->start; | ||
| 434 | 447 | ||
| 435 | /* used in gpmi_dma_filter() */ | 448 | /* request dma channel */ |
| 436 | this->private = r; | 449 | dma_cap_zero(mask); |
| 437 | 450 | dma_cap_set(DMA_SLAVE, mask); | |
| 438 | for (i = r->start; i <= r->end; i++) { | ||
| 439 | struct dma_chan *dma_chan; | ||
| 440 | dma_cap_mask_t mask; | ||
| 441 | 451 | ||
| 442 | if (i - r->start >= pdata->max_chip_count) | 452 | dma_chan = dma_request_channel(mask, gpmi_dma_filter, this); |
| 443 | break; | 453 | if (!dma_chan) { |
| 444 | 454 | pr_err("dma_request_channel failed.\n"); | |
| 445 | dma_cap_zero(mask); | 455 | goto acquire_err; |
| 446 | dma_cap_set(DMA_SLAVE, mask); | ||
| 447 | |||
| 448 | /* get the DMA interrupt */ | ||
| 449 | if (r_dma->start == r_dma->end) { | ||
| 450 | /* only register the first. */ | ||
| 451 | if (i == r->start) | ||
| 452 | this->dma_data.chan_irq = r_dma->start; | ||
| 453 | else | ||
| 454 | this->dma_data.chan_irq = NO_IRQ; | ||
| 455 | } else | ||
| 456 | this->dma_data.chan_irq = r_dma->start + (i - r->start); | ||
| 457 | |||
| 458 | dma_chan = dma_request_channel(mask, gpmi_dma_filter, this); | ||
| 459 | if (!dma_chan) | ||
| 460 | goto acquire_err; | ||
| 461 | |||
| 462 | /* fill the first empty item */ | ||
| 463 | this->dma_chans[i - r->start] = dma_chan; | ||
| 464 | } | 456 | } |
| 465 | 457 | ||
| 466 | res->dma_low_channel = r->start; | 458 | this->dma_chans[0] = dma_chan; |
| 467 | res->dma_high_channel = i; | ||
| 468 | return 0; | 459 | return 0; |
| 469 | 460 | ||
| 470 | acquire_err: | 461 | acquire_err: |
| 471 | pr_err("Can't acquire DMA channel %u\n", i); | ||
| 472 | release_dma_channels(this); | 462 | release_dma_channels(this); |
| 473 | return -EINVAL; | 463 | return -EINVAL; |
| 474 | } | 464 | } |
| @@ -1465,9 +1455,9 @@ void gpmi_nfc_exit(struct gpmi_nand_data *this) | |||
| 1465 | 1455 | ||
| 1466 | static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) | 1456 | static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) |
| 1467 | { | 1457 | { |
| 1468 | struct gpmi_nand_platform_data *pdata = this->pdata; | ||
| 1469 | struct mtd_info *mtd = &this->mtd; | 1458 | struct mtd_info *mtd = &this->mtd; |
| 1470 | struct nand_chip *chip = &this->nand; | 1459 | struct nand_chip *chip = &this->nand; |
| 1460 | struct mtd_part_parser_data ppdata = {}; | ||
| 1471 | int ret; | 1461 | int ret; |
| 1472 | 1462 | ||
| 1473 | /* init current chip */ | 1463 | /* init current chip */ |
| @@ -1505,14 +1495,14 @@ static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) | |||
| 1505 | if (ret) | 1495 | if (ret) |
| 1506 | goto err_out; | 1496 | goto err_out; |
| 1507 | 1497 | ||
| 1508 | ret = nand_scan(mtd, pdata->max_chip_count); | 1498 | ret = nand_scan(mtd, 1); |
| 1509 | if (ret) { | 1499 | if (ret) { |
| 1510 | pr_err("Chip scan failed\n"); | 1500 | pr_err("Chip scan failed\n"); |
| 1511 | goto err_out; | 1501 | goto err_out; |
| 1512 | } | 1502 | } |
| 1513 | 1503 | ||
| 1514 | ret = mtd_device_parse_register(mtd, NULL, NULL, | 1504 | ppdata.of_node = this->pdev->dev.of_node; |
| 1515 | pdata->partitions, pdata->partition_count); | 1505 | ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); |
| 1516 | if (ret) | 1506 | if (ret) |
| 1517 | goto err_out; | 1507 | goto err_out; |
| 1518 | return 0; | 1508 | return 0; |
| @@ -1522,12 +1512,37 @@ err_out: | |||
| 1522 | return ret; | 1512 | return ret; |
| 1523 | } | 1513 | } |
| 1524 | 1514 | ||
| 1515 | static const struct platform_device_id gpmi_ids[] = { | ||
| 1516 | { .name = "imx23-gpmi-nand", .driver_data = IS_MX23, }, | ||
| 1517 | { .name = "imx28-gpmi-nand", .driver_data = IS_MX28, }, | ||
| 1518 | {}, | ||
| 1519 | }; | ||
| 1520 | |||
| 1521 | static const struct of_device_id gpmi_nand_id_table[] = { | ||
| 1522 | { | ||
| 1523 | .compatible = "fsl,imx23-gpmi-nand", | ||
| 1524 | .data = (void *)&gpmi_ids[IS_MX23] | ||
| 1525 | }, { | ||
| 1526 | .compatible = "fsl,imx28-gpmi-nand", | ||
| 1527 | .data = (void *)&gpmi_ids[IS_MX28] | ||
| 1528 | }, {} | ||
| 1529 | }; | ||
| 1530 | MODULE_DEVICE_TABLE(of, gpmi_nand_id_table); | ||
| 1531 | |||
| 1525 | static int __devinit gpmi_nand_probe(struct platform_device *pdev) | 1532 | static int __devinit gpmi_nand_probe(struct platform_device *pdev) |
| 1526 | { | 1533 | { |
| 1527 | struct gpmi_nand_platform_data *pdata = pdev->dev.platform_data; | ||
| 1528 | struct gpmi_nand_data *this; | 1534 | struct gpmi_nand_data *this; |
| 1535 | const struct of_device_id *of_id; | ||
| 1529 | int ret; | 1536 | int ret; |
| 1530 | 1537 | ||
| 1538 | of_id = of_match_device(gpmi_nand_id_table, &pdev->dev); | ||
| 1539 | if (of_id) { | ||
| 1540 | pdev->id_entry = of_id->data; | ||
| 1541 | } else { | ||
| 1542 | pr_err("Failed to find the right device id.\n"); | ||
| 1543 | return -ENOMEM; | ||
| 1544 | } | ||
| 1545 | |||
| 1531 | this = kzalloc(sizeof(*this), GFP_KERNEL); | 1546 | this = kzalloc(sizeof(*this), GFP_KERNEL); |
| 1532 | if (!this) { | 1547 | if (!this) { |
| 1533 | pr_err("Failed to allocate per-device memory\n"); | 1548 | pr_err("Failed to allocate per-device memory\n"); |
| @@ -1537,13 +1552,6 @@ static int __devinit gpmi_nand_probe(struct platform_device *pdev) | |||
| 1537 | platform_set_drvdata(pdev, this); | 1552 | platform_set_drvdata(pdev, this); |
| 1538 | this->pdev = pdev; | 1553 | this->pdev = pdev; |
| 1539 | this->dev = &pdev->dev; | 1554 | this->dev = &pdev->dev; |
| 1540 | this->pdata = pdata; | ||
| 1541 | |||
| 1542 | if (pdata->platform_init) { | ||
| 1543 | ret = pdata->platform_init(); | ||
| 1544 | if (ret) | ||
| 1545 | goto platform_init_error; | ||
| 1546 | } | ||
| 1547 | 1555 | ||
| 1548 | ret = acquire_resources(this); | 1556 | ret = acquire_resources(this); |
| 1549 | if (ret) | 1557 | if (ret) |
| @@ -1561,7 +1569,6 @@ static int __devinit gpmi_nand_probe(struct platform_device *pdev) | |||
| 1561 | 1569 | ||
| 1562 | exit_nfc_init: | 1570 | exit_nfc_init: |
| 1563 | release_resources(this); | 1571 | release_resources(this); |
| 1564 | platform_init_error: | ||
| 1565 | exit_acquire_resources: | 1572 | exit_acquire_resources: |
| 1566 | platform_set_drvdata(pdev, NULL); | 1573 | platform_set_drvdata(pdev, NULL); |
| 1567 | kfree(this); | 1574 | kfree(this); |
| @@ -1579,19 +1586,10 @@ static int __exit gpmi_nand_remove(struct platform_device *pdev) | |||
| 1579 | return 0; | 1586 | return 0; |
| 1580 | } | 1587 | } |
| 1581 | 1588 | ||
| 1582 | static const struct platform_device_id gpmi_ids[] = { | ||
| 1583 | { | ||
| 1584 | .name = "imx23-gpmi-nand", | ||
| 1585 | .driver_data = IS_MX23, | ||
| 1586 | }, { | ||
| 1587 | .name = "imx28-gpmi-nand", | ||
| 1588 | .driver_data = IS_MX28, | ||
| 1589 | }, {}, | ||
| 1590 | }; | ||
| 1591 | |||
| 1592 | static struct platform_driver gpmi_nand_driver = { | 1589 | static struct platform_driver gpmi_nand_driver = { |
| 1593 | .driver = { | 1590 | .driver = { |
| 1594 | .name = "gpmi-nand", | 1591 | .name = "gpmi-nand", |
| 1592 | .of_match_table = gpmi_nand_id_table, | ||
| 1595 | }, | 1593 | }, |
| 1596 | .probe = gpmi_nand_probe, | 1594 | .probe = gpmi_nand_probe, |
| 1597 | .remove = __exit_p(gpmi_nand_remove), | 1595 | .remove = __exit_p(gpmi_nand_remove), |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h index ec6180d4ff8f..12fdd7767c1c 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h | |||
| @@ -266,8 +266,8 @@ extern int gpmi_read_page(struct gpmi_nand_data *, | |||
| 266 | #define STATUS_UNCORRECTABLE 0xfe | 266 | #define STATUS_UNCORRECTABLE 0xfe |
| 267 | 267 | ||
| 268 | /* Use the platform_id to distinguish different Archs. */ | 268 | /* Use the platform_id to distinguish different Archs. */ |
| 269 | #define IS_MX23 0x1 | 269 | #define IS_MX23 0x0 |
| 270 | #define IS_MX28 0x2 | 270 | #define IS_MX28 0x1 |
| 271 | #define GPMI_IS_MX23(x) ((x)->pdev->id_entry->driver_data == IS_MX23) | 271 | #define GPMI_IS_MX23(x) ((x)->pdev->id_entry->driver_data == IS_MX23) |
| 272 | #define GPMI_IS_MX28(x) ((x)->pdev->id_entry->driver_data == IS_MX28) | 272 | #define GPMI_IS_MX28(x) ((x)->pdev->id_entry->driver_data == IS_MX28) |
| 273 | #endif | 273 | #endif |
diff --git a/include/linux/mtd/gpmi-nand.h b/include/linux/mtd/gpmi-nand.h index 69b6dbf46b5e..ed3c4e09f3d1 100644 --- a/include/linux/mtd/gpmi-nand.h +++ b/include/linux/mtd/gpmi-nand.h | |||
| @@ -23,12 +23,12 @@ | |||
| 23 | #define GPMI_NAND_RES_SIZE 6 | 23 | #define GPMI_NAND_RES_SIZE 6 |
| 24 | 24 | ||
| 25 | /* Resource names for the GPMI NAND driver. */ | 25 | /* Resource names for the GPMI NAND driver. */ |
| 26 | #define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME "GPMI NAND GPMI Registers" | 26 | #define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME "gpmi-nand" |
| 27 | #define GPMI_NAND_GPMI_INTERRUPT_RES_NAME "GPMI NAND GPMI Interrupt" | 27 | #define GPMI_NAND_GPMI_INTERRUPT_RES_NAME "GPMI NAND GPMI Interrupt" |
| 28 | #define GPMI_NAND_BCH_REGS_ADDR_RES_NAME "GPMI NAND BCH Registers" | 28 | #define GPMI_NAND_BCH_REGS_ADDR_RES_NAME "bch" |
| 29 | #define GPMI_NAND_BCH_INTERRUPT_RES_NAME "GPMI NAND BCH Interrupt" | 29 | #define GPMI_NAND_BCH_INTERRUPT_RES_NAME "bch" |
| 30 | #define GPMI_NAND_DMA_CHANNELS_RES_NAME "GPMI NAND DMA Channels" | 30 | #define GPMI_NAND_DMA_CHANNELS_RES_NAME "GPMI NAND DMA Channels" |
| 31 | #define GPMI_NAND_DMA_INTERRUPT_RES_NAME "GPMI NAND DMA Interrupt" | 31 | #define GPMI_NAND_DMA_INTERRUPT_RES_NAME "gpmi-dma" |
| 32 | 32 | ||
| 33 | /** | 33 | /** |
| 34 | * struct gpmi_nand_platform_data - GPMI NAND driver platform data. | 34 | * struct gpmi_nand_platform_data - GPMI NAND driver platform data. |
