diff options
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r-- | drivers/mtd/nand/pxa3xx_nand.c | 99 |
1 files changed, 55 insertions, 44 deletions
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index ea2c288df3f6..f44044381360 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -126,6 +126,7 @@ struct pxa3xx_nand_info { | |||
126 | unsigned int buf_start; | 126 | unsigned int buf_start; |
127 | unsigned int buf_count; | 127 | unsigned int buf_count; |
128 | 128 | ||
129 | struct mtd_info *mtd; | ||
129 | /* DMA information */ | 130 | /* DMA information */ |
130 | int drcmr_dat; | 131 | int drcmr_dat; |
131 | int drcmr_cmd; | 132 | int drcmr_cmd; |
@@ -1044,34 +1045,27 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, | |||
1044 | this->chip_delay = 25; | 1045 | this->chip_delay = 25; |
1045 | } | 1046 | } |
1046 | 1047 | ||
1047 | static int pxa3xx_nand_probe(struct platform_device *pdev) | 1048 | static |
1049 | struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev) | ||
1048 | { | 1050 | { |
1049 | struct pxa3xx_nand_platform_data *pdata; | 1051 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; |
1050 | struct pxa3xx_nand_info *info; | 1052 | struct pxa3xx_nand_info *info; |
1051 | struct nand_chip *this; | ||
1052 | struct mtd_info *mtd; | 1053 | struct mtd_info *mtd; |
1053 | struct resource *r; | 1054 | struct resource *r; |
1054 | int ret = 0, irq; | 1055 | int ret, irq; |
1055 | |||
1056 | pdata = pdev->dev.platform_data; | ||
1057 | |||
1058 | if (!pdata) { | ||
1059 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
1060 | return -ENODEV; | ||
1061 | } | ||
1062 | 1056 | ||
1063 | mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info), | 1057 | mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info), |
1064 | GFP_KERNEL); | 1058 | GFP_KERNEL); |
1065 | if (!mtd) { | 1059 | if (!mtd) { |
1066 | dev_err(&pdev->dev, "failed to allocate memory\n"); | 1060 | dev_err(&pdev->dev, "failed to allocate memory\n"); |
1067 | return -ENOMEM; | 1061 | return NULL; |
1068 | } | 1062 | } |
1069 | 1063 | ||
1070 | info = (struct pxa3xx_nand_info *)(&mtd[1]); | 1064 | info = (struct pxa3xx_nand_info *)(&mtd[1]); |
1071 | info->pdev = pdev; | 1065 | info->pdev = pdev; |
1072 | 1066 | ||
1073 | this = &info->nand_chip; | ||
1074 | mtd->priv = info; | 1067 | mtd->priv = info; |
1068 | info->mtd = mtd; | ||
1075 | mtd->owner = THIS_MODULE; | 1069 | mtd->owner = THIS_MODULE; |
1076 | 1070 | ||
1077 | info->clk = clk_get(&pdev->dev, NULL); | 1071 | info->clk = clk_get(&pdev->dev, NULL); |
@@ -1149,31 +1143,9 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1149 | } | 1143 | } |
1150 | 1144 | ||
1151 | pxa3xx_nand_init_mtd(mtd, info); | 1145 | pxa3xx_nand_init_mtd(mtd, info); |
1146 | platform_set_drvdata(pdev, info); | ||
1152 | 1147 | ||
1153 | platform_set_drvdata(pdev, mtd); | 1148 | return info; |
1154 | |||
1155 | if (nand_scan(mtd, 1)) { | ||
1156 | dev_err(&pdev->dev, "failed to scan nand\n"); | ||
1157 | ret = -ENXIO; | ||
1158 | goto fail_free_irq; | ||
1159 | } | ||
1160 | |||
1161 | #ifdef CONFIG_MTD_PARTITIONS | ||
1162 | if (mtd_has_cmdlinepart()) { | ||
1163 | static const char *probes[] = { "cmdlinepart", NULL }; | ||
1164 | struct mtd_partition *parts; | ||
1165 | int nr_parts; | ||
1166 | |||
1167 | nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0); | ||
1168 | |||
1169 | if (nr_parts) | ||
1170 | return add_mtd_partitions(mtd, parts, nr_parts); | ||
1171 | } | ||
1172 | |||
1173 | return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); | ||
1174 | #else | ||
1175 | return 0; | ||
1176 | #endif | ||
1177 | 1149 | ||
1178 | fail_free_irq: | 1150 | fail_free_irq: |
1179 | free_irq(irq, info); | 1151 | free_irq(irq, info); |
@@ -1193,13 +1165,13 @@ fail_put_clk: | |||
1193 | clk_put(info->clk); | 1165 | clk_put(info->clk); |
1194 | fail_free_mtd: | 1166 | fail_free_mtd: |
1195 | kfree(mtd); | 1167 | kfree(mtd); |
1196 | return ret; | 1168 | return NULL; |
1197 | } | 1169 | } |
1198 | 1170 | ||
1199 | static int pxa3xx_nand_remove(struct platform_device *pdev) | 1171 | static int pxa3xx_nand_remove(struct platform_device *pdev) |
1200 | { | 1172 | { |
1201 | struct mtd_info *mtd = platform_get_drvdata(pdev); | 1173 | struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); |
1202 | struct pxa3xx_nand_info *info = mtd->priv; | 1174 | struct mtd_info *mtd = info->mtd; |
1203 | struct resource *r; | 1175 | struct resource *r; |
1204 | int irq; | 1176 | int irq; |
1205 | 1177 | ||
@@ -1230,11 +1202,50 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) | |||
1230 | return 0; | 1202 | return 0; |
1231 | } | 1203 | } |
1232 | 1204 | ||
1205 | static int pxa3xx_nand_probe(struct platform_device *pdev) | ||
1206 | { | ||
1207 | struct pxa3xx_nand_platform_data *pdata; | ||
1208 | struct pxa3xx_nand_info *info; | ||
1209 | |||
1210 | pdata = pdev->dev.platform_data; | ||
1211 | if (!pdata) { | ||
1212 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
1213 | return -ENODEV; | ||
1214 | } | ||
1215 | |||
1216 | info = alloc_nand_resource(pdev); | ||
1217 | if (info == NULL) | ||
1218 | return -ENOMEM; | ||
1219 | |||
1220 | if (nand_scan(info->mtd, 1)) { | ||
1221 | dev_err(&pdev->dev, "failed to scan nand\n"); | ||
1222 | pxa3xx_nand_remove(pdev); | ||
1223 | return -ENODEV; | ||
1224 | } | ||
1225 | |||
1226 | #ifdef CONFIG_MTD_PARTITIONS | ||
1227 | if (mtd_has_cmdlinepart()) { | ||
1228 | const char *probes[] = { "cmdlinepart", NULL }; | ||
1229 | struct mtd_partition *parts; | ||
1230 | int nr_parts; | ||
1231 | |||
1232 | nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0); | ||
1233 | |||
1234 | if (nr_parts) | ||
1235 | return add_mtd_partitions(mtd, parts, nr_parts); | ||
1236 | } | ||
1237 | |||
1238 | return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); | ||
1239 | #else | ||
1240 | return 0; | ||
1241 | #endif | ||
1242 | } | ||
1243 | |||
1233 | #ifdef CONFIG_PM | 1244 | #ifdef CONFIG_PM |
1234 | static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state) | 1245 | static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state) |
1235 | { | 1246 | { |
1236 | struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev); | 1247 | struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); |
1237 | struct pxa3xx_nand_info *info = mtd->priv; | 1248 | struct mtd_info *mtd = info->mtd; |
1238 | 1249 | ||
1239 | if (info->state != STATE_READY) { | 1250 | if (info->state != STATE_READY) { |
1240 | dev_err(&pdev->dev, "driver busy, state = %d\n", info->state); | 1251 | dev_err(&pdev->dev, "driver busy, state = %d\n", info->state); |
@@ -1246,8 +1257,8 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state) | |||
1246 | 1257 | ||
1247 | static int pxa3xx_nand_resume(struct platform_device *pdev) | 1258 | static int pxa3xx_nand_resume(struct platform_device *pdev) |
1248 | { | 1259 | { |
1249 | struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev); | 1260 | struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); |
1250 | struct pxa3xx_nand_info *info = mtd->priv; | 1261 | struct mtd_info *mtd = info->mtd; |
1251 | 1262 | ||
1252 | nand_writel(info, NDTR0CS0, info->ndtr0cs0); | 1263 | nand_writel(info, NDTR0CS0, info->ndtr0cs0); |
1253 | nand_writel(info, NDTR1CS0, info->ndtr1cs0); | 1264 | nand_writel(info, NDTR1CS0, info->ndtr1cs0); |