1 Merge OpenMoko kernel patches
2 git://git.openmoko.org/git/kernel.git#(no
4 lars@lars-laptop Thu May 14 18:33:23 UTC 2009
8 Index: linux-2.6.30-rc6/arch/arm/mach-s3c2410/include/mach/mci.h
9 ===================================================================
10 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
11 +++ linux-2.6.30-rc6/arch/arm/mach-s3c2410/include/mach/mci.h 2009-05-18 19:07:48.000000000 +0200
16 +struct s3c24xx_mci_pdata {
17 + unsigned int gpio_detect;
18 + unsigned int gpio_wprotect;
19 + unsigned long ocr_avail;
20 + unsigned int do_dma;
21 + void (*set_power)(unsigned char power_mode,
22 + unsigned short vdd);
25 +#endif /* _ARCH_NCI_H */
26 Index: linux-2.6.30-rc6/arch/arm/mach-s3c2410/include/mach/regs-sdi.h
27 ===================================================================
28 --- linux-2.6.30-rc6.orig/arch/arm/mach-s3c2410/include/mach/regs-sdi.h 2009-05-16 06:12:57.000000000 +0200
29 +++ linux-2.6.30-rc6/arch/arm/mach-s3c2410/include/mach/regs-sdi.h 2009-05-18 19:07:48.000000000 +0200
31 #define S3C2410_SDIFSTA (0x38)
33 #define S3C2410_SDIDATA (0x3C)
34 +#define S3C2410_SDIDATA_BYTE (0x3C)
35 #define S3C2410_SDIIMSK (0x40)
37 #define S3C2440_SDIDATA (0x40)
40 #define S3C2440_SDICON_SDRESET (1<<8)
41 #define S3C2440_SDICON_MMCCLOCK (1<<5)
42 +#define S3C2440_SDIDATA_BYTE (0x48)
44 #define S3C2410_SDICON_BYTEORDER (1<<4)
45 #define S3C2410_SDICON_SDIOIRQ (1<<3)
46 #define S3C2410_SDICON_RWAITEN (1<<2)
47 Index: linux-2.6.30-rc6/arch/arm/mach-s3c2440/s3c2440.c
48 ===================================================================
49 --- linux-2.6.30-rc6.orig/arch/arm/mach-s3c2440/s3c2440.c 2009-05-16 06:12:57.000000000 +0200
50 +++ linux-2.6.30-rc6/arch/arm/mach-s3c2440/s3c2440.c 2009-05-18 19:07:48.000000000 +0200
52 s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
53 s3c_device_wdt.resource[1].end = IRQ_S3C2440_WDT;
55 + /* make sure SD/MMC driver can distinguish 2440 from 2410 */
56 + s3c_device_sdi.name = "s3c2440-sdi";
58 /* register our system device for everything else */
60 return sysdev_register(&s3c2440_sysdev);
61 Index: linux-2.6.30-rc6/arch/arm/mach-s3c2442/s3c2442.c
62 ===================================================================
63 --- linux-2.6.30-rc6.orig/arch/arm/mach-s3c2442/s3c2442.c 2009-05-16 06:12:57.000000000 +0200
64 +++ linux-2.6.30-rc6/arch/arm/mach-s3c2442/s3c2442.c 2009-05-18 19:07:48.000000000 +0200
67 #include <plat/s3c2442.h>
69 +#include <plat/devs.h>
71 static struct sys_device s3c2442_sysdev = {
72 .cls = &s3c2442_sysclass,
75 printk("S3C2442: Initialising architecture\n");
77 + /* make sure SD/MMC driver can distinguish 2440 from 2410 */
78 + s3c_device_sdi.name = "s3c2440-sdi";
80 return sysdev_register(&s3c2442_sysdev);
82 Index: linux-2.6.30-rc6/arch/arm/Makefile
83 ===================================================================
84 --- linux-2.6.30-rc6.orig/arch/arm/Makefile 2009-05-16 06:12:57.000000000 +0200
85 +++ linux-2.6.30-rc6/arch/arm/Makefile 2009-05-18 19:07:48.000000000 +0200
87 arch-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k)
89 arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t)
90 -arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t
91 +# We can't load armv4t modules, but still need to assemble some armv4t code to be linked in.
92 +arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 -Wa,-march=armv4t
93 arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4
94 arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3
96 Index: linux-2.6.30-rc6/arch/arm/plat-s3c/include/mach/cpu.h
97 ===================================================================
98 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
99 +++ linux-2.6.30-rc6/arch/arm/plat-s3c/include/mach/cpu.h 2009-05-18 19:07:48.000000000 +0200
102 + * arch/arm/plat-s3c/include/mach/cpu.h
104 + * S3C cpu type detection
106 + * Copyright (C) 2008 Samsung Electronics
107 + * Kyungmin Park <kyungmin.park@samsung.com>
109 + * Derived from OMAP cpu.h
111 + * This program is free software; you can redistribute it and/or modify
112 + * it under the terms of the GNU General Public License as published by
113 + * the Free Software Foundation; either version 2 of the License, or
114 + * (at your option) any later version.
116 + * This program is distributed in the hope that it will be useful,
117 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
118 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
119 + * GNU General Public License for more details.
121 + * You should have received a copy of the GNU General Public License
122 + * along with this program; if not, write to the Free Software
123 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
126 +#ifndef __ASM_ARCH_S3C_CPU_H
127 +#define __ASM_ARCH_S3C_CPU_H
129 +extern unsigned int system_rev;
131 +#define S3C_SYSTEM_REV_ATAG (system_rev & 0xffff)
132 +#define S3C_SYSTEM_REV_CPU (system_rev & 0xffff0000)
135 + * cpu_is_s3c24xx(): True for s3c2400, s3c2410, s3c2440 and so on
136 + * cpu_is_s3c241x(): True fro s3c2410, s3c2412
137 + * cpu_is_s3c244x(): True fro s3c2440, s3c2442, s3c2443
138 + * cpu_is_s3c64xx(): True for s3c6400, s3c6410
140 +#define GET_S3C_CLASS ((system_rev >> 24) & 0xff)
142 +#define IS_S3C_CLASS(class, id) \
143 +static inline int is_s3c ##class (void) \
145 + return (GET_S3C_CLASS == (id)) ? 1 : 0; \
148 +#define GET_S3C_SUBCLASS ((system_rev >> 20) & 0xfff)
150 +#define IS_S3C_SUBCLASS(subclass, id) \
151 +static inline int is_s3c ##subclass (void) \
153 + return (GET_S3C_SUBCLASS == (id)) ? 1 : 0; \
156 +IS_S3C_CLASS(24xx, 0x24)
157 +IS_S3C_CLASS(64xx, 0x64)
159 +IS_S3C_SUBCLASS(241x, 0x241)
160 +IS_S3C_SUBCLASS(244x, 0x244)
162 +#define cpu_is_s3c24xx() 0
163 +#define cpu_is_s3c241x() 0
164 +#define cpu_is_s3c244x() 0
165 +#define cpu_is_s3c64xx() 0
167 +#if defined(CONFIG_ARCH_S3C2410)
168 +# undef cpu_is_s3c24xx
169 +# undef cpu_is_s3c241x
170 +# undef cpu_is_s3c244x
171 +# define cpu_is_s3c24xx() is_s3c24xx()
172 +# define cpu_is_s3c241x() is_s3c241x()
173 +# define cpu_is_s3c244x() is_s3c244x()
176 +#if defined(CONFIG_ARCH_S3C64XX)
177 +# undef cpu_is_s3c64xx
178 +# define cpu_is_s3c64xx() is_s3c64xx()
182 + * Macros to detect individual cpu types.
183 + * cpu_is_s3c2410(): True for s3c2410
184 + * cpu_is_s3c2440(): True for s3c2440
185 + * cpu_is_s3c6400(): True for s3c6400
186 + * cpu_is_s3c6410(): True for s3c6410
189 + * Store Revision A to 1
190 + * s3c2410a -> s3c2411
191 + * s3c2440a -> s3c2441
194 +#define GET_S3C_TYPE ((system_rev >> 16) & 0xffff)
196 +#define IS_S3C_TYPE(type, id) \
197 +static inline int is_s3c ##type (void) \
199 + return (GET_S3C_TYPE == (id)) ? 1 : 0; \
202 +IS_S3C_TYPE(2400, 0x2400)
203 +IS_S3C_TYPE(2410, 0x2410)
204 +IS_S3C_TYPE(2410a, 0x2411)
205 +IS_S3C_TYPE(2412, 0x2412)
206 +IS_S3C_TYPE(2440, 0x2440)
207 +IS_S3C_TYPE(2440a, 0x2441)
208 +IS_S3C_TYPE(2442, 0x2442)
209 +IS_S3C_TYPE(2443, 0x2443)
210 +IS_S3C_TYPE(6400, 0x6400)
211 +IS_S3C_TYPE(6410, 0x6410)
213 +#define cpu_is_s3c2400() 0
214 +#define cpu_is_s3c2410() 0
215 +#define cpu_is_s3c2410a() 0
216 +#define cpu_is_s3c2412() 0
217 +#define cpu_is_s3c2440() 0
218 +#define cpu_is_s3c2440a() 0
219 +#define cpu_is_s3c2442() 0
220 +#define cpu_is_s3c2443() 0
221 +#define cpu_is_s3c6400() 0
222 +#define cpu_is_s3c6410() 0
224 +#if defined(CONFIG_ARCH_S3C2410)
225 +# undef cpu_is_s3c2400
226 +# define cpu_is_s3c2400() is_s3c2400()
229 +#if defined(CONFIG_CPU_S3C2410)
230 +# undef cpu_is_s3c2410
231 +# undef cpu_is_s3c2410a
232 +# define cpu_is_s3c2410() is_s3c2410()
233 +# define cpu_is_s3c2410a() is_s3c2410a()
236 +#if defined(CONFIG_CPU_S3C2412)
237 +# undef cpu_is_s3c2412
238 +# define cpu_is_s3c2412() is_s3c2412()
241 +#if defined(CONFIG_CPU_S3C2440)
242 +# undef cpu_is_s3c2440
243 +# undef cpu_is_s3c2440a
244 +# define cpu_is_s3c2440() is_s3c2440()
245 +# define cpu_is_s3c2440a() is_s3c2440a()
248 +#if defined(CONFIG_CPU_S3C2442)
249 +# undef cpu_is_s3c2442
250 +# define cpu_is_s3c2442() is_s3c2442()
253 +#if defined(CONFIG_CPU_S3C2443)
254 +# undef cpu_is_s3c2443
255 +# define cpu_is_s3c2443() is_s3c2443()
258 +#if defined(CONFIG_ARCH_S3C64XX)
259 +# undef cpu_is_s3c6400
260 +# undef cpu_is_s3c6410
261 +# define cpu_is_s3c6400() is_s3c6400()
262 +# define cpu_is_s3c6410() is_s3c6410()
266 Index: linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/devs.h
267 ===================================================================
268 --- linux-2.6.30-rc6.orig/arch/arm/plat-s3c/include/plat/devs.h 2009-05-16 06:12:57.000000000 +0200
269 +++ linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/devs.h 2009-05-18 19:07:48.000000000 +0200
271 unsigned long nr_resources;
274 +struct s3c_plat_otg_data {
278 extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
279 extern struct s3c24xx_uart_resources s3c64xx_uart_resources[];
281 Index: linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/gpio-core.h
282 ===================================================================
283 --- linux-2.6.30-rc6.orig/arch/arm/plat-s3c/include/plat/gpio-core.h 2009-05-16 06:12:57.000000000 +0200
284 +++ linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/gpio-core.h 2009-05-18 19:07:48.000000000 +0200
289 +struct s3c_gpio_chip;
292 + * struct s3c_gpio_pm - power management (suspend/resume) information
293 + * @save: Routine to save the state of the GPIO block
294 + * @resume: Routine to resume the GPIO block.
296 +struct s3c_gpio_pm {
297 + void (*save)(struct s3c_gpio_chip *chip);
298 + void (*resume)(struct s3c_gpio_chip *chip);
306 * @chip: The chip structure to be exported via gpiolib.
307 * @base: The base pointer to the gpio configuration registers.
308 * @config: special function and pull-resistor control information.
309 + * @pm_save: Save information for suspend/resume support.
311 * This wrapper provides the necessary information for the Samsung
312 * specific gpios being registered with gpiolib.
314 struct s3c_gpio_chip {
315 struct gpio_chip chip;
316 struct s3c_gpio_cfg *config;
317 + struct s3c_gpio_pm *pm;
324 static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
327 static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
331 +extern struct s3c_gpio_pm s3c_gpio_pm_1bit;
332 +extern struct s3c_gpio_pm s3c_gpio_pm_2bit;
333 +extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
334 +#define __gpio_pm(x) x
336 +#define s3c_gpio_pm_1bit NULL
337 +#define s3c_gpio_pm_2bit NULL
338 +#define s3c_gpio_pm_4bit NULL
339 +#define __gpio_pm(x) NULL
341 +#endif /* CONFIG_PM */
342 Index: linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/map-base.h
343 ===================================================================
344 --- linux-2.6.30-rc6.orig/arch/arm/plat-s3c/include/plat/map-base.h 2009-05-16 06:12:57.000000000 +0200
345 +++ linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/map-base.h 2009-05-18 19:07:48.000000000 +0200
347 #define S3C_VA_TIMER S3C_ADDR(0x00300000) /* timer block */
348 #define S3C_VA_WATCHDOG S3C_ADDR(0x00400000) /* watchdog */
349 #define S3C_VA_UART S3C_ADDR(0x01000000) /* UART */
350 +#define S3C_VA_OTG S3C_ADDR(0x03900000) /* OTG */
351 +#define S3C_VA_OTGSFR S3C_ADDR(0x03a00000) /* OTGSFR */
353 #endif /* __ASM_PLAT_MAP_H */
354 Index: linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/nand.h
355 ===================================================================
356 --- linux-2.6.30-rc6.orig/arch/arm/plat-s3c/include/plat/nand.h 2009-05-16 06:12:57.000000000 +0200
357 +++ linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/nand.h 2009-05-18 19:07:48.000000000 +0200
359 * partitions = mtd partition list
362 +#define S3C2410_NAND_BBT 0x0001
364 struct s3c2410_nand_set {
365 unsigned int disable_ecc : 1;
369 + unsigned int flags;
372 struct mtd_partition *partitions;
375 struct s3c2410_nand_set *sets;
377 + /* force software_ecc at runtime */
380 void (*select_chip)(struct s3c2410_nand_set *,
383 Index: linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/pm.h
384 ===================================================================
385 --- linux-2.6.30-rc6.orig/arch/arm/plat-s3c/include/plat/pm.h 2009-05-16 06:12:57.000000000 +0200
386 +++ linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/pm.h 2009-05-18 19:07:48.000000000 +0200
388 * published by the Free Software Foundation.
391 +#include <linux/sysdev.h>
395 * called from board at initialisation time to setup the power
398 extern unsigned long s3c_pm_flags;
400 +extern unsigned char pm_uart_udivslot; /* true to save UART UDIVSLOT */
404 extern int s3c_cpu_save(unsigned long *saveblk);
412 /* helper functions to save/restore lists of registers. */
413 Index: linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/sdhci.h
414 ===================================================================
415 --- linux-2.6.30-rc6.orig/arch/arm/plat-s3c/include/plat/sdhci.h 2009-05-16 06:12:57.000000000 +0200
416 +++ linux-2.6.30-rc6/arch/arm/plat-s3c/include/plat/sdhci.h 2009-05-18 19:07:48.000000000 +0200
418 * is necessary the controllers and/or GPIO blocks require the
419 * changing of driver-strength and other controls dependant on
420 * the card and speed of operation.
421 + * sdhci_host: Pointer kept during init, allows presence change notification
423 * Initialisation data specific to either the machine or the platform
424 * for the device driver to use or call-back when configuring gpio or
426 void __iomem *regbase,
428 struct mmc_card *card);
429 + struct sdhci_host * sdhci_host;
432 +extern void sdhci_s3c_force_presence_change(struct platform_device *pdev);
435 * s3c_sdhci0_set_platdata - Set platform data for S3C SDHCI device.
436 * @pd: Platform data to register to device.
437 Index: linux-2.6.30-rc6/arch/arm/plat-s3c/init.c
438 ===================================================================
439 --- linux-2.6.30-rc6.orig/arch/arm/plat-s3c/init.c 2009-05-16 06:12:57.000000000 +0200
440 +++ linux-2.6.30-rc6/arch/arm/plat-s3c/init.c 2009-05-18 19:07:48.000000000 +0200
443 static struct cpu_table *cpu;
445 +static void __init set_system_rev(unsigned int idcode)
448 + * system_rev encoding is as follows
449 + * system_rev & 0xff000000 -> S3C Class (24xx/64xx)
450 + * system_rev & 0xfff00000 -> S3C Sub Class (241x/244x)
451 + * system_rev & 0xffff0000 -> S3C Type (2410/2440/6400/6410)
453 + * Remaining[15:0] are preserved from the value set by ATAG
456 + * Store Revision A to 1 such as
457 + * s3c2410A to s3c2411
458 + * s3c2440A to s3c2441
461 + system_rev &= 0xffff;
462 + system_rev |= (idcode & 0x0ffff000) << 4;
464 + if (idcode == 0x32410002 || idcode == 0x32440001)
465 + system_rev |= (0x1 << 16);
466 + if (idcode == 0x32440aaa /* s3c2442 */
467 + || idcode == 0x32440aab) /* s3c2442b */
468 + system_rev |= (0x2 << 16);
469 + if (idcode == 0x0) /* s3c2400 */
470 + system_rev |= (0x2400 << 16);
473 static struct cpu_table * __init s3c_lookup_cpu(unsigned long idcode,
474 struct cpu_table *tab,
477 panic("Unknown S3C24XX CPU");
480 + set_system_rev(idcode);
482 printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
484 if (cpu->map_io == NULL || cpu->init == NULL) {
485 Index: linux-2.6.30-rc6/arch/arm/plat-s3c/Makefile
486 ===================================================================
487 --- linux-2.6.30-rc6.orig/arch/arm/plat-s3c/Makefile 2009-05-16 06:12:57.000000000 +0200
488 +++ linux-2.6.30-rc6/arch/arm/plat-s3c/Makefile 2009-05-18 19:07:48.000000000 +0200
492 obj-$(CONFIG_PM) += pm.o
493 +obj-$(CONFIG_PM) += pm-gpio.o
494 obj-$(CONFIG_S3C2410_PM_CHECK) += pm-check.o
497 Index: linux-2.6.30-rc6/arch/arm/plat-s3c/pm.c
498 ===================================================================
499 --- linux-2.6.30-rc6.orig/arch/arm/plat-s3c/pm.c 2009-05-16 06:12:57.000000000 +0200
500 +++ linux-2.6.30-rc6/arch/arm/plat-s3c/pm.c 2009-05-18 19:07:48.000000000 +0200
503 #include <asm/cacheflush.h>
504 #include <mach/hardware.h>
505 +#include <mach/map.h>
507 #include <plat/regs-serial.h>
508 #include <mach/regs-clock.h>
509 -#include <mach/regs-gpio.h>
510 -#include <mach/regs-mem.h>
511 #include <mach/regs-irq.h>
516 /* Save the UART configurations if we are configured for debug. */
518 +unsigned char pm_uart_udivslot;
520 #ifdef CONFIG_S3C2410_PM_DEBUG
522 struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
524 save->ufcon = __raw_readl(regs + S3C2410_UFCON);
525 save->umcon = __raw_readl(regs + S3C2410_UMCON);
526 save->ubrdiv = __raw_readl(regs + S3C2410_UBRDIV);
528 + if (pm_uart_udivslot)
529 + save->udivslot = __raw_readl(regs + S3C2443_DIVSLOT);
531 + S3C_PMDBG("UART[%d]: ULCON=%04x, UCON=%04x, UFCON=%04x, UBRDIV=%04x\n",
532 + uart, save->ulcon, save->ucon, save->ufcon, save->ubrdiv);
535 static void s3c_pm_save_uarts(void)
538 void __iomem *regs = S3C_VA_UARTx(uart);
540 + s3c_pm_arch_update_uart(regs, save);
542 __raw_writel(save->ulcon, regs + S3C2410_ULCON);
543 __raw_writel(save->ucon, regs + S3C2410_UCON);
544 __raw_writel(save->ufcon, regs + S3C2410_UFCON);
545 __raw_writel(save->umcon, regs + S3C2410_UMCON);
546 __raw_writel(save->ubrdiv, regs + S3C2410_UBRDIV);
548 + if (pm_uart_udivslot)
549 + __raw_writel(save->udivslot, regs + S3C2443_DIVSLOT);
552 static void s3c_pm_restore_uarts(void)
553 @@ -289,11 +301,14 @@
555 s3c_pm_arch_stop_clocks();
557 - /* s3c_cpu_save will also act as our return point from when
558 - * we resume as it saves its own register state and restores it
559 - * during the resume. */
561 - s3c_cpu_save(regs_save);
562 + /* s3c2410_cpu_save will also act as our return point from when
563 + * we resume as it saves its own register state, so use the return
564 + * code to differentiate return from save and return from sleep */
566 + if (s3c_cpu_save(regs_save) == 0) {
571 /* restore the cpu state using the kernel's cpu init code. */
573 Index: linux-2.6.30-rc6/arch/arm/plat-s3c/pm-gpio.c
574 ===================================================================
575 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
576 +++ linux-2.6.30-rc6/arch/arm/plat-s3c/pm-gpio.c 2009-05-18 19:07:48.000000000 +0200
578 +/* linux/arch/arm/plat-s3c/pm-gpio.c
580 + * Copyright 2008 Openmoko, Inc.
581 + * Copyright 2008 Simtec Electronics
582 + * Ben Dooks <ben@simtec.co.uk>
583 + * http://armlinux.simtec.co.uk/
585 + * S3C series GPIO PM code
587 + * This program is free software; you can redistribute it and/or modify
588 + * it under the terms of the GNU General Public License version 2 as
589 + * published by the Free Software Foundation.
592 +#include <linux/kernel.h>
593 +#include <linux/init.h>
594 +#include <linux/io.h>
595 +#include <linux/gpio.h>
597 +#include <mach/gpio-core.h>
598 +#include <plat/pm.h>
600 +/* PM GPIO helpers */
602 +#define OFFS_CON (0x00)
603 +#define OFFS_DAT (0X04)
604 +#define OFFS_UP (0X08)
606 +static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip)
608 + chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
609 + chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
612 +static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
614 + void __iomem *base = chip->base;
615 + u32 old_gpcon = __raw_readl(base + OFFS_CON);
616 + u32 old_gpdat = __raw_readl(base + OFFS_DAT);
617 + u32 gps_gpcon = chip->pm_save[0];
618 + u32 gps_gpdat = chip->pm_save[1];
621 + /* GPACON only has one bit per control / data and no PULLUPs.
622 + * GPACON[x] = 0 => Output, 1 => SFN */
624 + /* first set all SFN bits to SFN */
626 + gpcon = old_gpcon | gps_gpcon;
627 + __raw_writel(gpcon, base + OFFS_CON);
629 + /* now set all the other bits */
631 + __raw_writel(gps_gpdat, base + OFFS_DAT);
632 + __raw_writel(gps_gpcon, base + OFFS_CON);
634 + S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
635 + chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
638 +struct s3c_gpio_pm s3c_gpio_pm_1bit = {
639 + .save = s3c_gpio_pm_1bit_save,
640 + .resume = s3c_gpio_pm_1bit_resume,
643 +static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip)
645 + chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
646 + chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
647 + chip->pm_save[2] = __raw_readl(chip->base + OFFS_UP);
650 +/* Test whether the given masked+shifted bits of an GPIO configuration
651 + * are one of the SFN (special function) modes. */
653 +static inline int is_sfn(unsigned long con)
658 +/* Test if the given masked+shifted GPIO configuration is an input */
660 +static inline int is_in(unsigned long con)
665 +/* Test if the given masked+shifted GPIO configuration is an output */
667 +static inline int is_out(unsigned long con)
673 + * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank
674 + * @chip: The chip information to resume.
676 + * Restore one of the GPIO banks that was saved during suspend. This is
677 + * not as simple as once thought, due to the possibility of glitches
678 + * from the order that the CON and DAT registers are set in.
680 + * The three states the pin can be are {IN,OUT,SFN} which gives us 9
681 + * combinations of changes to check. Three of these, if the pin stays
682 + * in the same configuration can be discounted. This leaves us with
685 + * { IN => OUT } Change DAT first
686 + * { IN => SFN } Change CON first
687 + * { OUT => SFN } Change CON first, so new data will not glitch
688 + * { OUT => IN } Change CON first, so new data will not glitch
689 + * { SFN => IN } Change CON first
690 + * { SFN => OUT } Change DAT first, so new data will not glitch [1]
692 + * We do not currently deal with the UP registers as these control
693 + * weak resistors, so a small delay in change should not need to bring
694 + * these into the calculations.
696 + * [1] this assumes that writing to a pin DAT whilst in SFN will set the
697 + * state for when it is next output.
699 +static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
701 + void __iomem *base = chip->base;
702 + u32 old_gpcon = __raw_readl(base + OFFS_CON);
703 + u32 old_gpdat = __raw_readl(base + OFFS_DAT);
704 + u32 gps_gpcon = chip->pm_save[0];
705 + u32 gps_gpdat = chip->pm_save[1];
706 + u32 gpcon, old, new, mask;
707 + u32 change_mask = 0x0;
710 + /* restore GPIO pull-up settings */
711 + __raw_writel(chip->pm_save[2], base + OFFS_UP);
713 + /* Create a change_mask of all the items that need to have
714 + * their CON value changed before their DAT value, so that
715 + * we minimise the work between the two settings.
718 + for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
719 + old = (old_gpcon & mask) >> nr;
720 + new = (gps_gpcon & mask) >> nr;
722 + /* If there is no change, then skip */
727 + /* If both are special function, then skip */
729 + if (is_sfn(old) && is_sfn(new))
732 + /* Change is IN => OUT, do not change now */
734 + if (is_in(old) && is_out(new))
737 + /* Change is SFN => OUT, do not change now */
739 + if (is_sfn(old) && is_out(new))
742 + /* We should now be at the case of IN=>SFN,
743 + * OUT=>SFN, OUT=>IN, SFN=>IN. */
745 + change_mask |= mask;
749 + /* Write the new CON settings */
751 + gpcon = old_gpcon & ~change_mask;
752 + gpcon |= gps_gpcon & change_mask;
754 + __raw_writel(gpcon, base + OFFS_CON);
756 + /* Now change any items that require DAT,CON */
758 + __raw_writel(gps_gpdat, base + OFFS_DAT);
759 + __raw_writel(gps_gpcon, base + OFFS_CON);
761 + S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
762 + chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
765 +struct s3c_gpio_pm s3c_gpio_pm_2bit = {
766 + .save = s3c_gpio_pm_2bit_save,
767 + .resume = s3c_gpio_pm_2bit_resume,
770 +#ifdef CONFIG_ARCH_S3C64XX
771 +static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
773 + chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
774 + chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
775 + chip->pm_save[3] = __raw_readl(chip->base + OFFS_UP);
777 + if (chip->chip.ngpio > 8)
778 + chip->pm_save[0] = __raw_readl(chip->base - 4);
781 +static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
783 + u32 old, new, mask;
784 + u32 change_mask = 0x0;
787 + for (nr = 0, mask = 0x0f; nr < 16; nr += 4, mask <<= 4) {
788 + old = (old_gpcon & mask) >> nr;
789 + new = (gps_gpcon & mask) >> nr;
791 + /* If there is no change, then skip */
796 + /* If both are special function, then skip */
798 + if (is_sfn(old) && is_sfn(new))
801 + /* Change is IN => OUT, do not change now */
803 + if (is_in(old) && is_out(new))
806 + /* Change is SFN => OUT, do not change now */
808 + if (is_sfn(old) && is_out(new))
811 + /* We should now be at the case of IN=>SFN,
812 + * OUT=>SFN, OUT=>IN, SFN=>IN. */
814 + change_mask |= mask;
817 + return change_mask;
820 +static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
822 + void __iomem *con = chip->base + (index * 4);
823 + u32 old_gpcon = __raw_readl(con);
824 + u32 gps_gpcon = chip->pm_save[index + 1];
827 + mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
829 + gpcon = old_gpcon & ~mask;
830 + gpcon |= gps_gpcon & mask;
832 + __raw_writel(gpcon, con);
835 +static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
837 + void __iomem *base = chip->base;
839 + u32 old_gpdat = __raw_readl(base + OFFS_DAT);
840 + u32 gps_gpdat = chip->pm_save[2];
842 + /* First, modify the CON settings */
845 + old_gpcon[1] = __raw_readl(base + OFFS_CON);
847 + s3c_gpio_pm_4bit_con(chip, 0);
848 + if (chip->chip.ngpio > 8) {
849 + old_gpcon[0] = __raw_readl(base - 4);
850 + s3c_gpio_pm_4bit_con(chip, -1);
853 + /* Now change the configurations that require DAT,CON */
855 + __raw_writel(chip->pm_save[2], base + OFFS_DAT);
856 + __raw_writel(chip->pm_save[1], base + OFFS_CON);
857 + if (chip->chip.ngpio > 8)
858 + __raw_writel(chip->pm_save[0], base - 4);
860 + __raw_writel(chip->pm_save[2], base + OFFS_DAT);
861 + __raw_writel(chip->pm_save[3], base + OFFS_UP);
863 + if (chip->chip.ngpio > 8) {
864 + S3C_PMDBG("%s: CON4 %08x,%08x => %08x,%08x, DAT %08x => %08x\n",
865 + chip->chip.label, old_gpcon[0], old_gpcon[1],
866 + __raw_readl(base - 4),
867 + __raw_readl(base + OFFS_CON),
868 + old_gpdat, gps_gpdat);
870 + S3C_PMDBG("%s: CON4 %08x => %08x, DAT %08x => %08x\n",
871 + chip->chip.label, old_gpcon[1],
872 + __raw_readl(base + OFFS_CON),
873 + old_gpdat, gps_gpdat);
876 +struct s3c_gpio_pm s3c_gpio_pm_4bit = {
877 + .save = s3c_gpio_pm_4bit_save,
878 + .resume = s3c_gpio_pm_4bit_resume,
880 +#endif /* CONFIG_ARCH_S3C64XX */
883 + * s3c_pm_save_gpio() - save gpio chip data for suspend
884 + * @ourchip: The chip for suspend.
886 +static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip)
888 + struct s3c_gpio_pm *pm = ourchip->pm;
890 + if (pm == NULL || pm->save == NULL)
891 + S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
897 + * s3c_pm_save_gpios() - Save the state of the GPIO banks.
899 + * For all the GPIO banks, save the state of each one ready for going
900 + * into a suspend mode.
902 +void s3c_pm_save_gpios(void)
904 + struct s3c_gpio_chip *ourchip;
905 + unsigned int gpio_nr;
907 + for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
908 + ourchip = s3c_gpiolib_getchip(gpio_nr);
912 + s3c_pm_save_gpio(ourchip);
914 + S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
915 + ourchip->chip.label,
916 + ourchip->pm_save[0],
917 + ourchip->pm_save[1],
918 + ourchip->pm_save[2],
919 + ourchip->pm_save[3]);
921 + gpio_nr += ourchip->chip.ngpio;
922 + gpio_nr += CONFIG_S3C_GPIO_SPACE;
927 + * s3c_pm_resume_gpio() - restore gpio chip data after suspend
928 + * @ourchip: The suspended chip.
930 +static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
932 + struct s3c_gpio_pm *pm = ourchip->pm;
934 + if (pm == NULL || pm->resume == NULL)
935 + S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
937 + pm->resume(ourchip);
940 +void s3c_pm_restore_gpios(void)
942 + struct s3c_gpio_chip *ourchip;
943 + unsigned int gpio_nr;
945 + for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
946 + ourchip = s3c_gpiolib_getchip(gpio_nr);
950 + s3c_pm_resume_gpio(ourchip);
952 + gpio_nr += ourchip->chip.ngpio;
953 + gpio_nr += CONFIG_S3C_GPIO_SPACE;
956 Index: linux-2.6.30-rc6/arch/arm/plat-s3c24xx/clock-dclk.c
957 ===================================================================
958 --- linux-2.6.30-rc6.orig/arch/arm/plat-s3c24xx/clock-dclk.c 2009-05-16 06:12:57.000000000 +0200
959 +++ linux-2.6.30-rc6/arch/arm/plat-s3c24xx/clock-dclk.c 2009-05-18 19:07:48.000000000 +0200
962 #include <mach/regs-clock.h>
963 #include <mach/regs-gpio.h>
964 +#include <mach/hardware.h>
966 #include <plat/clock.h>
967 #include <plat/cpu.h>
968 Index: linux-2.6.30-rc6/arch/arm/plat-s3c24xx/cpu.c
969 ===================================================================
970 --- linux-2.6.30-rc6.orig/arch/arm/plat-s3c24xx/cpu.c 2009-05-16 06:12:57.000000000 +0200
971 +++ linux-2.6.30-rc6/arch/arm/plat-s3c24xx/cpu.c 2009-05-18 19:07:48.000000000 +0200
973 static const char name_s3c2412[] = "S3C2412";
974 static const char name_s3c2440[] = "S3C2440";
975 static const char name_s3c2442[] = "S3C2442";
976 +static const char name_s3c2442b[] = "S3C2442B";
977 static const char name_s3c2443[] = "S3C2443";
978 static const char name_s3c2410a[] = "S3C2410A";
979 static const char name_s3c2440a[] = "S3C2440A";
984 + .idcode = 0x32440aab,
985 + .idmask = 0xffffffff,
986 + .map_io = s3c244x_map_io,
987 + .init_clocks = s3c244x_init_clocks,
988 + .init_uarts = s3c244x_init_uarts,
989 + .init = s3c2442_init,
990 + .name = name_s3c2442b
993 .idcode = 0x32412001,
994 .idmask = 0xffffffff,
995 .map_io = s3c2412_map_io,
996 Index: linux-2.6.30-rc6/arch/arm/plat-s3c24xx/gpiolib.c
997 ===================================================================
998 --- linux-2.6.30-rc6.orig/arch/arm/plat-s3c24xx/gpiolib.c 2009-05-16 06:12:57.000000000 +0200
999 +++ linux-2.6.30-rc6/arch/arm/plat-s3c24xx/gpiolib.c 2009-05-18 19:07:48.000000000 +0200
1001 #include <linux/io.h>
1002 #include <linux/gpio.h>
1004 -#include <mach/gpio-core.h>
1005 +#include <plat/gpio-core.h>
1006 #include <mach/hardware.h>
1007 #include <asm/irq.h>
1008 +#include <plat/pm.h>
1010 #include <mach/regs-gpio.h>
1013 struct s3c_gpio_chip s3c24xx_gpios[] = {
1015 .base = S3C24XX_GPIO_BASE(S3C2410_GPA0),
1016 + .pm = __gpio_pm(&s3c_gpio_pm_1bit),
1018 .base = S3C2410_GPA0,
1019 .owner = THIS_MODULE,
1023 .base = S3C24XX_GPIO_BASE(S3C2410_GPB0),
1024 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
1026 .base = S3C2410_GPB0,
1027 .owner = THIS_MODULE,
1031 .base = S3C24XX_GPIO_BASE(S3C2410_GPC0),
1032 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
1034 .base = S3C2410_GPC0,
1035 .owner = THIS_MODULE,
1039 .base = S3C24XX_GPIO_BASE(S3C2410_GPD0),
1040 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
1042 .base = S3C2410_GPD0,
1043 .owner = THIS_MODULE,
1047 .base = S3C24XX_GPIO_BASE(S3C2410_GPE0),
1048 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
1050 .base = S3C2410_GPE0,
1055 .base = S3C24XX_GPIO_BASE(S3C2410_GPF0),
1056 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
1058 .base = S3C2410_GPF0,
1059 .owner = THIS_MODULE,
1060 @@ -135,12 +142,23 @@
1063 .base = S3C24XX_GPIO_BASE(S3C2410_GPG0),
1064 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
1066 .base = S3C2410_GPG0,
1067 .owner = THIS_MODULE,
1070 .to_irq = s3c24xx_gpiolib_bankg_toirq,
1075 + .base = S3C24XX_GPIO_BASE(S3C2410_GPH0),
1076 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
1078 + .base = S3C2410_GPH0,
1079 + .owner = THIS_MODULE,
1085 Index: linux-2.6.30-rc6/arch/arm/plat-s3c24xx/include/plat/pm-core.h
1086 ===================================================================
1087 --- linux-2.6.30-rc6.orig/arch/arm/plat-s3c24xx/include/plat/pm-core.h 2009-05-16 06:12:57.000000000 +0200
1088 +++ linux-2.6.30-rc6/arch/arm/plat-s3c24xx/include/plat/pm-core.h 2009-05-18 19:07:48.000000000 +0200
1090 s3c_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
1091 s3c_irqwake_eintmask);
1094 +static inline void s3c_pm_arch_update_uart(void __iomem *regs,
1095 + struct pm_uart_save *save)
1098 Index: linux-2.6.30-rc6/arch/arm/plat-s3c24xx/irq-pm.c
1099 ===================================================================
1100 --- linux-2.6.30-rc6.orig/arch/arm/plat-s3c24xx/irq-pm.c 2009-05-16 06:12:57.000000000 +0200
1101 +++ linux-2.6.30-rc6/arch/arm/plat-s3c24xx/irq-pm.c 2009-05-18 19:07:48.000000000 +0200
1103 #include <linux/module.h>
1104 #include <linux/interrupt.h>
1105 #include <linux/sysdev.h>
1106 +#include <linux/irq.h>
1108 #include <plat/cpu.h>
1109 #include <plat/pm.h>
1112 int s3c24xx_irq_resume(struct sys_device *dev)
1115 + unsigned int i, irq;
1116 + unsigned long eintpnd;
1117 + struct irq_desc *desc;
1119 for (i = 0; i < ARRAY_SIZE(save_extint); i++)
1120 __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
1122 s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
1123 __raw_writel(save_eintmask, S3C24XX_EINTMASK);
1126 + * ACK those interrupts which are now masked and pending.
1127 + * Level interrupts if not ACKed here, create an interrupt storm
1128 + * because they are not handled at all.
1131 + eintpnd = __raw_readl(S3C24XX_EINTPEND);
1133 + eintpnd &= save_eintmask;
1134 + eintpnd &= ~0xff; /* ignore lower irqs */
1137 + irq = __ffs(eintpnd);
1138 + eintpnd &= ~(1 << irq);
1140 + irq += (IRQ_EINT4 - 4);
1141 + desc = irq_to_desc(irq);
1142 + desc->chip->ack(irq);
1147 Index: linux-2.6.30-rc6/arch/arm/plat-s3c24xx/pm.c
1148 ===================================================================
1149 --- linux-2.6.30-rc6.orig/arch/arm/plat-s3c24xx/pm.c 2009-05-16 06:12:57.000000000 +0200
1150 +++ linux-2.6.30-rc6/arch/arm/plat-s3c24xx/pm.c 2009-05-18 19:07:48.000000000 +0200
1152 #include <mach/regs-gpio.h>
1153 #include <mach/regs-mem.h>
1154 #include <mach/regs-irq.h>
1155 +#include <mach/hardware.h>
1157 #include <asm/mach/time.h>
1160 SAVE_ITEM(S3C2410_CLKSLOW),
1163 -static struct gpio_sleep {
1164 - void __iomem *base;
1165 - unsigned int gpcon;
1166 - unsigned int gpdat;
1167 - unsigned int gpup;
1170 - .base = S3C2410_GPACON,
1173 - .base = S3C2410_GPBCON,
1176 - .base = S3C2410_GPCCON,
1179 - .base = S3C2410_GPDCON,
1182 - .base = S3C2410_GPECON,
1185 - .base = S3C2410_GPFCON,
1188 - .base = S3C2410_GPGCON,
1191 - .base = S3C2410_GPHCON,
1195 static struct sleep_save misc_save[] = {
1196 SAVE_ITEM(S3C2410_DCLKCON),
1200 /* s3c_pm_check_resume_pin
1202 * check to see if the pin is configured correctly for sleep mode, and
1203 @@ -165,186 +133,6 @@
1207 -/* offsets for CON/DAT/UP registers */
1209 -#define OFFS_CON (S3C2410_GPACON - S3C2410_GPACON)
1210 -#define OFFS_DAT (S3C2410_GPADAT - S3C2410_GPACON)
1211 -#define OFFS_UP (S3C2410_GPBUP - S3C2410_GPBCON)
1213 -/* s3c_pm_save_gpios()
1215 - * Save the state of the GPIOs
1218 -void s3c_pm_save_gpios(void)
1220 - struct gpio_sleep *gps = gpio_save;
1221 - unsigned int gpio;
1223 - for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
1224 - void __iomem *base = gps->base;
1226 - gps->gpcon = __raw_readl(base + OFFS_CON);
1227 - gps->gpdat = __raw_readl(base + OFFS_DAT);
1230 - gps->gpup = __raw_readl(base + OFFS_UP);
1235 -/* Test whether the given masked+shifted bits of an GPIO configuration
1236 - * are one of the SFN (special function) modes. */
1238 -static inline int is_sfn(unsigned long con)
1240 - return (con == 2 || con == 3);
1243 -/* Test if the given masked+shifted GPIO configuration is an input */
1245 -static inline int is_in(unsigned long con)
1250 -/* Test if the given masked+shifted GPIO configuration is an output */
1252 -static inline int is_out(unsigned long con)
1258 - * s3c2410_pm_restore_gpio() - restore the given GPIO bank
1259 - * @index: The number of the GPIO bank being resumed.
1260 - * @gps: The sleep confgiuration for the bank.
1262 - * Restore one of the GPIO banks that was saved during suspend. This is
1263 - * not as simple as once thought, due to the possibility of glitches
1264 - * from the order that the CON and DAT registers are set in.
1266 - * The three states the pin can be are {IN,OUT,SFN} which gives us 9
1267 - * combinations of changes to check. Three of these, if the pin stays
1268 - * in the same configuration can be discounted. This leaves us with
1271 - * { IN => OUT } Change DAT first
1272 - * { IN => SFN } Change CON first
1273 - * { OUT => SFN } Change CON first, so new data will not glitch
1274 - * { OUT => IN } Change CON first, so new data will not glitch
1275 - * { SFN => IN } Change CON first
1276 - * { SFN => OUT } Change DAT first, so new data will not glitch [1]
1278 - * We do not currently deal with the UP registers as these control
1279 - * weak resistors, so a small delay in change should not need to bring
1280 - * these into the calculations.
1282 - * [1] this assumes that writing to a pin DAT whilst in SFN will set the
1283 - * state for when it is next output.
1286 -static void s3c2410_pm_restore_gpio(int index, struct gpio_sleep *gps)
1288 - void __iomem *base = gps->base;
1289 - unsigned long gps_gpcon = gps->gpcon;
1290 - unsigned long gps_gpdat = gps->gpdat;
1291 - unsigned long old_gpcon;
1292 - unsigned long old_gpdat;
1293 - unsigned long old_gpup = 0x0;
1294 - unsigned long gpcon;
1297 - old_gpcon = __raw_readl(base + OFFS_CON);
1298 - old_gpdat = __raw_readl(base + OFFS_DAT);
1300 - if (base == S3C2410_GPACON) {
1301 - /* GPACON only has one bit per control / data and no PULLUPs.
1302 - * GPACON[x] = 0 => Output, 1 => SFN */
1304 - /* first set all SFN bits to SFN */
1306 - gpcon = old_gpcon | gps->gpcon;
1307 - __raw_writel(gpcon, base + OFFS_CON);
1309 - /* now set all the other bits */
1311 - __raw_writel(gps_gpdat, base + OFFS_DAT);
1312 - __raw_writel(gps_gpcon, base + OFFS_CON);
1314 - unsigned long old, new, mask;
1315 - unsigned long change_mask = 0x0;
1317 - old_gpup = __raw_readl(base + OFFS_UP);
1319 - /* Create a change_mask of all the items that need to have
1320 - * their CON value changed before their DAT value, so that
1321 - * we minimise the work between the two settings.
1324 - for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
1325 - old = (old_gpcon & mask) >> nr;
1326 - new = (gps_gpcon & mask) >> nr;
1328 - /* If there is no change, then skip */
1333 - /* If both are special function, then skip */
1335 - if (is_sfn(old) && is_sfn(new))
1338 - /* Change is IN => OUT, do not change now */
1340 - if (is_in(old) && is_out(new))
1343 - /* Change is SFN => OUT, do not change now */
1345 - if (is_sfn(old) && is_out(new))
1348 - /* We should now be at the case of IN=>SFN,
1349 - * OUT=>SFN, OUT=>IN, SFN=>IN. */
1351 - change_mask |= mask;
1354 - /* Write the new CON settings */
1356 - gpcon = old_gpcon & ~change_mask;
1357 - gpcon |= gps_gpcon & change_mask;
1359 - __raw_writel(gpcon, base + OFFS_CON);
1361 - /* Now change any items that require DAT,CON */
1363 - __raw_writel(gps_gpdat, base + OFFS_DAT);
1364 - __raw_writel(gps_gpcon, base + OFFS_CON);
1365 - __raw_writel(gps->gpup, base + OFFS_UP);
1368 - S3C_PMDBG("GPIO[%d] CON %08lx => %08lx, DAT %08lx => %08lx\n",
1369 - index, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
1373 -/** s3c2410_pm_restore_gpios()
1375 - * Restore the state of the GPIOs
1378 -void s3c_pm_restore_gpios(void)
1380 - struct gpio_sleep *gps = gpio_save;
1383 - for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
1384 - s3c2410_pm_restore_gpio(gpio, gps);
1388 void s3c_pm_restore_core(void)
1390 Index: linux-2.6.30-rc6/drivers/mmc/host/Kconfig
1391 ===================================================================
1392 --- linux-2.6.30-rc6.orig/drivers/mmc/host/Kconfig 2009-05-18 19:07:38.000000000 +0200
1393 +++ linux-2.6.30-rc6/drivers/mmc/host/Kconfig 2009-05-18 19:07:48.000000000 +0200
1398 -config MMC_SDHCI_IO_ACCESSORS
1400 - depends on MMC_SDHCI
1402 - This is silent Kconfig symbol that is selected by the drivers that
1403 - need to overwrite SDHCI IO memory accessors.
1405 config MMC_SDHCI_PCI
1406 tristate "SDHCI support on PCI bus"
1407 depends on MMC_SDHCI && PCI
1412 +config MMC_SDHCI_S3C
1413 + tristate "SDHCI support on Samsung S3C SoC"
1414 + depends on MMC_SDHCI && PLAT_S3C24XX
1416 + This selects the Secure Digital Host Controller Interface (SDHCI)
1417 + often referrered to as the HSMMC block in some of the Samsung S3C
1420 + If you have a controller with this interface, say Y or M here.
1424 config MMC_RICOH_MMC
1425 tristate "Ricoh MMC Controller Disabler (EXPERIMENTAL)"
1426 depends on MMC_SDHCI_PCI
1431 -config MMC_SDHCI_OF
1432 - tristate "SDHCI support on OpenFirmware platforms"
1433 - depends on MMC_SDHCI && PPC_OF
1434 - select MMC_SDHCI_IO_ACCESSORS
1436 - This selects the OF support for Secure Digital Host Controller
1437 - Interfaces. So far, only the Freescale eSDHC controller is known
1438 - to exist on OF platforms.
1443 tristate "TI OMAP Multimedia Card Interface support"
1444 depends on ARCH_OMAP
1445 @@ -163,16 +157,6 @@
1450 - tristate "Freescale i.MX2/3 Multimedia Card Interface support"
1451 - depends on ARCH_MXC
1453 - This selects the Freescale i.MX2/3 Multimedia card Interface.
1454 - If you have a i.MX platform with a Multimedia Card slot,
1460 tristate "TI Flash Media MMC/SD Interface support (EXPERIMENTAL)"
1461 depends on EXPERIMENTAL && PCI
1462 Index: linux-2.6.30-rc6/drivers/mmc/host/Makefile
1463 ===================================================================
1464 --- linux-2.6.30-rc6.orig/drivers/mmc/host/Makefile 2009-05-18 19:07:38.000000000 +0200
1465 +++ linux-2.6.30-rc6/drivers/mmc/host/Makefile 2009-05-18 19:07:48.000000000 +0200
1467 obj-$(CONFIG_MMC_ARMMMCI) += mmci.o
1468 obj-$(CONFIG_MMC_PXA) += pxamci.o
1469 obj-$(CONFIG_MMC_IMX) += imxmmc.o
1470 -obj-$(CONFIG_MMC_MXC) += mxcmmc.o
1471 obj-$(CONFIG_MMC_SDHCI) += sdhci.o
1472 obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
1473 +obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
1474 obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o
1475 -obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o
1476 obj-$(CONFIG_MMC_WBSD) += wbsd.o
1477 obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
1478 obj-$(CONFIG_MMC_OMAP) += omap.o
1480 obj-$(CONFIG_MMC_AT91) += at91_mci.o
1481 obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o
1482 obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o
1483 -obj-$(CONFIG_MMC_MVSDIO) += mvsdio.o
1484 obj-$(CONFIG_MMC_SPI) += mmc_spi.o
1485 ifeq ($(CONFIG_OF),y)
1486 obj-$(CONFIG_MMC_SPI) += of_mmc_spi.o
1487 Index: linux-2.6.30-rc6/drivers/mmc/host/s3cmci.c
1488 ===================================================================
1489 --- linux-2.6.30-rc6.orig/drivers/mmc/host/s3cmci.c 2009-05-16 06:12:57.000000000 +0200
1490 +++ linux-2.6.30-rc6/drivers/mmc/host/s3cmci.c 2009-05-18 19:07:48.000000000 +0200
1492 * linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver
1494 * Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de>
1495 + * Copyright (C) 2007 Harald Welte <laforge@gnumonks.org>
1497 * Current driver maintained by Ben Dooks and Simtec Electronics
1498 * Copyright (C) 2008 Simtec Electronics <ben-linux@fluff.org>
1501 #include <mach/regs-sdi.h>
1502 #include <mach/regs-gpio.h>
1503 +#include <mach/hardware.h>
1505 #include <plat/mci.h>
1507 +#include <asm/dma.h>
1508 +#include <asm/dma-mapping.h>
1510 +#include <asm/io.h>
1511 +#include <mach/regs-gpio.h>
1512 +#include <mach/mci.h>
1513 +#include <mach/dma.h>
1517 #define DRIVER_NAME "s3c-mci"
1519 static const int dbgmap_info = dbg_info | dbg_conf;
1520 static const int dbgmap_debug = dbg_err | dbg_debug;
1522 +static int f_max = -1; /* override maximum frequency limit */
1523 +static int persist; /* keep interface alive across suspend/resume */
1525 #define dbg(host, channels, args...) \
1527 if (dbgmap_err & channels) \
1528 @@ -280,8 +293,11 @@
1529 * an even multiple of 4. */
1530 if (fifo >= host->pio_bytes)
1531 fifo = host->pio_bytes;
1539 host->pio_bytes -= fifo;
1540 host->pio_count += fifo;
1543 to_ptr = host->base + host->sdidata;
1545 - while ((fifo = fifo_free(host)) > 3) {
1546 + while ((fifo = fifo_free(host))) {
1547 if (!host->pio_bytes) {
1548 res = get_data_buffer(host, &host->pio_bytes,
1550 @@ -353,8 +369,11 @@
1551 * words, so round down to an even multiple of 4. */
1552 if (fifo >= host->pio_bytes)
1553 fifo = host->pio_bytes;
1561 host->pio_bytes -= fifo;
1562 host->pio_count += fifo;
1565 struct s3cmci_host *host = (struct s3cmci_host *) data;
1568 disable_irq(host->irq);
1570 if (host->pio_active == XFER_WRITE)
1573 spin_unlock_irqrestore(&host->complete_lock, iflags);
1579 @@ -789,11 +806,11 @@
1581 last_source = source;
1583 - s3c2410_dma_devconfig(host->dma, source, 3,
1584 + s3c2410_dma_devconfig(host->dma, source,
1585 host->mem->start + host->sdidata);
1588 - s3c2410_dma_config(host->dma, 4, 0);
1589 + s3c2410_dma_config(host->dma, 4);
1590 s3c2410_dma_set_buffdone_fn(host->dma,
1591 s3cmci_dma_done_callback);
1592 s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
1593 @@ -1026,6 +1043,7 @@
1594 dbg(host, dbg_err, "data prepare error %d\n", res);
1596 cmd->data->error = res;
1597 + cmd->data->error = -EIO;
1599 mmc_request_done(mmc, mrq);
1601 @@ -1263,10 +1281,8 @@
1602 host->is2440 = is2440;
1604 host->pdata = pdev->dev.platform_data;
1605 - if (!host->pdata) {
1606 - pdev->dev.platform_data = &s3cmci_def_pdata;
1608 host->pdata = &s3cmci_def_pdata;
1611 spin_lock_init(&host->complete_lock);
1612 tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
1613 @@ -1379,6 +1395,18 @@
1614 mmc->f_min = host->clk_rate / (host->clk_div * 256);
1615 mmc->f_max = host->clk_rate / host->clk_div;
1618 + unsigned f = f_max;
1620 + if (f < mmc->f_min)
1622 + if (mmc->f_max > f) {
1623 + dev_info(&pdev->dev, "f_max lowered from %u to %u Hz\n",
1629 if (host->pdata->ocr_avail)
1630 mmc->ocr_avail = host->pdata->ocr_avail;
1632 @@ -1491,18 +1519,60 @@
1636 +static int save_regs(struct mmc_host *mmc)
1638 + struct s3cmci_host *host = mmc_priv(mmc);
1639 + unsigned long flags;
1641 + u32 *to = host->saved;
1643 + mmc_flush_scheduled_work();
1645 + local_irq_save(flags);
1646 + for (from = S3C2410_SDICON; from != S3C2410_SDIIMSK+4; from += 4)
1647 + if (from != host->sdidata)
1648 + *to++ = readl(host->base + from);
1649 + BUG_ON(to-host->saved != ARRAY_SIZE(host->saved));
1650 + local_irq_restore(flags);
1655 +static int restore_regs(struct mmc_host *mmc)
1657 + struct s3cmci_host *host = mmc_priv(mmc);
1658 + unsigned long flags;
1660 + u32 *from = host->saved;
1663 + * Before we begin with the necromancy, make sure we don't
1664 + * inadvertently start something we'll regret microseconds later.
1666 + from[S3C2410_SDICMDCON - S3C2410_SDICON] = 0;
1668 + local_irq_save(flags);
1669 + for (to = S3C2410_SDICON; to != S3C2410_SDIIMSK+4; to += 4)
1670 + if (to != host->sdidata)
1671 + writel(*from++, host->base + to);
1672 + BUG_ON(from-host->saved != ARRAY_SIZE(host->saved));
1673 + local_irq_restore(flags);
1678 static int s3cmci_suspend(struct platform_device *dev, pm_message_t state)
1680 struct mmc_host *mmc = platform_get_drvdata(dev);
1682 - return mmc_suspend_host(mmc, state);
1683 + return persist ? save_regs(mmc) : mmc_suspend_host(mmc, state);
1686 static int s3cmci_resume(struct platform_device *dev)
1688 struct mmc_host *mmc = platform_get_drvdata(dev);
1690 - return mmc_resume_host(mmc);
1691 + return persist ? restore_regs(mmc) : mmc_resume_host(mmc);
1694 #else /* CONFIG_PM */
1695 @@ -1560,9 +1630,13 @@
1696 module_init(s3cmci_init);
1697 module_exit(s3cmci_exit);
1699 +module_param(f_max, int, 0644);
1700 +module_param(persist, int, 0644);
1702 MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
1703 MODULE_LICENSE("GPL v2");
1704 MODULE_AUTHOR("Thomas Kleffel <tk@maintech.de>, Ben Dooks <ben-linux@fluff.org>");
1705 MODULE_ALIAS("platform:s3c2410-sdi");
1706 MODULE_ALIAS("platform:s3c2412-sdi");
1707 MODULE_ALIAS("platform:s3c2440-sdi");
1709 Index: linux-2.6.30-rc6/drivers/mmc/host/s3cmci.h
1710 ===================================================================
1711 --- linux-2.6.30-rc6.orig/drivers/mmc/host/s3cmci.h 2009-05-16 06:12:57.000000000 +0200
1712 +++ linux-2.6.30-rc6/drivers/mmc/host/s3cmci.h 2009-05-18 19:07:48.000000000 +0200
1714 * published by the Free Software Foundation.
1718 +#include <mach/regs-sdi.h>
1719 +#include <linux/regulator/consumer.h>
1721 /* FIXME: DMA Resource management ?! */
1722 #define S3CMCI_DMA 0
1725 unsigned int ccnt, dcnt;
1726 struct tasklet_struct pio_tasklet;
1729 + * Here's where we save the registers during suspend. Note that we skip
1730 + * SDIDATA, which is at different positions on 2410 and 2440, so
1731 + * there's no "+1" in the array size.
1733 + u32 saved[(S3C2410_SDIIMSK-S3C2410_SDICON)/4];
1735 #ifdef CONFIG_CPU_FREQ
1736 struct notifier_block freq_transition;
1739 + struct regulator *regulator;
1741 Index: linux-2.6.30-rc6/drivers/mmc/host/sdhci-s3c.c
1742 ===================================================================
1743 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
1744 +++ linux-2.6.30-rc6/drivers/mmc/host/sdhci-s3c.c 2009-05-18 19:07:48.000000000 +0200
1746 +/* linux/drivers/mmc/host/sdhci-s3c.c
1748 + * Copyright 2008 Openmoko Inc.
1749 + * Copyright 2008 Simtec Electronics
1750 + * Ben Dooks <ben@simtec.co.uk>
1751 + * http://armlinux.simtec.co.uk/
1753 + * SDHCI (HSMMC) support for Samsung SoC
1755 + * This program is free software; you can redistribute it and/or modify
1756 + * it under the terms of the GNU General Public License version 2 as
1757 + * published by the Free Software Foundation.
1760 +#include <linux/delay.h>
1761 +#include <linux/dma-mapping.h>
1762 +#include <linux/platform_device.h>
1763 +#include <linux/clk.h>
1764 +#include <linux/io.h>
1766 +#include <linux/mmc/host.h>
1768 +#include <plat/regs-sdhci.h>
1769 +#include <plat/sdhci.h>
1773 +#define MAX_BUS_CLK (4)
1776 + struct sdhci_host *host;
1777 + struct platform_device *pdev;
1778 + struct resource *ioarea;
1779 + struct s3c_sdhci_platdata *pdata;
1780 + unsigned int cur_clk;
1782 + struct clk *clk_io; /* clock for io bus */
1783 + struct clk *clk_bus[MAX_BUS_CLK];
1786 +static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
1788 + return sdhci_priv(host);
1791 +static u32 get_curclk(u32 ctrl2)
1793 + ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
1794 + ctrl2 >>= S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
1799 +static void sdhci_s3c_check_sclk(struct sdhci_host *host)
1801 + struct sdhci_s3c *ourhost = to_s3c(host);
1802 + u32 tmp = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
1804 + if (get_curclk(tmp) != ourhost->cur_clk) {
1805 + dev_dbg(&ourhost->pdev->dev, "restored ctrl2 clock setting\n");
1807 + tmp &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
1808 + tmp |= ourhost->cur_clk << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
1809 + writel(tmp, host->ioaddr + 0x80);
1813 +static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host)
1815 + struct sdhci_s3c *ourhost = to_s3c(host);
1816 + struct clk *busclk;
1817 + unsigned int rate, max;
1820 + /* note, a reset will reset the clock source */
1822 + sdhci_s3c_check_sclk(host);
1824 + for (max = 0, clk = 0; clk < MAX_BUS_CLK; clk++) {
1825 + busclk = ourhost->clk_bus[clk];
1829 + rate = clk_get_rate(busclk);
1837 +static unsigned int sdhci_s3c_get_timeout_clk(struct sdhci_host *host)
1839 + return sdhci_s3c_get_max_clk(host) / 1000000;
1842 +static void sdhci_s3c_set_ios(struct sdhci_host *host,
1843 + struct mmc_ios *ios)
1845 + struct sdhci_s3c *ourhost = to_s3c(host);
1846 + struct s3c_sdhci_platdata *pdata = ourhost->pdata;
1849 + sdhci_s3c_check_sclk(host);
1851 + if (ios->power_mode != MMC_POWER_OFF) {
1852 + switch (ios->bus_width) {
1853 + case MMC_BUS_WIDTH_4:
1856 + case MMC_BUS_WIDTH_1:
1863 + if (pdata->cfg_gpio)
1864 + pdata->cfg_gpio(ourhost->pdev, width);
1867 + if (pdata->cfg_card)
1868 + pdata->cfg_card(ourhost->pdev, host->ioaddr,
1869 + ios, host->mmc->card);
1872 +static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
1874 + unsigned int wanted)
1876 + unsigned long rate;
1877 + struct clk *clksrc = ourhost->clk_bus[src];
1883 + rate = clk_get_rate(clksrc);
1885 + for (div = 1; div < 256; div *= 2) {
1886 + if ((rate / div) <= wanted)
1890 + dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n",
1891 + src, rate, wanted, rate / div);
1893 + return (wanted - (rate / div));
1896 +static void sdhci_s3c_change_clock(struct sdhci_host *host, unsigned int clock)
1898 + struct sdhci_s3c *ourhost = to_s3c(host);
1899 + unsigned int best = UINT_MAX;
1900 + unsigned int delta;
1905 + for (src = 0; src < MAX_BUS_CLK; src++) {
1906 + delta = sdhci_s3c_consider_clock(ourhost, src, clock);
1907 + if (delta < best) {
1913 + dev_dbg(&ourhost->pdev->dev,
1914 + "selected source %d, clock %d, delta %d\n",
1915 + best_src, clock, best);
1917 + /* turn clock off to card before changing clock source */
1918 + writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
1920 + /* select the new clock source */
1922 + if (ourhost->cur_clk != best_src) {
1923 + struct clk *clk = ourhost->clk_bus[best_src];
1925 + ourhost->cur_clk = best_src;
1926 + host->max_clk = clk_get_rate(clk);
1927 + host->timeout_clk = host->max_clk / 1000000;
1929 + ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
1930 + ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
1931 + ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
1932 + writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2);
1935 + sdhci_change_clock(host, clock);
1938 +static struct sdhci_ops sdhci_s3c_ops = {
1939 + .get_max_clock = sdhci_s3c_get_max_clk,
1940 + .get_timeout_clock = sdhci_s3c_get_timeout_clk,
1941 + .change_clock = sdhci_s3c_change_clock,
1942 + .set_ios = sdhci_s3c_set_ios,
1946 + * call this when you need sd stack to recognize insertion or removal of card
1947 + * that can't be told by SDHCI regs
1950 +void sdhci_s3c_force_presence_change(struct platform_device *pdev)
1952 + struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
1954 + dev_info(&pdev->dev, "sdhci_s3c_force_presence_change called\n");
1955 + mmc_detect_change(pdata->sdhci_host->mmc, msecs_to_jiffies(200));
1957 +EXPORT_SYMBOL_GPL(sdhci_s3c_force_presence_change);
1960 +static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
1962 + struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
1963 + struct device *dev = &pdev->dev;
1964 + struct sdhci_host *host;
1965 + struct sdhci_s3c *sc;
1966 + struct resource *res;
1967 + int ret, irq, ptr, clks;
1970 + dev_err(dev, "no device data specified\n");
1974 + irq = platform_get_irq(pdev, 0);
1976 + dev_err(dev, "no irq specified\n");
1980 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1982 + dev_err(dev, "no memory specified\n");
1986 + host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c));
1987 + if (IS_ERR(host)) {
1988 + dev_err(dev, "sdhci_alloc_host() failed\n");
1989 + return PTR_ERR(host);
1992 + pdata->sdhci_host = host;
1994 + sc = sdhci_priv(host);
1998 + sc->pdata = pdata;
2000 + platform_set_drvdata(pdev, host);
2002 + sc->clk_io = clk_get(dev, "hsmmc");
2003 + if (IS_ERR(sc->clk_io)) {
2004 + dev_err(dev, "failed to get io clock\n");
2005 + ret = PTR_ERR(sc->clk_io);
2009 + /* enable the local io clock and keep it running for the moment. */
2010 + clk_enable(sc->clk_io);
2012 + for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
2014 + char *name = pdata->clocks[ptr];
2019 + clk = clk_get(dev, name);
2020 + if (IS_ERR(clk)) {
2021 + dev_err(dev, "failed to get clock %s\n", name);
2026 + sc->clk_bus[ptr] = clk;
2029 + dev_info(dev, "clock source %d: %s (%ld Hz)\n",
2030 + ptr, name, clk_get_rate(clk));
2034 + dev_err(dev, "failed to find any bus clocks\n");
2036 + goto err_no_busclks;
2039 + sc->ioarea = request_mem_region(res->start, resource_size(res),
2040 + mmc_hostname(host->mmc));
2041 + if (!sc->ioarea) {
2042 + dev_err(dev, "failed to reserve register area\n");
2044 + goto err_req_regs;
2047 + host->ioaddr = ioremap_nocache(res->start, resource_size(res));
2048 + if (!host->ioaddr) {
2049 + dev_err(dev, "failed to map registers\n");
2051 + goto err_req_regs;
2054 + /* Ensure we have minimal gpio selected CMD/CLK/Detect */
2055 + if (pdata->cfg_gpio)
2056 + pdata->cfg_gpio(pdev, 0);
2058 + sdhci_s3c_check_sclk(host);
2060 + host->hw_name = "samsung-hsmmc";
2061 + host->ops = &sdhci_s3c_ops;
2065 + /* Setup quirks for the controller */
2067 + /* Currently with ADMA enabled we are getting some length
2068 + * interrupts that are not being dealt with, do disable
2069 + * ADMA until this is sorted out. */
2070 + host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
2071 + host->quirks |= SDHCI_QUIRK_32BIT_ADMA_SIZE;
2073 + /* It seems we do not get an DATA transfer complete on non-busy
2074 + * transfers, not sure if this is a problem with this specific
2075 + * SDHCI block, or a missing configuration that needs to be set. */
2076 + host->quirks |= SDHCI_QUIRK_NO_TCIRQ_ON_NOT_BUSY;
2078 + host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR |
2079 + SDHCI_QUIRK_32BIT_DMA_SIZE);
2081 + ret = sdhci_add_host(host);
2083 + dev_err(dev, "sdhci_add_host() failed\n");
2084 + goto err_add_host;
2090 + release_resource(sc->ioarea);
2091 + kfree(sc->ioarea);
2094 + for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
2095 + clk_disable(sc->clk_bus[ptr]);
2096 + clk_put(sc->clk_bus[ptr]);
2100 + clk_disable(sc->clk_io);
2101 + clk_put(sc->clk_io);
2104 + sdhci_free_host(host);
2109 +static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
2116 +static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm)
2118 + struct sdhci_host *host = platform_get_drvdata(dev);
2120 + sdhci_suspend_host(host, pm);
2124 +static int sdhci_s3c_resume(struct platform_device *dev)
2126 + struct sdhci_host *host = platform_get_drvdata(dev);
2128 + sdhci_resume_host(host);
2133 +#define sdhci_s3c_suspend NULL
2134 +#define sdhci_s3c_resume NULL
2137 +static struct platform_driver sdhci_s3c_driver = {
2138 + .probe = sdhci_s3c_probe,
2139 + .remove = __devexit_p(sdhci_s3c_remove),
2140 + .suspend = sdhci_s3c_suspend,
2141 + .resume = sdhci_s3c_resume,
2143 + .owner = THIS_MODULE,
2144 + .name = "s3c-sdhci",
2148 +static int __init sdhci_s3c_init(void)
2150 + return platform_driver_register(&sdhci_s3c_driver);
2153 +static void __exit sdhci_s3c_exit(void)
2155 + platform_driver_unregister(&sdhci_s3c_driver);
2158 +module_init(sdhci_s3c_init);
2159 +module_exit(sdhci_s3c_exit);
2161 +MODULE_DESCRIPTION("Samsung SDHCI (HSMMC) glue");
2162 +MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
2163 +MODULE_LICENSE("GPL v2");
2164 +MODULE_ALIAS("platform:s3c-sdhci");
2165 Index: linux-2.6.30-rc6/drivers/mtd/nand/s3c2410.c
2166 ===================================================================
2167 --- linux-2.6.30-rc6.orig/drivers/mtd/nand/s3c2410.c 2009-05-16 06:12:57.000000000 +0200
2168 +++ linux-2.6.30-rc6/drivers/mtd/nand/s3c2410.c 2009-05-18 19:07:48.000000000 +0200
2170 if ((diff0 & ~(1<<fls(diff0))) == 0)
2178 @@ -530,7 +530,12 @@
2179 static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
2181 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
2182 + u8 *ptr = buf + (len & ~3);
2185 readsl(info->regs + S3C2440_NFDATA, buf, len / 4);
2186 + for (i = 0; i != (len & 3); i++)
2187 + ptr[i] = readb(info->regs + S3C2440_NFDATA);
2190 static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
2191 @@ -645,17 +650,31 @@
2194 #ifdef CONFIG_MTD_PARTITIONS
2195 +const char *part_probes[] = { "cmdlinepart", NULL };
2196 static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
2197 struct s3c2410_nand_mtd *mtd,
2198 struct s3c2410_nand_set *set)
2200 + struct mtd_partition *part_info;
2204 return add_mtd_device(&mtd->mtd);
2206 - if (set->nr_partitions > 0 && set->partitions != NULL) {
2207 - return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions);
2208 + if (set->nr_partitions == 0) {
2209 + mtd->mtd.name = set->name;
2210 + nr_part = parse_mtd_partitions(&mtd->mtd, part_probes,
2213 + if (set->nr_partitions > 0 && set->partitions != NULL) {
2214 + nr_part = set->nr_partitions;
2215 + part_info = set->partitions;
2219 + if (nr_part > 0 && part_info)
2220 + return add_mtd_partitions(&mtd->mtd, part_info, nr_part);
2222 return add_mtd_device(&mtd->mtd);
2225 @@ -684,9 +703,13 @@
2226 chip->select_chip = s3c2410_nand_select_chip;
2227 chip->chip_delay = 50;
2229 - chip->options = 0;
2230 chip->controller = &info->controller;
2232 + if (set->flags & S3C2410_NAND_BBT)
2233 + chip->options = NAND_USE_FLASH_BBT;
2235 + chip->options = 0;
2237 switch (info->cpu_type) {
2239 chip->IO_ADDR_W = regs + S3C2410_NFDATA;
2241 nmtd->mtd.owner = THIS_MODULE;
2244 - if (hardware_ecc) {
2245 + if (!info->platform->software_ecc && hardware_ecc) {
2246 chip->ecc.calculate = s3c2410_nand_calculate_ecc;
2247 chip->ecc.correct = s3c2410_nand_correct_data;
2248 chip->ecc.mode = NAND_ECC_HW;
2249 Index: linux-2.6.30-rc6/drivers/mmc/core/core.c
2250 ===================================================================
2251 --- linux-2.6.30-rc6.orig/drivers/mmc/core/core.c 2009-05-16 06:12:57.000000000 +0200
2252 +++ linux-2.6.30-rc6/drivers/mmc/core/core.c 2009-05-18 19:07:48.000000000 +0200
2255 * Internal function. Flush all scheduled work from the MMC work queue.
2257 -static void mmc_flush_scheduled_work(void)
2258 +void mmc_flush_scheduled_work(void)
2260 flush_workqueue(workqueue);
2262 +EXPORT_SYMBOL_GPL(mmc_flush_scheduled_work);
2265 * mmc_request_done - finish processing an MMC request