Эх сурвалжийг харах

ARM: Merge next-s3c24xx-dev-rtp

Merge branch 'next-s3c24xx-dev-rtp' into for-rmk

Conflicts:

	arch/arm/mach-s3c2440/mach-anubis.c
Ben Dooks 15 жил өмнө
parent
commit
f18ea8276b

+ 8 - 0
arch/arm/mach-s3c2410/Kconfig

@@ -81,6 +81,14 @@ config ARCH_H1940
 	help
 	help
 	  Say Y here if you are using the HP IPAQ H1940
 	  Say Y here if you are using the HP IPAQ H1940
 
 
+config H1940BT
+        tristate "Control the state of H1940 bluetooth chip"
+        depends on ARCH_H1940
+        select RFKILL
+        help
+          This is a simple driver that is able to control
+          the state of built in bluetooth chip on h1940.
+
 config PM_H1940
 config PM_H1940
 	bool
 	bool
 	help
 	help

+ 2 - 1
arch/arm/mach-s3c2410/Makefile

@@ -21,7 +21,8 @@ obj-$(CONFIG_S3C2410_PLLTABLE)	+= pll.o
 # Machine support
 # Machine support
 
 
 obj-$(CONFIG_ARCH_SMDK2410)	+= mach-smdk2410.o
 obj-$(CONFIG_ARCH_SMDK2410)	+= mach-smdk2410.o
-obj-$(CONFIG_ARCH_H1940)	+= mach-h1940.o h1940-bluetooth.o
+obj-$(CONFIG_ARCH_H1940)	+= mach-h1940.o
+obj-$(CONFIG_H1940BT)		+= h1940-bluetooth.o
 obj-$(CONFIG_PM_H1940)		+= pm-h1940.o
 obj-$(CONFIG_PM_H1940)		+= pm-h1940.o
 obj-$(CONFIG_MACH_N30)		+= mach-n30.o
 obj-$(CONFIG_MACH_N30)		+= mach-n30.o
 obj-$(CONFIG_ARCH_BAST)		+= mach-bast.o usb-simtec.o
 obj-$(CONFIG_ARCH_BAST)		+= mach-bast.o usb-simtec.o

+ 42 - 46
arch/arm/mach-s3c2410/h1940-bluetooth.c

@@ -17,6 +17,7 @@
 #include <linux/ctype.h>
 #include <linux/ctype.h>
 #include <linux/leds.h>
 #include <linux/leds.h>
 #include <linux/gpio.h>
 #include <linux/gpio.h>
+#include <linux/rfkill.h>
 
 
 #include <mach/regs-gpio.h>
 #include <mach/regs-gpio.h>
 #include <mach/hardware.h>
 #include <mach/hardware.h>
@@ -24,21 +25,10 @@
 
 
 #define DRV_NAME              "h1940-bt"
 #define DRV_NAME              "h1940-bt"
 
 
-#ifdef CONFIG_LEDS_H1940
-DEFINE_LED_TRIGGER(bt_led_trigger);
-#endif
-
-static int state;
-
 /* Bluetooth control */
 /* Bluetooth control */
 static void h1940bt_enable(int on)
 static void h1940bt_enable(int on)
 {
 {
 	if (on) {
 	if (on) {
-#ifdef CONFIG_LEDS_H1940
-		/* flashing Blue */
-		led_trigger_event(bt_led_trigger, LED_HALF);
-#endif
-
 		/* Power on the chip */
 		/* Power on the chip */
 		h1940_latch_control(0, H1940_LATCH_BLUETOOTH_POWER);
 		h1940_latch_control(0, H1940_LATCH_BLUETOOTH_POWER);
 		/* Reset the chip */
 		/* Reset the chip */
@@ -46,48 +36,31 @@ static void h1940bt_enable(int on)
 		s3c2410_gpio_setpin(S3C2410_GPH(1), 1);
 		s3c2410_gpio_setpin(S3C2410_GPH(1), 1);
 		mdelay(10);
 		mdelay(10);
 		s3c2410_gpio_setpin(S3C2410_GPH(1), 0);
 		s3c2410_gpio_setpin(S3C2410_GPH(1), 0);
-
-		state = 1;
 	}
 	}
 	else {
 	else {
-#ifdef CONFIG_LEDS_H1940
-		led_trigger_event(bt_led_trigger, 0);
-#endif
-
 		s3c2410_gpio_setpin(S3C2410_GPH(1), 1);
 		s3c2410_gpio_setpin(S3C2410_GPH(1), 1);
 		mdelay(10);
 		mdelay(10);
 		s3c2410_gpio_setpin(S3C2410_GPH(1), 0);
 		s3c2410_gpio_setpin(S3C2410_GPH(1), 0);
 		mdelay(10);
 		mdelay(10);
 		h1940_latch_control(H1940_LATCH_BLUETOOTH_POWER, 0);
 		h1940_latch_control(H1940_LATCH_BLUETOOTH_POWER, 0);
-
-		state = 0;
 	}
 	}
 }
 }
 
 
-static ssize_t h1940bt_show(struct device *dev, struct device_attribute *attr, char *buf)
+static int h1940bt_set_block(void *data, bool blocked)
 {
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", state);
+	h1940bt_enable(!blocked);
+	return 0;
 }
 }
 
 
