diff options
author | Lei Wen <leiwen@marvell.com> | 2011-02-27 21:32:14 -0500 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2011-03-11 09:22:51 -0500 |
commit | 401e67e225f350757e11e39392dcc6a0fddcea63 (patch) | |
tree | c10b3f1308095e2458147af459f20cd28aa3a240 /drivers/mtd/nand | |
parent | 4eb2da8994042d68e84e31138788429a102da2ea (diff) |
mtd: pxa3xx_nand: mtd scan id process could be defined by driver itself
Different NAND driver may require its unique detection. For pxa3xx_nand,
it use its self id database to get the necessary info.
Signed-off-by: Lei Wen <leiwen@marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r-- | drivers/mtd/nand/pxa3xx_nand.c | 216 |
1 files changed, 123 insertions, 93 deletions
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index de0a2a25eb01..bb50cf2b11c4 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -123,6 +123,7 @@ enum { | |||
123 | struct pxa3xx_nand_info { | 123 | struct pxa3xx_nand_info { |
124 | struct nand_chip nand_chip; | 124 | struct nand_chip nand_chip; |
125 | 125 | ||
126 | struct nand_hw_control controller; | ||
126 | struct platform_device *pdev; | 127 | struct platform_device *pdev; |
127 | struct pxa3xx_nand_cmdset *cmdset; | 128 | struct pxa3xx_nand_cmdset *cmdset; |
128 | 129 | ||
@@ -157,6 +158,7 @@ struct pxa3xx_nand_info { | |||
157 | 158 | ||
158 | int use_ecc; /* use HW ECC ? */ | 159 | int use_ecc; /* use HW ECC ? */ |
159 | int use_dma; /* use DMA ? */ | 160 | int use_dma; /* use DMA ? */ |
161 | int is_ready; | ||
160 | 162 | ||
161 | unsigned int page_size; /* page size of attached chip */ | 163 | unsigned int page_size; /* page size of attached chip */ |
162 | unsigned int data_size; /* data size in FIFO */ | 164 | unsigned int data_size; /* data size in FIFO */ |
@@ -223,6 +225,8 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = { | |||
223 | /* Define a default flash type setting serve as flash detecting only */ | 225 | /* Define a default flash type setting serve as flash detecting only */ |
224 | #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0]) | 226 | #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0]) |
225 | 227 | ||
228 | const char *mtd_names[] = {"pxa3xx_nand-0", NULL}; | ||
229 | |||
226 | #define NDTR0_tCH(c) (min((c), 7) << 19) | 230 | #define NDTR0_tCH(c) (min((c), 7) << 19) |
227 | #define NDTR0_tCS(c) (min((c), 7) << 16) | 231 | #define NDTR0_tCS(c) (min((c), 7) << 16) |
228 | #define NDTR0_tWH(c) (min((c), 7) << 11) | 232 | #define NDTR0_tWH(c) (min((c), 7) << 11) |
@@ -437,8 +441,10 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) | |||
437 | info->state = STATE_CMD_DONE; | 441 | info->state = STATE_CMD_DONE; |
438 | is_completed = 1; | 442 | is_completed = 1; |
439 | } | 443 | } |
440 | if (status & NDSR_FLASH_RDY) | 444 | if (status & NDSR_FLASH_RDY) { |
445 | info->is_ready = 1; | ||
441 | info->state = STATE_READY; | 446 | info->state = STATE_READY; |
447 | } | ||
442 | 448 | ||
443 | if (status & NDSR_WRCMDREQ) { | 449 | if (status & NDSR_WRCMDREQ) { |
444 | nand_writel(info, NDSR, NDSR_WRCMDREQ); | 450 | nand_writel(info, NDSR, NDSR_WRCMDREQ); |
@@ -483,10 +489,11 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
483 | exec_cmd = 1; | 489 | exec_cmd = 1; |
484 | 490 | ||
485 | /* reset data and oob column point to handle data */ | 491 | /* reset data and oob column point to handle data */ |
486 | info->buf_start = 0; | 492 | info->buf_start = 0; |
487 | info->buf_count = 0; | 493 | info->buf_count = 0; |
488 | info->oob_size = 0; | 494 | info->oob_size = 0; |
489 | info->use_ecc = 0; | 495 | info->use_ecc = 0; |
496 | info->is_ready = 0; | ||
490 | info->retcode = ERR_NONE; | 497 | info->retcode = ERR_NONE; |
491 | 498 | ||
492 | switch (command) { | 499 | switch (command) { |
@@ -849,42 +856,6 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) | |||
849 | return 0; | 856 | return 0; |
850 | } | 857 | } |
851 | 858 | ||
852 | static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, | ||
853 | const struct pxa3xx_nand_platform_data *pdata) | ||
854 | { | ||
855 | const struct pxa3xx_nand_flash *f; | ||
856 | uint32_t id = -1; | ||
857 | int i; | ||
858 | |||
859 | if (pdata->keep_config) | ||
860 | if (pxa3xx_nand_detect_config(info) == 0) | ||
861 | return 0; | ||
862 | |||
863 | /* we use default timing to detect id */ | ||
864 | f = DEFAULT_FLASH_TYPE; | ||
865 | pxa3xx_nand_config_flash(info, f); | ||
866 | pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0); | ||
867 | id = *((uint16_t *)(info->data_buff)); | ||
868 | |||
869 | for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) { | ||
870 | /* we first choose the flash definition from platfrom */ | ||
871 | if (i < pdata->num_flash) | ||
872 | f = pdata->flash + i; | ||
873 | else | ||
874 | f = &builtin_flash_types[i - pdata->num_flash + 1]; | ||
875 | if (f->chip_id == id) { | ||
876 | dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id); | ||
877 | pxa3xx_nand_config_flash(info, f); | ||
878 | return 0; | ||
879 | } | ||
880 | } | ||
881 | |||
882 | dev_warn(&info->pdev->dev, | ||
883 | "failed to detect configured nand flash; found %04x instead of\n", | ||
884 | id); | ||
885 | return -ENODEV; | ||
886 | } | ||
887 | |||
888 | /* the maximum possible buffer size for large page with OOB data | 859 | /* the maximum possible buffer size for large page with OOB data |
889 | * is: 2048 + 64 = 2112 bytes, allocate a page here for both the | 860 | * is: 2048 + 64 = 2112 bytes, allocate a page here for both the |
890 | * data buffer and the DMA descriptor | 861 | * data buffer and the DMA descriptor |
@@ -926,57 +897,110 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) | |||
926 | return 0; | 897 | return 0; |
927 | } | 898 | } |
928 | 899 | ||
929 | static struct nand_ecclayout hw_smallpage_ecclayout = { | 900 | static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) |
930 | .eccbytes = 6, | 901 | { |
931 | .eccpos = {8, 9, 10, 11, 12, 13 }, | 902 | struct mtd_info *mtd = info->mtd; |
932 | .oobfree = { {2, 6} } | 903 | struct nand_chip *chip = mtd->priv; |
933 | }; | ||
934 | 904 | ||
935 | static struct nand_ecclayout hw_largepage_ecclayout = { | 905 | /* use the common timing to make a try */ |
936 | .eccbytes = 24, | 906 | pxa3xx_nand_config_flash(info, &builtin_flash_types[0]); |
937 | .eccpos = { | 907 | chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0); |
938 | 40, 41, 42, 43, 44, 45, 46, 47, | 908 | if (info->is_ready) |
939 | 48, 49, 50, 51, 52, 53, 54, 55, | 909 | return 1; |
940 | 56, 57, 58, 59, 60, 61, 62, 63}, | 910 | else |
941 | .oobfree = { {2, 38} } | 911 | return 0; |
942 | }; | 912 | } |
943 | 913 | ||
944 | static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, | 914 | static int pxa3xx_nand_scan(struct mtd_info *mtd) |
945 | struct pxa3xx_nand_info *info) | ||
946 | { | 915 | { |
947 | struct nand_chip *this = &info->nand_chip; | 916 | struct pxa3xx_nand_info *info = mtd->priv; |
948 | 917 | struct platform_device *pdev = info->pdev; | |
949 | this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0; | 918 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; |
950 | this->options |= NAND_NO_AUTOINCR; | 919 | const struct pxa3xx_nand_flash *f = NULL; |
951 | 920 | struct nand_chip *chip = mtd->priv; | |
952 | this->waitfunc = pxa3xx_nand_waitfunc; | 921 | uint32_t id = -1; |
953 | this->select_chip = pxa3xx_nand_select_chip; | 922 | int i, ret, num; |
954 | this->dev_ready = pxa3xx_nand_dev_ready; | 923 | |
955 | this->cmdfunc = pxa3xx_nand_cmdfunc; | 924 | if (pdata->keep_config && !pxa3xx_nand_detect_config(info)) |
956 | this->ecc.read_page = pxa3xx_nand_read_page_hwecc; | 925 | return 0; |
957 | this->ecc.write_page = pxa3xx_nand_write_page_hwecc; | 926 | |
958 | this->read_word = pxa3xx_nand_read_word; | 927 | ret = pxa3xx_nand_sensing(info); |
959 | this->read_byte = pxa3xx_nand_read_byte; | 928 | if (!ret) { |
960 | this->read_buf = pxa3xx_nand_read_buf; | 929 | kfree(mtd); |
961 | this->write_buf = pxa3xx_nand_write_buf; | 930 | info->mtd = NULL; |
962 | this->verify_buf = pxa3xx_nand_verify_buf; | 931 | printk(KERN_INFO "There is no nand chip on cs 0!\n"); |
963 | 932 | ||
964 | this->ecc.mode = NAND_ECC_HW; | 933 | return -EINVAL; |
965 | this->ecc.size = info->page_size; | 934 | } |
966 | 935 | ||
967 | if (info->page_size == 2048) | 936 | chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0); |
968 | this->ecc.layout = &hw_largepage_ecclayout; | 937 | id = *((uint16_t *)(info->data_buff)); |
969 | else | 938 | if (id != 0) |
970 | this->ecc.layout = &hw_smallpage_ecclayout; | 939 | printk(KERN_INFO "Detect a flash id %x\n", id); |
940 | else { | ||
941 | kfree(mtd); | ||
942 | info->mtd = NULL; | ||
943 | printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n"); | ||
944 | |||
945 | return -EINVAL; | ||
946 | } | ||
947 | |||
948 | num = ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; | ||
949 | for (i = 0; i < num; i++) { | ||
950 | if (i < pdata->num_flash) | ||
951 | f = pdata->flash + i; | ||
952 | else | ||
953 | f = &builtin_flash_types[i - pdata->num_flash + 1]; | ||
954 | |||
955 | /* find the chip in default list */ | ||
956 | if (f->chip_id == id) { | ||
957 | pxa3xx_nand_config_flash(info, f); | ||
958 | mtd->writesize = f->page_size; | ||
959 | mtd->writesize_shift = ffs(mtd->writesize) - 1; | ||
960 | mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; | ||
961 | mtd->oobsize = mtd->writesize / 32; | ||
962 | mtd->erasesize = f->page_size * f->page_per_block; | ||
963 | mtd->erasesize_shift = ffs(mtd->erasesize) - 1; | ||
964 | mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; | ||
965 | |||
966 | mtd->name = mtd_names[0]; | ||
967 | break; | ||
968 | } | ||
969 | } | ||
970 | |||
971 | if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash)) { | ||
972 | kfree(mtd); | ||
973 | info->mtd = NULL; | ||
974 | printk(KERN_ERR "ERROR!! flash not defined!!!\n"); | ||
975 | |||
976 | return -EINVAL; | ||
977 | } | ||
978 | |||
979 | chip->ecc.mode = NAND_ECC_HW; | ||
980 | chip->ecc.size = f->page_size; | ||
981 | chip->chipsize = (uint64_t)f->num_blocks * f->page_per_block | ||
982 | * f->page_size; | ||
983 | mtd->size = chip->chipsize; | ||
984 | |||
985 | /* Calculate the address shift from the page size */ | ||
986 | chip->page_shift = ffs(mtd->writesize) - 1; | ||
987 | chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1; | ||
988 | chip->numchips = 1; | ||
989 | chip->phys_erase_shift = ffs(mtd->erasesize) - 1; | ||
990 | chip->bbt_erase_shift = chip->phys_erase_shift; | ||
991 | |||
992 | chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16 : 0; | ||
993 | chip->options |= NAND_NO_AUTOINCR; | ||
994 | chip->options |= NAND_NO_READRDY; | ||
971 | 995 | ||
972 | this->chip_delay = 25; | 996 | return nand_scan_tail(mtd); |
973 | } | 997 | } |
974 | 998 | ||
975 | static | 999 | static |
976 | struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev) | 1000 | struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev) |
977 | { | 1001 | { |
978 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; | ||
979 | struct pxa3xx_nand_info *info; | 1002 | struct pxa3xx_nand_info *info; |
1003 | struct nand_chip *chip; | ||
980 | struct mtd_info *mtd; | 1004 | struct mtd_info *mtd; |
981 | struct resource *r; | 1005 | struct resource *r; |
982 | int ret, irq; | 1006 | int ret, irq; |
@@ -989,12 +1013,27 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev) | |||
989 | } | 1013 | } |
990 | 1014 | ||
991 | info = (struct pxa3xx_nand_info *)(&mtd[1]); | 1015 | info = (struct pxa3xx_nand_info *)(&mtd[1]); |
1016 | chip = (struct nand_chip *)(&mtd[1]); | ||
992 | info->pdev = pdev; | 1017 | info->pdev = pdev; |
993 | |||
994 | mtd->priv = info; | ||
995 | info->mtd = mtd; | 1018 | info->mtd = mtd; |
1019 | mtd->priv = info; | ||
996 | mtd->owner = THIS_MODULE; | 1020 | mtd->owner = THIS_MODULE; |
997 | 1021 | ||
1022 | chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; | ||
1023 | chip->ecc.write_page = pxa3xx_nand_write_page_hwecc; | ||
1024 | chip->controller = &info->controller; | ||
1025 | chip->waitfunc = pxa3xx_nand_waitfunc; | ||
1026 | chip->select_chip = pxa3xx_nand_select_chip; | ||
1027 | chip->dev_ready = pxa3xx_nand_dev_ready; | ||
1028 | chip->cmdfunc = pxa3xx_nand_cmdfunc; | ||
1029 | chip->read_word = pxa3xx_nand_read_word; | ||
1030 | chip->read_byte = pxa3xx_nand_read_byte; | ||
1031 | chip->read_buf = pxa3xx_nand_read_buf; | ||
1032 | chip->write_buf = pxa3xx_nand_write_buf; | ||
1033 | chip->verify_buf = pxa3xx_nand_verify_buf; | ||
1034 | |||
1035 | spin_lock_init(&chip->controller->lock); | ||
1036 | init_waitqueue_head(&chip->controller->wq); | ||
998 | info->clk = clk_get(&pdev->dev, NULL); | 1037 | info->clk = clk_get(&pdev->dev, NULL); |
999 | if (IS_ERR(info->clk)) { | 1038 | if (IS_ERR(info->clk)) { |
1000 | dev_err(&pdev->dev, "failed to get nand clock\n"); | 1039 | dev_err(&pdev->dev, "failed to get nand clock\n"); |
@@ -1062,21 +1101,12 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev) | |||
1062 | goto fail_free_buf; | 1101 | goto fail_free_buf; |
1063 | } | 1102 | } |
1064 | 1103 | ||
1065 | ret = pxa3xx_nand_detect_flash(info, pdata); | ||
1066 | if (ret) { | ||
1067 | dev_err(&pdev->dev, "failed to detect flash\n"); | ||
1068 | ret = -ENODEV; | ||
1069 | goto fail_free_irq; | ||
1070 | } | ||
1071 | |||
1072 | pxa3xx_nand_init_mtd(mtd, info); | ||
1073 | platform_set_drvdata(pdev, info); | 1104 | platform_set_drvdata(pdev, info); |
1074 | 1105 | ||
1075 | return info; | 1106 | return info; |
1076 | 1107 | ||
1077 | fail_free_irq: | ||
1078 | free_irq(irq, info); | ||
1079 | fail_free_buf: | 1108 | fail_free_buf: |
1109 | free_irq(irq, info); | ||
1080 | if (use_dma) { | 1110 | if (use_dma) { |
1081 | pxa_free_dma(info->data_dma_ch); | 1111 | pxa_free_dma(info->data_dma_ch); |
1082 | dma_free_coherent(&pdev->dev, info->data_buff_size, | 1112 | dma_free_coherent(&pdev->dev, info->data_buff_size, |
@@ -1146,7 +1176,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1146 | if (info == NULL) | 1176 | if (info == NULL) |
1147 | return -ENOMEM; | 1177 | return -ENOMEM; |
1148 | 1178 | ||
1149 | if (nand_scan(info->mtd, 1)) { | 1179 | if (pxa3xx_nand_scan(info->mtd)) { |
1150 | dev_err(&pdev->dev, "failed to scan nand\n"); | 1180 | dev_err(&pdev->dev, "failed to scan nand\n"); |
1151 | pxa3xx_nand_remove(pdev); | 1181 | pxa3xx_nand_remove(pdev); |
1152 | return -ENODEV; | 1182 | return -ENODEV; |