aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2012-04-23 05:23:40 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-05-14 00:03:02 -0400
commitf48d0f9aa93c8f1d38f21d2531d572cf96205d58 (patch)
treeeb4b9fc47b235758956757baa4cb1fcb9bf269d3 /drivers
parent69d023be00e9bb5368ced679cead9fb25474ec69 (diff)
mtd: mxc_nand: put several more fields into devtype_data
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/nand/mxc_nand.c130
1 files changed, 94 insertions, 36 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 4a6d763ab7f7..35c928ac1901 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -156,6 +156,22 @@ struct mxc_nand_devtype_data {
156 void (*select_chip)(struct mtd_info *mtd, int chip); 156 void (*select_chip)(struct mtd_info *mtd, int chip);
157 int (*correct_data)(struct mtd_info *mtd, u_char *dat, 157 int (*correct_data)(struct mtd_info *mtd, u_char *dat,
158 u_char *read_ecc, u_char *calc_ecc); 158 u_char *read_ecc, u_char *calc_ecc);
159
160 /*
161 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
162 * (CONFIG1:INT_MSK is set). To handle this the driver uses
163 * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK
164 */
165 int irqpending_quirk;
166 int needs_ip;
167
168 size_t regs_offset;
169 size_t spare0_offset;
170 size_t axi_offset;
171
172 int spare_len;
173 int eccbytes;
174 int eccsize;
159}; 175};
160 176
161struct mxc_nand_host { 177struct mxc_nand_host {
@@ -181,16 +197,8 @@ struct mxc_nand_host {
181 197
182 uint8_t *data_buf; 198 uint8_t *data_buf;
183 unsigned int buf_start; 199 unsigned int buf_start;
184 int spare_len;
185 200
186 const struct mxc_nand_devtype_data *devtype_data; 201 const struct mxc_nand_devtype_data *devtype_data;
187
188 /*
189 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
190 * (CONFIG1:INT_MSK is set). To handle this the driver uses
191 * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK
192 */
193 int irqpending_quirk;
194}; 202};
195 203
196/* OOB placement block for use with hardware ecc generation */ 204/* OOB placement block for use with hardware ecc generation */
@@ -284,7 +292,7 @@ static int check_int_v1_v2(struct mxc_nand_host *host)
284 if (!(tmp & NFC_V1_V2_CONFIG2_INT)) 292 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
285 return 0; 293 return 0;
286 294
287 if (!host->irqpending_quirk) 295 if (!host->devtype_data->irqpending_quirk)
288 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); 296 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
289 297
290 return 1; 298 return 1;
@@ -320,7 +328,7 @@ static void irq_control_v3(struct mxc_nand_host *host, int activate)
320 328
321static void irq_control(struct mxc_nand_host *host, int activate) 329static void irq_control(struct mxc_nand_host *host, int activate)
322{ 330{
323 if (host->irqpending_quirk) { 331 if (host->devtype_data->irqpending_quirk) {
324 if (activate) 332 if (activate)
325 enable_irq(host->irq); 333 enable_irq(host->irq);
326 else 334 else
@@ -405,7 +413,7 @@ static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
405 writew(cmd, NFC_V1_V2_FLASH_CMD); 413 writew(cmd, NFC_V1_V2_FLASH_CMD);
406 writew(NFC_CMD, NFC_V1_V2_CONFIG2); 414 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
407 415
408 if (host->irqpending_quirk && (cmd == NAND_CMD_RESET)) { 416 if (host->devtype_data->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
409 int max_retries = 100; 417 int max_retries = 100;
410 /* Reset completion is indicated by NFC_CONFIG2 */ 418 /* Reset completion is indicated by NFC_CONFIG2 */
411 /* being set to 0 */ 419 /* being set to 0 */
@@ -780,7 +788,7 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom)
780 u16 n = mtd->writesize >> 9; 788 u16 n = mtd->writesize >> 9;
781 u8 *d = host->data_buf + mtd->writesize; 789 u8 *d = host->data_buf + mtd->writesize;
782 u8 *s = host->spare0; 790 u8 *s = host->spare0;
783 u16 t = host->spare_len; 791 u16 t = host->devtype_data->spare_len;
784 792
785 j = (mtd->oobsize / n >> 1) << 1; 793 j = (mtd->oobsize / n >> 1) << 1;
786 794
@@ -880,7 +888,7 @@ static void preset_v1(struct mtd_info *mtd)
880 if (nand_chip->ecc.mode == NAND_ECC_HW) 888 if (nand_chip->ecc.mode == NAND_ECC_HW)
881 config1 |= NFC_V1_V2_CONFIG1_ECC_EN; 889 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
882 890
883 if (!host->irqpending_quirk) 891 if (!host->devtype_data->irqpending_quirk)
884 config1 |= NFC_V1_V2_CONFIG1_INT_MSK; 892 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
885 893
886 host->eccsize = 1; 894 host->eccsize = 1;
@@ -910,7 +918,7 @@ static void preset_v2(struct mtd_info *mtd)
910 918
911 config1 |= NFC_V2_CONFIG1_FP_INT; 919 config1 |= NFC_V2_CONFIG1_FP_INT;
912 920
913 if (!host->irqpending_quirk) 921 if (!host->devtype_data->irqpending_quirk)
914 config1 |= NFC_V1_V2_CONFIG1_INT_MSK; 922 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
915 923
916 if (mtd->writesize) { 924 if (mtd->writesize) {
@@ -1125,7 +1133,7 @@ static struct nand_bbt_descr bbt_mirror_descr = {
1125 .pattern = mirror_pattern, 1133 .pattern = mirror_pattern,
1126}; 1134};
1127 1135
1128/* v1: i.MX21, i.MX27, i.MX31 */ 1136/* v1 + irqpending_quirk: i.MX21 */
1129static const struct mxc_nand_devtype_data imx21_nand_devtype_data = { 1137static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
1130 .preset = preset_v1, 1138 .preset = preset_v1,
1131 .send_cmd = send_cmd_v1_v2, 1139 .send_cmd = send_cmd_v1_v2,
@@ -1141,6 +1149,39 @@ static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
1141 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */ 1149 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
1142 .select_chip = mxc_nand_select_chip_v1_v3, 1150 .select_chip = mxc_nand_select_chip_v1_v3,
1143 .correct_data = mxc_nand_correct_data_v1, 1151 .correct_data = mxc_nand_correct_data_v1,
1152 .irqpending_quirk = 1,
1153 .needs_ip = 0,
1154 .regs_offset = 0xe00,
1155 .spare0_offset = 0x800,
1156 .spare_len = 16,
1157 .eccbytes = 3,
1158 .eccsize = 1,
1159};
1160
1161/* v1 + !irqpending_quirk: i.MX27, i.MX31 */
1162static const struct mxc_nand_devtype_data imx27_nand_devtype_data = {
1163 .preset = preset_v1,
1164 .send_cmd = send_cmd_v1_v2,
1165 .send_addr = send_addr_v1_v2,
1166 .send_page = send_page_v1,
1167 .send_read_id = send_read_id_v1_v2,
1168 .get_dev_status = get_dev_status_v1_v2,
1169 .check_int = check_int_v1_v2,
1170 .irq_control = irq_control_v1_v2,
1171 .get_ecc_status = get_ecc_status_v1,
1172 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1173 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1174 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
1175 .select_chip = mxc_nand_select_chip_v1_v3,
1176 .correct_data = mxc_nand_correct_data_v1,
1177 .irqpending_quirk = 0,
1178 .needs_ip = 0,
1179 .regs_offset = 0xe00,
1180 .spare0_offset = 0x800,
1181 .axi_offset = 0,
1182 .spare_len = 16,
1183 .eccbytes = 3,
1184 .eccsize = 1,
1144}; 1185};
1145 1186
1146/* v21: i.MX25, i.MX35 */ 1187/* v21: i.MX25, i.MX35 */
@@ -1159,6 +1200,14 @@ static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
1159 .ecclayout_4k = &nandv2_hw_eccoob_4k, 1200 .ecclayout_4k = &nandv2_hw_eccoob_4k,
1160 .select_chip = mxc_nand_select_chip_v2, 1201 .select_chip = mxc_nand_select_chip_v2,
1161 .correct_data = mxc_nand_correct_data_v2_v3, 1202 .correct_data = mxc_nand_correct_data_v2_v3,
1203 .irqpending_quirk = 0,
1204 .needs_ip = 0,
1205 .regs_offset = 0x1e00,
1206 .spare0_offset = 0x1000,
1207 .axi_offset = 0,
1208 .spare_len = 64,
1209 .eccbytes = 9,
1210 .eccsize = 0,
1162}; 1211};
1163 1212
1164/* v3: i.MX51, i.MX53 */ 1213/* v3: i.MX51, i.MX53 */
@@ -1177,6 +1226,14 @@ static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
1177 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */ 1226 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
1178 .select_chip = mxc_nand_select_chip_v1_v3, 1227 .select_chip = mxc_nand_select_chip_v1_v3,
1179 .correct_data = mxc_nand_correct_data_v2_v3, 1228 .correct_data = mxc_nand_correct_data_v2_v3,
1229 .irqpending_quirk = 0,
1230 .needs_ip = 1,
1231 .regs_offset = 0,
1232 .spare0_offset = 0x1000,
1233 .axi_offset = 0x1e00,
1234 .spare_len = 64,
1235 .eccbytes = 0,
1236 .eccsize = 0,
1180}; 1237};
1181 1238
1182static int __init mxcnd_probe(struct platform_device *pdev) 1239static int __init mxcnd_probe(struct platform_device *pdev)
@@ -1241,22 +1298,31 @@ static int __init mxcnd_probe(struct platform_device *pdev)
1241 host->main_area0 = host->base; 1298 host->main_area0 = host->base;
1242 1299
1243 if (nfc_is_v1()) { 1300 if (nfc_is_v1()) {
1244 host->devtype_data = &imx21_nand_devtype_data;
1245 if (cpu_is_mx21()) 1301 if (cpu_is_mx21())
1246 host->irqpending_quirk = 1; 1302 host->devtype_data = &imx21_nand_devtype_data;
1247 host->regs = host->base + 0xe00; 1303 else
1248 host->spare0 = host->base + 0x800; 1304 host->devtype_data = &imx27_nand_devtype_data;
1249 host->spare_len = 16;
1250 this->ecc.bytes = 3;
1251 host->eccsize = 1;
1252 } else if (nfc_is_v21()) { 1305 } else if (nfc_is_v21()) {
1253 host->devtype_data = &imx25_nand_devtype_data; 1306 host->devtype_data = &imx25_nand_devtype_data;
1254 host->regs = host->base + 0x1e00;
1255 host->spare0 = host->base + 0x1000;
1256 host->spare_len = 64;
1257 this->ecc.bytes = 9;
1258 } else if (nfc_is_v3_2()) { 1307 } else if (nfc_is_v3_2()) {
1259 host->devtype_data = &imx51_nand_devtype_data; 1308 host->devtype_data = &imx51_nand_devtype_data;
1309 } else
1310 BUG();
1311
1312 if (host->devtype_data->regs_offset)
1313 host->regs = host->base + host->devtype_data->regs_offset;
1314 host->spare0 = host->base + host->devtype_data->spare0_offset;
1315 if (host->devtype_data->axi_offset)
1316 host->regs_axi = host->base + host->devtype_data->axi_offset;
1317
1318 this->ecc.bytes = host->devtype_data->eccbytes;
1319 host->eccsize = host->devtype_data->eccsize;
1320
1321 this->select_chip = host->devtype_data->select_chip;
1322 this->ecc.size = 512;
1323 this->ecc.layout = host->devtype_data->ecclayout_512;
1324
1325 if (host->devtype_data->needs_ip) {
1260 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 1326 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1261 if (!res) { 1327 if (!res) {
1262 err = -ENODEV; 1328 err = -ENODEV;
@@ -1267,15 +1333,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
1267 err = -ENOMEM; 1333 err = -ENOMEM;
1268 goto eirq; 1334 goto eirq;
1269 } 1335 }
1270 host->regs_axi = host->base + 0x1e00; 1336 }
1271 host->spare0 = host->base + 0x1000;
1272 host->spare_len = 64;
1273 } else
1274 BUG();
1275
1276 this->select_chip = host->devtype_data->select_chip;
1277 this->ecc.size = 512;
1278 this->ecc.layout = host->devtype_data->ecclayout_512;
1279 1337
1280 if (pdata->hw_ecc) { 1338 if (pdata->hw_ecc) {
1281 this->ecc.calculate = mxc_nand_calculate_ecc; 1339 this->ecc.calculate = mxc_nand_calculate_ecc;
@@ -1317,7 +1375,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
1317 * cleared on i.MX21. Otherwise we can't read the interrupt status bit 1375 * cleared on i.MX21. Otherwise we can't read the interrupt status bit
1318 * on this machine. 1376 * on this machine.
1319 */ 1377 */
1320 if (host->irqpending_quirk) { 1378 if (host->devtype_data->irqpending_quirk) {
1321 disable_irq_nosync(host->irq); 1379 disable_irq_nosync(host->irq);
1322 host->devtype_data->irq_control(host, 1); 1380 host->devtype_data->irq_control(host, 1);
1323 } 1381 }