goldfish: R.I.P.
[openwrt.git] / target / linux / s3c24xx / patches-2.6.30 / 001-merge-openmoko.patch
1 Merge OpenMoko kernel patches
2 git://git.openmoko.org/git/kernel.git#(no
3
4 lars@lars-laptop   Thu May 14 18:33:23 UTC 2009
5
6 ---
7
8 --- /dev/null
9 +++ b/arch/arm/mach-s3c2410/include/mach/mci.h
10 @@ -0,0 +1,13 @@
11 +#ifndef _ARCH_MCI_H
12 +#define _ARCH_MCI_H
13 +
14 +struct s3c24xx_mci_pdata {
15 +       unsigned int    gpio_detect;
16 +       unsigned int    gpio_wprotect;
17 +       unsigned long   ocr_avail;
18 +       unsigned int    do_dma;
19 +       void            (*set_power)(unsigned char power_mode,
20 +                                    unsigned short vdd);
21 +};
22 +
23 +#endif /* _ARCH_NCI_H */
24 --- a/arch/arm/mach-s3c2410/include/mach/regs-sdi.h
25 +++ b/arch/arm/mach-s3c2410/include/mach/regs-sdi.h
26 @@ -30,6 +30,7 @@
27  #define S3C2410_SDIFSTA               (0x38)
28  
29  #define S3C2410_SDIDATA               (0x3C)
30 +#define S3C2410_SDIDATA_BYTE          (0x3C)
31  #define S3C2410_SDIIMSK               (0x40)
32  
33  #define S3C2440_SDIDATA               (0x40)
34 @@ -37,6 +38,8 @@
35  
36  #define S3C2440_SDICON_SDRESET        (1<<8)
37  #define S3C2440_SDICON_MMCCLOCK       (1<<5)
38 +#define S3C2440_SDIDATA_BYTE          (0x48)
39 +
40  #define S3C2410_SDICON_BYTEORDER      (1<<4)
41  #define S3C2410_SDICON_SDIOIRQ        (1<<3)
42  #define S3C2410_SDICON_RWAITEN        (1<<2)
43 --- a/arch/arm/mach-s3c2440/s3c2440.c
44 +++ b/arch/arm/mach-s3c2440/s3c2440.c
45 @@ -46,6 +46,9 @@ int __init s3c2440_init(void)
46         s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
47         s3c_device_wdt.resource[1].end   = IRQ_S3C2440_WDT;
48  
49 +       /* make sure SD/MMC driver can distinguish 2440 from 2410 */
50 +       s3c_device_sdi.name = "s3c2440-sdi";
51 +
52         /* register our system device for everything else */
53  
54         return sysdev_register(&s3c2440_sysdev);
55 --- a/arch/arm/mach-s3c2442/s3c2442.c
56 +++ b/arch/arm/mach-s3c2442/s3c2442.c
57 @@ -21,6 +21,7 @@
58  
59  #include <plat/s3c2442.h>
60  #include <plat/cpu.h>
61 +#include <plat/devs.h>
62  
63  static struct sys_device s3c2442_sysdev = {
64         .cls            = &s3c2442_sysclass,
65 @@ -30,5 +31,8 @@ int __init s3c2442_init(void)
66  {
67         printk("S3C2442: Initialising architecture\n");
68  
69 +       /* make sure SD/MMC driver can distinguish 2440 from 2410 */
70 +       s3c_device_sdi.name = "s3c2440-sdi";
71 +
72         return sysdev_register(&s3c2442_sysdev);
73  }
74 --- a/arch/arm/Makefile
75 +++ b/arch/arm/Makefile
76 @@ -55,7 +55,8 @@ ifeq ($(CONFIG_CPU_32v6),y)
77  arch-$(CONFIG_CPU_32v6K)       :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k)
78  endif
79  arch-$(CONFIG_CPU_32v5)                :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t)
80 -arch-$(CONFIG_CPU_32v4T)       :=-D__LINUX_ARM_ARCH__=4 -march=armv4t
81 +# We can't load armv4t modules, but still need to assemble some armv4t code to be linked in.
82 +arch-$(CONFIG_CPU_32v4T)       :=-D__LINUX_ARM_ARCH__=4 -march=armv4 -Wa,-march=armv4t
83  arch-$(CONFIG_CPU_32v4)                :=-D__LINUX_ARM_ARCH__=4 -march=armv4
84  arch-$(CONFIG_CPU_32v3)                :=-D__LINUX_ARM_ARCH__=3 -march=armv3
85  
86 --- /dev/null
87 +++ b/arch/arm/plat-s3c/include/mach/cpu.h
88 @@ -0,0 +1,165 @@
89 +/*
90 + * arch/arm/plat-s3c/include/mach/cpu.h
91 + *
92 + *  S3C cpu type detection
93 + *
94 + *  Copyright (C) 2008 Samsung Electronics
95 + *  Kyungmin Park <kyungmin.park@samsung.com>
96 + *
97 + * Derived from OMAP cpu.h
98 + *
99 + * This program is free software; you can redistribute it and/or modify
100 + * it under the terms of the GNU General Public License as published by
101 + * the Free Software Foundation; either version 2 of the License, or
102 + * (at your option) any later version.
103 + *
104 + * This program is distributed in the hope that it will be useful,
105 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
106 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
107 + * GNU General Public License for more details.
108 + *
109 + * You should have received a copy of the GNU General Public License
110 + * along with this program; if not, write to the Free Software
111 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
112 + */
113 +
114 +#ifndef __ASM_ARCH_S3C_CPU_H
115 +#define __ASM_ARCH_S3C_CPU_H
116 +
117 +extern unsigned int system_rev;
118 +
119 +#define S3C_SYSTEM_REV_ATAG (system_rev & 0xffff)
120 +#define S3C_SYSTEM_REV_CPU (system_rev & 0xffff0000)
121 +
122 +/*
123 + * cpu_is_s3c24xx():   True for s3c2400, s3c2410, s3c2440 and so on
124 + * cpu_is_s3c241x():   True fro s3c2410, s3c2412
125 + * cpu_is_s3c244x():   True fro s3c2440, s3c2442, s3c2443
126 + * cpu_is_s3c64xx():   True for s3c6400, s3c6410
127 + */
128 +#define GET_S3C_CLASS  ((system_rev >> 24) & 0xff)
129 +
130 +#define IS_S3C_CLASS(class, id)                                                \
131 +static inline int is_s3c ##class (void)                                        \
132 +{                                                                      \
133 +       return (GET_S3C_CLASS == (id)) ? 1 : 0;                         \
134 +}
135 +
136 +#define GET_S3C_SUBCLASS       ((system_rev >> 20) & 0xfff)
137 +
138 +#define IS_S3C_SUBCLASS(subclass, id)                                  \
139 +static inline int is_s3c ##subclass (void)                             \
140 +{                                                                      \
141 +       return (GET_S3C_SUBCLASS == (id)) ? 1 : 0;                      \
142 +}
143 +
144 +IS_S3C_CLASS(24xx, 0x24)
145 +IS_S3C_CLASS(64xx, 0x64)
146 +
147 +IS_S3C_SUBCLASS(241x, 0x241)
148 +IS_S3C_SUBCLASS(244x, 0x244)
149 +
150 +#define cpu_is_s3c24xx()               0
151 +#define cpu_is_s3c241x()               0
152 +#define cpu_is_s3c244x()               0
153 +#define cpu_is_s3c64xx()               0
154 +
155 +#if defined(CONFIG_ARCH_S3C2410)
156 +# undef  cpu_is_s3c24xx
157 +# undef  cpu_is_s3c241x
158 +# undef  cpu_is_s3c244x
159 +# define cpu_is_s3c24xx()              is_s3c24xx()
160 +# define cpu_is_s3c241x()              is_s3c241x()
161 +# define cpu_is_s3c244x()              is_s3c244x()
162 +#endif
163 +
164 +#if defined(CONFIG_ARCH_S3C64XX)
165 +# undef  cpu_is_s3c64xx
166 +# define cpu_is_s3c64xx()              is_s3c64xx()
167 +#endif
168 +
169 +/*
170 + * Macros to detect individual cpu types.
171 + * cpu_is_s3c2410():   True for s3c2410
172 + * cpu_is_s3c2440():   True for s3c2440
173 + * cpu_is_s3c6400():   True for s3c6400
174 + * cpu_is_s3c6410():   True for s3c6410
175 + *
176 + * Exception:
177 + * Store Revision A to 1
178 + * s3c2410a -> s3c2411
179 + * s3c2440a -> s3c2441
180 + */
181 +
182 +#define GET_S3C_TYPE   ((system_rev >> 16) & 0xffff)
183 +
184 +#define IS_S3C_TYPE(type, id)                                          \
185 +static inline int is_s3c ##type (void)                                 \
186 +{                                                                      \
187 +       return (GET_S3C_TYPE == (id)) ? 1 : 0;                          \
188 +}
189 +
190 +IS_S3C_TYPE(2400, 0x2400)
191 +IS_S3C_TYPE(2410, 0x2410)
192 +IS_S3C_TYPE(2410a, 0x2411)
193 +IS_S3C_TYPE(2412, 0x2412)
194 +IS_S3C_TYPE(2440, 0x2440)
195 +IS_S3C_TYPE(2440a, 0x2441)
196 +IS_S3C_TYPE(2442, 0x2442)
197 +IS_S3C_TYPE(2443, 0x2443)
198 +IS_S3C_TYPE(6400, 0x6400)
199 +IS_S3C_TYPE(6410, 0x6410)
200 +
201 +#define cpu_is_s3c2400()               0
202 +#define cpu_is_s3c2410()               0
203 +#define cpu_is_s3c2410a()              0
204 +#define cpu_is_s3c2412()               0
205 +#define cpu_is_s3c2440()               0
206 +#define cpu_is_s3c2440a()              0
207 +#define cpu_is_s3c2442()               0
208 +#define cpu_is_s3c2443()               0
209 +#define cpu_is_s3c6400()               0
210 +#define cpu_is_s3c6410()               0
211 +
212 +#if defined(CONFIG_ARCH_S3C2410)
213 +# undef  cpu_is_s3c2400
214 +# define cpu_is_s3c2400()              is_s3c2400()
215 +#endif
216 +
217 +#if defined(CONFIG_CPU_S3C2410)
218 +# undef  cpu_is_s3c2410
219 +# undef  cpu_is_s3c2410a
220 +# define cpu_is_s3c2410()              is_s3c2410()
221 +# define cpu_is_s3c2410a()             is_s3c2410a()
222 +#endif
223 +
224 +#if defined(CONFIG_CPU_S3C2412)
225 +# undef  cpu_is_s3c2412
226 +# define cpu_is_s3c2412()              is_s3c2412()
227 +#endif
228 +
229 +#if defined(CONFIG_CPU_S3C2440)
230 +# undef  cpu_is_s3c2440
231 +# undef  cpu_is_s3c2440a
232 +# define cpu_is_s3c2440()              is_s3c2440()
233 +# define cpu_is_s3c2440a()             is_s3c2440a()
234 +#endif
235 +
236 +#if defined(CONFIG_CPU_S3C2442)
237 +# undef  cpu_is_s3c2442
238 +# define cpu_is_s3c2442()              is_s3c2442()
239 +#endif
240 +
241 +#if defined(CONFIG_CPU_S3C2443)
242 +# undef  cpu_is_s3c2443
243 +# define cpu_is_s3c2443()              is_s3c2443()
244 +#endif
245 +
246 +#if defined(CONFIG_ARCH_S3C64XX)
247 +# undef  cpu_is_s3c6400
248 +# undef  cpu_is_s3c6410
249 +# define cpu_is_s3c6400()              is_s3c6400()
250 +# define cpu_is_s3c6410()              is_s3c6410()
251 +#endif
252 +
253 +#endif
254 --- a/arch/arm/plat-s3c/include/plat/devs.h
255 +++ b/arch/arm/plat-s3c/include/plat/devs.h
256 @@ -16,6 +16,10 @@ struct s3c24xx_uart_resources {
257         unsigned long            nr_resources;
258  };
259  
260 +struct s3c_plat_otg_data {
261 +       int             phyclk;
262 +};
263 +
264  extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
265  extern struct s3c24xx_uart_resources s3c64xx_uart_resources[];
266  
267 --- a/arch/arm/plat-s3c/include/plat/gpio-core.h
268 +++ b/arch/arm/plat-s3c/include/plat/gpio-core.h
269 @@ -20,6 +20,19 @@
270   * specific code.
271  */
272  
273 +struct s3c_gpio_chip;
274 +
275 +/**
276 + * struct s3c_gpio_pm - power management (suspend/resume) information
277 + * @save: Routine to save the state of the GPIO block
278 + * @resume: Routine to resume the GPIO block.
279 + */
280 +struct s3c_gpio_pm {
281 +       void (*save)(struct s3c_gpio_chip *chip);
282 +       void (*resume)(struct s3c_gpio_chip *chip);
283 +};
284 +
285 +
286  struct s3c_gpio_cfg;
287  
288  /**
289 @@ -27,6 +40,7 @@ struct s3c_gpio_cfg;
290   * @chip: The chip structure to be exported via gpiolib.
291   * @base: The base pointer to the gpio configuration registers.
292   * @config: special function and pull-resistor control information.
293 + * @pm_save: Save information for suspend/resume support.
294   *
295   * This wrapper provides the necessary information for the Samsung
296   * specific gpios being registered with gpiolib.
297 @@ -34,7 +48,11 @@ struct s3c_gpio_cfg;
298  struct s3c_gpio_chip {
299         struct gpio_chip        chip;
300         struct s3c_gpio_cfg     *config;
301 +       struct s3c_gpio_pm      *pm;
302         void __iomem            *base;
303 +#ifdef CONFIG_PM
304 +       u32                     pm_save[4];
305 +#endif
306  };
307  
308  static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
309 @@ -75,3 +93,16 @@ static inline struct s3c_gpio_chip *s3c_
310  
311  static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
312  #endif
313 +
314 +#ifdef CONFIG_PM
315 +extern struct s3c_gpio_pm s3c_gpio_pm_1bit;
316 +extern struct s3c_gpio_pm s3c_gpio_pm_2bit;
317 +extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
318 +#define __gpio_pm(x) x
319 +#else
320 +#define s3c_gpio_pm_1bit NULL
321 +#define s3c_gpio_pm_2bit NULL
322 +#define s3c_gpio_pm_4bit NULL
323 +#define __gpio_pm(x) NULL
324 +
325 +#endif /* CONFIG_PM */
326 --- a/arch/arm/plat-s3c/include/plat/map-base.h
327 +++ b/arch/arm/plat-s3c/include/plat/map-base.h
328 @@ -36,5 +36,7 @@
329  #define S3C_VA_TIMER   S3C_ADDR(0x00300000)    /* timer block */
330  #define S3C_VA_WATCHDOG        S3C_ADDR(0x00400000)    /* watchdog */
331  #define S3C_VA_UART    S3C_ADDR(0x01000000)    /* UART */
332 +#define S3C_VA_OTG     S3C_ADDR(0x03900000)    /* OTG */
333 +#define S3C_VA_OTGSFR  S3C_ADDR(0x03a00000)    /* OTGSFR */
334  
335  #endif /* __ASM_PLAT_MAP_H */
336 --- a/arch/arm/plat-s3c/include/plat/nand.h
337 +++ b/arch/arm/plat-s3c/include/plat/nand.h
338 @@ -21,11 +21,14 @@
339   * partitions   = mtd partition list
340  */
341  
342 +#define S3C2410_NAND_BBT       0x0001
343 +
344  struct s3c2410_nand_set {
345         unsigned int            disable_ecc : 1;
346  
347         int                     nr_chips;
348         int                     nr_partitions;
349 +       unsigned int            flags;
350         char                    *name;
351         int                     *nr_map;
352         struct mtd_partition    *partitions;
353 @@ -44,6 +47,9 @@ struct s3c2410_platform_nand {
354         int                     nr_sets;
355         struct s3c2410_nand_set *sets;
356  
357 +       /* force software_ecc at runtime */
358 +       int     software_ecc;
359 +
360         void                    (*select_chip)(struct s3c2410_nand_set *,
361                                                int chip);
362  };
363 --- a/arch/arm/plat-s3c/include/plat/pm.h
364 +++ b/arch/arm/plat-s3c/include/plat/pm.h
365 @@ -9,6 +9,8 @@
366   * published by the Free Software Foundation.
367  */
368  
369 +#include <linux/sysdev.h>
370 +
371  /* s3c_pm_init
372   *
373   * called from board at initialisation time to setup the power
374 @@ -44,6 +46,8 @@ extern void (*pm_cpu_sleep)(void);
375  
376  extern unsigned long s3c_pm_flags;
377  
378 +extern unsigned char pm_uart_udivslot;  /* true to save UART UDIVSLOT */
379 +
380  /* from sleep.S */
381  
382  extern int  s3c_cpu_save(unsigned long *saveblk);
383 @@ -88,6 +92,7 @@ struct pm_uart_save {
384         u32     ufcon;
385         u32     umcon;
386         u32     ubrdiv;
387 +       u32     udivslot;
388  };
389  
390  /* helper functions to save/restore lists of registers. */
391 --- a/arch/arm/plat-s3c/include/plat/sdhci.h
392 +++ b/arch/arm/plat-s3c/include/plat/sdhci.h
393 @@ -29,6 +29,7 @@ struct mmc_ios;
394   *            is necessary the controllers and/or GPIO blocks require the
395   *           changing of driver-strength and other controls dependant on
396   *           the card and speed of operation.
397 + * sdhci_host: Pointer kept during init, allows presence change notification
398   *
399   * Initialisation data specific to either the machine or the platform
400   * for the device driver to use or call-back when configuring gpio or
401 @@ -45,8 +46,11 @@ struct s3c_sdhci_platdata {
402                             void __iomem *regbase,
403                             struct mmc_ios *ios,
404                             struct mmc_card *card);
405 +       struct sdhci_host * sdhci_host;
406  };
407  
408 +extern void sdhci_s3c_force_presence_change(struct platform_device *pdev);
409 +
410  /**
411   * s3c_sdhci0_set_platdata - Set platform data for S3C SDHCI device.
412   * @pd: Platform data to register to device.
413 --- a/arch/arm/plat-s3c/init.c
414 +++ b/arch/arm/plat-s3c/init.c
415 @@ -31,6 +31,34 @@
416  
417  static struct cpu_table *cpu;
418  
419 +static void __init set_system_rev(unsigned int idcode)
420 +{
421 +       /*
422 +        * system_rev encoding is as follows
423 +        * system_rev & 0xff000000 -> S3C Class (24xx/64xx)
424 +        * system_rev & 0xfff00000 -> S3C Sub Class (241x/244x)
425 +        * system_rev & 0xffff0000 -> S3C Type (2410/2440/6400/6410)
426 +        *
427 +        * Remaining[15:0] are preserved from the value set by ATAG
428 +        *
429 +        * Exception:
430 +        *  Store Revision A to 1 such as
431 +        *  s3c2410A to s3c2411
432 +        *  s3c2440A to s3c2441
433 +        */
434 +
435 +       system_rev &= 0xffff;
436 +       system_rev |= (idcode & 0x0ffff000) << 4;
437 +
438 +       if (idcode == 0x32410002 || idcode == 0x32440001)
439 +               system_rev |= (0x1 << 16);
440 +       if (idcode == 0x32440aaa        /* s3c2442 */
441 +           || idcode == 0x32440aab)    /* s3c2442b */
442 +               system_rev |= (0x2 << 16);
443 +       if (idcode == 0x0)              /* s3c2400 */
444 +               system_rev |= (0x2400 << 16);
445 +}
446 +
447  static struct cpu_table * __init s3c_lookup_cpu(unsigned long idcode,
448                                                 struct cpu_table *tab,
449                                                 unsigned int count)
450 @@ -53,6 +81,8 @@ void __init s3c_init_cpu(unsigned long i
451                 panic("Unknown S3C24XX CPU");
452         }
453  
454 +       set_system_rev(idcode);
455 +
456         printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
457  
458         if (cpu->map_io == NULL || cpu->init == NULL) {
459 --- a/arch/arm/plat-s3c/Makefile
460 +++ b/arch/arm/plat-s3c/Makefile
461 @@ -21,6 +21,7 @@ obj-y                         += gpio-config.o
462  # PM support
463  
464  obj-$(CONFIG_PM)               += pm.o
465 +obj-$(CONFIG_PM)               += pm-gpio.o
466  obj-$(CONFIG_S3C2410_PM_CHECK) += pm-check.o
467  
468  # devices
469 --- a/arch/arm/plat-s3c/pm.c
470 +++ b/arch/arm/plat-s3c/pm.c
471 @@ -21,11 +21,10 @@
472  
473  #include <asm/cacheflush.h>
474  #include <mach/hardware.h>
475 +#include <mach/map.h>
476  
477  #include <plat/regs-serial.h>
478  #include <mach/regs-clock.h>
479 -#include <mach/regs-gpio.h>
480 -#include <mach/regs-mem.h>
481  #include <mach/regs-irq.h>
482  #include <asm/irq.h>
483  
484 @@ -70,6 +69,8 @@ static inline void s3c_pm_debug_init(voi
485  
486  /* Save the UART configurations if we are configured for debug. */
487  
488 +unsigned char pm_uart_udivslot;
489 +
490  #ifdef CONFIG_S3C2410_PM_DEBUG
491  
492  struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
493 @@ -83,6 +84,12 @@ static void s3c_pm_save_uart(unsigned in
494         save->ufcon = __raw_readl(regs + S3C2410_UFCON);
495         save->umcon = __raw_readl(regs + S3C2410_UMCON);
496         save->ubrdiv = __raw_readl(regs + S3C2410_UBRDIV);
497 +
498 +       if (pm_uart_udivslot)
499 +               save->udivslot = __raw_readl(regs + S3C2443_DIVSLOT);
500 +
501 +       S3C_PMDBG("UART[%d]: ULCON=%04x, UCON=%04x, UFCON=%04x, UBRDIV=%04x\n",
502 +                 uart, save->ulcon, save->ucon, save->ufcon, save->ubrdiv);
503  }
504  
505  static void s3c_pm_save_uarts(void)
506 @@ -98,11 +105,16 @@ static void s3c_pm_restore_uart(unsigned
507  {
508         void __iomem *regs = S3C_VA_UARTx(uart);
509  
510 +       s3c_pm_arch_update_uart(regs, save);
511 +
512         __raw_writel(save->ulcon, regs + S3C2410_ULCON);
513         __raw_writel(save->ucon,  regs + S3C2410_UCON);
514         __raw_writel(save->ufcon, regs + S3C2410_UFCON);
515         __raw_writel(save->umcon, regs + S3C2410_UMCON);
516         __raw_writel(save->ubrdiv, regs + S3C2410_UBRDIV);
517 +
518 +       if (pm_uart_udivslot)
519 +               __raw_writel(save->udivslot, regs + S3C2443_DIVSLOT);
520  }
521  
522  static void s3c_pm_restore_uarts(void)
523 @@ -289,11 +301,14 @@ static int s3c_pm_enter(suspend_state_t 
524  
525         s3c_pm_arch_stop_clocks();
526  
527 -       /* s3c_cpu_save will also act as our return point from when
528 -        * we resume as it saves its own register state and restores it
529 -        * during the resume.  */
530 -
531 -       s3c_cpu_save(regs_save);
532 +       /* s3c2410_cpu_save will also act as our return point from when
533 +        * we resume as it saves its own register state, so use the return
534 +        * code to differentiate return from save and return from sleep */
535 +
536 +       if (s3c_cpu_save(regs_save) == 0) {
537 +               flush_cache_all();
538 +               pm_cpu_sleep();
539 +       }
540  
541         /* restore the cpu state using the kernel's cpu init code. */
542  
543 --- /dev/null
544 +++ b/arch/arm/plat-s3c/pm-gpio.c
545 @@ -0,0 +1,378 @@
546 +/* linux/arch/arm/plat-s3c/pm-gpio.c
547 + *
548 + * Copyright 2008 Openmoko, Inc.
549 + * Copyright 2008 Simtec Electronics
550 + *     Ben Dooks <ben@simtec.co.uk>
551 + *     http://armlinux.simtec.co.uk/
552 + *
553 + * S3C series GPIO PM code
554 + *
555 + * This program is free software; you can redistribute it and/or modify
556 + * it under the terms of the GNU General Public License version 2 as
557 + * published by the Free Software Foundation.
558 +*/
559 +
560 +#include <linux/kernel.h>
561 +#include <linux/init.h>
562 +#include <linux/io.h>
563 +#include <linux/gpio.h>
564 +
565 +#include <mach/gpio-core.h>
566 +#include <plat/pm.h>
567 +
568 +/* PM GPIO helpers */
569 +
570 +#define OFFS_CON       (0x00)
571 +#define OFFS_DAT       (0X04)
572 +#define OFFS_UP                (0X08)
573 +
574 +static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip)
575 +{
576 +       chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
577 +       chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
578 +}
579 +
580 +static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
581 +{
582 +       void __iomem *base = chip->base;
583 +       u32 old_gpcon = __raw_readl(base + OFFS_CON);
584 +       u32 old_gpdat = __raw_readl(base + OFFS_DAT);
585 +       u32 gps_gpcon = chip->pm_save[0];
586 +       u32 gps_gpdat = chip->pm_save[1];
587 +       u32 gpcon;
588 +
589 +       /* GPACON only has one bit per control / data and no PULLUPs.
590 +        * GPACON[x] = 0 => Output, 1 => SFN */
591 +
592 +       /* first set all SFN bits to SFN */
593 +
594 +       gpcon = old_gpcon | gps_gpcon;
595 +       __raw_writel(gpcon, base + OFFS_CON);
596 +
597 +       /* now set all the other bits */
598 +
599 +       __raw_writel(gps_gpdat, base + OFFS_DAT);
600 +       __raw_writel(gps_gpcon, base + OFFS_CON);
601 +
602 +       S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
603 +                 chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
604 +}
605 +
606 +struct s3c_gpio_pm s3c_gpio_pm_1bit = {
607 +       .save   = s3c_gpio_pm_1bit_save,
608 +       .resume = s3c_gpio_pm_1bit_resume,
609 +};
610 +
611 +static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip)
612 +{
613 +       chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
614 +       chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
615 +       chip->pm_save[2] = __raw_readl(chip->base + OFFS_UP);
616 +}
617 +
618 +/* Test whether the given masked+shifted bits of an GPIO configuration
619 + * are one of the SFN (special function) modes. */
620 +
621 +static inline int is_sfn(unsigned long con)
622 +{
623 +       return con >= 2;
624 +}
625 +
626 +/* Test if the given masked+shifted GPIO configuration is an input */
627 +
628 +static inline int is_in(unsigned long con)
629 +{
630 +       return con == 0;
631 +}
632 +
633 +/* Test if the given masked+shifted GPIO configuration is an output */
634 +
635 +static inline int is_out(unsigned long con)
636 +{
637 +       return con == 1;
638 +}
639 +
640 +/**
641 + * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank
642 + * @chip: The chip information to resume.
643 + *
644 + * Restore one of the GPIO banks that was saved during suspend. This is
645 + * not as simple as once thought, due to the possibility of glitches
646 + * from the order that the CON and DAT registers are set in.
647 + *
648 + * The three states the pin can be are {IN,OUT,SFN} which gives us 9
649 + * combinations of changes to check. Three of these, if the pin stays
650 + * in the same configuration can be discounted. This leaves us with
651 + * the following:
652 + *
653 + * { IN => OUT }  Change DAT first
654 + * { IN => SFN }  Change CON first
655 + * { OUT => SFN } Change CON first, so new data will not glitch
656 + * { OUT => IN }  Change CON first, so new data will not glitch
657 + * { SFN => IN }  Change CON first
658 + * { SFN => OUT } Change DAT first, so new data will not glitch [1]
659 + *
660 + * We do not currently deal with the UP registers as these control
661 + * weak resistors, so a small delay in change should not need to bring
662 + * these into the calculations.
663 + *
664 + * [1] this assumes that writing to a pin DAT whilst in SFN will set the
665 + *     state for when it is next output.
666 + */
667 +static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
668 +{
669 +       void __iomem *base = chip->base;
670 +       u32 old_gpcon = __raw_readl(base + OFFS_CON);
671 +       u32 old_gpdat = __raw_readl(base + OFFS_DAT);
672 +       u32 gps_gpcon = chip->pm_save[0];
673 +       u32 gps_gpdat = chip->pm_save[1];
674 +       u32 gpcon, old, new, mask;
675 +       u32 change_mask = 0x0;
676 +       int nr;
677 +
678 +       /* restore GPIO pull-up settings */
679 +       __raw_writel(chip->pm_save[2], base + OFFS_UP);
680 +
681 +       /* Create a change_mask of all the items that need to have
682 +        * their CON value changed before their DAT value, so that
683 +        * we minimise the work between the two settings.
684 +        */
685 +
686 +       for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
687 +               old = (old_gpcon & mask) >> nr;
688 +               new = (gps_gpcon & mask) >> nr;
689 +
690 +               /* If there is no change, then skip */
691 +
692 +               if (old == new)
693 +                       continue;
694 +
695 +               /* If both are special function, then skip */
696 +
697 +               if (is_sfn(old) && is_sfn(new))
698 +                       continue;
699 +
700 +               /* Change is IN => OUT, do not change now */
701 +
702 +               if (is_in(old) && is_out(new))
703 +                       continue;
704 +
705 +               /* Change is SFN => OUT, do not change now */
706 +
707 +               if (is_sfn(old) && is_out(new))
708 +                       continue;
709 +
710 +               /* We should now be at the case of IN=>SFN,
711 +                * OUT=>SFN, OUT=>IN, SFN=>IN. */
712 +
713 +               change_mask |= mask;
714 +       }
715 +
716 +
717 +       /* Write the new CON settings */
718 +
719 +       gpcon = old_gpcon & ~change_mask;
720 +       gpcon |= gps_gpcon & change_mask;
721 +
722 +       __raw_writel(gpcon, base + OFFS_CON);
723 +
724 +       /* Now change any items that require DAT,CON */
725 +
726 +       __raw_writel(gps_gpdat, base + OFFS_DAT);
727 +       __raw_writel(gps_gpcon, base + OFFS_CON);
728 +
729 +       S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
730 +                 chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
731 +}
732 +
733 +struct s3c_gpio_pm s3c_gpio_pm_2bit = {
734 +       .save   = s3c_gpio_pm_2bit_save,
735 +       .resume = s3c_gpio_pm_2bit_resume,
736 +};
737 +
738 +#ifdef CONFIG_ARCH_S3C64XX
739 +static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
740 +{
741 +       chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
742 +       chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
743 +       chip->pm_save[3] = __raw_readl(chip->base + OFFS_UP);
744 +
745 +       if (chip->chip.ngpio > 8)
746 +               chip->pm_save[0] = __raw_readl(chip->base - 4);
747 +}
748 +
749 +static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
750 +{
751 +       u32 old, new, mask;
752 +       u32 change_mask = 0x0;
753 +       int nr;
754 +
755 +       for (nr = 0, mask = 0x0f; nr < 16; nr += 4, mask <<= 4) {
756 +               old = (old_gpcon & mask) >> nr;
757 +               new = (gps_gpcon & mask) >> nr;
758 +
759 +               /* If there is no change, then skip */
760 +
761 +               if (old == new)
762 +                       continue;
763 +
764 +               /* If both are special function, then skip */
765 +
766 +               if (is_sfn(old) && is_sfn(new))
767 +                       continue;
768 +
769 +               /* Change is IN => OUT, do not change now */
770 +
771 +               if (is_in(old) && is_out(new))
772 +                       continue;
773 +
774 +               /* Change is SFN => OUT, do not change now */
775 +
776 +               if (is_sfn(old) && is_out(new))
777 +                       continue;
778 +
779 +               /* We should now be at the case of IN=>SFN,
780 +                * OUT=>SFN, OUT=>IN, SFN=>IN. */
781 +
782 +               change_mask |= mask;
783 +       }
784 +
785 +       return change_mask;
786 +}
787 +
788 +static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
789 +{
790 +       void __iomem *con = chip->base + (index * 4);
791 +       u32 old_gpcon = __raw_readl(con);
792 +       u32 gps_gpcon = chip->pm_save[index + 1];
793 +       u32 gpcon, mask;
794 +
795 +       mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
796 +
797 +       gpcon = old_gpcon & ~mask;
798 +       gpcon |= gps_gpcon & mask;
799 +
800 +       __raw_writel(gpcon, con);
801 +}
802 +
803 +static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
804 +{
805 +       void __iomem *base = chip->base;
806 +       u32 old_gpcon[2];
807 +       u32 old_gpdat = __raw_readl(base + OFFS_DAT);
808 +       u32 gps_gpdat = chip->pm_save[2];
809 +
810 +       /* First, modify the CON settings */
811 +
812 +       old_gpcon[0] = 0;
813 +       old_gpcon[1] = __raw_readl(base + OFFS_CON);
814 +
815 +       s3c_gpio_pm_4bit_con(chip, 0);
816 +       if (chip->chip.ngpio > 8) {
817 +               old_gpcon[0] = __raw_readl(base - 4);
818 +               s3c_gpio_pm_4bit_con(chip, -1);
819 +       }
820 +
821 +       /* Now change the configurations that require DAT,CON */
822 +
823 +       __raw_writel(chip->pm_save[2], base + OFFS_DAT);
824 +       __raw_writel(chip->pm_save[1], base + OFFS_CON);
825 +       if (chip->chip.ngpio > 8)
826 +               __raw_writel(chip->pm_save[0], base - 4);
827 +
828 +       __raw_writel(chip->pm_save[2], base + OFFS_DAT);
829 +       __raw_writel(chip->pm_save[3], base + OFFS_UP);
830 +
831 +       if (chip->chip.ngpio > 8) {
832 +               S3C_PMDBG("%s: CON4 %08x,%08x => %08x,%08x, DAT %08x => %08x\n",
833 +                         chip->chip.label, old_gpcon[0], old_gpcon[1],
834 +                         __raw_readl(base - 4),
835 +                         __raw_readl(base + OFFS_CON),
836 +                         old_gpdat, gps_gpdat);
837 +       } else
838 +               S3C_PMDBG("%s: CON4 %08x => %08x, DAT %08x => %08x\n",
839 +                         chip->chip.label, old_gpcon[1],
840 +                         __raw_readl(base + OFFS_CON),
841 +                         old_gpdat, gps_gpdat);
842 +}
843 +
844 +struct s3c_gpio_pm s3c_gpio_pm_4bit = {
845 +       .save   = s3c_gpio_pm_4bit_save,
846 +       .resume = s3c_gpio_pm_4bit_resume,
847 +};
848 +#endif /* CONFIG_ARCH_S3C64XX */
849 +
850 +/**
851 + * s3c_pm_save_gpio() - save gpio chip data for suspend
852 + * @ourchip: The chip for suspend.
853 + */
854 +static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip)
855 +{
856 +       struct s3c_gpio_pm *pm = ourchip->pm;
857 +
858 +       if (pm == NULL || pm->save == NULL)
859 +               S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
860 +       else
861 +               pm->save(ourchip);
862 +}
863 +
864 +/**
865 + * s3c_pm_save_gpios() - Save the state of the GPIO banks.
866 + *
867 + * For all the GPIO banks, save the state of each one ready for going
868 + * into a suspend mode.
869 + */
870 +void s3c_pm_save_gpios(void)
871 +{
872 +       struct s3c_gpio_chip *ourchip;
873 +       unsigned int gpio_nr;
874 +
875 +       for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
876 +               ourchip = s3c_gpiolib_getchip(gpio_nr);
877 +               if (!ourchip)
878 +                       continue;
879 +
880 +               s3c_pm_save_gpio(ourchip);
881 +
882 +               S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
883 +                         ourchip->chip.label,
884 +                         ourchip->pm_save[0],
885 +                         ourchip->pm_save[1],
886 +                         ourchip->pm_save[2],
887 +                         ourchip->pm_save[3]);
888 +
889 +               gpio_nr += ourchip->chip.ngpio;
890 +               gpio_nr += CONFIG_S3C_GPIO_SPACE;
891 +       }
892 +}
893 +
894 +/**
895 + * s3c_pm_resume_gpio() - restore gpio chip data after suspend
896 + * @ourchip: The suspended chip.
897 + */
898 +static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
899 +{
900 +       struct s3c_gpio_pm *pm = ourchip->pm;
901 +
902 +       if (pm == NULL || pm->resume == NULL)
903 +               S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
904 +       else
905 +               pm->resume(ourchip);
906 +}
907 +
908 +void s3c_pm_restore_gpios(void)
909 +{
910 +       struct s3c_gpio_chip *ourchip;
911 +       unsigned int gpio_nr;
912 +
913 +       for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
914 +               ourchip = s3c_gpiolib_getchip(gpio_nr);
915 +               if (!ourchip)
916 +                       continue;
917 +
918 +               s3c_pm_resume_gpio(ourchip);
919 +
920 +               gpio_nr += ourchip->chip.ngpio;
921 +               gpio_nr += CONFIG_S3C_GPIO_SPACE;
922 +       }
923 +}
924 --- a/arch/arm/plat-s3c24xx/clock-dclk.c
925 +++ b/arch/arm/plat-s3c24xx/clock-dclk.c
926 @@ -18,6 +18,7 @@
927  
928  #include <mach/regs-clock.h>
929  #include <mach/regs-gpio.h>
930 +#include <mach/hardware.h>
931  
932  #include <plat/clock.h>
933  #include <plat/cpu.h>
934 --- a/arch/arm/plat-s3c24xx/cpu.c
935 +++ b/arch/arm/plat-s3c24xx/cpu.c
936 @@ -61,6 +61,7 @@ static const char name_s3c2410[]  = "S3C
937  static const char name_s3c2412[]  = "S3C2412";
938  static const char name_s3c2440[]  = "S3C2440";
939  static const char name_s3c2442[]  = "S3C2442";
940 +static const char name_s3c2442b[]  = "S3C2442B";
941  static const char name_s3c2443[]  = "S3C2443";
942  static const char name_s3c2410a[] = "S3C2410A";
943  static const char name_s3c2440a[] = "S3C2440A";
944 @@ -112,6 +113,15 @@ static struct cpu_table cpu_ids[] __init
945                 .name           = name_s3c2442
946         },
947         {
948 +               .idcode         = 0x32440aab,
949 +               .idmask         = 0xffffffff,
950 +               .map_io         = s3c244x_map_io,
951 +               .init_clocks    = s3c244x_init_clocks,
952 +               .init_uarts     = s3c244x_init_uarts,
953 +               .init           = s3c2442_init,
954 +               .name           = name_s3c2442b
955 +       },
956 +       {
957                 .idcode         = 0x32412001,
958                 .idmask         = 0xffffffff,
959                 .map_io         = s3c2412_map_io,
960 --- a/arch/arm/plat-s3c24xx/gpiolib.c
961 +++ b/arch/arm/plat-s3c24xx/gpiolib.c
962 @@ -19,9 +19,10 @@
963  #include <linux/io.h>
964  #include <linux/gpio.h>
965  
966 -#include <mach/gpio-core.h>
967 +#include <plat/gpio-core.h>
968  #include <mach/hardware.h>
969  #include <asm/irq.h>
970 +#include <plat/pm.h>
971  
972  #include <mach/regs-gpio.h>
973  
974 @@ -78,6 +79,7 @@ static int s3c24xx_gpiolib_bankg_toirq(s
975  struct s3c_gpio_chip s3c24xx_gpios[] = {
976         [0] = {
977                 .base   = S3C24XX_GPIO_BASE(S3C2410_GPA0),
978 +               .pm     = __gpio_pm(&s3c_gpio_pm_1bit),
979                 .chip   = {
980                         .base                   = S3C2410_GPA0,
981                         .owner                  = THIS_MODULE,
982 @@ -89,6 +91,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
983         },
984         [1] = {
985                 .base   = S3C24XX_GPIO_BASE(S3C2410_GPB0),
986 +               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
987                 .chip   = {
988                         .base                   = S3C2410_GPB0,
989                         .owner                  = THIS_MODULE,
990 @@ -98,6 +101,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
991         },
992         [2] = {
993                 .base   = S3C24XX_GPIO_BASE(S3C2410_GPC0),
994 +               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
995                 .chip   = {
996                         .base                   = S3C2410_GPC0,
997                         .owner                  = THIS_MODULE,
998 @@ -107,6 +111,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
999         },
1000         [3] = {
1001                 .base   = S3C24XX_GPIO_BASE(S3C2410_GPD0),
1002 +               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
1003                 .chip   = {
1004                         .base                   = S3C2410_GPD0,
1005                         .owner                  = THIS_MODULE,
1006 @@ -116,6 +121,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
1007         },
1008         [4] = {
1009                 .base   = S3C24XX_GPIO_BASE(S3C2410_GPE0),
1010 +               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
1011                 .chip   = {
1012                         .base                   = S3C2410_GPE0,
1013                         .label                  = "GPIOE",
1014 @@ -125,6 +131,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
1015         },
1016         [5] = {
1017                 .base   = S3C24XX_GPIO_BASE(S3C2410_GPF0),
1018 +               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
1019                 .chip   = {
1020                         .base                   = S3C2410_GPF0,
1021                         .owner                  = THIS_MODULE,
1022 @@ -135,12 +142,23 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
1023         },
1024         [6] = {
1025                 .base   = S3C24XX_GPIO_BASE(S3C2410_GPG0),
1026 +               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
1027                 .chip   = {
1028                         .base                   = S3C2410_GPG0,
1029                         .owner                  = THIS_MODULE,
1030                         .label                  = "GPIOG",
1031 -                       .ngpio                  = 10,
1032                         .to_irq                 = s3c24xx_gpiolib_bankg_toirq,
1033 +                       .ngpio                  = 16,
1034 +               },
1035 +       },
1036 +       [7] = {
1037 +               .base   = S3C24XX_GPIO_BASE(S3C2410_GPH0),
1038 +               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
1039 +               .chip   = {
1040 +                       .base                   = S3C2410_GPH0,
1041 +                       .owner                  = THIS_MODULE,
1042 +                       .label                  = "GPIOH",
1043 +                       .ngpio                  = 11,
1044                 },
1045         },
1046  };
1047 --- a/arch/arm/plat-s3c24xx/include/plat/pm-core.h
1048 +++ b/arch/arm/plat-s3c24xx/include/plat/pm-core.h
1049 @@ -57,3 +57,8 @@ static inline void s3c_pm_arch_show_resu
1050         s3c_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
1051                                 s3c_irqwake_eintmask);
1052  }
1053 +
1054 +static inline void s3c_pm_arch_update_uart(void __iomem *regs,
1055 +                                          struct pm_uart_save *save)
1056 +{
1057 +}
1058 --- a/arch/arm/plat-s3c24xx/irq-pm.c
1059 +++ b/arch/arm/plat-s3c24xx/irq-pm.c
1060 @@ -15,6 +15,7 @@
1061  #include <linux/module.h>
1062  #include <linux/interrupt.h>
1063  #include <linux/sysdev.h>
1064 +#include <linux/irq.h>
1065  
1066  #include <plat/cpu.h>
1067  #include <plat/pm.h>
1068 @@ -80,7 +81,9 @@ int s3c24xx_irq_suspend(struct sys_devic
1069  
1070  int s3c24xx_irq_resume(struct sys_device *dev)
1071  {
1072 -       unsigned int i;
1073 +       unsigned int i, irq;
1074 +       unsigned long eintpnd;
1075 +       struct irq_desc *desc;
1076  
1077         for (i = 0; i < ARRAY_SIZE(save_extint); i++)
1078                 __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
1079 @@ -91,5 +94,25 @@ int s3c24xx_irq_resume(struct sys_device
1080         s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
1081         __raw_writel(save_eintmask, S3C24XX_EINTMASK);
1082  
1083 +       /*
1084 +        * ACK those interrupts which are now masked and pending.
1085 +        * Level interrupts if not ACKed here, create an interrupt storm
1086 +        * because they are not handled at all.
1087 +        */
1088 +
1089 +       eintpnd = __raw_readl(S3C24XX_EINTPEND);
1090 +
1091 +       eintpnd &= save_eintmask;
1092 +       eintpnd &= ~0xff;       /* ignore lower irqs */
1093 +
1094 +       while (eintpnd) {
1095 +               irq = __ffs(eintpnd);
1096 +               eintpnd &= ~(1 << irq);
1097 +
1098 +               irq += (IRQ_EINT4 - 4);
1099 +               desc = irq_to_desc(irq);
1100 +               desc->chip->ack(irq);
1101 +       }
1102 +
1103         return 0;
1104  }
1105 --- a/arch/arm/plat-s3c24xx/pm.c
1106 +++ b/arch/arm/plat-s3c24xx/pm.c
1107 @@ -39,6 +39,7 @@
1108  #include <mach/regs-gpio.h>
1109  #include <mach/regs-mem.h>
1110  #include <mach/regs-irq.h>
1111 +#include <mach/hardware.h>
1112  
1113  #include <asm/mach/time.h>
1114  
1115 @@ -75,43 +76,10 @@ static struct sleep_save core_save[] = {
1116         SAVE_ITEM(S3C2410_CLKSLOW),
1117  };
1118  
1119 -static struct gpio_sleep {
1120 -       void __iomem    *base;
1121 -       unsigned int     gpcon;
1122 -       unsigned int     gpdat;
1123 -       unsigned int     gpup;
1124 -} gpio_save[] = {
1125 -       [0] = {
1126 -               .base   = S3C2410_GPACON,
1127 -       },
1128 -       [1] = {
1129 -               .base   = S3C2410_GPBCON,
1130 -       },
1131 -       [2] = {
1132 -               .base   = S3C2410_GPCCON,
1133 -       },
1134 -       [3] = {
1135 -               .base   = S3C2410_GPDCON,
1136 -       },
1137 -       [4] = {
1138 -               .base   = S3C2410_GPECON,
1139 -       },
1140 -       [5] = {
1141 -               .base   = S3C2410_GPFCON,
1142 -       },
1143 -       [6] = {
1144 -               .base   = S3C2410_GPGCON,
1145 -       },
1146 -       [7] = {
1147 -               .base   = S3C2410_GPHCON,
1148 -       },
1149 -};
1150 -
1151  static struct sleep_save misc_save[] = {
1152         SAVE_ITEM(S3C2410_DCLKCON),
1153  };
1154  
1155 -
1156  /* s3c_pm_check_resume_pin
1157   *
1158   * check to see if the pin is configured correctly for sleep mode, and
1159 @@ -165,186 +133,6 @@ void s3c_pm_configure_extint(void)
1160         }
1161  }
1162  
1163 -/* offsets for CON/DAT/UP registers */
1164 -
1165 -#define OFFS_CON       (S3C2410_GPACON - S3C2410_GPACON)
1166 -#define OFFS_DAT       (S3C2410_GPADAT - S3C2410_GPACON)
1167 -#define OFFS_UP                (S3C2410_GPBUP  - S3C2410_GPBCON)
1168 -
1169 -/* s3c_pm_save_gpios()
1170 - *
1171 - * Save the state of the GPIOs
1172 - */
1173 -
1174 -void s3c_pm_save_gpios(void)
1175 -{
1176 -       struct gpio_sleep *gps = gpio_save;
1177 -       unsigned int gpio;
1178 -
1179 -       for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
1180 -               void __iomem *base = gps->base;
1181 -
1182 -               gps->gpcon = __raw_readl(base + OFFS_CON);
1183 -               gps->gpdat = __raw_readl(base + OFFS_DAT);
1184 -
1185 -               if (gpio > 0)
1186 -                       gps->gpup = __raw_readl(base + OFFS_UP);
1187 -
1188 -       }
1189 -}
1190 -
1191 -/* Test whether the given masked+shifted bits of an GPIO configuration
1192 - * are one of the SFN (special function) modes. */
1193 -
1194 -static inline int is_sfn(unsigned long con)
1195 -{
1196 -       return (con == 2 || con == 3);
1197 -}
1198 -
1199 -/* Test if the given masked+shifted GPIO configuration is an input */
1200 -
1201 -static inline int is_in(unsigned long con)
1202 -{
1203 -       return con == 0;
1204 -}
1205 -
1206 -/* Test if the given masked+shifted GPIO configuration is an output */
1207 -
1208 -static inline int is_out(unsigned long con)
1209 -{
1210 -       return con == 1;
1211 -}
1212 -
1213 -/**
1214 - * s3c2410_pm_restore_gpio() - restore the given GPIO bank
1215 - * @index: The number of the GPIO bank being resumed.
1216 - * @gps: The sleep confgiuration for the bank.
1217 - *
1218 - * Restore one of the GPIO banks that was saved during suspend. This is
1219 - * not as simple as once thought, due to the possibility of glitches
1220 - * from the order that the CON and DAT registers are set in.
1221 - *
1222 - * The three states the pin can be are {IN,OUT,SFN} which gives us 9
1223 - * combinations of changes to check. Three of these, if the pin stays
1224 - * in the same configuration can be discounted. This leaves us with
1225 - * the following:
1226 - *
1227 - * { IN => OUT }  Change DAT first
1228 - * { IN => SFN }  Change CON first
1229 - * { OUT => SFN } Change CON first, so new data will not glitch
1230 - * { OUT => IN }  Change CON first, so new data will not glitch
1231 - * { SFN => IN }  Change CON first
1232 - * { SFN => OUT } Change DAT first, so new data will not glitch [1]
1233 - *
1234 - * We do not currently deal with the UP registers as these control
1235 - * weak resistors, so a small delay in change should not need to bring
1236 - * these into the calculations.
1237 - *
1238 - * [1] this assumes that writing to a pin DAT whilst in SFN will set the
1239 - *     state for when it is next output.
1240 - */
1241 -
1242 -static void s3c2410_pm_restore_gpio(int index, struct gpio_sleep *gps)
1243 -{
1244 -       void __iomem *base = gps->base;
1245 -       unsigned long gps_gpcon = gps->gpcon;
1246 -       unsigned long gps_gpdat = gps->gpdat;
1247 -       unsigned long old_gpcon;
1248 -       unsigned long old_gpdat;
1249 -       unsigned long old_gpup = 0x0;
1250 -       unsigned long gpcon;
1251 -       int nr;
1252 -
1253 -       old_gpcon = __raw_readl(base + OFFS_CON);
1254 -       old_gpdat = __raw_readl(base + OFFS_DAT);
1255 -
1256 -       if (base == S3C2410_GPACON) {
1257 -               /* GPACON only has one bit per control / data and no PULLUPs.
1258 -                * GPACON[x] = 0 => Output, 1 => SFN */
1259 -
1260 -               /* first set all SFN bits to SFN */
1261 -
1262 -               gpcon = old_gpcon | gps->gpcon;
1263 -               __raw_writel(gpcon, base + OFFS_CON);
1264 -
1265 -               /* now set all the other bits */
1266 -
1267 -               __raw_writel(gps_gpdat, base + OFFS_DAT);
1268 -               __raw_writel(gps_gpcon, base + OFFS_CON);
1269 -       } else {
1270 -               unsigned long old, new, mask;
1271 -               unsigned long change_mask = 0x0;
1272 -
1273 -               old_gpup = __raw_readl(base + OFFS_UP);
1274 -
1275 -               /* Create a change_mask of all the items that need to have
1276 -                * their CON value changed before their DAT value, so that
1277 -                * we minimise the work between the two settings.
1278 -                */
1279 -
1280 -               for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
1281 -                       old = (old_gpcon & mask) >> nr;
1282 -                       new = (gps_gpcon & mask) >> nr;
1283 -
1284 -                       /* If there is no change, then skip */
1285 -
1286 -                       if (old == new)
1287 -                               continue;
1288 -
1289 -                       /* If both are special function, then skip */
1290 -
1291 -                       if (is_sfn(old) && is_sfn(new))
1292 -                               continue;
1293 -
1294 -                       /* Change is IN => OUT, do not change now */
1295 -
1296 -                       if (is_in(old) && is_out(new))
1297 -                               continue;
1298 -
1299 -                       /* Change is SFN => OUT, do not change now */
1300 -
1301 -                       if (is_sfn(old) && is_out(new))
1302 -                               continue;
1303 -
1304 -                       /* We should now be at the case of IN=>SFN,
1305 -                        * OUT=>SFN, OUT=>IN, SFN=>IN. */
1306 -
1307 -                       change_mask |= mask;
1308 -               }
1309 -
1310 -               /* Write the new CON settings */
1311 -
1312 -               gpcon = old_gpcon & ~change_mask;
1313 -               gpcon |= gps_gpcon & change_mask;
1314 -
1315 -               __raw_writel(gpcon, base + OFFS_CON);
1316 -
1317 -               /* Now change any items that require DAT,CON */
1318 -
1319 -               __raw_writel(gps_gpdat, base + OFFS_DAT);
1320 -               __raw_writel(gps_gpcon, base + OFFS_CON);
1321 -               __raw_writel(gps->gpup, base + OFFS_UP);
1322 -       }
1323 -
1324 -       S3C_PMDBG("GPIO[%d] CON %08lx => %08lx, DAT %08lx => %08lx\n",
1325 -                 index, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
1326 -}
1327 -
1328 -
1329 -/** s3c2410_pm_restore_gpios()
1330 - *
1331 - * Restore the state of the GPIOs
1332 - */
1333 -
1334 -void s3c_pm_restore_gpios(void)
1335 -{
1336 -       struct gpio_sleep *gps = gpio_save;
1337 -       int gpio;
1338 -
1339 -       for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
1340 -               s3c2410_pm_restore_gpio(gpio, gps);
1341 -       }
1342 -}
1343  
1344  void s3c_pm_restore_core(void)
1345  {
1346 --- a/drivers/mmc/host/Kconfig
1347 +++ b/drivers/mmc/host/Kconfig
1348 @@ -37,13 +37,6 @@ config MMC_SDHCI
1349  
1350           If unsure, say N.
1351  
1352 -config MMC_SDHCI_IO_ACCESSORS
1353 -       bool
1354 -       depends on MMC_SDHCI
1355 -       help
1356 -         This is silent Kconfig symbol that is selected by the drivers that
1357 -         need to overwrite SDHCI IO memory accessors.
1358 -
1359  config MMC_SDHCI_PCI
1360         tristate "SDHCI support on PCI bus"
1361         depends on MMC_SDHCI && PCI
1362 @@ -55,6 +48,18 @@ config MMC_SDHCI_PCI
1363  
1364           If unsure, say N.
1365  
1366 +config MMC_SDHCI_S3C
1367 +       tristate "SDHCI support on Samsung S3C SoC"
1368 +       depends on MMC_SDHCI && PLAT_S3C24XX
1369 +       help
1370 +         This selects the Secure Digital Host Controller Interface (SDHCI)
1371 +         often referrered to as the HSMMC block in some of the Samsung S3C
1372 +         range of SoC.
1373 +
1374 +         If you have a controller with this interface, say Y or M here.
1375 +
1376 +         If unsure, say N.
1377 +
1378  config MMC_RICOH_MMC
1379         tristate "Ricoh MMC Controller Disabler  (EXPERIMENTAL)"
1380         depends on MMC_SDHCI_PCI
1381 @@ -72,17 +77,6 @@ config MMC_RICOH_MMC
1382  
1383           If unsure, say Y.
1384  
1385 -config MMC_SDHCI_OF
1386 -       tristate "SDHCI support on OpenFirmware platforms"
1387 -       depends on MMC_SDHCI && PPC_OF
1388 -       select MMC_SDHCI_IO_ACCESSORS
1389 -       help
1390 -         This selects the OF support for Secure Digital Host Controller
1391 -         Interfaces. So far, only the Freescale eSDHC controller is known
1392 -         to exist on OF platforms.
1393 -
1394 -         If unsure, say N.
1395 -
1396  config MMC_OMAP
1397         tristate "TI OMAP Multimedia Card Interface support"
1398         depends on ARCH_OMAP
1399 @@ -163,16 +157,6 @@ config MMC_IMX
1400  
1401           If unsure, say N.
1402  
1403 -config MMC_MXC
1404 -       tristate "Freescale i.MX2/3 Multimedia Card Interface support"
1405 -       depends on ARCH_MXC
1406 -       help
1407 -         This selects the Freescale i.MX2/3 Multimedia card Interface.
1408 -         If you have a i.MX platform with a Multimedia Card slot,
1409 -         say Y or M here.
1410 -
1411 -         If unsure, say N.
1412 -
1413  config MMC_TIFM_SD
1414         tristate "TI Flash Media MMC/SD Interface support  (EXPERIMENTAL)"
1415         depends on EXPERIMENTAL && PCI
1416 --- a/drivers/mmc/host/Makefile
1417 +++ b/drivers/mmc/host/Makefile
1418 @@ -9,11 +9,10 @@ endif
1419  obj-$(CONFIG_MMC_ARMMMCI)      += mmci.o
1420  obj-$(CONFIG_MMC_PXA)          += pxamci.o
1421  obj-$(CONFIG_MMC_IMX)          += imxmmc.o
1422 -obj-$(CONFIG_MMC_MXC)          += mxcmmc.o
1423  obj-$(CONFIG_MMC_SDHCI)                += sdhci.o
1424  obj-$(CONFIG_MMC_SDHCI_PCI)    += sdhci-pci.o
1425 +obj-$(CONFIG_MMC_SDHCI_S3C)    += sdhci-s3c.o
1426  obj-$(CONFIG_MMC_RICOH_MMC)    += ricoh_mmc.o
1427 -obj-$(CONFIG_MMC_SDHCI_OF)     += sdhci-of.o
1428  obj-$(CONFIG_MMC_WBSD)         += wbsd.o
1429  obj-$(CONFIG_MMC_AU1X)         += au1xmmc.o
1430  obj-$(CONFIG_MMC_OMAP)         += omap.o
1431 @@ -21,7 +20,6 @@ obj-$(CONFIG_MMC_OMAP_HS)     += omap_hsmmc.
1432  obj-$(CONFIG_MMC_AT91)         += at91_mci.o
1433  obj-$(CONFIG_MMC_ATMELMCI)     += atmel-mci.o
1434  obj-$(CONFIG_MMC_TIFM_SD)      += tifm_sd.o
1435 -obj-$(CONFIG_MMC_MVSDIO)       += mvsdio.o
1436  obj-$(CONFIG_MMC_SPI)          += mmc_spi.o
1437  ifeq ($(CONFIG_OF),y)
1438  obj-$(CONFIG_MMC_SPI)          += of_mmc_spi.o
1439 --- a/drivers/mmc/host/s3cmci.c
1440 +++ b/drivers/mmc/host/s3cmci.c
1441 @@ -2,6 +2,7 @@
1442   *  linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver
1443   *
1444   *  Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de>
1445 + *  Copyright (C) 2007 Harald Welte <laforge@gnumonks.org>
1446   *
1447   * Current driver maintained by Ben Dooks and Simtec Electronics
1448   *  Copyright (C) 2008 Simtec Electronics <ben-linux@fluff.org>
1449 @@ -24,9 +25,18 @@
1450  
1451  #include <mach/regs-sdi.h>
1452  #include <mach/regs-gpio.h>
1453 +#include <mach/hardware.h>
1454  
1455  #include <plat/mci.h>
1456  
1457 +#include <asm/dma.h>
1458 +#include <asm/dma-mapping.h>
1459 +
1460 +#include <asm/io.h>
1461 +#include <mach/regs-gpio.h>
1462 +#include <mach/mci.h>
1463 +#include <mach/dma.h>
1464 +
1465  #include "s3cmci.h"
1466  
1467  #define DRIVER_NAME "s3c-mci"
1468 @@ -47,6 +57,9 @@ static const int dbgmap_err   = dbg_fail
1469  static const int dbgmap_info  = dbg_info | dbg_conf;
1470  static const int dbgmap_debug = dbg_err | dbg_debug;
1471  
1472 +static int f_max = -1; /* override maximum frequency limit */
1473 +static int persist; /* keep interface alive across suspend/resume */
1474 +
1475  #define dbg(host, channels, args...)             \
1476         do {                                      \
1477         if (dbgmap_err & channels)                \
1478 @@ -280,8 +293,11 @@ static void do_pio_read(struct s3cmci_ho
1479                  * an even multiple of 4. */
1480                 if (fifo >= host->pio_bytes)
1481                         fifo = host->pio_bytes;
1482 -               else
1483 +               else {
1484                         fifo -= fifo & 3;
1485 +                       if (!fifo)
1486 +                               break;
1487 +               }
1488  
1489                 host->pio_bytes -= fifo;
1490                 host->pio_count += fifo;
1491 @@ -329,7 +345,7 @@ static void do_pio_write(struct s3cmci_h
1492  
1493         to_ptr = host->base + host->sdidata;
1494  
1495 -       while ((fifo = fifo_free(host)) > 3) {
1496 +       while ((fifo = fifo_free(host))) {
1497                 if (!host->pio_bytes) {
1498                         res = get_data_buffer(host, &host->pio_bytes,
1499                                                         &host->pio_ptr);
1500 @@ -353,8 +369,11 @@ static void do_pio_write(struct s3cmci_h
1501                  * words, so round down to an even multiple of 4. */
1502                 if (fifo >= host->pio_bytes)
1503                         fifo = host->pio_bytes;
1504 -               else
1505 +               else {
1506                         fifo -= fifo & 3;
1507 +                       if (!fifo)
1508 +                               break;
1509 +               }
1510  
1511                 host->pio_bytes -= fifo;
1512                 host->pio_count += fifo;
1513 @@ -373,7 +392,6 @@ static void pio_tasklet(unsigned long da
1514  {
1515         struct s3cmci_host *host = (struct s3cmci_host *) data;
1516  
1517 -
1518         disable_irq(host->irq);
1519  
1520         if (host->pio_active == XFER_WRITE)
1521 @@ -614,7 +632,6 @@ irq_out:
1522  
1523         spin_unlock_irqrestore(&host->complete_lock, iflags);
1524         return IRQ_HANDLED;
1525 -
1526  }
1527  
1528  /*
1529 @@ -789,11 +806,11 @@ static void s3cmci_dma_setup(struct s3cm
1530  
1531         last_source = source;
1532  
1533 -       s3c2410_dma_devconfig(host->dma, source, 3,
1534 +       s3c2410_dma_devconfig(host->dma, source,
1535                               host->mem->start + host->sdidata);
1536  
1537         if (!setup_ok) {
1538 -               s3c2410_dma_config(host->dma, 4, 0);
1539 +               s3c2410_dma_config(host->dma, 4);
1540                 s3c2410_dma_set_buffdone_fn(host->dma,
1541                                             s3cmci_dma_done_callback);
1542                 s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
1543 @@ -1026,6 +1043,7 @@ static void s3cmci_send_request(struct m
1544                         dbg(host, dbg_err, "data prepare error %d\n", res);
1545                         cmd->error = res;
1546                         cmd->data->error = res;
1547 +                       cmd->data->error = -EIO;
1548  
1549                         mmc_request_done(mmc, mrq);
1550                         return;
1551 @@ -1263,10 +1281,8 @@ static int __devinit s3cmci_probe(struct
1552         host->is2440    = is2440;
1553  
1554         host->pdata = pdev->dev.platform_data;
1555 -       if (!host->pdata) {
1556 -               pdev->dev.platform_data = &s3cmci_def_pdata;
1557 +       if (!host->pdata)
1558                 host->pdata = &s3cmci_def_pdata;
1559 -       }
1560  
1561         spin_lock_init(&host->complete_lock);
1562         tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
1563 @@ -1379,6 +1395,18 @@ static int __devinit s3cmci_probe(struct
1564         mmc->f_min      = host->clk_rate / (host->clk_div * 256);
1565         mmc->f_max      = host->clk_rate / host->clk_div;
1566  
1567 +       if (f_max >= 0) {
1568 +               unsigned f = f_max;
1569 +
1570 +               if (f < mmc->f_min)
1571 +                       f = mmc->f_min;
1572 +               if (mmc->f_max > f) {
1573 +                       dev_info(&pdev->dev, "f_max lowered from %u to %u Hz\n",
1574 +                           mmc->f_max, f);
1575 +                       mmc->f_max = f;
1576 +               }
1577 +       }
1578 +
1579         if (host->pdata->ocr_avail)
1580                 mmc->ocr_avail = host->pdata->ocr_avail;
1581  
1582 @@ -1491,18 +1519,60 @@ static int __devinit s3cmci_2440_probe(s
1583  
1584  #ifdef CONFIG_PM
1585  
1586 +static int save_regs(struct mmc_host *mmc)
1587 +{
1588 +       struct s3cmci_host *host = mmc_priv(mmc);
1589 +       unsigned long flags;
1590 +       unsigned from;
1591 +       u32 *to = host->saved;
1592 +
1593 +       mmc_flush_scheduled_work();
1594 +
1595 +       local_irq_save(flags);
1596 +       for (from = S3C2410_SDICON; from != S3C2410_SDIIMSK+4; from += 4)
1597 +               if (from != host->sdidata)
1598 +                       *to++ = readl(host->base + from);
1599 +       BUG_ON(to-host->saved != ARRAY_SIZE(host->saved));
1600 +       local_irq_restore(flags);
1601 +
1602 +       return 0;
1603 +}
1604 +
1605 +static int restore_regs(struct mmc_host *mmc)
1606 +{
1607 +       struct s3cmci_host *host = mmc_priv(mmc);
1608 +       unsigned long flags;
1609 +       unsigned to;
1610 +       u32 *from = host->saved;
1611 +
1612 +       /*
1613 +        * Before we begin with the necromancy, make sure we don't
1614 +        * inadvertently start something we'll regret microseconds later.
1615 +        */
1616 +       from[S3C2410_SDICMDCON - S3C2410_SDICON] = 0;
1617 +
1618 +       local_irq_save(flags);
1619 +       for (to = S3C2410_SDICON; to != S3C2410_SDIIMSK+4; to += 4)
1620 +               if (to != host->sdidata)
1621 +                       writel(*from++, host->base + to);
1622 +       BUG_ON(from-host->saved != ARRAY_SIZE(host->saved));
1623 +       local_irq_restore(flags);
1624 +
1625 +       return 0;
1626 +}
1627 +
1628  static int s3cmci_suspend(struct platform_device *dev, pm_message_t state)
1629  {
1630         struct mmc_host *mmc = platform_get_drvdata(dev);
1631  
1632 -       return  mmc_suspend_host(mmc, state);
1633 +       return persist ? save_regs(mmc) : mmc_suspend_host(mmc, state);
1634  }
1635  
1636  static int s3cmci_resume(struct platform_device *dev)
1637  {
1638         struct mmc_host *mmc = platform_get_drvdata(dev);
1639  
1640 -       return mmc_resume_host(mmc);
1641 +       return persist ? restore_regs(mmc) : mmc_resume_host(mmc);
1642  }
1643  
1644  #else /* CONFIG_PM */
1645 @@ -1560,9 +1630,13 @@ static void __exit s3cmci_exit(void)
1646  module_init(s3cmci_init);
1647  module_exit(s3cmci_exit);
1648  
1649 +module_param(f_max, int, 0644);
1650 +module_param(persist, int, 0644);
1651 +
1652  MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
1653  MODULE_LICENSE("GPL v2");
1654  MODULE_AUTHOR("Thomas Kleffel <tk@maintech.de>, Ben Dooks <ben-linux@fluff.org>");
1655  MODULE_ALIAS("platform:s3c2410-sdi");
1656  MODULE_ALIAS("platform:s3c2412-sdi");
1657  MODULE_ALIAS("platform:s3c2440-sdi");
1658 +
1659 --- a/drivers/mmc/host/s3cmci.h
1660 +++ b/drivers/mmc/host/s3cmci.h
1661 @@ -8,6 +8,10 @@
1662   * published by the Free Software Foundation.
1663   */
1664  
1665 +
1666 +#include <mach/regs-sdi.h>
1667 +#include <linux/regulator/consumer.h>
1668 +
1669  /* FIXME: DMA Resource management ?! */
1670  #define S3CMCI_DMA 0
1671  
1672 @@ -68,7 +72,16 @@ struct s3cmci_host {
1673         unsigned int            ccnt, dcnt;
1674         struct tasklet_struct   pio_tasklet;
1675  
1676 +       /*
1677 +        * Here's where we save the registers during suspend. Note that we skip
1678 +        * SDIDATA, which is at different positions on 2410 and 2440, so
1679 +        * there's no "+1" in the array size.
1680 +        */
1681 +       u32                     saved[(S3C2410_SDIIMSK-S3C2410_SDICON)/4];
1682 +
1683  #ifdef CONFIG_CPU_FREQ
1684         struct notifier_block   freq_transition;
1685  #endif
1686 +
1687 +       struct regulator *regulator;
1688  };
1689 --- /dev/null
1690 +++ b/drivers/mmc/host/sdhci-s3c.c
1691 @@ -0,0 +1,419 @@
1692 +/* linux/drivers/mmc/host/sdhci-s3c.c
1693 + *
1694 + * Copyright 2008 Openmoko Inc.
1695 + * Copyright 2008 Simtec Electronics
1696 + *      Ben Dooks <ben@simtec.co.uk>
1697 + *      http://armlinux.simtec.co.uk/
1698 + *
1699 + * SDHCI (HSMMC) support for Samsung SoC
1700 + *
1701 + * This program is free software; you can redistribute it and/or modify
1702 + * it under the terms of the GNU General Public License version 2 as
1703 + * published by the Free Software Foundation.
1704 + */
1705 +
1706 +#include <linux/delay.h>
1707 +#include <linux/dma-mapping.h>
1708 +#include <linux/platform_device.h>
1709 +#include <linux/clk.h>
1710 +#include <linux/io.h>
1711 +
1712 +#include <linux/mmc/host.h>
1713 +
1714 +#include <plat/regs-sdhci.h>
1715 +#include <plat/sdhci.h>
1716 +
1717 +#include "sdhci.h"
1718 +
1719 +#define MAX_BUS_CLK    (4)
1720 +
1721 +struct sdhci_s3c {
1722 +       struct sdhci_host       *host;
1723 +       struct platform_device  *pdev;
1724 +       struct resource         *ioarea;
1725 +       struct s3c_sdhci_platdata *pdata;
1726 +       unsigned int            cur_clk;
1727 +
1728 +       struct clk              *clk_io;        /* clock for io bus */
1729 +       struct clk              *clk_bus[MAX_BUS_CLK];
1730 +};
1731 +
1732 +static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
1733 +{
1734 +       return sdhci_priv(host);
1735 +}
1736 +
1737 +static u32 get_curclk(u32 ctrl2)
1738 +{
1739 +       ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
1740 +       ctrl2 >>= S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
1741 +
1742 +       return ctrl2;
1743 +}
1744 +
1745 +static void sdhci_s3c_check_sclk(struct sdhci_host *host)
1746 +{
1747 +       struct sdhci_s3c *ourhost = to_s3c(host);
1748 +       u32 tmp = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
1749 +
1750 +       if (get_curclk(tmp) != ourhost->cur_clk) {
1751 +               dev_dbg(&ourhost->pdev->dev, "restored ctrl2 clock setting\n");
1752 +
1753 +               tmp &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
1754 +               tmp |= ourhost->cur_clk << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
1755 +               writel(tmp, host->ioaddr + 0x80);
1756 +       }
1757 +}
1758 +
1759 +static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host)
1760 +{
1761 +       struct sdhci_s3c *ourhost = to_s3c(host);
1762 +       struct clk *busclk;
1763 +       unsigned int rate, max;
1764 +       int clk;
1765 +
1766 +       /* note, a reset will reset the clock source */
1767 +
1768 +       sdhci_s3c_check_sclk(host);
1769 +
1770 +       for (max = 0, clk = 0; clk < MAX_BUS_CLK; clk++) {
1771 +               busclk = ourhost->clk_bus[clk];
1772 +               if (!busclk)
1773 +                       continue;
1774 +
1775 +               rate = clk_get_rate(busclk);
1776 +               if (rate > max)
1777 +                       max = rate;
1778 +       }
1779 +
1780 +       return max;
1781 +}
1782 +
1783 +static unsigned int sdhci_s3c_get_timeout_clk(struct sdhci_host *host)
1784 +{
1785 +       return sdhci_s3c_get_max_clk(host) / 1000000;
1786 +}
1787 +
1788 +static void sdhci_s3c_set_ios(struct sdhci_host *host,
1789 +                             struct mmc_ios *ios)
1790 +{
1791 +       struct sdhci_s3c *ourhost = to_s3c(host);
1792 +       struct s3c_sdhci_platdata *pdata = ourhost->pdata;
1793 +       int width;
1794 +
1795 +       sdhci_s3c_check_sclk(host);
1796 +
1797 +       if (ios->power_mode != MMC_POWER_OFF) {
1798 +               switch (ios->bus_width) {
1799 +               case MMC_BUS_WIDTH_4:
1800 +                       width = 4;
1801 +                       break;
1802 +               case MMC_BUS_WIDTH_1:
1803 +                       width = 1;
1804 +                       break;
1805 +               default:
1806 +                       BUG();
1807 +               }
1808 +
1809 +               if (pdata->cfg_gpio)
1810 +                       pdata->cfg_gpio(ourhost->pdev, width);
1811 +       }
1812 +
1813 +       if (pdata->cfg_card)
1814 +               pdata->cfg_card(ourhost->pdev, host->ioaddr,
1815 +                               ios, host->mmc->card);
1816 +}
1817 +
1818 +static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
1819 +                                            unsigned int src,
1820 +                                            unsigned int wanted)
1821 +{
1822 +       unsigned long rate;
1823 +       struct clk *clksrc = ourhost->clk_bus[src];
1824 +       int div;
1825 +
1826 +       if (!clksrc)
1827 +               return UINT_MAX;
1828 +
1829 +       rate = clk_get_rate(clksrc);
1830 +
1831 +       for (div = 1; div < 256; div *= 2) {
1832 +               if ((rate / div) <= wanted)
1833 +                       break;
1834 +       }
1835 +
1836 +       dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n",
1837 +               src, rate, wanted, rate / div);
1838 +
1839 +       return (wanted - (rate / div));
1840 +}
1841 +
1842 +static void sdhci_s3c_change_clock(struct sdhci_host *host, unsigned int clock)
1843 +{
1844 +       struct sdhci_s3c *ourhost = to_s3c(host);
1845 +       unsigned int best = UINT_MAX;
1846 +       unsigned int delta;
1847 +       int best_src = 0;
1848 +       int src;
1849 +       u32 ctrl;
1850 +
1851 +       for (src = 0; src < MAX_BUS_CLK; src++) {
1852 +               delta = sdhci_s3c_consider_clock(ourhost, src, clock);
1853 +               if (delta < best) {
1854 +                       best = delta;
1855 +                       best_src = src;
1856 +               }
1857 +       }
1858 +
1859 +       dev_dbg(&ourhost->pdev->dev,
1860 +               "selected source %d, clock %d, delta %d\n",
1861 +                best_src, clock, best);
1862 +
1863 +       /* turn clock off to card before changing clock source */
1864 +       writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
1865 +
1866 +       /* select the new clock source */
1867 +
1868 +       if (ourhost->cur_clk != best_src) {
1869 +               struct clk *clk = ourhost->clk_bus[best_src];
1870 +
1871 +               ourhost->cur_clk = best_src;
1872 +               host->max_clk = clk_get_rate(clk);
1873 +               host->timeout_clk = host->max_clk / 1000000;
1874 +
1875 +               ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
1876 +               ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
1877 +               ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
1878 +               writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2);
1879 +       }
1880 +
1881 +       sdhci_change_clock(host, clock);
1882 +}
1883 +
1884 +static struct sdhci_ops sdhci_s3c_ops = {
1885 +       .get_max_clock          = sdhci_s3c_get_max_clk,
1886 +       .get_timeout_clock      = sdhci_s3c_get_timeout_clk,
1887 +       .change_clock           = sdhci_s3c_change_clock,
1888 +       .set_ios                = sdhci_s3c_set_ios,
1889 +};
1890 +
1891 +/*
1892 + * call this when you need sd stack to recognize insertion or removal of card
1893 + * that can't be told by SDHCI regs
1894 + */
1895 +
1896 +void sdhci_s3c_force_presence_change(struct platform_device *pdev)
1897 +{
1898 +       struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
1899 +
1900 +       dev_info(&pdev->dev, "sdhci_s3c_force_presence_change called\n");
1901 +       mmc_detect_change(pdata->sdhci_host->mmc, msecs_to_jiffies(200));
1902 +}
1903 +EXPORT_SYMBOL_GPL(sdhci_s3c_force_presence_change);
1904 +
1905 +
1906 +static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
1907 +{
1908 +       struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
1909 +       struct device *dev = &pdev->dev;
1910 +       struct sdhci_host *host;
1911 +       struct sdhci_s3c *sc;
1912 +       struct resource *res;
1913 +       int ret, irq, ptr, clks;
1914 +
1915 +       if (!pdata) {
1916 +               dev_err(dev, "no device data specified\n");
1917 +               return -ENOENT;
1918 +       }
1919 +
1920 +       irq = platform_get_irq(pdev, 0);
1921 +       if (irq < 0) {
1922 +               dev_err(dev, "no irq specified\n");
1923 +               return irq;
1924 +       }
1925 +
1926 +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1927 +       if (!res) {
1928 +               dev_err(dev, "no memory specified\n");
1929 +               return -ENOENT;
1930 +       }
1931 +
1932 +       host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c));
1933 +       if (IS_ERR(host)) {
1934 +               dev_err(dev, "sdhci_alloc_host() failed\n");
1935 +               return PTR_ERR(host);
1936 +       }
1937 +
1938 +       pdata->sdhci_host = host;
1939 +
1940 +       sc = sdhci_priv(host);
1941 +
1942 +       sc->host = host;
1943 +       sc->pdev = pdev;
1944 +       sc->pdata = pdata;
1945 +
1946 +       platform_set_drvdata(pdev, host);
1947 +
1948 +       sc->clk_io = clk_get(dev, "hsmmc");
1949 +       if (IS_ERR(sc->clk_io)) {
1950 +               dev_err(dev, "failed to get io clock\n");
1951 +               ret = PTR_ERR(sc->clk_io);
1952 +               goto err_io_clk;
1953 +       }
1954 +
1955 +       /* enable the local io clock and keep it running for the moment. */
1956 +       clk_enable(sc->clk_io);
1957 +
1958 +       for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
1959 +               struct clk *clk;
1960 +               char *name = pdata->clocks[ptr];
1961 +
1962 +               if (name == NULL)
1963 +                       continue;
1964 +
1965 +               clk = clk_get(dev, name);
1966 +               if (IS_ERR(clk)) {
1967 +                       dev_err(dev, "failed to get clock %s\n", name);
1968 +                       continue;
1969 +               }
1970 +
1971 +               clks++;
1972 +               sc->clk_bus[ptr] = clk;
1973 +               clk_enable(clk);
1974 +
1975 +               dev_info(dev, "clock source %d: %s (%ld Hz)\n",
1976 +                        ptr, name, clk_get_rate(clk));
1977 +       }
1978 +
1979 +       if (clks == 0) {
1980 +               dev_err(dev, "failed to find any bus clocks\n");
1981 +               ret = -ENOENT;
1982 +               goto err_no_busclks;
1983 +       }
1984 +
1985 +       sc->ioarea = request_mem_region(res->start, resource_size(res),
1986 +                                       mmc_hostname(host->mmc));
1987 +       if (!sc->ioarea) {
1988 +               dev_err(dev, "failed to reserve register area\n");
1989 +               ret = -ENXIO;
1990 +               goto err_req_regs;
1991 +       }
1992 +
1993 +       host->ioaddr = ioremap_nocache(res->start, resource_size(res));
1994 +       if (!host->ioaddr) {
1995 +               dev_err(dev, "failed to map registers\n");
1996 +               ret = -ENXIO;
1997 +               goto err_req_regs;
1998 +       }
1999 +
2000 +       /* Ensure we have minimal gpio selected CMD/CLK/Detect */
2001 +       if (pdata->cfg_gpio)
2002 +               pdata->cfg_gpio(pdev, 0);
2003 +
2004 +       sdhci_s3c_check_sclk(host);
2005 +
2006 +       host->hw_name = "samsung-hsmmc";
2007 +       host->ops = &sdhci_s3c_ops;
2008 +       host->quirks = 0;
2009 +       host->irq = irq;
2010 +
2011 +       /* Setup quirks for the controller */
2012 +
2013 +       /* Currently with ADMA enabled we are getting some length
2014 +        * interrupts that are not being dealt with, do disable
2015 +        * ADMA until this is sorted out. */
2016 +       host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
2017 +       host->quirks |= SDHCI_QUIRK_32BIT_ADMA_SIZE;
2018 +
2019 +       /* It seems we do not get an DATA transfer complete on non-busy
2020 +        * transfers, not sure if this is a problem with this specific
2021 +        * SDHCI block, or a missing configuration that needs to be set. */
2022 +       host->quirks |= SDHCI_QUIRK_NO_TCIRQ_ON_NOT_BUSY;
2023 +
2024 +       host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR |
2025 +                        SDHCI_QUIRK_32BIT_DMA_SIZE);
2026 +
2027 +       ret = sdhci_add_host(host);
2028 +       if (ret) {
2029 +               dev_err(dev, "sdhci_add_host() failed\n");
2030 +               goto err_add_host;
2031 +       }
2032 +
2033 +       return 0;
2034 +
2035 + err_add_host:
2036 +       release_resource(sc->ioarea);
2037 +       kfree(sc->ioarea);
2038 +
2039 + err_req_regs:
2040 +       for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
2041 +               clk_disable(sc->clk_bus[ptr]);
2042 +               clk_put(sc->clk_bus[ptr]);
2043 +       }
2044 +
2045 + err_no_busclks:
2046 +       clk_disable(sc->clk_io);
2047 +       clk_put(sc->clk_io);
2048 +
2049 + err_io_clk:
2050 +       sdhci_free_host(host);
2051 +
2052 +       return ret;
2053 +}
2054 +
2055 +static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
2056 +{
2057 +       return 0;
2058 +}
2059 +
2060 +#ifdef CONFIG_PM
2061 +
2062 +static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm)
2063 +{
2064 +       struct sdhci_host *host = platform_get_drvdata(dev);
2065 +
2066 +       sdhci_suspend_host(host, pm);
2067 +       return 0;
2068 +}
2069 +
2070 +static int sdhci_s3c_resume(struct platform_device *dev)
2071 +{
2072 +       struct sdhci_host *host = platform_get_drvdata(dev);
2073 +
2074 +       sdhci_resume_host(host);
2075 +       return 0;
2076 +}
2077 +
2078 +#else
2079 +#define sdhci_s3c_suspend NULL
2080 +#define sdhci_s3c_resume NULL
2081 +#endif
2082 +
2083 +static struct platform_driver sdhci_s3c_driver = {
2084 +       .probe          = sdhci_s3c_probe,
2085 +       .remove         = __devexit_p(sdhci_s3c_remove),
2086 +       .suspend        = sdhci_s3c_suspend,
2087 +       .resume         = sdhci_s3c_resume,
2088 +       .driver         = {
2089 +               .owner  = THIS_MODULE,
2090 +               .name   = "s3c-sdhci",
2091 +       },
2092 +};
2093 +
2094 +static int __init sdhci_s3c_init(void)
2095 +{
2096 +       return platform_driver_register(&sdhci_s3c_driver);
2097 +}
2098 +
2099 +static void __exit sdhci_s3c_exit(void)
2100 +{
2101 +       platform_driver_unregister(&sdhci_s3c_driver);
2102 +}
2103 +
2104 +module_init(sdhci_s3c_init);
2105 +module_exit(sdhci_s3c_exit);
2106 +
2107 +MODULE_DESCRIPTION("Samsung SDHCI (HSMMC) glue");
2108 +MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
2109 +MODULE_LICENSE("GPL v2");
2110 +MODULE_ALIAS("platform:s3c-sdhci");
2111 --- a/drivers/mtd/nand/s3c2410.c
2112 +++ b/drivers/mtd/nand/s3c2410.c
2113 @@ -438,7 +438,7 @@ static int s3c2410_nand_correct_data(str
2114         if ((diff0 & ~(1<<fls(diff0))) == 0)
2115                 return 1;
2116  
2117 -       return -1;
2118 +       return -EBADMSG;
2119  }
2120  
2121  /* ECC functions
2122 @@ -530,7 +530,12 @@ static void s3c2410_nand_read_buf(struct
2123  static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
2124  {
2125         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
2126 +       u8 *ptr = buf + (len & ~3);
2127 +       int i;
2128 +
2129         readsl(info->regs + S3C2440_NFDATA, buf, len / 4);
2130 +       for (i = 0; i != (len & 3); i++)
2131 +               ptr[i] = readb(info->regs + S3C2440_NFDATA);
2132  }
2133  
2134  static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
2135 @@ -645,17 +650,31 @@ static int s3c2410_nand_remove(struct pl
2136  }
2137  
2138  #ifdef CONFIG_MTD_PARTITIONS
2139 +const char *part_probes[] = { "cmdlinepart", NULL };
2140  static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
2141                                       struct s3c2410_nand_mtd *mtd,
2142                                       struct s3c2410_nand_set *set)
2143  {
2144 +       struct mtd_partition *part_info;
2145 +       int nr_part = 0;
2146 +
2147         if (set == NULL)
2148                 return add_mtd_device(&mtd->mtd);
2149  
2150 -       if (set->nr_partitions > 0 && set->partitions != NULL) {
2151 -               return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions);
2152 +       if (set->nr_partitions == 0) {
2153 +               mtd->mtd.name = set->name;
2154 +               nr_part = parse_mtd_partitions(&mtd->mtd, part_probes,
2155 +                                               &part_info, 0);
2156 +       } else {
2157 +               if (set->nr_partitions > 0 && set->partitions != NULL) {
2158 +                       nr_part = set->nr_partitions;
2159 +                       part_info = set->partitions;
2160 +               }
2161         }
2162  
2163 +       if (nr_part > 0 && part_info)
2164 +               return add_mtd_partitions(&mtd->mtd, part_info, nr_part);
2165 +
2166         return add_mtd_device(&mtd->mtd);
2167  }
2168  #else
2169 @@ -684,9 +703,13 @@ static void s3c2410_nand_init_chip(struc
2170         chip->select_chip  = s3c2410_nand_select_chip;
2171         chip->chip_delay   = 50;
2172         chip->priv         = nmtd;
2173 -       chip->options      = 0;
2174         chip->controller   = &info->controller;
2175  
2176 +       if (set->flags & S3C2410_NAND_BBT)
2177 +               chip->options      = NAND_USE_FLASH_BBT;
2178 +       else
2179 +               chip->options      = 0;
2180 +
2181         switch (info->cpu_type) {
2182         case TYPE_S3C2410:
2183                 chip->IO_ADDR_W = regs + S3C2410_NFDATA;
2184 @@ -726,7 +749,7 @@ static void s3c2410_nand_init_chip(struc
2185         nmtd->mtd.owner    = THIS_MODULE;
2186         nmtd->set          = set;
2187  
2188 -       if (hardware_ecc) {
2189 +       if (!info->platform->software_ecc && hardware_ecc) {
2190                 chip->ecc.calculate = s3c2410_nand_calculate_ecc;
2191                 chip->ecc.correct   = s3c2410_nand_correct_data;
2192                 chip->ecc.mode      = NAND_ECC_HW;
2193 --- a/drivers/mmc/core/core.c
2194 +++ b/drivers/mmc/core/core.c
2195 @@ -59,10 +59,11 @@ static int mmc_schedule_delayed_work(str
2196  /*
2197   * Internal function. Flush all scheduled work from the MMC work queue.
2198   */
2199 -static void mmc_flush_scheduled_work(void)
2200 +void mmc_flush_scheduled_work(void)
2201  {
2202         flush_workqueue(workqueue);
2203  }
2204 +EXPORT_SYMBOL_GPL(mmc_flush_scheduled_work);
2205  
2206  /**
2207   *     mmc_request_done - finish processing an MMC request