Root/target/linux/s3c24xx/patches-2.6.30/001-merge-openmoko.patch

1Merge OpenMoko kernel patches
2git://git.openmoko.org/git/kernel.git#(no
3
4lars@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
2208

Archive Download this file



interactive