0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #define pr_fmt(fmt) "nand-s3c2410: " fmt
0011
0012 #ifdef CONFIG_MTD_NAND_S3C2410_DEBUG
0013 #define DEBUG
0014 #endif
0015
0016 #include <linux/module.h>
0017 #include <linux/types.h>
0018 #include <linux/kernel.h>
0019 #include <linux/string.h>
0020 #include <linux/io.h>
0021 #include <linux/ioport.h>
0022 #include <linux/platform_device.h>
0023 #include <linux/delay.h>
0024 #include <linux/err.h>
0025 #include <linux/slab.h>
0026 #include <linux/clk.h>
0027 #include <linux/cpufreq.h>
0028 #include <linux/of.h>
0029 #include <linux/of_device.h>
0030
0031 #include <linux/mtd/mtd.h>
0032 #include <linux/mtd/rawnand.h>
0033 #include <linux/mtd/partitions.h>
0034
0035 #include <linux/platform_data/mtd-nand-s3c2410.h>
0036
0037 #define S3C2410_NFREG(x) (x)
0038
0039 #define S3C2410_NFCONF S3C2410_NFREG(0x00)
0040 #define S3C2410_NFCMD S3C2410_NFREG(0x04)
0041 #define S3C2410_NFADDR S3C2410_NFREG(0x08)
0042 #define S3C2410_NFDATA S3C2410_NFREG(0x0C)
0043 #define S3C2410_NFSTAT S3C2410_NFREG(0x10)
0044 #define S3C2410_NFECC S3C2410_NFREG(0x14)
0045 #define S3C2440_NFCONT S3C2410_NFREG(0x04)
0046 #define S3C2440_NFCMD S3C2410_NFREG(0x08)
0047 #define S3C2440_NFADDR S3C2410_NFREG(0x0C)
0048 #define S3C2440_NFDATA S3C2410_NFREG(0x10)
0049 #define S3C2440_NFSTAT S3C2410_NFREG(0x20)
0050 #define S3C2440_NFMECC0 S3C2410_NFREG(0x2C)
0051 #define S3C2412_NFSTAT S3C2410_NFREG(0x28)
0052 #define S3C2412_NFMECC0 S3C2410_NFREG(0x34)
0053 #define S3C2410_NFCONF_EN (1<<15)
0054 #define S3C2410_NFCONF_INITECC (1<<12)
0055 #define S3C2410_NFCONF_nFCE (1<<11)
0056 #define S3C2410_NFCONF_TACLS(x) ((x)<<8)
0057 #define S3C2410_NFCONF_TWRPH0(x) ((x)<<4)
0058 #define S3C2410_NFCONF_TWRPH1(x) ((x)<<0)
0059 #define S3C2410_NFSTAT_BUSY (1<<0)
0060 #define S3C2440_NFCONF_TACLS(x) ((x)<<12)
0061 #define S3C2440_NFCONF_TWRPH0(x) ((x)<<8)
0062 #define S3C2440_NFCONF_TWRPH1(x) ((x)<<4)
0063 #define S3C2440_NFCONT_INITECC (1<<4)
0064 #define S3C2440_NFCONT_nFCE (1<<1)
0065 #define S3C2440_NFCONT_ENABLE (1<<0)
0066 #define S3C2440_NFSTAT_READY (1<<0)
0067 #define S3C2412_NFCONF_NANDBOOT (1<<31)
0068 #define S3C2412_NFCONT_INIT_MAIN_ECC (1<<5)
0069 #define S3C2412_NFCONT_nFCE0 (1<<1)
0070 #define S3C2412_NFSTAT_READY (1<<0)
0071
0072
0073
0074 static int s3c2410_ooblayout_ecc(struct mtd_info *mtd, int section,
0075 struct mtd_oob_region *oobregion)
0076 {
0077 if (section)
0078 return -ERANGE;
0079
0080 oobregion->offset = 0;
0081 oobregion->length = 3;
0082
0083 return 0;
0084 }
0085
0086 static int s3c2410_ooblayout_free(struct mtd_info *mtd, int section,
0087 struct mtd_oob_region *oobregion)
0088 {
0089 if (section)
0090 return -ERANGE;
0091
0092 oobregion->offset = 8;
0093 oobregion->length = 8;
0094
0095 return 0;
0096 }
0097
0098 static const struct mtd_ooblayout_ops s3c2410_ooblayout_ops = {
0099 .ecc = s3c2410_ooblayout_ecc,
0100 .free = s3c2410_ooblayout_free,
0101 };
0102
0103
0104
0105 struct s3c2410_nand_info;
0106
0107
0108
0109
0110
0111
0112
0113
0114 struct s3c2410_nand_mtd {
0115 struct nand_chip chip;
0116 struct s3c2410_nand_set *set;
0117 struct s3c2410_nand_info *info;
0118 };
0119
0120 enum s3c_cpu_type {
0121 TYPE_S3C2410,
0122 TYPE_S3C2412,
0123 TYPE_S3C2440,
0124 };
0125
0126 enum s3c_nand_clk_state {
0127 CLOCK_DISABLE = 0,
0128 CLOCK_ENABLE,
0129 CLOCK_SUSPEND,
0130 };
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151 struct s3c2410_nand_info {
0152
0153 struct nand_controller controller;
0154 struct s3c2410_nand_mtd *mtds;
0155 struct s3c2410_platform_nand *platform;
0156
0157
0158 struct device *device;
0159 struct clk *clk;
0160 void __iomem *regs;
0161 void __iomem *sel_reg;
0162 int sel_bit;
0163 int mtd_count;
0164 unsigned long save_sel;
0165 unsigned long clk_rate;
0166 enum s3c_nand_clk_state clk_state;
0167
0168 enum s3c_cpu_type cpu_type;
0169
0170 #ifdef CONFIG_ARM_S3C24XX_CPUFREQ
0171 struct notifier_block freq_transition;
0172 #endif
0173 };
0174
0175 struct s3c24XX_nand_devtype_data {
0176 enum s3c_cpu_type type;
0177 };
0178
0179 static const struct s3c24XX_nand_devtype_data s3c2410_nand_devtype_data = {
0180 .type = TYPE_S3C2410,
0181 };
0182
0183 static const struct s3c24XX_nand_devtype_data s3c2412_nand_devtype_data = {
0184 .type = TYPE_S3C2412,
0185 };
0186
0187 static const struct s3c24XX_nand_devtype_data s3c2440_nand_devtype_data = {
0188 .type = TYPE_S3C2440,
0189 };
0190
0191
0192
0193 static struct s3c2410_nand_mtd *s3c2410_nand_mtd_toours(struct mtd_info *mtd)
0194 {
0195 return container_of(mtd_to_nand(mtd), struct s3c2410_nand_mtd,
0196 chip);
0197 }
0198
0199 static struct s3c2410_nand_info *s3c2410_nand_mtd_toinfo(struct mtd_info *mtd)
0200 {
0201 return s3c2410_nand_mtd_toours(mtd)->info;
0202 }
0203
0204 static struct s3c2410_nand_info *to_nand_info(struct platform_device *dev)
0205 {
0206 return platform_get_drvdata(dev);
0207 }
0208
0209 static struct s3c2410_platform_nand *to_nand_plat(struct platform_device *dev)
0210 {
0211 return dev_get_platdata(&dev->dev);
0212 }
0213
0214 static inline int allow_clk_suspend(struct s3c2410_nand_info *info)
0215 {
0216 #ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP
0217 return 1;
0218 #else
0219 return 0;
0220 #endif
0221 }
0222
0223
0224
0225
0226
0227
0228 static void s3c2410_nand_clk_set_state(struct s3c2410_nand_info *info,
0229 enum s3c_nand_clk_state new_state)
0230 {
0231 if (!allow_clk_suspend(info) && new_state == CLOCK_SUSPEND)
0232 return;
0233
0234 if (info->clk_state == CLOCK_ENABLE) {
0235 if (new_state != CLOCK_ENABLE)
0236 clk_disable_unprepare(info->clk);
0237 } else {
0238 if (new_state == CLOCK_ENABLE)
0239 clk_prepare_enable(info->clk);
0240 }
0241
0242 info->clk_state = new_state;
0243 }
0244
0245
0246
0247 #define NS_IN_KHZ 1000000
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257 static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)
0258 {
0259 int result;
0260
0261 result = DIV_ROUND_UP((wanted * clk), NS_IN_KHZ);
0262
0263 pr_debug("result %d from %ld, %d\n", result, clk, wanted);
0264
0265 if (result > max) {
0266 pr_err("%d ns is too big for current clock rate %ld\n",
0267 wanted, clk);
0268 return -1;
0269 }
0270
0271 if (result < 1)
0272 result = 1;
0273
0274 return result;
0275 }
0276
0277 #define to_ns(ticks, clk) (((ticks) * NS_IN_KHZ) / (unsigned int)(clk))
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289 static int s3c2410_nand_setrate(struct s3c2410_nand_info *info)
0290 {
0291 struct s3c2410_platform_nand *plat = info->platform;
0292 int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4;
0293 int tacls, twrph0, twrph1;
0294 unsigned long clkrate = clk_get_rate(info->clk);
0295 unsigned long set, cfg, mask;
0296 unsigned long flags;
0297
0298
0299
0300 info->clk_rate = clkrate;
0301 clkrate /= 1000;
0302
0303 if (plat != NULL) {
0304 tacls = s3c_nand_calc_rate(plat->tacls, clkrate, tacls_max);
0305 twrph0 = s3c_nand_calc_rate(plat->twrph0, clkrate, 8);
0306 twrph1 = s3c_nand_calc_rate(plat->twrph1, clkrate, 8);
0307 } else {
0308
0309 tacls = tacls_max;
0310 twrph0 = 8;
0311 twrph1 = 8;
0312 }
0313
0314 if (tacls < 0 || twrph0 < 0 || twrph1 < 0) {
0315 dev_err(info->device, "cannot get suitable timings\n");
0316 return -EINVAL;
0317 }
0318
0319 dev_info(info->device, "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n",
0320 tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate),
0321 twrph1, to_ns(twrph1, clkrate));
0322
0323 switch (info->cpu_type) {
0324 case TYPE_S3C2410:
0325 mask = (S3C2410_NFCONF_TACLS(3) |
0326 S3C2410_NFCONF_TWRPH0(7) |
0327 S3C2410_NFCONF_TWRPH1(7));
0328 set = S3C2410_NFCONF_EN;
0329 set |= S3C2410_NFCONF_TACLS(tacls - 1);
0330 set |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
0331 set |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
0332 break;
0333
0334 case TYPE_S3C2440:
0335 case TYPE_S3C2412:
0336 mask = (S3C2440_NFCONF_TACLS(tacls_max - 1) |
0337 S3C2440_NFCONF_TWRPH0(7) |
0338 S3C2440_NFCONF_TWRPH1(7));
0339
0340 set = S3C2440_NFCONF_TACLS(tacls - 1);
0341 set |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
0342 set |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
0343 break;
0344
0345 default:
0346 BUG();
0347 }
0348
0349 local_irq_save(flags);
0350
0351 cfg = readl(info->regs + S3C2410_NFCONF);
0352 cfg &= ~mask;
0353 cfg |= set;
0354 writel(cfg, info->regs + S3C2410_NFCONF);
0355
0356 local_irq_restore(flags);
0357
0358 dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
0359
0360 return 0;
0361 }
0362
0363
0364
0365
0366
0367
0368
0369
0370 static int s3c2410_nand_inithw(struct s3c2410_nand_info *info)
0371 {
0372 int ret;
0373
0374 ret = s3c2410_nand_setrate(info);
0375 if (ret < 0)
0376 return ret;
0377
0378 switch (info->cpu_type) {
0379 case TYPE_S3C2410:
0380 default:
0381 break;
0382
0383 case TYPE_S3C2440:
0384 case TYPE_S3C2412:
0385
0386
0387 writel(S3C2440_NFCONT_ENABLE, info->regs + S3C2440_NFCONT);
0388 }
0389
0390 return 0;
0391 }
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406 static void s3c2410_nand_select_chip(struct nand_chip *this, int chip)
0407 {
0408 struct s3c2410_nand_info *info;
0409 struct s3c2410_nand_mtd *nmtd;
0410 unsigned long cur;
0411
0412 nmtd = nand_get_controller_data(this);
0413 info = nmtd->info;
0414
0415 if (chip != -1)
0416 s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
0417
0418 cur = readl(info->sel_reg);
0419
0420 if (chip == -1) {
0421 cur |= info->sel_bit;
0422 } else {
0423 if (nmtd->set != NULL && chip > nmtd->set->nr_chips) {
0424 dev_err(info->device, "invalid chip %d\n", chip);
0425 return;
0426 }
0427
0428 if (info->platform != NULL) {
0429 if (info->platform->select_chip != NULL)
0430 (info->platform->select_chip) (nmtd->set, chip);
0431 }
0432
0433 cur &= ~info->sel_bit;
0434 }
0435
0436 writel(cur, info->sel_reg);
0437
0438 if (chip == -1)
0439 s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
0440 }
0441
0442
0443
0444
0445
0446
0447 static void s3c2410_nand_hwcontrol(struct nand_chip *chip, int cmd,
0448 unsigned int ctrl)
0449 {
0450 struct mtd_info *mtd = nand_to_mtd(chip);
0451 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
0452
0453 if (cmd == NAND_CMD_NONE)
0454 return;
0455
0456 if (ctrl & NAND_CLE)
0457 writeb(cmd, info->regs + S3C2410_NFCMD);
0458 else
0459 writeb(cmd, info->regs + S3C2410_NFADDR);
0460 }
0461
0462
0463
0464 static void s3c2440_nand_hwcontrol(struct nand_chip *chip, int cmd,
0465 unsigned int ctrl)
0466 {
0467 struct mtd_info *mtd = nand_to_mtd(chip);
0468 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
0469
0470 if (cmd == NAND_CMD_NONE)
0471 return;
0472
0473 if (ctrl & NAND_CLE)
0474 writeb(cmd, info->regs + S3C2440_NFCMD);
0475 else
0476 writeb(cmd, info->regs + S3C2440_NFADDR);
0477 }
0478
0479
0480
0481
0482
0483
0484 static int s3c2410_nand_devready(struct nand_chip *chip)
0485 {
0486 struct mtd_info *mtd = nand_to_mtd(chip);
0487 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
0488 return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY;
0489 }
0490
0491 static int s3c2440_nand_devready(struct nand_chip *chip)
0492 {
0493 struct mtd_info *mtd = nand_to_mtd(chip);
0494 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
0495 return readb(info->regs + S3C2440_NFSTAT) & S3C2440_NFSTAT_READY;
0496 }
0497
0498 static int s3c2412_nand_devready(struct nand_chip *chip)
0499 {
0500 struct mtd_info *mtd = nand_to_mtd(chip);
0501 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
0502 return readb(info->regs + S3C2412_NFSTAT) & S3C2412_NFSTAT_READY;
0503 }
0504
0505
0506
0507 static int s3c2410_nand_correct_data(struct nand_chip *chip, u_char *dat,
0508 u_char *read_ecc, u_char *calc_ecc)
0509 {
0510 struct mtd_info *mtd = nand_to_mtd(chip);
0511 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
0512 unsigned int diff0, diff1, diff2;
0513 unsigned int bit, byte;
0514
0515 pr_debug("%s(%p,%p,%p,%p)\n", __func__, mtd, dat, read_ecc, calc_ecc);
0516
0517 diff0 = read_ecc[0] ^ calc_ecc[0];
0518 diff1 = read_ecc[1] ^ calc_ecc[1];
0519 diff2 = read_ecc[2] ^ calc_ecc[2];
0520
0521 pr_debug("%s: rd %*phN calc %*phN diff %02x%02x%02x\n",
0522 __func__, 3, read_ecc, 3, calc_ecc,
0523 diff0, diff1, diff2);
0524
0525 if (diff0 == 0 && diff1 == 0 && diff2 == 0)
0526 return 0;
0527
0528
0529
0530
0531
0532 if (read_ecc[0] == 0xff && read_ecc[1] == 0xff && read_ecc[2] == 0xff
0533 && info->platform->ignore_unset_ecc)
0534 return 0;
0535
0536
0537
0538
0539 if (((diff0 ^ (diff0 >> 1)) & 0x55) == 0x55 &&
0540 ((diff1 ^ (diff1 >> 1)) & 0x55) == 0x55 &&
0541 ((diff2 ^ (diff2 >> 1)) & 0x55) == 0x55) {
0542
0543
0544 bit = ((diff2 >> 3) & 1) |
0545 ((diff2 >> 4) & 2) |
0546 ((diff2 >> 5) & 4);
0547
0548
0549
0550 byte = ((diff2 << 7) & 0x100) |
0551 ((diff1 << 0) & 0x80) |
0552 ((diff1 << 1) & 0x40) |
0553 ((diff1 << 2) & 0x20) |
0554 ((diff1 << 3) & 0x10) |
0555 ((diff0 >> 4) & 0x08) |
0556 ((diff0 >> 3) & 0x04) |
0557 ((diff0 >> 2) & 0x02) |
0558 ((diff0 >> 1) & 0x01);
0559
0560 dev_dbg(info->device, "correcting error bit %d, byte %d\n",
0561 bit, byte);
0562
0563 dat[byte] ^= (1 << bit);
0564 return 1;
0565 }
0566
0567
0568
0569
0570
0571 diff0 |= (diff1 << 8);
0572 diff0 |= (diff2 << 16);
0573
0574
0575 if ((diff0 & (diff0 - 1)) == 0)
0576 return 1;
0577
0578 return -1;
0579 }
0580
0581
0582
0583
0584
0585
0586
0587 static void s3c2410_nand_enable_hwecc(struct nand_chip *chip, int mode)
0588 {
0589 struct s3c2410_nand_info *info;
0590 unsigned long ctrl;
0591
0592 info = s3c2410_nand_mtd_toinfo(nand_to_mtd(chip));
0593 ctrl = readl(info->regs + S3C2410_NFCONF);
0594 ctrl |= S3C2410_NFCONF_INITECC;
0595 writel(ctrl, info->regs + S3C2410_NFCONF);
0596 }
0597
0598 static void s3c2412_nand_enable_hwecc(struct nand_chip *chip, int mode)
0599 {
0600 struct s3c2410_nand_info *info;
0601 unsigned long ctrl;
0602
0603 info = s3c2410_nand_mtd_toinfo(nand_to_mtd(chip));
0604 ctrl = readl(info->regs + S3C2440_NFCONT);
0605 writel(ctrl | S3C2412_NFCONT_INIT_MAIN_ECC,
0606 info->regs + S3C2440_NFCONT);
0607 }
0608
0609 static void s3c2440_nand_enable_hwecc(struct nand_chip *chip, int mode)
0610 {
0611 struct s3c2410_nand_info *info;
0612 unsigned long ctrl;
0613
0614 info = s3c2410_nand_mtd_toinfo(nand_to_mtd(chip));
0615 ctrl = readl(info->regs + S3C2440_NFCONT);
0616 writel(ctrl | S3C2440_NFCONT_INITECC, info->regs + S3C2440_NFCONT);
0617 }
0618
0619 static int s3c2410_nand_calculate_ecc(struct nand_chip *chip,
0620 const u_char *dat, u_char *ecc_code)
0621 {
0622 struct mtd_info *mtd = nand_to_mtd(chip);
0623 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
0624
0625 ecc_code[0] = readb(info->regs + S3C2410_NFECC + 0);
0626 ecc_code[1] = readb(info->regs + S3C2410_NFECC + 1);
0627 ecc_code[2] = readb(info->regs + S3C2410_NFECC + 2);
0628
0629 pr_debug("%s: returning ecc %*phN\n", __func__, 3, ecc_code);
0630
0631 return 0;
0632 }
0633
0634 static int s3c2412_nand_calculate_ecc(struct nand_chip *chip,
0635 const u_char *dat, u_char *ecc_code)
0636 {
0637 struct mtd_info *mtd = nand_to_mtd(chip);
0638 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
0639 unsigned long ecc = readl(info->regs + S3C2412_NFMECC0);
0640
0641 ecc_code[0] = ecc;
0642 ecc_code[1] = ecc >> 8;
0643 ecc_code[2] = ecc >> 16;
0644
0645 pr_debug("%s: returning ecc %*phN\n", __func__, 3, ecc_code);
0646
0647 return 0;
0648 }
0649
0650 static int s3c2440_nand_calculate_ecc(struct nand_chip *chip,
0651 const u_char *dat, u_char *ecc_code)
0652 {
0653 struct mtd_info *mtd = nand_to_mtd(chip);
0654 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
0655 unsigned long ecc = readl(info->regs + S3C2440_NFMECC0);
0656
0657 ecc_code[0] = ecc;
0658 ecc_code[1] = ecc >> 8;
0659 ecc_code[2] = ecc >> 16;
0660
0661 pr_debug("%s: returning ecc %06lx\n", __func__, ecc & 0xffffff);
0662
0663 return 0;
0664 }
0665
0666
0667
0668
0669
0670 static void s3c2410_nand_read_buf(struct nand_chip *this, u_char *buf, int len)
0671 {
0672 readsb(this->legacy.IO_ADDR_R, buf, len);
0673 }
0674
0675 static void s3c2440_nand_read_buf(struct nand_chip *this, u_char *buf, int len)
0676 {
0677 struct mtd_info *mtd = nand_to_mtd(this);
0678 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
0679
0680 readsl(info->regs + S3C2440_NFDATA, buf, len >> 2);
0681
0682
0683 if (len & 3) {
0684 buf += len & ~3;
0685
0686 for (; len & 3; len--)
0687 *buf++ = readb(info->regs + S3C2440_NFDATA);
0688 }
0689 }
0690
0691 static void s3c2410_nand_write_buf(struct nand_chip *this, const u_char *buf,
0692 int len)
0693 {
0694 writesb(this->legacy.IO_ADDR_W, buf, len);
0695 }
0696
0697 static void s3c2440_nand_write_buf(struct nand_chip *this, const u_char *buf,
0698 int len)
0699 {
0700 struct mtd_info *mtd = nand_to_mtd(this);
0701 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
0702
0703 writesl(info->regs + S3C2440_NFDATA, buf, len >> 2);
0704
0705
0706 if (len & 3) {
0707 buf += len & ~3;
0708
0709 for (; len & 3; len--, buf++)
0710 writeb(*buf, info->regs + S3C2440_NFDATA);
0711 }
0712 }
0713
0714
0715
0716 #ifdef CONFIG_ARM_S3C24XX_CPUFREQ
0717
0718 static int s3c2410_nand_cpufreq_transition(struct notifier_block *nb,
0719 unsigned long val, void *data)
0720 {
0721 struct s3c2410_nand_info *info;
0722 unsigned long newclk;
0723
0724 info = container_of(nb, struct s3c2410_nand_info, freq_transition);
0725 newclk = clk_get_rate(info->clk);
0726
0727 if ((val == CPUFREQ_POSTCHANGE && newclk < info->clk_rate) ||
0728 (val == CPUFREQ_PRECHANGE && newclk > info->clk_rate)) {
0729 s3c2410_nand_setrate(info);
0730 }
0731
0732 return 0;
0733 }
0734
0735 static inline int s3c2410_nand_cpufreq_register(struct s3c2410_nand_info *info)
0736 {
0737 info->freq_transition.notifier_call = s3c2410_nand_cpufreq_transition;
0738
0739 return cpufreq_register_notifier(&info->freq_transition,
0740 CPUFREQ_TRANSITION_NOTIFIER);
0741 }
0742
0743 static inline void
0744 s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *info)
0745 {
0746 cpufreq_unregister_notifier(&info->freq_transition,
0747 CPUFREQ_TRANSITION_NOTIFIER);
0748 }
0749
0750 #else
0751 static inline int s3c2410_nand_cpufreq_register(struct s3c2410_nand_info *info)
0752 {
0753 return 0;
0754 }
0755
0756 static inline void
0757 s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *info)
0758 {
0759 }
0760 #endif
0761
0762
0763
0764 static int s3c24xx_nand_remove(struct platform_device *pdev)
0765 {
0766 struct s3c2410_nand_info *info = to_nand_info(pdev);
0767
0768 if (info == NULL)
0769 return 0;
0770
0771 s3c2410_nand_cpufreq_deregister(info);
0772
0773
0774
0775
0776
0777 if (info->mtds != NULL) {
0778 struct s3c2410_nand_mtd *ptr = info->mtds;
0779 int mtdno;
0780
0781 for (mtdno = 0; mtdno < info->mtd_count; mtdno++, ptr++) {
0782 pr_debug("releasing mtd %d (%p)\n", mtdno, ptr);
0783 WARN_ON(mtd_device_unregister(nand_to_mtd(&ptr->chip)));
0784 nand_cleanup(&ptr->chip);
0785 }
0786 }
0787
0788
0789
0790 if (!IS_ERR(info->clk))
0791 s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
0792
0793 return 0;
0794 }
0795
0796 static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
0797 struct s3c2410_nand_mtd *mtd,
0798 struct s3c2410_nand_set *set)
0799 {
0800 if (set) {
0801 struct mtd_info *mtdinfo = nand_to_mtd(&mtd->chip);
0802
0803 mtdinfo->name = set->name;
0804
0805 return mtd_device_register(mtdinfo, set->partitions,
0806 set->nr_partitions);
0807 }
0808
0809 return -ENODEV;
0810 }
0811
0812 static int s3c2410_nand_setup_interface(struct nand_chip *chip, int csline,
0813 const struct nand_interface_config *conf)
0814 {
0815 struct mtd_info *mtd = nand_to_mtd(chip);
0816 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
0817 struct s3c2410_platform_nand *pdata = info->platform;
0818 const struct nand_sdr_timings *timings;
0819 int tacls;
0820
0821 timings = nand_get_sdr_timings(conf);
0822 if (IS_ERR(timings))
0823 return -ENOTSUPP;
0824
0825 tacls = timings->tCLS_min - timings->tWP_min;
0826 if (tacls < 0)
0827 tacls = 0;
0828
0829 pdata->tacls = DIV_ROUND_UP(tacls, 1000);
0830 pdata->twrph0 = DIV_ROUND_UP(timings->tWP_min, 1000);
0831 pdata->twrph1 = DIV_ROUND_UP(timings->tCLH_min, 1000);
0832
0833 return s3c2410_nand_setrate(info);
0834 }
0835
0836
0837
0838
0839
0840
0841
0842
0843
0844
0845
0846 static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
0847 struct s3c2410_nand_mtd *nmtd,
0848 struct s3c2410_nand_set *set)
0849 {
0850 struct device_node *np = info->device->of_node;
0851 struct nand_chip *chip = &nmtd->chip;
0852 void __iomem *regs = info->regs;
0853
0854 nand_set_flash_node(chip, set->of_node);
0855
0856 chip->legacy.write_buf = s3c2410_nand_write_buf;
0857 chip->legacy.read_buf = s3c2410_nand_read_buf;
0858 chip->legacy.select_chip = s3c2410_nand_select_chip;
0859 chip->legacy.chip_delay = 50;
0860 nand_set_controller_data(chip, nmtd);
0861 chip->options = set->options;
0862 chip->controller = &info->controller;
0863
0864
0865
0866
0867
0868 if (!np)
0869 chip->options |= NAND_KEEP_TIMINGS;
0870
0871 switch (info->cpu_type) {
0872 case TYPE_S3C2410:
0873 chip->legacy.IO_ADDR_W = regs + S3C2410_NFDATA;
0874 info->sel_reg = regs + S3C2410_NFCONF;
0875 info->sel_bit = S3C2410_NFCONF_nFCE;
0876 chip->legacy.cmd_ctrl = s3c2410_nand_hwcontrol;
0877 chip->legacy.dev_ready = s3c2410_nand_devready;
0878 break;
0879
0880 case TYPE_S3C2440:
0881 chip->legacy.IO_ADDR_W = regs + S3C2440_NFDATA;
0882 info->sel_reg = regs + S3C2440_NFCONT;
0883 info->sel_bit = S3C2440_NFCONT_nFCE;
0884 chip->legacy.cmd_ctrl = s3c2440_nand_hwcontrol;
0885 chip->legacy.dev_ready = s3c2440_nand_devready;
0886 chip->legacy.read_buf = s3c2440_nand_read_buf;
0887 chip->legacy.write_buf = s3c2440_nand_write_buf;
0888 break;
0889
0890 case TYPE_S3C2412:
0891 chip->legacy.IO_ADDR_W = regs + S3C2440_NFDATA;
0892 info->sel_reg = regs + S3C2440_NFCONT;
0893 info->sel_bit = S3C2412_NFCONT_nFCE0;
0894 chip->legacy.cmd_ctrl = s3c2440_nand_hwcontrol;
0895 chip->legacy.dev_ready = s3c2412_nand_devready;
0896
0897 if (readl(regs + S3C2410_NFCONF) & S3C2412_NFCONF_NANDBOOT)
0898 dev_info(info->device, "System booted from NAND\n");
0899
0900 break;
0901 }
0902
0903 chip->legacy.IO_ADDR_R = chip->legacy.IO_ADDR_W;
0904
0905 nmtd->info = info;
0906 nmtd->set = set;
0907
0908 chip->ecc.engine_type = info->platform->engine_type;
0909
0910
0911
0912
0913
0914 if (set->flash_bbt)
0915 chip->bbt_options |= NAND_BBT_USE_FLASH;
0916 }
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926
0927
0928 static int s3c2410_nand_attach_chip(struct nand_chip *chip)
0929 {
0930 struct mtd_info *mtd = nand_to_mtd(chip);
0931 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
0932
0933 switch (chip->ecc.engine_type) {
0934
0935 case NAND_ECC_ENGINE_TYPE_NONE:
0936 dev_info(info->device, "ECC disabled\n");
0937 break;
0938
0939 case NAND_ECC_ENGINE_TYPE_SOFT:
0940
0941
0942
0943
0944
0945
0946 chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
0947 dev_info(info->device, "soft ECC\n");
0948 break;
0949
0950 case NAND_ECC_ENGINE_TYPE_ON_HOST:
0951 chip->ecc.calculate = s3c2410_nand_calculate_ecc;
0952 chip->ecc.correct = s3c2410_nand_correct_data;
0953 chip->ecc.strength = 1;
0954
0955 switch (info->cpu_type) {
0956 case TYPE_S3C2410:
0957 chip->ecc.hwctl = s3c2410_nand_enable_hwecc;
0958 chip->ecc.calculate = s3c2410_nand_calculate_ecc;
0959 break;
0960
0961 case TYPE_S3C2412:
0962 chip->ecc.hwctl = s3c2412_nand_enable_hwecc;
0963 chip->ecc.calculate = s3c2412_nand_calculate_ecc;
0964 break;
0965
0966 case TYPE_S3C2440:
0967 chip->ecc.hwctl = s3c2440_nand_enable_hwecc;
0968 chip->ecc.calculate = s3c2440_nand_calculate_ecc;
0969 break;
0970 }
0971
0972 dev_dbg(info->device, "chip %p => page shift %d\n",
0973 chip, chip->page_shift);
0974
0975
0976
0977 if (chip->page_shift > 10) {
0978 chip->ecc.size = 256;
0979 chip->ecc.bytes = 3;
0980 } else {
0981 chip->ecc.size = 512;
0982 chip->ecc.bytes = 3;
0983 mtd_set_ooblayout(nand_to_mtd(chip),
0984 &s3c2410_ooblayout_ops);
0985 }
0986
0987 dev_info(info->device, "hardware ECC\n");
0988 break;
0989
0990 default:
0991 dev_err(info->device, "invalid ECC mode!\n");
0992 return -EINVAL;
0993 }
0994
0995 if (chip->bbt_options & NAND_BBT_USE_FLASH)
0996 chip->options |= NAND_SKIP_BBTSCAN;
0997
0998 return 0;
0999 }
1000
1001 static const struct nand_controller_ops s3c24xx_nand_controller_ops = {
1002 .attach_chip = s3c2410_nand_attach_chip,
1003 .setup_interface = s3c2410_nand_setup_interface,
1004 };
1005
1006 static const struct of_device_id s3c24xx_nand_dt_ids[] = {
1007 {
1008 .compatible = "samsung,s3c2410-nand",
1009 .data = &s3c2410_nand_devtype_data,
1010 }, {
1011
1012 .compatible = "samsung,s3c2412-nand",
1013 .data = &s3c2412_nand_devtype_data,
1014 }, {
1015 .compatible = "samsung,s3c2440-nand",
1016 .data = &s3c2440_nand_devtype_data,
1017 },
1018 { }
1019 };
1020 MODULE_DEVICE_TABLE(of, s3c24xx_nand_dt_ids);
1021
1022 static int s3c24xx_nand_probe_dt(struct platform_device *pdev)
1023 {
1024 const struct s3c24XX_nand_devtype_data *devtype_data;
1025 struct s3c2410_platform_nand *pdata;
1026 struct s3c2410_nand_info *info = platform_get_drvdata(pdev);
1027 struct device_node *np = pdev->dev.of_node, *child;
1028 struct s3c2410_nand_set *sets;
1029
1030 devtype_data = of_device_get_match_data(&pdev->dev);
1031 if (!devtype_data)
1032 return -ENODEV;
1033
1034 info->cpu_type = devtype_data->type;
1035
1036 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
1037 if (!pdata)
1038 return -ENOMEM;
1039
1040 pdev->dev.platform_data = pdata;
1041
1042 pdata->nr_sets = of_get_child_count(np);
1043 if (!pdata->nr_sets)
1044 return 0;
1045
1046 sets = devm_kcalloc(&pdev->dev, pdata->nr_sets, sizeof(*sets),
1047 GFP_KERNEL);
1048 if (!sets)
1049 return -ENOMEM;
1050
1051 pdata->sets = sets;
1052
1053 for_each_available_child_of_node(np, child) {
1054 sets->name = (char *)child->name;
1055 sets->of_node = child;
1056 sets->nr_chips = 1;
1057
1058 of_node_get(child);
1059
1060 sets++;
1061 }
1062
1063 return 0;
1064 }
1065
1066 static int s3c24xx_nand_probe_pdata(struct platform_device *pdev)
1067 {
1068 struct s3c2410_nand_info *info = platform_get_drvdata(pdev);
1069
1070 info->cpu_type = platform_get_device_id(pdev)->driver_data;
1071
1072 return 0;
1073 }
1074
1075
1076
1077
1078
1079
1080
1081
1082 static int s3c24xx_nand_probe(struct platform_device *pdev)
1083 {
1084 struct s3c2410_platform_nand *plat;
1085 struct s3c2410_nand_info *info;
1086 struct s3c2410_nand_mtd *nmtd;
1087 struct s3c2410_nand_set *sets;
1088 struct resource *res;
1089 int err = 0;
1090 int size;
1091 int nr_sets;
1092 int setno;
1093
1094 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
1095 if (info == NULL) {
1096 err = -ENOMEM;
1097 goto exit_error;
1098 }
1099
1100 platform_set_drvdata(pdev, info);
1101
1102 nand_controller_init(&info->controller);
1103 info->controller.ops = &s3c24xx_nand_controller_ops;
1104
1105
1106
1107 info->clk = devm_clk_get(&pdev->dev, "nand");
1108 if (IS_ERR(info->clk)) {
1109 dev_err(&pdev->dev, "failed to get clock\n");
1110 err = -ENOENT;
1111 goto exit_error;
1112 }
1113
1114 s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
1115
1116 if (pdev->dev.of_node)
1117 err = s3c24xx_nand_probe_dt(pdev);
1118 else
1119 err = s3c24xx_nand_probe_pdata(pdev);
1120
1121 if (err)
1122 goto exit_error;
1123
1124 plat = to_nand_plat(pdev);
1125
1126
1127
1128
1129 res = pdev->resource;
1130 size = resource_size(res);
1131
1132 info->device = &pdev->dev;
1133 info->platform = plat;
1134
1135 info->regs = devm_ioremap_resource(&pdev->dev, res);
1136 if (IS_ERR(info->regs)) {
1137 err = PTR_ERR(info->regs);
1138 goto exit_error;
1139 }
1140
1141 dev_dbg(&pdev->dev, "mapped registers at %p\n", info->regs);
1142
1143 if (!plat->sets || plat->nr_sets < 1) {
1144 err = -EINVAL;
1145 goto exit_error;
1146 }
1147
1148 sets = plat->sets;
1149 nr_sets = plat->nr_sets;
1150
1151 info->mtd_count = nr_sets;
1152
1153
1154
1155 size = nr_sets * sizeof(*info->mtds);
1156 info->mtds = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
1157 if (info->mtds == NULL) {
1158 err = -ENOMEM;
1159 goto exit_error;
1160 }
1161
1162
1163
1164 nmtd = info->mtds;
1165
1166 for (setno = 0; setno < nr_sets; setno++, nmtd++, sets++) {
1167 struct mtd_info *mtd = nand_to_mtd(&nmtd->chip);
1168
1169 pr_debug("initialising set %d (%p, info %p)\n",
1170 setno, nmtd, info);
1171
1172 mtd->dev.parent = &pdev->dev;
1173 s3c2410_nand_init_chip(info, nmtd, sets);
1174
1175 err = nand_scan(&nmtd->chip, sets ? sets->nr_chips : 1);
1176 if (err)
1177 goto exit_error;
1178
1179 s3c2410_nand_add_partition(info, nmtd, sets);
1180 }
1181
1182
1183 err = s3c2410_nand_inithw(info);
1184 if (err != 0)
1185 goto exit_error;
1186
1187 err = s3c2410_nand_cpufreq_register(info);
1188 if (err < 0) {
1189 dev_err(&pdev->dev, "failed to init cpufreq support\n");
1190 goto exit_error;
1191 }
1192
1193 if (allow_clk_suspend(info)) {
1194 dev_info(&pdev->dev, "clock idle support enabled\n");
1195 s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
1196 }
1197
1198 return 0;
1199
1200 exit_error:
1201 s3c24xx_nand_remove(pdev);
1202
1203 if (err == 0)
1204 err = -EINVAL;
1205 return err;
1206 }
1207
1208
1209 #ifdef CONFIG_PM
1210
1211 static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
1212 {
1213 struct s3c2410_nand_info *info = platform_get_drvdata(dev);
1214
1215 if (info) {
1216 info->save_sel = readl(info->sel_reg);
1217
1218
1219
1220
1221
1222
1223 writel(info->save_sel | info->sel_bit, info->sel_reg);
1224
1225 s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
1226 }
1227
1228 return 0;
1229 }
1230
1231 static int s3c24xx_nand_resume(struct platform_device *dev)
1232 {
1233 struct s3c2410_nand_info *info = platform_get_drvdata(dev);
1234 unsigned long sel;
1235
1236 if (info) {
1237 s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
1238 s3c2410_nand_inithw(info);
1239
1240
1241
1242 sel = readl(info->sel_reg);
1243 sel &= ~info->sel_bit;
1244 sel |= info->save_sel & info->sel_bit;
1245 writel(sel, info->sel_reg);
1246
1247 s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
1248 }
1249
1250 return 0;
1251 }
1252
1253 #else
1254 #define s3c24xx_nand_suspend NULL
1255 #define s3c24xx_nand_resume NULL
1256 #endif
1257
1258
1259
1260 static const struct platform_device_id s3c24xx_driver_ids[] = {
1261 {
1262 .name = "s3c2410-nand",
1263 .driver_data = TYPE_S3C2410,
1264 }, {
1265 .name = "s3c2440-nand",
1266 .driver_data = TYPE_S3C2440,
1267 }, {
1268 .name = "s3c2412-nand",
1269 .driver_data = TYPE_S3C2412,
1270 }, {
1271 .name = "s3c6400-nand",
1272 .driver_data = TYPE_S3C2412,
1273 },
1274 { }
1275 };
1276
1277 MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
1278
1279 static struct platform_driver s3c24xx_nand_driver = {
1280 .probe = s3c24xx_nand_probe,
1281 .remove = s3c24xx_nand_remove,
1282 .suspend = s3c24xx_nand_suspend,
1283 .resume = s3c24xx_nand_resume,
1284 .id_table = s3c24xx_driver_ids,
1285 .driver = {
1286 .name = "s3c24xx-nand",
1287 .of_match_table = s3c24xx_nand_dt_ids,
1288 },
1289 };
1290
1291 module_platform_driver(s3c24xx_nand_driver);
1292
1293 MODULE_LICENSE("GPL");
1294 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
1295 MODULE_DESCRIPTION("S3C24XX MTD NAND driver");