diff options
author | Ezequiel Garcia <ezequiel.garcia@free-electrons.com> | 2013-10-04 14:30:38 -0400 |
---|---|---|
committer | Brian Norris <computersforpeace@gmail.com> | 2013-11-07 02:32:54 -0500 |
commit | 62e8b851783138a11da63285be0fbf69530ff73d (patch) | |
tree | 5c284713748762bc11fa9575a373a4e87aa4b187 /drivers/mtd | |
parent | 95b26563c739d5ed5101318b1bd8895773a3d872 (diff) |
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: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Tested-by: Daniel Mack <zonque@gmail.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/pxa3xx_nand.c | 45 |
1 files changed, 30 insertions, 15 deletions
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 287997487b95..64c258ec0170 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -39,6 +39,13 @@ | |||
39 | #define NAND_STOP_DELAY (2 * HZ/50) | 39 | #define NAND_STOP_DELAY (2 * HZ/50) |
40 | #define PAGE_CHUNK_SIZE (2048) | 40 | #define PAGE_CHUNK_SIZE (2048) |
41 | 41 | ||
42 | /* | ||
43 | * Define a buffer size for the initial command that detects the flash device: | ||
44 | * STATUS, READID and PARAM. The largest of these is the PARAM command, | ||
45 | * needing 256 bytes. | ||
46 | */ | ||
47 | #define INIT_BUFFER_SIZE 256 | ||
48 | |||
42 | /* registers and bit definitions */ | 49 | /* registers and bit definitions */ |
43 | #define NDCR (0x00) /* Control register */ | 50 | #define NDCR (0x00) /* Control register */ |
44 | #define NDTR0CS0 (0x04) /* Timing Parameter 0 for CS0 */ | 51 | #define NDTR0CS0 (0x04) /* Timing Parameter 0 for CS0 */ |
@@ -164,6 +171,7 @@ struct pxa3xx_nand_info { | |||
164 | 171 | ||
165 | unsigned int buf_start; | 172 | unsigned int buf_start; |
166 | unsigned int buf_count; | 173 | unsigned int buf_count; |
174 | unsigned int buf_size; | ||
167 | 175 | ||
168 | /* DMA information */ | 176 | /* DMA information */ |
169 | int drcmr_dat; | 177 | int drcmr_dat; |
@@ -911,26 +919,20 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) | |||
911 | return 0; | 919 | return 0; |
912 | } | 920 | } |
913 | 921 | ||
914 | /* the maximum possible buffer size for large page with OOB data | ||
915 | * is: 2048 + 64 = 2112 bytes, allocate a page here for both the | ||
916 | * data buffer and the DMA descriptor | ||
917 | */ | ||
918 | #define MAX_BUFF_SIZE PAGE_SIZE | ||
919 | |||
920 | #ifdef ARCH_HAS_DMA | 922 | #ifdef ARCH_HAS_DMA |
921 | static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) | 923 | static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) |
922 | { | 924 | { |
923 | struct platform_device *pdev = info->pdev; | 925 | struct platform_device *pdev = info->pdev; |
924 | int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc); | 926 | int data_desc_offset = info->buf_size - sizeof(struct pxa_dma_desc); |
925 | 927 | ||
926 | if (use_dma == 0) { | 928 | if (use_dma == 0) { |
927 | info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL); | 929 | info->data_buff = kmalloc(info->buf_size, GFP_KERNEL); |
928 | if (info->data_buff == NULL) | 930 | if (info->data_buff == NULL) |
929 | return -ENOMEM; | 931 | return -ENOMEM; |
930 | return 0; | 932 | return 0; |
931 | } | 933 | } |
932 | 934 | ||
933 | info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE, | 935 | info->data_buff = dma_alloc_coherent(&pdev->dev, info->buf_size, |
934 | &info->data_buff_phys, GFP_KERNEL); | 936 | &info->data_buff_phys, GFP_KERNEL); |
935 | if (info->data_buff == NULL) { | 937 | if (info->data_buff == NULL) { |
936 | dev_err(&pdev->dev, "failed to allocate dma buffer\n"); | 938 | 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 | pxa3xx_nand_data_dma_irq, info); | 946 | pxa3xx_nand_data_dma_irq, info); |
945 | if (info->data_dma_ch < 0) { | 947 | if (info->data_dma_ch < 0) { |
946 | dev_err(&pdev->dev, "failed to request data dma\n"); | 948 | dev_err(&pdev->dev, "failed to request data dma\n"); |
947 | dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE, | 949 | dma_free_coherent(&pdev->dev, info->buf_size, |
948 | info->data_buff, info->data_buff_phys); | 950 | info->data_buff, info->data_buff_phys); |
949 | return info->data_dma_ch; | 951 | return info->data_dma_ch; |
950 | } | 952 | } |
@@ -962,7 +964,7 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info) | |||
962 | struct platform_device *pdev = info->pdev; | 964 | struct platform_device *pdev = info->pdev; |
963 | if (use_dma) { | 965 | if (use_dma) { |
964 | pxa_free_dma(info->data_dma_ch); | 966 | pxa_free_dma(info->data_dma_ch); |
965 | dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE, | 967 | dma_free_coherent(&pdev->dev, info->buf_size, |
966 | info->data_buff, info->data_buff_phys); | 968 | info->data_buff, info->data_buff_phys); |
967 | } else { | 969 | } else { |
968 | kfree(info->data_buff); | 970 | kfree(info->data_buff); |
@@ -971,7 +973,7 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info) | |||
971 | #else | 973 | #else |
972 | static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) | 974 | static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) |
973 | { | 975 | { |
974 | info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL); | 976 | info->data_buff = kmalloc(info->buf_size, GFP_KERNEL); |
975 | if (info->data_buff == NULL) | 977 | if (info->data_buff == NULL) |
976 | return -ENOMEM; | 978 | return -ENOMEM; |
977 | return 0; | 979 | return 0; |
@@ -1085,7 +1087,16 @@ KEEP_CONFIG: | |||
1085 | else | 1087 | else |
1086 | host->col_addr_cycles = 1; | 1088 | host->col_addr_cycles = 1; |
1087 | 1089 | ||
1090 | /* release the initial buffer */ | ||
1091 | kfree(info->data_buff); | ||
1092 | |||
1093 | /* allocate the real data + oob buffer */ | ||
1094 | info->buf_size = mtd->writesize + mtd->oobsize; | ||
1095 | ret = pxa3xx_nand_init_buff(info); | ||
1096 | if (ret) | ||
1097 | return ret; | ||
1088 | info->oob_buff = info->data_buff + mtd->writesize; | 1098 | info->oob_buff = info->data_buff + mtd->writesize; |
1099 | |||
1089 | if ((mtd->size >> chip->page_shift) > 65536) | 1100 | if ((mtd->size >> chip->page_shift) > 65536) |
1090 | host->row_addr_cycles = 3; | 1101 | host->row_addr_cycles = 3; |
1091 | else | 1102 | else |
@@ -1191,9 +1202,13 @@ static int alloc_nand_resource(struct platform_device *pdev) | |||
1191 | } | 1202 | } |
1192 | info->mmio_phys = r->start; | 1203 | info->mmio_phys = r->start; |
1193 | 1204 | ||
1194 | ret = pxa3xx_nand_init_buff(info); | 1205 | /* Allocate a buffer to allow flash detection */ |
1195 | if (ret) | 1206 | info->buf_size = INIT_BUFFER_SIZE; |
1207 | info->data_buff = kmalloc(info->buf_size, GFP_KERNEL); | ||
1208 | if (info->data_buff == NULL) { | ||
1209 | ret = -ENOMEM; | ||
1196 | goto fail_disable_clk; | 1210 | goto fail_disable_clk; |
1211 | } | ||
1197 | 1212 | ||
1198 | /* initialize all interrupts to be disabled */ | 1213 | /* initialize all interrupts to be disabled */ |
1199 | disable_int(info, NDSR_MASK); | 1214 | disable_int(info, NDSR_MASK); |
@@ -1211,7 +1226,7 @@ static int alloc_nand_resource(struct platform_device *pdev) | |||
1211 | 1226 | ||
1212 | fail_free_buf: | 1227 | fail_free_buf: |
1213 | free_irq(irq, info); | 1228 | free_irq(irq, info); |
1214 | pxa3xx_nand_free_buff(info); | 1229 | kfree(info->data_buff); |
1215 | fail_disable_clk: | 1230 | fail_disable_clk: |
1216 | clk_disable_unprepare(info->clk); | 1231 | clk_disable_unprepare(info->clk); |
1217 | return ret; | 1232 | return ret; |