mvebu: backport mainline patches from kernel 3.13
[openwrt.git] / target / linux / mvebu / patches-3.10 / 0130-mtd-nand-pxa3xx-Allocate-data-buffer-on-detected-fla.patch
1 From 71d6267980d7590e38059a784785ca158e361f87 Mon Sep 17 00:00:00 2001
2 From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
3 Date: Fri, 4 Oct 2013 15:30:38 -0300
4 Subject: [PATCH 130/203] mtd: nand: pxa3xx: Allocate data buffer on detected
5  flash size
6
7 This commit replaces the currently hardcoded buffer size, by a
8 dynamic detection scheme. First a small 256 bytes buffer is allocated
9 so the device can be detected (using READID and friends commands).
10
11 After detection, this buffer is released and a new buffer is allocated
12 to acommodate the page size plus out-of-band size.
13
14 Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
15 Tested-by: Daniel Mack <zonque@gmail.com>
16 Signed-off-by: Brian Norris <computersforpeace@gmail.com>
17 ---
18  drivers/mtd/nand/pxa3xx_nand.c | 45 ++++++++++++++++++++++++++++--------------
19  1 file changed, 30 insertions(+), 15 deletions(-)
20
21 --- a/drivers/mtd/nand/pxa3xx_nand.c
22 +++ b/drivers/mtd/nand/pxa3xx_nand.c
23 @@ -39,6 +39,13 @@
24  #define NAND_STOP_DELAY                (2 * HZ/50)
25  #define PAGE_CHUNK_SIZE                (2048)
26  
27 +/*
28 + * Define a buffer size for the initial command that detects the flash device:
29 + * STATUS, READID and PARAM. The largest of these is the PARAM command,
30 + * needing 256 bytes.
31 + */
32 +#define INIT_BUFFER_SIZE       256
33 +
34  /* registers and bit definitions */
35  #define NDCR           (0x00) /* Control register */
36  #define NDTR0CS0       (0x04) /* Timing Parameter 0 for CS0 */
37 @@ -164,6 +171,7 @@ struct pxa3xx_nand_info {
38  
39         unsigned int            buf_start;
40         unsigned int            buf_count;
41 +       unsigned int            buf_size;
42  
43         /* DMA information */
44         int                     drcmr_dat;
45 @@ -911,26 +919,20 @@ static int pxa3xx_nand_detect_config(str
46         return 0;
47  }
48  
49 -/* the maximum possible buffer size for large page with OOB data
50 - * is: 2048 + 64 = 2112 bytes, allocate a page here for both the
51 - * data buffer and the DMA descriptor
52 - */
53 -#define MAX_BUFF_SIZE  PAGE_SIZE
54 -
55  #ifdef ARCH_HAS_DMA
56  static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
57  {
58         struct platform_device *pdev = info->pdev;
59 -       int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc);
60 +       int data_desc_offset = info->buf_size - sizeof(struct pxa_dma_desc);
61  
62         if (use_dma == 0) {
63 -               info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
64 +               info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
65                 if (info->data_buff == NULL)
66                         return -ENOMEM;
67                 return 0;
68         }
69  
70 -       info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
71 +       info->data_buff = dma_alloc_coherent(&pdev->dev, info->buf_size,
72                                 &info->data_buff_phys, GFP_KERNEL);
73         if (info->data_buff == NULL) {
74                 dev_err(&pdev->dev, "failed to allocate dma buffer\n");
75 @@ -944,7 +946,7 @@ static int pxa3xx_nand_init_buff(struct
76                                 pxa3xx_nand_data_dma_irq, info);
77         if (info->data_dma_ch < 0) {
78                 dev_err(&pdev->dev, "failed to request data dma\n");
79 -               dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE,
80 +               dma_free_coherent(&pdev->dev, info->buf_size,
81                                 info->data_buff, info->data_buff_phys);
82                 return info->data_dma_ch;
83         }
84 @@ -962,7 +964,7 @@ static void pxa3xx_nand_free_buff(struct
85         struct platform_device *pdev = info->pdev;
86         if (use_dma) {
87                 pxa_free_dma(info->data_dma_ch);
88 -               dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE,
89 +               dma_free_coherent(&pdev->dev, info->buf_size,
90                                   info->data_buff, info->data_buff_phys);
91         } else {
92                 kfree(info->data_buff);
93 @@ -971,7 +973,7 @@ static void pxa3xx_nand_free_buff(struct
94  #else
95  static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
96  {
97 -       info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
98 +       info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
99         if (info->data_buff == NULL)
100                 return -ENOMEM;
101         return 0;
102 @@ -1085,7 +1087,16 @@ KEEP_CONFIG:
103         else
104                 host->col_addr_cycles = 1;
105  
106 +       /* release the initial buffer */
107 +       kfree(info->data_buff);
108 +
109 +       /* allocate the real data + oob buffer */
110 +       info->buf_size = mtd->writesize + mtd->oobsize;
111 +       ret = pxa3xx_nand_init_buff(info);
112 +       if (ret)
113 +               return ret;
114         info->oob_buff = info->data_buff + mtd->writesize;
115 +
116         if ((mtd->size >> chip->page_shift) > 65536)
117                 host->row_addr_cycles = 3;
118         else
119 @@ -1191,9 +1202,13 @@ static int alloc_nand_resource(struct pl
120         }
121         info->mmio_phys = r->start;
122  
123 -       ret = pxa3xx_nand_init_buff(info);
124 -       if (ret)
125 +       /* Allocate a buffer to allow flash detection */
126 +       info->buf_size = INIT_BUFFER_SIZE;
127 +       info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
128 +       if (info->data_buff == NULL) {
129 +               ret = -ENOMEM;
130                 goto fail_disable_clk;
131 +       }
132  
133         /* initialize all interrupts to be disabled */
134         disable_int(info, NDSR_MASK);
135 @@ -1211,7 +1226,7 @@ static int alloc_nand_resource(struct pl
136  
137  fail_free_buf:
138         free_irq(irq, info);
139 -       pxa3xx_nand_free_buff(info);
140 +       kfree(info->data_buff);
141  fail_disable_clk:
142         clk_disable_unprepare(info->clk);
143         return ret;