diff options
Diffstat (limited to 'drivers/mtd/nand/pxa3xx_nand.c')
-rw-r--r-- | drivers/mtd/nand/pxa3xx_nand.c | 147 |
1 files changed, 77 insertions, 70 deletions
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index a64ad15b8fdd..c0fa9c9edf08 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -115,55 +115,11 @@ enum { | |||
115 | STATE_PIO_WRITING, | 115 | STATE_PIO_WRITING, |
116 | }; | 116 | }; |
117 | 117 | ||
118 | struct pxa3xx_nand_timing { | ||
119 | unsigned int tCH; /* Enable signal hold time */ | ||
120 | unsigned int tCS; /* Enable signal setup time */ | ||
121 | unsigned int tWH; /* ND_nWE high duration */ | ||
122 | unsigned int tWP; /* ND_nWE pulse time */ | ||
123 | unsigned int tRH; /* ND_nRE high duration */ | ||
124 | unsigned int tRP; /* ND_nRE pulse width */ | ||
125 | unsigned int tR; /* ND_nWE high to ND_nRE low for read */ | ||
126 | unsigned int tWHR; /* ND_nWE high to ND_nRE low for status read */ | ||
127 | unsigned int tAR; /* ND_ALE low to ND_nRE low delay */ | ||
128 | }; | ||
129 | |||
130 | struct pxa3xx_nand_cmdset { | ||
131 | uint16_t read1; | ||
132 | uint16_t read2; | ||
133 | uint16_t program; | ||
134 | uint16_t read_status; | ||
135 | uint16_t read_id; | ||
136 | uint16_t erase; | ||
137 | uint16_t reset; | ||
138 | uint16_t lock; | ||
139 | uint16_t unlock; | ||
140 | uint16_t lock_status; | ||
141 | }; | ||
142 | |||
143 | struct pxa3xx_nand_flash { | ||
144 | struct pxa3xx_nand_timing *timing; /* NAND Flash timing */ | ||
145 | struct pxa3xx_nand_cmdset *cmdset; | ||
146 | |||
147 | uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */ | ||
148 | uint32_t page_size; /* Page size in bytes (PAGE_SZ) */ | ||
149 | uint32_t flash_width; /* Width of Flash memory (DWIDTH_M) */ | ||
150 | uint32_t dfc_width; /* Width of flash controller(DWIDTH_C) */ | ||
151 | uint32_t num_blocks; /* Number of physical blocks in Flash */ | ||
152 | uint32_t chip_id; | ||
153 | |||
154 | /* NOTE: these are automatically calculated, do not define */ | ||
155 | size_t oob_size; | ||
156 | size_t read_id_bytes; | ||
157 | |||
158 | unsigned int col_addr_cycles; | ||
159 | unsigned int row_addr_cycles; | ||
160 | }; | ||
161 | |||
162 | struct pxa3xx_nand_info { | 118 | struct pxa3xx_nand_info { |
163 | struct nand_chip nand_chip; | 119 | struct nand_chip nand_chip; |
164 | 120 | ||
165 | struct platform_device *pdev; | 121 | struct platform_device *pdev; |
166 | struct pxa3xx_nand_flash *flash_info; | 122 | const struct pxa3xx_nand_flash *flash_info; |
167 | 123 | ||
168 | struct clk *clk; | 124 | struct clk *clk; |
169 | void __iomem *mmio_base; | 125 | void __iomem *mmio_base; |
@@ -202,12 +158,20 @@ struct pxa3xx_nand_info { | |||
202 | uint32_t ndcb0; | 158 | uint32_t ndcb0; |
203 | uint32_t ndcb1; | 159 | uint32_t ndcb1; |
204 | uint32_t ndcb2; | 160 | uint32_t ndcb2; |
161 | |||
162 | /* calculated from pxa3xx_nand_flash data */ | ||
163 | size_t oob_size; | ||
164 | size_t read_id_bytes; | ||
165 | |||
166 | unsigned int col_addr_cycles; | ||
167 | unsigned int row_addr_cycles; | ||
205 | }; | 168 | }; |
206 | 169 | ||
207 | static int use_dma = 1; | 170 | static int use_dma = 1; |
208 | module_param(use_dma, bool, 0444); | 171 | module_param(use_dma, bool, 0444); |
209 | MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW"); | 172 | MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW"); |
210 | 173 | ||
174 | #ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN | ||
211 | static struct pxa3xx_nand_cmdset smallpage_cmdset = { | 175 | static struct pxa3xx_nand_cmdset smallpage_cmdset = { |
212 | .read1 = 0x0000, | 176 | .read1 = 0x0000, |
213 | .read2 = 0x0050, | 177 | .read2 = 0x0050, |
@@ -291,11 +255,35 @@ static struct pxa3xx_nand_flash micron1GbX16 = { | |||
291 | .chip_id = 0xb12c, | 255 | .chip_id = 0xb12c, |
292 | }; | 256 | }; |
293 | 257 | ||
258 | static struct pxa3xx_nand_timing stm2GbX16_timing = { | ||
259 | .tCH = 10, | ||
260 | .tCS = 35, | ||
261 | .tWH = 15, | ||
262 | .tWP = 25, | ||
263 | .tRH = 15, | ||
264 | .tRP = 25, | ||
265 | .tR = 25000, | ||
266 | .tWHR = 60, | ||
267 | .tAR = 10, | ||
268 | }; | ||
269 | |||
270 | static struct pxa3xx_nand_flash stm2GbX16 = { | ||
271 | .timing = &stm2GbX16_timing, | ||
272 | .page_per_block = 64, | ||
273 | .page_size = 2048, | ||
274 | .flash_width = 16, | ||
275 | .dfc_width = 16, | ||
276 | .num_blocks = 2048, | ||
277 | .chip_id = 0xba20, | ||
278 | }; | ||
279 | |||
294 | static struct pxa3xx_nand_flash *builtin_flash_types[] = { | 280 | static struct pxa3xx_nand_flash *builtin_flash_types[] = { |
295 | &samsung512MbX16, | 281 | &samsung512MbX16, |
296 | µn1GbX8, | 282 | µn1GbX8, |
297 | µn1GbX16, | 283 | µn1GbX16, |
284 | &stm2GbX16, | ||
298 | }; | 285 | }; |
286 | #endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */ | ||
299 | 287 | ||
300 | #define NDTR0_tCH(c) (min((c), 7) << 19) | 288 | #define NDTR0_tCH(c) (min((c), 7) << 19) |
301 | #define NDTR0_tCS(c) (min((c), 7) << 16) | 289 | #define NDTR0_tCS(c) (min((c), 7) << 16) |
@@ -312,7 +300,7 @@ static struct pxa3xx_nand_flash *builtin_flash_types[] = { | |||
312 | #define ns2cycle(ns, clk) (int)(((ns) * (clk / 1000000) / 1000) + 1) | 300 | #define ns2cycle(ns, clk) (int)(((ns) * (clk / 1000000) / 1000) + 1) |
313 | 301 | ||
314 | static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, | 302 | static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, |
315 | struct pxa3xx_nand_timing *t) | 303 | const struct pxa3xx_nand_timing *t) |
316 | { | 304 | { |
317 | unsigned long nand_clk = clk_get_rate(info->clk); | 305 | unsigned long nand_clk = clk_get_rate(info->clk); |
318 | uint32_t ndtr0, ndtr1; | 306 | uint32_t ndtr0, ndtr1; |
@@ -354,8 +342,8 @@ static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event) | |||
354 | static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, | 342 | static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, |
355 | uint16_t cmd, int column, int page_addr) | 343 | uint16_t cmd, int column, int page_addr) |
356 | { | 344 | { |
357 | struct pxa3xx_nand_flash *f = info->flash_info; | 345 | const struct pxa3xx_nand_flash *f = info->flash_info; |
358 | struct pxa3xx_nand_cmdset *cmdset = f->cmdset; | 346 | const struct pxa3xx_nand_cmdset *cmdset = f->cmdset; |
359 | 347 | ||
360 | /* calculate data size */ | 348 | /* calculate data size */ |
361 | switch (f->page_size) { | 349 | switch (f->page_size) { |
@@ -373,14 +361,14 @@ static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, | |||
373 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); | 361 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); |
374 | info->ndcb1 = 0; | 362 | info->ndcb1 = 0; |
375 | info->ndcb2 = 0; | 363 | info->ndcb2 = 0; |
376 | info->ndcb0 |= NDCB0_ADDR_CYC(f->row_addr_cycles + f->col_addr_cycles); | 364 | info->ndcb0 |= NDCB0_ADDR_CYC(info->row_addr_cycles + info->col_addr_cycles); |
377 | 365 | ||
378 | if (f->col_addr_cycles == 2) { | 366 | if (info->col_addr_cycles == 2) { |
379 | /* large block, 2 cycles for column address | 367 | /* large block, 2 cycles for column address |
380 | * row address starts from 3rd cycle | 368 | * row address starts from 3rd cycle |
381 | */ | 369 | */ |
382 | info->ndcb1 |= (page_addr << 16) | (column & 0xffff); | 370 | info->ndcb1 |= (page_addr << 16) | (column & 0xffff); |
383 | if (f->row_addr_cycles == 3) | 371 | if (info->row_addr_cycles == 3) |
384 | info->ndcb2 = (page_addr >> 16) & 0xff; | 372 | info->ndcb2 = (page_addr >> 16) & 0xff; |
385 | } else | 373 | } else |
386 | /* small block, 1 cycles for column address | 374 | /* small block, 1 cycles for column address |
@@ -406,7 +394,7 @@ static int prepare_erase_cmd(struct pxa3xx_nand_info *info, | |||
406 | 394 | ||
407 | static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) | 395 | static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) |
408 | { | 396 | { |
409 | struct pxa3xx_nand_cmdset *cmdset = info->flash_info->cmdset; | 397 | const struct pxa3xx_nand_cmdset *cmdset = info->flash_info->cmdset; |
410 | 398 | ||
411 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); | 399 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); |
412 | info->ndcb1 = 0; | 400 | info->ndcb1 = 0; |
@@ -641,8 +629,8 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
641 | int column, int page_addr) | 629 | int column, int page_addr) |
642 | { | 630 | { |
643 | struct pxa3xx_nand_info *info = mtd->priv; | 631 | struct pxa3xx_nand_info *info = mtd->priv; |
644 | struct pxa3xx_nand_flash *flash_info = info->flash_info; | 632 | const struct pxa3xx_nand_flash *flash_info = info->flash_info; |
645 | struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset; | 633 | const struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset; |
646 | int ret; | 634 | int ret; |
647 | 635 | ||
648 | info->use_dma = (use_dma) ? 1 : 0; | 636 | info->use_dma = (use_dma) ? 1 : 0; |
@@ -720,7 +708,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
720 | info->use_dma = 0; /* force PIO read */ | 708 | info->use_dma = 0; /* force PIO read */ |
721 | info->buf_start = 0; | 709 | info->buf_start = 0; |
722 | info->buf_count = (command == NAND_CMD_READID) ? | 710 | info->buf_count = (command == NAND_CMD_READID) ? |
723 | flash_info->read_id_bytes : 1; | 711 | info->read_id_bytes : 1; |
724 | 712 | ||
725 | if (prepare_other_cmd(info, (command == NAND_CMD_READID) ? | 713 | if (prepare_other_cmd(info, (command == NAND_CMD_READID) ? |
726 | cmdset->read_id : cmdset->read_status)) | 714 | cmdset->read_id : cmdset->read_status)) |
@@ -861,8 +849,8 @@ static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd, | |||
861 | 849 | ||
862 | static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) | 850 | static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) |
863 | { | 851 | { |
864 | struct pxa3xx_nand_flash *f = info->flash_info; | 852 | const struct pxa3xx_nand_flash *f = info->flash_info; |
865 | struct pxa3xx_nand_cmdset *cmdset = f->cmdset; | 853 | const struct pxa3xx_nand_cmdset *cmdset = f->cmdset; |
866 | uint32_t ndcr; | 854 | uint32_t ndcr; |
867 | uint8_t id_buff[8]; | 855 | uint8_t id_buff[8]; |
868 | 856 | ||
@@ -891,7 +879,7 @@ fail_timeout: | |||
891 | } | 879 | } |
892 | 880 | ||
893 | static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, | 881 | static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, |
894 | struct pxa3xx_nand_flash *f) | 882 | const struct pxa3xx_nand_flash *f) |
895 | { | 883 | { |
896 | struct platform_device *pdev = info->pdev; | 884 | struct platform_device *pdev = info->pdev; |
897 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; | 885 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; |
@@ -904,25 +892,25 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, | |||
904 | return -EINVAL; | 892 | return -EINVAL; |
905 | 893 | ||
906 | /* calculate flash information */ | 894 | /* calculate flash information */ |
907 | f->oob_size = (f->page_size == 2048) ? 64 : 16; | 895 | info->oob_size = (f->page_size == 2048) ? 64 : 16; |
908 | f->read_id_bytes = (f->page_size == 2048) ? 4 : 2; | 896 | info->read_id_bytes = (f->page_size == 2048) ? 4 : 2; |
909 | 897 | ||
910 | /* calculate addressing information */ | 898 | /* calculate addressing information */ |
911 | f->col_addr_cycles = (f->page_size == 2048) ? 2 : 1; | 899 | info->col_addr_cycles = (f->page_size == 2048) ? 2 : 1; |
912 | 900 | ||
913 | if (f->num_blocks * f->page_per_block > 65536) | 901 | if (f->num_blocks * f->page_per_block > 65536) |
914 | f->row_addr_cycles = 3; | 902 | info->row_addr_cycles = 3; |
915 | else | 903 | else |
916 | f->row_addr_cycles = 2; | 904 | info->row_addr_cycles = 2; |
917 | 905 | ||
918 | ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; | 906 | ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; |
919 | ndcr |= (f->col_addr_cycles == 2) ? NDCR_RA_START : 0; | 907 | ndcr |= (info->col_addr_cycles == 2) ? NDCR_RA_START : 0; |
920 | ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0; | 908 | ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0; |
921 | ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0; | 909 | ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0; |
922 | ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0; | 910 | ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0; |
923 | ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0; | 911 | ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0; |
924 | 912 | ||
925 | ndcr |= NDCR_RD_ID_CNT(f->read_id_bytes); | 913 | ndcr |= NDCR_RD_ID_CNT(info->read_id_bytes); |
926 | ndcr |= NDCR_SPARE_EN; /* enable spare by default */ | 914 | ndcr |= NDCR_SPARE_EN; /* enable spare by default */ |
927 | 915 | ||
928 | info->reg_ndcr = ndcr; | 916 | info->reg_ndcr = ndcr; |
@@ -932,12 +920,27 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, | |||
932 | return 0; | 920 | return 0; |
933 | } | 921 | } |
934 | 922 | ||
935 | static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info) | 923 | static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, |
924 | const struct pxa3xx_nand_platform_data *pdata) | ||
936 | { | 925 | { |
937 | struct pxa3xx_nand_flash *f; | 926 | const struct pxa3xx_nand_flash *f; |
938 | uint32_t id; | 927 | uint32_t id = -1; |
939 | int i; | 928 | int i; |
940 | 929 | ||
930 | for (i = 0; i<pdata->num_flash; ++i) { | ||
931 | f = pdata->flash + i; | ||
932 | |||
933 | if (pxa3xx_nand_config_flash(info, f)) | ||
934 | continue; | ||
935 | |||
936 | if (__readid(info, &id)) | ||
937 | continue; | ||
938 | |||
939 | if (id == f->chip_id) | ||
940 | return 0; | ||
941 | } | ||
942 | |||
943 | #ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN | ||
941 | for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) { | 944 | for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) { |
942 | 945 | ||
943 | f = builtin_flash_types[i]; | 946 | f = builtin_flash_types[i]; |
@@ -951,7 +954,11 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info) | |||
951 | if (id == f->chip_id) | 954 | if (id == f->chip_id) |
952 | return 0; | 955 | return 0; |
953 | } | 956 | } |
957 | #endif | ||
954 | 958 | ||
959 | dev_warn(&info->pdev->dev, | ||
960 | "failed to detect configured nand flash; found %04x instead of\n", | ||
961 | id); | ||
955 | return -ENODEV; | 962 | return -ENODEV; |
956 | } | 963 | } |
957 | 964 | ||
@@ -1014,7 +1021,7 @@ static struct nand_ecclayout hw_largepage_ecclayout = { | |||
1014 | static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, | 1021 | static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, |
1015 | struct pxa3xx_nand_info *info) | 1022 | struct pxa3xx_nand_info *info) |
1016 | { | 1023 | { |
1017 | struct pxa3xx_nand_flash *f = info->flash_info; | 1024 | const struct pxa3xx_nand_flash *f = info->flash_info; |
1018 | struct nand_chip *this = &info->nand_chip; | 1025 | struct nand_chip *this = &info->nand_chip; |
1019 | 1026 | ||
1020 | this->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0; | 1027 | this->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0; |
@@ -1135,7 +1142,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1135 | goto fail_free_buf; | 1142 | goto fail_free_buf; |
1136 | } | 1143 | } |
1137 | 1144 | ||
1138 | ret = pxa3xx_nand_detect_flash(info); | 1145 | ret = pxa3xx_nand_detect_flash(info, pdata); |
1139 | if (ret) { | 1146 | if (ret) { |
1140 | dev_err(&pdev->dev, "failed to detect flash\n"); | 1147 | dev_err(&pdev->dev, "failed to detect flash\n"); |
1141 | ret = -ENODEV; | 1148 | ret = -ENODEV; |