diff options
-rw-r--r-- | drivers/mtd/onenand/Kconfig | 6 | ||||
-rw-r--r-- | drivers/mtd/onenand/omap-onenand.c | 66 | ||||
-rw-r--r-- | drivers/mtd/onenand/onenand_base.c | 39 | ||||
-rw-r--r-- | include/linux/mtd/onenand.h | 1 | ||||
-rw-r--r-- | include/linux/mtd/onenand_regs.h | 17 |
5 files changed, 123 insertions, 6 deletions
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index 7d76ede984d8..186ea9dc0942 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig | |||
@@ -29,4 +29,10 @@ config MTD_ONENAND_OMAP | |||
29 | help | 29 | help |
30 | Support for OneNAND flash on TI OMAP board. | 30 | Support for OneNAND flash on TI OMAP board. |
31 | 31 | ||
32 | config MTD_ONENAND_SYNC_READ | ||
33 | bool "OneNAND Sync. Burst Read Support" | ||
34 | depends on ARCH_OMAP | ||
35 | help | ||
36 | This enables support for Sync. Burst Read. | ||
37 | |||
32 | endmenu | 38 | endmenu |
diff --git a/drivers/mtd/onenand/omap-onenand.c b/drivers/mtd/onenand/omap-onenand.c index 56e1aec6b835..7c89549f7f58 100644 --- a/drivers/mtd/onenand/omap-onenand.c +++ b/drivers/mtd/onenand/omap-onenand.c | |||
@@ -25,9 +25,10 @@ | |||
25 | #include <asm/arch/hardware.h> | 25 | #include <asm/arch/hardware.h> |
26 | #include <asm/arch/tc.h> | 26 | #include <asm/arch/tc.h> |
27 | #include <asm/sizes.h> | 27 | #include <asm/sizes.h> |
28 | #include <asm/mach-types.h> | ||
28 | 29 | ||
29 | #define OMAP_ONENAND_FLASH_START1 OMAP_CS2A_PHYS | 30 | #define OMAP_ONENAND_FLASH_START1 OMAP_CS2A_PHYS |
30 | #define OMAP_ONENAND_FLASH_START2 OMAP_CS0_PHYS | 31 | #define OMAP_ONENAND_FLASH_START2 omap_cs3_phys() |
31 | /* | 32 | /* |
32 | * MTD structure for OMAP board | 33 | * MTD structure for OMAP board |
33 | */ | 34 | */ |
@@ -68,10 +69,66 @@ static struct mtd_partition static_partition[] = { | |||
68 | }, | 69 | }, |
69 | }; | 70 | }; |
70 | 71 | ||
71 | const char *part_probes[] = { "cmdlinepart", NULL, }; | 72 | static const char *part_probes[] = { "cmdlinepart", NULL, }; |
72 | 73 | ||
73 | #endif | 74 | #endif |
74 | 75 | ||
76 | #ifdef CONFIG_MTD_ONENAND_SYNC_READ | ||
77 | static unsigned int omap_emifs_cs; | ||
78 | |||
79 | static void omap_find_emifs_cs(unsigned int addr) | ||
80 | { | ||
81 | /* Check CS3 */ | ||
82 | if (OMAP_EMIFS_CONFIG_REG & OMAP_EMIFS_CONFIG_BM && addr == 0x0) { | ||
83 | omap_emifs_cs = 3; | ||
84 | } else { | ||
85 | omap_emifs_cs = (addr >> 26); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * omap_onenand_mmcontrol - Control OMAP EMIFS | ||
91 | */ | ||
92 | static void omap_onenand_mmcontrol(struct mtd_info *mtd, int sync_read) | ||
93 | { | ||
94 | struct onenand_chip *this = mtd->priv; | ||
95 | static unsigned long omap_emifs_ccs, omap_emifs_acs; | ||
96 | static unsigned long onenand_sys_cfg1; | ||
97 | int config, emifs_ccs, emifs_acs; | ||
98 | |||
99 | if (sync_read) { | ||
100 | /* | ||
101 | * Note: BRL and RDWST is equal | ||
102 | */ | ||
103 | omap_emifs_ccs = EMIFS_CCS(omap_emifs_cs); | ||
104 | omap_emifs_acs = EMIFS_ACS(omap_emifs_cs); | ||
105 | |||
106 | emifs_ccs = 0x41141; | ||
107 | emifs_acs = 0x1; | ||
108 | |||
109 | /* OneNAND System Configuration 1 */ | ||
110 | onenand_sys_cfg1 = this->read_word(this->base + ONENAND_REG_SYS_CFG1); | ||
111 | config = (onenand_sys_cfg1 | ||
112 | & ~(0x3f << ONENAND_SYS_CFG1_BL_SHIFT)) | ||
113 | | ONENAND_SYS_CFG1_SYNC_READ | ||
114 | | ONENAND_SYS_CFG1_BRL_4 | ||
115 | | ONENAND_SYS_CFG1_BL_8; | ||
116 | } else { | ||
117 | emifs_ccs = omap_emifs_ccs; | ||
118 | emifs_acs = omap_emifs_acs; | ||
119 | config = onenand_sys_cfg1; | ||
120 | } | ||
121 | |||
122 | this->write_word(config, this->base + ONENAND_REG_SYS_CFG1); | ||
123 | EMIFS_CCS(omap_emifs_cs) = emifs_ccs; | ||
124 | EMIFS_ACS(omap_emifs_cs) = emifs_acs; | ||
125 | } | ||
126 | #else | ||
127 | #define omap_find_emifs_cs(x) do { } while (0) | ||
128 | #define omap_onenand_mmcontrol NULL | ||
129 | #endif | ||
130 | |||
131 | |||
75 | /* Scan to find existance of the device at base. | 132 | /* Scan to find existance of the device at base. |
76 | This also allocates oob and data internal buffers */ | 133 | This also allocates oob and data internal buffers */ |
77 | static char onenand_name[] = "onenand"; | 134 | static char onenand_name[] = "onenand"; |
@@ -102,14 +159,19 @@ static int __init omap_onenand_init (void) | |||
102 | 159 | ||
103 | /* Link the private data with the MTD structure */ | 160 | /* Link the private data with the MTD structure */ |
104 | omap_onenand_mtd->priv = this; | 161 | omap_onenand_mtd->priv = this; |
162 | this->mmcontrol = omap_onenand_mmcontrol; | ||
105 | 163 | ||
106 | /* try the first address */ | 164 | /* try the first address */ |
107 | this->base = ioremap(OMAP_ONENAND_FLASH_START1, SZ_128K); | 165 | this->base = ioremap(OMAP_ONENAND_FLASH_START1, SZ_128K); |
166 | omap_find_emifs_cs(OMAP_ONENAND_FLASH_START1); | ||
167 | |||
108 | omap_onenand_mtd->name = onenand_name; | 168 | omap_onenand_mtd->name = onenand_name; |
109 | if (onenand_scan(omap_onenand_mtd, 1)){ | 169 | if (onenand_scan(omap_onenand_mtd, 1)){ |
110 | /* try the second address */ | 170 | /* try the second address */ |
111 | iounmap(this->base); | 171 | iounmap(this->base); |
112 | this->base = ioremap(OMAP_ONENAND_FLASH_START2, SZ_128K); | 172 | this->base = ioremap(OMAP_ONENAND_FLASH_START2, SZ_128K); |
173 | omap_find_emifs_cs(OMAP_ONENAND_FLASH_START2); | ||
174 | |||
113 | if (onenand_scan(omap_onenand_mtd, 1)) { | 175 | if (onenand_scan(omap_onenand_mtd, 1)) { |
114 | iounmap(this->base); | 176 | iounmap(this->base); |
115 | err = -ENXIO; | 177 | err = -ENXIO; |
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index bcce22ae3cb1..e87489505772 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c | |||
@@ -379,6 +379,35 @@ static int onenand_read_bufferram(struct mtd_info *mtd, int area, | |||
379 | } | 379 | } |
380 | 380 | ||
381 | /** | 381 | /** |
382 | * onenand_sync_read_bufferram - [OneNAND Interface] Read the bufferram area with Sync. Burst mode | ||
383 | * @param mtd MTD data structure | ||
384 | * @param area BufferRAM area | ||
385 | * @param buffer the databuffer to put/get data | ||
386 | * @param offset offset to read from or write to | ||
387 | * @param count number of bytes to read/write | ||
388 | * | ||
389 | * Read the BufferRAM area with Sync. Burst Mode | ||
390 | */ | ||
391 | static int onenand_sync_read_bufferram(struct mtd_info *mtd, int area, | ||
392 | unsigned char *buffer, int offset, size_t count) | ||
393 | { | ||
394 | struct onenand_chip *this = mtd->priv; | ||
395 | void __iomem *bufferram; | ||
396 | |||
397 | bufferram = this->base + area; | ||
398 | |||
399 | bufferram += onenand_bufferram_offset(mtd, area); | ||
400 | |||
401 | this->mmcontrol(mtd, ONENAND_SYS_CFG1_SYNC_READ); | ||
402 | |||
403 | memcpy(buffer, bufferram + offset, count); | ||
404 | |||
405 | this->mmcontrol(mtd, 0); | ||
406 | |||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | /** | ||
382 | * onenand_write_bufferram - [OneNAND Interface] Write the bufferram area | 411 | * onenand_write_bufferram - [OneNAND Interface] Write the bufferram area |
383 | * @param mtd MTD data structure | 412 | * @param mtd MTD data structure |
384 | * @param area BufferRAM area | 413 | * @param area BufferRAM area |
@@ -1273,8 +1302,8 @@ static int onenand_check_maf(int manuf) | |||
1273 | break; | 1302 | break; |
1274 | } | 1303 | } |
1275 | 1304 | ||
1276 | printk(KERN_DEBUG "OneNAND Manufacturer: %s\n", | 1305 | printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n", |
1277 | onenand_manuf_ids[i].name); | 1306 | onenand_manuf_ids[i].name, manuf); |
1278 | 1307 | ||
1279 | return (i != ONENAND_MFR_UNKNOWN); | 1308 | return (i != ONENAND_MFR_UNKNOWN); |
1280 | } | 1309 | } |
@@ -1385,6 +1414,12 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) | |||
1385 | if (onenand_probe(mtd)) | 1414 | if (onenand_probe(mtd)) |
1386 | return -ENXIO; | 1415 | return -ENXIO; |
1387 | 1416 | ||
1417 | /* Set Sync. Burst Read after probing */ | ||
1418 | if (this->mmcontrol) { | ||
1419 | printk(KERN_INFO "OneNAND Sync. Burst Read support\n"); | ||
1420 | this->read_bufferram = onenand_sync_read_bufferram; | ||
1421 | } | ||
1422 | |||
1388 | this->state = FL_READY; | 1423 | this->state = FL_READY; |
1389 | init_waitqueue_head(&this->wq); | 1424 | init_waitqueue_head(&this->wq); |
1390 | spin_lock_init(&this->chip_lock); | 1425 | spin_lock_init(&this->chip_lock); |
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index b9a64117d646..c557caa24a6c 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h | |||
@@ -95,6 +95,7 @@ struct onenand_chip { | |||
95 | const unsigned char *buffer, int offset, size_t count); | 95 | const unsigned char *buffer, int offset, size_t count); |
96 | unsigned short (*read_word)(void __iomem *addr); | 96 | unsigned short (*read_word)(void __iomem *addr); |
97 | void (*write_word)(unsigned short value, void __iomem *addr); | 97 | void (*write_word)(unsigned short value, void __iomem *addr); |
98 | void (*mmcontrol)(struct mtd_info *mtd, int sync_read); | ||
98 | 99 | ||
99 | spinlock_t chip_lock; | 100 | spinlock_t chip_lock; |
100 | wait_queue_head_t wq; | 101 | wait_queue_head_t wq; |
diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h index 4a2daad7d738..d7832ef8ed63 100644 --- a/include/linux/mtd/onenand_regs.h +++ b/include/linux/mtd/onenand_regs.h | |||
@@ -121,8 +121,21 @@ | |||
121 | * System Configuration 1 Register F221h (R, R/W) | 121 | * System Configuration 1 Register F221h (R, R/W) |
122 | */ | 122 | */ |
123 | #define ONENAND_SYS_CFG1_SYNC_READ (1 << 15) | 123 | #define ONENAND_SYS_CFG1_SYNC_READ (1 << 15) |
124 | #define ONENAND_SYS_CFG1_BRL (1 << 12) | 124 | #define ONENAND_SYS_CFG1_BRL_7 (7 << 12) |
125 | #define ONENAND_SYS_CFG1_BL (1 << 9) | 125 | #define ONENAND_SYS_CFG1_BRL_6 (6 << 12) |
126 | #define ONENAND_SYS_CFG1_BRL_5 (5 << 12) | ||
127 | #define ONENAND_SYS_CFG1_BRL_4 (4 << 12) | ||
128 | #define ONENAND_SYS_CFG1_BRL_3 (3 << 12) | ||
129 | #define ONENAND_SYS_CFG1_BRL_10 (2 << 12) | ||
130 | #define ONENAND_SYS_CFG1_BRL_9 (1 << 12) | ||
131 | #define ONENAND_SYS_CFG1_BRL_8 (0 << 12) | ||
132 | #define ONENAND_SYS_CFG1_BRL_SHIFT (12) | ||
133 | #define ONENAND_SYS_CFG1_BL_32 (4 << 9) | ||
134 | #define ONENAND_SYS_CFG1_BL_16 (3 << 9) | ||
135 | #define ONENAND_SYS_CFG1_BL_8 (2 << 9) | ||
136 | #define ONENAND_SYS_CFG1_BL_4 (1 << 9) | ||
137 | #define ONENAND_SYS_CFG1_BL_CONT (0 << 9) | ||
138 | #define ONENAND_SYS_CFG1_BL_SHIFT (9) | ||
126 | #define ONENAND_SYS_CFG1_NO_ECC (1 << 8) | 139 | #define ONENAND_SYS_CFG1_NO_ECC (1 << 8) |
127 | #define ONENAND_SYS_CFG1_RDY (1 << 7) | 140 | #define ONENAND_SYS_CFG1_RDY (1 << 7) |
128 | #define ONENAND_SYS_CFG1_INT (1 << 6) | 141 | #define ONENAND_SYS_CFG1_INT (1 << 6) |