Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mtd: rawnand: s3c2410: Drop driver (no actual S3C64xx user)

The s3c2410 NAND driver still supports S3C64xx platform, which in
general is supported in the kernel. There are however no references of
"s3c6400-nand" platform device ID or "s3c24xx-nand" driver, thus this
driver cannot be instantiated for S3C64xx platform and is basically
unused.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

authored by

Krzysztof Kozlowski and committed by
Miquel Raynal
c9f62564 6186e80a

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