Commit 62e8b851 authored by Ezequiel Garcia's avatar Ezequiel Garcia Committed by Brian Norris

mtd: nand: pxa3xx: Allocate data buffer on detected flash size

This commit replaces the currently hardcoded buffer size, by a
dynamic detection scheme. First a small 256 bytes buffer is allocated
so the device can be detected (using READID and friends commands).

After detection, this buffer is released and a new buffer is allocated
to acommodate the page size plus out-of-band size.
Signed-off-by: default avatarEzequiel Garcia <ezequiel.garcia@free-electrons.com>
Tested-by: default avatarDaniel Mack <zonque@gmail.com>
Signed-off-by: default avatarBrian Norris <computersforpeace@gmail.com>
parent 95b26563
...@@ -39,6 +39,13 @@ ...@@ -39,6 +39,13 @@
#define NAND_STOP_DELAY (2 * HZ/50) #define NAND_STOP_DELAY (2 * HZ/50)
#define PAGE_CHUNK_SIZE (2048) #define PAGE_CHUNK_SIZE (2048)
/*
* Define a buffer size for the initial command that detects the flash device:
* STATUS, READID and PARAM. The largest of these is the PARAM command,
* needing 256 bytes.
*/
#define INIT_BUFFER_SIZE 256
/* registers and bit definitions */ /* registers and bit definitions */
#define NDCR (0x00) /* Control register */ #define NDCR (0x00) /* Control register */
#define NDTR0CS0 (0x04) /* Timing Parameter 0 for CS0 */ #define NDTR0CS0 (0x04) /* Timing Parameter 0 for CS0 */
...@@ -164,6 +171,7 @@ struct pxa3xx_nand_info { ...@@ -164,6 +171,7 @@ struct pxa3xx_nand_info {
unsigned int buf_start; unsigned int buf_start;
unsigned int buf_count; unsigned int buf_count;
unsigned int buf_size;
/* DMA information */ /* DMA information */
int drcmr_dat; int drcmr_dat;
...@@ -911,26 +919,20 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) ...@@ -911,26 +919,20 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
return 0; return 0;
} }
/* the maximum possible buffer size for large page with OOB data
* is: 2048 + 64 = 2112 bytes, allocate a page here for both the
* data buffer and the DMA descriptor
*/
#define MAX_BUFF_SIZE PAGE_SIZE
#ifdef ARCH_HAS_DMA #ifdef ARCH_HAS_DMA
static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
{ {
struct platform_device *pdev = info->pdev; struct platform_device *pdev = info->pdev;
int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc); int data_desc_offset = info->buf_size - sizeof(struct pxa_dma_desc);
if (use_dma == 0) { if (use_dma == 0) {
info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL); info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
if (info->data_buff == NULL) if (info->data_buff == NULL)
return -ENOMEM; return -ENOMEM;
return 0; return 0;
} }
info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE, info->data_buff = dma_alloc_coherent(&pdev->dev, info->buf_size,
&info->data_buff_phys, GFP_KERNEL); &info->data_buff_phys, GFP_KERNEL);
if (info->data_buff == NULL) { if (info->data_buff == NULL) {
dev_err(&pdev->dev, "failed to allocate dma buffer\n"); dev_err(&pdev->dev, "failed to allocate dma buffer\n");
...@@ -944,7 +946,7 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) ...@@ -944,7 +946,7 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
pxa3xx_nand_data_dma_irq, info); pxa3xx_nand_data_dma_irq, info);
if (info->data_dma_ch < 0) { if (info->data_dma_ch < 0) {
dev_err(&pdev->dev, "failed to request data dma\n"); dev_err(&pdev->dev, "failed to request data dma\n");
dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE, dma_free_coherent(&pdev->dev, info->buf_size,
info->data_buff, info->data_buff_phys); info->data_buff, info->data_buff_phys);
return info->data_dma_ch; return info->data_dma_ch;
} }
...@@ -962,7 +964,7 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info) ...@@ -962,7 +964,7 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
struct platform_device *pdev = info->pdev; struct platform_device *pdev = info->pdev;
if (use_dma) { if (use_dma) {
pxa_free_dma(info->data_dma_ch); pxa_free_dma(info->data_dma_ch);
dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE, dma_free_coherent(&pdev->dev, info->buf_size,
info->data_buff, info->data_buff_phys); info->data_buff, info->data_buff_phys);
} else { } else {
kfree(info->data_buff); kfree(info->data_buff);
...@@ -971,7 +973,7 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info) ...@@ -971,7 +973,7 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
#else #else
static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
{ {
info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL); info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
if (info->data_buff == NULL) if (info->data_buff == NULL)
return -ENOMEM; return -ENOMEM;
return 0; return 0;
...@@ -1085,7 +1087,16 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) ...@@ -1085,7 +1087,16 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
else else
host->col_addr_cycles = 1; host->col_addr_cycles = 1;
/* release the initial buffer */
kfree(info->data_buff);
/* allocate the real data + oob buffer */
info->buf_size = mtd->writesize + mtd->oobsize;
ret = pxa3xx_nand_init_buff(info);
if (ret)
return ret;
info->oob_buff = info->data_buff + mtd->writesize; info->oob_buff = info->data_buff + mtd->writesize;
if ((mtd->size >> chip->page_shift) > 65536) if ((mtd->size >> chip->page_shift) > 65536)
host->row_addr_cycles = 3; host->row_addr_cycles = 3;
else else
...@@ -1191,9 +1202,13 @@ static int alloc_nand_resource(struct platform_device *pdev) ...@@ -1191,9 +1202,13 @@ static int alloc_nand_resource(struct platform_device *pdev)
} }
info->mmio_phys = r->start; info->mmio_phys = r->start;
ret = pxa3xx_nand_init_buff(info); /* Allocate a buffer to allow flash detection */
if (ret) info->buf_size = INIT_BUFFER_SIZE;
info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
if (info->data_buff == NULL) {
ret = -ENOMEM;
goto fail_disable_clk; goto fail_disable_clk;
}
/* initialize all interrupts to be disabled */ /* initialize all interrupts to be disabled */
disable_int(info, NDSR_MASK); disable_int(info, NDSR_MASK);
...@@ -1211,7 +1226,7 @@ static int alloc_nand_resource(struct platform_device *pdev) ...@@ -1211,7 +1226,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
fail_free_buf: fail_free_buf:
free_irq(irq, info); free_irq(irq, info);
pxa3xx_nand_free_buff(info); kfree(info->data_buff);
fail_disable_clk: fail_disable_clk:
clk_disable_unprepare(info->clk); clk_disable_unprepare(info->clk);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment