root/drivers/mtd/nand/raw/s3c2410.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. s3c2410_ooblayout_ecc
  2. s3c2410_ooblayout_free
  3. s3c2410_nand_mtd_toours
  4. s3c2410_nand_mtd_toinfo
  5. to_nand_info
  6. to_nand_plat
  7. allow_clk_suspend
  8. s3c2410_nand_clk_set_state
  9. s3c_nand_calc_rate
  10. s3c2410_nand_setrate
  11. s3c2410_nand_inithw
  12. s3c2410_nand_select_chip
  13. s3c2410_nand_hwcontrol
  14. s3c2440_nand_hwcontrol
  15. s3c2410_nand_devready
  16. s3c2440_nand_devready
  17. s3c2412_nand_devready
  18. s3c2410_nand_correct_data
  19. s3c2410_nand_enable_hwecc
  20. s3c2412_nand_enable_hwecc
  21. s3c2440_nand_enable_hwecc
  22. s3c2410_nand_calculate_ecc
  23. s3c2412_nand_calculate_ecc
  24. s3c2440_nand_calculate_ecc
  25. s3c2410_nand_read_buf
  26. s3c2440_nand_read_buf
  27. s3c2410_nand_write_buf
  28. s3c2440_nand_write_buf
  29. s3c2410_nand_cpufreq_transition
  30. s3c2410_nand_cpufreq_register
  31. s3c2410_nand_cpufreq_deregister
  32. s3c2410_nand_cpufreq_register
  33. s3c2410_nand_cpufreq_deregister
  34. s3c24xx_nand_remove
  35. s3c2410_nand_add_partition
  36. s3c2410_nand_setup_data_interface
  37. s3c2410_nand_init_chip
  38. s3c2410_nand_attach_chip
  39. s3c24xx_nand_probe_dt
  40. s3c24xx_nand_probe_pdata
  41. s3c24xx_nand_probe
  42. s3c24xx_nand_suspend
  43. s3c24xx_nand_resume

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright © 2004-2008 Simtec Electronics
   4  *      http://armlinux.simtec.co.uk/
   5  *      Ben Dooks <ben@simtec.co.uk>
   6  *
   7  * Samsung S3C2410/S3C2440/S3C2412 NAND driver
   8 */
   9 
  10 #define pr_fmt(fmt) "nand-s3c2410: " fmt
  11 
  12 #ifdef CONFIG_MTD_NAND_S3C2410_DEBUG
  13 #define DEBUG
  14 #endif
  15 
  16 #include <linux/module.h>
  17 #include <linux/types.h>
  18 #include <linux/kernel.h>
  19 #include <linux/string.h>
  20 #include <linux/io.h>
  21 #include <linux/ioport.h>
  22 #include <linux/platform_device.h>
  23 #include <linux/delay.h>
  24 #include <linux/err.h>
  25 #include <linux/slab.h>
  26 #include <linux/clk.h>
  27 #include <linux/cpufreq.h>
  28 #include <linux/of.h>
  29 #include <linux/of_device.h>
  30 
  31 #include <linux/mtd/mtd.h>
  32 #include <linux/mtd/rawnand.h>
  33 #include <linux/mtd/nand_ecc.h>
  34 #include <linux/mtd/partitions.h>
  35 
  36 #include <linux/platform_data/mtd-nand-s3c2410.h>
  37 
  38 #define S3C2410_NFREG(x) (x)
  39 
  40 #define S3C2410_NFCONF          S3C2410_NFREG(0x00)
  41 #define S3C2410_NFCMD           S3C2410_NFREG(0x04)
  42 #define S3C2410_NFADDR          S3C2410_NFREG(0x08)
  43 #define S3C2410_NFDATA          S3C2410_NFREG(0x0C)
  44 #define S3C2410_NFSTAT          S3C2410_NFREG(0x10)
  45 #define S3C2410_NFECC           S3C2410_NFREG(0x14)
  46 #define S3C2440_NFCONT          S3C2410_NFREG(0x04)
  47 #define S3C2440_NFCMD           S3C2410_NFREG(0x08)
  48 #define S3C2440_NFADDR          S3C2410_NFREG(0x0C)
  49 #define S3C2440_NFDATA          S3C2410_NFREG(0x10)
  50 #define S3C2440_NFSTAT          S3C2410_NFREG(0x20)
  51 #define S3C2440_NFMECC0         S3C2410_NFREG(0x2C)
  52 #define S3C2412_NFSTAT          S3C2410_NFREG(0x28)
  53 #define S3C2412_NFMECC0         S3C2410_NFREG(0x34)
  54 #define S3C2410_NFCONF_EN               (1<<15)
  55 #define S3C2410_NFCONF_INITECC          (1<<12)
  56 #define S3C2410_NFCONF_nFCE             (1<<11)
  57 #define S3C2410_NFCONF_TACLS(x)         ((x)<<8)
  58 #define S3C2410_NFCONF_TWRPH0(x)        ((x)<<4)
  59 #define S3C2410_NFCONF_TWRPH1(x)        ((x)<<0)
  60 #define S3C2410_NFSTAT_BUSY             (1<<0)
  61 #define S3C2440_NFCONF_TACLS(x)         ((x)<<12)
  62 #define S3C2440_NFCONF_TWRPH0(x)        ((x)<<8)
  63 #define S3C2440_NFCONF_TWRPH1(x)        ((x)<<4)
  64 #define S3C2440_NFCONT_INITECC          (1<<4)
  65 #define S3C2440_NFCONT_nFCE             (1<<1)
  66 #define S3C2440_NFCONT_ENABLE           (1<<0)
  67 #define S3C2440_NFSTAT_READY            (1<<0)
  68 #define S3C2412_NFCONF_NANDBOOT         (1<<31)
  69 #define S3C2412_NFCONT_INIT_MAIN_ECC    (1<<5)
  70 #define S3C2412_NFCONT_nFCE0            (1<<1)
  71 #define S3C2412_NFSTAT_READY            (1<<0)
  72 
  73 /* new oob placement block for use with hardware ecc generation
  74  */
  75 static int s3c2410_ooblayout_ecc(struct mtd_info *mtd, int section,
  76                                  struct mtd_oob_region *oobregion)
  77 {
  78         if (section)
  79                 return -ERANGE;
  80 
  81         oobregion->offset = 0;
  82         oobregion->length = 3;
  83 
  84         return 0;
  85 }
  86 
  87 static int s3c2410_ooblayout_free(struct mtd_info *mtd, int section,
  88                                   struct mtd_oob_region *oobregion)
  89 {
  90         if (section)
  91                 return -ERANGE;
  92 
  93         oobregion->offset = 8;
  94         oobregion->length = 8;
  95 
  96         return 0;
  97 }
  98 
  99 static const struct mtd_ooblayout_ops s3c2410_ooblayout_ops = {
 100         .ecc = s3c2410_ooblayout_ecc,
 101         .free = s3c2410_ooblayout_free,
 102 };
 103 
 104 /* controller and mtd information */
 105 
 106 struct s3c2410_nand_info;
 107 
 108 /**
 109  * struct s3c2410_nand_mtd - driver MTD structure
 110  * @mtd: The MTD instance to pass to the MTD layer.
 111  * @chip: The NAND chip information.
 112  * @set: The platform information supplied for this set of NAND chips.
 113  * @info: Link back to the hardware information.
 114 */
 115 struct s3c2410_nand_mtd {
 116         struct nand_chip                chip;
 117         struct s3c2410_nand_set         *set;
 118         struct s3c2410_nand_info        *info;
 119 };
 120 
 121 enum s3c_cpu_type {
 122         TYPE_S3C2410,
 123         TYPE_S3C2412,
 124         TYPE_S3C2440,
 125 };
 126 
 127 enum s3c_nand_clk_state {
 128         CLOCK_DISABLE   = 0,
 129         CLOCK_ENABLE,
 130         CLOCK_SUSPEND,
 131 };
 132 
 133 /* overview of the s3c2410 nand state */
 134 
 135 /**
 136  * struct s3c2410_nand_info - NAND controller state.
 137  * @mtds: An array of MTD instances on this controoler.
 138  * @platform: The platform data for this board.
 139  * @device: The platform device we bound to.
 140  * @clk: The clock resource for this controller.
 141  * @regs: The area mapped for the hardware registers.
 142  * @sel_reg: Pointer to the register controlling the NAND selection.
 143  * @sel_bit: The bit in @sel_reg to select the NAND chip.
 144  * @mtd_count: The number of MTDs created from this controller.
 145  * @save_sel: The contents of @sel_reg to be saved over suspend.
 146  * @clk_rate: The clock rate from @clk.
 147  * @clk_state: The current clock state.
 148  * @cpu_type: The exact type of this controller.
 149  */
 150 struct s3c2410_nand_info {
 151         /* mtd info */
 152         struct nand_controller          controller;
 153         struct s3c2410_nand_mtd         *mtds;
 154         struct s3c2410_platform_nand    *platform;
 155 
 156         /* device info */
 157         struct device                   *device;
 158         struct clk                      *clk;
 159         void __iomem                    *regs;
 160         void __iomem                    *sel_reg;
 161         int                             sel_bit;
 162         int                             mtd_count;
 163         unsigned long                   save_sel;
 164         unsigned long                   clk_rate;
 165         enum s3c_nand_clk_state         clk_state;
 166 
 167         enum s3c_cpu_type               cpu_type;
 168 
 169 #ifdef CONFIG_ARM_S3C24XX_CPUFREQ
 170         struct notifier_block   freq_transition;
 171 #endif
 172 };
 173 
 174 struct s3c24XX_nand_devtype_data {
 175         enum s3c_cpu_type type;
 176 };
 177 
 178 static const struct s3c24XX_nand_devtype_data s3c2410_nand_devtype_data = {
 179         .type = TYPE_S3C2410,
 180 };
 181 
 182 static const struct s3c24XX_nand_devtype_data s3c2412_nand_devtype_data = {
 183         .type = TYPE_S3C2412,
 184 };
 185 
 186 static const struct s3c24XX_nand_devtype_data s3c2440_nand_devtype_data = {
 187         .type = TYPE_S3C2440,
 188 };
 189 
 190 /* conversion functions */
 191 
 192 static struct s3c2410_nand_mtd *s3c2410_nand_mtd_toours(struct mtd_info *mtd)
 193 {
 194         return container_of(mtd_to_nand(mtd), struct s3c2410_nand_mtd,
 195                             chip);
 196 }
 197 
 198 static struct s3c2410_nand_info *s3c2410_nand_mtd_toinfo(struct mtd_info *mtd)
 199 {
 200         return s3c2410_nand_mtd_toours(mtd)->info;
 201 }
 202 
 203 static struct s3c2410_nand_info *to_nand_info(struct platform_device *dev)
 204 {
 205         return platform_get_drvdata(dev);
 206 }
 207 
 208 static struct s3c2410_platform_nand *to_nand_plat(struct platform_device *dev)
 209 {
 210         return dev_get_platdata(&dev->dev);
 211 }
 212 
 213 static inline int allow_clk_suspend(struct s3c2410_nand_info *info)
 214 {
 215 #ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP
 216         return 1;
 217 #else
 218         return 0;
 219 #endif
 220 }
 221 
 222 /**
 223  * s3c2410_nand_clk_set_state - Enable, disable or suspend NAND clock.
 224  * @info: The controller instance.
 225  * @new_state: State to which clock should be set.
 226  */
 227 static void s3c2410_nand_clk_set_state(struct s3c2410_nand_info *info,
 228                 enum s3c_nand_clk_state new_state)
 229 {
 230         if (!allow_clk_suspend(info) && new_state == CLOCK_SUSPEND)
 231                 return;
 232 
 233         if (info->clk_state == CLOCK_ENABLE) {
 234                 if (new_state != CLOCK_ENABLE)
 235                         clk_disable_unprepare(info->clk);
 236         } else {
 237                 if (new_state == CLOCK_ENABLE)
 238                         clk_prepare_enable(info->clk);
 239         }
 240 
 241         info->clk_state = new_state;
 242 }
 243 
 244 /* timing calculations */
 245 
 246 #define NS_IN_KHZ 1000000
 247 
 248 /**
 249  * s3c_nand_calc_rate - calculate timing data.
 250  * @wanted: The cycle time in nanoseconds.
 251  * @clk: The clock rate in kHz.
 252  * @max: The maximum divider value.
 253  *
 254  * Calculate the timing value from the given parameters.
 255  */
 256 static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)
 257 {
 258         int result;
 259 
 260         result = DIV_ROUND_UP((wanted * clk), NS_IN_KHZ);
 261 
 262         pr_debug("result %d from %ld, %d\n", result, clk, wanted);
 263 
 264         if (result > max) {
 265                 pr_err("%d ns is too big for current clock rate %ld\n",
 266                         wanted, clk);
 267                 return -1;
 268         }
 269 
 270         if (result < 1)
 271                 result = 1;
 272 
 273         return result;
 274 }
 275 
 276 #define to_ns(ticks, clk) (((ticks) * NS_IN_KHZ) / (unsigned int)(clk))
 277 
 278 /* controller setup */
 279 
 280 /**
 281  * s3c2410_nand_setrate - setup controller timing information.
 282  * @info: The controller instance.
 283  *
 284  * Given the information supplied by the platform, calculate and set
 285  * the necessary timing registers in the hardware to generate the
 286  * necessary timing cycles to the hardware.
 287  */
 288 static int s3c2410_nand_setrate(struct s3c2410_nand_info *info)
 289 {
 290         struct s3c2410_platform_nand *plat = info->platform;
 291         int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4;
 292         int tacls, twrph0, twrph1;
 293         unsigned long clkrate = clk_get_rate(info->clk);
 294         unsigned long uninitialized_var(set), cfg, uninitialized_var(mask);
 295         unsigned long flags;
 296 
 297         /* calculate the timing information for the controller */
 298 
 299         info->clk_rate = clkrate;
 300         clkrate /= 1000;        /* turn clock into kHz for ease of use */
 301 
 302         if (plat != NULL) {
 303                 tacls = s3c_nand_calc_rate(plat->tacls, clkrate, tacls_max);
 304                 twrph0 = s3c_nand_calc_rate(plat->twrph0, clkrate, 8);
 305                 twrph1 = s3c_nand_calc_rate(plat->twrph1, clkrate, 8);
 306         } else {
 307                 /* default timings */
 308                 tacls = tacls_max;
 309                 twrph0 = 8;
 310                 twrph1 = 8;
 311         }
 312 
 313         if (tacls < 0 || twrph0 < 0 || twrph1 < 0) {
 314                 dev_err(info->device, "cannot get suitable timings\n");
 315                 return -EINVAL;
 316         }
 317 
 318         dev_info(info->device, "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n",
 319                 tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate),
 320                                                 twrph1, to_ns(twrph1, clkrate));
 321 
 322         switch (info->cpu_type) {
 323         case TYPE_S3C2410:
 324                 mask = (S3C2410_NFCONF_TACLS(3) |
 325                         S3C2410_NFCONF_TWRPH0(7) |
 326                         S3C2410_NFCONF_TWRPH1(7));
 327                 set = S3C2410_NFCONF_EN;
 328                 set |= S3C2410_NFCONF_TACLS(tacls - 1);
 329                 set |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
 330                 set |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
 331                 break;
 332 
 333         case TYPE_S3C2440:
 334         case TYPE_S3C2412:
 335                 mask = (S3C2440_NFCONF_TACLS(tacls_max - 1) |
 336                         S3C2440_NFCONF_TWRPH0(7) |
 337                         S3C2440_NFCONF_TWRPH1(7));
 338 
 339                 set = S3C2440_NFCONF_TACLS(tacls - 1);
 340                 set |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
 341                 set |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
 342                 break;
 343 
 344         default:
 345                 BUG();
 346         }
 347 
 348         local_irq_save(flags);
 349 
 350         cfg = readl(info->regs + S3C2410_NFCONF);
 351         cfg &= ~mask;
 352         cfg |= set;
 353         writel(cfg, info->regs + S3C2410_NFCONF);
 354 
 355         local_irq_restore(flags);
 356 
 357         dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
 358 
 359         return 0;
 360 }
 361 
 362 /**
 363  * s3c2410_nand_inithw - basic hardware initialisation
 364  * @info: The hardware state.
 365  *
 366  * Do the basic initialisation of the hardware, using s3c2410_nand_setrate()
 367  * to setup the hardware access speeds and set the controller to be enabled.
 368 */
 369 static int s3c2410_nand_inithw(struct s3c2410_nand_info *info)
 370 {
 371         int ret;
 372 
 373         ret = s3c2410_nand_setrate(info);
 374         if (ret < 0)
 375                 return ret;
 376 
 377         switch (info->cpu_type) {
 378         case TYPE_S3C2410:
 379         default:
 380                 break;
 381 
 382         case TYPE_S3C2440:
 383         case TYPE_S3C2412:
 384                 /* enable the controller and de-assert nFCE */
 385 
 386                 writel(S3C2440_NFCONT_ENABLE, info->regs + S3C2440_NFCONT);
 387         }
 388 
 389         return 0;
 390 }
 391 
 392 /**
 393  * s3c2410_nand_select_chip - select the given nand chip
 394  * @this: NAND chip object.
 395  * @chip: The chip number.
 396  *
 397  * This is called by the MTD layer to either select a given chip for the
 398  * @mtd instance, or to indicate that the access has finished and the
 399  * chip can be de-selected.
 400  *
 401  * The routine ensures that the nFCE line is correctly setup, and any
 402  * platform specific selection code is called to route nFCE to the specific
 403  * chip.
 404  */
 405 static void s3c2410_nand_select_chip(struct nand_chip *this, int chip)
 406 {
 407         struct s3c2410_nand_info *info;
 408         struct s3c2410_nand_mtd *nmtd;
 409         unsigned long cur;
 410 
 411         nmtd = nand_get_controller_data(this);
 412         info = nmtd->info;
 413 
 414         if (chip != -1)
 415                 s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
 416 
 417         cur = readl(info->sel_reg);
 418 
 419         if (chip == -1) {
 420                 cur |= info->sel_bit;
 421         } else {
 422                 if (nmtd->set != NULL && chip > nmtd->set->nr_chips) {
 423                         dev_err(info->device, "invalid chip %d\n", chip);
 424                         return;
 425                 }
 426 
 427                 if (info->platform != NULL) {
 428                         if (info->platform->select_chip != NULL)
 429                                 (info->platform->select_chip) (nmtd->set, chip);
 430                 }
 431 
 432                 cur &= ~info->sel_bit;
 433         }
 434 
 435         writel(cur, info->sel_reg);
 436 
 437         if (chip == -1)
 438                 s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
 439 }
 440 
 441 /* s3c2410_nand_hwcontrol
 442  *
 443  * Issue command and address cycles to the chip
 444 */
 445 
 446 static void s3c2410_nand_hwcontrol(struct nand_chip *chip, int cmd,
 447                                    unsigned int ctrl)
 448 {
 449         struct mtd_info *mtd = nand_to_mtd(chip);
 450         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 451 
 452         if (cmd == NAND_CMD_NONE)
 453                 return;
 454 
 455         if (ctrl & NAND_CLE)
 456                 writeb(cmd, info->regs + S3C2410_NFCMD);
 457         else
 458                 writeb(cmd, info->regs + S3C2410_NFADDR);
 459 }
 460 
 461 /* command and control functions */
 462 
 463 static void s3c2440_nand_hwcontrol(struct nand_chip *chip, int cmd,
 464                                    unsigned int ctrl)
 465 {
 466         struct mtd_info *mtd = nand_to_mtd(chip);
 467         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 468 
 469         if (cmd == NAND_CMD_NONE)
 470                 return;
 471 
 472         if (ctrl & NAND_CLE)
 473                 writeb(cmd, info->regs + S3C2440_NFCMD);
 474         else
 475                 writeb(cmd, info->regs + S3C2440_NFADDR);
 476 }
 477 
 478 /* s3c2410_nand_devready()
 479  *
 480  * returns 0 if the nand is busy, 1 if it is ready
 481 */
 482 
 483 static int s3c2410_nand_devready(struct nand_chip *chip)
 484 {
 485         struct mtd_info *mtd = nand_to_mtd(chip);
 486         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 487         return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY;
 488 }
 489 
 490 static int s3c2440_nand_devready(struct nand_chip *chip)
 491 {
 492         struct mtd_info *mtd = nand_to_mtd(chip);
 493         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 494         return readb(info->regs + S3C2440_NFSTAT) & S3C2440_NFSTAT_READY;
 495 }
 496 
 497 static int s3c2412_nand_devready(struct nand_chip *chip)
 498 {
 499         struct mtd_info *mtd = nand_to_mtd(chip);
 500         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 501         return readb(info->regs + S3C2412_NFSTAT) & S3C2412_NFSTAT_READY;
 502 }
 503 
 504 /* ECC handling functions */
 505 
 506 static int s3c2410_nand_correct_data(struct nand_chip *chip, u_char *dat,
 507                                      u_char *read_ecc, u_char *calc_ecc)
 508 {
 509         struct mtd_info *mtd = nand_to_mtd(chip);
 510         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 511         unsigned int diff0, diff1, diff2;
 512         unsigned int bit, byte;
 513 
 514         pr_debug("%s(%p,%p,%p,%p)\n", __func__, mtd, dat, read_ecc, calc_ecc);
 515 
 516         diff0 = read_ecc[0] ^ calc_ecc[0];
 517         diff1 = read_ecc[1] ^ calc_ecc[1];
 518         diff2 = read_ecc[2] ^ calc_ecc[2];
 519 
 520         pr_debug("%s: rd %*phN calc %*phN diff %02x%02x%02x\n",
 521                  __func__, 3, read_ecc, 3, calc_ecc,
 522                  diff0, diff1, diff2);
 523 
 524         if (diff0 == 0 && diff1 == 0 && diff2 == 0)
 525                 return 0;               /* ECC is ok */
 526 
 527         /* sometimes people do not think about using the ECC, so check
 528          * to see if we have an 0xff,0xff,0xff read ECC and then ignore
 529          * the error, on the assumption that this is an un-eccd page.
 530          */
 531         if (read_ecc[0] == 0xff && read_ecc[1] == 0xff && read_ecc[2] == 0xff
 532             && info->platform->ignore_unset_ecc)
 533                 return 0;
 534 
 535         /* Can we correct this ECC (ie, one row and column change).
 536          * Note, this is similar to the 256 error code on smartmedia */
 537 
 538         if (((diff0 ^ (diff0 >> 1)) & 0x55) == 0x55 &&
 539             ((diff1 ^ (diff1 >> 1)) & 0x55) == 0x55 &&
 540             ((diff2 ^ (diff2 >> 1)) & 0x55) == 0x55) {
 541                 /* calculate the bit position of the error */
 542 
 543                 bit  = ((diff2 >> 3) & 1) |
 544                        ((diff2 >> 4) & 2) |
 545                        ((diff2 >> 5) & 4);
 546 
 547                 /* calculate the byte position of the error */
 548 
 549                 byte = ((diff2 << 7) & 0x100) |
 550                        ((diff1 << 0) & 0x80)  |
 551                        ((diff1 << 1) & 0x40)  |
 552                        ((diff1 << 2) & 0x20)  |
 553                        ((diff1 << 3) & 0x10)  |
 554                        ((diff0 >> 4) & 0x08)  |
 555                        ((diff0 >> 3) & 0x04)  |
 556                        ((diff0 >> 2) & 0x02)  |
 557                        ((diff0 >> 1) & 0x01);
 558 
 559                 dev_dbg(info->device, "correcting error bit %d, byte %d\n",
 560                         bit, byte);
 561 
 562                 dat[byte] ^= (1 << bit);
 563                 return 1;
 564         }
 565 
 566         /* if there is only one bit difference in the ECC, then
 567          * one of only a row or column parity has changed, which
 568          * means the error is most probably in the ECC itself */
 569 
 570         diff0 |= (diff1 << 8);
 571         diff0 |= (diff2 << 16);
 572 
 573         /* equal to "(diff0 & ~(1 << __ffs(diff0)))" */
 574         if ((diff0 & (diff0 - 1)) == 0)
 575                 return 1;
 576 
 577         return -1;
 578 }
 579 
 580 /* ECC functions
 581  *
 582  * These allow the s3c2410 and s3c2440 to use the controller's ECC
 583  * generator block to ECC the data as it passes through]
 584 */
 585 
 586 static void s3c2410_nand_enable_hwecc(struct nand_chip *chip, int mode)
 587 {
 588         struct s3c2410_nand_info *info;
 589         unsigned long ctrl;
 590 
 591         info = s3c2410_nand_mtd_toinfo(nand_to_mtd(chip));
 592         ctrl = readl(info->regs + S3C2410_NFCONF);
 593         ctrl |= S3C2410_NFCONF_INITECC;
 594         writel(ctrl, info->regs + S3C2410_NFCONF);
 595 }
 596 
 597 static void s3c2412_nand_enable_hwecc(struct nand_chip *chip, int mode)
 598 {
 599         struct s3c2410_nand_info *info;
 600         unsigned long ctrl;
 601 
 602         info = s3c2410_nand_mtd_toinfo(nand_to_mtd(chip));
 603         ctrl = readl(info->regs + S3C2440_NFCONT);
 604         writel(ctrl | S3C2412_NFCONT_INIT_MAIN_ECC,
 605                info->regs + S3C2440_NFCONT);
 606 }
 607 
 608 static void s3c2440_nand_enable_hwecc(struct nand_chip *chip, int mode)
 609 {
 610         struct s3c2410_nand_info *info;
 611         unsigned long ctrl;
 612 
 613         info = s3c2410_nand_mtd_toinfo(nand_to_mtd(chip));
 614         ctrl = readl(info->regs + S3C2440_NFCONT);
 615         writel(ctrl | S3C2440_NFCONT_INITECC, info->regs + S3C2440_NFCONT);
 616 }
 617 
 618 static int s3c2410_nand_calculate_ecc(struct nand_chip *chip,
 619                                       const u_char *dat, u_char *ecc_code)
 620 {
 621         struct mtd_info *mtd = nand_to_mtd(chip);
 622         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 623 
 624         ecc_code[0] = readb(info->regs + S3C2410_NFECC + 0);
 625         ecc_code[1] = readb(info->regs + S3C2410_NFECC + 1);
 626         ecc_code[2] = readb(info->regs + S3C2410_NFECC + 2);
 627 
 628         pr_debug("%s: returning ecc %*phN\n", __func__, 3, ecc_code);
 629 
 630         return 0;
 631 }
 632 
 633 static int s3c2412_nand_calculate_ecc(struct nand_chip *chip,
 634                                       const u_char *dat, u_char *ecc_code)
 635 {
 636         struct mtd_info *mtd = nand_to_mtd(chip);
 637         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 638         unsigned long ecc = readl(info->regs + S3C2412_NFMECC0);
 639 
 640         ecc_code[0] = ecc;
 641         ecc_code[1] = ecc >> 8;
 642         ecc_code[2] = ecc >> 16;
 643 
 644         pr_debug("%s: returning ecc %*phN\n", __func__, 3, ecc_code);
 645 
 646         return 0;
 647 }
 648 
 649 static int s3c2440_nand_calculate_ecc(struct nand_chip *chip,
 650                                       const u_char *dat, u_char *ecc_code)
 651 {
 652         struct mtd_info *mtd = nand_to_mtd(chip);
 653         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 654         unsigned long ecc = readl(info->regs + S3C2440_NFMECC0);
 655 
 656         ecc_code[0] = ecc;
 657         ecc_code[1] = ecc >> 8;
 658         ecc_code[2] = ecc >> 16;
 659 
 660         pr_debug("%s: returning ecc %06lx\n", __func__, ecc & 0xffffff);
 661 
 662         return 0;
 663 }
 664 
 665 /* over-ride the standard functions for a little more speed. We can
 666  * use read/write block to move the data buffers to/from the controller
 667 */
 668 
 669 static void s3c2410_nand_read_buf(struct nand_chip *this, u_char *buf, int len)
 670 {
 671         readsb(this->legacy.IO_ADDR_R, buf, len);
 672 }
 673 
 674 static void s3c2440_nand_read_buf(struct nand_chip *this, u_char *buf, int len)
 675 {
 676         struct mtd_info *mtd = nand_to_mtd(this);
 677         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 678 
 679         readsl(info->regs + S3C2440_NFDATA, buf, len >> 2);
 680 
 681         /* cleanup if we've got less than a word to do */
 682         if (len & 3) {
 683                 buf += len & ~3;
 684 
 685                 for (; len & 3; len--)
 686                         *buf++ = readb(info->regs + S3C2440_NFDATA);
 687         }
 688 }
 689 
 690 static void s3c2410_nand_write_buf(struct nand_chip *this, const u_char *buf,
 691                                    int len)
 692 {
 693         writesb(this->legacy.IO_ADDR_W, buf, len);
 694 }
 695 
 696 static void s3c2440_nand_write_buf(struct nand_chip *this, const u_char *buf,
 697                                    int len)
 698 {
 699         struct mtd_info *mtd = nand_to_mtd(this);
 700         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 701 
 702         writesl(info->regs + S3C2440_NFDATA, buf, len >> 2);
 703 
 704         /* cleanup any fractional write */
 705         if (len & 3) {
 706                 buf += len & ~3;
 707 
 708                 for (; len & 3; len--, buf++)
 709                         writeb(*buf, info->regs + S3C2440_NFDATA);
 710         }
 711 }
 712 
 713 /* cpufreq driver support */
 714 
 715 #ifdef CONFIG_ARM_S3C24XX_CPUFREQ
 716 
 717 static int s3c2410_nand_cpufreq_transition(struct notifier_block *nb,
 718                                           unsigned long val, void *data)
 719 {
 720         struct s3c2410_nand_info *info;
 721         unsigned long newclk;
 722 
 723         info = container_of(nb, struct s3c2410_nand_info, freq_transition);
 724         newclk = clk_get_rate(info->clk);
 725 
 726         if ((val == CPUFREQ_POSTCHANGE && newclk < info->clk_rate) ||
 727             (val == CPUFREQ_PRECHANGE && newclk > info->clk_rate)) {
 728                 s3c2410_nand_setrate(info);
 729         }
 730 
 731         return 0;
 732 }
 733 
 734 static inline int s3c2410_nand_cpufreq_register(struct s3c2410_nand_info *info)
 735 {
 736         info->freq_transition.notifier_call = s3c2410_nand_cpufreq_transition;
 737 
 738         return cpufreq_register_notifier(&info->freq_transition,
 739                                          CPUFREQ_TRANSITION_NOTIFIER);
 740 }
 741 
 742 static inline void
 743 s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *info)
 744 {
 745         cpufreq_unregister_notifier(&info->freq_transition,
 746                                     CPUFREQ_TRANSITION_NOTIFIER);
 747 }
 748 
 749 #else
 750 static inline int s3c2410_nand_cpufreq_register(struct s3c2410_nand_info *info)
 751 {
 752         return 0;
 753 }
 754 
 755 static inline void
 756 s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *info)
 757 {
 758 }
 759 #endif
 760 
 761 /* device management functions */
 762 
 763 static int s3c24xx_nand_remove(struct platform_device *pdev)
 764 {
 765         struct s3c2410_nand_info *info = to_nand_info(pdev);
 766 
 767         if (info == NULL)
 768                 return 0;
 769 
 770         s3c2410_nand_cpufreq_deregister(info);
 771 
 772         /* Release all our mtds  and their partitions, then go through
 773          * freeing the resources used
 774          */
 775 
 776         if (info->mtds != NULL) {
 777                 struct s3c2410_nand_mtd *ptr = info->mtds;
 778                 int mtdno;
 779 
 780                 for (mtdno = 0; mtdno < info->mtd_count; mtdno++, ptr++) {
 781                         pr_debug("releasing mtd %d (%p)\n", mtdno, ptr);
 782                         nand_release(&ptr->chip);
 783                 }
 784         }
 785 
 786         /* free the common resources */
 787 
 788         if (!IS_ERR(info->clk))
 789                 s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
 790 
 791         return 0;
 792 }
 793 
 794 static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
 795                                       struct s3c2410_nand_mtd *mtd,
 796                                       struct s3c2410_nand_set *set)
 797 {
 798         if (set) {
 799                 struct mtd_info *mtdinfo = nand_to_mtd(&mtd->chip);
 800 
 801                 mtdinfo->name = set->name;
 802 
 803                 return mtd_device_register(mtdinfo, set->partitions,
 804                                            set->nr_partitions);
 805         }
 806 
 807         return -ENODEV;
 808 }
 809 
 810 static int s3c2410_nand_setup_data_interface(struct nand_chip *chip, int csline,
 811                                         const struct nand_data_interface *conf)
 812 {
 813         struct mtd_info *mtd = nand_to_mtd(chip);
 814         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 815         struct s3c2410_platform_nand *pdata = info->platform;
 816         const struct nand_sdr_timings *timings;
 817         int tacls;
 818 
 819         timings = nand_get_sdr_timings(conf);
 820         if (IS_ERR(timings))
 821                 return -ENOTSUPP;
 822 
 823         tacls = timings->tCLS_min - timings->tWP_min;
 824         if (tacls < 0)
 825                 tacls = 0;
 826 
 827         pdata->tacls  = DIV_ROUND_UP(tacls, 1000);
 828         pdata->twrph0 = DIV_ROUND_UP(timings->tWP_min, 1000);
 829         pdata->twrph1 = DIV_ROUND_UP(timings->tCLH_min, 1000);
 830 
 831         return s3c2410_nand_setrate(info);
 832 }
 833 
 834 /**
 835  * s3c2410_nand_init_chip - initialise a single instance of an chip
 836  * @info: The base NAND controller the chip is on.
 837  * @nmtd: The new controller MTD instance to fill in.
 838  * @set: The information passed from the board specific platform data.
 839  *
 840  * Initialise the given @nmtd from the information in @info and @set. This
 841  * readies the structure for use with the MTD layer functions by ensuring
 842  * all pointers are setup and the necessary control routines selected.
 843  */
 844 static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
 845                                    struct s3c2410_nand_mtd *nmtd,
 846                                    struct s3c2410_nand_set *set)
 847 {
 848         struct device_node *np = info->device->of_node;
 849         struct nand_chip *chip = &nmtd->chip;
 850         void __iomem *regs = info->regs;
 851 
 852         nand_set_flash_node(chip, set->of_node);
 853 
 854         chip->legacy.write_buf    = s3c2410_nand_write_buf;
 855         chip->legacy.read_buf     = s3c2410_nand_read_buf;
 856         chip->legacy.select_chip  = s3c2410_nand_select_chip;
 857         chip->legacy.chip_delay   = 50;
 858         nand_set_controller_data(chip, nmtd);
 859         chip->options      = set->options;
 860         chip->controller   = &info->controller;
 861 
 862         /*
 863          * let's keep behavior unchanged for legacy boards booting via pdata and
 864          * auto-detect timings only when booting with a device tree.
 865          */
 866         if (!np)
 867                 chip->options |= NAND_KEEP_TIMINGS;
 868 
 869         switch (info->cpu_type) {
 870         case TYPE_S3C2410:
 871                 chip->legacy.IO_ADDR_W = regs + S3C2410_NFDATA;
 872                 info->sel_reg   = regs + S3C2410_NFCONF;
 873                 info->sel_bit   = S3C2410_NFCONF_nFCE;
 874                 chip->legacy.cmd_ctrl  = s3c2410_nand_hwcontrol;
 875                 chip->legacy.dev_ready = s3c2410_nand_devready;
 876                 break;
 877 
 878         case TYPE_S3C2440:
 879                 chip->legacy.IO_ADDR_W = regs + S3C2440_NFDATA;
 880                 info->sel_reg   = regs + S3C2440_NFCONT;
 881                 info->sel_bit   = S3C2440_NFCONT_nFCE;
 882                 chip->legacy.cmd_ctrl  = s3c2440_nand_hwcontrol;
 883                 chip->legacy.dev_ready = s3c2440_nand_devready;
 884                 chip->legacy.read_buf  = s3c2440_nand_read_buf;
 885                 chip->legacy.write_buf  = s3c2440_nand_write_buf;
 886                 break;
 887 
 888         case TYPE_S3C2412:
 889                 chip->legacy.IO_ADDR_W = regs + S3C2440_NFDATA;
 890                 info->sel_reg   = regs + S3C2440_NFCONT;
 891                 info->sel_bit   = S3C2412_NFCONT_nFCE0;
 892                 chip->legacy.cmd_ctrl  = s3c2440_nand_hwcontrol;
 893                 chip->legacy.dev_ready = s3c2412_nand_devready;
 894 
 895                 if (readl(regs + S3C2410_NFCONF) & S3C2412_NFCONF_NANDBOOT)
 896                         dev_info(info->device, "System booted from NAND\n");
 897 
 898                 break;
 899         }
 900 
 901         chip->legacy.IO_ADDR_R = chip->legacy.IO_ADDR_W;
 902 
 903         nmtd->info         = info;
 904         nmtd->set          = set;
 905 
 906         chip->ecc.mode = info->platform->ecc_mode;
 907 
 908         /*
 909          * If you use u-boot BBT creation code, specifying this flag will
 910          * let the kernel fish out the BBT from the NAND.
 911          */
 912         if (set->flash_bbt)
 913                 chip->bbt_options |= NAND_BBT_USE_FLASH;
 914 }
 915 
 916 /**
 917  * s3c2410_nand_attach_chip - Init the ECC engine after NAND scan
 918  * @chip: The NAND chip
 919  *
 920  * This hook is called by the core after the identification of the NAND chip,
 921  * once the relevant per-chip information is up to date.. This call ensure that
 922  * we update the internal state accordingly.
 923  *
 924  * The internal state is currently limited to the ECC state information.
 925 */
 926 static int s3c2410_nand_attach_chip(struct nand_chip *chip)
 927 {
 928         struct mtd_info *mtd = nand_to_mtd(chip);
 929         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 930 
 931         switch (chip->ecc.mode) {
 932 
 933         case NAND_ECC_NONE:
 934                 dev_info(info->device, "ECC disabled\n");
 935                 break;
 936 
 937         case NAND_ECC_SOFT:
 938                 /*
 939                  * This driver expects Hamming based ECC when ecc_mode is set
 940                  * to NAND_ECC_SOFT. Force ecc.algo to NAND_ECC_HAMMING to
 941                  * avoid adding an extra ecc_algo field to
 942                  * s3c2410_platform_nand.
 943                  */
 944                 chip->ecc.algo = NAND_ECC_HAMMING;
 945                 dev_info(info->device, "soft ECC\n");
 946                 break;
 947 
 948         case NAND_ECC_HW:
 949                 chip->ecc.calculate = s3c2410_nand_calculate_ecc;
 950                 chip->ecc.correct   = s3c2410_nand_correct_data;
 951                 chip->ecc.strength  = 1;
 952 
 953                 switch (info->cpu_type) {
 954                 case TYPE_S3C2410:
 955                         chip->ecc.hwctl     = s3c2410_nand_enable_hwecc;
 956                         chip->ecc.calculate = s3c2410_nand_calculate_ecc;
 957                         break;
 958 
 959                 case TYPE_S3C2412:
 960                         chip->ecc.hwctl     = s3c2412_nand_enable_hwecc;
 961                         chip->ecc.calculate = s3c2412_nand_calculate_ecc;
 962                         break;
 963 
 964                 case TYPE_S3C2440:
 965                         chip->ecc.hwctl     = s3c2440_nand_enable_hwecc;
 966                         chip->ecc.calculate = s3c2440_nand_calculate_ecc;
 967                         break;
 968                 }
 969 
 970                 dev_dbg(info->device, "chip %p => page shift %d\n",
 971                         chip, chip->page_shift);
 972 
 973                 /* change the behaviour depending on whether we are using
 974                  * the large or small page nand device */
 975                 if (chip->page_shift > 10) {
 976                         chip->ecc.size      = 256;
 977                         chip->ecc.bytes     = 3;
 978                 } else {
 979                         chip->ecc.size      = 512;
 980                         chip->ecc.bytes     = 3;
 981                         mtd_set_ooblayout(nand_to_mtd(chip),
 982                                           &s3c2410_ooblayout_ops);
 983                 }
 984 
 985                 dev_info(info->device, "hardware ECC\n");
 986                 break;
 987 
 988         default:
 989                 dev_err(info->device, "invalid ECC mode!\n");
 990                 return -EINVAL;
 991         }
 992 
 993         if (chip->bbt_options & NAND_BBT_USE_FLASH)
 994                 chip->options |= NAND_SKIP_BBTSCAN;
 995 
 996         return 0;
 997 }
 998 
 999 static const struct nand_controller_ops s3c24xx_nand_controller_ops = {
1000         .attach_chip = s3c2410_nand_attach_chip,
1001         .setup_data_interface = s3c2410_nand_setup_data_interface,
1002 };
1003 
1004 static const struct of_device_id s3c24xx_nand_dt_ids[] = {
1005         {
1006                 .compatible = "samsung,s3c2410-nand",
1007                 .data = &s3c2410_nand_devtype_data,
1008         }, {
1009                 /* also compatible with s3c6400 */
1010                 .compatible = "samsung,s3c2412-nand",
1011                 .data = &s3c2412_nand_devtype_data,
1012         }, {
1013                 .compatible = "samsung,s3c2440-nand",
1014                 .data = &s3c2440_nand_devtype_data,
1015         },
1016         { /* sentinel */ }
1017 };
1018 MODULE_DEVICE_TABLE(of, s3c24xx_nand_dt_ids);
1019 
1020 static int s3c24xx_nand_probe_dt(struct platform_device *pdev)
1021 {
1022         const struct s3c24XX_nand_devtype_data *devtype_data;
1023         struct s3c2410_platform_nand *pdata;
1024         struct s3c2410_nand_info *info = platform_get_drvdata(pdev);
1025         struct device_node *np = pdev->dev.of_node, *child;
1026         struct s3c2410_nand_set *sets;
1027 
1028         devtype_data = of_device_get_match_data(&pdev->dev);
1029         if (!devtype_data)
1030                 return -ENODEV;
1031 
1032         info->cpu_type = devtype_data->type;
1033 
1034         pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
1035         if (!pdata)
1036                 return -ENOMEM;
1037 
1038         pdev->dev.platform_data = pdata;
1039 
1040         pdata->nr_sets = of_get_child_count(np);
1041         if (!pdata->nr_sets)
1042                 return 0;
1043 
1044         sets = devm_kcalloc(&pdev->dev, pdata->nr_sets, sizeof(*sets),
1045                             GFP_KERNEL);
1046         if (!sets)
1047                 return -ENOMEM;
1048 
1049         pdata->sets = sets;
1050 
1051         for_each_available_child_of_node(np, child) {
1052                 sets->name = (char *)child->name;
1053                 sets->of_node = child;
1054                 sets->nr_chips = 1;
1055 
1056                 of_node_get(child);
1057 
1058                 sets++;
1059         }
1060 
1061         return 0;
1062 }
1063 
1064 static int s3c24xx_nand_probe_pdata(struct platform_device *pdev)
1065 {
1066         struct s3c2410_nand_info *info = platform_get_drvdata(pdev);
1067 
1068         info->cpu_type = platform_get_device_id(pdev)->driver_data;
1069 
1070         return 0;
1071 }
1072 
1073 /* s3c24xx_nand_probe
1074  *
1075  * called by device layer when it finds a device matching
1076  * one our driver can handled. This code checks to see if
1077  * it can allocate all necessary resources then calls the
1078  * nand layer to look for devices
1079 */
1080 static int s3c24xx_nand_probe(struct platform_device *pdev)
1081 {
1082         struct s3c2410_platform_nand *plat;
1083         struct s3c2410_nand_info *info;
1084         struct s3c2410_nand_mtd *nmtd;
1085         struct s3c2410_nand_set *sets;
1086         struct resource *res;
1087         int err = 0;
1088         int size;
1089         int nr_sets;
1090         int setno;
1091 
1092         info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
1093         if (info == NULL) {
1094                 err = -ENOMEM;
1095                 goto exit_error;
1096         }
1097 
1098         platform_set_drvdata(pdev, info);
1099 
1100         nand_controller_init(&info->controller);
1101         info->controller.ops = &s3c24xx_nand_controller_ops;
1102 
1103         /* get the clock source and enable it */
1104 
1105         info->clk = devm_clk_get(&pdev->dev, "nand");
1106         if (IS_ERR(info->clk)) {
1107                 dev_err(&pdev->dev, "failed to get clock\n");
1108                 err = -ENOENT;
1109                 goto exit_error;
1110         }
1111 
1112         s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
1113 
1114         if (pdev->dev.of_node)
1115                 err = s3c24xx_nand_probe_dt(pdev);
1116         else
1117                 err = s3c24xx_nand_probe_pdata(pdev);
1118 
1119         if (err)
1120                 goto exit_error;
1121 
1122         plat = to_nand_plat(pdev);
1123 
1124         /* allocate and map the resource */
1125 
1126         /* currently we assume we have the one resource */
1127         res = pdev->resource;
1128         size = resource_size(res);
1129 
1130         info->device    = &pdev->dev;
1131         info->platform  = plat;
1132 
1133         info->regs = devm_ioremap_resource(&pdev->dev, res);
1134         if (IS_ERR(info->regs)) {
1135                 err = PTR_ERR(info->regs);
1136                 goto exit_error;
1137         }
1138 
1139         dev_dbg(&pdev->dev, "mapped registers at %p\n", info->regs);
1140 
1141         if (!plat->sets || plat->nr_sets < 1) {
1142                 err = -EINVAL;
1143                 goto exit_error;
1144         }
1145 
1146         sets = plat->sets;
1147         nr_sets = plat->nr_sets;
1148 
1149         info->mtd_count = nr_sets;
1150 
1151         /* allocate our information */
1152 
1153         size = nr_sets * sizeof(*info->mtds);
1154         info->mtds = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
1155         if (info->mtds == NULL) {
1156                 err = -ENOMEM;
1157                 goto exit_error;
1158         }
1159 
1160         /* initialise all possible chips */
1161 
1162         nmtd = info->mtds;
1163 
1164         for (setno = 0; setno < nr_sets; setno++, nmtd++, sets++) {
1165                 struct mtd_info *mtd = nand_to_mtd(&nmtd->chip);
1166 
1167                 pr_debug("initialising set %d (%p, info %p)\n",
1168                          setno, nmtd, info);
1169 
1170                 mtd->dev.parent = &pdev->dev;
1171                 s3c2410_nand_init_chip(info, nmtd, sets);
1172 
1173                 err = nand_scan(&nmtd->chip, sets ? sets->nr_chips : 1);
1174                 if (err)
1175                         goto exit_error;
1176 
1177                 s3c2410_nand_add_partition(info, nmtd, sets);
1178         }
1179 
1180         /* initialise the hardware */
1181         err = s3c2410_nand_inithw(info);
1182         if (err != 0)
1183                 goto exit_error;
1184 
1185         err = s3c2410_nand_cpufreq_register(info);
1186         if (err < 0) {
1187                 dev_err(&pdev->dev, "failed to init cpufreq support\n");
1188                 goto exit_error;
1189         }
1190 
1191         if (allow_clk_suspend(info)) {
1192                 dev_info(&pdev->dev, "clock idle support enabled\n");
1193                 s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
1194         }
1195 
1196         return 0;
1197 
1198  exit_error:
1199         s3c24xx_nand_remove(pdev);
1200 
1201         if (err == 0)
1202                 err = -EINVAL;
1203         return err;
1204 }
1205 
1206 /* PM Support */
1207 #ifdef CONFIG_PM
1208 
1209 static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
1210 {
1211         struct s3c2410_nand_info *info = platform_get_drvdata(dev);
1212 
1213         if (info) {
1214                 info->save_sel = readl(info->sel_reg);
1215 
1216                 /* For the moment, we must ensure nFCE is high during
1217                  * the time we are suspended. This really should be
1218                  * handled by suspending the MTDs we are using, but
1219                  * that is currently not the case. */
1220 
1221                 writel(info->save_sel | info->sel_bit, info->sel_reg);
1222 
1223                 s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
1224         }
1225 
1226         return 0;
1227 }
1228 
1229 static int s3c24xx_nand_resume(struct platform_device *dev)
1230 {
1231         struct s3c2410_nand_info *info = platform_get_drvdata(dev);
1232         unsigned long sel;
1233 
1234         if (info) {
1235                 s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
1236                 s3c2410_nand_inithw(info);
1237 
1238                 /* Restore the state of the nFCE line. */
1239 
1240                 sel = readl(info->sel_reg);
1241                 sel &= ~info->sel_bit;
1242                 sel |= info->save_sel & info->sel_bit;
1243                 writel(sel, info->sel_reg);
1244 
1245                 s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
1246         }
1247 
1248         return 0;
1249 }
1250 
1251 #else
1252 #define s3c24xx_nand_suspend NULL
1253 #define s3c24xx_nand_resume NULL
1254 #endif
1255 
1256 /* driver device registration */
1257 
1258 static const struct platform_device_id s3c24xx_driver_ids[] = {
1259         {
1260                 .name           = "s3c2410-nand",
1261                 .driver_data    = TYPE_S3C2410,
1262         }, {
1263                 .name           = "s3c2440-nand",
1264                 .driver_data    = TYPE_S3C2440,
1265         }, {
1266                 .name           = "s3c2412-nand",
1267                 .driver_data    = TYPE_S3C2412,
1268         }, {
1269                 .name           = "s3c6400-nand",
1270                 .driver_data    = TYPE_S3C2412, /* compatible with 2412 */
1271         },
1272         { }
1273 };
1274 
1275 MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
1276 
1277 static struct platform_driver s3c24xx_nand_driver = {
1278         .probe          = s3c24xx_nand_probe,
1279         .remove         = s3c24xx_nand_remove,
1280         .suspend        = s3c24xx_nand_suspend,
1281         .resume         = s3c24xx_nand_resume,
1282         .id_table       = s3c24xx_driver_ids,
1283         .driver         = {
1284                 .name   = "s3c24xx-nand",
1285                 .of_match_table = s3c24xx_nand_dt_ids,
1286         },
1287 };
1288 
1289 module_platform_driver(s3c24xx_nand_driver);
1290 
1291 MODULE_LICENSE("GPL");
1292 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
1293 MODULE_DESCRIPTION("S3C24XX MTD NAND driver");

/* [<][>][^][v][top][bottom][index][help] */