diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-08 08:12:43 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-08 08:12:43 -0800 |
commit | 79c9601c2e0dbbe69895d302de4d19f3a31fbd30 (patch) | |
tree | 78d4be2df851b2b4106adcfd736622a90cecf9e9 /drivers/mtd/nand/pxa3xx_nand.c | |
parent | 41440ffe21f29bdb985cab76b2d0b06d83e63b19 (diff) | |
parent | 3d14b5beba35250c548d3851a2b84fce742d8311 (diff) |
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (272 commits)
Fix soc_common PCMCIA configuration
ARM: 5827/1: SA1100: h3100/h3600: emit messages on failed gpio_request
ARM: 5826/1: SA1100: h3100/h3600: always build htc-egpio driver
ARM: 5825/1: SA1100: h3600: update defconfig
ARM: 5824/1: SA1100: reuse h3600 PCMCIA driver on h3100
ARM: 5823/1: SA1100: h3100/h3600: add support for gpio-keys
ARM: 5822/1: SA1100: h3100/h3600: clean up #includes
ARM: 5821/1: SA1100: h3100/h3600: revise copyright boilerplates
ARM: 5820/1: SA1100: h3100/h3600: split h3600.c
ARM: 5819/1: SA1100: h3100/h3600: merge h3600.h and h3600_gpio.h into h3xxx.h
ARM: 5818/1: SA1100: h3100/h3600: drop old GPIO definitions
ARM: 5817/1: SA1100: h3100/h3600: configure all unused gpios as inputs
ARM: 5816/1: SA1100: h3600: remove IRQ_GPIO_* definitions
ARM: 5815/1: SA1100: h3100/h3600: remove now unused assign_h3600_egpio handlers
ARM: 5814/1: SA1100: h3100/h3600: convert all users of assign_h3600_egpio to gpiolib
ARM: 5813/1: SA1100: h3100/h3600: add htc-egpio driver
ARM: 5812/1: SA1100: h3100/h3600: separate machine-specific LCD helpers
ARM: 5811/2: pcmcia: convert sa1100_h3600 driver to gpiolib
ARM: 5799/1: SA1100: h3600: stop setting direction for LCD pins
ARM: 5798/1: SA1100: h3600: remove unused cruft from h3600.h
...
Diffstat (limited to 'drivers/mtd/nand/pxa3xx_nand.c')
-rw-r--r-- | drivers/mtd/nand/pxa3xx_nand.c | 82 |
1 files changed, 68 insertions, 14 deletions
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 6ea520ae241..1a5a0365c98 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -9,6 +9,7 @@ * published by the Free Software Foundation. */ +#include <linux/kernel.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/platform_device.h> @@ -22,7 +23,7 @@ #include <linux/irq.h> #include <mach/dma.h> -#include <mach/pxa3xx_nand.h> +#include <plat/pxa3xx_nand.h> #define CHIP_DELAY_TIMEOUT (2 * HZ/10) @@ -84,10 +85,6 @@ #define NDCB0_CMD1_MASK (0xff) #define NDCB0_ADDR_CYC_SHIFT (16) -/* dma-able I/O address for the NAND data and commands */ -#define NDCB0_DMA_ADDR (0x43100048) -#define NDDB_DMA_ADDR (0x43100040) - /* macros for registers read/write */ #define nand_writel(info, off, val) \ __raw_writel((val), (info)->mmio_base + (off)) @@ -123,6 +120,7 @@ struct pxa3xx_nand_info { struct clk *clk; void __iomem *mmio_base; + unsigned long mmio_phys; unsigned int buf_start; unsigned int buf_count; @@ -228,13 +226,35 @@ static struct pxa3xx_nand_flash samsung512MbX16 = { .chip_id = 0x46ec, }; +static struct pxa3xx_nand_flash samsung2GbX8 = { + .timing = &samsung512MbX16_timing, + .cmdset = &smallpage_cmdset, + .page_per_block = 64, + .page_size = 2048, + .flash_width = 8, + .dfc_width = 8, + .num_blocks = 2048, + .chip_id = 0xdaec, +}; + +static struct pxa3xx_nand_flash samsung32GbX8 = { + .timing = &samsung512MbX16_timing, + .cmdset = &smallpage_cmdset, + .page_per_block = 128, + .page_size = 4096, + .flash_width = 8, + .dfc_width = 8, + .num_blocks = 8192, + .chip_id = 0xd7ec, +}; + static struct pxa3xx_nand_timing micron_timing = { .tCH = 10, .tCS = 25, .tWH = 15, .tWP = 25, .tRH = 15, - .tRP = 25, + .tRP = 30, .tR = 25000, .tWHR = 60, .tAR = 10, @@ -262,6 +282,28 @@ static struct pxa3xx_nand_flash micron1GbX16 = { .chip_id = 0xb12c, }; +static struct pxa3xx_nand_flash micron4GbX8 = { + .timing = µn_timing, + .cmdset = &largepage_cmdset, + .page_per_block = 64, + .page_size = 2048, + .flash_width = 8, + .dfc_width = 8, + .num_blocks = 4096, + .chip_id = 0xdc2c, +}; + +static struct pxa3xx_nand_flash micron4GbX16 = { + .timing = µn_timing, + .cmdset = &largepage_cmdset, + .page_per_block = 64, + .page_size = 2048, + .flash_width = 16, + .dfc_width = 16, + .num_blocks = 4096, + .chip_id = 0xcc2c, +}; + static struct pxa3xx_nand_timing stm2GbX16_timing = { .tCH = 10, .tCS = 35, @@ -287,8 +329,12 @@ static struct pxa3xx_nand_flash stm2GbX16 = { static struct pxa3xx_nand_flash *builtin_flash_types[] = { &samsung512MbX16, + &samsung2GbX8, + &samsung32GbX8, µn1GbX8, µn1GbX16, + µn4GbX8, + µn4GbX16, &stm2GbX16, }; #endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */ @@ -489,7 +535,7 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) switch (info->state) { case STATE_PIO_WRITING: __raw_writesl(info->mmio_base + NDDB, info->data_buff, - info->data_size << 2); + DIV_ROUND_UP(info->data_size, 4)); enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); @@ -501,7 +547,7 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) break; case STATE_PIO_READING: __raw_readsl(info->mmio_base + NDDB, info->data_buff, - info->data_size << 2); + DIV_ROUND_UP(info->data_size, 4)); break; default: printk(KERN_ERR "%s: invalid state %d\n", __func__, @@ -523,11 +569,11 @@ static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) if (dir_out) { desc->dsadr = info->data_buff_phys; - desc->dtadr = NDDB_DMA_ADDR; + desc->dtadr = info->mmio_phys + NDDB; desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG; } else { desc->dtadr = info->data_buff_phys; - desc->dsadr = NDDB_DMA_ADDR; + desc->dsadr = info->mmio_phys + NDDB; desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC; } @@ -669,6 +715,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, /* disable HW ECC to get all the OOB data */ info->buf_count = mtd->writesize + mtd->oobsize; info->buf_start = mtd->writesize + column; + memset(info->data_buff, 0xFF, info->buf_count); if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr)) break; @@ -1239,13 +1286,17 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) ret = -ENODEV; goto fail_free_res; } + info->mmio_phys = r->start; ret = pxa3xx_nand_init_buff(info); if (ret) goto fail_free_io; - ret = request_irq(IRQ_NAND, pxa3xx_nand_irq, IRQF_DISABLED, - pdev->name, info); + /* initialize all interrupts to be disabled */ + disable_int(info, NDSR_MASK); + + ret = request_irq(irq, pxa3xx_nand_irq, IRQF_DISABLED, + pdev->name, info); if (ret < 0) { dev_err(&pdev->dev, "failed to request IRQ\n"); goto fail_free_buf; @@ -1271,7 +1322,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); fail_free_irq: - free_irq(IRQ_NAND, info); + free_irq(irq, info); fail_free_buf: if (use_dma) { pxa_free_dma(info->data_dma_ch); @@ -1296,12 +1347,15 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) struct mtd_info *mtd = platform_get_drvdata(pdev); struct pxa3xx_nand_info *info = mtd->priv; struct resource *r; + int irq; platform_set_drvdata(pdev, NULL); del_mtd_device(mtd); del_mtd_partitions(mtd); - free_irq(IRQ_NAND, info); + irq = platform_get_irq(pdev, 0); + if (irq >= 0) + free_irq(irq, info); if (use_dma) { pxa_free_dma(info->data_dma_ch); dma_free_writecombine(&pdev->dev, info->data_buff_size, |