diff options
| -rw-r--r-- | arch/arm/mach-omap2/gpmc.c | 275 | ||||
| -rw-r--r-- | arch/arm/plat-omap/include/plat/gpmc.h | 39 | ||||
| -rw-r--r-- | drivers/mtd/nand/omap2.c | 4 |
3 files changed, 301 insertions, 17 deletions
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 5bc3ca03551c..1be8f9ae8437 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c | |||
| @@ -46,8 +46,9 @@ | |||
| 46 | #define GPMC_ECC_CONFIG 0x1f4 | 46 | #define GPMC_ECC_CONFIG 0x1f4 |
| 47 | #define GPMC_ECC_CONTROL 0x1f8 | 47 | #define GPMC_ECC_CONTROL 0x1f8 |
| 48 | #define GPMC_ECC_SIZE_CONFIG 0x1fc | 48 | #define GPMC_ECC_SIZE_CONFIG 0x1fc |
| 49 | #define GPMC_ECC1_RESULT 0x200 | ||
| 49 | 50 | ||
| 50 | #define GPMC_CS0 0x60 | 51 | #define GPMC_CS0_OFFSET 0x60 |
| 51 | #define GPMC_CS_SIZE 0x30 | 52 | #define GPMC_CS_SIZE 0x30 |
| 52 | 53 | ||
| 53 | #define GPMC_MEM_START 0x00000000 | 54 | #define GPMC_MEM_START 0x00000000 |
| @@ -92,7 +93,8 @@ struct omap3_gpmc_regs { | |||
| 92 | static struct resource gpmc_mem_root; | 93 | static struct resource gpmc_mem_root; |
| 93 | static struct resource gpmc_cs_mem[GPMC_CS_NUM]; | 94 | static struct resource gpmc_cs_mem[GPMC_CS_NUM]; |
| 94 | static DEFINE_SPINLOCK(gpmc_mem_lock); | 95 | static DEFINE_SPINLOCK(gpmc_mem_lock); |
| 95 | static unsigned gpmc_cs_map; | 96 | static unsigned int gpmc_cs_map; /* flag for cs which are initialized */ |
| 97 | static int gpmc_ecc_used = -EINVAL; /* cs using ecc engine */ | ||
| 96 | 98 | ||
| 97 | static void __iomem *gpmc_base; | 99 | static void __iomem *gpmc_base; |
| 98 | 100 | ||
| @@ -108,11 +110,27 @@ static u32 gpmc_read_reg(int idx) | |||
| 108 | return __raw_readl(gpmc_base + idx); | 110 | return __raw_readl(gpmc_base + idx); |
| 109 | } | 111 | } |
| 110 | 112 | ||
| 113 | static void gpmc_cs_write_byte(int cs, int idx, u8 val) | ||
| 114 | { | ||
| 115 | void __iomem *reg_addr; | ||
| 116 | |||
| 117 | reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx; | ||
| 118 | __raw_writeb(val, reg_addr); | ||
| 119 | } | ||
| 120 | |||
| 121 | static u8 gpmc_cs_read_byte(int cs, int idx) | ||
| 122 | { | ||
| 123 | void __iomem *reg_addr; | ||
| 124 | |||
| 125 | reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx; | ||
| 126 | return __raw_readb(reg_addr); | ||
| 127 | } | ||
| 128 | |||
| 111 | void gpmc_cs_write_reg(int cs, int idx, u32 val) | 129 | void gpmc_cs_write_reg(int cs, int idx, u32 val) |
| 112 | { | 130 | { |
| 113 | void __iomem *reg_addr; | 131 | void __iomem *reg_addr; |
| 114 | 132 | ||
| 115 | reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; | 133 | reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx; |
| 116 | __raw_writel(val, reg_addr); | 134 | __raw_writel(val, reg_addr); |
| 117 | } | 135 | } |
| 118 | 136 | ||
| @@ -120,7 +138,7 @@ u32 gpmc_cs_read_reg(int cs, int idx) | |||
| 120 | { | 138 | { |
| 121 | void __iomem *reg_addr; | 139 | void __iomem *reg_addr; |
| 122 | 140 | ||
| 123 | reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; | 141 | reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx; |
| 124 | return __raw_readl(reg_addr); | 142 | return __raw_readl(reg_addr); |
| 125 | } | 143 | } |
| 126 | 144 | ||
| @@ -419,8 +437,157 @@ void gpmc_cs_free(int cs) | |||
| 419 | EXPORT_SYMBOL(gpmc_cs_free); | 437 | EXPORT_SYMBOL(gpmc_cs_free); |
| 420 | 438 | ||
| 421 | /** | 439 | /** |
| 440 | * gpmc_read_status - read access request to get the different gpmc status | ||
| 441 | * @cmd: command type | ||
| 442 | * @return status | ||
| 443 | */ | ||
| 444 | int gpmc_read_status(int cmd) | ||
| 445 | { | ||
| 446 | int status = -EINVAL; | ||
| 447 | u32 regval = 0; | ||
| 448 | |||
| 449 | switch (cmd) { | ||
| 450 | case GPMC_GET_IRQ_STATUS: | ||
| 451 | status = gpmc_read_reg(GPMC_IRQSTATUS); | ||
| 452 | break; | ||
| 453 | |||
| 454 | case GPMC_PREFETCH_FIFO_CNT: | ||
| 455 | regval = gpmc_read_reg(GPMC_PREFETCH_STATUS); | ||
| 456 | status = GPMC_PREFETCH_STATUS_FIFO_CNT(regval); | ||
| 457 | break; | ||
| 458 | |||
| 459 | case GPMC_PREFETCH_COUNT: | ||
| 460 | regval = gpmc_read_reg(GPMC_PREFETCH_STATUS); | ||
| 461 | status = GPMC_PREFETCH_STATUS_COUNT(regval); | ||
| 462 | break; | ||
| 463 | |||
| 464 | case GPMC_STATUS_BUFFER: | ||
| 465 | regval = gpmc_read_reg(GPMC_STATUS); | ||
| 466 | /* 1 : buffer is available to write */ | ||
| 467 | status = regval & GPMC_STATUS_BUFF_EMPTY; | ||
| 468 | break; | ||
| 469 | |||
| 470 | default: | ||
| 471 | printk(KERN_ERR "gpmc_read_status: Not supported\n"); | ||
| 472 | } | ||
| 473 | return status; | ||
| 474 | } | ||
| 475 | EXPORT_SYMBOL(gpmc_read_status); | ||
| 476 | |||
| 477 | /** | ||
| 478 | * gpmc_cs_configure - write request to configure gpmc | ||
| 479 | * @cs: chip select number | ||
| 480 | * @cmd: command type | ||
| 481 | * @wval: value to write | ||
| 482 | * @return status of the operation | ||
| 483 | */ | ||
| 484 | int gpmc_cs_configure(int cs, int cmd, int wval) | ||
| 485 | { | ||
| 486 | int err = 0; | ||
| 487 | u32 regval = 0; | ||
| 488 | |||
| 489 | switch (cmd) { | ||
| 490 | case GPMC_SET_IRQ_STATUS: | ||
| 491 | gpmc_write_reg(GPMC_IRQSTATUS, wval); | ||
| 492 | break; | ||
| 493 | |||
| 494 | case GPMC_CONFIG_WP: | ||
| 495 | regval = gpmc_read_reg(GPMC_CONFIG); | ||
| 496 | if (wval) | ||
| 497 | regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */ | ||
| 498 | else | ||
| 499 | regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is OFF */ | ||
| 500 | gpmc_write_reg(GPMC_CONFIG, regval); | ||
| 501 | break; | ||
| 502 | |||
| 503 | case GPMC_CONFIG_RDY_BSY: | ||
| 504 | regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); | ||
| 505 | if (wval) | ||
| 506 | regval |= WR_RD_PIN_MONITORING; | ||
| 507 | else | ||
| 508 | regval &= ~WR_RD_PIN_MONITORING; | ||
| 509 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); | ||
| 510 | break; | ||
| 511 | |||
| 512 | case GPMC_CONFIG_DEV_SIZE: | ||
| 513 | regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); | ||
| 514 | regval |= GPMC_CONFIG1_DEVICESIZE(wval); | ||
| 515 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); | ||
| 516 | break; | ||
| 517 | |||
| 518 | case GPMC_CONFIG_DEV_TYPE: | ||
| 519 | regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); | ||
| 520 | regval |= GPMC_CONFIG1_DEVICETYPE(wval); | ||
| 521 | if (wval == GPMC_DEVICETYPE_NOR) | ||
| 522 | regval |= GPMC_CONFIG1_MUXADDDATA; | ||
| 523 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); | ||
| 524 | break; | ||
| 525 | |||
| 526 | default: | ||
| 527 | printk(KERN_ERR "gpmc_configure_cs: Not supported\n"); | ||
| 528 | err = -EINVAL; | ||
| 529 | } | ||
| 530 | |||
| 531 | return err; | ||
| 532 | } | ||
| 533 | EXPORT_SYMBOL(gpmc_cs_configure); | ||
| 534 | |||
| 535 | /** | ||
| 536 | * gpmc_nand_read - nand specific read access request | ||
| 537 | * @cs: chip select number | ||
| 538 | * @cmd: command type | ||
| 539 | */ | ||
| 540 | int gpmc_nand_read(int cs, int cmd) | ||
| 541 | { | ||
| 542 | int rval = -EINVAL; | ||
| 543 | |||
| 544 | switch (cmd) { | ||
| 545 | case GPMC_NAND_DATA: | ||
| 546 | rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA); | ||
| 547 | break; | ||
| 548 | |||
| 549 | default: | ||
| 550 | printk(KERN_ERR "gpmc_read_nand_ctrl: Not supported\n"); | ||
| 551 | } | ||
| 552 | return rval; | ||
| 553 | } | ||
| 554 | EXPORT_SYMBOL(gpmc_nand_read); | ||
| 555 | |||
| 556 | /** | ||
| 557 | * gpmc_nand_write - nand specific write request | ||
| 558 | * @cs: chip select number | ||
| 559 | * @cmd: command type | ||
| 560 | * @wval: value to write | ||
| 561 | */ | ||
| 562 | int gpmc_nand_write(int cs, int cmd, int wval) | ||
| 563 | { | ||
| 564 | int err = 0; | ||
| 565 | |||
| 566 | switch (cmd) { | ||
| 567 | case GPMC_NAND_COMMAND: | ||
| 568 | gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval); | ||
| 569 | break; | ||
| 570 | |||
| 571 | case GPMC_NAND_ADDRESS: | ||
| 572 | gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval); | ||
| 573 | break; | ||
| 574 | |||
| 575 | case GPMC_NAND_DATA: | ||
| 576 | gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval); | ||
| 577 | |||
| 578 | default: | ||
| 579 | printk(KERN_ERR "gpmc_write_nand_ctrl: Not supported\n"); | ||
| 580 | err = -EINVAL; | ||
| 581 | } | ||
| 582 | return err; | ||
| 583 | } | ||
| 584 | EXPORT_SYMBOL(gpmc_nand_write); | ||
| 585 | |||
| 586 | |||
| 587 | |||
| 588 | /** | ||
| 422 | * gpmc_prefetch_enable - configures and starts prefetch transfer | 589 | * gpmc_prefetch_enable - configures and starts prefetch transfer |
| 423 | * @cs: nand cs (chip select) number | 590 | * @cs: cs (chip select) number |
| 424 | * @dma_mode: dma mode enable (1) or disable (0) | 591 | * @dma_mode: dma mode enable (1) or disable (0) |
| 425 | * @u32_count: number of bytes to be transferred | 592 | * @u32_count: number of bytes to be transferred |
| 426 | * @is_write: prefetch read(0) or write post(1) mode | 593 | * @is_write: prefetch read(0) or write post(1) mode |
| @@ -428,7 +595,6 @@ EXPORT_SYMBOL(gpmc_cs_free); | |||
| 428 | int gpmc_prefetch_enable(int cs, int dma_mode, | 595 | int gpmc_prefetch_enable(int cs, int dma_mode, |
| 429 | unsigned int u32_count, int is_write) | 596 | unsigned int u32_count, int is_write) |
| 430 | { | 597 | { |
| 431 | uint32_t prefetch_config1; | ||
| 432 | 598 | ||
| 433 | if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) { | 599 | if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) { |
| 434 | /* Set the amount of bytes to be prefetched */ | 600 | /* Set the amount of bytes to be prefetched */ |
| @@ -437,17 +603,17 @@ int gpmc_prefetch_enable(int cs, int dma_mode, | |||
| 437 | /* Set dma/mpu mode, the prefetch read / post write and | 603 | /* Set dma/mpu mode, the prefetch read / post write and |
| 438 | * enable the engine. Set which cs is has requested for. | 604 | * enable the engine. Set which cs is has requested for. |
| 439 | */ | 605 | */ |
| 440 | prefetch_config1 = ((cs << CS_NUM_SHIFT) | | 606 | gpmc_write_reg(GPMC_PREFETCH_CONFIG1, ((cs << CS_NUM_SHIFT) | |
| 441 | PREFETCH_FIFOTHRESHOLD | | 607 | PREFETCH_FIFOTHRESHOLD | |
| 442 | ENABLE_PREFETCH | | 608 | ENABLE_PREFETCH | |
| 443 | (dma_mode << DMA_MPU_MODE) | | 609 | (dma_mode << DMA_MPU_MODE) | |
| 444 | (0x1 & is_write)); | 610 | (0x1 & is_write))); |
| 445 | gpmc_write_reg(GPMC_PREFETCH_CONFIG1, prefetch_config1); | 611 | |
| 612 | /* Start the prefetch engine */ | ||
| 613 | gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1); | ||
| 446 | } else { | 614 | } else { |
| 447 | return -EBUSY; | 615 | return -EBUSY; |
| 448 | } | 616 | } |
| 449 | /* Start the prefetch engine */ | ||
| 450 | gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1); | ||
| 451 | 617 | ||
| 452 | return 0; | 618 | return 0; |
| 453 | } | 619 | } |
| @@ -456,13 +622,22 @@ EXPORT_SYMBOL(gpmc_prefetch_enable); | |||
| 456 | /** | 622 | /** |
| 457 | * gpmc_prefetch_reset - disables and stops the prefetch engine | 623 | * gpmc_prefetch_reset - disables and stops the prefetch engine |
| 458 | */ | 624 | */ |
| 459 | void gpmc_prefetch_reset(void) | 625 | int gpmc_prefetch_reset(int cs) |
| 460 | { | 626 | { |
| 627 | u32 config1; | ||
| 628 | |||
| 629 | /* check if the same module/cs is trying to reset */ | ||
| 630 | config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1); | ||
| 631 | if (((config1 >> CS_NUM_SHIFT) & 0x7) != cs) | ||
| 632 | return -EINVAL; | ||
| 633 | |||
| 461 | /* Stop the PFPW engine */ | 634 | /* Stop the PFPW engine */ |
| 462 | gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0); | 635 | gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0); |
| 463 | 636 | ||
| 464 | /* Reset/disable the PFPW engine */ | 637 | /* Reset/disable the PFPW engine */ |
| 465 | gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0); | 638 | gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0); |
| 639 | |||
| 640 | return 0; | ||
| 466 | } | 641 | } |
| 467 | EXPORT_SYMBOL(gpmc_prefetch_reset); | 642 | EXPORT_SYMBOL(gpmc_prefetch_reset); |
| 468 | 643 | ||
| @@ -615,3 +790,79 @@ void omap3_gpmc_restore_context(void) | |||
| 615 | } | 790 | } |
| 616 | } | 791 | } |
| 617 | #endif /* CONFIG_ARCH_OMAP3 */ | 792 | #endif /* CONFIG_ARCH_OMAP3 */ |
| 793 | |||
| 794 | /** | ||
| 795 | * gpmc_enable_hwecc - enable hardware ecc functionality | ||
| 796 | * @cs: chip select number | ||
| 797 | * @mode: read/write mode | ||
| 798 | * @dev_width: device bus width(1 for x16, 0 for x8) | ||
| 799 | * @ecc_size: bytes for which ECC will be generated | ||
| 800 | */ | ||
| 801 | int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size) | ||
| 802 | { | ||
| 803 | unsigned int val; | ||
| 804 | |||
| 805 | /* check if ecc module is in used */ | ||
| 806 | if (gpmc_ecc_used != -EINVAL) | ||
| 807 | return -EINVAL; | ||
| 808 | |||
| 809 | gpmc_ecc_used = cs; | ||
| 810 | |||
| 811 | /* clear ecc and enable bits */ | ||
| 812 | val = ((0x00000001<<8) | 0x00000001); | ||
| 813 | gpmc_write_reg(GPMC_ECC_CONTROL, val); | ||
| 814 | |||
| 815 | /* program ecc and result sizes */ | ||
| 816 | val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F)); | ||
| 817 | gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val); | ||
| 818 | |||
| 819 | switch (mode) { | ||
| 820 | case GPMC_ECC_READ: | ||
| 821 | gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); | ||
| 822 | break; | ||
| 823 | case GPMC_ECC_READSYN: | ||
| 824 | gpmc_write_reg(GPMC_ECC_CONTROL, 0x100); | ||
| 825 | break; | ||
| 826 | case GPMC_ECC_WRITE: | ||
| 827 | gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); | ||
| 828 | break; | ||
| 829 | default: | ||
| 830 | printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode); | ||
| 831 | break; | ||
| 832 | } | ||
| 833 | |||
| 834 | /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ | ||
| 835 | val = (dev_width << 7) | (cs << 1) | (0x1); | ||
| 836 | gpmc_write_reg(GPMC_ECC_CONFIG, val); | ||
| 837 | return 0; | ||
| 838 | } | ||
| 839 | |||
| 840 | /** | ||
| 841 | * gpmc_calculate_ecc - generate non-inverted ecc bytes | ||
| 842 | * @cs: chip select number | ||
| 843 | * @dat: data pointer over which ecc is computed | ||
| 844 | * @ecc_code: ecc code buffer | ||
| 845 | * | ||
| 846 | * Using non-inverted ECC is considered ugly since writing a blank | ||
| 847 | * page (padding) will clear the ECC bytes. This is not a problem as long | ||
| 848 | * no one is trying to write data on the seemingly unused page. Reading | ||
| 849 | * an erased page will produce an ECC mismatch between generated and read | ||
| 850 | * ECC bytes that has to be dealt with separately. | ||
| 851 | */ | ||
| 852 | int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code) | ||
| 853 | { | ||
| 854 | unsigned int val = 0x0; | ||
| 855 | |||
| 856 | if (gpmc_ecc_used != cs) | ||
| 857 | return -EINVAL; | ||
| 858 | |||
| 859 | /* read ecc result */ | ||
| 860 | val = gpmc_read_reg(GPMC_ECC1_RESULT); | ||
| 861 | *ecc_code++ = val; /* P128e, ..., P1e */ | ||
| 862 | *ecc_code++ = val >> 16; /* P128o, ..., P1o */ | ||
| 863 | /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */ | ||
| 864 | *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0); | ||
| 865 | |||
| 866 | gpmc_ecc_used = -EINVAL; | ||
| 867 | return 0; | ||
| 868 | } | ||
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 145838a81ef6..561c64f5ab50 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h | |||
| @@ -27,8 +27,27 @@ | |||
| 27 | 27 | ||
| 28 | #define GPMC_CONFIG 0x50 | 28 | #define GPMC_CONFIG 0x50 |
| 29 | #define GPMC_STATUS 0x54 | 29 | #define GPMC_STATUS 0x54 |
| 30 | #define GPMC_CS0_BASE 0x60 | 30 | |
| 31 | #define GPMC_CS_SIZE 0x30 | 31 | /* Control Commands */ |
| 32 | #define GPMC_CONFIG_RDY_BSY 0x00000001 | ||
| 33 | #define GPMC_CONFIG_DEV_SIZE 0x00000002 | ||
| 34 | #define GPMC_CONFIG_DEV_TYPE 0x00000003 | ||
| 35 | #define GPMC_SET_IRQ_STATUS 0x00000004 | ||
| 36 | #define GPMC_CONFIG_WP 0x00000005 | ||
| 37 | |||
| 38 | #define GPMC_GET_IRQ_STATUS 0x00000006 | ||
| 39 | #define GPMC_PREFETCH_FIFO_CNT 0x00000007 /* bytes available in FIFO for r/w */ | ||
| 40 | #define GPMC_PREFETCH_COUNT 0x00000008 /* remaining bytes to be read/write*/ | ||
| 41 | #define GPMC_STATUS_BUFFER 0x00000009 /* 1: buffer is available to write */ | ||
| 42 | |||
| 43 | #define GPMC_NAND_COMMAND 0x0000000a | ||
| 44 | #define GPMC_NAND_ADDRESS 0x0000000b | ||
| 45 | #define GPMC_NAND_DATA 0x0000000c | ||
| 46 | |||
| 47 | /* ECC commands */ | ||
| 48 | #define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ | ||
| 49 | #define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ | ||
| 50 | #define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */ | ||
| 32 | 51 | ||
| 33 | #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) | 52 | #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) |
| 34 | #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) | 53 | #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) |
| @@ -56,6 +75,14 @@ | |||
| 56 | #define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) | 75 | #define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) |
| 57 | #define GPMC_CONFIG7_CSVALID (1 << 6) | 76 | #define GPMC_CONFIG7_CSVALID (1 << 6) |
| 58 | 77 | ||
| 78 | #define GPMC_DEVICETYPE_NOR 0 | ||
| 79 | #define GPMC_DEVICETYPE_NAND 2 | ||
| 80 | #define GPMC_CONFIG_WRITEPROTECT 0x00000010 | ||
| 81 | #define GPMC_STATUS_BUFF_EMPTY 0x00000001 | ||
| 82 | #define WR_RD_PIN_MONITORING 0x00600000 | ||
| 83 | #define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F) | ||
| 84 | #define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff) | ||
| 85 | |||
| 59 | /* | 86 | /* |
| 60 | * Note that all values in this struct are in nanoseconds, while | 87 | * Note that all values in this struct are in nanoseconds, while |
| 61 | * the register values are in gpmc_fck cycles. | 88 | * the register values are in gpmc_fck cycles. |
| @@ -108,10 +135,16 @@ extern int gpmc_cs_set_reserved(int cs, int reserved); | |||
| 108 | extern int gpmc_cs_reserved(int cs); | 135 | extern int gpmc_cs_reserved(int cs); |
| 109 | extern int gpmc_prefetch_enable(int cs, int dma_mode, | 136 | extern int gpmc_prefetch_enable(int cs, int dma_mode, |
| 110 | unsigned int u32_count, int is_write); | 137 | unsigned int u32_count, int is_write); |
| 111 | extern void gpmc_prefetch_reset(void); | 138 | extern int gpmc_prefetch_reset(int cs); |
| 112 | extern int gpmc_prefetch_status(void); | 139 | extern int gpmc_prefetch_status(void); |
| 113 | extern void omap3_gpmc_save_context(void); | 140 | extern void omap3_gpmc_save_context(void); |
| 114 | extern void omap3_gpmc_restore_context(void); | 141 | extern void omap3_gpmc_restore_context(void); |
| 115 | extern void gpmc_init(void); | 142 | extern void gpmc_init(void); |
| 143 | extern int gpmc_read_status(int cmd); | ||
| 144 | extern int gpmc_cs_configure(int cs, int cmd, int wval); | ||
| 145 | extern int gpmc_nand_read(int cs, int cmd); | ||
| 146 | extern int gpmc_nand_write(int cs, int cmd, int wval); | ||
| 116 | 147 | ||
| 148 | int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size); | ||
| 149 | int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code); | ||
| 117 | #endif | 150 | #endif |
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index ee87325c7712..ec8eb3109d0d 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
| @@ -319,7 +319,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) | |||
| 319 | } while (len); | 319 | } while (len); |
| 320 | 320 | ||
| 321 | /* disable and stop the PFPW engine */ | 321 | /* disable and stop the PFPW engine */ |
| 322 | gpmc_prefetch_reset(); | 322 | gpmc_prefetch_reset(info->gpmc_cs); |
| 323 | } | 323 | } |
| 324 | } | 324 | } |
| 325 | 325 | ||
| @@ -363,7 +363,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd, | |||
| 363 | } | 363 | } |
| 364 | 364 | ||
| 365 | /* disable and stop the PFPW engine */ | 365 | /* disable and stop the PFPW engine */ |
| 366 | gpmc_prefetch_reset(); | 366 | gpmc_prefetch_reset(info->gpmc_cs); |
| 367 | } | 367 | } |
| 368 | } | 368 | } |
| 369 | 369 | ||