-static ssize_t h1940bt_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	int new_state;
-	char *endp;
-
-	new_state = simple_strtoul(buf, &endp, 0);
-	if (*endp && !isspace(*endp))
-		return -EINVAL;
-
-	h1940bt_enable(new_state);
-
-	return count;
-}
-static DEVICE_ATTR(enable, 0644,
-		h1940bt_show,
-		h1940bt_store);
+static const struct rfkill_ops h1940bt_rfkill_ops = {
+	.set_block = h1940bt_set_block,
+};
 
 
 static int __init h1940bt_probe(struct platform_device *pdev)
 static int __init h1940bt_probe(struct platform_device *pdev)
 {
 {
+	struct rfkill *rfk;
+	int ret = 0;
+
 	/* Configures BT serial port GPIOs */
 	/* Configures BT serial port GPIOs */
 	s3c2410_gpio_cfgpin(S3C2410_GPH(0), S3C2410_GPH0_nCTS0);
 	s3c2410_gpio_cfgpin(S3C2410_GPH(0), S3C2410_GPH0_nCTS0);
 	s3c2410_gpio_pullup(S3C2410_GPH(0), 1);
 	s3c2410_gpio_pullup(S3C2410_GPH(0), 1);
@@ -98,21 +71,44 @@ static int __init h1940bt_probe(struct platform_device *pdev)
 	s3c2410_gpio_cfgpin(S3C2410_GPH(3), S3C2410_GPH3_RXD0);
 	s3c2410_gpio_cfgpin(S3C2410_GPH(3), S3C2410_GPH3_RXD0);
 	s3c2410_gpio_pullup(S3C2410_GPH(3), 1);
 	s3c2410_gpio_pullup(S3C2410_GPH(3), 1);
 
 
-#ifdef CONFIG_LEDS_H1940
-	led_trigger_register_simple("h1940-bluetooth", &bt_led_trigger);
-#endif
 
 
-	/* disable BT by default */
-	h1940bt_enable(0);
+	rfk = rfkill_alloc(DRV_NAME, &pdev->dev, RFKILL_TYPE_BLUETOOTH,
+			&h1940bt_rfkill_ops, NULL);
+	if (!rfk) {
+		ret = -ENOMEM;
+		goto err_rfk_alloc;
+	}
+
+	rfkill_set_led_trigger_name(rfk, "h1940-bluetooth");
+
+	ret = rfkill_register(rfk);
+	if (ret)
+		goto err_rfkill;
+
+	platform_set_drvdata(pdev, rfk);
+
+	return 0;
 
 
-	return device_create_file(&pdev->dev, &dev_attr_enable);
+err_rfkill:
+	rfkill_destroy(rfk);
+err_rfk_alloc:
+	return ret;
 }
 }
 
 
 static int h1940bt_remove(struct platform_device *pdev)
 static int h1940bt_remove(struct platform_device *pdev)
 {
 {
-#ifdef CONFIG_LEDS_H1940
-	led_trigger_unregister_simple(bt_led_trigger);
-#endif
+	struct rfkill *rfk = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (rfk) {
+		rfkill_unregister(rfk);
+		rfkill_destroy(rfk);
+	}
+	rfk = NULL;
+
+	h1940bt_enable(0);
+
 	return 0;
 	return 0;
 }
 }
 
 

+ 4 - 4
arch/arm/mach-s3c2410/mach-bast.c

@@ -248,7 +248,7 @@ static int chip0_map[] = { 1 };
 static int chip1_map[] = { 2 };
 static int chip1_map[] = { 2 };
 static int chip2_map[] = { 3 };
 static int chip2_map[] = { 3 };
 
 
