diff options
Diffstat (limited to 'drivers/mtd/nand/pxa3xx_nand.c')
-rw-r--r-- | drivers/mtd/nand/pxa3xx_nand.c | 83 |
1 files changed, 69 insertions, 14 deletions
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 6ea520ae2410..5d55152162cf 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
13 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
14 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
@@ -20,9 +21,10 @@ | |||
20 | #include <linux/mtd/partitions.h> | 21 | #include <linux/mtd/partitions.h> |
21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
22 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
24 | #include <linux/slab.h> | ||
23 | 25 | ||
24 | #include <mach/dma.h> | 26 | #include <mach/dma.h> |
25 | #include <mach/pxa3xx_nand.h> | 27 | #include <plat/pxa3xx_nand.h> |
26 | 28 | ||
27 | #define CHIP_DELAY_TIMEOUT (2 * HZ/10) | 29 | #define CHIP_DELAY_TIMEOUT (2 * HZ/10) |
28 | 30 | ||
@@ -84,10 +86,6 @@ | |||
84 | #define NDCB0_CMD1_MASK (0xff) | 86 | #define NDCB0_CMD1_MASK (0xff) |
85 | #define NDCB0_ADDR_CYC_SHIFT (16) | 87 | #define NDCB0_ADDR_CYC_SHIFT (16) |
86 | 88 | ||
87 | /* dma-able I/O address for the NAND data and commands */ | ||
88 | #define NDCB0_DMA_ADDR (0x43100048) | ||
89 | #define NDDB_DMA_ADDR (0x43100040) | ||
90 | |||
91 | /* macros for registers read/write */ | 89 | /* macros for registers read/write */ |
92 | #define nand_writel(info, off, val) \ | 90 | #define nand_writel(info, off, val) \ |
93 | __raw_writel((val), (info)->mmio_base + (off)) | 91 | __raw_writel((val), (info)->mmio_base + (off)) |
@@ -123,6 +121,7 @@ struct pxa3xx_nand_info { | |||
123 | 121 | ||
124 | struct clk *clk; | 122 | struct clk *clk; |
125 | void __iomem *mmio_base; | 123 | void __iomem *mmio_base; |
124 | unsigned long mmio_phys; | ||
126 | 125 | ||
127 | unsigned int buf_start; | 126 | unsigned int buf_start; |
128 | unsigned int buf_count; | 127 | unsigned int buf_count; |
@@ -228,13 +227,35 @@ static struct pxa3xx_nand_flash samsung512MbX16 = { | |||
228 | .chip_id = 0x46ec, | 227 | .chip_id = 0x46ec, |
229 | }; | 228 | }; |
230 | 229 | ||
230 | static struct pxa3xx_nand_flash samsung2GbX8 = { | ||
231 | .timing = &samsung512MbX16_timing, | ||
232 | .cmdset = &smallpage_cmdset, | ||
233 | .page_per_block = 64, | ||
234 | .page_size = 2048, | ||
235 | .flash_width = 8, | ||
236 | .dfc_width = 8, | ||
237 | .num_blocks = 2048, | ||
238 | .chip_id = 0xdaec, | ||
239 | }; | ||
240 | |||
241 | static struct pxa3xx_nand_flash samsung32GbX8 = { | ||
242 | .timing = &samsung512MbX16_timing, | ||
243 | .cmdset = &smallpage_cmdset, | ||
244 | .page_per_block = 128, | ||
245 | .page_size = 4096, | ||
246 | .flash_width = 8, | ||
247 | .dfc_width = 8, | ||
248 | .num_blocks = 8192, | ||
249 | .chip_id = 0xd7ec, | ||
250 | }; | ||
251 | |||
231 | static struct pxa3xx_nand_timing micron_timing = { | 252 | static struct pxa3xx_nand_timing micron_timing = { |
232 | .tCH = 10, | 253 | .tCH = 10, |
233 | .tCS = 25, | 254 | .tCS = 25, |
234 | .tWH = 15, | 255 | .tWH = 15, |
235 | .tWP = 25, | 256 | .tWP = 25, |
236 | .tRH = 15, | 257 | .tRH = 15, |
237 | .tRP = 25, | 258 | .tRP = 30, |
238 | .tR = 25000, | 259 | .tR = 25000, |
239 | .tWHR = 60, | 260 | .tWHR = 60, |
240 | .tAR = 10, | 261 | .tAR = 10, |
@@ -262,6 +283,28 @@ static struct pxa3xx_nand_flash micron1GbX16 = { | |||
262 | .chip_id = 0xb12c, | 283 | .chip_id = 0xb12c, |
263 | }; | 284 | }; |
264 | 285 | ||
286 | static struct pxa3xx_nand_flash micron4GbX8 = { | ||
287 | .timing = µn_timing, | ||
288 | .cmdset = &largepage_cmdset, | ||
289 | .page_per_block = 64, | ||
290 | .page_size = 2048, | ||
291 | .flash_width = 8, | ||
292 | .dfc_width = 8, | ||
293 | .num_blocks = 4096, | ||
294 | .chip_id = 0xdc2c, | ||
295 | }; | ||
296 | |||
297 | static struct pxa3xx_nand_flash micron4GbX16 = { | ||
298 | .timing = µn_timing, | ||
299 | .cmdset = &largepage_cmdset, | ||
300 | .page_per_block = 64, | ||
301 | .page_size = 2048, | ||
302 | .flash_width = 16, | ||
303 | .dfc_width = 16, | ||
304 | .num_blocks = 4096, | ||
305 | .chip_id = 0xcc2c, | ||
306 | }; | ||
307 | |||
265 | static struct pxa3xx_nand_timing stm2GbX16_timing = { | 308 | static struct pxa3xx_nand_timing stm2GbX16_timing = { |
266 | .tCH = 10, | 309 | .tCH = 10, |
267 | .tCS = 35, | 310 | .tCS = 35, |
@@ -287,8 +330,12 @@ static struct pxa3xx_nand_flash stm2GbX16 = { | |||
287 | 330 | ||
288 | static struct pxa3xx_nand_flash *builtin_flash_types[] = { | 331 | static struct pxa3xx_nand_flash *builtin_flash_types[] = { |
289 | &samsung512MbX16, | 332 | &samsung512MbX16, |
333 | &samsung2GbX8, | ||
334 | &samsung32GbX8, | ||
290 | µn1GbX8, | 335 | µn1GbX8, |
291 | µn1GbX16, | 336 | µn1GbX16, |
337 | µn4GbX8, | ||
338 | µn4GbX16, | ||
292 | &stm2GbX16, | 339 | &stm2GbX16, |
293 | }; | 340 | }; |
294 | #endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */ | 341 | #endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */ |
@@ -489,7 +536,7 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) | |||
489 | switch (info->state) { | 536 | switch (info->state) { |
490 | case STATE_PIO_WRITING: | 537 | case STATE_PIO_WRITING: |
491 | __raw_writesl(info->mmio_base + NDDB, info->data_buff, | 538 | __raw_writesl(info->mmio_base + NDDB, info->data_buff, |
492 | info->data_size << 2); | 539 | DIV_ROUND_UP(info->data_size, 4)); |
493 | 540 | ||
494 | enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); | 541 | enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); |
495 | 542 | ||
@@ -501,7 +548,7 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) | |||
501 | break; | 548 | break; |
502 | case STATE_PIO_READING: | 549 | case STATE_PIO_READING: |
503 | __raw_readsl(info->mmio_base + NDDB, info->data_buff, | 550 | __raw_readsl(info->mmio_base + NDDB, info->data_buff, |
504 | info->data_size << 2); | 551 | DIV_ROUND_UP(info->data_size, 4)); |
505 | break; | 552 | break; |
506 | default: | 553 | default: |
507 | printk(KERN_ERR "%s: invalid state %d\n", __func__, | 554 | printk(KERN_ERR "%s: invalid state %d\n", __func__, |
@@ -523,11 +570,11 @@ static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) | |||
523 | 570 | ||
524 | if (dir_out) { | 571 | if (dir_out) { |
525 | desc->dsadr = info->data_buff_phys; | 572 | desc->dsadr = info->data_buff_phys; |
526 | desc->dtadr = NDDB_DMA_ADDR; | 573 | desc->dtadr = info->mmio_phys + NDDB; |
527 | desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG; | 574 | desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG; |
528 | } else { | 575 | } else { |
529 | desc->dtadr = info->data_buff_phys; | 576 | desc->dtadr = info->data_buff_phys; |
530 | desc->dsadr = NDDB_DMA_ADDR; | 577 | desc->dsadr = info->mmio_phys + NDDB; |
531 | desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC; | 578 | desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC; |
532 | } | 579 | } |
533 | 580 | ||
@@ -669,6 +716,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
669 | /* disable HW ECC to get all the OOB data */ | 716 | /* disable HW ECC to get all the OOB data */ |
670 | info->buf_count = mtd->writesize + mtd->oobsize; | 717 | info->buf_count = mtd->writesize + mtd->oobsize; |
671 | info->buf_start = mtd->writesize + column; | 718 | info->buf_start = mtd->writesize + column; |
719 | memset(info->data_buff, 0xFF, info->buf_count); | ||
672 | 720 | ||
673 | if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr)) | 721 | if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr)) |
674 | break; | 722 | break; |
@@ -1239,13 +1287,17 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1239 | ret = -ENODEV; | 1287 | ret = -ENODEV; |
1240 | goto fail_free_res; | 1288 | goto fail_free_res; |
1241 | } | 1289 | } |
1290 | info->mmio_phys = r->start; | ||
1242 | 1291 | ||
1243 | ret = pxa3xx_nand_init_buff(info); | 1292 | ret = pxa3xx_nand_init_buff(info); |
1244 | if (ret) | 1293 | if (ret) |
1245 | goto fail_free_io; | 1294 | goto fail_free_io; |
1246 | 1295 | ||
1247 | ret = request_irq(IRQ_NAND, pxa3xx_nand_irq, IRQF_DISABLED, | 1296 | /* initialize all interrupts to be disabled */ |
1248 | pdev->name, info); | 1297 | disable_int(info, NDSR_MASK); |
1298 | |||
1299 | ret = request_irq(irq, pxa3xx_nand_irq, IRQF_DISABLED, | ||
1300 | pdev->name, info); | ||
1249 | if (ret < 0) { | 1301 | if (ret < 0) { |
1250 | dev_err(&pdev->dev, "failed to request IRQ\n"); | 1302 | dev_err(&pdev->dev, "failed to request IRQ\n"); |
1251 | goto fail_free_buf; | 1303 | goto fail_free_buf; |
@@ -1271,7 +1323,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1271 | return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); | 1323 | return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); |
1272 | 1324 | ||
1273 | fail_free_irq: | 1325 | fail_free_irq: |
1274 | free_irq(IRQ_NAND, info); | 1326 | free_irq(irq, info); |
1275 | fail_free_buf: | 1327 | fail_free_buf: |
1276 | if (use_dma) { | 1328 | if (use_dma) { |
1277 | pxa_free_dma(info->data_dma_ch); | 1329 | pxa_free_dma(info->data_dma_ch); |
@@ -1296,12 +1348,15 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) | |||
1296 | struct mtd_info *mtd = platform_get_drvdata(pdev); | 1348 | struct mtd_info *mtd = platform_get_drvdata(pdev); |
1297 | struct pxa3xx_nand_info *info = mtd->priv; | 1349 | struct pxa3xx_nand_info *info = mtd->priv; |
1298 | struct resource *r; | 1350 | struct resource *r; |
1351 | int irq; | ||
1299 | 1352 | ||
1300 | platform_set_drvdata(pdev, NULL); | 1353 | platform_set_drvdata(pdev, NULL); |
1301 | 1354 | ||
1302 | del_mtd_device(mtd); | 1355 | del_mtd_device(mtd); |
1303 | del_mtd_partitions(mtd); | 1356 | del_mtd_partitions(mtd); |
1304 | free_irq(IRQ_NAND, info); | 1357 | irq = platform_get_irq(pdev, 0); |
1358 | if (irq >= 0) | ||
1359 | free_irq(irq, info); | ||
1305 | if (use_dma) { | 1360 | if (use_dma) { |
1306 | pxa_free_dma(info->data_dma_ch); | 1361 | pxa_free_dma(info->data_dma_ch); |
1307 | dma_free_writecombine(&pdev->dev, info->data_buff_size, | 1362 | dma_free_writecombine(&pdev->dev, info->data_buff_size, |