aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2009-06-08 07:21:27 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-06-08 07:21:27 -0400
commite635a01ea0a16cf7cd31ecd2305870385dca9be6 (patch)
treec7153e7dee5caf6ac90d85694ff27e4d0b606290 /drivers/mtd
parent143070e74630b9557e1bb64d899ff2cc5a1dcb48 (diff)
parent947391cfbaa3b08558844c0b187bcd0223c3f660 (diff)
Merge branch 'next-mtd' of git://aeryn.fluff.org.uk/bjdooks/linux
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c2
-rw-r--r--drivers/mtd/mtdsuper.c3
-rw-r--r--drivers/mtd/nand/mxc_nand.c40
-rw-r--r--drivers/mtd/nand/s3c2410.c259
4 files changed, 201 insertions, 103 deletions
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 62dee54af0a5..43976aa4dbb1 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -178,7 +178,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
178 /* Calculate flash page address; use block erase (for speed) if 178 /* Calculate flash page address; use block erase (for speed) if
179 * we're at a block boundary and need to erase the whole block. 179 * we're at a block boundary and need to erase the whole block.
180 */ 180 */
181 pageaddr = div_u64(instr->len, priv->page_size); 181 pageaddr = div_u64(instr->addr, priv->page_size);
182 do_block = (pageaddr & 0x7) == 0 && instr->len >= blocksize; 182 do_block = (pageaddr & 0x7) == 0 && instr->len >= blocksize;
183 pageaddr = pageaddr << priv->page_offset; 183 pageaddr = pageaddr << priv->page_offset;
184 184
diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c
index 92285d0089c2..af8b42e0a55b 100644
--- a/drivers/mtd/mtdsuper.c
+++ b/drivers/mtd/mtdsuper.c
@@ -74,8 +74,7 @@ static int get_sb_mtd_aux(struct file_system_type *fs_type, int flags,
74 74
75 ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0); 75 ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
76 if (ret < 0) { 76 if (ret < 0) {
77 up_write(&sb->s_umount); 77 deactivate_locked_super(sb);
78 deactivate_super(sb);
79 return ret; 78 return ret;
80 } 79 }
81 80
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index da41ea82941a..76beea40d2cf 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -842,6 +842,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
842 break; 842 break;
843 843
844 case NAND_CMD_READID: 844 case NAND_CMD_READID:
845 host->col_addr = 0;
845 send_read_id(host); 846 send_read_id(host);
846 break; 847 break;
847 848
@@ -878,6 +879,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
878 mtd->priv = this; 879 mtd->priv = this;
879 mtd->owner = THIS_MODULE; 880 mtd->owner = THIS_MODULE;
880 mtd->dev.parent = &pdev->dev; 881 mtd->dev.parent = &pdev->dev;
882 mtd->name = "mxc_nand";
881 883
882 /* 50 us command delay time */ 884 /* 50 us command delay time */
883 this->chip_delay = 5; 885 this->chip_delay = 5;
@@ -893,8 +895,10 @@ static int __init mxcnd_probe(struct platform_device *pdev)
893 this->verify_buf = mxc_nand_verify_buf; 895 this->verify_buf = mxc_nand_verify_buf;
894 896
895 host->clk = clk_get(&pdev->dev, "nfc"); 897 host->clk = clk_get(&pdev->dev, "nfc");
896 if (IS_ERR(host->clk)) 898 if (IS_ERR(host->clk)) {
899 err = PTR_ERR(host->clk);
897 goto eclk; 900 goto eclk;
901 }
898 902
899 clk_enable(host->clk); 903 clk_enable(host->clk);
900 host->clk_act = 1; 904 host->clk_act = 1;
@@ -907,7 +911,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
907 911
908 host->regs = ioremap(res->start, res->end - res->start + 1); 912 host->regs = ioremap(res->start, res->end - res->start + 1);
909 if (!host->regs) { 913 if (!host->regs) {
910 err = -EIO; 914 err = -ENOMEM;
911 goto eres; 915 goto eres;
912 } 916 }
913 917
@@ -1053,25 +1057,35 @@ static int __devexit mxcnd_remove(struct platform_device *pdev)
1053#ifdef CONFIG_PM 1057#ifdef CONFIG_PM
1054static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state) 1058static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state)
1055{ 1059{
1056 struct mtd_info *info = platform_get_drvdata(pdev); 1060 struct mtd_info *mtd = platform_get_drvdata(pdev);
1061 struct nand_chip *nand_chip = mtd->priv;
1062 struct mxc_nand_host *host = nand_chip->priv;
1057 int ret = 0; 1063 int ret = 0;
1058 1064
1059 DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND suspend\n"); 1065 DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND suspend\n");
1060 1066 if (mtd) {
1061 /* Disable the NFC clock */ 1067 ret = mtd->suspend(mtd);
1062 clk_disable(nfc_clk); /* FIXME */ 1068 /* Disable the NFC clock */
1069 clk_disable(host->clk);
1070 }
1063 1071
1064 return ret; 1072 return ret;
1065} 1073}
1066 1074
1067static int mxcnd_resume(struct platform_device *pdev) 1075static int mxcnd_resume(struct platform_device *pdev)
1068{ 1076{
1069 struct mtd_info *info = platform_get_drvdata(pdev); 1077 struct mtd_info *mtd = platform_get_drvdata(pdev);
1078 struct nand_chip *nand_chip = mtd->priv;
1079 struct mxc_nand_host *host = nand_chip->priv;
1070 int ret = 0; 1080 int ret = 0;
1071 1081
1072 DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n"); 1082 DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n");
1073 /* Enable the NFC clock */ 1083
1074 clk_enable(nfc_clk); /* FIXME */ 1084 if (mtd) {
1085 /* Enable the NFC clock */
1086 clk_enable(host->clk);
1087 mtd->resume(mtd);
1088 }
1075 1089
1076 return ret; 1090 return ret;
1077} 1091}
@@ -1092,13 +1106,7 @@ static struct platform_driver mxcnd_driver = {
1092 1106
1093static int __init mxc_nd_init(void) 1107static int __init mxc_nd_init(void)
1094{ 1108{
1095 /* Register the device driver structure. */ 1109 return platform_driver_probe(&mxcnd_driver, mxcnd_probe);
1096 pr_info("MXC MTD nand Driver\n");
1097 if (platform_driver_probe(&mxcnd_driver, mxcnd_probe) != 0) {
1098 printk(KERN_ERR "Driver register failed for mxcnd_driver\n");
1099 return -ENODEV;
1100 }
1101 return 0;
1102} 1110}
1103 1111
1104static void __exit mxc_nd_cleanup(void) 1112static void __exit mxc_nd_cleanup(void)
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 776756e4ebe5..01a105eda3f4 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -74,6 +74,14 @@ static struct nand_ecclayout nand_hw_eccoob = {
74 74
75struct s3c2410_nand_info; 75struct s3c2410_nand_info;
76 76
77/**
78 * struct s3c2410_nand_mtd - driver MTD structure
79 * @mtd: The MTD instance to pass to the MTD layer.
80 * @chip: The NAND chip information.
81 * @set: The platform information supplied for this set of NAND chips.
82 * @info: Link back to the hardware information.
83 * @scan_res: The result from calling nand_scan_ident().
84*/
77struct s3c2410_nand_mtd { 85struct s3c2410_nand_mtd {
78 struct mtd_info mtd; 86 struct mtd_info mtd;
79 struct nand_chip chip; 87 struct nand_chip chip;
@@ -90,6 +98,21 @@ enum s3c_cpu_type {
90 98
91/* overview of the s3c2410 nand state */ 99/* overview of the s3c2410 nand state */
92 100
101/**
102 * struct s3c2410_nand_info - NAND controller state.
103 * @mtds: An array of MTD instances on this controoler.
104 * @platform: The platform data for this board.
105 * @device: The platform device we bound to.
106 * @area: The IO area resource that came from request_mem_region().
107 * @clk: The clock resource for this controller.
108 * @regs: The area mapped for the hardware registers described by @area.
109 * @sel_reg: Pointer to the register controlling the NAND selection.
110 * @sel_bit: The bit in @sel_reg to select the NAND chip.
111 * @mtd_count: The number of MTDs created from this controller.
112 * @save_sel: The contents of @sel_reg to be saved over suspend.
113 * @clk_rate: The clock rate from @clk.
114 * @cpu_type: The exact type of this controller.
115 */
93struct s3c2410_nand_info { 116struct s3c2410_nand_info {
94 /* mtd info */ 117 /* mtd info */
95 struct nand_hw_control controller; 118 struct nand_hw_control controller;
@@ -145,12 +168,19 @@ static inline int allow_clk_stop(struct s3c2410_nand_info *info)
145 168
146#define NS_IN_KHZ 1000000 169#define NS_IN_KHZ 1000000
147 170
171/**
172 * s3c_nand_calc_rate - calculate timing data.
173 * @wanted: The cycle time in nanoseconds.
174 * @clk: The clock rate in kHz.
175 * @max: The maximum divider value.
176 *
177 * Calculate the timing value from the given parameters.
178 */
148static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max) 179static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)
149{ 180{
150 int result; 181 int result;
151 182
152 result = (wanted * clk) / NS_IN_KHZ; 183 result = DIV_ROUND_UP((wanted * clk), NS_IN_KHZ);
153 result++;
154 184
155 pr_debug("result %d from %ld, %d\n", result, clk, wanted); 185 pr_debug("result %d from %ld, %d\n", result, clk, wanted);
156 186
@@ -169,13 +199,21 @@ static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)
169 199
170/* controller setup */ 200/* controller setup */
171 201
202/**
203 * s3c2410_nand_setrate - setup controller timing information.
204 * @info: The controller instance.
205 *
206 * Given the information supplied by the platform, calculate and set
207 * the necessary timing registers in the hardware to generate the
208 * necessary timing cycles to the hardware.
209 */
172static int s3c2410_nand_setrate(struct s3c2410_nand_info *info) 210static int s3c2410_nand_setrate(struct s3c2410_nand_info *info)
173{ 211{
174 struct s3c2410_platform_nand *plat = info->platform; 212 struct s3c2410_platform_nand *plat = info->platform;
175 int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4; 213 int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4;
176 int tacls, twrph0, twrph1; 214 int tacls, twrph0, twrph1;
177 unsigned long clkrate = clk_get_rate(info->clk); 215 unsigned long clkrate = clk_get_rate(info->clk);
178 unsigned long set, cfg, mask; 216 unsigned long uninitialized_var(set), cfg, uninitialized_var(mask);
179 unsigned long flags; 217 unsigned long flags;
180 218
181 /* calculate the timing information for the controller */ 219 /* calculate the timing information for the controller */
@@ -225,14 +263,9 @@ static int s3c2410_nand_setrate(struct s3c2410_nand_info *info)
225 break; 263 break;
226 264
227 default: 265 default:
228 /* keep compiler happy */
229 mask = 0;
230 set = 0;
231 BUG(); 266 BUG();
232 } 267 }
233 268
234 dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
235
236 local_irq_save(flags); 269 local_irq_save(flags);
237 270
238 cfg = readl(info->regs + S3C2410_NFCONF); 271 cfg = readl(info->regs + S3C2410_NFCONF);
@@ -242,9 +275,18 @@ static int s3c2410_nand_setrate(struct s3c2410_nand_info *info)
242 275
243 local_irq_restore(flags); 276 local_irq_restore(flags);
244 277
278 dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
279
245 return 0; 280 return 0;
246} 281}
247 282
283/**
284 * s3c2410_nand_inithw - basic hardware initialisation
285 * @info: The hardware state.
286 *
287 * Do the basic initialisation of the hardware, using s3c2410_nand_setrate()
288 * to setup the hardware access speeds and set the controller to be enabled.
289*/
248static int s3c2410_nand_inithw(struct s3c2410_nand_info *info) 290static int s3c2410_nand_inithw(struct s3c2410_nand_info *info)
249{ 291{
250 int ret; 292 int ret;
@@ -268,8 +310,19 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info)
268 return 0; 310 return 0;
269} 311}
270 312
271/* select chip */ 313/**
272 314 * s3c2410_nand_select_chip - select the given nand chip
315 * @mtd: The MTD instance for this chip.
316 * @chip: The chip number.
317 *
318 * This is called by the MTD layer to either select a given chip for the
319 * @mtd instance, or to indicate that the access has finished and the
320 * chip can be de-selected.
321 *
322 * The routine ensures that the nFCE line is correctly setup, and any
323 * platform specific selection code is called to route nFCE to the specific
324 * chip.
325 */
273static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) 326static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
274{ 327{
275 struct s3c2410_nand_info *info; 328 struct s3c2410_nand_info *info;
@@ -530,7 +583,16 @@ static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
530static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) 583static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
531{ 584{
532 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); 585 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
533 readsl(info->regs + S3C2440_NFDATA, buf, len / 4); 586
587 readsl(info->regs + S3C2440_NFDATA, buf, len >> 2);
588
589 /* cleanup if we've got less than a word to do */
590 if (len & 3) {
591 buf += len & ~3;
592
593 for (; len & 3; len--)
594 *buf++ = readb(info->regs + S3C2440_NFDATA);
595 }
534} 596}
535 597
536static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) 598static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
@@ -542,7 +604,16 @@ static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int
542static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) 604static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
543{ 605{
544 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); 606 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
545 writesl(info->regs + S3C2440_NFDATA, buf, len / 4); 607
608 writesl(info->regs + S3C2440_NFDATA, buf, len >> 2);
609
610 /* cleanup any fractional write */
611 if (len & 3) {
612 buf += len & ~3;
613
614 for (; len & 3; len--, buf++)
615 writeb(*buf, info->regs + S3C2440_NFDATA);
616 }
546} 617}
547 618
548/* cpufreq driver support */ 619/* cpufreq driver support */
@@ -593,7 +664,7 @@ static inline void s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *inf
593 664
594/* device management functions */ 665/* device management functions */
595 666
596static int s3c2410_nand_remove(struct platform_device *pdev) 667static int s3c24xx_nand_remove(struct platform_device *pdev)
597{ 668{
598 struct s3c2410_nand_info *info = to_nand_info(pdev); 669 struct s3c2410_nand_info *info = to_nand_info(pdev);
599 670
@@ -645,17 +716,31 @@ static int s3c2410_nand_remove(struct platform_device *pdev)
645} 716}
646 717
647#ifdef CONFIG_MTD_PARTITIONS 718#ifdef CONFIG_MTD_PARTITIONS
719const char *part_probes[] = { "cmdlinepart", NULL };
648static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, 720static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
649 struct s3c2410_nand_mtd *mtd, 721 struct s3c2410_nand_mtd *mtd,
650 struct s3c2410_nand_set *set) 722 struct s3c2410_nand_set *set)
651{ 723{
724 struct mtd_partition *part_info;
725 int nr_part = 0;
726
652 if (set == NULL) 727 if (set == NULL)
653 return add_mtd_device(&mtd->mtd); 728 return add_mtd_device(&mtd->mtd);
654 729
655 if (set->nr_partitions > 0 && set->partitions != NULL) { 730 if (set->nr_partitions == 0) {
656 return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions); 731 mtd->mtd.name = set->name;
732 nr_part = parse_mtd_partitions(&mtd->mtd, part_probes,
733 &part_info, 0);
734 } else {
735 if (set->nr_partitions > 0 && set->partitions != NULL) {
736 nr_part = set->nr_partitions;
737 part_info = set->partitions;
738 }
657 } 739 }
658 740
741 if (nr_part > 0 && part_info)
742 return add_mtd_partitions(&mtd->mtd, part_info, nr_part);
743
659 return add_mtd_device(&mtd->mtd); 744 return add_mtd_device(&mtd->mtd);
660} 745}
661#else 746#else
@@ -667,11 +752,16 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
667} 752}
668#endif 753#endif
669 754
670/* s3c2410_nand_init_chip 755/**
756 * s3c2410_nand_init_chip - initialise a single instance of an chip
757 * @info: The base NAND controller the chip is on.
758 * @nmtd: The new controller MTD instance to fill in.
759 * @set: The information passed from the board specific platform data.
671 * 760 *
672 * init a single instance of an chip 761 * Initialise the given @nmtd from the information in @info and @set. This
673*/ 762 * readies the structure for use with the MTD layer functions by ensuring
674 763 * all pointers are setup and the necessary control routines selected.
764 */
675static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, 765static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
676 struct s3c2410_nand_mtd *nmtd, 766 struct s3c2410_nand_mtd *nmtd,
677 struct s3c2410_nand_set *set) 767 struct s3c2410_nand_set *set)
@@ -757,14 +847,40 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
757 847
758 if (set->disable_ecc) 848 if (set->disable_ecc)
759 chip->ecc.mode = NAND_ECC_NONE; 849 chip->ecc.mode = NAND_ECC_NONE;
850
851 switch (chip->ecc.mode) {
852 case NAND_ECC_NONE:
853 dev_info(info->device, "NAND ECC disabled\n");
854 break;
855 case NAND_ECC_SOFT:
856 dev_info(info->device, "NAND soft ECC\n");
857 break;
858 case NAND_ECC_HW:
859 dev_info(info->device, "NAND hardware ECC\n");
860 break;
861 default:
862 dev_info(info->device, "NAND ECC UNKNOWN\n");
863 break;
864 }
865
866 /* If you use u-boot BBT creation code, specifying this flag will
867 * let the kernel fish out the BBT from the NAND, and also skip the
868 * full NAND scan that can take 1/2s or so. Little things... */
869 if (set->flash_bbt)
870 chip->options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN;
760} 871}
761 872
762/* s3c2410_nand_update_chip 873/**
874 * s3c2410_nand_update_chip - post probe update
875 * @info: The controller instance.
876 * @nmtd: The driver version of the MTD instance.
763 * 877 *
764 * post-probe chip update, to change any items, such as the 878 * This routine is called after the chip probe has succesfully completed
765 * layout for large page nand 879 * and the relevant per-chip information updated. This call ensure that
766 */ 880 * we update the internal state accordingly.
767 881 *
882 * The internal state is currently limited to the ECC state information.
883*/
768static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info, 884static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
769 struct s3c2410_nand_mtd *nmtd) 885 struct s3c2410_nand_mtd *nmtd)
770{ 886{
@@ -773,33 +889,33 @@ static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
773 dev_dbg(info->device, "chip %p => page shift %d\n", 889 dev_dbg(info->device, "chip %p => page shift %d\n",
774 chip, chip->page_shift); 890 chip, chip->page_shift);
775 891
776 if (hardware_ecc) { 892 if (chip->ecc.mode != NAND_ECC_HW)
893 return;
894
777 /* change the behaviour depending on wether we are using 895 /* change the behaviour depending on wether we are using
778 * the large or small page nand device */ 896 * the large or small page nand device */
779 897
780 if (chip->page_shift > 10) { 898 if (chip->page_shift > 10) {
781 chip->ecc.size = 256; 899 chip->ecc.size = 256;
782 chip->ecc.bytes = 3; 900 chip->ecc.bytes = 3;
783 } else { 901 } else {
784 chip->ecc.size = 512; 902 chip->ecc.size = 512;
785 chip->ecc.bytes = 3; 903 chip->ecc.bytes = 3;
786 chip->ecc.layout = &nand_hw_eccoob; 904 chip->ecc.layout = &nand_hw_eccoob;
787 }
788 } 905 }
789} 906}
790 907
791/* s3c2410_nand_probe 908/* s3c24xx_nand_probe
792 * 909 *
793 * called by device layer when it finds a device matching 910 * called by device layer when it finds a device matching
794 * one our driver can handled. This code checks to see if 911 * one our driver can handled. This code checks to see if
795 * it can allocate all necessary resources then calls the 912 * it can allocate all necessary resources then calls the
796 * nand layer to look for devices 913 * nand layer to look for devices
797*/ 914*/
798 915static int s3c24xx_nand_probe(struct platform_device *pdev)
799static int s3c24xx_nand_probe(struct platform_device *pdev,
800 enum s3c_cpu_type cpu_type)
801{ 916{
802 struct s3c2410_platform_nand *plat = to_nand_plat(pdev); 917 struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
918 enum s3c_cpu_type cpu_type;
803 struct s3c2410_nand_info *info; 919 struct s3c2410_nand_info *info;
804 struct s3c2410_nand_mtd *nmtd; 920 struct s3c2410_nand_mtd *nmtd;
805 struct s3c2410_nand_set *sets; 921 struct s3c2410_nand_set *sets;
@@ -809,6 +925,8 @@ static int s3c24xx_nand_probe(struct platform_device *pdev,
809 int nr_sets; 925 int nr_sets;
810 int setno; 926 int setno;
811 927
928 cpu_type = platform_get_device_id(pdev)->driver_data;
929
812 pr_debug("s3c2410_nand_probe(%p)\n", pdev); 930 pr_debug("s3c2410_nand_probe(%p)\n", pdev);
813 931
814 info = kmalloc(sizeof(*info), GFP_KERNEL); 932 info = kmalloc(sizeof(*info), GFP_KERNEL);
@@ -922,7 +1040,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev,
922 return 0; 1040 return 0;
923 1041
924 exit_error: 1042 exit_error:
925 s3c2410_nand_remove(pdev); 1043 s3c24xx_nand_remove(pdev);
926 1044
927 if (err == 0) 1045 if (err == 0)
928 err = -EINVAL; 1046 err = -EINVAL;
@@ -983,50 +1101,30 @@ static int s3c24xx_nand_resume(struct platform_device *dev)
983 1101
984/* driver device registration */ 1102/* driver device registration */
985 1103
986static int s3c2410_nand_probe(struct platform_device *dev) 1104static struct platform_device_id s3c24xx_driver_ids[] = {
987{ 1105 {
988 return s3c24xx_nand_probe(dev, TYPE_S3C2410); 1106 .name = "s3c2410-nand",
989} 1107 .driver_data = TYPE_S3C2410,
990 1108 }, {
991static int s3c2440_nand_probe(struct platform_device *dev) 1109 .name = "s3c2440-nand",
992{ 1110 .driver_data = TYPE_S3C2440,
993 return s3c24xx_nand_probe(dev, TYPE_S3C2440); 1111 }, {
994} 1112 .name = "s3c2412-nand",
995 1113 .driver_data = TYPE_S3C2412,
996static int s3c2412_nand_probe(struct platform_device *dev)
997{
998 return s3c24xx_nand_probe(dev, TYPE_S3C2412);
999}
1000
1001static struct platform_driver s3c2410_nand_driver = {
1002 .probe = s3c2410_nand_probe,
1003 .remove = s3c2410_nand_remove,
1004 .suspend = s3c24xx_nand_suspend,
1005 .resume = s3c24xx_nand_resume,
1006 .driver = {
1007 .name = "s3c2410-nand",
1008 .owner = THIS_MODULE,
1009 }, 1114 },
1115 { }
1010}; 1116};
1011 1117
1012static struct platform_driver s3c2440_nand_driver = { 1118MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
1013 .probe = s3c2440_nand_probe,
1014 .remove = s3c2410_nand_remove,
1015 .suspend = s3c24xx_nand_suspend,
1016 .resume = s3c24xx_nand_resume,
1017 .driver = {
1018 .name = "s3c2440-nand",
1019 .owner = THIS_MODULE,
1020 },
1021};
1022 1119
1023static struct platform_driver s3c2412_nand_driver = { 1120static struct platform_driver s3c24xx_nand_driver = {
1024 .probe = s3c2412_nand_probe, 1121 .probe = s3c24xx_nand_probe,
1025 .remove = s3c2410_nand_remove, 1122 .remove = s3c24xx_nand_remove,
1026 .suspend = s3c24xx_nand_suspend, 1123 .suspend = s3c24xx_nand_suspend,
1027 .resume = s3c24xx_nand_resume, 1124 .resume = s3c24xx_nand_resume,
1125 .id_table = s3c24xx_driver_ids,
1028 .driver = { 1126 .driver = {
1029 .name = "s3c2412-nand", 1127 .name = "s3c24xx-nand",
1030 .owner = THIS_MODULE, 1128 .owner = THIS_MODULE,
1031 }, 1129 },
1032}; 1130};
@@ -1035,16 +1133,12 @@ static int __init s3c2410_nand_init(void)
1035{ 1133{
1036 printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronics\n"); 1134 printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronics\n");
1037 1135
1038 platform_driver_register(&s3c2412_nand_driver); 1136 return platform_driver_register(&s3c24xx_nand_driver);
1039 platform_driver_register(&s3c2440_nand_driver);
1040 return platform_driver_register(&s3c2410_nand_driver);
1041} 1137}
1042 1138
1043static void __exit s3c2410_nand_exit(void) 1139static void __exit s3c2410_nand_exit(void)
1044{ 1140{
1045 platform_driver_unregister(&s3c2412_nand_driver); 1141 platform_driver_unregister(&s3c24xx_nand_driver);
1046 platform_driver_unregister(&s3c2440_nand_driver);
1047 platform_driver_unregister(&s3c2410_nand_driver);
1048} 1142}
1049 1143
1050module_init(s3c2410_nand_init); 1144module_init(s3c2410_nand_init);
@@ -1053,6 +1147,3 @@ module_exit(s3c2410_nand_exit);
1053MODULE_LICENSE("GPL"); 1147MODULE_LICENSE("GPL");
1054MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 1148MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
1055MODULE_DESCRIPTION("S3C24XX MTD NAND driver"); 1149MODULE_DESCRIPTION("S3C24XX MTD NAND driver");
1056MODULE_ALIAS("platform:s3c2410-nand");
1057MODULE_ALIAS("platform:s3c2412-nand");
1058MODULE_ALIAS("platform:s3c2440-nand");