-static struct mtd_partition bast_default_nand_part[] = {
+static struct mtd_partition __initdata bast_default_nand_part[] = {
 	[0] = {
 	[0] = {
 		.name	= "Boot Agent",
 		.name	= "Boot Agent",
 		.size	= SZ_16K,
 		.size	= SZ_16K,
@@ -274,7 +274,7 @@ static struct mtd_partition bast_default_nand_part[] = {
  * socket.
  * socket.
 */
 */
 
 
-static struct s3c2410_nand_set bast_nand_sets[] = {
+static struct s3c2410_nand_set __initdata bast_nand_sets[] = {
 	[0] = {
 	[0] = {
 		.name		= "SmartMedia",
 		.name		= "SmartMedia",
 		.nr_chips	= 1,
 		.nr_chips	= 1,
@@ -324,7 +324,7 @@ static void bast_nand_select(struct s3c2410_nand_set *set, int slot)
 	__raw_writeb(tmp, BAST_VA_CTRL2);
 	__raw_writeb(tmp, BAST_VA_CTRL2);
 }
 }
 
 
-static struct s3c2410_platform_nand bast_nand_info = {
+static struct s3c2410_platform_nand __initdata bast_nand_info = {
 	.tacls		= 30,
 	.tacls		= 30,
 	.twrph0		= 60,
 	.twrph0		= 60,
 	.twrph1		= 60,
 	.twrph1		= 60,
@@ -631,7 +631,6 @@ static void __init bast_map_io(void)
 
 
 	s3c24xx_register_clocks(bast_clocks, ARRAY_SIZE(bast_clocks));
 	s3c24xx_register_clocks(bast_clocks, ARRAY_SIZE(bast_clocks));
 
 
-	s3c_device_nand.dev.platform_data = &bast_nand_info;
 	s3c_device_hwmon.dev.platform_data = &bast_hwmon_info;
 	s3c_device_hwmon.dev.platform_data = &bast_hwmon_info;
 
 
 	s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
 	s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
@@ -645,6 +644,7 @@ static void __init bast_init(void)
 	sysdev_register(&bast_pm_sysdev);
 	sysdev_register(&bast_pm_sysdev);
 
 
 	s3c_i2c0_set_platdata(&bast_i2c_info);
 	s3c_i2c0_set_platdata(&bast_i2c_info);
+	s3c_nand_set_platdata(&bast_nand_info);
 	s3c24xx_fb_set_platdata(&bast_fb_info);
 	s3c24xx_fb_set_platdata(&bast_fb_info);
 	platform_add_devices(bast_devices, ARRAY_SIZE(bast_devices));
 	platform_add_devices(bast_devices, ARRAY_SIZE(bast_devices));
 
 

+ 100 - 5
arch/arm/mach-s3c2410/mach-h1940.c

@@ -21,6 +21,11 @@
 #include <linux/serial_core.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/pwm_backlight.h>
+#include <video/platform_lcd.h>
+
+#include <linux/mmc/host.h>
 
 
 #include <asm/mach/arch.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/map.h>
@@ -32,9 +37,12 @@
 
 
 #include <plat/regs-serial.h>
 #include <plat/regs-serial.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-lcd.h>
-#include <mach/regs-gpio.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-clock.h>
 
 
+#include <mach/regs-gpio.h>
+#include <mach/gpio-fns.h>
+#include <mach/gpio-nrs.h>
+
 #include <mach/h1940.h>
 #include <mach/h1940.h>
 #include <mach/h1940-latch.h>
 #include <mach/h1940-latch.h>
 #include <mach/fb.h>
 #include <mach/fb.h>
@@ -46,6 +54,7 @@
 #include <plat/cpu.h>
 #include <plat/cpu.h>
 #include <plat/pll.h>
 #include <plat/pll.h>
 #include <plat/pm.h>
 #include <plat/pm.h>
+#include <plat/mci.h>
 
 
 static struct map_desc h1940_iodesc[] __initdata = {
 static struct map_desc h1940_iodesc[] __initdata = {
 	[0] = {
 	[0] = {
@@ -171,16 +180,90 @@ static struct s3c2410fb_mach_info h1940_fb_info __initdata = {
 	.gpdup_mask=	0xffffffff,
 	.gpdup_mask=	0xffffffff,
 };
 };
 
 
-static struct platform_device s3c_device_leds = {
+static struct platform_device h1940_device_leds = {
 	.name             = "h1940-leds",
 	.name             = "h1940-leds",
 	.id               = -1,
 	.id               = -1,
 };
 };
 
 
-static struct platform_device s3c_device_bluetooth = {
+static struct platform_device h1940_device_bluetooth = {
 	.name             = "h1940-bt",
 	.name             = "h1940-bt",
 	.id               = -1,
 	.id               = -1,
 };
 };
 
 
+static struct s3c24xx_mci_pdata h1940_mmc_cfg = {
+	.gpio_detect   = S3C2410_GPF(5),
+	.gpio_wprotect = S3C2410_GPH(8),
+	.set_power     = NULL,
+	.ocr_avail     = MMC_VDD_32_33,
+};
+
+static int h1940_backlight_init(struct device *dev)
+{
+	gpio_request(S3C2410_GPB(0), "Backlight");
+
+	s3c2410_gpio_setpin(S3C2410_GPB(0), 0);
+	s3c2410_gpio_pullup(S3C2410_GPB(0), 0);
+	s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);
+
+	return 0;
+}
+
+static void h1940_backlight_exit(struct device *dev)
+{
+	s3c2410_gpio_cfgpin(S3C2410_GPB(0), 1/*S3C2410_GPB0_OUTP*/);
+}
+
+static struct platform_pwm_backlight_data backlight_data = {
+	.pwm_id         = 0,
+	.max_brightness = 100,
+	.dft_brightness = 50,
+	/* tcnt = 0x31 */
+	.pwm_period_ns  = 36296,
+	.init           = h1940_backlight_init,
+	.exit           = h1940_backlight_exit,
+};
+
+static struct platform_device h1940_backlight = {
+	.name = "pwm-backlight",
+	.dev  = {
+		.parent = &s3c_device_timer[0].dev,
+		.platform_data = &backlight_data,
+	},
+	.id   = -1,
+};
+
+static void h1940_lcd_power_set(struct plat_lcd_data *pd,
+					unsigned int power)
+{
+	int value;
+
+	if (!power) {
+		/* set to 3ec */
+		s3c2410_gpio_setpin(S3C2410_GPC(0), 0);
+		/* wait for 3ac */
+		do {
+			value = s3c2410_gpio_getpin(S3C2410_GPC(6));
+		} while (value);
+		/* set to 38c */
+		s3c2410_gpio_setpin(S3C2410_GPC(5), 0);
+	} else {
+		/* Set to 3ac */
+		s3c2410_gpio_setpin(S3C2410_GPC(5), 1);
+		/* Set to 3ad */
+		s3c2410_gpio_setpin(S3C2410_GPC(0), 1);
+	}
+}
+
+static struct plat_lcd_data h1940_lcd_power_data = {
+	.set_power      = h1940_lcd_power_set,
+};
+
+static struct platform_device h1940_lcd_powerdev = {
+	.name                   = "platform-lcd",
+	.dev.parent             = &s3c_device_lcd.dev,
+	.dev.platform_data      = &h1940_lcd_power_data,
+};
+
 static struct platform_device *h1940_devices[] __initdata = {
 static struct platform_device *h1940_devices[] __initdata = {
 	&s3c_device_usb,
 	&s3c_device_usb,
 	&s3c_device_lcd,
 	&s3c_device_lcd,
@@ -188,8 +271,13 @@ static struct platform_device *h1940_devices[] __initdata = {
 	&s3c_device_i2c0,
 	&s3c_device_i2c0,
 	&s3c_device_iis,
 	&s3c_device_iis,
 	&s3c_device_usbgadget,
 	&s3c_device_usbgadget,
-	&s3c_device_leds,
-	&s3c_device_bluetooth,
+	&h1940_device_leds,
+	&h1940_device_bluetooth,
+	&s3c_device_sdi,
+	&s3c_device_rtc,
+	&s3c_device_timer[0],
+	&h1940_backlight,
+	&h1940_lcd_powerdev,
 };
 };
 
 
 static void __init h1940_map_io(void)
 static void __init h1940_map_io(void)
@@ -219,6 +307,8 @@ static void __init h1940_init(void)
  	s3c24xx_udc_set_platdata(&h1940_udc_cfg);
  	s3c24xx_udc_set_platdata(&h1940_udc_cfg);
 	s3c_i2c0_set_platdata(NULL);
 	s3c_i2c0_set_platdata(NULL);
 
 
+	s3c_device_sdi.dev.platform_data = &h1940_mmc_cfg;
+
 	/* Turn off suspend on both USB ports, and switch the
 	/* Turn off suspend on both USB ports, and switch the
 	 * selectable USB port to USB device mode. */
 	 * selectable USB port to USB device mode. */
 
 
@@ -231,6 +321,11 @@ static void __init h1940_init(void)
 	      | (0x03 << S3C24XX_PLLCON_SDIVSHIFT);
 	      | (0x03 << S3C24XX_PLLCON_SDIVSHIFT);
 	writel(tmp, S3C2410_UPLLCON);
 	writel(tmp, S3C2410_UPLLCON);
 
 
+	gpio_request(S3C2410_GPC(0), "LCD power");
+	gpio_request(S3C2410_GPC(5), "LCD power");
+	gpio_request(S3C2410_GPC(6), "LCD power");
+
+
 	platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices));
 	platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices));
 }
 }
 
 

+ 2 - 2
arch/arm/mach-s3c2410/mach-n30.c

@@ -338,7 +338,7 @@ static struct platform_device *n35_devices[] __initdata = {
 	&n35_button_device,
 	&n35_button_device,
 };
 };
 
 
-static struct s3c2410_platform_i2c n30_i2ccfg = {
+static struct s3c2410_platform_i2c __initdata n30_i2ccfg = {
 	.flags		= 0,
 	.flags		= 0,
 	.slave_addr	= 0x10,
 	.slave_addr	= 0x10,
 	.frequency	= 10*1000,
 	.frequency	= 10*1000,
@@ -500,8 +500,8 @@ static void __init n30_init_irq(void)
 static void __init n30_init(void)
 static void __init n30_init(void)
 {
 {
 	s3c24xx_fb_set_platdata(&n30_fb_info);
 	s3c24xx_fb_set_platdata(&n30_fb_info);
-	s3c_device_i2c0.dev.platform_data = &n30_i2ccfg;
 	s3c24xx_udc_set_platdata(&n30_udc_cfg);
 	s3c24xx_udc_set_platdata(&n30_udc_cfg);
+	s3c_i2c0_set_platdata(&n30_i2ccfg);
 
 
 	/* Turn off suspend on both USB ports, and switch the
 	/* Turn off suspend on both USB ports, and switch the
 	 * selectable USB port to USB device mode. */
 	 * selectable USB port to USB device mode. */

+ 4 - 4
arch/arm/mach-s3c2410/mach-qt2410.c

@@ -258,7 +258,7 @@ static struct platform_device *qt2410_devices[] __initdata = {
 	&qt2410_led,
 	&qt2410_led,
 };
 };
 
 
-static struct mtd_partition qt2410_nand_part[] = {
+static struct mtd_partition __initdata qt2410_nand_part[] = {
 	[0] = {
 	[0] = {
 		.name	= "U-Boot",
 		.name	= "U-Boot",
 		.size	= 0x30000,
 		.size	= 0x30000,
@@ -286,7 +286,7 @@ static struct mtd_partition qt2410_nand_part[] = {
 	},
 	},
 };
 };
 
 
-static struct s3c2410_nand_set qt2410_nand_sets[] = {
+static struct s3c2410_nand_set __initdata qt2410_nand_sets[] = {
 	[0] = {
 	[0] = {
 		.name		= "NAND",
 		.name		= "NAND",
 		.nr_chips	= 1,
 		.nr_chips	= 1,
@@ -299,7 +299,7 @@ static struct s3c2410_nand_set qt2410_nand_sets[] = {
  * chips and beyond.
  * chips and beyond.
  */
  */
 
 
-static struct s3c2410_platform_nand qt2410_nand_info = {
+static struct s3c2410_platform_nand __initdata qt2410_nand_info = {
 	.tacls		= 20,
 	.tacls		= 20,
 	.twrph0		= 60,
 	.twrph0		= 60,
 	.twrph1		= 20,
 	.twrph1		= 20,
@@ -331,7 +331,7 @@ static void __init qt2410_map_io(void)
 
 
 static void __init qt2410_machine_init(void)
 static void __init qt2410_machine_init(void)
 {
 {
-	s3c_device_nand.dev.platform_data = &qt2410_nand_info;
+	s3c_nand_set_platdata(&qt2410_nand_info);
 
 
 	switch (tft_type) {
 	switch (tft_type) {
 	case 'p': /* production */
 	case 'p': /* production */

+ 6 - 5
arch/arm/mach-s3c2412/mach-jive.c

@@ -96,7 +96,7 @@ static struct s3c2410_uartcfg jive_uartcfgs[] = {
  * 0x017d0000-0x02bd0000 : cramfs B
  * 0x017d0000-0x02bd0000 : cramfs B
  * 0x02bd0000-0x03fd0000 : yaffs
  * 0x02bd0000-0x03fd0000 : yaffs
  */
  */
-static struct mtd_partition jive_imageA_nand_part[] = {
+static struct mtd_partition __initdata jive_imageA_nand_part[] = {
 
 
 #ifdef CONFIG_MACH_JIVE_SHOW_BOOTLOADER
 #ifdef CONFIG_MACH_JIVE_SHOW_BOOTLOADER
 	/* Don't allow access to the bootloader from linux */
 	/* Don't allow access to the bootloader from linux */
@@ -154,7 +154,7 @@ static struct mtd_partition jive_imageA_nand_part[] = {
         },
         },
 };
 };
 
 
-static struct mtd_partition jive_imageB_nand_part[] = {
+static struct mtd_partition __initdata jive_imageB_nand_part[] = {
 
 
 #ifdef CONFIG_MACH_JIVE_SHOW_BOOTLOADER
 #ifdef CONFIG_MACH_JIVE_SHOW_BOOTLOADER
 	/* Don't allow access to the bootloader from linux */
 	/* Don't allow access to the bootloader from linux */
@@ -213,7 +213,7 @@ static struct mtd_partition jive_imageB_nand_part[] = {
         },
         },
 };
 };
 
 
-static struct s3c2410_nand_set jive_nand_sets[] = {
+static struct s3c2410_nand_set __initdata jive_nand_sets[] = {
 	[0] = {
 	[0] = {
 		.name           = "flash",
 		.name           = "flash",
 		.nr_chips       = 1,
 		.nr_chips       = 1,
@@ -222,7 +222,7 @@ static struct s3c2410_nand_set jive_nand_sets[] = {
 	},
 	},
 };
 };
 
 
-static struct s3c2410_platform_nand jive_nand_info = {
+static struct s3c2410_platform_nand __initdata jive_nand_info = {
 	/* set taken from osiris nand timings, possibly still conservative */
 	/* set taken from osiris nand timings, possibly still conservative */
 	.tacls		= 30,
 	.tacls		= 30,
 	.twrph0		= 55,
 	.twrph0		= 55,
@@ -631,7 +631,8 @@ static void __init jive_machine_init(void)
 
 
 	s3c_pm_init();
 	s3c_pm_init();
 
 
-	s3c_device_nand.dev.platform_data = &jive_nand_info;
+	/** TODO - check that this is after the cmdline option! */
+	s3c_nand_set_platdata(&jive_nand_info);
 
 
 	/* initialise the spi */
 	/* initialise the spi */
 
 

+ 5 - 5
arch/arm/mach-s3c2412/mach-vstms.c

@@ -76,7 +76,7 @@ static struct s3c2410_uartcfg vstms_uartcfgs[] __initdata = {
 	}
 	}
 };
 };
 
 
-static struct mtd_partition vstms_nand_part[] = {
+static struct mtd_partition __initdata vstms_nand_part[] = {
 	[0] = {
 	[0] = {
 		.name	= "Boot Agent",
 		.name	= "Boot Agent",
 		.size	= 0x7C000,
 		.size	= 0x7C000,
@@ -99,7 +99,7 @@ static struct mtd_partition vstms_nand_part[] = {
 	},
 	},
 };
 };
 
 
-static struct s3c2410_nand_set vstms_nand_sets[] = {
+static struct s3c2410_nand_set __initdata vstms_nand_sets[] = {
 	[0] = {
 	[0] = {
 		.name		= "NAND",
 		.name		= "NAND",
 		.nr_chips	= 1,
 		.nr_chips	= 1,
@@ -112,7 +112,7 @@ static struct s3c2410_nand_set vstms_nand_sets[] = {
  * chips and beyond.
  * chips and beyond.
 */
 */
 
 
-static struct s3c2410_platform_nand vstms_nand_info = {
+static struct s3c2410_platform_nand __initdata vstms_nand_info = {
 	.tacls		= 20,
 	.tacls		= 20,
 	.twrph0		= 60,
 	.twrph0		= 60,
 	.twrph1		= 20,
 	.twrph1		= 20,
@@ -143,8 +143,6 @@ static void __init vstms_fixup(struct machine_desc *desc,
 
 
 static void __init vstms_map_io(void)
 static void __init vstms_map_io(void)
 {
 {
-	s3c_device_nand.dev.platform_data = &vstms_nand_info;
-
 	s3c24xx_init_io(vstms_iodesc, ARRAY_SIZE(vstms_iodesc));
 	s3c24xx_init_io(vstms_iodesc, ARRAY_SIZE(vstms_iodesc));
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(vstms_uartcfgs, ARRAY_SIZE(vstms_uartcfgs));
 	s3c24xx_init_uarts(vstms_uartcfgs, ARRAY_SIZE(vstms_uartcfgs));
@@ -153,6 +151,8 @@ static void __init vstms_map_io(void)
 static void __init vstms_init(void)
 static void __init vstms_init(void)
 {
 {
 	s3c_i2c0_set_platdata(NULL);
 	s3c_i2c0_set_platdata(NULL);
+	s3c_nand_set_platdata(&vstms_nand_info);
+
 	platform_add_devices(vstms_devices, ARRAY_SIZE(vstms_devices));
 	platform_add_devices(vstms_devices, ARRAY_SIZE(vstms_devices));
 }
 }
 
 

+ 6 - 6
arch/arm/mach-s3c2440/mach-anubis.c

@@ -139,7 +139,7 @@ static int external_map[]   = { 2 };
 static int chip0_map[]      = { 0 };
 static int chip0_map[]      = { 0 };
 static int chip1_map[]      = { 1 };
 static int chip1_map[]      = { 1 };
 
 
-static struct mtd_partition anubis_default_nand_part[] = {
+static struct mtd_partition __initdata anubis_default_nand_part[] = {
 	[0] = {
 	[0] = {
 		.name	= "Boot Agent",
 		.name	= "Boot Agent",
 		.size	= SZ_16K,
 		.size	= SZ_16K,
@@ -162,7 +162,7 @@ static struct mtd_partition anubis_default_nand_part[] = {
 	}
 	}
 };
 };
 
 
-static struct mtd_partition anubis_default_nand_part_large[] = {
+static struct mtd_partition __initdata anubis_default_nand_part_large[] = {
 	[0] = {
 	[0] = {
 		.name	= "Boot Agent",
 		.name	= "Boot Agent",
 		.size	= SZ_128K,
 		.size	= SZ_128K,
@@ -192,7 +192,7 @@ static struct mtd_partition anubis_default_nand_part_large[] = {
  * socket.
  * socket.
 */
 */
 
 
-static struct s3c2410_nand_set anubis_nand_sets[] = {
+static struct s3c2410_nand_set __initdata anubis_nand_sets[] = {
 	[1] = {
 	[1] = {
 		.name		= "External",
 		.name		= "External",
 		.nr_chips	= 1,
 		.nr_chips	= 1,
@@ -234,7 +234,7 @@ static void anubis_nand_select(struct s3c2410_nand_set *set, int slot)
 	__raw_writeb(tmp, ANUBIS_VA_CTRL1);
 	__raw_writeb(tmp, ANUBIS_VA_CTRL1);
 }
 }
 
 
-static struct s3c2410_platform_nand anubis_nand_info = {
+static struct s3c2410_platform_nand __initdata anubis_nand_info = {
 	.tacls		= 25,
 	.tacls		= 25,
 	.twrph0		= 55,
 	.twrph0		= 55,
 	.twrph1		= 40,
 	.twrph1		= 40,
@@ -466,8 +466,6 @@ static void __init anubis_map_io(void)
 
 
 	s3c24xx_register_clocks(anubis_clocks, ARRAY_SIZE(anubis_clocks));
 	s3c24xx_register_clocks(anubis_clocks, ARRAY_SIZE(anubis_clocks));
 
 
-	s3c_device_nand.dev.platform_data = &anubis_nand_info;
-
 	s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
 	s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
 	s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
@@ -488,7 +486,9 @@ static void __init anubis_map_io(void)
 static void __init anubis_init(void)
 static void __init anubis_init(void)
 {
 {
 	s3c_i2c0_set_platdata(NULL);
 	s3c_i2c0_set_platdata(NULL);
+	s3c_nand_set_platdata(&anubis_nand_info);
 	simtec_audio_add(NULL, false, &anubis_audio);
 	simtec_audio_add(NULL, false, &anubis_audio);
+
 	platform_add_devices(anubis_devices, ARRAY_SIZE(anubis_devices));
 	platform_add_devices(anubis_devices, ARRAY_SIZE(anubis_devices));
 
 
 	i2c_register_board_info(0, anubis_i2c_devs,
 	i2c_register_board_info(0, anubis_i2c_devs,

+ 4 - 5
arch/arm/mach-s3c2440/mach-at2440evb.c

@@ -96,7 +96,7 @@ static struct s3c2410_uartcfg at2440evb_uartcfgs[] __initdata = {
 
 
 /* NAND Flash on AT2440EVB board */
 /* NAND Flash on AT2440EVB board */
 
 
-static struct mtd_partition at2440evb_default_nand_part[] = {
+static struct mtd_partition __initdata at2440evb_default_nand_part[] = {
 	[0] = {
 	[0] = {
 		.name	= "Boot Agent",
 		.name	= "Boot Agent",
 		.size	= SZ_256K,
 		.size	= SZ_256K,
@@ -114,7 +114,7 @@ static struct mtd_partition at2440evb_default_nand_part[] = {
 	},
 	},
 };
 };
 
 
-static struct s3c2410_nand_set at2440evb_nand_sets[] = {
+static struct s3c2410_nand_set __initdata at2440evb_nand_sets[] = {
 	[0] = {
 	[0] = {
 		.name		= "nand",
 		.name		= "nand",
 		.nr_chips	= 1,
 		.nr_chips	= 1,
@@ -123,7 +123,7 @@ static struct s3c2410_nand_set at2440evb_nand_sets[] = {
 	},
 	},
 };
 };
 
 
-static struct s3c2410_platform_nand at2440evb_nand_info = {
+static struct s3c2410_platform_nand __initdata at2440evb_nand_info = {
 	.tacls		= 25,
 	.tacls		= 25,
 	.twrph0		= 55,
 	.twrph0		= 55,
 	.twrph1		= 40,
 	.twrph1		= 40,
@@ -216,8 +216,6 @@ static struct platform_device *at2440evb_devices[] __initdata = {
 
 
 static void __init at2440evb_map_io(void)
 static void __init at2440evb_map_io(void)
 {
 {
-	s3c_device_nand.dev.platform_data = &at2440evb_nand_info;
-	s3c_device_sdi.name = "s3c2440-sdi";
 	s3c_device_sdi.dev.platform_data = &at2440evb_mci_pdata;
 	s3c_device_sdi.dev.platform_data = &at2440evb_mci_pdata;
 
 
 	s3c24xx_init_io(at2440evb_iodesc, ARRAY_SIZE(at2440evb_iodesc));
 	s3c24xx_init_io(at2440evb_iodesc, ARRAY_SIZE(at2440evb_iodesc));
@@ -228,6 +226,7 @@ static void __init at2440evb_map_io(void)
 static void __init at2440evb_init(void)
 static void __init at2440evb_init(void)
 {
 {
 	s3c24xx_fb_set_platdata(&at2440evb_fb_info);
 	s3c24xx_fb_set_platdata(&at2440evb_fb_info);
+	s3c_nand_set_platdata(&at2440evb_nand_info);
 	s3c_i2c0_set_platdata(NULL);
 	s3c_i2c0_set_platdata(NULL);
 
 
 	platform_add_devices(at2440evb_devices, ARRAY_SIZE(at2440evb_devices));
 	platform_add_devices(at2440evb_devices, ARRAY_SIZE(at2440evb_devices));

+ 3 - 1
arch/arm/mach-s3c2440/mach-mini2440.c

@@ -532,7 +532,6 @@ static void __init mini2440_map_io(void)
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(mini2440_uartcfgs, ARRAY_SIZE(mini2440_uartcfgs));
 	s3c24xx_init_uarts(mini2440_uartcfgs, ARRAY_SIZE(mini2440_uartcfgs));
 
 
-	s3c_device_nand.dev.platform_data = &mini2440_nand_info;
 	s3c_device_sdi.dev.platform_data = &mini2440_mmc_cfg;
 	s3c_device_sdi.dev.platform_data = &mini2440_mmc_cfg;
 }
 }
 
 
@@ -677,8 +676,11 @@ static void __init mini2440_init(void)
 		printk("\n");
 		printk("\n");
 		s3c24xx_fb_set_platdata(&mini2440_fb_info);
 		s3c24xx_fb_set_platdata(&mini2440_fb_info);
 	}
 	}
+
 	s3c24xx_udc_set_platdata(&mini2440_udc_cfg);
 	s3c24xx_udc_set_platdata(&mini2440_udc_cfg);
+	s3c_nand_set_platdata(&mini2440_nand_info);
 	s3c_i2c0_set_platdata(NULL);
 	s3c_i2c0_set_platdata(NULL);
+
 	i2c_register_board_info(0, mini2440_i2c_devs,
 	i2c_register_board_info(0, mini2440_i2c_devs,
 				ARRAY_SIZE(mini2440_i2c_devs));
 				ARRAY_SIZE(mini2440_i2c_devs));
 
 

+ 5 - 6
arch/arm/mach-s3c2440/mach-osiris.c

@@ -150,7 +150,7 @@ static int external_map[]   = { 2 };
 static int chip0_map[]      = { 0 };
 static int chip0_map[]      = { 0 };
 static int chip1_map[]      = { 1 };
 static int chip1_map[]      = { 1 };
 
 
-static struct mtd_partition osiris_default_nand_part[] = {
+static struct mtd_partition __initdata osiris_default_nand_part[] = {
 	[0] = {
 	[0] = {
 		.name	= "Boot Agent",
 		.name	= "Boot Agent",
 		.size	= SZ_16K,
 		.size	= SZ_16K,
@@ -173,7 +173,7 @@ static struct mtd_partition osiris_default_nand_part[] = {
 	}
 	}
 };
 };
 
 
-static struct mtd_partition osiris_default_nand_part_large[] = {
+static struct mtd_partition __initdata osiris_default_nand_part_large[] = {
 	[0] = {
 	[0] = {
 		.name	= "Boot Agent",
 		.name	= "Boot Agent",
 		.size	= SZ_128K,
 		.size	= SZ_128K,
@@ -203,7 +203,7 @@ static struct mtd_partition osiris_default_nand_part_large[] = {
  * socket.
  * socket.
 */
 */
 
 
-static struct s3c2410_nand_set osiris_nand_sets[] = {
+static struct s3c2410_nand_set __initdata osiris_nand_sets[] = {
 	[1] = {
 	[1] = {
 		.name		= "External",
 		.name		= "External",
 		.nr_chips	= 1,
 		.nr_chips	= 1,
@@ -245,7 +245,7 @@ static void osiris_nand_select(struct s3c2410_nand_set *set, int slot)
 	__raw_writeb(tmp, OSIRIS_VA_CTRL0);
 	__raw_writeb(tmp, OSIRIS_VA_CTRL0);
 }
 }
 
 
-static struct s3c2410_platform_nand osiris_nand_info = {
+static struct s3c2410_platform_nand __initdata osiris_nand_info = {
 	.tacls		= 25,
 	.tacls		= 25,
 	.twrph0		= 60,
 	.twrph0		= 60,
 	.twrph1		= 60,
 	.twrph1		= 60,
@@ -411,8 +411,6 @@ static void __init osiris_map_io(void)
 
 
 	s3c24xx_register_clocks(osiris_clocks, ARRAY_SIZE(osiris_clocks));
 	s3c24xx_register_clocks(osiris_clocks, ARRAY_SIZE(osiris_clocks));
 
 
-	s3c_device_nand.dev.platform_data = &osiris_nand_info;
-
 	s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc));
 	s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc));
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
 	s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
@@ -442,6 +440,7 @@ static void __init osiris_init(void)
 	sysdev_register(&osiris_pm_sysdev);
 	sysdev_register(&osiris_pm_sysdev);
 
 
 	s3c_i2c0_set_platdata(NULL);
 	s3c_i2c0_set_platdata(NULL);
+	s3c_nand_set_platdata(&osiris_nand_info);
 
 
 	s3c_cpufreq_setboard(&osiris_cpufreq);
 	s3c_cpufreq_setboard(&osiris_cpufreq);
 
 

+ 4 - 5
arch/arm/mach-s3c2440/mach-rx3715.c

@@ -149,7 +149,7 @@ static struct s3c2410fb_mach_info rx3715_fb_info __initdata = {
 	.gpdup_mask =	0xffffffff,
 	.gpdup_mask =	0xffffffff,
 };
 };
 
 
-static struct mtd_partition rx3715_nand_part[] = {
+static struct mtd_partition __initdata rx3715_nand_part[] = {
 	[0] = {
 	[0] = {
 		.name		= "Whole Flash",
 		.name		= "Whole Flash",
 		.offset		= 0,
 		.offset		= 0,
@@ -158,7 +158,7 @@ static struct mtd_partition rx3715_nand_part[] = {
 	}
 	}
 };
 };
 
 
-static struct s3c2410_nand_set rx3715_nand_sets[] = {
+static struct s3c2410_nand_set __initdata rx3715_nand_sets[] = {
 	[0] = {
 	[0] = {
 		.name		= "Internal",
 		.name		= "Internal",
 		.nr_chips	= 1,
 		.nr_chips	= 1,
@@ -167,7 +167,7 @@ static struct s3c2410_nand_set rx3715_nand_sets[] = {
 	},
 	},
 };
 };
 
 
-static struct s3c2410_platform_nand rx3715_nand_info = {
+static struct s3c2410_platform_nand __initdata rx3715_nand_info = {
 	.tacls		= 25,
 	.tacls		= 25,
 	.twrph0		= 50,
 	.twrph0		= 50,
 	.twrph1		= 15,
 	.twrph1		= 15,
@@ -186,8 +186,6 @@ static struct platform_device *rx3715_devices[] __initdata = {
 
 
 static void __init rx3715_map_io(void)
 static void __init rx3715_map_io(void)
 {
 {
-	s3c_device_nand.dev.platform_data = &rx3715_nand_info;
-
 	s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc));
 	s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc));
 	s3c24xx_init_clocks(16934000);
 	s3c24xx_init_clocks(16934000);
 	s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs));
 	s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs));
@@ -205,6 +203,7 @@ static void __init rx3715_init_machine(void)
 #endif
 #endif
 	s3c_pm_init();
 	s3c_pm_init();
 
 
+	s3c_nand_set_platdata(&rx3715_nand_info);
 	s3c24xx_fb_set_platdata(&rx3715_fb_info);
 	s3c24xx_fb_set_platdata(&rx3715_fb_info);
 	platform_add_devices(rx3715_devices, ARRAY_SIZE(rx3715_devices));
 	platform_add_devices(rx3715_devices, ARRAY_SIZE(rx3715_devices));
 }
 }

+ 3 - 3
arch/arm/mach-s3c2442/mach-gta02.c

@@ -423,7 +423,7 @@ static struct i2c_board_info gta02_i2c_devs[] __initdata = {
 	},
 	},
 };
 };
 
 
-static struct s3c2410_nand_set gta02_nand_sets[] = {
+static struct s3c2410_nand_set __initdata gta02_nand_sets[] = {
 	[0] = {
 	[0] = {
 		/*
 		/*
 		 * This name is also hard-coded in the boot loaders, so
 		 * This name is also hard-coded in the boot loaders, so
@@ -442,7 +442,7 @@ static struct s3c2410_nand_set gta02_nand_sets[] = {
  * data sheet (K5D2G13ACM-D075 MCP Memory).
  * data sheet (K5D2G13ACM-D075 MCP Memory).
  */
  */
 
 
-static struct s3c2410_platform_nand gta02_nand_info = {
+static struct s3c2410_platform_nand __initdata gta02_nand_info = {
 	.tacls		= 0,
 	.tacls		= 0,
 	.twrph0		= 25,
 	.twrph0		= 25,
 	.twrph1		= 15,
 	.twrph1		= 15,
@@ -621,9 +621,9 @@ static void __init gta02_machine_init(void)
 #endif
 #endif
 
 
 	s3c_device_usb.dev.platform_data = &gta02_usb_info;
 	s3c_device_usb.dev.platform_data = &gta02_usb_info;
-	s3c_device_nand.dev.platform_data = &gta02_nand_info;
 
 
 	s3c24xx_udc_set_platdata(&gta02_udc_cfg);
 	s3c24xx_udc_set_platdata(&gta02_udc_cfg);
+	s3c_nand_set_platdata(&gta02_nand_info);
 	s3c_i2c0_set_platdata(NULL);
 	s3c_i2c0_set_platdata(NULL);
 
 
 	i2c_register_board_info(0, gta02_i2c_devs, ARRAY_SIZE(gta02_i2c_devs));
 	i2c_register_board_info(0, gta02_i2c_devs, ARRAY_SIZE(gta02_i2c_devs));

+ 1 - 1
arch/arm/mach-s3c6410/mach-hmt.c

@@ -250,7 +250,7 @@ static void __init hmt_machine_init(void)
 {
 {
 	s3c_i2c0_set_platdata(NULL);
 	s3c_i2c0_set_platdata(NULL);
 	s3c_fb_set_platdata(&hmt_lcd_pdata);
 	s3c_fb_set_platdata(&hmt_lcd_pdata);
-	s3c_device_nand.dev.platform_data = &hmt_nand_info;
+	s3c_nand_set_platdata(&hmt_nand_info);
 
 
 	gpio_request(S3C64XX_GPC(7), "usb power");
 	gpio_request(S3C64XX_GPC(7), "usb power");
 	gpio_direction_output(S3C64XX_GPC(7), 0);
 	gpio_direction_output(S3C64XX_GPC(7), 0);

+ 97 - 0
arch/arm/plat-s3c/dev-nand.c

@@ -9,8 +9,12 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 
 
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
 #include <mach/map.h>
 #include <mach/map.h>
 #include <plat/devs.h>
 #include <plat/devs.h>
+#include <plat/nand.h>
 
 
 static struct resource s3c_nand_resource[] = {
 static struct resource s3c_nand_resource[] = {
 	[0] = {
 	[0] = {
@@ -28,3 +32,96 @@ struct platform_device s3c_device_nand = {
 };
 };
 
 
 EXPORT_SYMBOL(s3c_device_nand);
 EXPORT_SYMBOL(s3c_device_nand);
+
+/**
+ * s3c_nand_copy_set() - copy nand set data
+ * @set: The new structure, directly copied from the old.
+ *
+ * Copy all the fields from the NAND set field from what is probably __initdata
+ * to new kernel memory. The code returns 0 if the copy happened correctly or
+ * an error code for the calling function to display.
+ *
+ * Note, we currently do not try and look to see if we've already copied the
+ * data in a previous set.
+ */
+static int __init s3c_nand_copy_set(struct s3c2410_nand_set *set)
+{
+	void *ptr;
+	int size;
+
+	size = sizeof(struct mtd_partition) * set->nr_partitions;
+	if (size) {
+		ptr = kmemdup(set->partitions, size, GFP_KERNEL);
+		set->partitions = ptr;
+
+		if (!ptr)
+			return -ENOMEM;
+	}
+	
+	size = sizeof(int) * set->nr_chips;
+	if (size) {
+		ptr = kmemdup(set->nr_map, size, GFP_KERNEL);
+		set->nr_map = ptr;
+
+		if (!ptr)
+			return -ENOMEM;
+	}
+
+	if (set->ecc_layout) {
+		ptr = kmemdup(set->ecc_layout,
+			      sizeof(struct nand_ecclayout), GFP_KERNEL);
+		set->ecc_layout = ptr;
+
+		if (!ptr)
+			return -ENOMEM;
+	}
+	
+	return 0;
+}
+
+void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
+{
+	struct s3c2410_platform_nand *npd;
+	int size;
+	int ret;
+
+	/* note, if we get a failure in allocation, we simply drop out of the
+	 * function. If there is so little memory available at initialisation
+	 * time then there is little chance the system is going to run.
+	 */ 
+
+	npd = kmemdup(nand, sizeof(struct s3c2410_platform_nand), GFP_KERNEL);
+	if (!npd) {
+		printk(KERN_ERR "%s: failed copying platform data\n", __func__);
+		return;
+	}
+
+	/* now see if we need to copy any of the nand set data */
+
+	size = sizeof(struct s3c2410_nand_set) * npd->nr_sets;
+	if (size) {
+		struct s3c2410_nand_set *from = npd->sets;
+		struct s3c2410_nand_set *to;
+		int i;
+
+		to = kmemdup(from, size, GFP_KERNEL);
+		npd->sets = to;	/* set, even if we failed */
+
+		if (!to) {
+			printk(KERN_ERR "%s: no memory for sets\n", __func__);
+			return;
+		}
+		
+		for (i = 0; i < npd->nr_sets; i++) {
+			ret = s3c_nand_copy_set(to);
+			if (!ret) {
+				printk(KERN_ERR "%s: failed to copy set %d\n",
+				__func__, i);
+				return;
+			}
+			to++;
+		}
+	}
+}
+
+EXPORT_SYMBOL_GPL(s3c_nand_set_platdata);

+ 8 - 0
arch/arm/plat-s3c/include/plat/nand.h

@@ -55,3 +55,11 @@ struct s3c2410_platform_nand {
 					       int chip);
 					       int chip);
 };
 };
 
 
+/**
+ * s3c_nand_set_platdata() - register NAND platform data.
+ * @nand: The NAND platform data to register with s3c_device_nand.
+ *
+ * This function copies the given NAND platform data, @nand and registers
+ * it with the s3c_device_nand. This allows @nand to be __initdata.
+*/
+extern void s3c_nand_set_platdata(struct s3c2410_platform_nand *nand);

+ 1 - 1
arch/arm/plat-s3c24xx/common-smdk.c

@@ -198,7 +198,7 @@ void __init smdk_machine_init(void)
 	if (machine_is_smdk2443())
 	if (machine_is_smdk2443())
 		smdk_nand_info.twrph0 = 50;
 		smdk_nand_info.twrph0 = 50;
 
 
-	s3c_device_nand.dev.platform_data = &smdk_nand_info;
+	s3c_nand_set_platdata(&smdk_nand_info);
 
 
 	platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));
 	platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));