aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/s3c24xx/patches-2.6.30/001-merge-openmoko.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/s3c24xx/patches-2.6.30/001-merge-openmoko.patch')
-rw-r--r--target/linux/s3c24xx/patches-2.6.30/001-merge-openmoko.patch2207
1 files changed, 0 insertions, 2207 deletions
diff --git a/target/linux/s3c24xx/patches-2.6.30/001-merge-openmoko.patch b/target/linux/s3c24xx/patches-2.6.30/001-merge-openmoko.patch
deleted file mode 100644
index 1a515a4896..0000000000
--- a/target/linux/s3c24xx/patches-2.6.30/001-merge-openmoko.patch
+++ /dev/null
@@ -1,2207 +0,0 @@
-Merge OpenMoko kernel patches
-git://git.openmoko.org/git/kernel.git#(no
-
-lars@lars-laptop Thu May 14 18:33:23 UTC 2009
-
----
-
---- /dev/null
-+++ b/arch/arm/mach-s3c2410/include/mach/mci.h
-@@ -0,0 +1,13 @@
-+#ifndef _ARCH_MCI_H
-+#define _ARCH_MCI_H
-+
-+struct s3c24xx_mci_pdata {
-+ unsigned int gpio_detect;
-+ unsigned int gpio_wprotect;
-+ unsigned long ocr_avail;
-+ unsigned int do_dma;
-+ void (*set_power)(unsigned char power_mode,
-+ unsigned short vdd);
-+};
-+
-+#endif /* _ARCH_NCI_H */
---- a/arch/arm/mach-s3c2410/include/mach/regs-sdi.h
-+++ b/arch/arm/mach-s3c2410/include/mach/regs-sdi.h
-@@ -30,6 +30,7 @@
- #define S3C2410_SDIFSTA (0x38)
-
- #define S3C2410_SDIDATA (0x3C)
-+#define S3C2410_SDIDATA_BYTE (0x3C)
- #define S3C2410_SDIIMSK (0x40)
-
- #define S3C2440_SDIDATA (0x40)
-@@ -37,6 +38,8 @@
-
- #define S3C2440_SDICON_SDRESET (1<<8)
- #define S3C2440_SDICON_MMCCLOCK (1<<5)
-+#define S3C2440_SDIDATA_BYTE (0x48)
-+
- #define S3C2410_SDICON_BYTEORDER (1<<4)
- #define S3C2410_SDICON_SDIOIRQ (1<<3)
- #define S3C2410_SDICON_RWAITEN (1<<2)
---- a/arch/arm/mach-s3c2440/s3c2440.c
-+++ b/arch/arm/mach-s3c2440/s3c2440.c
-@@ -46,6 +46,9 @@ int __init s3c2440_init(void)
- s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
- s3c_device_wdt.resource[1].end = IRQ_S3C2440_WDT;
-
-+ /* make sure SD/MMC driver can distinguish 2440 from 2410 */
-+ s3c_device_sdi.name = "s3c2440-sdi";
-+
- /* register our system device for everything else */
-
- return sysdev_register(&s3c2440_sysdev);
---- a/arch/arm/mach-s3c2442/s3c2442.c
-+++ b/arch/arm/mach-s3c2442/s3c2442.c
-@@ -21,6 +21,7 @@
-
- #include <plat/s3c2442.h>
- #include <plat/cpu.h>
-+#include <plat/devs.h>
-
- static struct sys_device s3c2442_sysdev = {
- .cls = &s3c2442_sysclass,
-@@ -30,5 +31,8 @@ int __init s3c2442_init(void)
- {
- printk("S3C2442: Initialising architecture\n");
-
-+ /* make sure SD/MMC driver can distinguish 2440 from 2410 */
-+ s3c_device_sdi.name = "s3c2440-sdi";
-+
- return sysdev_register(&s3c2442_sysdev);
- }
---- a/arch/arm/Makefile
-+++ b/arch/arm/Makefile
-@@ -55,7 +55,8 @@ ifeq ($(CONFIG_CPU_32v6),y)
- arch-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k)
- endif
- arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t)
--arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t
-+# We can't load armv4t modules, but still need to assemble some armv4t code to be linked in.
-+arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 -Wa,-march=armv4t
- arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4
- arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3
-
---- /dev/null
-+++ b/arch/arm/plat-s3c/include/mach/cpu.h
-@@ -0,0 +1,165 @@
-+/*
-+ * arch/arm/plat-s3c/include/mach/cpu.h
-+ *
-+ * S3C cpu type detection
-+ *
-+ * Copyright (C) 2008 Samsung Electronics
-+ * Kyungmin Park <kyungmin.park@samsung.com>
-+ *
-+ * Derived from OMAP cpu.h
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#ifndef __ASM_ARCH_S3C_CPU_H
-+#define __ASM_ARCH_S3C_CPU_H
-+
-+extern unsigned int system_rev;
-+
-+#define S3C_SYSTEM_REV_ATAG (system_rev & 0xffff)
-+#define S3C_SYSTEM_REV_CPU (system_rev & 0xffff0000)
-+
-+/*
-+ * cpu_is_s3c24xx(): True for s3c2400, s3c2410, s3c2440 and so on
-+ * cpu_is_s3c241x(): True fro s3c2410, s3c2412
-+ * cpu_is_s3c244x(): True fro s3c2440, s3c2442, s3c2443
-+ * cpu_is_s3c64xx(): True for s3c6400, s3c6410
-+ */
-+#define GET_S3C_CLASS ((system_rev >> 24) & 0xff)
-+
-+#define IS_S3C_CLASS(class, id) \
-+static inline int is_s3c ##class (void) \
-+{ \
-+ return (GET_S3C_CLASS == (id)) ? 1 : 0; \
-+}
-+
-+#define GET_S3C_SUBCLASS ((system_rev >> 20) & 0xfff)
-+
-+#define IS_S3C_SUBCLASS(subclass, id) \
-+static inline int is_s3c ##subclass (void) \
-+{ \
-+ return (GET_S3C_SUBCLASS == (id)) ? 1 : 0; \
-+}
-+
-+IS_S3C_CLASS(24xx, 0x24)
-+IS_S3C_CLASS(64xx, 0x64)
-+
-+IS_S3C_SUBCLASS(241x, 0x241)
-+IS_S3C_SUBCLASS(244x, 0x244)
-+
-+#define cpu_is_s3c24xx() 0
-+#define cpu_is_s3c241x() 0
-+#define cpu_is_s3c244x() 0
-+#define cpu_is_s3c64xx() 0
-+
-+#if defined(CONFIG_ARCH_S3C2410)
-+# undef cpu_is_s3c24xx
-+# undef cpu_is_s3c241x
-+# undef cpu_is_s3c244x
-+# define cpu_is_s3c24xx() is_s3c24xx()
-+# define cpu_is_s3c241x() is_s3c241x()
-+# define cpu_is_s3c244x() is_s3c244x()
-+#endif
-+
-+#if defined(CONFIG_ARCH_S3C64XX)
-+# undef cpu_is_s3c64xx
-+# define cpu_is_s3c64xx() is_s3c64xx()
-+#endif
-+
-+/*
-+ * Macros to detect individual cpu types.
-+ * cpu_is_s3c2410(): True for s3c2410
-+ * cpu_is_s3c2440(): True for s3c2440
-+ * cpu_is_s3c6400(): True for s3c6400
-+ * cpu_is_s3c6410(): True for s3c6410
-+ *
-+ * Exception:
-+ * Store Revision A to 1
-+ * s3c2410a -> s3c2411
-+ * s3c2440a -> s3c2441
-+ */
-+
-+#define GET_S3C_TYPE ((system_rev >> 16) & 0xffff)
-+
-+#define IS_S3C_TYPE(type, id) \
-+static inline int is_s3c ##type (void) \
-+{ \
-+ return (GET_S3C_TYPE == (id)) ? 1 : 0; \
-+}
-+
-+IS_S3C_TYPE(2400, 0x2400)
-+IS_S3C_TYPE(2410, 0x2410)
-+IS_S3C_TYPE(2410a, 0x2411)
-+IS_S3C_TYPE(2412, 0x2412)
-+IS_S3C_TYPE(2440, 0x2440)
-+IS_S3C_TYPE(2440a, 0x2441)
-+IS_S3C_TYPE(2442, 0x2442)
-+IS_S3C_TYPE(2443, 0x2443)
-+IS_S3C_TYPE(6400, 0x6400)
-+IS_S3C_TYPE(6410, 0x6410)
-+
-+#define cpu_is_s3c2400() 0
-+#define cpu_is_s3c2410() 0
-+#define cpu_is_s3c2410a() 0
-+#define cpu_is_s3c2412() 0
-+#define cpu_is_s3c2440() 0
-+#define cpu_is_s3c2440a() 0
-+#define cpu_is_s3c2442() 0
-+#define cpu_is_s3c2443() 0
-+#define cpu_is_s3c6400() 0
-+#define cpu_is_s3c6410() 0
-+
-+#if defined(CONFIG_ARCH_S3C2410)
-+# undef cpu_is_s3c2400
-+# define cpu_is_s3c2400() is_s3c2400()
-+#endif
-+
-+#if defined(CONFIG_CPU_S3C2410)
-+# undef cpu_is_s3c2410
-+# undef cpu_is_s3c2410a
-+# define cpu_is_s3c2410() is_s3c2410()
-+# define cpu_is_s3c2410a() is_s3c2410a()
-+#endif
-+
-+#if defined(CONFIG_CPU_S3C2412)
-+# undef cpu_is_s3c2412
-+# define cpu_is_s3c2412() is_s3c2412()
-+#endif
-+
-+#if defined(CONFIG_CPU_S3C2440)
-+# undef cpu_is_s3c2440
-+# undef cpu_is_s3c2440a
-+# define cpu_is_s3c2440() is_s3c2440()
-+# define cpu_is_s3c2440a() is_s3c2440a()
-+#endif
-+
-+#if defined(CONFIG_CPU_S3C2442)
-+# undef cpu_is_s3c2442
-+# define cpu_is_s3c2442() is_s3c2442()
-+#endif
-+
-+#if defined(CONFIG_CPU_S3C2443)
-+# undef cpu_is_s3c2443
-+# define cpu_is_s3c2443() is_s3c2443()
-+#endif
-+
-+#if defined(CONFIG_ARCH_S3C64XX)
-+# undef cpu_is_s3c6400
-+# undef cpu_is_s3c6410
-+# define cpu_is_s3c6400() is_s3c6400()
-+# define cpu_is_s3c6410() is_s3c6410()
-+#endif
-+
-+#endif
---- a/arch/arm/plat-s3c/include/plat/devs.h
-+++ b/arch/arm/plat-s3c/include/plat/devs.h
-@@ -16,6 +16,10 @@ struct s3c24xx_uart_resources {
- unsigned long nr_resources;
- };
-
-+struct s3c_plat_otg_data {
-+ int phyclk;
-+};
-+
- extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
- extern struct s3c24xx_uart_resources s3c64xx_uart_resources[];
-
---- a/arch/arm/plat-s3c/include/plat/gpio-core.h
-+++ b/arch/arm/plat-s3c/include/plat/gpio-core.h
-@@ -20,6 +20,19 @@
- * specific code.
- */
-
-+struct s3c_gpio_chip;
-+
-+/**
-+ * struct s3c_gpio_pm - power management (suspend/resume) information
-+ * @save: Routine to save the state of the GPIO block
-+ * @resume: Routine to resume the GPIO block.
-+ */
-+struct s3c_gpio_pm {
-+ void (*save)(struct s3c_gpio_chip *chip);
-+ void (*resume)(struct s3c_gpio_chip *chip);
-+};
-+
-+
- struct s3c_gpio_cfg;
-
- /**
-@@ -27,6 +40,7 @@ struct s3c_gpio_cfg;
- * @chip: The chip structure to be exported via gpiolib.
- * @base: The base pointer to the gpio configuration registers.
- * @config: special function and pull-resistor control information.
-+ * @pm_save: Save information for suspend/resume support.
- *
- * This wrapper provides the necessary information for the Samsung
- * specific gpios being registered with gpiolib.
-@@ -34,7 +48,11 @@ struct s3c_gpio_cfg;
- struct s3c_gpio_chip {
- struct gpio_chip chip;
- struct s3c_gpio_cfg *config;
-+ struct s3c_gpio_pm *pm;
- void __iomem *base;
-+#ifdef CONFIG_PM
-+ u32 pm_save[4];
-+#endif
- };
-
- static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
-@@ -75,3 +93,16 @@ static inline struct s3c_gpio_chip *s3c_
-
- static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
- #endif
-+
-+#ifdef CONFIG_PM
-+extern struct s3c_gpio_pm s3c_gpio_pm_1bit;
-+extern struct s3c_gpio_pm s3c_gpio_pm_2bit;
-+extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
-+#define __gpio_pm(x) x
-+#else
-+#define s3c_gpio_pm_1bit NULL
-+#define s3c_gpio_pm_2bit NULL
-+#define s3c_gpio_pm_4bit NULL
-+#define __gpio_pm(x) NULL
-+
-+#endif /* CONFIG_PM */
---- a/arch/arm/plat-s3c/include/plat/map-base.h
-+++ b/arch/arm/plat-s3c/include/plat/map-base.h
-@@ -36,5 +36,7 @@
- #define S3C_VA_TIMER S3C_ADDR(0x00300000) /* timer block */
- #define S3C_VA_WATCHDOG S3C_ADDR(0x00400000) /* watchdog */
- #define S3C_VA_UART S3C_ADDR(0x01000000) /* UART */
-+#define S3C_VA_OTG S3C_ADDR(0x03900000) /* OTG */
-+#define S3C_VA_OTGSFR S3C_ADDR(0x03a00000) /* OTGSFR */
-
- #endif /* __ASM_PLAT_MAP_H */
---- a/arch/arm/plat-s3c/include/plat/nand.h
-+++ b/arch/arm/plat-s3c/include/plat/nand.h
-@@ -21,11 +21,14 @@
- * partitions = mtd partition list
- */
-
-+#define S3C2410_NAND_BBT 0x0001
-+
- struct s3c2410_nand_set {
- unsigned int disable_ecc : 1;
-
- int nr_chips;
- int nr_partitions;
-+ unsigned int flags;
- char *name;
- int *nr_map;
- struct mtd_partition *partitions;
-@@ -44,6 +47,9 @@ struct s3c2410_platform_nand {
- int nr_sets;
- struct s3c2410_nand_set *sets;
-
-+ /* force software_ecc at runtime */
-+ int software_ecc;
-+
- void (*select_chip)(struct s3c2410_nand_set *,
- int chip);
- };
---- a/arch/arm/plat-s3c/include/plat/pm.h
-+++ b/arch/arm/plat-s3c/include/plat/pm.h
-@@ -9,6 +9,8 @@
- * published by the Free Software Foundation.
- */
-
-+#include <linux/sysdev.h>
-+
- /* s3c_pm_init
- *
- * called from board at initialisation time to setup the power
-@@ -44,6 +46,8 @@ extern void (*pm_cpu_sleep)(void);
-
- extern unsigned long s3c_pm_flags;
-
-+extern unsigned char pm_uart_udivslot; /* true to save UART UDIVSLOT */
-+
- /* from sleep.S */
-
- extern int s3c_cpu_save(unsigned long *saveblk);
-@@ -88,6 +92,7 @@ struct pm_uart_save {
- u32 ufcon;
- u32 umcon;
- u32 ubrdiv;
-+ u32 udivslot;
- };
-
- /* helper functions to save/restore lists of registers. */
---- a/arch/arm/plat-s3c/include/plat/sdhci.h
-+++ b/arch/arm/plat-s3c/include/plat/sdhci.h
-@@ -29,6 +29,7 @@ struct mmc_ios;
- * is necessary the controllers and/or GPIO blocks require the
- * changing of driver-strength and other controls dependant on
- * the card and speed of operation.
-+ * sdhci_host: Pointer kept during init, allows presence change notification
- *
- * Initialisation data specific to either the machine or the platform
- * for the device driver to use or call-back when configuring gpio or
-@@ -45,8 +46,11 @@ struct s3c_sdhci_platdata {
- void __iomem *regbase,
- struct mmc_ios *ios,
- struct mmc_card *card);
-+ struct sdhci_host * sdhci_host;
- };
-
-+extern void sdhci_s3c_force_presence_change(struct platform_device *pdev);
-+
- /**
- * s3c_sdhci0_set_platdata - Set platform data for S3C SDHCI device.
- * @pd: Platform data to register to device.
---- a/arch/arm/plat-s3c/init.c
-+++ b/arch/arm/plat-s3c/init.c
-@@ -31,6 +31,34 @@
-
- static struct cpu_table *cpu;
-
-+static void __init set_system_rev(unsigned int idcode)
-+{
-+ /*
-+ * system_rev encoding is as follows
-+ * system_rev & 0xff000000 -> S3C Class (24xx/64xx)
-+ * system_rev & 0xfff00000 -> S3C Sub Class (241x/244x)
-+ * system_rev & 0xffff0000 -> S3C Type (2410/2440/6400/6410)
-+ *
-+ * Remaining[15:0] are preserved from the value set by ATAG
-+ *
-+ * Exception:
-+ * Store Revision A to 1 such as
-+ * s3c2410A to s3c2411
-+ * s3c2440A to s3c2441
-+ */
-+
-+ system_rev &= 0xffff;
-+ system_rev |= (idcode & 0x0ffff000) << 4;
-+
-+ if (idcode == 0x32410002 || idcode == 0x32440001)
-+ system_rev |= (0x1 << 16);
-+ if (idcode == 0x32440aaa /* s3c2442 */
-+ || idcode == 0x32440aab) /* s3c2442b */
-+ system_rev |= (0x2 << 16);
-+ if (idcode == 0x0) /* s3c2400 */
-+ system_rev |= (0x2400 << 16);
-+}
-+
- static struct cpu_table * __init s3c_lookup_cpu(unsigned long idcode,
- struct cpu_table *tab,
- unsigned int count)
-@@ -53,6 +81,8 @@ void __init s3c_init_cpu(unsigned long i
- panic("Unknown S3C24XX CPU");
- }
-
-+ set_system_rev(idcode);
-+
- printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
-
- if (cpu->map_io == NULL || cpu->init == NULL) {
---- a/arch/arm/plat-s3c/Makefile
-+++ b/arch/arm/plat-s3c/Makefile
-@@ -21,6 +21,7 @@ obj-y += gpio-config.o
- # PM support
-
- obj-$(CONFIG_PM) += pm.o
-+obj-$(CONFIG_PM) += pm-gpio.o
- obj-$(CONFIG_S3C2410_PM_CHECK) += pm-check.o
-
- # devices
---- a/arch/arm/plat-s3c/pm.c
-+++ b/arch/arm/plat-s3c/pm.c
-@@ -21,11 +21,10 @@
-
- #include <asm/cacheflush.h>
- #include <mach/hardware.h>
-+#include <mach/map.h>
-
- #include <plat/regs-serial.h>
- #include <mach/regs-clock.h>
--#include <mach/regs-gpio.h>
--#include <mach/regs-mem.h>
- #include <mach/regs-irq.h>
- #include <asm/irq.h>
-
-@@ -70,6 +69,8 @@ static inline void s3c_pm_debug_init(voi
-
- /* Save the UART configurations if we are configured for debug. */
-
-+unsigned char pm_uart_udivslot;
-+
- #ifdef CONFIG_S3C2410_PM_DEBUG
-
- struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
-@@ -83,6 +84,12 @@ static void s3c_pm_save_uart(unsigned in
- save->ufcon = __raw_readl(regs + S3C2410_UFCON);
- save->umcon = __raw_readl(regs + S3C2410_UMCON);
- save->ubrdiv = __raw_readl(regs + S3C2410_UBRDIV);
-+
-+ if (pm_uart_udivslot)
-+ save->udivslot = __raw_readl(regs + S3C2443_DIVSLOT);
-+
-+ S3C_PMDBG("UART[%d]: ULCON=%04x, UCON=%04x, UFCON=%04x, UBRDIV=%04x\n",
-+ uart, save->ulcon, save->ucon, save->ufcon, save->ubrdiv);
- }
-
- static void s3c_pm_save_uarts(void)
-@@ -98,11 +105,16 @@ static void s3c_pm_restore_uart(unsigned
- {
- void __iomem *regs = S3C_VA_UARTx(uart);
-
-+ s3c_pm_arch_update_uart(regs, save);
-+
- __raw_writel(save->ulcon, regs + S3C2410_ULCON);
- __raw_writel(save->ucon, regs + S3C2410_UCON);
- __raw_writel(save->ufcon, regs + S3C2410_UFCON);
- __raw_writel(save->umcon, regs + S3C2410_UMCON);
- __raw_writel(save->ubrdiv, regs + S3C2410_UBRDIV);
-+
-+ if (pm_uart_udivslot)
-+ __raw_writel(save->udivslot, regs + S3C2443_DIVSLOT);
- }
-
- static void s3c_pm_restore_uarts(void)
-@@ -289,11 +301,14 @@ static int s3c_pm_enter(suspend_state_t
-
- s3c_pm_arch_stop_clocks();
-
-- /* s3c_cpu_save will also act as our return point from when
-- * we resume as it saves its own register state and restores it
-- * during the resume. */
--
-- s3c_cpu_save(regs_save);
-+ /* s3c2410_cpu_save will also act as our return point from when
-+ * we resume as it saves its own register state, so use the return
-+ * code to differentiate return from save and return from sleep */
-+
-+ if (s3c_cpu_save(regs_save) == 0) {
-+ flush_cache_all();
-+ pm_cpu_sleep();
-+ }
-
- /* restore the cpu state using the kernel's cpu init code. */
-
---- /dev/null
-+++ b/arch/arm/plat-s3c/pm-gpio.c
-@@ -0,0 +1,378 @@
-+/* linux/arch/arm/plat-s3c/pm-gpio.c
-+ *
-+ * Copyright 2008 Openmoko, Inc.
-+ * Copyright 2008 Simtec Electronics
-+ * Ben Dooks <ben@simtec.co.uk>
-+ * http://armlinux.simtec.co.uk/
-+ *
-+ * S3C series GPIO PM code
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+*/
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/io.h>
-+#include <linux/gpio.h>
-+
-+#include <mach/gpio-core.h>
-+#include <plat/pm.h>
-+
-+/* PM GPIO helpers */
-+
-+#define OFFS_CON (0x00)
-+#define OFFS_DAT (0X04)
-+#define OFFS_UP (0X08)
-+
-+static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip)
-+{
-+ chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
-+ chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
-+}
-+
-+static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
-+{
-+ void __iomem *base = chip->base;
-+ u32 old_gpcon = __raw_readl(base + OFFS_CON);
-+ u32 old_gpdat = __raw_readl(base + OFFS_DAT);
-+ u32 gps_gpcon = chip->pm_save[0];
-+ u32 gps_gpdat = chip->pm_save[1];
-+ u32 gpcon;
-+
-+ /* GPACON only has one bit per control / data and no PULLUPs.
-+ * GPACON[x] = 0 => Output, 1 => SFN */
-+
-+ /* first set all SFN bits to SFN */
-+
-+ gpcon = old_gpcon | gps_gpcon;
-+ __raw_writel(gpcon, base + OFFS_CON);
-+
-+ /* now set all the other bits */
-+
-+ __raw_writel(gps_gpdat, base + OFFS_DAT);
-+ __raw_writel(gps_gpcon, base + OFFS_CON);
-+
-+ S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
-+ chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
-+}
-+
-+struct s3c_gpio_pm s3c_gpio_pm_1bit = {
-+ .save = s3c_gpio_pm_1bit_save,
-+ .resume = s3c_gpio_pm_1bit_resume,
-+};
-+
-+static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip)
-+{
-+ chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
-+ chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
-+ chip->pm_save[2] = __raw_readl(chip->base + OFFS_UP);
-+}
-+
-+/* Test whether the given masked+shifted bits of an GPIO configuration
-+ * are one of the SFN (special function) modes. */
-+
-+static inline int is_sfn(unsigned long con)
-+{
-+ return con >= 2;
-+}
-+
-+/* Test if the given masked+shifted GPIO configuration is an input */
-+
-+static inline int is_in(unsigned long con)
-+{
-+ return con == 0;
-+}
-+
-+/* Test if the given masked+shifted GPIO configuration is an output */
-+
-+static inline int is_out(unsigned long con)
-+{
-+ return con == 1;
-+}
-+
-+/**
-+ * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank
-+ * @chip: The chip information to resume.
-+ *
-+ * Restore one of the GPIO banks that was saved during suspend. This is
-+ * not as simple as once thought, due to the possibility of glitches
-+ * from the order that the CON and DAT registers are set in.
-+ *
-+ * The three states the pin can be are {IN,OUT,SFN} which gives us 9
-+ * combinations of changes to check. Three of these, if the pin stays
-+ * in the same configuration can be discounted. This leaves us with
-+ * the following:
-+ *
-+ * { IN => OUT } Change DAT first
-+ * { IN => SFN } Change CON first
-+ * { OUT => SFN } Change CON first, so new data will not glitch
-+ * { OUT => IN } Change CON first, so new data will not glitch
-+ * { SFN => IN } Change CON first
-+ * { SFN => OUT } Change DAT first, so new data will not glitch [1]
-+ *
-+ * We do not currently deal with the UP registers as these control
-+ * weak resistors, so a small delay in change should not need to bring
-+ * these into the calculations.
-+ *
-+ * [1] this assumes that writing to a pin DAT whilst in SFN will set the
-+ * state for when it is next output.
-+ */
-+static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
-+{
-+ void __iomem *base = chip->base;
-+ u32 old_gpcon = __raw_readl(base + OFFS_CON);
-+ u32 old_gpdat = __raw_readl(base + OFFS_DAT);
-+ u32 gps_gpcon = chip->pm_save[0];
-+ u32 gps_gpdat = chip->pm_save[1];
-+ u32 gpcon, old, new, mask;
-+ u32 change_mask = 0x0;
-+ int nr;
-+
-+ /* restore GPIO pull-up settings */
-+ __raw_writel(chip->pm_save[2], base + OFFS_UP);
-+
-+ /* Create a change_mask of all the items that need to have
-+ * their CON value changed before their DAT value, so that
-+ * we minimise the work between the two settings.
-+ */
-+
-+ for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
-+ old = (old_gpcon & mask) >> nr;
-+ new = (gps_gpcon & mask) >> nr;
-+
-+ /* If there is no change, then skip */
-+
-+ if (old == new)
-+ continue;
-+
-+ /* If both are special function, then skip */
-+
-+ if (is_sfn(old) && is_sfn(new))
-+ continue;
-+
-+ /* Change is IN => OUT, do not change now */
-+
-+ if (is_in(old) && is_out(new))
-+ continue;
-+
-+ /* Change is SFN => OUT, do not change now */
-+
-+ if (is_sfn(old) && is_out(new))
-+ continue;
-+
-+ /* We should now be at the case of IN=>SFN,
-+ * OUT=>SFN, OUT=>IN, SFN=>IN. */
-+
-+ change_mask |= mask;
-+ }
-+
-+
-+ /* Write the new CON settings */
-+
-+ gpcon = old_gpcon & ~change_mask;
-+ gpcon |= gps_gpcon & change_mask;
-+
-+ __raw_writel(gpcon, base + OFFS_CON);
-+
-+ /* Now change any items that require DAT,CON */
-+
-+ __raw_writel(gps_gpdat, base + OFFS_DAT);
-+ __raw_writel(gps_gpcon, base + OFFS_CON);
-+
-+ S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
-+ chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
-+}
-+
-+struct s3c_gpio_pm s3c_gpio_pm_2bit = {
-+ .save = s3c_gpio_pm_2bit_save,
-+ .resume = s3c_gpio_pm_2bit_resume,
-+};
-+
-+#ifdef CONFIG_ARCH_S3C64XX
-+static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
-+{
-+ chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
-+ chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
-+ chip->pm_save[3] = __raw_readl(chip->base + OFFS_UP);
-+
-+ if (chip->chip.ngpio > 8)
-+ chip->pm_save[0] = __raw_readl(chip->base - 4);
-+}
-+
-+static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
-+{
-+ u32 old, new, mask;
-+ u32 change_mask = 0x0;
-+ int nr;
-+
-+ for (nr = 0, mask = 0x0f; nr < 16; nr += 4, mask <<= 4) {
-+ old = (old_gpcon & mask) >> nr;
-+ new = (gps_gpcon & mask) >> nr;
-+
-+ /* If there is no change, then skip */
-+
-+ if (old == new)
-+ continue;
-+
-+ /* If both are special function, then skip */
-+
-+ if (is_sfn(old) && is_sfn(new))
-+ continue;
-+
-+ /* Change is IN => OUT, do not change now */
-+
-+ if (is_in(old) && is_out(new))
-+ continue;
-+
-+ /* Change is SFN => OUT, do not change now */
-+
-+ if (is_sfn(old) && is_out(new))
-+ continue;
-+
-+ /* We should now be at the case of IN=>SFN,
-+ * OUT=>SFN, OUT=>IN, SFN=>IN. */
-+
-+ change_mask |= mask;
-+ }
-+
-+ return change_mask;
-+}
-+
-+static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
-+{
-+ void __iomem *con = chip->base + (index * 4);
-+ u32 old_gpcon = __raw_readl(con);
-+ u32 gps_gpcon = chip->pm_save[index + 1];
-+ u32 gpcon, mask;
-+
-+ mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
-+
-+ gpcon = old_gpcon & ~mask;
-+ gpcon |= gps_gpcon & mask;
-+
-+ __raw_writel(gpcon, con);
-+}
-+
-+static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
-+{
-+ void __iomem *base = chip->base;
-+ u32 old_gpcon[2];
-+ u32 old_gpdat = __raw_readl(base + OFFS_DAT);
-+ u32 gps_gpdat = chip->pm_save[2];
-+
-+ /* First, modify the CON settings */
-+
-+ old_gpcon[0] = 0;
-+ old_gpcon[1] = __raw_readl(base + OFFS_CON);
-+
-+ s3c_gpio_pm_4bit_con(chip, 0);
-+ if (chip->chip.ngpio > 8) {
-+ old_gpcon[0] = __raw_readl(base - 4);
-+ s3c_gpio_pm_4bit_con(chip, -1);
-+ }
-+
-+ /* Now change the configurations that require DAT,CON */
-+
-+ __raw_writel(chip->pm_save[2], base + OFFS_DAT);
-+ __raw_writel(chip->pm_save[1], base + OFFS_CON);
-+ if (chip->chip.ngpio > 8)
-+ __raw_writel(chip->pm_save[0], base - 4);
-+
-+ __raw_writel(chip->pm_save[2], base + OFFS_DAT);
-+ __raw_writel(chip->pm_save[3], base + OFFS_UP);
-+
-+ if (chip->chip.ngpio > 8) {
-+ S3C_PMDBG("%s: CON4 %08x,%08x => %08x,%08x, DAT %08x => %08x\n",
-+ chip->chip.label, old_gpcon[0], old_gpcon[1],
-+ __raw_readl(base - 4),
-+ __raw_readl(base + OFFS_CON),
-+ old_gpdat, gps_gpdat);
-+ } else
-+ S3C_PMDBG("%s: CON4 %08x => %08x, DAT %08x => %08x\n",
-+ chip->chip.label, old_gpcon[1],
-+ __raw_readl(base + OFFS_CON),
-+ old_gpdat, gps_gpdat);
-+}
-+
-+struct s3c_gpio_pm s3c_gpio_pm_4bit = {
-+ .save = s3c_gpio_pm_4bit_save,
-+ .resume = s3c_gpio_pm_4bit_resume,
-+};
-+#endif /* CONFIG_ARCH_S3C64XX */
-+
-+/**
-+ * s3c_pm_save_gpio() - save gpio chip data for suspend
-+ * @ourchip: The chip for suspend.
-+ */
-+static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip)
-+{
-+ struct s3c_gpio_pm *pm = ourchip->pm;
-+
-+ if (pm == NULL || pm->save == NULL)
-+ S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
-+ else
-+ pm->save(ourchip);
-+}
-+
-+/**
-+ * s3c_pm_save_gpios() - Save the state of the GPIO banks.
-+ *
-+ * For all the GPIO banks, save the state of each one ready for going
-+ * into a suspend mode.
-+ */
-+void s3c_pm_save_gpios(void)
-+{
-+ struct s3c_gpio_chip *ourchip;
-+ unsigned int gpio_nr;
-+
-+ for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
-+ ourchip = s3c_gpiolib_getchip(gpio_nr);
-+ if (!ourchip)
-+ continue;
-+
-+ s3c_pm_save_gpio(ourchip);
-+
-+ S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
-+ ourchip->chip.label,
-+ ourchip->pm_save[0],
-+ ourchip->pm_save[1],
-+ ourchip->pm_save[2],
-+ ourchip->pm_save[3]);
-+
-+ gpio_nr += ourchip->chip.ngpio;
-+ gpio_nr += CONFIG_S3C_GPIO_SPACE;
-+ }
-+}
-+
-+/**
-+ * s3c_pm_resume_gpio() - restore gpio chip data after suspend
-+ * @ourchip: The suspended chip.
-+ */
-+static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
-+{
-+ struct s3c_gpio_pm *pm = ourchip->pm;
-+
-+ if (pm == NULL || pm->resume == NULL)
-+ S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
-+ else
-+ pm->resume(ourchip);
-+}
-+
-+void s3c_pm_restore_gpios(void)
-+{
-+ struct s3c_gpio_chip *ourchip;
-+ unsigned int gpio_nr;
-+
-+ for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
-+ ourchip = s3c_gpiolib_getchip(gpio_nr);
-+ if (!ourchip)
-+ continue;
-+
-+ s3c_pm_resume_gpio(ourchip);
-+
-+ gpio_nr += ourchip->chip.ngpio;
-+ gpio_nr += CONFIG_S3C_GPIO_SPACE;
-+ }
-+}
---- a/arch/arm/plat-s3c24xx/clock-dclk.c
-+++ b/arch/arm/plat-s3c24xx/clock-dclk.c
-@@ -18,6 +18,7 @@
-
- #include <mach/regs-clock.h>
- #include <mach/regs-gpio.h>
-+#include <mach/hardware.h>
-
- #include <plat/clock.h>
- #include <plat/cpu.h>
---- a/arch/arm/plat-s3c24xx/cpu.c
-+++ b/arch/arm/plat-s3c24xx/cpu.c
-@@ -61,6 +61,7 @@ static const char name_s3c2410[] = "S3C
- static const char name_s3c2412[] = "S3C2412";
- static const char name_s3c2440[] = "S3C2440";
- static const char name_s3c2442[] = "S3C2442";
-+static const char name_s3c2442b[] = "S3C2442B";
- static const char name_s3c2443[] = "S3C2443";
- static const char name_s3c2410a[] = "S3C2410A";
- static const char name_s3c2440a[] = "S3C2440A";
-@@ -112,6 +113,15 @@ static struct cpu_table cpu_ids[] __init
- .name = name_s3c2442
- },
- {
-+ .idcode = 0x32440aab,
-+ .idmask = 0xffffffff,
-+ .map_io = s3c244x_map_io,
-+ .init_clocks = s3c244x_init_clocks,
-+ .init_uarts = s3c244x_init_uarts,
-+ .init = s3c2442_init,
-+ .name = name_s3c2442b
-+ },
-+ {
- .idcode = 0x32412001,
- .idmask = 0xffffffff,
- .map_io = s3c2412_map_io,
---- a/arch/arm/plat-s3c24xx/gpiolib.c
-+++ b/arch/arm/plat-s3c24xx/gpiolib.c
-@@ -19,9 +19,10 @@
- #include <linux/io.h>
- #include <linux/gpio.h>
-
--#include <mach/gpio-core.h>
-+#include <plat/gpio-core.h>
- #include <mach/hardware.h>
- #include <asm/irq.h>
-+#include <plat/pm.h>
-
- #include <mach/regs-gpio.h>
-
-@@ -78,6 +79,7 @@ static int s3c24xx_gpiolib_bankg_toirq(s
- struct s3c_gpio_chip s3c24xx_gpios[] = {
- [0] = {
- .base = S3C24XX_GPIO_BASE(S3C2410_GPA0),
-+ .pm = __gpio_pm(&s3c_gpio_pm_1bit),
- .chip = {
- .base = S3C2410_GPA0,
- .owner = THIS_MODULE,
-@@ -89,6 +91,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
- },
- [1] = {
- .base = S3C24XX_GPIO_BASE(S3C2410_GPB0),
-+ .pm = __gpio_pm(&s3c_gpio_pm_2bit),
- .chip = {
- .base = S3C2410_GPB0,
- .owner = THIS_MODULE,
-@@ -98,6 +101,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
- },
- [2] = {
- .base = S3C24XX_GPIO_BASE(S3C2410_GPC0),
-+ .pm = __gpio_pm(&s3c_gpio_pm_2bit),
- .chip = {
- .base = S3C2410_GPC0,
- .owner = THIS_MODULE,
-@@ -107,6 +111,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
- },
- [3] = {
- .base = S3C24XX_GPIO_BASE(S3C2410_GPD0),
-+ .pm = __gpio_pm(&s3c_gpio_pm_2bit),
- .chip = {
- .base = S3C2410_GPD0,
- .owner = THIS_MODULE,
-@@ -116,6 +121,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
- },
- [4] = {
- .base = S3C24XX_GPIO_BASE(S3C2410_GPE0),
-+ .pm = __gpio_pm(&s3c_gpio_pm_2bit),
- .chip = {
- .base = S3C2410_GPE0,
- .label = "GPIOE",
-@@ -125,6 +131,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
- },
- [5] = {
- .base = S3C24XX_GPIO_BASE(S3C2410_GPF0),
-+ .pm = __gpio_pm(&s3c_gpio_pm_2bit),
- .chip = {
- .base = S3C2410_GPF0,
- .owner = THIS_MODULE,
-@@ -135,12 +142,23 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
- },
- [6] = {
- .base = S3C24XX_GPIO_BASE(S3C2410_GPG0),
-+ .pm = __gpio_pm(&s3c_gpio_pm_2bit),
- .chip = {
- .base = S3C2410_GPG0,
- .owner = THIS_MODULE,
- .label = "GPIOG",
-- .ngpio = 10,
- .to_irq = s3c24xx_gpiolib_bankg_toirq,
-+ .ngpio = 16,
-+ },
-+ },
-+ [7] = {
-+ .base = S3C24XX_GPIO_BASE(S3C2410_GPH0),
-+ .pm = __gpio_pm(&s3c_gpio_pm_2bit),
-+ .chip = {
-+ .base = S3C2410_GPH0,
-+ .owner = THIS_MODULE,
-+ .label = "GPIOH",
-+ .ngpio = 11,
- },
- },
- };
---- a/arch/arm/plat-s3c24xx/include/plat/pm-core.h
-+++ b/arch/arm/plat-s3c24xx/include/plat/pm-core.h
-@@ -57,3 +57,8 @@ static inline void s3c_pm_arch_show_resu
- s3c_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
- s3c_irqwake_eintmask);
- }
-+
-+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
-+ struct pm_uart_save *save)
-+{
-+}
---- a/arch/arm/plat-s3c24xx/irq-pm.c
-+++ b/arch/arm/plat-s3c24xx/irq-pm.c
-@@ -15,6 +15,7 @@
- #include <linux/module.h>
- #include <linux/interrupt.h>
- #include <linux/sysdev.h>
-+#include <linux/irq.h>
-
- #include <plat/cpu.h>
- #include <plat/pm.h>
-@@ -80,7 +81,9 @@ int s3c24xx_irq_suspend(struct sys_devic
-
- int s3c24xx_irq_resume(struct sys_device *dev)
- {
-- unsigned int i;
-+ unsigned int i, irq;
-+ unsigned long eintpnd;
-+ struct irq_desc *desc;
-
- for (i = 0; i < ARRAY_SIZE(save_extint); i++)
- __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
-@@ -91,5 +94,25 @@ int s3c24xx_irq_resume(struct sys_device
- s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
- __raw_writel(save_eintmask, S3C24XX_EINTMASK);
-
-+ /*
-+ * ACK those interrupts which are now masked and pending.
-+ * Level interrupts if not ACKed here, create an interrupt storm
-+ * because they are not handled at all.
-+ */
-+
-+ eintpnd = __raw_readl(S3C24XX_EINTPEND);
-+
-+ eintpnd &= save_eintmask;
-+ eintpnd &= ~0xff; /* ignore lower irqs */
-+
-+ while (eintpnd) {
-+ irq = __ffs(eintpnd);
-+ eintpnd &= ~(1 << irq);
-+
-+ irq += (IRQ_EINT4 - 4);
-+ desc = irq_to_desc(irq);
-+ desc->chip->ack(irq);
-+ }
-+
- return 0;
- }
---- a/arch/arm/plat-s3c24xx/pm.c
-+++ b/arch/arm/plat-s3c24xx/pm.c
-@@ -39,6 +39,7 @@
- #include <mach/regs-gpio.h>
- #include <mach/regs-mem.h>
- #include <mach/regs-irq.h>
-+#include <mach/hardware.h>
-
- #include <asm/mach/time.h>
-
-@@ -75,43 +76,10 @@ static struct sleep_save core_save[] = {
- SAVE_ITEM(S3C2410_CLKSLOW),
- };
-
--static struct gpio_sleep {
-- void __iomem *base;
-- unsigned int gpcon;
-- unsigned int gpdat;
-- unsigned int gpup;
--} gpio_save[] = {
-- [0] = {
-- .base = S3C2410_GPACON,
-- },
-- [1] = {
-- .base = S3C2410_GPBCON,
-- },
-- [2] = {
-- .base = S3C2410_GPCCON,
-- },
-- [3] = {
-- .base = S3C2410_GPDCON,
-- },
-- [4] = {
-- .base = S3C2410_GPECON,
-- },
-- [5] = {
-- .base = S3C2410_GPFCON,
-- },
-- [6] = {
-- .base = S3C2410_GPGCON,
-- },
-- [7] = {
-- .base = S3C2410_GPHCON,
-- },
--};
--
- static struct sleep_save misc_save[] = {
- SAVE_ITEM(S3C2410_DCLKCON),
- };
-
--
- /* s3c_pm_check_resume_pin
- *
- * check to see if the pin is configured correctly for sleep mode, and
-@@ -165,186 +133,6 @@ void s3c_pm_configure_extint(void)
- }
- }
-
--/* offsets for CON/DAT/UP registers */
--
--#define OFFS_CON (S3C2410_GPACON - S3C2410_GPACON)
--#define OFFS_DAT (S3C2410_GPADAT - S3C2410_GPACON)
--#define OFFS_UP (S3C2410_GPBUP - S3C2410_GPBCON)
--
--/* s3c_pm_save_gpios()
-- *
-- * Save the state of the GPIOs
-- */
--
--void s3c_pm_save_gpios(void)
--{
-- struct gpio_sleep *gps = gpio_save;
-- unsigned int gpio;
--
-- for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
-- void __iomem *base = gps->base;
--
-- gps->gpcon = __raw_readl(base + OFFS_CON);
-- gps->gpdat = __raw_readl(base + OFFS_DAT);
--
-- if (gpio > 0)
-- gps->gpup = __raw_readl(base + OFFS_UP);
--
-- }
--}
--
--/* Test whether the given masked+shifted bits of an GPIO configuration
-- * are one of the SFN (special function) modes. */
--
--static inline int is_sfn(unsigned long con)
--{
-- return (con == 2 || con == 3);
--}
--
--/* Test if the given masked+shifted GPIO configuration is an input */
--
--static inline int is_in(unsigned long con)
--{
-- return con == 0;
--}
--
--/* Test if the given masked+shifted GPIO configuration is an output */
--
--static inline int is_out(unsigned long con)
--{
-- return con == 1;
--}
--
--/**
-- * s3c2410_pm_restore_gpio() - restore the given GPIO bank
-- * @index: The number of the GPIO bank being resumed.
-- * @gps: The sleep confgiuration for the bank.
-- *
-- * Restore one of the GPIO banks that was saved during suspend. This is
-- * not as simple as once thought, due to the possibility of glitches
-- * from the order that the CON and DAT registers are set in.
-- *
-- * The three states the pin can be are {IN,OUT,SFN} which gives us 9
-- * combinations of changes to check. Three of these, if the pin stays
-- * in the same configuration can be discounted. This leaves us with
-- * the following:
-- *
-- * { IN => OUT } Change DAT first
-- * { IN => SFN } Change CON first
-- * { OUT => SFN } Change CON first, so new data will not glitch
-- * { OUT => IN } Change CON first, so new data will not glitch
-- * { SFN => IN } Change CON first
-- * { SFN => OUT } Change DAT first, so new data will not glitch [1]
-- *
-- * We do not currently deal with the UP registers as these control
-- * weak resistors, so a small delay in change should not need to bring
-- * these into the calculations.
-- *
-- * [1] this assumes that writing to a pin DAT whilst in SFN will set the
-- * state for when it is next output.
-- */
--
--static void s3c2410_pm_restore_gpio(int index, struct gpio_sleep *gps)
--{
-- void __iomem *base = gps->base;
-- unsigned long gps_gpcon = gps->gpcon;
-- unsigned long gps_gpdat = gps->gpdat;
-- unsigned long old_gpcon;
-- unsigned long old_gpdat;
-- unsigned long old_gpup = 0x0;
-- unsigned long gpcon;
-- int nr;
--
-- old_gpcon = __raw_readl(base + OFFS_CON);
-- old_gpdat = __raw_readl(base + OFFS_DAT);
--
-- if (base == S3C2410_GPACON) {
-- /* GPACON only has one bit per control / data and no PULLUPs.
-- * GPACON[x] = 0 => Output, 1 => SFN */
--
-- /* first set all SFN bits to SFN */
--
-- gpcon = old_gpcon | gps->gpcon;
-- __raw_writel(gpcon, base + OFFS_CON);
--
-- /* now set all the other bits */
--
-- __raw_writel(gps_gpdat, base + OFFS_DAT);
-- __raw_writel(gps_gpcon, base + OFFS_CON);
-- } else {
-- unsigned long old, new, mask;
-- unsigned long change_mask = 0x0;
--
-- old_gpup = __raw_readl(base + OFFS_UP);
--
-- /* Create a change_mask of all the items that need to have
-- * their CON value changed before their DAT value, so that
-- * we minimise the work between the two settings.
-- */
--
-- for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
-- old = (old_gpcon & mask) >> nr;
-- new = (gps_gpcon & mask) >> nr;
--
-- /* If there is no change, then skip */
--
-- if (old == new)
-- continue;
--
-- /* If both are special function, then skip */
--
-- if (is_sfn(old) && is_sfn(new))
-- continue;
--
-- /* Change is IN => OUT, do not change now */
--
-- if (is_in(old) && is_out(new))
-- continue;
--
-- /* Change is SFN => OUT, do not change now */
--
-- if (is_sfn(old) && is_out(new))
-- continue;
--
-- /* We should now be at the case of IN=>SFN,
-- * OUT=>SFN, OUT=>IN, SFN=>IN. */
--
-- change_mask |= mask;
-- }
--
-- /* Write the new CON settings */
--
-- gpcon = old_gpcon & ~change_mask;
-- gpcon |= gps_gpcon & change_mask;
--
-- __raw_writel(gpcon, base + OFFS_CON);
--
-- /* Now change any items that require DAT,CON */
--
-- __raw_writel(gps_gpdat, base + OFFS_DAT);
-- __raw_writel(gps_gpcon, base + OFFS_CON);
-- __raw_writel(gps->gpup, base + OFFS_UP);
-- }
--
-- S3C_PMDBG("GPIO[%d] CON %08lx => %08lx, DAT %08lx => %08lx\n",
-- index, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
--}
--
--
--/** s3c2410_pm_restore_gpios()
-- *
-- * Restore the state of the GPIOs
-- */
--
--void s3c_pm_restore_gpios(void)
--{
-- struct gpio_sleep *gps = gpio_save;
-- int gpio;
--
-- for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
-- s3c2410_pm_restore_gpio(gpio, gps);
-- }
--}
-
- void s3c_pm_restore_core(void)
- {
---- a/drivers/mmc/host/Kconfig
-+++ b/drivers/mmc/host/Kconfig
-@@ -37,13 +37,6 @@ config MMC_SDHCI
-
- If unsure, say N.
-
--config MMC_SDHCI_IO_ACCESSORS
-- bool
-- depends on MMC_SDHCI
-- help
-- This is silent Kconfig symbol that is selected by the drivers that
-- need to overwrite SDHCI IO memory accessors.
--
- config MMC_SDHCI_PCI
- tristate "SDHCI support on PCI bus"
- depends on MMC_SDHCI && PCI
-@@ -55,6 +48,18 @@ config MMC_SDHCI_PCI
-
- If unsure, say N.
-
-+config MMC_SDHCI_S3C
-+ tristate "SDHCI support on Samsung S3C SoC"
-+ depends on MMC_SDHCI && PLAT_S3C24XX
-+ help
-+ This selects the Secure Digital Host Controller Interface (SDHCI)
-+ often referrered to as the HSMMC block in some of the Samsung S3C
-+ range of SoC.
-+
-+ If you have a controller with this interface, say Y or M here.
-+
-+ If unsure, say N.
-+
- config MMC_RICOH_MMC
- tristate "Ricoh MMC Controller Disabler (EXPERIMENTAL)"
- depends on MMC_SDHCI_PCI
-@@ -72,17 +77,6 @@ config MMC_RICOH_MMC
-
- If unsure, say Y.
-
--config MMC_SDHCI_OF
-- tristate "SDHCI support on OpenFirmware platforms"
-- depends on MMC_SDHCI && PPC_OF
-- select MMC_SDHCI_IO_ACCESSORS
-- help
-- This selects the OF support for Secure Digital Host Controller
-- Interfaces. So far, only the Freescale eSDHC controller is known
-- to exist on OF platforms.
--
-- If unsure, say N.
--
- config MMC_OMAP
- tristate "TI OMAP Multimedia Card Interface support"
- depends on ARCH_OMAP
-@@ -163,16 +157,6 @@ config MMC_IMX
-
- If unsure, say N.
-
--config MMC_MXC
-- tristate "Freescale i.MX2/3 Multimedia Card Interface support"
-- depends on ARCH_MXC
-- help
-- This selects the Freescale i.MX2/3 Multimedia card Interface.
-- If you have a i.MX platform with a Multimedia Card slot,
-- say Y or M here.
--
-- If unsure, say N.
--
- config MMC_TIFM_SD
- tristate "TI Flash Media MMC/SD Interface support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && PCI
---- a/drivers/mmc/host/Makefile
-+++ b/drivers/mmc/host/Makefile
-@@ -9,11 +9,10 @@ endif
- obj-$(CONFIG_MMC_ARMMMCI) += mmci.o
- obj-$(CONFIG_MMC_PXA) += pxamci.o
- obj-$(CONFIG_MMC_IMX) += imxmmc.o
--obj-$(CONFIG_MMC_MXC) += mxcmmc.o
- obj-$(CONFIG_MMC_SDHCI) += sdhci.o
- obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
-+obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
- obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o
--obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o
- obj-$(CONFIG_MMC_WBSD) += wbsd.o
- obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
- obj-$(CONFIG_MMC_OMAP) += omap.o
-@@ -21,7 +20,6 @@ obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.
- obj-$(CONFIG_MMC_AT91) += at91_mci.o
- obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o
- obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o
--obj-$(CONFIG_MMC_MVSDIO) += mvsdio.o
- obj-$(CONFIG_MMC_SPI) += mmc_spi.o
- ifeq ($(CONFIG_OF),y)
- obj-$(CONFIG_MMC_SPI) += of_mmc_spi.o
---- a/drivers/mmc/host/s3cmci.c
-+++ b/drivers/mmc/host/s3cmci.c
-@@ -2,6 +2,7 @@
- * linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver
- *
- * Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de>
-+ * Copyright (C) 2007 Harald Welte <laforge@gnumonks.org>
- *
- * Current driver maintained by Ben Dooks and Simtec Electronics
- * Copyright (C) 2008 Simtec Electronics <ben-linux@fluff.org>
-@@ -24,9 +25,18 @@
-
- #include <mach/regs-sdi.h>
- #include <mach/regs-gpio.h>
-+#include <mach/hardware.h>
-
- #include <plat/mci.h>
-
-+#include <asm/dma.h>
-+#include <asm/dma-mapping.h>
-+
-+#include <asm/io.h>
-+#include <mach/regs-gpio.h>
-+#include <mach/mci.h>
-+#include <mach/dma.h>
-+
- #include "s3cmci.h"
-
- #define DRIVER_NAME "s3c-mci"
-@@ -47,6 +57,9 @@ static const int dbgmap_err = dbg_fail
- static const int dbgmap_info = dbg_info | dbg_conf;
- static const int dbgmap_debug = dbg_err | dbg_debug;
-
-+static int f_max = -1; /* override maximum frequency limit */
-+static int persist; /* keep interface alive across suspend/resume */
-+
- #define dbg(host, channels, args...) \
- do { \
- if (dbgmap_err & channels) \
-@@ -280,8 +293,11 @@ static void do_pio_read(struct s3cmci_ho
- * an even multiple of 4. */
- if (fifo >= host->pio_bytes)
- fifo = host->pio_bytes;
-- else
-+ else {
- fifo -= fifo & 3;
-+ if (!fifo)
-+ break;
-+ }
-
- host->pio_bytes -= fifo;
- host->pio_count += fifo;
-@@ -329,7 +345,7 @@ static void do_pio_write(struct s3cmci_h
-
- to_ptr = host->base + host->sdidata;
-
-- while ((fifo = fifo_free(host)) > 3) {
-+ while ((fifo = fifo_free(host))) {
- if (!host->pio_bytes) {
- res = get_data_buffer(host, &host->pio_bytes,
- &host->pio_ptr);
-@@ -353,8 +369,11 @@ static void do_pio_write(struct s3cmci_h
- * words, so round down to an even multiple of 4. */
- if (fifo >= host->pio_bytes)
- fifo = host->pio_bytes;
-- else
-+ else {
- fifo -= fifo & 3;
-+ if (!fifo)
-+ break;
-+ }
-
- host->pio_bytes -= fifo;
- host->pio_count += fifo;
-@@ -373,7 +392,6 @@ static void pio_tasklet(unsigned long da
- {
- struct s3cmci_host *host = (struct s3cmci_host *) data;
-
--
- disable_irq(host->irq);
-
- if (host->pio_active == XFER_WRITE)
-@@ -614,7 +632,6 @@ irq_out:
-
- spin_unlock_irqrestore(&host->complete_lock, iflags);
- return IRQ_HANDLED;
--
- }
-
- /*
-@@ -789,11 +806,11 @@ static void s3cmci_dma_setup(struct s3cm
-
- last_source = source;
-
-- s3c2410_dma_devconfig(host->dma, source, 3,
-+ s3c2410_dma_devconfig(host->dma, source,
- host->mem->start + host->sdidata);
-
- if (!setup_ok) {
-- s3c2410_dma_config(host->dma, 4, 0);
-+ s3c2410_dma_config(host->dma, 4);
- s3c2410_dma_set_buffdone_fn(host->dma,
- s3cmci_dma_done_callback);
- s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
-@@ -1026,6 +1043,7 @@ static void s3cmci_send_request(struct m
- dbg(host, dbg_err, "data prepare error %d\n", res);
- cmd->error = res;
- cmd->data->error = res;
-+ cmd->data->error = -EIO;
-
- mmc_request_done(mmc, mrq);
- return;
-@@ -1263,10 +1281,8 @@ static int __devinit s3cmci_probe(struct
- host->is2440 = is2440;
-
- host->pdata = pdev->dev.platform_data;
-- if (!host->pdata) {
-- pdev->dev.platform_data = &s3cmci_def_pdata;
-+ if (!host->pdata)
- host->pdata = &s3cmci_def_pdata;
-- }
-
- spin_lock_init(&host->complete_lock);
- tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
-@@ -1379,6 +1395,18 @@ static int __devinit s3cmci_probe(struct
- mmc->f_min = host->clk_rate / (host->clk_div * 256);
- mmc->f_max = host->clk_rate / host->clk_div;
-
-+ if (f_max >= 0) {
-+ unsigned f = f_max;
-+
-+ if (f < mmc->f_min)
-+ f = mmc->f_min;
-+ if (mmc->f_max > f) {
-+ dev_info(&pdev->dev, "f_max lowered from %u to %u Hz\n",
-+ mmc->f_max, f);
-+ mmc->f_max = f;
-+ }
-+ }
-+
- if (host->pdata->ocr_avail)
- mmc->ocr_avail = host->pdata->ocr_avail;
-
-@@ -1491,18 +1519,60 @@ static int __devinit s3cmci_2440_probe(s
-
- #ifdef CONFIG_PM
-
-+static int save_regs(struct mmc_host *mmc)
-+{
-+ struct s3cmci_host *host = mmc_priv(mmc);
-+ unsigned long flags;
-+ unsigned from;
-+ u32 *to = host->saved;
-+
-+ mmc_flush_scheduled_work();
-+
-+ local_irq_save(flags);
-+ for (from = S3C2410_SDICON; from != S3C2410_SDIIMSK+4; from += 4)
-+ if (from != host->sdidata)
-+ *to++ = readl(host->base + from);
-+ BUG_ON(to-host->saved != ARRAY_SIZE(host->saved));
-+ local_irq_restore(flags);
-+
-+ return 0;
-+}
-+
-+static int restore_regs(struct mmc_host *mmc)
-+{
-+ struct s3cmci_host *host = mmc_priv(mmc);
-+ unsigned long flags;
-+ unsigned to;
-+ u32 *from = host->saved;
-+
-+ /*
-+ * Before we begin with the necromancy, make sure we don't
-+ * inadvertently start something we'll regret microseconds later.
-+ */
-+ from[S3C2410_SDICMDCON - S3C2410_SDICON] = 0;
-+
-+ local_irq_save(flags);
-+ for (to = S3C2410_SDICON; to != S3C2410_SDIIMSK+4; to += 4)
-+ if (to != host->sdidata)
-+ writel(*from++, host->base + to);
-+ BUG_ON(from-host->saved != ARRAY_SIZE(host->saved));
-+ local_irq_restore(flags);
-+
-+ return 0;
-+}
-+
- static int s3cmci_suspend(struct platform_device *dev, pm_message_t state)
- {
- struct mmc_host *mmc = platform_get_drvdata(dev);
-
-- return mmc_suspend_host(mmc, state);
-+ return persist ? save_regs(mmc) : mmc_suspend_host(mmc, state);
- }
-
- static int s3cmci_resume(struct platform_device *dev)
- {
- struct mmc_host *mmc = platform_get_drvdata(dev);
-
-- return mmc_resume_host(mmc);
-+ return persist ? restore_regs(mmc) : mmc_resume_host(mmc);
- }
-
- #else /* CONFIG_PM */
-@@ -1560,9 +1630,13 @@ static void __exit s3cmci_exit(void)
- module_init(s3cmci_init);
- module_exit(s3cmci_exit);
-
-+module_param(f_max, int, 0644);
-+module_param(persist, int, 0644);
-+
- MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
- MODULE_LICENSE("GPL v2");
- MODULE_AUTHOR("Thomas Kleffel <tk@maintech.de>, Ben Dooks <ben-linux@fluff.org>");
- MODULE_ALIAS("platform:s3c2410-sdi");
- MODULE_ALIAS("platform:s3c2412-sdi");
- MODULE_ALIAS("platform:s3c2440-sdi");
-+
---- a/drivers/mmc/host/s3cmci.h
-+++ b/drivers/mmc/host/s3cmci.h
-@@ -8,6 +8,10 @@
- * published by the Free Software Foundation.
- */
-
-+
-+#include <mach/regs-sdi.h>
-+#include <linux/regulator/consumer.h>
-+
- /* FIXME: DMA Resource management ?! */
- #define S3CMCI_DMA 0
-
-@@ -68,7 +72,16 @@ struct s3cmci_host {
- unsigned int ccnt, dcnt;
- struct tasklet_struct pio_tasklet;
-
-+ /*
-+ * Here's where we save the registers during suspend. Note that we skip
-+ * SDIDATA, which is at different positions on 2410 and 2440, so
-+ * there's no "+1" in the array size.
-+ */
-+ u32 saved[(S3C2410_SDIIMSK-S3C2410_SDICON)/4];
-+
- #ifdef CONFIG_CPU_FREQ
- struct notifier_block freq_transition;
- #endif
-+
-+ struct regulator *regulator;
- };
---- /dev/null
-+++ b/drivers/mmc/host/sdhci-s3c.c
-@@ -0,0 +1,419 @@
-+/* linux/drivers/mmc/host/sdhci-s3c.c
-+ *
-+ * Copyright 2008 Openmoko Inc.
-+ * Copyright 2008 Simtec Electronics
-+ * Ben Dooks <ben@simtec.co.uk>
-+ * http://armlinux.simtec.co.uk/
-+ *
-+ * SDHCI (HSMMC) support for Samsung SoC
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/delay.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/platform_device.h>
-+#include <linux/clk.h>
-+#include <linux/io.h>
-+
-+#include <linux/mmc/host.h>
-+
-+#include <plat/regs-sdhci.h>
-+#include <plat/sdhci.h>
-+
-+#include "sdhci.h"
-+
-+#define MAX_BUS_CLK (4)
-+
-+struct sdhci_s3c {
-+ struct sdhci_host *host;
-+ struct platform_device *pdev;
-+ struct resource *ioarea;
-+ struct s3c_sdhci_platdata *pdata;
-+ unsigned int cur_clk;
-+
-+ struct clk *clk_io; /* clock for io bus */
-+ struct clk *clk_bus[MAX_BUS_CLK];
-+};
-+
-+static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
-+{
-+ return sdhci_priv(host);
-+}
-+
-+static u32 get_curclk(u32 ctrl2)
-+{
-+ ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-+ ctrl2 >>= S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
-+
-+ return ctrl2;
-+}
-+
-+static void sdhci_s3c_check_sclk(struct sdhci_host *host)
-+{
-+ struct sdhci_s3c *ourhost = to_s3c(host);
-+ u32 tmp = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
-+
-+ if (get_curclk(tmp) != ourhost->cur_clk) {
-+ dev_dbg(&ourhost->pdev->dev, "restored ctrl2 clock setting\n");
-+
-+ tmp &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-+ tmp |= ourhost->cur_clk << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
-+ writel(tmp, host->ioaddr + 0x80);
-+ }
-+}
-+
-+static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host)
-+{
-+ struct sdhci_s3c *ourhost = to_s3c(host);
-+ struct clk *busclk;
-+ unsigned int rate, max;
-+ int clk;
-+
-+ /* note, a reset will reset the clock source */
-+
-+ sdhci_s3c_check_sclk(host);
-+
-+ for (max = 0, clk = 0; clk < MAX_BUS_CLK; clk++) {
-+ busclk = ourhost->clk_bus[clk];
-+ if (!busclk)
-+ continue;
-+
-+ rate = clk_get_rate(busclk);
-+ if (rate > max)
-+ max = rate;
-+ }
-+
-+ return max;
-+}
-+
-+static unsigned int sdhci_s3c_get_timeout_clk(struct sdhci_host *host)
-+{
-+ return sdhci_s3c_get_max_clk(host) / 1000000;
-+}
-+
-+static void sdhci_s3c_set_ios(struct sdhci_host *host,
-+ struct mmc_ios *ios)
-+{
-+ struct sdhci_s3c *ourhost = to_s3c(host);
-+ struct s3c_sdhci_platdata *pdata = ourhost->pdata;
-+ int width;
-+
-+ sdhci_s3c_check_sclk(host);
-+
-+ if (ios->power_mode != MMC_POWER_OFF) {
-+ switch (ios->bus_width) {
-+ case MMC_BUS_WIDTH_4:
-+ width = 4;
-+ break;
-+ case MMC_BUS_WIDTH_1:
-+ width = 1;
-+ break;
-+ default:
-+ BUG();
-+ }
-+
-+ if (pdata->cfg_gpio)
-+ pdata->cfg_gpio(ourhost->pdev, width);
-+ }
-+
-+ if (pdata->cfg_card)
-+ pdata->cfg_card(ourhost->pdev, host->ioaddr,
-+ ios, host->mmc->card);
-+}
-+
-+static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
-+ unsigned int src,
-+ unsigned int wanted)
-+{
-+ unsigned long rate;
-+ struct clk *clksrc = ourhost->clk_bus[src];
-+ int div;
-+
-+ if (!clksrc)
-+ return UINT_MAX;
-+
-+ rate = clk_get_rate(clksrc);
-+
-+ for (div = 1; div < 256; div *= 2) {
-+ if ((rate / div) <= wanted)
-+ break;
-+ }
-+
-+ dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n",
-+ src, rate, wanted, rate / div);
-+
-+ return (wanted - (rate / div));
-+}
-+
-+static void sdhci_s3c_change_clock(struct sdhci_host *host, unsigned int clock)
-+{
-+ struct sdhci_s3c *ourhost = to_s3c(host);
-+ unsigned int best = UINT_MAX;
-+ unsigned int delta;
-+ int best_src = 0;
-+ int src;
-+ u32 ctrl;
-+
-+ for (src = 0; src < MAX_BUS_CLK; src++) {
-+ delta = sdhci_s3c_consider_clock(ourhost, src, clock);
-+ if (delta < best) {
-+ best = delta;
-+ best_src = src;
-+ }
-+ }
-+
-+ dev_dbg(&ourhost->pdev->dev,
-+ "selected source %d, clock %d, delta %d\n",
-+ best_src, clock, best);
-+
-+ /* turn clock off to card before changing clock source */
-+ writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
-+
-+ /* select the new clock source */
-+
-+ if (ourhost->cur_clk != best_src) {
-+ struct clk *clk = ourhost->clk_bus[best_src];
-+
-+ ourhost->cur_clk = best_src;
-+ host->max_clk = clk_get_rate(clk);
-+ host->timeout_clk = host->max_clk / 1000000;
-+
-+ ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
-+ ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-+ ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
-+ writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2);
-+ }
-+
-+ sdhci_change_clock(host, clock);
-+}
-+
-+static struct sdhci_ops sdhci_s3c_ops = {
-+ .get_max_clock = sdhci_s3c_get_max_clk,
-+ .get_timeout_clock = sdhci_s3c_get_timeout_clk,
-+ .change_clock = sdhci_s3c_change_clock,
-+ .set_ios = sdhci_s3c_set_ios,
-+};
-+
-+/*
-+ * call this when you need sd stack to recognize insertion or removal of card
-+ * that can't be told by SDHCI regs
-+ */
-+
-+void sdhci_s3c_force_presence_change(struct platform_device *pdev)
-+{
-+ struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
-+
-+ dev_info(&pdev->dev, "sdhci_s3c_force_presence_change called\n");
-+ mmc_detect_change(pdata->sdhci_host->mmc, msecs_to_jiffies(200));
-+}
-+EXPORT_SYMBOL_GPL(sdhci_s3c_force_presence_change);
-+
-+
-+static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
-+{
-+ struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
-+ struct device *dev = &pdev->dev;
-+ struct sdhci_host *host;
-+ struct sdhci_s3c *sc;
-+ struct resource *res;
-+ int ret, irq, ptr, clks;
-+
-+ if (!pdata) {
-+ dev_err(dev, "no device data specified\n");
-+ return -ENOENT;
-+ }
-+
-+ irq = platform_get_irq(pdev, 0);
-+ if (irq < 0) {
-+ dev_err(dev, "no irq specified\n");
-+ return irq;
-+ }
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!res) {
-+ dev_err(dev, "no memory specified\n");
-+ return -ENOENT;
-+ }
-+
-+ host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c));
-+ if (IS_ERR(host)) {
-+ dev_err(dev, "sdhci_alloc_host() failed\n");
-+ return PTR_ERR(host);
-+ }
-+
-+ pdata->sdhci_host = host;
-+
-+ sc = sdhci_priv(host);
-+
-+ sc->host = host;
-+ sc->pdev = pdev;
-+ sc->pdata = pdata;
-+
-+ platform_set_drvdata(pdev, host);
-+
-+ sc->clk_io = clk_get(dev, "hsmmc");
-+ if (IS_ERR(sc->clk_io)) {
-+ dev_err(dev, "failed to get io clock\n");
-+ ret = PTR_ERR(sc->clk_io);
-+ goto err_io_clk;
-+ }
-+
-+ /* enable the local io clock and keep it running for the moment. */
-+ clk_enable(sc->clk_io);
-+
-+ for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
-+ struct clk *clk;
-+ char *name = pdata->clocks[ptr];
-+
-+ if (name == NULL)
-+ continue;
-+
-+ clk = clk_get(dev, name);
-+ if (IS_ERR(clk)) {
-+ dev_err(dev, "failed to get clock %s\n", name);
-+ continue;
-+ }
-+
-+ clks++;
-+ sc->clk_bus[ptr] = clk;
-+ clk_enable(clk);
-+
-+ dev_info(dev, "clock source %d: %s (%ld Hz)\n",
-+ ptr, name, clk_get_rate(clk));
-+ }
-+
-+ if (clks == 0) {
-+ dev_err(dev, "failed to find any bus clocks\n");
-+ ret = -ENOENT;
-+ goto err_no_busclks;
-+ }
-+
-+ sc->ioarea = request_mem_region(res->start, resource_size(res),
-+ mmc_hostname(host->mmc));
-+ if (!sc->ioarea) {
-+ dev_err(dev, "failed to reserve register area\n");
-+ ret = -ENXIO;
-+ goto err_req_regs;
-+ }
-+
-+ host->ioaddr = ioremap_nocache(res->start, resource_size(res));
-+ if (!host->ioaddr) {
-+ dev_err(dev, "failed to map registers\n");
-+ ret = -ENXIO;
-+ goto err_req_regs;
-+ }
-+
-+ /* Ensure we have minimal gpio selected CMD/CLK/Detect */
-+ if (pdata->cfg_gpio)
-+ pdata->cfg_gpio(pdev, 0);
-+
-+ sdhci_s3c_check_sclk(host);
-+
-+ host->hw_name = "samsung-hsmmc";
-+ host->ops = &sdhci_s3c_ops;
-+ host->quirks = 0;
-+ host->irq = irq;
-+
-+ /* Setup quirks for the controller */
-+
-+ /* Currently with ADMA enabled we are getting some length
-+ * interrupts that are not being dealt with, do disable
-+ * ADMA until this is sorted out. */
-+ host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
-+ host->quirks |= SDHCI_QUIRK_32BIT_ADMA_SIZE;
-+
-+ /* It seems we do not get an DATA transfer complete on non-busy
-+ * transfers, not sure if this is a problem with this specific
-+ * SDHCI block, or a missing configuration that needs to be set. */
-+ host->quirks |= SDHCI_QUIRK_NO_TCIRQ_ON_NOT_BUSY;
-+
-+ host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR |
-+ SDHCI_QUIRK_32BIT_DMA_SIZE);
-+
-+ ret = sdhci_add_host(host);
-+ if (ret) {
-+ dev_err(dev, "sdhci_add_host() failed\n");
-+ goto err_add_host;
-+ }
-+
-+ return 0;
-+
-+ err_add_host:
-+ release_resource(sc->ioarea);
-+ kfree(sc->ioarea);
-+
-+ err_req_regs:
-+ for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
-+ clk_disable(sc->clk_bus[ptr]);
-+ clk_put(sc->clk_bus[ptr]);
-+ }
-+
-+ err_no_busclks:
-+ clk_disable(sc->clk_io);
-+ clk_put(sc->clk_io);
-+
-+ err_io_clk:
-+ sdhci_free_host(host);
-+
-+ return ret;
-+}
-+
-+static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
-+{
-+ return 0;
-+}
-+
-+#ifdef CONFIG_PM
-+
-+static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm)
-+{
-+ struct sdhci_host *host = platform_get_drvdata(dev);
-+
-+ sdhci_suspend_host(host, pm);
-+ return 0;
-+}
-+
-+static int sdhci_s3c_resume(struct platform_device *dev)
-+{
-+ struct sdhci_host *host = platform_get_drvdata(dev);
-+
-+ sdhci_resume_host(host);
-+ return 0;
-+}
-+
-+#else
-+#define sdhci_s3c_suspend NULL
-+#define sdhci_s3c_resume NULL
-+#endif
-+
-+static struct platform_driver sdhci_s3c_driver = {
-+ .probe = sdhci_s3c_probe,
-+ .remove = __devexit_p(sdhci_s3c_remove),
-+ .suspend = sdhci_s3c_suspend,
-+ .resume = sdhci_s3c_resume,
-+ .driver = {
-+ .owner = THIS_MODULE,
-+ .name = "s3c-sdhci",
-+ },
-+};
-+
-+static int __init sdhci_s3c_init(void)
-+{
-+ return platform_driver_register(&sdhci_s3c_driver);
-+}
-+
-+static void __exit sdhci_s3c_exit(void)
-+{
-+ platform_driver_unregister(&sdhci_s3c_driver);
-+}
-+
-+module_init(sdhci_s3c_init);
-+module_exit(sdhci_s3c_exit);
-+
-+MODULE_DESCRIPTION("Samsung SDHCI (HSMMC) glue");
-+MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
-+MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:s3c-sdhci");
---- a/drivers/mtd/nand/s3c2410.c
-+++ b/drivers/mtd/nand/s3c2410.c
-@@ -438,7 +438,7 @@ static int s3c2410_nand_correct_data(str
- if ((diff0 & ~(1<<fls(diff0))) == 0)
- return 1;
-
-- return -1;
-+ return -EBADMSG;
- }
-
- /* ECC functions
-@@ -530,7 +530,12 @@ static void s3c2410_nand_read_buf(struct
- static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
- {
- struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
-+ u8 *ptr = buf + (len & ~3);
-+ int i;
-+
- readsl(info->regs + S3C2440_NFDATA, buf, len / 4);
-+ for (i = 0; i != (len & 3); i++)
-+ ptr[i] = readb(info->regs + S3C2440_NFDATA);
- }
-
- static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
-@@ -645,17 +650,31 @@ static int s3c2410_nand_remove(struct pl
- }
-
- #ifdef CONFIG_MTD_PARTITIONS
-+const char *part_probes[] = { "cmdlinepart", NULL };
- static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
- struct s3c2410_nand_mtd *mtd,
- struct s3c2410_nand_set *set)
- {
-+ struct mtd_partition *part_info;
-+ int nr_part = 0;
-+
- if (set == NULL)
- return add_mtd_device(&mtd->mtd);
-
-- if (set->nr_partitions > 0 && set->partitions != NULL) {
-- return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions);
-+ if (set->nr_partitions == 0) {
-+ mtd->mtd.name = set->name;
-+ nr_part = parse_mtd_partitions(&mtd->mtd, part_probes,
-+ &part_info, 0);
-+ } else {
-+ if (set->nr_partitions > 0 && set->partitions != NULL) {
-+ nr_part = set->nr_partitions;
-+ part_info = set->partitions;
-+ }
- }
-
-+ if (nr_part > 0 && part_info)
-+ return add_mtd_partitions(&mtd->mtd, part_info, nr_part);
-+
- return add_mtd_device(&mtd->mtd);
- }
- #else
-@@ -684,9 +703,13 @@ static void s3c2410_nand_init_chip(struc
- chip->select_chip = s3c2410_nand_select_chip;
- chip->chip_delay = 50;
- chip->priv = nmtd;
-- chip->options = 0;
- chip->controller = &info->controller;
-
-+ if (set->flags & S3C2410_NAND_BBT)
-+ chip->options = NAND_USE_FLASH_BBT;
-+ else
-+ chip->options = 0;
-+
- switch (info->cpu_type) {
- case TYPE_S3C2410:
- chip->IO_ADDR_W = regs + S3C2410_NFDATA;
-@@ -726,7 +749,7 @@ static void s3c2410_nand_init_chip(struc
- nmtd->mtd.owner = THIS_MODULE;
- nmtd->set = set;
-
-- if (hardware_ecc) {
-+ if (!info->platform->software_ecc && hardware_ecc) {
- chip->ecc.calculate = s3c2410_nand_calculate_ecc;
- chip->ecc.correct = s3c2410_nand_correct_data;
- chip->ecc.mode = NAND_ECC_HW;
---- a/drivers/mmc/core/core.c
-+++ b/drivers/mmc/core/core.c
-@@ -59,10 +59,11 @@ static int mmc_schedule_delayed_work(str
- /*
- * Internal function. Flush all scheduled work from the MMC work queue.
- */
--static void mmc_flush_scheduled_work(void)
-+void mmc_flush_scheduled_work(void)
- {
- flush_workqueue(workqueue);
- }
-+EXPORT_SYMBOL_GPL(mmc_flush_scheduled_work);
-
- /**
- * mmc_request_done - finish processing an MMC request