aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2012-04-23 05:23:35 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-05-14 00:01:39 -0400
commite4303b25f4452dd6a0a49c318e5e93d0c5f8b1ba (patch)
tree024262f7aaafb2ecc1e52890bb04c6b42f5b0c0e /drivers/mtd
parent8556958af4ef58147c11f772e6171c149efee53c (diff)
mtd: mxc_nand: move function pointers to a per-SOC struct
This prepares switching to platform ids and of-tree probing. 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/mtd')
-rw-r--r--drivers/mtd/nand/mxc_nand.c170
1 files changed, 104 insertions, 66 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 6f6068043fad..b6e4618bb043 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -140,6 +140,19 @@
140 140
141#define NFC_V3_DELAY_LINE (host->regs_ip + 0x34) 141#define NFC_V3_DELAY_LINE (host->regs_ip + 0x34)
142 142
143struct mxc_nand_host;
144
145struct mxc_nand_devtype_data {
146 void (*preset)(struct mtd_info *);
147 void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
148 void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
149 void (*send_page)(struct mtd_info *, unsigned int);
150 void (*send_read_id)(struct mxc_nand_host *);
151 uint16_t (*get_dev_status)(struct mxc_nand_host *);
152 int (*check_int)(struct mxc_nand_host *);
153 void (*irq_control)(struct mxc_nand_host *, int);
154};
155
143struct mxc_nand_host { 156struct mxc_nand_host {
144 struct mtd_info mtd; 157 struct mtd_info mtd;
145 struct nand_chip nand; 158 struct nand_chip nand;
@@ -165,14 +178,7 @@ struct mxc_nand_host {
165 unsigned int buf_start; 178 unsigned int buf_start;
166 int spare_len; 179 int spare_len;
167 180
168 void (*preset)(struct mtd_info *); 181 const struct mxc_nand_devtype_data *devtype_data;
169 void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
170 void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
171 void (*send_page)(struct mtd_info *, unsigned int);
172 void (*send_read_id)(struct mxc_nand_host *);
173 uint16_t (*get_dev_status)(struct mxc_nand_host *);
174 int (*check_int)(struct mxc_nand_host *);
175 void (*irq_control)(struct mxc_nand_host *, int);
176 182
177 /* 183 /*
178 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked 184 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
@@ -315,7 +321,7 @@ static void irq_control(struct mxc_nand_host *host, int activate)
315 else 321 else
316 disable_irq_nosync(host->irq); 322 disable_irq_nosync(host->irq);
317 } else { 323 } else {
318 host->irq_control(host, activate); 324 host->devtype_data->irq_control(host, activate);
319 } 325 }
320} 326}
321 327
@@ -323,7 +329,7 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
323{ 329{
324 struct mxc_nand_host *host = dev_id; 330 struct mxc_nand_host *host = dev_id;
325 331
326 if (!host->check_int(host)) 332 if (!host->devtype_data->check_int(host))
327 return IRQ_NONE; 333 return IRQ_NONE;
328 334
329 irq_control(host, 0); 335 irq_control(host, 0);
@@ -341,14 +347,14 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq)
341 int max_retries = 8000; 347 int max_retries = 8000;
342 348
343 if (useirq) { 349 if (useirq) {
344 if (!host->check_int(host)) { 350 if (!host->devtype_data->check_int(host)) {
345 INIT_COMPLETION(host->op_completion); 351 INIT_COMPLETION(host->op_completion);
346 irq_control(host, 1); 352 irq_control(host, 1);
347 wait_for_completion(&host->op_completion); 353 wait_for_completion(&host->op_completion);
348 } 354 }
349 } else { 355 } else {
350 while (max_retries-- > 0) { 356 while (max_retries-- > 0) {
351 if (host->check_int(host)) 357 if (host->devtype_data->check_int(host))
352 break; 358 break;
353 359
354 udelay(1); 360 udelay(1);
@@ -621,7 +627,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd)
621 627
622 /* Check for status request */ 628 /* Check for status request */
623 if (host->status_request) 629 if (host->status_request)
624 return host->get_dev_status(host) & 0xFF; 630 return host->devtype_data->get_dev_status(host) & 0xFF;
625 631
626 ret = *(uint8_t *)(host->data_buf + host->buf_start); 632 ret = *(uint8_t *)(host->data_buf + host->buf_start);
627 host->buf_start++; 633 host->buf_start++;
@@ -756,34 +762,44 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
756 * perform a read/write buf operation, the saved column 762 * perform a read/write buf operation, the saved column
757 * address is used to index into the full page. 763 * address is used to index into the full page.
758 */ 764 */
759 host->send_addr(host, 0, page_addr == -1); 765 host->devtype_data->send_addr(host, 0, page_addr == -1);
760 if (mtd->writesize > 512) 766 if (mtd->writesize > 512)
761 /* another col addr cycle for 2k page */ 767 /* another col addr cycle for 2k page */
762 host->send_addr(host, 0, false); 768 host->devtype_data->send_addr(host, 0, false);
763 } 769 }
764 770
765 /* Write out page address, if necessary */ 771 /* Write out page address, if necessary */
766 if (page_addr != -1) { 772 if (page_addr != -1) {
767 /* paddr_0 - p_addr_7 */ 773 /* paddr_0 - p_addr_7 */
768 host->send_addr(host, (page_addr & 0xff), false); 774 host->devtype_data->send_addr(host, (page_addr & 0xff), false);
769 775
770 if (mtd->writesize > 512) { 776 if (mtd->writesize > 512) {
771 if (mtd->size >= 0x10000000) { 777 if (mtd->size >= 0x10000000) {
772 /* paddr_8 - paddr_15 */ 778 /* paddr_8 - paddr_15 */
773 host->send_addr(host, (page_addr >> 8) & 0xff, false); 779 host->devtype_data->send_addr(host,
774 host->send_addr(host, (page_addr >> 16) & 0xff, true); 780 (page_addr >> 8) & 0xff,
781 false);
782 host->devtype_data->send_addr(host,
783 (page_addr >> 16) & 0xff,
784 true);
775 } else 785 } else
776 /* paddr_8 - paddr_15 */ 786 /* paddr_8 - paddr_15 */
777 host->send_addr(host, (page_addr >> 8) & 0xff, true); 787 host->devtype_data->send_addr(host,
788 (page_addr >> 8) & 0xff, true);
778 } else { 789 } else {
779 /* One more address cycle for higher density devices */ 790 /* One more address cycle for higher density devices */
780 if (mtd->size >= 0x4000000) { 791 if (mtd->size >= 0x4000000) {
781 /* paddr_8 - paddr_15 */ 792 /* paddr_8 - paddr_15 */
782 host->send_addr(host, (page_addr >> 8) & 0xff, false); 793 host->devtype_data->send_addr(host,
783 host->send_addr(host, (page_addr >> 16) & 0xff, true); 794 (page_addr >> 8) & 0xff,
795 false);
796 host->devtype_data->send_addr(host,
797 (page_addr >> 16) & 0xff,
798 true);
784 } else 799 } else
785 /* paddr_8 - paddr_15 */ 800 /* paddr_8 - paddr_15 */
786 host->send_addr(host, (page_addr >> 8) & 0xff, true); 801 host->devtype_data->send_addr(host,
802 (page_addr >> 8) & 0xff, true);
787 } 803 }
788 } 804 }
789} 805}
@@ -942,15 +958,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
942 /* Command pre-processing step */ 958 /* Command pre-processing step */
943 switch (command) { 959 switch (command) {
944 case NAND_CMD_RESET: 960 case NAND_CMD_RESET:
945 host->preset(mtd); 961 host->devtype_data->preset(mtd);
946 host->send_cmd(host, command, false); 962 host->devtype_data->send_cmd(host, command, false);
947 break; 963 break;
948 964
949 case NAND_CMD_STATUS: 965 case NAND_CMD_STATUS:
950 host->buf_start = 0; 966 host->buf_start = 0;
951 host->status_request = true; 967 host->status_request = true;
952 968
953 host->send_cmd(host, command, true); 969 host->devtype_data->send_cmd(host, command, true);
954 mxc_do_addr_cycle(mtd, column, page_addr); 970 mxc_do_addr_cycle(mtd, column, page_addr);
955 break; 971 break;
956 972
@@ -963,13 +979,14 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
963 979
964 command = NAND_CMD_READ0; /* only READ0 is valid */ 980 command = NAND_CMD_READ0; /* only READ0 is valid */
965 981
966 host->send_cmd(host, command, false); 982 host->devtype_data->send_cmd(host, command, false);
967 mxc_do_addr_cycle(mtd, column, page_addr); 983 mxc_do_addr_cycle(mtd, column, page_addr);
968 984
969 if (mtd->writesize > 512) 985 if (mtd->writesize > 512)
970 host->send_cmd(host, NAND_CMD_READSTART, true); 986 host->devtype_data->send_cmd(host,
987 NAND_CMD_READSTART, true);
971 988
972 host->send_page(mtd, NFC_OUTPUT); 989 host->devtype_data->send_page(mtd, NFC_OUTPUT);
973 990
974 memcpy(host->data_buf, host->main_area0, mtd->writesize); 991 memcpy(host->data_buf, host->main_area0, mtd->writesize);
975 copy_spare(mtd, true); 992 copy_spare(mtd, true);
@@ -982,28 +999,28 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
982 999
983 host->buf_start = column; 1000 host->buf_start = column;
984 1001
985 host->send_cmd(host, command, false); 1002 host->devtype_data->send_cmd(host, command, false);
986 mxc_do_addr_cycle(mtd, column, page_addr); 1003 mxc_do_addr_cycle(mtd, column, page_addr);
987 break; 1004 break;
988 1005
989 case NAND_CMD_PAGEPROG: 1006 case NAND_CMD_PAGEPROG:
990 memcpy(host->main_area0, host->data_buf, mtd->writesize); 1007 memcpy(host->main_area0, host->data_buf, mtd->writesize);
991 copy_spare(mtd, false); 1008 copy_spare(mtd, false);
992 host->send_page(mtd, NFC_INPUT); 1009 host->devtype_data->send_page(mtd, NFC_INPUT);
993 host->send_cmd(host, command, true); 1010 host->devtype_data->send_cmd(host, command, true);
994 mxc_do_addr_cycle(mtd, column, page_addr); 1011 mxc_do_addr_cycle(mtd, column, page_addr);
995 break; 1012 break;
996 1013
997 case NAND_CMD_READID: 1014 case NAND_CMD_READID:
998 host->send_cmd(host, command, true); 1015 host->devtype_data->send_cmd(host, command, true);
999 mxc_do_addr_cycle(mtd, column, page_addr); 1016 mxc_do_addr_cycle(mtd, column, page_addr);
1000 host->send_read_id(host); 1017 host->devtype_data->send_read_id(host);
1001 host->buf_start = column; 1018 host->buf_start = column;
1002 break; 1019 break;
1003 1020
1004 case NAND_CMD_ERASE1: 1021 case NAND_CMD_ERASE1:
1005 case NAND_CMD_ERASE2: 1022 case NAND_CMD_ERASE2:
1006 host->send_cmd(host, command, false); 1023 host->devtype_data->send_cmd(host, command, false);
1007 mxc_do_addr_cycle(mtd, column, page_addr); 1024 mxc_do_addr_cycle(mtd, column, page_addr);
1008 1025
1009 break; 1026 break;
@@ -1037,6 +1054,42 @@ static struct nand_bbt_descr bbt_mirror_descr = {
1037 .pattern = mirror_pattern, 1054 .pattern = mirror_pattern,
1038}; 1055};
1039 1056
1057/* v1: i.MX21, i.MX27, i.MX31 */
1058static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
1059 .preset = preset_v1_v2,
1060 .send_cmd = send_cmd_v1_v2,
1061 .send_addr = send_addr_v1_v2,
1062 .send_page = send_page_v1_v2,
1063 .send_read_id = send_read_id_v1_v2,
1064 .get_dev_status = get_dev_status_v1_v2,
1065 .check_int = check_int_v1_v2,
1066 .irq_control = irq_control_v1_v2,
1067};
1068
1069/* v21: i.MX25, i.MX35 */
1070static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
1071 .preset = preset_v1_v2,
1072 .send_cmd = send_cmd_v1_v2,
1073 .send_addr = send_addr_v1_v2,
1074 .send_page = send_page_v1_v2,
1075 .send_read_id = send_read_id_v1_v2,
1076 .get_dev_status = get_dev_status_v1_v2,
1077 .check_int = check_int_v1_v2,
1078 .irq_control = irq_control_v1_v2,
1079};
1080
1081/* v3: i.MX51, i.MX53 */
1082static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
1083 .preset = preset_v3,
1084 .send_cmd = send_cmd_v3,
1085 .send_addr = send_addr_v3,
1086 .send_page = send_page_v3,
1087 .send_read_id = send_read_id_v3,
1088 .get_dev_status = get_dev_status_v3,
1089 .check_int = check_int_v3,
1090 .irq_control = irq_control_v3,
1091};
1092
1040static int __init mxcnd_probe(struct platform_device *pdev) 1093static int __init mxcnd_probe(struct platform_device *pdev)
1041{ 1094{
1042 struct nand_chip *this; 1095 struct nand_chip *this;
@@ -1100,27 +1153,10 @@ static int __init mxcnd_probe(struct platform_device *pdev)
1100 1153
1101 host->main_area0 = host->base; 1154 host->main_area0 = host->base;
1102 1155
1103 if (nfc_is_v1() || nfc_is_v21()) { 1156 if (nfc_is_v1()) {
1104 host->preset = preset_v1_v2; 1157 host->devtype_data = &imx21_nand_devtype_data;
1105 host->send_cmd = send_cmd_v1_v2;
1106 host->send_addr = send_addr_v1_v2;
1107 host->send_page = send_page_v1_v2;
1108 host->send_read_id = send_read_id_v1_v2;
1109 host->get_dev_status = get_dev_status_v1_v2;
1110 host->check_int = check_int_v1_v2;
1111 host->irq_control = irq_control_v1_v2;
1112 if (cpu_is_mx21()) 1158 if (cpu_is_mx21())
1113 host->irqpending_quirk = 1; 1159 host->irqpending_quirk = 1;
1114 }
1115
1116 if (nfc_is_v21()) {
1117 host->regs = host->base + 0x1e00;
1118 host->spare0 = host->base + 0x1000;
1119 host->spare_len = 64;
1120 oob_smallpage = &nandv2_hw_eccoob_smallpage;
1121 oob_largepage = &nandv2_hw_eccoob_largepage;
1122 this->ecc.bytes = 9;
1123 } else if (nfc_is_v1()) {
1124 host->regs = host->base + 0xe00; 1160 host->regs = host->base + 0xe00;
1125 host->spare0 = host->base + 0x800; 1161 host->spare0 = host->base + 0x800;
1126 host->spare_len = 16; 1162 host->spare_len = 16;
@@ -1128,7 +1164,16 @@ static int __init mxcnd_probe(struct platform_device *pdev)
1128 oob_largepage = &nandv1_hw_eccoob_largepage; 1164 oob_largepage = &nandv1_hw_eccoob_largepage;
1129 this->ecc.bytes = 3; 1165 this->ecc.bytes = 3;
1130 host->eccsize = 1; 1166 host->eccsize = 1;
1167 } else if (nfc_is_v21()) {
1168 host->devtype_data = &imx25_nand_devtype_data;
1169 host->regs = host->base + 0x1e00;
1170 host->spare0 = host->base + 0x1000;
1171 host->spare_len = 64;
1172 oob_smallpage = &nandv2_hw_eccoob_smallpage;
1173 oob_largepage = &nandv2_hw_eccoob_largepage;
1174 this->ecc.bytes = 9;
1131 } else if (nfc_is_v3_2()) { 1175 } else if (nfc_is_v3_2()) {
1176 host->devtype_data = &imx51_nand_devtype_data;
1132 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 1177 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1133 if (!res) { 1178 if (!res) {
1134 err = -ENODEV; 1179 err = -ENODEV;
@@ -1142,14 +1187,6 @@ static int __init mxcnd_probe(struct platform_device *pdev)
1142 host->regs_axi = host->base + 0x1e00; 1187 host->regs_axi = host->base + 0x1e00;
1143 host->spare0 = host->base + 0x1000; 1188 host->spare0 = host->base + 0x1000;
1144 host->spare_len = 64; 1189 host->spare_len = 64;
1145 host->preset = preset_v3;
1146 host->send_cmd = send_cmd_v3;
1147 host->send_addr = send_addr_v3;
1148 host->send_page = send_page_v3;
1149 host->send_read_id = send_read_id_v3;
1150 host->check_int = check_int_v3;
1151 host->get_dev_status = get_dev_status_v3;
1152 host->irq_control = irq_control_v3;
1153 oob_smallpage = &nandv2_hw_eccoob_smallpage; 1190 oob_smallpage = &nandv2_hw_eccoob_smallpage;
1154 oob_largepage = &nandv2_hw_eccoob_largepage; 1191 oob_largepage = &nandv2_hw_eccoob_largepage;
1155 } else 1192 } else
@@ -1186,10 +1223,11 @@ static int __init mxcnd_probe(struct platform_device *pdev)
1186 host->irq = platform_get_irq(pdev, 0); 1223 host->irq = platform_get_irq(pdev, 0);
1187 1224
1188 /* 1225 /*
1189 * Use host->irq_control here instead of irq_control because we must not 1226 * Use host->devtype_data->irq_control() here instead of irq_control()
1190 * disable_irq_nosync without having requested the irq 1227 * because we must not disable_irq_nosync without having requested the
1228 * irq.
1191 */ 1229 */
1192 host->irq_control(host, 0); 1230 host->devtype_data->irq_control(host, 0);
1193 1231
1194 err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host); 1232 err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
1195 if (err) 1233 if (err)
@@ -1202,7 +1240,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
1202 */ 1240 */
1203 if (host->irqpending_quirk) { 1241 if (host->irqpending_quirk) {
1204 disable_irq_nosync(host->irq); 1242 disable_irq_nosync(host->irq);
1205 host->irq_control(host, 1); 1243 host->devtype_data->irq_control(host, 1);
1206 } 1244 }
1207 1245
1208 /* first scan to find the device and get the page size */ 1246 /* first scan to find the device and get the page size */
@@ -1212,7 +1250,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
1212 } 1250 }
1213 1251
1214 /* Call preset again, with correct writesize this time */ 1252 /* Call preset again, with correct writesize this time */
1215 host->preset(mtd); 1253 host->devtype_data->preset(mtd);
1216 1254
1217 if (mtd->writesize == 2048) 1255 if (mtd->writesize == 2048)
1218 this->ecc.layout = oob_largepage; 1256 this->ecc.layout = oob_largepage;