aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2012-04-23 05:23:34 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-05-14 00:01:17 -0400
commit8556958af4ef58147c11f772e6171c149efee53c (patch)
tree5cf13b30e4c217206906a8f39911d01ffe252925 /drivers/mtd
parent8d1fd16df9e14b29965ed64e120015e481d1fe0a (diff)
mtd: mxc_nand: use a flag to detect if the mx21 quirk is necessary
This gets rid of several instances of cpu_is_mx21() in the driver. 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.c98
1 files changed, 49 insertions, 49 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 7d82cc44cb26..6f6068043fad 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -173,6 +173,13 @@ struct mxc_nand_host {
173 uint16_t (*get_dev_status)(struct mxc_nand_host *); 173 uint16_t (*get_dev_status)(struct mxc_nand_host *);
174 int (*check_int)(struct mxc_nand_host *); 174 int (*check_int)(struct mxc_nand_host *);
175 void (*irq_control)(struct mxc_nand_host *, int); 175 void (*irq_control)(struct mxc_nand_host *, int);
176
177 /*
178 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
179 * (CONFIG1:INT_MSK is set). To handle this the driver uses
180 * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK
181 */
182 int irqpending_quirk;
176}; 183};
177 184
178/* OOB placement block for use with hardware ecc generation */ 185/* OOB placement block for use with hardware ecc generation */
@@ -244,20 +251,6 @@ static struct nand_ecclayout nandv2_hw_eccoob_4k = {
244 251
245static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL }; 252static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL };
246 253
247static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
248{
249 struct mxc_nand_host *host = dev_id;
250
251 if (!host->check_int(host))
252 return IRQ_NONE;
253
254 host->irq_control(host, 0);
255
256 complete(&host->op_completion);
257
258 return IRQ_HANDLED;
259}
260
261static int check_int_v3(struct mxc_nand_host *host) 254static int check_int_v3(struct mxc_nand_host *host)
262{ 255{
263 uint32_t tmp; 256 uint32_t tmp;
@@ -280,26 +273,12 @@ static int check_int_v1_v2(struct mxc_nand_host *host)
280 if (!(tmp & NFC_V1_V2_CONFIG2_INT)) 273 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
281 return 0; 274 return 0;
282 275
283 if (!cpu_is_mx21()) 276 if (!host->irqpending_quirk)
284 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); 277 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
285 278
286 return 1; 279 return 1;
287} 280}
288 281
289/*
290 * It has been observed that the i.MX21 cannot read the CONFIG2:INT bit
291 * if interrupts are masked (CONFIG1:INT_MSK is set). To handle this, the
292 * driver can enable/disable the irq line rather than simply masking the
293 * interrupts.
294 */
295static void irq_control_mx21(struct mxc_nand_host *host, int activate)
296{
297 if (activate)
298 enable_irq(host->irq);
299 else
300 disable_irq_nosync(host->irq);
301}
302
303static void irq_control_v1_v2(struct mxc_nand_host *host, int activate) 282static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
304{ 283{
305 uint16_t tmp; 284 uint16_t tmp;
@@ -328,6 +307,32 @@ static void irq_control_v3(struct mxc_nand_host *host, int activate)
328 writel(tmp, NFC_V3_CONFIG2); 307 writel(tmp, NFC_V3_CONFIG2);
329} 308}
330 309
310static void irq_control(struct mxc_nand_host *host, int activate)
311{
312 if (host->irqpending_quirk) {
313 if (activate)
314 enable_irq(host->irq);
315 else
316 disable_irq_nosync(host->irq);
317 } else {
318 host->irq_control(host, activate);
319 }
320}
321
322static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
323{
324 struct mxc_nand_host *host = dev_id;
325
326 if (!host->check_int(host))
327 return IRQ_NONE;
328
329 irq_control(host, 0);
330
331 complete(&host->op_completion);
332
333 return IRQ_HANDLED;
334}
335
331/* This function polls the NANDFC to wait for the basic operation to 336/* This function polls the NANDFC to wait for the basic operation to
332 * complete by checking the INT bit of config2 register. 337 * complete by checking the INT bit of config2 register.
333 */ 338 */
@@ -338,7 +343,7 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq)
338 if (useirq) { 343 if (useirq) {
339 if (!host->check_int(host)) { 344 if (!host->check_int(host)) {
340 INIT_COMPLETION(host->op_completion); 345 INIT_COMPLETION(host->op_completion);
341 host->irq_control(host, 1); 346 irq_control(host, 1);
342 wait_for_completion(&host->op_completion); 347 wait_for_completion(&host->op_completion);
343 } 348 }
344 } else { 349 } else {
@@ -374,7 +379,7 @@ static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
374 writew(cmd, NFC_V1_V2_FLASH_CMD); 379 writew(cmd, NFC_V1_V2_FLASH_CMD);
375 writew(NFC_CMD, NFC_V1_V2_CONFIG2); 380 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
376 381
377 if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) { 382 if (host->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
378 int max_retries = 100; 383 int max_retries = 100;
379 /* Reset completion is indicated by NFC_CONFIG2 */ 384 /* Reset completion is indicated by NFC_CONFIG2 */
380 /* being set to 0 */ 385 /* being set to 0 */
@@ -812,7 +817,7 @@ static void preset_v1_v2(struct mtd_info *mtd)
812 if (nfc_is_v21()) 817 if (nfc_is_v21())
813 config1 |= NFC_V2_CONFIG1_FP_INT; 818 config1 |= NFC_V2_CONFIG1_FP_INT;
814 819
815 if (!cpu_is_mx21()) 820 if (!host->irqpending_quirk)
816 config1 |= NFC_V1_V2_CONFIG1_INT_MSK; 821 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
817 822
818 if (nfc_is_v21() && mtd->writesize) { 823 if (nfc_is_v21() && mtd->writesize) {
@@ -1103,10 +1108,9 @@ static int __init mxcnd_probe(struct platform_device *pdev)
1103 host->send_read_id = send_read_id_v1_v2; 1108 host->send_read_id = send_read_id_v1_v2;
1104 host->get_dev_status = get_dev_status_v1_v2; 1109 host->get_dev_status = get_dev_status_v1_v2;
1105 host->check_int = check_int_v1_v2; 1110 host->check_int = check_int_v1_v2;
1111 host->irq_control = irq_control_v1_v2;
1106 if (cpu_is_mx21()) 1112 if (cpu_is_mx21())
1107 host->irq_control = irq_control_mx21; 1113 host->irqpending_quirk = 1;
1108 else
1109 host->irq_control = irq_control_v1_v2;
1110 } 1114 }
1111 1115
1112 if (nfc_is_v21()) { 1116 if (nfc_is_v21()) {
@@ -1182,28 +1186,24 @@ static int __init mxcnd_probe(struct platform_device *pdev)
1182 host->irq = platform_get_irq(pdev, 0); 1186 host->irq = platform_get_irq(pdev, 0);
1183 1187
1184 /* 1188 /*
1185 * mask the interrupt. For i.MX21 explicitely call 1189 * Use host->irq_control here instead of irq_control because we must not
1186 * irq_control_v1_v2 to use the mask bit. We can't call 1190 * disable_irq_nosync without having requested the irq
1187 * disable_irq_nosync() for an interrupt we do not own yet.
1188 */ 1191 */
1189 if (cpu_is_mx21()) 1192 host->irq_control(host, 0);
1190 irq_control_v1_v2(host, 0);
1191 else
1192 host->irq_control(host, 0);
1193 1193
1194 err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host); 1194 err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
1195 if (err) 1195 if (err)
1196 goto eirq; 1196 goto eirq;
1197 1197
1198 host->irq_control(host, 0);
1199
1200 /* 1198 /*
1201 * Now that the interrupt is disabled make sure the interrupt 1199 * Now that we "own" the interrupt make sure the interrupt mask bit is
1202 * mask bit is cleared on i.MX21. Otherwise we can't read 1200 * cleared on i.MX21. Otherwise we can't read the interrupt status bit
1203 * the interrupt status bit on this machine. 1201 * on this machine.
1204 */ 1202 */
1205 if (cpu_is_mx21()) 1203 if (host->irqpending_quirk) {
1206 irq_control_v1_v2(host, 1); 1204 disable_irq_nosync(host->irq);
1205 host->irq_control(host, 1);
1206 }
1207 1207
1208 /* first scan to find the device and get the page size */ 1208 /* first scan to find the device and get the page size */
1209 if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) { 1209 if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) {