aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/common/Kconfig7
-rw-r--r--arch/arm/common/vic.c221
-rw-r--r--arch/arm/include/asm/hardware/vic.h2
-rw-r--r--arch/arm/mach-ep93xx/core.c4
-rw-r--r--arch/arm/mach-netx/generic.c2
-rw-r--r--arch/arm/mach-s3c2410/Kconfig8
-rw-r--r--arch/arm/mach-s3c2410/include/mach/map.h2
-rw-r--r--arch/arm/mach-s3c2410/include/mach/system-reset.h36
-rw-r--r--arch/arm/mach-s3c2412/Kconfig3
-rw-r--r--arch/arm/mach-s3c2440/Kconfig5
-rw-r--r--arch/arm/mach-s3c6400/Kconfig25
-rw-r--r--arch/arm/mach-s3c6400/Makefile10
-rw-r--r--arch/arm/mach-s3c6400/include/mach/map.h6
-rw-r--r--arch/arm/mach-s3c6400/include/mach/regs-clock.h16
-rw-r--r--arch/arm/mach-s3c6400/include/mach/system.h8
-rw-r--r--arch/arm/mach-s3c6400/mach-smdk6400.c96
-rw-r--r--arch/arm/mach-s3c6400/s3c6400.c89
-rw-r--r--arch/arm/mach-s3c6400/setup-sdhci.c63
-rw-r--r--arch/arm/mach-s3c6410/Kconfig37
-rw-r--r--arch/arm/mach-s3c6410/Makefile4
-rw-r--r--arch/arm/mach-s3c6410/cpu.c3
-rw-r--r--arch/arm/mach-s3c6410/mach-anw6410.c245
-rw-r--r--arch/arm/mach-s3c6410/mach-ncp.c107
-rw-r--r--arch/arm/mach-s3c6410/mach-smdk6410.c198
-rw-r--r--arch/arm/mach-s3c6410/setup-sdhci.c34
-rw-r--r--arch/arm/mach-versatile/core.c2
-rw-r--r--arch/arm/plat-s3c/Kconfig19
-rw-r--r--arch/arm/plat-s3c/Makefile3
-rw-r--r--arch/arm/plat-s3c/dev-usb-hsotg.c41
-rw-r--r--arch/arm/plat-s3c/dev-usb.c50
-rw-r--r--arch/arm/plat-s3c/gpio.c11
-rw-r--r--arch/arm/plat-s3c/include/plat/adc.h10
-rw-r--r--arch/arm/plat-s3c/include/plat/clock.h1
-rw-r--r--arch/arm/plat-s3c/include/plat/cpu.h3
-rw-r--r--arch/arm/plat-s3c/include/plat/devs.h1
-rw-r--r--arch/arm/plat-s3c/include/plat/gpio-core.h30
-rw-r--r--arch/arm/plat-s3c/include/plat/pm.h15
-rw-r--r--arch/arm/plat-s3c/include/plat/regs-serial.h5
-rw-r--r--arch/arm/plat-s3c/include/plat/sdhci.h50
-rw-r--r--arch/arm/plat-s3c/include/plat/udc-hs.h29
-rw-r--r--arch/arm/plat-s3c/include/plat/watchdog-reset.h49
-rw-r--r--arch/arm/plat-s3c/pm-gpio.c380
-rw-r--r--arch/arm/plat-s3c/pm.c19
-rw-r--r--arch/arm/plat-s3c24xx/adc.c11
-rw-r--r--arch/arm/plat-s3c24xx/devs.c30
-rw-r--r--arch/arm/plat-s3c24xx/gpiolib.c8
-rw-r--r--arch/arm/plat-s3c24xx/include/plat/map.h1
-rw-r--r--arch/arm/plat-s3c24xx/include/plat/pm-core.h5
-rw-r--r--arch/arm/plat-s3c24xx/pm.c213
-rw-r--r--arch/arm/plat-s3c64xx/Kconfig6
-rw-r--r--arch/arm/plat-s3c64xx/Makefile7
-rw-r--r--arch/arm/plat-s3c64xx/clock.c19
-rw-r--r--arch/arm/plat-s3c64xx/cpu.c32
-rw-r--r--arch/arm/plat-s3c64xx/gpiolib.c10
-rw-r--r--arch/arm/plat-s3c64xx/include/plat/irqs.h1
-rw-r--r--arch/arm/plat-s3c64xx/include/plat/pm-core.h98
-rw-r--r--arch/arm/plat-s3c64xx/include/plat/regs-clock.h1
-rw-r--r--arch/arm/plat-s3c64xx/include/plat/s3c6400.h3
-rw-r--r--arch/arm/plat-s3c64xx/irq-eint.c3
-rw-r--r--arch/arm/plat-s3c64xx/irq-pm.c111
-rw-r--r--arch/arm/plat-s3c64xx/irq.c9
-rw-r--r--arch/arm/plat-s3c64xx/pm.c175
-rw-r--r--arch/arm/plat-s3c64xx/s3c6400-clock.c106
-rw-r--r--arch/arm/plat-s3c64xx/setup-sdhci-gpio.c55
-rw-r--r--arch/arm/plat-s3c64xx/sleep.S144
65 files changed, 2644 insertions, 353 deletions
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index a2cd9beaf37d..38518d450bc0 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -4,6 +4,13 @@ config ARM_GIC
4config ARM_VIC 4config ARM_VIC
5 bool 5 bool
6 6
7config ARM_VIC_NR
8 int
9 default 2
10 help
11 The maximum number of VICs available in the system, for
12 power management.
13
7config ICST525 14config ICST525
8 bool 15 bool
9 16
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index b2a781d9ce05..887c6eb3a18a 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -21,6 +21,7 @@
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/list.h> 22#include <linux/list.h>
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/sysdev.h>
24 25
25#include <asm/mach/irq.h> 26#include <asm/mach/irq.h>
26#include <asm/hardware/vic.h> 27#include <asm/hardware/vic.h>
@@ -39,11 +40,219 @@ static void vic_unmask_irq(unsigned int irq)
39 writel(1 << irq, base + VIC_INT_ENABLE); 40 writel(1 << irq, base + VIC_INT_ENABLE);
40} 41}
41 42
43/**
44 * vic_init2 - common initialisation code
45 * @base: Base of the VIC.
46 *
47 * Common initialisation code for registeration
48 * and resume.
49*/
50static void vic_init2(void __iomem *base)
51{
52 int i;
53
54 for (i = 0; i < 16; i++) {
55 void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
56 writel(VIC_VECT_CNTL_ENABLE | i, reg);
57 }
58
59 writel(32, base + VIC_PL190_DEF_VECT_ADDR);
60}
61
62#if defined(CONFIG_PM)
63/**
64 * struct vic_device - VIC PM device
65 * @sysdev: The system device which is registered.
66 * @irq: The IRQ number for the base of the VIC.
67 * @base: The register base for the VIC.
68 * @resume_sources: A bitmask of interrupts for resume.
69 * @resume_irqs: The IRQs enabled for resume.
70 * @int_select: Save for VIC_INT_SELECT.
71 * @int_enable: Save for VIC_INT_ENABLE.
72 * @soft_int: Save for VIC_INT_SOFT.
73 * @protect: Save for VIC_PROTECT.
74 */
75struct vic_device {
76 struct sys_device sysdev;
77
78 void __iomem *base;
79 int irq;
80 u32 resume_sources;
81 u32 resume_irqs;
82 u32 int_select;
83 u32 int_enable;
84 u32 soft_int;
85 u32 protect;
86};
87
88/* we cannot allocate memory when VICs are initially registered */
89static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];
90
91static inline struct vic_device *to_vic(struct sys_device *sys)
92{
93 return container_of(sys, struct vic_device, sysdev);
94}
95
96static int vic_id;
97
98static int vic_class_resume(struct sys_device *dev)
99{
100 struct vic_device *vic = to_vic(dev);
101 void __iomem *base = vic->base;
102
103 printk(KERN_DEBUG "%s: resuming vic at %p\n", __func__, base);
104
105 /* re-initialise static settings */
106 vic_init2(base);
107
108 writel(vic->int_select, base + VIC_INT_SELECT);
109 writel(vic->protect, base + VIC_PROTECT);
110
111 /* set the enabled ints and then clear the non-enabled */
112 writel(vic->int_enable, base + VIC_INT_ENABLE);
113 writel(~vic->int_enable, base + VIC_INT_ENABLE_CLEAR);
114
115 /* and the same for the soft-int register */
116
117 writel(vic->soft_int, base + VIC_INT_SOFT);
118 writel(~vic->soft_int, base + VIC_INT_SOFT_CLEAR);
119
120 return 0;
121}
122
123static int vic_class_suspend(struct sys_device *dev, pm_message_t state)
124{
125 struct vic_device *vic = to_vic(dev);
126 void __iomem *base = vic->base;
127
128 printk(KERN_DEBUG "%s: suspending vic at %p\n", __func__, base);
129
130 vic->int_select = readl(base + VIC_INT_SELECT);
131 vic->int_enable = readl(base + VIC_INT_ENABLE);
132 vic->soft_int = readl(base + VIC_INT_SOFT);
133 vic->protect = readl(base + VIC_PROTECT);
134
135 /* set the interrupts (if any) that are used for
136 * resuming the system */
137
138 writel(vic->resume_irqs, base + VIC_INT_ENABLE);
139 writel(~vic->resume_irqs, base + VIC_INT_ENABLE_CLEAR);
140
141 return 0;
142}
143
144struct sysdev_class vic_class = {
145 .name = "vic",
146 .suspend = vic_class_suspend,
147 .resume = vic_class_resume,
148};
149
150/**
151 * vic_pm_register - Register a VIC for later power management control
152 * @base: The base address of the VIC.
153 * @irq: The base IRQ for the VIC.
154 * @resume_sources: bitmask of interrupts allowed for resume sources.
155 *
156 * Register the VIC with the system device tree so that it can be notified
157 * of suspend and resume requests and ensure that the correct actions are
158 * taken to re-instate the settings on resume.
159 */
160static void __init vic_pm_register(void __iomem *base, unsigned int irq, u32 resume_sources)
161{
162 struct vic_device *v;
163
164 if (vic_id >= ARRAY_SIZE(vic_devices))
165 printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__);
166 else {
167 v = &vic_devices[vic_id];
168 v->base = base;
169 v->resume_sources = resume_sources;
170 v->irq = irq;
171 vic_id++;
172 }
173}
174
175/**
176 * vic_pm_init - initicall to register VIC pm
177 *
178 * This is called via late_initcall() to register
179 * the resources for the VICs due to the early
180 * nature of the VIC's registration.
181*/
182static int __init vic_pm_init(void)
183{
184 struct vic_device *dev = vic_devices;
185 int err;
186 int id;
187
188 if (vic_id == 0)
189 return 0;
190
191 err = sysdev_class_register(&vic_class);
192 if (err) {
193 printk(KERN_ERR "%s: cannot register class\n", __func__);
194 return err;
195 }
196
197 for (id = 0; id < vic_id; id++, dev++) {
198 dev->sysdev.id = id;
199 dev->sysdev.cls = &vic_class;
200
201 err = sysdev_register(&dev->sysdev);
202 if (err) {
203 printk(KERN_ERR "%s: failed to register device\n",
204 __func__);
205 return err;
206 }
207 }
208
209 return 0;
210}
211
212late_initcall(vic_pm_init);
213
214static struct vic_device *vic_from_irq(unsigned int irq)
215{
216 struct vic_device *v = vic_devices;
217 unsigned int base_irq = irq & ~31;
218 int id;
219
220 for (id = 0; id < vic_id; id++, v++) {
221 if (v->irq == base_irq)
222 return v;
223 }
224
225 return NULL;
226}
227
228static int vic_set_wake(unsigned int irq, unsigned int on)
229{
230 struct vic_device *v = vic_from_irq(irq);
231 unsigned int off = irq & 31;
232
233 if (!v)
234 return -EINVAL;
235
236 if (on)
237 v->resume_irqs |= 1 << off;
238 else
239 v->resume_irqs &= ~(1 << off);
240
241 return 0;
242}
243
244#else
245static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg1) { }
246
247#define vic_set_wake NULL
248#endif /* CONFIG_PM */
249
42static struct irq_chip vic_chip = { 250static struct irq_chip vic_chip = {
43 .name = "VIC", 251 .name = "VIC",
44 .ack = vic_mask_irq, 252 .ack = vic_mask_irq,
45 .mask = vic_mask_irq, 253 .mask = vic_mask_irq,
46 .unmask = vic_unmask_irq, 254 .unmask = vic_unmask_irq,
255 .set_wake = vic_set_wake,
47}; 256};
48 257
49/** 258/**
@@ -51,9 +260,10 @@ static struct irq_chip vic_chip = {
51 * @base: iomem base address 260 * @base: iomem base address
52 * @irq_start: starting interrupt number, must be muliple of 32 261 * @irq_start: starting interrupt number, must be muliple of 32
53 * @vic_sources: bitmask of interrupt sources to allow 262 * @vic_sources: bitmask of interrupt sources to allow
263 * @resume_sources: bitmask of interrupt sources to allow for resume
54 */ 264 */
55void __init vic_init(void __iomem *base, unsigned int irq_start, 265void __init vic_init(void __iomem *base, unsigned int irq_start,
56 u32 vic_sources) 266 u32 vic_sources, u32 resume_sources)
57{ 267{
58 unsigned int i; 268 unsigned int i;
59 269
@@ -77,12 +287,7 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
77 writel(value, base + VIC_PL190_VECT_ADDR); 287 writel(value, base + VIC_PL190_VECT_ADDR);
78 } 288 }
79 289
80 for (i = 0; i < 16; i++) { 290 vic_init2(base);
81 void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
82 writel(VIC_VECT_CNTL_ENABLE | i, reg);
83 }
84
85 writel(32, base + VIC_PL190_DEF_VECT_ADDR);
86 291
87 for (i = 0; i < 32; i++) { 292 for (i = 0; i < 32; i++) {
88 if (vic_sources & (1 << i)) { 293 if (vic_sources & (1 << i)) {
@@ -94,4 +299,6 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
94 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); 299 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
95 } 300 }
96 } 301 }
302
303 vic_pm_register(base, irq_start, resume_sources);
97} 304}
diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h
index f87328d4a180..5d72550a8097 100644
--- a/arch/arm/include/asm/hardware/vic.h
+++ b/arch/arm/include/asm/hardware/vic.h
@@ -41,7 +41,7 @@
41#define VIC_PL192_VECT_ADDR 0xF00 41#define VIC_PL192_VECT_ADDR 0xF00
42 42
43#ifndef __ASSEMBLY__ 43#ifndef __ASSEMBLY__
44void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources); 44void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
45#endif 45#endif
46 46
47#endif 47#endif
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index ae24486f858a..6faa3dc29cec 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -362,8 +362,8 @@ void __init ep93xx_init_irq(void)
362{ 362{
363 int gpio_irq; 363 int gpio_irq;
364 364
365 vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK); 365 vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0);
366 vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK); 366 vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0);
367 367
368 for (gpio_irq = gpio_to_irq(0); 368 for (gpio_irq = gpio_to_irq(0);
369 gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) { 369 gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c
index 79df60c20e70..43da8bb4926b 100644
--- a/arch/arm/mach-netx/generic.c
+++ b/arch/arm/mach-netx/generic.c
@@ -168,7 +168,7 @@ void __init netx_init_irq(void)
168{ 168{
169 int irq; 169 int irq;
170 170
171 vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0); 171 vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0, 0);
172 172
173 for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) { 173 for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) {
174 set_irq_chip(irq, &netx_hif_chip); 174 set_irq_chip(irq, &netx_hif_chip);
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 63a30d1dd425..41bb65d5b91f 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -59,6 +59,7 @@ config ARCH_H1940
59 bool "IPAQ H1940" 59 bool "IPAQ H1940"
60 select CPU_S3C2410 60 select CPU_S3C2410
61 select PM_H1940 if PM 61 select PM_H1940 if PM
62 select S3C_DEV_USB_HOST
62 help 63 help
63 Say Y here if you are using the HP IPAQ H1940 64 Say Y here if you are using the HP IPAQ H1940
64 65
@@ -70,6 +71,7 @@ config PM_H1940
70config MACH_N30 71config MACH_N30
71 bool "Acer N30 family" 72 bool "Acer N30 family"
72 select CPU_S3C2410 73 select CPU_S3C2410
74 select S3C_DEV_USB_HOST
73 help 75 help
74 Say Y here if you want suppt for the Acer N30, Acer N35, 76 Say Y here if you want suppt for the Acer N30, Acer N35,
75 Navman PiN570, Yakumo AlphaX or Airis NC05 PDAs. 77 Navman PiN570, Yakumo AlphaX or Airis NC05 PDAs.
@@ -82,6 +84,7 @@ config ARCH_BAST
82 select MACH_BAST_IDE 84 select MACH_BAST_IDE
83 select S3C24XX_DCLK 85 select S3C24XX_DCLK
84 select ISA 86 select ISA
87 select S3C_DEV_USB_HOST
85 help 88 help
86 Say Y here if you are using the Simtec Electronics EB2410ITX 89 Say Y here if you are using the Simtec Electronics EB2410ITX
87 development board (also known as BAST) 90 development board (also known as BAST)
@@ -89,6 +92,7 @@ config ARCH_BAST
89config MACH_OTOM 92config MACH_OTOM
90 bool "NexVision OTOM Board" 93 bool "NexVision OTOM Board"
91 select CPU_S3C2410 94 select CPU_S3C2410
95 select S3C_DEV_USB_HOST
92 help 96 help
93 Say Y here if you are using the Nex Vision OTOM board 97 Say Y here if you are using the Nex Vision OTOM board
94 98
@@ -96,6 +100,7 @@ config MACH_AML_M5900
96 bool "AML M5900 Series" 100 bool "AML M5900 Series"
97 select CPU_S3C2410 101 select CPU_S3C2410
98 select PM_SIMTEC if PM 102 select PM_SIMTEC if PM
103 select S3C_DEV_USB_HOST
99 help 104 help
100 Say Y here if you are using the American Microsystems M5900 Series 105 Say Y here if you are using the American Microsystems M5900 Series
101 <http://www.amltd.com> 106 <http://www.amltd.com>
@@ -111,6 +116,7 @@ config BAST_PC104_IRQ
111config MACH_TCT_HAMMER 116config MACH_TCT_HAMMER
112 bool "TCT Hammer Board" 117 bool "TCT Hammer Board"
113 select CPU_S3C2410 118 select CPU_S3C2410
119 select S3C_DEV_USB_HOST
114 help 120 help
115 Say Y here if you are using the TinCanTools Hammer Board 121 Say Y here if you are using the TinCanTools Hammer Board
116 <http://www.tincantools.com> 122 <http://www.tincantools.com>
@@ -122,12 +128,14 @@ config MACH_VR1000
122 select SIMTEC_NOR 128 select SIMTEC_NOR
123 select MACH_BAST_IDE 129 select MACH_BAST_IDE
124 select CPU_S3C2410 130 select CPU_S3C2410
131 select S3C_DEV_USB_HOST
125 help 132 help
126 Say Y here if you are using the Thorcom VR1000 board. 133 Say Y here if you are using the Thorcom VR1000 board.
127 134
128config MACH_QT2410 135config MACH_QT2410
129 bool "QT2410" 136 bool "QT2410"
130 select CPU_S3C2410 137 select CPU_S3C2410
138 select S3C_DEV_USB_HOST
131 help 139 help
132 Say Y here if you are using the Armzone QT2410 140 Say Y here if you are using the Armzone QT2410
133 141
diff --git a/arch/arm/mach-s3c2410/include/mach/map.h b/arch/arm/mach-s3c2410/include/mach/map.h
index 255fdfeaf957..e99b212cb1ca 100644
--- a/arch/arm/mach-s3c2410/include/mach/map.h
+++ b/arch/arm/mach-s3c2410/include/mach/map.h
@@ -84,7 +84,6 @@
84 84
85#define S3C24XX_PA_IRQ S3C2410_PA_IRQ 85#define S3C24XX_PA_IRQ S3C2410_PA_IRQ
86#define S3C24XX_PA_MEMCTRL S3C2410_PA_MEMCTRL 86#define S3C24XX_PA_MEMCTRL S3C2410_PA_MEMCTRL
87#define S3C24XX_PA_USBHOST S3C2410_PA_USBHOST
88#define S3C24XX_PA_DMA S3C2410_PA_DMA 87#define S3C24XX_PA_DMA S3C2410_PA_DMA
89#define S3C24XX_PA_CLKPWR S3C2410_PA_CLKPWR 88#define S3C24XX_PA_CLKPWR S3C2410_PA_CLKPWR
90#define S3C24XX_PA_LCD S3C2410_PA_LCD 89#define S3C24XX_PA_LCD S3C2410_PA_LCD
@@ -102,6 +101,7 @@
102 101
103#define S3C_PA_IIC S3C2410_PA_IIC 102#define S3C_PA_IIC S3C2410_PA_IIC
104#define S3C_PA_UART S3C24XX_PA_UART 103#define S3C_PA_UART S3C24XX_PA_UART
104#define S3C_PA_USBHOST S3C2410_PA_USBHOST
105#define S3C_PA_HSMMC0 S3C2443_PA_HSMMC 105#define S3C_PA_HSMMC0 S3C2443_PA_HSMMC
106 106
107#endif /* __ASM_ARCH_MAP_H */ 107#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s3c2410/include/mach/system-reset.h b/arch/arm/mach-s3c2410/include/mach/system-reset.h
index b8687f71c304..6faadcee7729 100644
--- a/arch/arm/mach-s3c2410/include/mach/system-reset.h
+++ b/arch/arm/mach-s3c2410/include/mach/system-reset.h
@@ -11,21 +11,13 @@
11*/ 11*/
12 12
13#include <mach/hardware.h> 13#include <mach/hardware.h>
14#include <linux/io.h> 14#include <plat/watchdog-reset.h>
15
16#include <plat/regs-watchdog.h>
17#include <mach/regs-clock.h>
18
19#include <linux/clk.h>
20#include <linux/err.h>
21 15
22extern void (*s3c24xx_reset_hook)(void); 16extern void (*s3c24xx_reset_hook)(void);
23 17
24static void 18static void
25arch_reset(char mode, const char *cmd) 19arch_reset(char mode, const char *cmd)
26{ 20{
27 struct clk *wdtclk;
28
29 if (mode == 's') { 21 if (mode == 's') {
30 cpu_reset(0); 22 cpu_reset(0);
31 } 23 }
@@ -33,31 +25,7 @@ arch_reset(char mode, const char *cmd)
33 if (s3c24xx_reset_hook) 25 if (s3c24xx_reset_hook)
34 s3c24xx_reset_hook(); 26 s3c24xx_reset_hook();
35 27
36 printk("arch_reset: attempting watchdog reset\n"); 28 arch_wdt_reset();
37
38 __raw_writel(0, S3C2410_WTCON); /* disable watchdog, to be safe */
39
40 wdtclk = clk_get(NULL, "watchdog");
41 if (!IS_ERR(wdtclk)) {
42 clk_enable(wdtclk);
43 } else
44 printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__);
45
46 /* put initial values into count and data */
47 __raw_writel(0x80, S3C2410_WTCNT);
48 __raw_writel(0x80, S3C2410_WTDAT);
49
50 /* set the watchdog to go and reset... */
51 __raw_writel(S3C2410_WTCON_ENABLE|S3C2410_WTCON_DIV16|S3C2410_WTCON_RSTEN |
52 S3C2410_WTCON_PRESCALE(0x20), S3C2410_WTCON);
53
54 /* wait for reset to assert... */
55 mdelay(500);
56
57 printk(KERN_ERR "Watchdog reset failed to assert reset\n");
58
59 /* delay to allow the serial port to show the message */
60 mdelay(50);
61 29
62 /* we'll take a jump through zero as a poor second */ 30 /* we'll take a jump through zero as a poor second */
63 cpu_reset(0); 31 cpu_reset(0);
diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig
index ca99564ae4b5..63586ffd0ae7 100644
--- a/arch/arm/mach-s3c2412/Kconfig
+++ b/arch/arm/mach-s3c2412/Kconfig
@@ -38,6 +38,7 @@ menu "S3C2412 Machines"
38config MACH_JIVE 38config MACH_JIVE
39 bool "Logitech Jive" 39 bool "Logitech Jive"
40 select CPU_S3C2412 40 select CPU_S3C2412
41 select S3C_DEV_USB_HOST
41 help 42 help
42 Say Y here if you are using the Logitech Jive. 43 Say Y here if you are using the Logitech Jive.
43 44
@@ -50,6 +51,7 @@ config MACH_SMDK2413
50 select CPU_S3C2412 51 select CPU_S3C2412
51 select MACH_S3C2413 52 select MACH_S3C2413
52 select MACH_SMDK 53 select MACH_SMDK
54 select S3C_DEV_USB_HOST
53 help 55 help
54 Say Y here if you are using an SMDK2413 56 Say Y here if you are using an SMDK2413
55 57
@@ -72,6 +74,7 @@ config MACH_SMDK2412
72config MACH_VSTMS 74config MACH_VSTMS
73 bool "VMSTMS" 75 bool "VMSTMS"
74 select CPU_S3C2412 76 select CPU_S3C2412
77 select S3C_DEV_USB_HOST
75 help 78 help
76 Say Y here if you are using an VSTMS board 79 Say Y here if you are using an VSTMS board
77 80
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
index cde5ae9a4340..5df73cbf2b40 100644
--- a/arch/arm/mach-s3c2440/Kconfig
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -33,6 +33,7 @@ config MACH_ANUBIS
33 select PM_SIMTEC if PM 33 select PM_SIMTEC if PM
34 select HAVE_PATA_PLATFORM 34 select HAVE_PATA_PLATFORM
35 select S3C24XX_GPIO_EXTRA64 35 select S3C24XX_GPIO_EXTRA64
36 select S3C_DEV_USB_HOST
36 help 37 help
37 Say Y here if you are using the Simtec Electronics ANUBIS 38 Say Y here if you are using the Simtec Electronics ANUBIS
38 development system 39 development system
@@ -43,6 +44,7 @@ config MACH_OSIRIS
43 select S3C24XX_DCLK 44 select S3C24XX_DCLK
44 select PM_SIMTEC if PM 45 select PM_SIMTEC if PM
45 select S3C24XX_GPIO_EXTRA128 46 select S3C24XX_GPIO_EXTRA128
47 select S3C_DEV_USB_HOST
46 help 48 help
47 Say Y here if you are using the Simtec IM2440D20 module, also 49 Say Y here if you are using the Simtec IM2440D20 module, also
48 known as the Osiris. 50 known as the Osiris.
@@ -58,12 +60,14 @@ config ARCH_S3C2440
58 bool "SMDK2440" 60 bool "SMDK2440"
59 select CPU_S3C2440 61 select CPU_S3C2440
60 select MACH_SMDK 62 select MACH_SMDK
63 select S3C_DEV_USB_HOST
61 help 64 help
62 Say Y here if you are using the SMDK2440. 65 Say Y here if you are using the SMDK2440.
63 66
64config MACH_NEXCODER_2440 67config MACH_NEXCODER_2440
65 bool "NexVision NEXCODER 2440 Light Board" 68 bool "NexVision NEXCODER 2440 Light Board"
66 select CPU_S3C2440 69 select CPU_S3C2440
70 select S3C_DEV_USB_HOST
67 help 71 help
68 Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board 72 Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
69 73
@@ -76,6 +80,7 @@ config SMDK2440_CPU2440
76config MACH_AT2440EVB 80config MACH_AT2440EVB
77 bool "Avantech AT2440EVB development board" 81 bool "Avantech AT2440EVB development board"
78 select CPU_S3C2440 82 select CPU_S3C2440
83 select S3C_DEV_USB_HOST
79 help 84 help
80 Say Y here if you are using the AT2440EVB development board 85 Say Y here if you are using the AT2440EVB development board
81 86
diff --git a/arch/arm/mach-s3c6400/Kconfig b/arch/arm/mach-s3c6400/Kconfig
index 6da82b5c09ba..f5af212066c3 100644
--- a/arch/arm/mach-s3c6400/Kconfig
+++ b/arch/arm/mach-s3c6400/Kconfig
@@ -5,4 +5,27 @@
5# 5#
6# Licensed under GPLv2 6# Licensed under GPLv2
7 7
8# Currently nothing here, this will be added later 8# Configuration options for the S3C6410 CPU
9
10config CPU_S3C6400
11 bool
12 select CPU_S3C6400_INIT
13 select CPU_S3C6400_CLOCK
14 help
15 Enable S3C6400 CPU support
16
17config S3C6400_SETUP_SDHCI
18 bool
19 help
20 Internal configuration for default SDHCI
21 setup for S3C6400.
22
23# S36400 Macchine support
24
25config MACH_SMDK6400
26 bool "SMDK6400"
27 select CPU_S3C6400
28 select S3C_DEV_HSMMC
29 select S3C6400_SETUP_SDHCI
30 help
31 Machine support for the Samsung SMDK6400
diff --git a/arch/arm/mach-s3c6400/Makefile b/arch/arm/mach-s3c6400/Makefile
index 8f397db25b87..df1ce4aa03e5 100644
--- a/arch/arm/mach-s3c6400/Makefile
+++ b/arch/arm/mach-s3c6400/Makefile
@@ -12,4 +12,12 @@ obj- :=
12 12
13# Core support for S3C6400 system 13# Core support for S3C6400 system
14 14
15obj-n += blank.o 15obj-$(CONFIG_CPU_S3C6400) += s3c6400.o
16
17# setup support
18
19obj-$(CONFIG_S3C6400_SETUP_SDHCI) += setup-sdhci.o
20
21# Machine support
22
23obj-$(CONFIG_MACH_SMDK6400) += mach-smdk6400.o
diff --git a/arch/arm/mach-s3c6400/include/mach/map.h b/arch/arm/mach-s3c6400/include/mach/map.h
index baf1c0f1ea5a..7a1e5a2455b3 100644
--- a/arch/arm/mach-s3c6400/include/mach/map.h
+++ b/arch/arm/mach-s3c6400/include/mach/map.h
@@ -39,6 +39,8 @@
39#define S3C_VA_UART3 S3C_VA_UARTx(3) 39#define S3C_VA_UART3 S3C_VA_UARTx(3)
40 40
41#define S3C64XX_PA_FB (0x77100000) 41#define S3C64XX_PA_FB (0x77100000)
42#define S3C64XX_PA_USB_HSOTG (0x7C000000)
43#define S3C64XX_PA_WATCHDOG (0x7E004000)
42#define S3C64XX_PA_SYSCON (0x7E00F000) 44#define S3C64XX_PA_SYSCON (0x7E00F000)
43#define S3C64XX_PA_TIMER (0x7F006000) 45#define S3C64XX_PA_TIMER (0x7F006000)
44#define S3C64XX_PA_IIC0 (0x7F004000) 46#define S3C64XX_PA_IIC0 (0x7F004000)
@@ -55,6 +57,8 @@
55#define S3C64XX_PA_MODEM (0x74108000) 57#define S3C64XX_PA_MODEM (0x74108000)
56#define S3C64XX_VA_MODEM S3C_ADDR(0x00600000) 58#define S3C64XX_VA_MODEM S3C_ADDR(0x00600000)
57 59
60#define S3C64XX_PA_USBHOST (0x74300000)
61
58/* place VICs close together */ 62/* place VICs close together */
59#define S3C_VA_VIC0 (S3C_VA_IRQ + 0x00) 63#define S3C_VA_VIC0 (S3C_VA_IRQ + 0x00)
60#define S3C_VA_VIC1 (S3C_VA_IRQ + 0x10000) 64#define S3C_VA_VIC1 (S3C_VA_IRQ + 0x10000)
@@ -67,5 +71,7 @@
67#define S3C_PA_IIC S3C64XX_PA_IIC0 71#define S3C_PA_IIC S3C64XX_PA_IIC0
68#define S3C_PA_IIC1 S3C64XX_PA_IIC1 72#define S3C_PA_IIC1 S3C64XX_PA_IIC1
69#define S3C_PA_FB S3C64XX_PA_FB 73#define S3C_PA_FB S3C64XX_PA_FB
74#define S3C_PA_USBHOST S3C64XX_PA_USBHOST
75#define S3C_PA_USB_HSOTG S3C64XX_PA_USB_HSOTG
70 76
71#endif /* __ASM_ARCH_6400_MAP_H */ 77#endif /* __ASM_ARCH_6400_MAP_H */
diff --git a/arch/arm/mach-s3c6400/include/mach/regs-clock.h b/arch/arm/mach-s3c6400/include/mach/regs-clock.h
new file mode 100644
index 000000000000..a6c7f4eb3a1b
--- /dev/null
+++ b/arch/arm/mach-s3c6400/include/mach/regs-clock.h
@@ -0,0 +1,16 @@
1/* linux/arch/arm/mach-s3c6400/include/mach/regs-clock.h
2 *
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * http://armlinux.simtec.co.uk/
6 * Ben Dooks <ben@simtec.co.uk>
7 *
8 * S3C64XX - clock register compatibility with s3c24xx
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <plat/regs-clock.h>
16
diff --git a/arch/arm/mach-s3c6400/include/mach/system.h b/arch/arm/mach-s3c6400/include/mach/system.h
index 090cfd969bc7..2e58cb7a7147 100644
--- a/arch/arm/mach-s3c6400/include/mach/system.h
+++ b/arch/arm/mach-s3c6400/include/mach/system.h
@@ -11,6 +11,8 @@
11#ifndef __ASM_ARCH_SYSTEM_H 11#ifndef __ASM_ARCH_SYSTEM_H
12#define __ASM_ARCH_SYSTEM_H __FILE__ 12#define __ASM_ARCH_SYSTEM_H __FILE__
13 13
14#include <plat/watchdog-reset.h>
15
14static void arch_idle(void) 16static void arch_idle(void)
15{ 17{
16 /* nothing here yet */ 18 /* nothing here yet */
@@ -18,7 +20,11 @@ static void arch_idle(void)
18 20
19static void arch_reset(char mode, const char *cmd) 21static void arch_reset(char mode, const char *cmd)
20{ 22{
21 /* nothing here yet */ 23 if (mode != 's')
24 arch_wdt_reset();
25
26 /* if all else fails, or mode was for soft, jump to 0 */
27 cpu_reset(0);
22} 28}
23 29
24#endif /* __ASM_ARCH_IRQ_H */ 30#endif /* __ASM_ARCH_IRQ_H */
diff --git a/arch/arm/mach-s3c6400/mach-smdk6400.c b/arch/arm/mach-s3c6400/mach-smdk6400.c
new file mode 100644
index 000000000000..ab19285389a7
--- /dev/null
+++ b/arch/arm/mach-s3c6400/mach-smdk6400.c
@@ -0,0 +1,96 @@
1/* linux/arch/arm/mach-s3c6400/mach-smdk6400.c
2 *
3 * Copyright 2008 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 * http://armlinux.simtec.co.uk/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10*/
11
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/interrupt.h>
15#include <linux/list.h>
16#include <linux/timer.h>
17#include <linux/init.h>
18#include <linux/serial_core.h>
19#include <linux/platform_device.h>
20#include <linux/i2c.h>
21#include <linux/io.h>
22
23#include <asm/mach-types.h>
24
25#include <asm/mach/arch.h>
26#include <asm/mach/map.h>
27#include <asm/mach/irq.h>
28
29#include <mach/hardware.h>
30#include <mach/map.h>
31
32#include <plat/regs-serial.h>
33
34#include <plat/s3c6400.h>
35#include <plat/clock.h>
36#include <plat/devs.h>
37#include <plat/cpu.h>
38#include <plat/iic.h>
39
40#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
41#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
42#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
43
44static struct s3c2410_uartcfg smdk6400_uartcfgs[] __initdata = {
45 [0] = {
46 .hwport = 0,
47 .flags = 0,
48 .ucon = 0x3c5,
49 .ulcon = 0x03,
50 .ufcon = 0x51,
51 },
52 [1] = {
53 .hwport = 1,
54 .flags = 0,
55 .ucon = 0x3c5,
56 .ulcon = 0x03,
57 .ufcon = 0x51,
58 },
59};
60
61static struct map_desc smdk6400_iodesc[] = {};
62
63static void __init smdk6400_map_io(void)
64{
65 s3c64xx_init_io(smdk6400_iodesc, ARRAY_SIZE(smdk6400_iodesc));
66 s3c24xx_init_clocks(12000000);
67 s3c24xx_init_uarts(smdk6400_uartcfgs, ARRAY_SIZE(smdk6400_uartcfgs));
68}
69
70static struct platform_device *smdk6400_devices[] __initdata = {
71 &s3c_device_hsmmc1,
72 &s3c_device_i2c0,
73};
74
75static struct i2c_board_info i2c_devs[] __initdata = {
76 { I2C_BOARD_INFO("wm8753", 0x1A), },
77 { I2C_BOARD_INFO("24c08", 0x50), },
78};
79
80static void __init smdk6400_machine_init(void)
81{
82 i2c_register_board_info(0, i2c_devs, ARRAY_SIZE(i2c_devs));
83 platform_add_devices(smdk6400_devices, ARRAY_SIZE(smdk6400_devices));
84}
85
86MACHINE_START(SMDK6400, "SMDK6400")
87 /* Maintainer: Ben Dooks <ben@fluff.org> */
88 .phys_io = S3C_PA_UART & 0xfff00000,
89 .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
90 .boot_params = S3C64XX_PA_SDRAM + 0x100,
91
92 .init_irq = s3c6400_init_irq,
93 .map_io = smdk6400_map_io,
94 .init_machine = smdk6400_machine_init,
95 .timer = &s3c24xx_timer,
96MACHINE_END
diff --git a/arch/arm/mach-s3c6400/s3c6400.c b/arch/arm/mach-s3c6400/s3c6400.c
new file mode 100644
index 000000000000..1ece887d90bb
--- /dev/null
+++ b/arch/arm/mach-s3c6400/s3c6400.c
@@ -0,0 +1,89 @@
1/* linux/arch/arm/mach-s3c6410/cpu.c
2 *
3 * Copyright 2009 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 * http://armlinux.simtec.co.uk/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10*/
11
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/interrupt.h>
15#include <linux/list.h>
16#include <linux/timer.h>
17#include <linux/init.h>
18#include <linux/clk.h>
19#include <linux/io.h>
20#include <linux/sysdev.h>
21#include <linux/serial_core.h>
22#include <linux/platform_device.h>
23
24#include <asm/mach/arch.h>
25#include <asm/mach/map.h>
26#include <asm/mach/irq.h>
27
28#include <mach/hardware.h>
29#include <asm/irq.h>
30
31#include <plat/cpu-freq.h>
32#include <plat/regs-serial.h>
33#include <plat/regs-clock.h>
34
35#include <plat/cpu.h>
36#include <plat/devs.h>
37#include <plat/clock.h>
38#include <plat/sdhci.h>
39#include <plat/iic-core.h>
40#include <plat/s3c6400.h>
41
42void __init s3c6400_map_io(void)
43{
44 /* setup SDHCI */
45
46 s3c6400_default_sdhci0();
47 s3c6400_default_sdhci1();
48
49 /* the i2c devices are directly compatible with s3c2440 */
50 s3c_i2c0_setname("s3c2440-i2c");
51}
52
53void __init s3c6400_init_clocks(int xtal)
54{
55 printk(KERN_DEBUG "%s: initialising clocks\n", __func__);
56 s3c24xx_register_baseclocks(xtal);
57 s3c64xx_register_clocks();
58 s3c6400_register_clocks(S3C6400_CLKDIV0_ARM_MASK);
59 s3c6400_setup_clocks();
60}
61
62void __init s3c6400_init_irq(void)
63{
64 /* VIC0 does not have IRQS 5..7,
65 * VIC1 is fully populated. */
66 s3c64xx_init_irq(~0 & ~(0xf << 5), ~0);
67}
68
69struct sysdev_class s3c6400_sysclass = {
70 .name = "s3c6400-core",
71};
72
73static struct sys_device s3c6400_sysdev = {
74 .cls = &s3c6400_sysclass,
75};
76
77static int __init s3c6400_core_init(void)
78{
79 return sysdev_class_register(&s3c6400_sysclass);
80}
81
82core_initcall(s3c6400_core_init);
83
84int __init s3c6400_init(void)
85{
86 printk("S3C6400: Initialising architecture\n");
87
88 return sysdev_register(&s3c6400_sysdev);
89}
diff --git a/arch/arm/mach-s3c6400/setup-sdhci.c b/arch/arm/mach-s3c6400/setup-sdhci.c
new file mode 100644
index 000000000000..b93dafbee1f4
--- /dev/null
+++ b/arch/arm/mach-s3c6400/setup-sdhci.c
@@ -0,0 +1,63 @@
1/* linux/arch/arm/mach-s3c6410/setup-sdhci.c
2 *
3 * Copyright 2008 Simtec Electronics
4 * Copyright 2008 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
7 *
8 * S3C6410 - Helper functions for settign up SDHCI device(s) (HSMMC)
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/kernel.h>
16#include <linux/types.h>
17#include <linux/interrupt.h>
18#include <linux/platform_device.h>
19#include <linux/io.h>
20
21#include <linux/mmc/card.h>
22#include <linux/mmc/host.h>
23
24#include <plat/regs-sdhci.h>
25#include <plat/sdhci.h>
26
27/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
28
29char *s3c6400_hsmmc_clksrcs[4] = {
30 [0] = "hsmmc",
31 [1] = "hsmmc",
32 [2] = "mmc_bus",
33 /* [3] = "48m", - note not succesfully used yet */
34};
35
36void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev,
37 void __iomem *r,
38 struct mmc_ios *ios,
39 struct mmc_card *card)
40{
41 u32 ctrl2, ctrl3;
42
43 ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
44 ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
45 ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
46 S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
47 S3C_SDHCI_CTRL2_ENFBCLKRX |
48 S3C_SDHCI_CTRL2_DFCNT_NONE |
49 S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
50
51 if (ios->clock < 25 * 1000000)
52 ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
53 S3C_SDHCI_CTRL3_FCSEL2 |
54 S3C_SDHCI_CTRL3_FCSEL1 |
55 S3C_SDHCI_CTRL3_FCSEL0);
56 else
57 ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
58
59 printk(KERN_INFO "%s: CTRL 2=%08x, 3=%08x\n", __func__, ctrl2, ctrl3);
60 writel(ctrl2, r + S3C_SDHCI_CONTROL2);
61 writel(ctrl3, r + S3C_SDHCI_CONTROL3);
62}
63
diff --git a/arch/arm/mach-s3c6410/Kconfig b/arch/arm/mach-s3c6410/Kconfig
index 1d5010070027..e63aac7f4e5a 100644
--- a/arch/arm/mach-s3c6410/Kconfig
+++ b/arch/arm/mach-s3c6410/Kconfig
@@ -16,9 +16,18 @@ config CPU_S3C6410
16 16
17config S3C6410_SETUP_SDHCI 17config S3C6410_SETUP_SDHCI
18 bool 18 bool
19 select S3C64XX_SETUP_SDHCI_GPIO
19 help 20 help
20 Internal helper functions for S3C6410 based SDHCI systems 21 Internal helper functions for S3C6410 based SDHCI systems
21 22
23config MACH_ANW6410
24 bool "A&W6410"
25 select CPU_S3C6410
26 select S3C_DEV_FB
27 select S3C64XX_SETUP_FB_24BPP
28 help
29 Machine support for the A&W6410
30
22config MACH_SMDK6410 31config MACH_SMDK6410
23 bool "SMDK6410" 32 bool "SMDK6410"
24 select CPU_S3C6410 33 select CPU_S3C6410
@@ -26,6 +35,8 @@ config MACH_SMDK6410
26 select S3C_DEV_HSMMC1 35 select S3C_DEV_HSMMC1
27 select S3C_DEV_I2C1 36 select S3C_DEV_I2C1
28 select S3C_DEV_FB 37 select S3C_DEV_FB
38 select S3C_DEV_USB_HOST
39 select S3C_DEV_USB_HSOTG
29 select S3C6410_SETUP_SDHCI 40 select S3C6410_SETUP_SDHCI
30 select S3C64XX_SETUP_I2C1 41 select S3C64XX_SETUP_I2C1
31 select S3C64XX_SETUP_FB_24BPP 42 select S3C64XX_SETUP_FB_24BPP
@@ -60,3 +71,29 @@ config SMDK6410_SD_CH1
60 channels 0 and 1 are the same. 71 channels 0 and 1 are the same.
61 72
62endchoice 73endchoice
74
75config SMDK6410_WM1190_EV1
76 bool "Support Wolfson Microelectronics 1190-EV1 PMIC card"
77 depends on MACH_SMDK6410
78 select REGULATOR
79 select REGULATOR_WM8350
80 select MFD_WM8350_I2C
81 select MFD_WM8350_CONFIG_MODE_0
82 select MFD_WM8350_CONFIG_MODE_3
83 select MFD_WM8352_CONFIG_MODE_0
84 help
85 The Wolfson Microelectronics 1190-EV1 is a WM835x based PMIC
86 and audio daughtercard for the Samsung SMDK6410 reference
87 platform. Enabling this option will build support for this
88 module into the kernel. The presence of the module will be
89 detected at runtime so the the resulting kernel can be used
90 with or without the 1190-EV1 fitted.
91
92config MACH_NCP
93 bool "NCP"
94 select CPU_S3C6410
95 select S3C_DEV_I2C1
96 select S3C_DEV_HSMMC1
97 select S3C64XX_SETUP_I2C1
98 help
99 Machine support for the Samsung NCP
diff --git a/arch/arm/mach-s3c6410/Makefile b/arch/arm/mach-s3c6410/Makefile
index 2cd4f189036b..6f9deac88612 100644
--- a/arch/arm/mach-s3c6410/Makefile
+++ b/arch/arm/mach-s3c6410/Makefile
@@ -20,4 +20,8 @@ obj-$(CONFIG_S3C6410_SETUP_SDHCI) += setup-sdhci.o
20 20
21# machine support 21# machine support
22 22
23obj-$(CONFIG_MACH_ANW6410) += mach-anw6410.o
23obj-$(CONFIG_MACH_SMDK6410) += mach-smdk6410.o 24obj-$(CONFIG_MACH_SMDK6410) += mach-smdk6410.o
25obj-$(CONFIG_MACH_NCP) += mach-ncp.o
26
27
diff --git a/arch/arm/mach-s3c6410/cpu.c b/arch/arm/mach-s3c6410/cpu.c
index 6a73ca6b7a3a..ade904de8895 100644
--- a/arch/arm/mach-s3c6410/cpu.c
+++ b/arch/arm/mach-s3c6410/cpu.c
@@ -31,6 +31,7 @@
31 31
32#include <plat/cpu-freq.h> 32#include <plat/cpu-freq.h>
33#include <plat/regs-serial.h> 33#include <plat/regs-serial.h>
34#include <plat/regs-clock.h>
34 35
35#include <plat/cpu.h> 36#include <plat/cpu.h>
36#include <plat/devs.h> 37#include <plat/devs.h>
@@ -68,7 +69,7 @@ void __init s3c6410_init_clocks(int xtal)
68 printk(KERN_DEBUG "%s: initialising clocks\n", __func__); 69 printk(KERN_DEBUG "%s: initialising clocks\n", __func__);
69 s3c24xx_register_baseclocks(xtal); 70 s3c24xx_register_baseclocks(xtal);
70 s3c64xx_register_clocks(); 71 s3c64xx_register_clocks();
71 s3c6400_register_clocks(); 72 s3c6400_register_clocks(S3C6410_CLKDIV0_ARM_MASK);
72 s3c6400_setup_clocks(); 73 s3c6400_setup_clocks();
73} 74}
74 75
diff --git a/arch/arm/mach-s3c6410/mach-anw6410.c b/arch/arm/mach-s3c6410/mach-anw6410.c
new file mode 100644
index 000000000000..661cca63de25
--- /dev/null
+++ b/arch/arm/mach-s3c6410/mach-anw6410.c
@@ -0,0 +1,245 @@
1/* linux/arch/arm/mach-s3c6410/mach-anw6410.c
2 *
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
7 * Copyright 2009 Kwangwoo Lee
8 * Kwangwoo Lee <kwangwoo.lee@gmail.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14*/
15
16#include <linux/kernel.h>
17#include <linux/types.h>
18#include <linux/interrupt.h>
19#include <linux/list.h>
20#include <linux/timer.h>
21#include <linux/init.h>
22#include <linux/serial_core.h>
23#include <linux/platform_device.h>
24#include <linux/io.h>
25#include <linux/i2c.h>
26#include <linux/fb.h>
27#include <linux/gpio.h>
28#include <linux/delay.h>
29#include <linux/dm9000.h>
30
31#include <video/platform_lcd.h>
32
33#include <asm/mach/arch.h>
34#include <asm/mach/map.h>
35#include <asm/mach/irq.h>
36
37#include <mach/hardware.h>
38#include <mach/regs-fb.h>
39#include <mach/map.h>
40
41#include <asm/irq.h>
42#include <asm/mach-types.h>
43
44#include <plat/regs-serial.h>
45#include <plat/iic.h>
46#include <plat/fb.h>
47
48#include <plat/s3c6410.h>
49#include <plat/clock.h>
50#include <plat/devs.h>
51#include <plat/cpu.h>
52#include <plat/regs-gpio.h>
53#include <plat/regs-modem.h>
54
55/* DM9000 */
56#define ANW6410_PA_DM9000 (0x18000000)
57
58/* A hardware buffer to control external devices is mapped at 0x30000000.
59 * It can not be read. So current status must be kept in anw6410_extdev_status.
60 */
61#define ANW6410_VA_EXTDEV S3C_ADDR(0x02000000)
62#define ANW6410_PA_EXTDEV (0x30000000)
63
64#define ANW6410_EN_DM9000 (1<<11)
65#define ANW6410_EN_LCD (1<<14)
66
67static __u32 anw6410_extdev_status;
68
69static struct s3c2410_uartcfg anw6410_uartcfgs[] __initdata = {
70 [0] = {
71 .hwport = 0,
72 .flags = 0,
73 .ucon = 0x3c5,
74 .ulcon = 0x03,
75 .ufcon = 0x51,
76 },
77 [1] = {
78 .hwport = 1,
79 .flags = 0,
80 .ucon = 0x3c5,
81 .ulcon = 0x03,
82 .ufcon = 0x51,
83 },
84};
85
86/* framebuffer and LCD setup. */
87static void __init anw6410_lcd_mode_set(void)
88{
89 u32 tmp;
90
91 /* set the LCD type */
92 tmp = __raw_readl(S3C64XX_SPCON);
93 tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
94 tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
95 __raw_writel(tmp, S3C64XX_SPCON);
96
97 /* remove the LCD bypass */
98 tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
99 tmp &= ~MIFPCON_LCD_BYPASS;
100 __raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
101}
102
103/* GPF1 = LCD panel power
104 * GPF4 = LCD backlight control
105 */
106static void anw6410_lcd_power_set(struct plat_lcd_data *pd,
107 unsigned int power)
108{
109 if (power) {
110 anw6410_extdev_status |= (ANW6410_EN_LCD << 16);
111 __raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);
112
113 gpio_direction_output(S3C64XX_GPF(1), 1);
114 gpio_direction_output(S3C64XX_GPF(4), 1);
115 } else {
116 anw6410_extdev_status &= ~(ANW6410_EN_LCD << 16);
117 __raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);
118
119 gpio_direction_output(S3C64XX_GPF(1), 0);
120 gpio_direction_output(S3C64XX_GPF(4), 0);
121 }
122}
123
124static struct plat_lcd_data anw6410_lcd_power_data = {
125 .set_power = anw6410_lcd_power_set,
126};
127
128static struct platform_device anw6410_lcd_powerdev = {
129 .name = "platform-lcd",
130 .dev.parent = &s3c_device_fb.dev,
131 .dev.platform_data = &anw6410_lcd_power_data,
132};
133
134static struct s3c_fb_pd_win anw6410_fb_win0 = {
135 /* this is to ensure we use win0 */
136 .win_mode = {
137 .pixclock = 41094,
138 .left_margin = 8,
139 .right_margin = 13,
140 .upper_margin = 7,
141 .lower_margin = 5,
142 .hsync_len = 3,
143 .vsync_len = 1,
144 .xres = 800,
145 .yres = 480,
146 },
147 .max_bpp = 32,
148 .default_bpp = 16,
149};
150
151/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
152static struct s3c_fb_platdata anw6410_lcd_pdata __initdata = {
153 .setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
154 .win[0] = &anw6410_fb_win0,
155 .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
156 .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
157};
158
159/* DM9000AEP 10/100 ethernet controller */
160static void __init anw6410_dm9000_enable(void)
161{
162 anw6410_extdev_status |= (ANW6410_EN_DM9000 << 16);
163 __raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);
164}
165
166static struct resource anw6410_dm9000_resource[] = {
167 [0] = {
168 .start = ANW6410_PA_DM9000,
169 .end = ANW6410_PA_DM9000 + 3,
170 .flags = IORESOURCE_MEM,
171 },
172 [1] = {
173 .start = ANW6410_PA_DM9000 + 4,
174 .end = ANW6410_PA_DM9000 + 4 + 500,
175 .flags = IORESOURCE_MEM,
176 },
177 [2] = {
178 .start = IRQ_EINT(15),
179 .end = IRQ_EINT(15),
180 .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
181 },
182};
183
184static struct dm9000_plat_data anw6410_dm9000_pdata = {
185 .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
186 /* dev_addr can be set to provide hwaddr. */
187};
188
189static struct platform_device anw6410_device_eth = {
190 .name = "dm9000",
191 .id = -1,
192 .num_resources = ARRAY_SIZE(anw6410_dm9000_resource),
193 .resource = anw6410_dm9000_resource,
194 .dev = {
195 .platform_data = &anw6410_dm9000_pdata,
196 },
197};
198
199static struct map_desc anw6410_iodesc[] __initdata = {
200 {
201 .virtual = (unsigned long)ANW6410_VA_EXTDEV,
202 .pfn = __phys_to_pfn(ANW6410_PA_EXTDEV),
203 .length = SZ_64K,
204 .type = MT_DEVICE,
205 },
206};
207
208static struct platform_device *anw6410_devices[] __initdata = {
209 &s3c_device_fb,
210 &anw6410_lcd_powerdev,
211 &anw6410_device_eth,
212};
213
214static void __init anw6410_map_io(void)
215{
216 s3c64xx_init_io(anw6410_iodesc, ARRAY_SIZE(anw6410_iodesc));
217 s3c24xx_init_clocks(12000000);
218 s3c24xx_init_uarts(anw6410_uartcfgs, ARRAY_SIZE(anw6410_uartcfgs));
219
220 anw6410_lcd_mode_set();
221}
222
223static void __init anw6410_machine_init(void)
224{
225 s3c_fb_set_platdata(&anw6410_lcd_pdata);
226
227 gpio_request(S3C64XX_GPF(1), "panel power");
228 gpio_request(S3C64XX_GPF(4), "LCD backlight");
229
230 anw6410_dm9000_enable();
231
232 platform_add_devices(anw6410_devices, ARRAY_SIZE(anw6410_devices));
233}
234
235MACHINE_START(ANW6410, "A&W6410")
236 /* Maintainer: Kwangwoo Lee <kwangwoo.lee@gmail.com> */
237 .phys_io = S3C_PA_UART & 0xfff00000,
238 .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
239 .boot_params = S3C64XX_PA_SDRAM + 0x100,
240
241 .init_irq = s3c6410_init_irq,
242 .map_io = anw6410_map_io,
243 .init_machine = anw6410_machine_init,
244 .timer = &s3c24xx_timer,
245MACHINE_END
diff --git a/arch/arm/mach-s3c6410/mach-ncp.c b/arch/arm/mach-s3c6410/mach-ncp.c
new file mode 100644
index 000000000000..6030636f8548
--- /dev/null
+++ b/arch/arm/mach-s3c6410/mach-ncp.c
@@ -0,0 +1,107 @@
1/*
2 * linux/arch/arm/mach-s3c6410/mach-ncp.c
3 *
4 * Copyright (C) 2008-2009 Samsung Electronics
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 */
11
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/interrupt.h>
15#include <linux/list.h>
16#include <linux/timer.h>
17#include <linux/init.h>
18#include <linux/serial_core.h>
19#include <linux/platform_device.h>
20#include <linux/io.h>
21#include <linux/i2c.h>
22#include <linux/fb.h>
23#include <linux/gpio.h>
24#include <linux/delay.h>
25
26#include <video/platform_lcd.h>
27
28#include <asm/mach/arch.h>
29#include <asm/mach/map.h>
30#include <asm/mach/irq.h>
31
32#include <mach/hardware.h>
33#include <mach/regs-fb.h>
34#include <mach/map.h>
35
36#include <asm/irq.h>
37#include <asm/mach-types.h>
38
39#include <plat/regs-serial.h>
40#include <plat/iic.h>
41#include <plat/fb.h>
42
43#include <plat/s3c6410.h>
44#include <plat/clock.h>
45#include <plat/devs.h>
46#include <plat/cpu.h>
47
48#define UCON S3C2410_UCON_DEFAULT
49#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE
50#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
51
52static struct s3c2410_uartcfg ncp_uartcfgs[] __initdata = {
53 /* REVISIT: NCP uses only serial 1, 2 */
54 [0] = {
55 .hwport = 0,
56 .flags = 0,
57 .ucon = UCON,
58 .ulcon = ULCON,
59 .ufcon = UFCON,
60 },
61 [1] = {
62 .hwport = 1,
63 .flags = 0,
64 .ucon = UCON,
65 .ulcon = ULCON,
66 .ufcon = UFCON,
67 },
68 [2] = {
69 .hwport = 2,
70 .flags = 0,
71 .ucon = UCON,
72 .ulcon = ULCON,
73 .ufcon = UFCON,
74 },
75};
76
77static struct platform_device *ncp_devices[] __initdata = {
78 &s3c_device_hsmmc1,
79 &s3c_device_i2c0,
80};
81
82struct map_desc ncp_iodesc[] = {};
83
84static void __init ncp_map_io(void)
85{
86 s3c64xx_init_io(ncp_iodesc, ARRAY_SIZE(ncp_iodesc));
87 s3c24xx_init_clocks(12000000);
88 s3c24xx_init_uarts(ncp_uartcfgs, ARRAY_SIZE(ncp_uartcfgs));
89}
90
91static void __init ncp_machine_init(void)
92{
93 s3c_i2c0_set_platdata(NULL);
94
95 platform_add_devices(ncp_devices, ARRAY_SIZE(ncp_devices));
96}
97
98MACHINE_START(NCP, "NCP")
99 /* Maintainer: Samsung Electronics */
100 .phys_io = S3C_PA_UART & 0xfff00000,
101 .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
102 .boot_params = S3C64XX_PA_SDRAM + 0x100,
103 .init_irq = s3c6410_init_irq,
104 .map_io = ncp_map_io,
105 .init_machine = ncp_machine_init,
106 .timer = &s3c24xx_timer,
107MACHINE_END
diff --git a/arch/arm/mach-s3c6410/mach-smdk6410.c b/arch/arm/mach-s3c6410/mach-smdk6410.c
index 7f473e47e4f1..bc9a7dea567f 100644
--- a/arch/arm/mach-s3c6410/mach-smdk6410.c
+++ b/arch/arm/mach-s3c6410/mach-smdk6410.c
@@ -24,6 +24,12 @@
24#include <linux/fb.h> 24#include <linux/fb.h>
25#include <linux/gpio.h> 25#include <linux/gpio.h>
26#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/smsc911x.h>
28
29#ifdef CONFIG_SMDK6410_WM1190_EV1
30#include <linux/mfd/wm8350/core.h>
31#include <linux/mfd/wm8350/pmic.h>
32#endif
27 33
28#include <video/platform_lcd.h> 34#include <video/platform_lcd.h>
29 35
@@ -39,8 +45,12 @@
39#include <asm/mach-types.h> 45#include <asm/mach-types.h>
40 46
41#include <plat/regs-serial.h> 47#include <plat/regs-serial.h>
48#include <plat/regs-modem.h>
49#include <plat/regs-gpio.h>
50#include <plat/regs-sys.h>
42#include <plat/iic.h> 51#include <plat/iic.h>
43#include <plat/fb.h> 52#include <plat/fb.h>
53#include <plat/gpio-cfg.h>
44 54
45#include <plat/s3c6410.h> 55#include <plat/s3c6410.h>
46#include <plat/clock.h> 56#include <plat/clock.h>
@@ -129,6 +139,37 @@ static struct s3c_fb_platdata smdk6410_lcd_pdata __initdata = {
129 .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, 139 .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
130}; 140};
131 141
142static struct resource smdk6410_smsc911x_resources[] = {
143 [0] = {
144 .start = 0x18000000,
145 .end = 0x18000000 + SZ_64K - 1,
146 .flags = IORESOURCE_MEM,
147 },
148 [1] = {
149 .start = S3C_EINT(10),
150 .end = S3C_EINT(10),
151 .flags = IORESOURCE_IRQ | IRQ_TYPE_LEVEL_LOW,
152 },
153};
154
155static struct smsc911x_platform_config smdk6410_smsc911x_pdata = {
156 .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
157 .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
158 .flags = SMSC911X_USE_32BIT | SMSC911X_FORCE_INTERNAL_PHY,
159 .phy_interface = PHY_INTERFACE_MODE_MII,
160};
161
162
163static struct platform_device smdk6410_smsc911x = {
164 .name = "smsc911x",
165 .id = -1,
166 .num_resources = ARRAY_SIZE(smdk6410_smsc911x_resources),
167 .resource = &smdk6410_smsc911x_resources[0],
168 .dev = {
169 .platform_data = &smdk6410_smsc911x_pdata,
170 },
171};
172
132static struct map_desc smdk6410_iodesc[] = {}; 173static struct map_desc smdk6410_iodesc[] = {};
133 174
134static struct platform_device *smdk6410_devices[] __initdata = { 175static struct platform_device *smdk6410_devices[] __initdata = {
@@ -141,12 +182,155 @@ static struct platform_device *smdk6410_devices[] __initdata = {
141 &s3c_device_i2c0, 182 &s3c_device_i2c0,
142 &s3c_device_i2c1, 183 &s3c_device_i2c1,
143 &s3c_device_fb, 184 &s3c_device_fb,
185 &s3c_device_usb,
186 &s3c_device_usb_hsotg,
144 &smdk6410_lcd_powerdev, 187 &smdk6410_lcd_powerdev,
188
189 &smdk6410_smsc911x,
190};
191
192#ifdef CONFIG_SMDK6410_WM1190_EV1
193/* S3C64xx internal logic & PLL */
194static struct regulator_init_data wm8350_dcdc1_data = {
195 .constraints = {
196 .name = "PVDD_INT/PVDD_PLL",
197 .min_uV = 1200000,
198 .max_uV = 1200000,
199 .always_on = 1,
200 .apply_uV = 1,
201 },
202};
203
204/* Memory */
205static struct regulator_init_data wm8350_dcdc3_data = {
206 .constraints = {
207 .name = "PVDD_MEM",
208 .min_uV = 1800000,
209 .max_uV = 1800000,
210 .always_on = 1,
211 .state_mem = {
212 .uV = 1800000,
213 .mode = REGULATOR_MODE_NORMAL,
214 .enabled = 1,
215 },
216 .initial_state = PM_SUSPEND_MEM,
217 },
218};
219
220/* USB, EXT, PCM, ADC/DAC, USB, MMC */
221static struct regulator_init_data wm8350_dcdc4_data = {
222 .constraints = {
223 .name = "PVDD_HI/PVDD_EXT/PVDD_SYS/PVCCM2MTV",
224 .min_uV = 3000000,
225 .max_uV = 3000000,
226 .always_on = 1,
227 },
228};
229
230/* ARM core */
231static struct regulator_consumer_supply dcdc6_consumers[] = {
232 {
233 .supply = "vddarm",
234 }
235};
236
237static struct regulator_init_data wm8350_dcdc6_data = {
238 .constraints = {
239 .name = "PVDD_ARM",
240 .min_uV = 1000000,
241 .max_uV = 1300000,
242 .always_on = 1,
243 .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
244 },
245 .num_consumer_supplies = ARRAY_SIZE(dcdc6_consumers),
246 .consumer_supplies = dcdc6_consumers,
145}; 247};
146 248
249/* Alive */
250static struct regulator_init_data wm8350_ldo1_data = {
251 .constraints = {
252 .name = "PVDD_ALIVE",
253 .min_uV = 1200000,
254 .max_uV = 1200000,
255 .always_on = 1,
256 .apply_uV = 1,
257 },
258};
259
260/* OTG */
261static struct regulator_init_data wm8350_ldo2_data = {
262 .constraints = {
263 .name = "PVDD_OTG",
264 .min_uV = 3300000,
265 .max_uV = 3300000,
266 .always_on = 1,
267 },
268};
269
270/* LCD */
271static struct regulator_init_data wm8350_ldo3_data = {
272 .constraints = {
273 .name = "PVDD_LCD",
274 .min_uV = 3000000,
275 .max_uV = 3000000,
276 .always_on = 1,
277 },
278};
279
280/* OTGi/1190-EV1 HPVDD & AVDD */
281static struct regulator_init_data wm8350_ldo4_data = {
282 .constraints = {
283 .name = "PVDD_OTGI/HPVDD/AVDD",
284 .min_uV = 1200000,
285 .max_uV = 1200000,
286 .apply_uV = 1,
287 .always_on = 1,
288 },
289};
290
291static struct {
292 int regulator;
293 struct regulator_init_data *initdata;
294} wm1190_regulators[] = {
295 { WM8350_DCDC_1, &wm8350_dcdc1_data },
296 { WM8350_DCDC_3, &wm8350_dcdc3_data },
297 { WM8350_DCDC_4, &wm8350_dcdc4_data },
298 { WM8350_DCDC_6, &wm8350_dcdc6_data },
299 { WM8350_LDO_1, &wm8350_ldo1_data },
300 { WM8350_LDO_2, &wm8350_ldo2_data },
301 { WM8350_LDO_3, &wm8350_ldo3_data },
302 { WM8350_LDO_4, &wm8350_ldo4_data },
303};
304
305static int __init smdk6410_wm8350_init(struct wm8350 *wm8350)
306{
307 int i;
308
309 /* Instantiate the regulators */
310 for (i = 0; i < ARRAY_SIZE(wm1190_regulators); i++)
311 wm8350_register_regulator(wm8350,
312 wm1190_regulators[i].regulator,
313 wm1190_regulators[i].initdata);
314
315 return 0;
316}
317
318static struct wm8350_platform_data __initdata smdk6410_wm8350_pdata = {
319 .init = smdk6410_wm8350_init,
320 .irq_high = 1,
321};
322#endif
323
147static struct i2c_board_info i2c_devs0[] __initdata = { 324static struct i2c_board_info i2c_devs0[] __initdata = {
148 { I2C_BOARD_INFO("24c08", 0x50), }, 325 { I2C_BOARD_INFO("24c08", 0x50), },
149 { I2C_BOARD_INFO("wm8580", 0x1b), }, 326 { I2C_BOARD_INFO("wm8580", 0x1b), },
327
328#ifdef CONFIG_SMDK6410_WM1190_EV1
329 { I2C_BOARD_INFO("wm8350", 0x1a),
330 .platform_data = &smdk6410_wm8350_pdata,
331 .irq = S3C_EINT(12),
332 },
333#endif
150}; 334};
151 335
152static struct i2c_board_info i2c_devs1[] __initdata = { 336static struct i2c_board_info i2c_devs1[] __initdata = {
@@ -155,9 +339,23 @@ static struct i2c_board_info i2c_devs1[] __initdata = {
155 339
156static void __init smdk6410_map_io(void) 340static void __init smdk6410_map_io(void)
157{ 341{
342 u32 tmp;
343
158 s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc)); 344 s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc));
159 s3c24xx_init_clocks(12000000); 345 s3c24xx_init_clocks(12000000);
160 s3c24xx_init_uarts(smdk6410_uartcfgs, ARRAY_SIZE(smdk6410_uartcfgs)); 346 s3c24xx_init_uarts(smdk6410_uartcfgs, ARRAY_SIZE(smdk6410_uartcfgs));
347
348 /* set the LCD type */
349
350 tmp = __raw_readl(S3C64XX_SPCON);
351 tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
352 tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
353 __raw_writel(tmp, S3C64XX_SPCON);
354
355 /* remove the lcd bypass */
356 tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
357 tmp &= ~MIFPCON_LCD_BYPASS;
358 __raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
161} 359}
162 360
163static void __init smdk6410_machine_init(void) 361static void __init smdk6410_machine_init(void)
diff --git a/arch/arm/mach-s3c6410/setup-sdhci.c b/arch/arm/mach-s3c6410/setup-sdhci.c
index 0b5788bd5985..20666f3bd478 100644
--- a/arch/arm/mach-s3c6410/setup-sdhci.c
+++ b/arch/arm/mach-s3c6410/setup-sdhci.c
@@ -21,8 +21,6 @@
21#include <linux/mmc/card.h> 21#include <linux/mmc/card.h>
22#include <linux/mmc/host.h> 22#include <linux/mmc/host.h>
23 23
24#include <mach/gpio.h>
25#include <plat/gpio-cfg.h>
26#include <plat/regs-sdhci.h> 24#include <plat/regs-sdhci.h>
27#include <plat/sdhci.h> 25#include <plat/sdhci.h>
28 26
@@ -35,22 +33,6 @@ char *s3c6410_hsmmc_clksrcs[4] = {
35 /* [3] = "48m", - note not succesfully used yet */ 33 /* [3] = "48m", - note not succesfully used yet */
36}; 34};
37 35
38void s3c6410_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
39{
40 unsigned int gpio;
41 unsigned int end;
42
43 end = S3C64XX_GPG(2 + width);
44
45 /* Set all the necessary GPG pins to special-function 0 */
46 for (gpio = S3C64XX_GPG(0); gpio < end; gpio++) {
47 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
48 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
49 }
50
51 s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
52 s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(2));
53}
54 36
55void s3c6410_setup_sdhci0_cfg_card(struct platform_device *dev, 37void s3c6410_setup_sdhci0_cfg_card(struct platform_device *dev,
56 void __iomem *r, 38 void __iomem *r,
@@ -84,19 +66,3 @@ void s3c6410_setup_sdhci0_cfg_card(struct platform_device *dev,
84 writel(ctrl3, r + S3C_SDHCI_CONTROL3); 66 writel(ctrl3, r + S3C_SDHCI_CONTROL3);
85} 67}
86 68
87void s3c6410_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
88{
89 unsigned int gpio;
90 unsigned int end;
91
92 end = S3C64XX_GPH(2 + width);
93
94 /* Set all the necessary GPG pins to special-function 0 */
95 for (gpio = S3C64XX_GPH(0); gpio < end; gpio++) {
96 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
97 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
98 }
99
100 s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
101 s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(3));
102}
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 1f929c391af7..c39c788e2731 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -116,7 +116,7 @@ void __init versatile_init_irq(void)
116{ 116{
117 unsigned int i; 117 unsigned int i;
118 118
119 vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0); 119 vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0);
120 120
121 set_irq_chained_handler(IRQ_VICSOURCE31, sic_handle_irq); 121 set_irq_chained_handler(IRQ_VICSOURCE31, sic_handle_irq);
122 122
diff --git a/arch/arm/plat-s3c/Kconfig b/arch/arm/plat-s3c/Kconfig
index d4fc89fc5f45..935c7558469b 100644
--- a/arch/arm/plat-s3c/Kconfig
+++ b/arch/arm/plat-s3c/Kconfig
@@ -71,6 +71,15 @@ config S3C2410_PM_DEBUG
71 Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt> 71 Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
72 for more information. 72 for more information.
73 73
74config S3C_PM_DEBUG_LED_SMDK
75 bool "SMDK LED suspend/resume debugging"
76 depends on PM && (MACH_SMDK6410)
77 help
78 Say Y here to enable the use of the SMDK LEDs on the baseboard
79 for debugging of the state of the suspend and resume process.
80
81 Note, this currently only works for S3C64XX based SMDK boards.
82
74config S3C2410_PM_CHECK 83config S3C2410_PM_CHECK
75 bool "S3C2410 PM Suspend Memory CRC" 84 bool "S3C2410 PM Suspend Memory CRC"
76 depends on PM && CRC32 85 depends on PM && CRC32
@@ -179,4 +188,14 @@ config S3C_DEV_FB
179 help 188 help
180 Compile in platform device definition for framebuffer 189 Compile in platform device definition for framebuffer
181 190
191config S3C_DEV_USB_HOST
192 bool
193 help
194 Compile in platform device definition for USB host.
195
196config S3C_DEV_USB_HSOTG
197 bool
198 help
199 Compile in platform device definition for USB high-speed OtG
200
182endif 201endif
diff --git a/arch/arm/plat-s3c/Makefile b/arch/arm/plat-s3c/Makefile
index e8b23fc8fba2..610651455a78 100644
--- a/arch/arm/plat-s3c/Makefile
+++ b/arch/arm/plat-s3c/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_S3C_DMA) += dma.o
25# PM support 25# PM support
26 26
27obj-$(CONFIG_PM) += pm.o 27obj-$(CONFIG_PM) += pm.o
28obj-$(CONFIG_PM) += pm-gpio.o
28obj-$(CONFIG_S3C2410_PM_CHECK) += pm-check.o 29obj-$(CONFIG_S3C2410_PM_CHECK) += pm-check.o
29 30
30# devices 31# devices
@@ -34,3 +35,5 @@ obj-$(CONFIG_S3C_DEV_HSMMC1) += dev-hsmmc1.o
34obj-y += dev-i2c0.o 35obj-y += dev-i2c0.o
35obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o 36obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o
36obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o 37obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o
38obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o
39obj-$(CONFIG_S3C_DEV_USB_HSOTG) += dev-usb-hsotg.o
diff --git a/arch/arm/plat-s3c/dev-usb-hsotg.c b/arch/arm/plat-s3c/dev-usb-hsotg.c
new file mode 100644
index 000000000000..e2f604b51c86
--- /dev/null
+++ b/arch/arm/plat-s3c/dev-usb-hsotg.c
@@ -0,0 +1,41 @@
1/* linux/arch/arm/plat-s3c/dev-usb-hsotg.c
2 *
3 * Copyright 2008 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 * http://armlinux.simtec.co.uk/
6 *
7 * S3C series device definition for USB high-speed UDC/OtG block
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12*/
13
14#include <linux/kernel.h>
15#include <linux/string.h>
16#include <linux/platform_device.h>
17
18#include <mach/irqs.h>
19#include <mach/map.h>
20
21#include <plat/devs.h>
22
23static struct resource s3c_usb_hsotg_resources[] = {
24 [0] = {
25 .start = S3C_PA_USB_HSOTG,
26 .end = S3C_PA_USB_HSOTG + 0x10000 - 1,
27 .flags = IORESOURCE_MEM,
28 },
29 [1] = {
30 .start = IRQ_OTG,
31 .end = IRQ_OTG,
32 .flags = IORESOURCE_IRQ,
33 },
34};
35
36struct platform_device s3c_device_usb_hsotg = {
37 .name = "s3c-hsotg",
38 .id = -1,
39 .num_resources = ARRAY_SIZE(s3c_usb_hsotg_resources),
40 .resource = s3c_usb_hsotg_resources,
41};
diff --git a/arch/arm/plat-s3c/dev-usb.c b/arch/arm/plat-s3c/dev-usb.c
new file mode 100644
index 000000000000..2ee85abed6d9
--- /dev/null
+++ b/arch/arm/plat-s3c/dev-usb.c
@@ -0,0 +1,50 @@
1/* linux/arch/arm/plat-s3c/dev-usb.c
2 *
3 * Copyright 2008 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 * http://armlinux.simtec.co.uk/
6 *
7 * S3C series device definition for USB host
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12*/
13
14#include <linux/kernel.h>
15#include <linux/string.h>
16#include <linux/platform_device.h>
17
18#include <mach/irqs.h>
19#include <mach/map.h>
20
21#include <plat/devs.h>
22
23
24static struct resource s3c_usb_resource[] = {
25 [0] = {
26 .start = S3C_PA_USBHOST,
27 .end = S3C_PA_USBHOST + 0x100 - 1,
28 .flags = IORESOURCE_MEM,
29 },
30 [1] = {
31 .start = IRQ_USBH,
32 .end = IRQ_USBH,
33 .flags = IORESOURCE_IRQ,
34 }
35};
36
37static u64 s3c_device_usb_dmamask = 0xffffffffUL;
38
39struct platform_device s3c_device_usb = {
40 .name = "s3c2410-ohci",
41 .id = -1,
42 .num_resources = ARRAY_SIZE(s3c_usb_resource),
43 .resource = s3c_usb_resource,
44 .dev = {
45 .dma_mask = &s3c_device_usb_dmamask,
46 .coherent_dma_mask = 0xffffffffUL
47 }
48};
49
50EXPORT_SYMBOL(s3c_device_usb);
diff --git a/arch/arm/plat-s3c/gpio.c b/arch/arm/plat-s3c/gpio.c
index d71dd6d9ce5c..260fdc6ad685 100644
--- a/arch/arm/plat-s3c/gpio.c
+++ b/arch/arm/plat-s3c/gpio.c
@@ -16,7 +16,7 @@
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/gpio.h> 17#include <linux/gpio.h>
18 18
19#include <plat/gpio-core.h> 19#include <mach/gpio-core.h>
20 20
21#ifdef CONFIG_S3C_GPIO_TRACK 21#ifdef CONFIG_S3C_GPIO_TRACK
22struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END]; 22struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
@@ -140,6 +140,15 @@ __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
140 if (!gc->get) 140 if (!gc->get)
141 gc->get = s3c_gpiolib_get; 141 gc->get = s3c_gpiolib_get;
142 142
143#ifdef CONFIG_PM
144 if (chip->pm != NULL) {
145 if (!chip->pm->save || !chip->pm->resume)
146 printk(KERN_ERR "gpio: %s has missing PM functions\n",
147 gc->label);
148 } else
149 printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
150#endif
151
143 /* gpiochip_add() prints own failure message on error. */ 152 /* gpiochip_add() prints own failure message on error. */
144 ret = gpiochip_add(gc); 153 ret = gpiochip_add(gc);
145 if (ret >= 0) 154 if (ret >= 0)
diff --git a/arch/arm/plat-s3c/include/plat/adc.h b/arch/arm/plat-s3c/include/plat/adc.h
index 43df2a404b0b..d847bd476b6c 100644
--- a/arch/arm/plat-s3c/include/plat/adc.h
+++ b/arch/arm/plat-s3c/include/plat/adc.h
@@ -19,10 +19,12 @@ struct s3c_adc_client;
19extern int s3c_adc_start(struct s3c_adc_client *client, 19extern int s3c_adc_start(struct s3c_adc_client *client,
20 unsigned int channel, unsigned int nr_samples); 20 unsigned int channel, unsigned int nr_samples);
21 21
22extern struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev, 22extern struct s3c_adc_client *
23 void (*select)(unsigned selected), 23 s3c_adc_register(struct platform_device *pdev,
24 void (*conv)(unsigned d0, unsigned d1), 24 void (*select)(unsigned selected),
25 unsigned int is_ts); 25 void (*conv)(unsigned d0, unsigned d1,
26 unsigned *samples_left),
27 unsigned int is_ts);
26 28
27extern void s3c_adc_release(struct s3c_adc_client *client); 29extern void s3c_adc_release(struct s3c_adc_client *client);
28 30
diff --git a/arch/arm/plat-s3c/include/plat/clock.h b/arch/arm/plat-s3c/include/plat/clock.h
index a10622eed43a..d86af84b5b8c 100644
--- a/arch/arm/plat-s3c/include/plat/clock.h
+++ b/arch/arm/plat-s3c/include/plat/clock.h
@@ -50,6 +50,7 @@ extern struct clk clk_xtal;
50extern struct clk clk_ext; 50extern struct clk clk_ext;
51 51
52/* S3C64XX specific clocks */ 52/* S3C64XX specific clocks */
53extern struct clk clk_h2;
53extern struct clk clk_27m; 54extern struct clk clk_27m;
54extern struct clk clk_48m; 55extern struct clk clk_48m;
55 56
diff --git a/arch/arm/plat-s3c/include/plat/cpu.h b/arch/arm/plat-s3c/include/plat/cpu.h
index e62ae0fcfe56..be541cbba070 100644
--- a/arch/arm/plat-s3c/include/plat/cpu.h
+++ b/arch/arm/plat-s3c/include/plat/cpu.h
@@ -69,3 +69,6 @@ extern struct sysdev_class s3c2412_sysclass;
69extern struct sysdev_class s3c2440_sysclass; 69extern struct sysdev_class s3c2440_sysclass;
70extern struct sysdev_class s3c2442_sysclass; 70extern struct sysdev_class s3c2442_sysclass;
71extern struct sysdev_class s3c2443_sysclass; 71extern struct sysdev_class s3c2443_sysclass;
72extern struct sysdev_class s3c6410_sysclass;
73extern struct sysdev_class s3c64xx_sysclass;
74
diff --git a/arch/arm/plat-s3c/include/plat/devs.h b/arch/arm/plat-s3c/include/plat/devs.h
index 26f0cec3ac04..a0b6768fddcf 100644
--- a/arch/arm/plat-s3c/include/plat/devs.h
+++ b/arch/arm/plat-s3c/include/plat/devs.h
@@ -45,6 +45,7 @@ extern struct platform_device s3c_device_spi1;
45extern struct platform_device s3c_device_nand; 45extern struct platform_device s3c_device_nand;
46 46
47extern struct platform_device s3c_device_usbgadget; 47extern struct platform_device s3c_device_usbgadget;
48extern struct platform_device s3c_device_usb_hsotg;
48 49
49/* s3c2440 specific devices */ 50/* s3c2440 specific devices */
50 51
diff --git a/arch/arm/plat-s3c/include/plat/gpio-core.h b/arch/arm/plat-s3c/include/plat/gpio-core.h
index 2fc60a580ac8..32af612767aa 100644
--- a/arch/arm/plat-s3c/include/plat/gpio-core.h
+++ b/arch/arm/plat-s3c/include/plat/gpio-core.h
@@ -20,6 +20,18 @@
20 * specific code. 20 * specific code.
21*/ 21*/
22 22
23struct s3c_gpio_chip;
24
25/**
26 * struct s3c_gpio_pm - power management (suspend/resume) information
27 * @save: Routine to save the state of the GPIO block
28 * @resume: Routine to resume the GPIO block.
29 */
30struct s3c_gpio_pm {
31 void (*save)(struct s3c_gpio_chip *chip);
32 void (*resume)(struct s3c_gpio_chip *chip);
33};
34
23struct s3c_gpio_cfg; 35struct s3c_gpio_cfg;
24 36
25/** 37/**
@@ -27,6 +39,7 @@ struct s3c_gpio_cfg;
27 * @chip: The chip structure to be exported via gpiolib. 39 * @chip: The chip structure to be exported via gpiolib.
28 * @base: The base pointer to the gpio configuration registers. 40 * @base: The base pointer to the gpio configuration registers.
29 * @config: special function and pull-resistor control information. 41 * @config: special function and pull-resistor control information.
42 * @pm_save: Save information for suspend/resume support.
30 * 43 *
31 * This wrapper provides the necessary information for the Samsung 44 * This wrapper provides the necessary information for the Samsung
32 * specific gpios being registered with gpiolib. 45 * specific gpios being registered with gpiolib.
@@ -34,7 +47,11 @@ struct s3c_gpio_cfg;
34struct s3c_gpio_chip { 47struct s3c_gpio_chip {
35 struct gpio_chip chip; 48 struct gpio_chip chip;
36 struct s3c_gpio_cfg *config; 49 struct s3c_gpio_cfg *config;
50 struct s3c_gpio_pm *pm;
37 void __iomem *base; 51 void __iomem *base;
52#ifdef CONFIG_PM
53 u32 pm_save[4];
54#endif
38}; 55};
39 56
40static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc) 57static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
@@ -75,3 +92,16 @@ static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip)
75 92
76static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { } 93static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
77#endif 94#endif
95
96#ifdef CONFIG_PM
97extern struct s3c_gpio_pm s3c_gpio_pm_1bit;
98extern struct s3c_gpio_pm s3c_gpio_pm_2bit;
99extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
100#define __gpio_pm(x) x
101#else
102#define s3c_gpio_pm_1bit NULL
103#define s3c_gpio_pm_2bit NULL
104#define s3c_gpio_pm_4bit NULL
105#define __gpio_pm(x) NULL
106
107#endif /* CONFIG_PM */
diff --git a/arch/arm/plat-s3c/include/plat/pm.h b/arch/arm/plat-s3c/include/plat/pm.h
index 3779775133a9..7a797192fcf3 100644
--- a/arch/arm/plat-s3c/include/plat/pm.h
+++ b/arch/arm/plat-s3c/include/plat/pm.h
@@ -44,6 +44,8 @@ extern void (*pm_cpu_sleep)(void);
44 44
45extern unsigned long s3c_pm_flags; 45extern unsigned long s3c_pm_flags;
46 46
47extern unsigned char pm_uart_udivslot; /* true to save UART UDIVSLOT */
48
47/* from sleep.S */ 49/* from sleep.S */
48 50
49extern int s3c_cpu_save(unsigned long *saveblk); 51extern int s3c_cpu_save(unsigned long *saveblk);
@@ -88,6 +90,7 @@ struct pm_uart_save {
88 u32 ufcon; 90 u32 ufcon;
89 u32 umcon; 91 u32 umcon;
90 u32 ubrdiv; 92 u32 ubrdiv;
93 u32 udivslot;
91}; 94};
92 95
93/* helper functions to save/restore lists of registers. */ 96/* helper functions to save/restore lists of registers. */
@@ -124,6 +127,18 @@ extern void s3c_pm_dbg(const char *msg, ...);
124#define S3C_PMDBG(fmt...) printk(KERN_DEBUG fmt) 127#define S3C_PMDBG(fmt...) printk(KERN_DEBUG fmt)
125#endif 128#endif
126 129
130#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
131/**
132 * s3c_pm_debug_smdkled() - Debug PM suspend/resume via SMDK Board LEDs
133 * @set: set bits for the state of the LEDs
134 * @clear: clear bits for the state of the LEDs.
135 */
136extern void s3c_pm_debug_smdkled(u32 set, u32 clear);
137
138#else
139static inline void s3c_pm_debug_smdkled(u32 set, u32 clear) { }
140#endif /* CONFIG_S3C_PM_DEBUG_LED_SMDK */
141
127/* suspend memory checking */ 142/* suspend memory checking */
128 143
129#ifdef CONFIG_S3C2410_PM_CHECK 144#ifdef CONFIG_S3C2410_PM_CHECK
diff --git a/arch/arm/plat-s3c/include/plat/regs-serial.h b/arch/arm/plat-s3c/include/plat/regs-serial.h
index 487d7d2a7e1d..66af75a5cdd1 100644
--- a/arch/arm/plat-s3c/include/plat/regs-serial.h
+++ b/arch/arm/plat-s3c/include/plat/regs-serial.h
@@ -189,6 +189,11 @@
189 189
190#define S3C2443_DIVSLOT (0x2C) 190#define S3C2443_DIVSLOT (0x2C)
191 191
192/* S3C64XX interrupt registers. */
193#define S3C64XX_UINTP 0x30
194#define S3C64XX_UINTSP 0x34
195#define S3C64XX_UINTM 0x38
196
192#ifndef __ASSEMBLY__ 197#ifndef __ASSEMBLY__
193 198
194/* struct s3c24xx_uart_clksrc 199/* struct s3c24xx_uart_clksrc
diff --git a/arch/arm/plat-s3c/include/plat/sdhci.h b/arch/arm/plat-s3c/include/plat/sdhci.h
index c4ca3920ca4b..f615308ccdfb 100644
--- a/arch/arm/plat-s3c/include/plat/sdhci.h
+++ b/arch/arm/plat-s3c/include/plat/sdhci.h
@@ -67,12 +67,52 @@ extern struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata;
67 67
68/* Helper function availablity */ 68/* Helper function availablity */
69 69
70extern void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
71extern void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
72
73/* S3C6400 SDHCI setup */
74
75#ifdef CONFIG_S3C6400_SETUP_SDHCI
76extern char *s3c6400_hsmmc_clksrcs[4];
77
78#ifdef CONFIG_S3C_DEV_HSMMC
79extern void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev,
80 void __iomem *r,
81 struct mmc_ios *ios,
82 struct mmc_card *card);
83
84static inline void s3c6400_default_sdhci0(void)
85{
86 s3c_hsmmc0_def_platdata.clocks = s3c6400_hsmmc_clksrcs;
87 s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
88 s3c_hsmmc0_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
89}
90
91#else
92static inline void s3c6400_default_sdhci0(void) { }
93#endif /* CONFIG_S3C_DEV_HSMMC */
94
95#ifdef CONFIG_S3C_DEV_HSMMC1
96static inline void s3c6400_default_sdhci1(void)
97{
98 s3c_hsmmc1_def_platdata.clocks = s3c6400_hsmmc_clksrcs;
99 s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
100 s3c_hsmmc1_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
101}
102#else
103static inline void s3c6400_default_sdhci1(void) { }
104#endif /* CONFIG_S3C_DEV_HSMMC1 */
105
106#else
107static inline void s3c6400_default_sdhci0(void) { }
108static inline void s3c6400_default_sdhci1(void) { }
109#endif /* CONFIG_S3C6400_SETUP_SDHCI */
110
111/* S3C6410 SDHCI setup */
112
70#ifdef CONFIG_S3C6410_SETUP_SDHCI 113#ifdef CONFIG_S3C6410_SETUP_SDHCI
71extern char *s3c6410_hsmmc_clksrcs[4]; 114extern char *s3c6410_hsmmc_clksrcs[4];
72 115
73extern void s3c6410_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
74extern void s3c6410_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
75
76extern void s3c6410_setup_sdhci0_cfg_card(struct platform_device *dev, 116extern void s3c6410_setup_sdhci0_cfg_card(struct platform_device *dev,
77 void __iomem *r, 117 void __iomem *r,
78 struct mmc_ios *ios, 118 struct mmc_ios *ios,
@@ -82,7 +122,7 @@ extern void s3c6410_setup_sdhci0_cfg_card(struct platform_device *dev,
82static inline void s3c6410_default_sdhci0(void) 122static inline void s3c6410_default_sdhci0(void)
83{ 123{
84 s3c_hsmmc0_def_platdata.clocks = s3c6410_hsmmc_clksrcs; 124 s3c_hsmmc0_def_platdata.clocks = s3c6410_hsmmc_clksrcs;
85 s3c_hsmmc0_def_platdata.cfg_gpio = s3c6410_setup_sdhci0_cfg_gpio; 125 s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
86 s3c_hsmmc0_def_platdata.cfg_card = s3c6410_setup_sdhci0_cfg_card; 126 s3c_hsmmc0_def_platdata.cfg_card = s3c6410_setup_sdhci0_cfg_card;
87} 127}
88#else 128#else
@@ -93,7 +133,7 @@ static inline void s3c6410_default_sdhci0(void) { }
93static inline void s3c6410_default_sdhci1(void) 133static inline void s3c6410_default_sdhci1(void)
94{ 134{
95 s3c_hsmmc1_def_platdata.clocks = s3c6410_hsmmc_clksrcs; 135 s3c_hsmmc1_def_platdata.clocks = s3c6410_hsmmc_clksrcs;
96 s3c_hsmmc1_def_platdata.cfg_gpio = s3c6410_setup_sdhci1_cfg_gpio; 136 s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
97 s3c_hsmmc1_def_platdata.cfg_card = s3c6410_setup_sdhci0_cfg_card; 137 s3c_hsmmc1_def_platdata.cfg_card = s3c6410_setup_sdhci0_cfg_card;
98} 138}
99#else 139#else
diff --git a/arch/arm/plat-s3c/include/plat/udc-hs.h b/arch/arm/plat-s3c/include/plat/udc-hs.h
new file mode 100644
index 000000000000..dd04db043109
--- /dev/null
+++ b/arch/arm/plat-s3c/include/plat/udc-hs.h
@@ -0,0 +1,29 @@
1/* arch/arm/plat-s3c/include/plat/udc-hs.h
2 *
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
7 *
8 * S3C USB2.0 High-speed / OtG platform information
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15enum s3c_hostg_dmamode {
16 S3C_HSOTG_DMA_NONE, /* do not use DMA at-all */
17 S3C_HSOTG_DMA_ONLY, /* always use DMA */
18 S3C_HSOTG_DMA_DRV, /* DMA is chosen by driver */
19};
20
21/**
22 * struct s3c_hsotg_plat - platform data for high-speed otg/udc
23 * @dma: Whether to use DMA or not.
24 * @is_osc: The clock source is an oscillator, not a crystal
25 */
26struct s3c_hsotg_plat {
27 enum s3c_hostg_dmamode dma;
28 unsigned int is_osc : 1;
29};
diff --git a/arch/arm/plat-s3c/include/plat/watchdog-reset.h b/arch/arm/plat-s3c/include/plat/watchdog-reset.h
new file mode 100644
index 000000000000..54b762acb5a0
--- /dev/null
+++ b/arch/arm/plat-s3c/include/plat/watchdog-reset.h
@@ -0,0 +1,49 @@
1/* arch/arm/plat-s3c/include/plat/watchdog-reset.h
2 *
3 * Copyright (c) 2008 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C2410 - System define for arch_reset() function
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <plat/regs-watchdog.h>
14#include <mach/map.h>
15
16#include <linux/clk.h>
17#include <linux/err.h>
18#include <linux/io.h>
19
20static inline void arch_wdt_reset(void)
21{
22 struct clk *wdtclk;
23
24 printk("arch_reset: attempting watchdog reset\n");
25
26 __raw_writel(0, S3C2410_WTCON); /* disable watchdog, to be safe */
27
28 wdtclk = clk_get(NULL, "watchdog");
29 if (!IS_ERR(wdtclk)) {
30 clk_enable(wdtclk);
31 } else
32 printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__);
33
34 /* put initial values into count and data */
35 __raw_writel(0x80, S3C2410_WTCNT);
36 __raw_writel(0x80, S3C2410_WTDAT);
37
38 /* set the watchdog to go and reset... */
39 __raw_writel(S3C2410_WTCON_ENABLE|S3C2410_WTCON_DIV16|S3C2410_WTCON_RSTEN |
40 S3C2410_WTCON_PRESCALE(0x20), S3C2410_WTCON);
41
42 /* wait for reset to assert... */
43 mdelay(500);
44
45 printk(KERN_ERR "Watchdog reset failed to assert reset\n");
46
47 /* delay to allow the serial port to show the message */
48 mdelay(50);
49}
diff --git a/arch/arm/plat-s3c/pm-gpio.c b/arch/arm/plat-s3c/pm-gpio.c
new file mode 100644
index 000000000000..cfd326a8b693
--- /dev/null
+++ b/arch/arm/plat-s3c/pm-gpio.c
@@ -0,0 +1,380 @@
1
2/* linux/arch/arm/plat-s3c/pm-gpio.c
3 *
4 * Copyright 2008 Openmoko, Inc.
5 * Copyright 2008 Simtec Electronics
6 * Ben Dooks <ben@simtec.co.uk>
7 * http://armlinux.simtec.co.uk/
8 *
9 * S3C series GPIO PM code
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14*/
15
16#include <linux/kernel.h>
17#include <linux/sysdev.h>
18#include <linux/init.h>
19#include <linux/io.h>
20#include <linux/gpio.h>
21
22#include <mach/gpio-core.h>
23#include <plat/pm.h>
24
25/* PM GPIO helpers */
26
27#define OFFS_CON (0x00)
28#define OFFS_DAT (0x04)
29#define OFFS_UP (0x08)
30
31static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip)
32{
33 chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
34 chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
35}
36
37static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
38{
39 void __iomem *base = chip->base;
40 u32 old_gpcon = __raw_readl(base + OFFS_CON);
41 u32 old_gpdat = __raw_readl(base + OFFS_DAT);
42 u32 gps_gpcon = chip->pm_save[0];
43 u32 gps_gpdat = chip->pm_save[1];
44 u32 gpcon;
45
46 /* GPACON only has one bit per control / data and no PULLUPs.
47 * GPACON[x] = 0 => Output, 1 => SFN */
48
49 /* first set all SFN bits to SFN */
50
51 gpcon = old_gpcon | gps_gpcon;
52 __raw_writel(gpcon, base + OFFS_CON);
53
54 /* now set all the other bits */
55
56 __raw_writel(gps_gpdat, base + OFFS_DAT);
57 __raw_writel(gps_gpcon, base + OFFS_CON);
58
59 S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
60 chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
61}
62
63struct s3c_gpio_pm s3c_gpio_pm_1bit = {
64 .save = s3c_gpio_pm_1bit_save,
65 .resume = s3c_gpio_pm_1bit_resume,
66};
67
68static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip)
69{
70 chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
71 chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
72 chip->pm_save[2] = __raw_readl(chip->base + OFFS_UP);
73}
74
75/* Test whether the given masked+shifted bits of an GPIO configuration
76 * are one of the SFN (special function) modes. */
77
78static inline int is_sfn(unsigned long con)
79{
80 return con >= 2;
81}
82
83/* Test if the given masked+shifted GPIO configuration is an input */
84
85static inline int is_in(unsigned long con)
86{
87 return con == 0;
88}
89
90/* Test if the given masked+shifted GPIO configuration is an output */
91
92static inline int is_out(unsigned long con)
93{
94 return con == 1;
95}
96
97/**
98 * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank
99 * @chip: The chip information to resume.
100 *
101 * Restore one of the GPIO banks that was saved during suspend. This is
102 * not as simple as once thought, due to the possibility of glitches
103 * from the order that the CON and DAT registers are set in.
104 *
105 * The three states the pin can be are {IN,OUT,SFN} which gives us 9
106 * combinations of changes to check. Three of these, if the pin stays
107 * in the same configuration can be discounted. This leaves us with
108 * the following:
109 *
110 * { IN => OUT } Change DAT first
111 * { IN => SFN } Change CON first
112 * { OUT => SFN } Change CON first, so new data will not glitch
113 * { OUT => IN } Change CON first, so new data will not glitch
114 * { SFN => IN } Change CON first
115 * { SFN => OUT } Change DAT first, so new data will not glitch [1]
116 *
117 * We do not currently deal with the UP registers as these control
118 * weak resistors, so a small delay in change should not need to bring
119 * these into the calculations.
120 *
121 * [1] this assumes that writing to a pin DAT whilst in SFN will set the
122 * state for when it is next output.
123 */
124static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
125{
126 void __iomem *base = chip->base;
127 u32 old_gpcon = __raw_readl(base + OFFS_CON);
128 u32 old_gpdat = __raw_readl(base + OFFS_DAT);
129 u32 gps_gpcon = chip->pm_save[0];
130 u32 gps_gpdat = chip->pm_save[1];
131 u32 gpcon, old, new, mask;
132 u32 change_mask = 0x0;
133 int nr;
134
135 /* restore GPIO pull-up settings */
136 __raw_writel(chip->pm_save[2], base + OFFS_UP);
137
138 /* Create a change_mask of all the items that need to have
139 * their CON value changed before their DAT value, so that
140 * we minimise the work between the two settings.
141 */
142
143 for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
144 old = (old_gpcon & mask) >> nr;
145 new = (gps_gpcon & mask) >> nr;
146
147 /* If there is no change, then skip */
148
149 if (old == new)
150 continue;
151
152 /* If both are special function, then skip */
153
154 if (is_sfn(old) && is_sfn(new))
155 continue;
156
157 /* Change is IN => OUT, do not change now */
158
159 if (is_in(old) && is_out(new))
160 continue;
161
162 /* Change is SFN => OUT, do not change now */
163
164 if (is_sfn(old) && is_out(new))
165 continue;
166
167 /* We should now be at the case of IN=>SFN,
168 * OUT=>SFN, OUT=>IN, SFN=>IN. */
169
170 change_mask |= mask;
171 }
172
173
174 /* Write the new CON settings */
175
176 gpcon = old_gpcon & ~change_mask;
177 gpcon |= gps_gpcon & change_mask;
178
179 __raw_writel(gpcon, base + OFFS_CON);
180
181 /* Now change any items that require DAT,CON */
182
183 __raw_writel(gps_gpdat, base + OFFS_DAT);
184 __raw_writel(gps_gpcon, base + OFFS_CON);
185
186 S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
187 chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
188}
189
190struct s3c_gpio_pm s3c_gpio_pm_2bit = {
191 .save = s3c_gpio_pm_2bit_save,
192 .resume = s3c_gpio_pm_2bit_resume,
193};
194
195#ifdef CONFIG_ARCH_S3C64XX
196static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
197{
198 chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
199 chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
200 chip->pm_save[3] = __raw_readl(chip->base + OFFS_UP);
201
202 if (chip->chip.ngpio > 8)
203 chip->pm_save[0] = __raw_readl(chip->base - 4);
204}
205
206static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
207{
208 u32 old, new, mask;
209 u32 change_mask = 0x0;
210 int nr;
211
212 for (nr = 0, mask = 0x0f; nr < 16; nr += 4, mask <<= 4) {
213 old = (old_gpcon & mask) >> nr;
214 new = (gps_gpcon & mask) >> nr;
215
216 /* If there is no change, then skip */
217
218 if (old == new)
219 continue;
220
221 /* If both are special function, then skip */
222
223 if (is_sfn(old) && is_sfn(new))
224 continue;
225
226 /* Change is IN => OUT, do not change now */
227
228 if (is_in(old) && is_out(new))
229 continue;
230
231 /* Change is SFN => OUT, do not change now */
232
233 if (is_sfn(old) && is_out(new))
234 continue;
235
236 /* We should now be at the case of IN=>SFN,
237 * OUT=>SFN, OUT=>IN, SFN=>IN. */
238
239 change_mask |= mask;
240 }
241
242 return change_mask;
243}
244
245static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
246{
247 void __iomem *con = chip->base + (index * 4);
248 u32 old_gpcon = __raw_readl(con);
249 u32 gps_gpcon = chip->pm_save[index + 1];
250 u32 gpcon, mask;
251
252 mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
253
254 gpcon = old_gpcon & ~mask;
255 gpcon |= gps_gpcon & mask;
256
257 __raw_writel(gpcon, con);
258}
259
260static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
261{
262 void __iomem *base = chip->base;
263 u32 old_gpcon[2];
264 u32 old_gpdat = __raw_readl(base + OFFS_DAT);
265 u32 gps_gpdat = chip->pm_save[2];
266
267 /* First, modify the CON settings */
268
269 old_gpcon[0] = 0;
270 old_gpcon[1] = __raw_readl(base + OFFS_CON);
271
272 s3c_gpio_pm_4bit_con(chip, 0);
273 if (chip->chip.ngpio > 8) {
274 old_gpcon[0] = __raw_readl(base - 4);
275 s3c_gpio_pm_4bit_con(chip, -1);
276 }
277
278 /* Now change the configurations that require DAT,CON */
279
280 __raw_writel(chip->pm_save[2], base + OFFS_DAT);
281 __raw_writel(chip->pm_save[1], base + OFFS_CON);
282 if (chip->chip.ngpio > 8)
283 __raw_writel(chip->pm_save[0], base - 4);
284
285 __raw_writel(chip->pm_save[2], base + OFFS_DAT);
286 __raw_writel(chip->pm_save[3], base + OFFS_UP);
287
288 if (chip->chip.ngpio > 8) {
289 S3C_PMDBG("%s: CON4 %08x,%08x => %08x,%08x, DAT %08x => %08x\n",
290 chip->chip.label, old_gpcon[0], old_gpcon[1],
291 __raw_readl(base - 4),
292 __raw_readl(base + OFFS_CON),
293 old_gpdat, gps_gpdat);
294 } else
295 S3C_PMDBG("%s: CON4 %08x => %08x, DAT %08x => %08x\n",
296 chip->chip.label, old_gpcon[1],
297 __raw_readl(base + OFFS_CON),
298 old_gpdat, gps_gpdat);
299}
300
301struct s3c_gpio_pm s3c_gpio_pm_4bit = {
302 .save = s3c_gpio_pm_4bit_save,
303 .resume = s3c_gpio_pm_4bit_resume,
304};
305#endif /* CONFIG_ARCH_S3C64XX */
306
307/**
308 * s3c_pm_save_gpio() - save gpio chip data for suspend
309 * @ourchip: The chip for suspend.
310 */
311static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip)
312{
313 struct s3c_gpio_pm *pm = ourchip->pm;
314
315 if (pm == NULL || pm->save == NULL)
316 S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
317 else
318 pm->save(ourchip);
319}
320
321/**
322 * s3c_pm_save_gpios() - Save the state of the GPIO banks.
323 *
324 * For all the GPIO banks, save the state of each one ready for going
325 * into a suspend mode.
326 */
327void s3c_pm_save_gpios(void)
328{
329 struct s3c_gpio_chip *ourchip;
330 unsigned int gpio_nr;
331
332 for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
333 ourchip = s3c_gpiolib_getchip(gpio_nr);
334 if (!ourchip)
335 continue;
336
337 s3c_pm_save_gpio(ourchip);
338
339 S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
340 ourchip->chip.label,
341 ourchip->pm_save[0],
342 ourchip->pm_save[1],
343 ourchip->pm_save[2],
344 ourchip->pm_save[3]);
345
346 gpio_nr += ourchip->chip.ngpio;
347 gpio_nr += CONFIG_S3C_GPIO_SPACE;
348 }
349}
350
351/**
352 * s3c_pm_resume_gpio() - restore gpio chip data after suspend
353 * @ourchip: The suspended chip.
354 */
355static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
356{
357 struct s3c_gpio_pm *pm = ourchip->pm;
358
359 if (pm == NULL || pm->resume == NULL)
360 S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
361 else
362 pm->resume(ourchip);
363}
364
365void s3c_pm_restore_gpios(void)
366{
367 struct s3c_gpio_chip *ourchip;
368 unsigned int gpio_nr;
369
370 for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
371 ourchip = s3c_gpiolib_getchip(gpio_nr);
372 if (!ourchip)
373 continue;
374
375 s3c_pm_resume_gpio(ourchip);
376
377 gpio_nr += ourchip->chip.ngpio;
378 gpio_nr += CONFIG_S3C_GPIO_SPACE;
379 }
380}
diff --git a/arch/arm/plat-s3c/pm.c b/arch/arm/plat-s3c/pm.c
index 061182ca66e3..8d97db2c7a0d 100644
--- a/arch/arm/plat-s3c/pm.c
+++ b/arch/arm/plat-s3c/pm.c
@@ -21,11 +21,10 @@
21 21
22#include <asm/cacheflush.h> 22#include <asm/cacheflush.h>
23#include <mach/hardware.h> 23#include <mach/hardware.h>
24#include <mach/map.h>
24 25
25#include <plat/regs-serial.h> 26#include <plat/regs-serial.h>
26#include <mach/regs-clock.h> 27#include <mach/regs-clock.h>
27#include <mach/regs-gpio.h>
28#include <mach/regs-mem.h>
29#include <mach/regs-irq.h> 28#include <mach/regs-irq.h>
30#include <asm/irq.h> 29#include <asm/irq.h>
31 30
@@ -70,6 +69,8 @@ static inline void s3c_pm_debug_init(void)
70 69
71/* Save the UART configurations if we are configured for debug. */ 70/* Save the UART configurations if we are configured for debug. */
72 71
72unsigned char pm_uart_udivslot;
73
73#ifdef CONFIG_S3C2410_PM_DEBUG 74#ifdef CONFIG_S3C2410_PM_DEBUG
74 75
75struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS]; 76struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
@@ -83,6 +84,12 @@ static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save)
83 save->ufcon = __raw_readl(regs + S3C2410_UFCON); 84 save->ufcon = __raw_readl(regs + S3C2410_UFCON);
84 save->umcon = __raw_readl(regs + S3C2410_UMCON); 85 save->umcon = __raw_readl(regs + S3C2410_UMCON);
85 save->ubrdiv = __raw_readl(regs + S3C2410_UBRDIV); 86 save->ubrdiv = __raw_readl(regs + S3C2410_UBRDIV);
87
88 if (pm_uart_udivslot)
89 save->udivslot = __raw_readl(regs + S3C2443_DIVSLOT);
90
91 S3C_PMDBG("UART[%d]: ULCON=%04x, UCON=%04x, UFCON=%04x, UBRDIV=%04x\n",
92 uart, save->ulcon, save->ucon, save->ufcon, save->ubrdiv);
86} 93}
87 94
88static void s3c_pm_save_uarts(void) 95static void s3c_pm_save_uarts(void)
@@ -98,11 +105,16 @@ static void s3c_pm_restore_uart(unsigned int uart, struct pm_uart_save *save)
98{ 105{
99 void __iomem *regs = S3C_VA_UARTx(uart); 106 void __iomem *regs = S3C_VA_UARTx(uart);
100 107
108 s3c_pm_arch_update_uart(regs, save);
109
101 __raw_writel(save->ulcon, regs + S3C2410_ULCON); 110 __raw_writel(save->ulcon, regs + S3C2410_ULCON);
102 __raw_writel(save->ucon, regs + S3C2410_UCON); 111 __raw_writel(save->ucon, regs + S3C2410_UCON);
103 __raw_writel(save->ufcon, regs + S3C2410_UFCON); 112 __raw_writel(save->ufcon, regs + S3C2410_UFCON);
104 __raw_writel(save->umcon, regs + S3C2410_UMCON); 113 __raw_writel(save->umcon, regs + S3C2410_UMCON);
105 __raw_writel(save->ubrdiv, regs + S3C2410_UBRDIV); 114 __raw_writel(save->ubrdiv, regs + S3C2410_UBRDIV);
115
116 if (pm_uart_udivslot)
117 __raw_writel(save->udivslot, regs + S3C2443_DIVSLOT);
106} 118}
107 119
108static void s3c_pm_restore_uarts(void) 120static void s3c_pm_restore_uarts(void)
@@ -313,6 +325,9 @@ static int s3c_pm_enter(suspend_state_t state)
313 325
314 S3C_PMDBG("%s: post sleep, preparing to return\n", __func__); 326 S3C_PMDBG("%s: post sleep, preparing to return\n", __func__);
315 327
328 /* LEDs should now be 1110 */
329 s3c_pm_debug_smdkled(1 << 1, 0);
330
316 s3c_pm_check_restore(); 331 s3c_pm_check_restore();
317 332
318 /* ok, let's return from sleep */ 333 /* ok, let's return from sleep */
diff --git a/arch/arm/plat-s3c24xx/adc.c b/arch/arm/plat-s3c24xx/adc.c
index 91adfa71c172..ee1baf11ad9e 100644
--- a/arch/arm/plat-s3c24xx/adc.c
+++ b/arch/arm/plat-s3c24xx/adc.c
@@ -45,7 +45,8 @@ struct s3c_adc_client {
45 unsigned char channel; 45 unsigned char channel;
46 46
47 void (*select_cb)(unsigned selected); 47 void (*select_cb)(unsigned selected);
48 void (*convert_cb)(unsigned val1, unsigned val2); 48 void (*convert_cb)(unsigned val1, unsigned val2,
49 unsigned *samples_left);
49}; 50};
50 51
51struct adc_device { 52struct adc_device {
@@ -158,7 +159,8 @@ static void s3c_adc_default_select(unsigned select)
158 159
159struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev, 160struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev,
160 void (*select)(unsigned int selected), 161 void (*select)(unsigned int selected),
161 void (*conv)(unsigned d0, unsigned d1), 162 void (*conv)(unsigned d0, unsigned d1,
163 unsigned *samples_left),
162 unsigned int is_ts) 164 unsigned int is_ts)
163{ 165{
164 struct s3c_adc_client *client; 166 struct s3c_adc_client *client;
@@ -227,9 +229,10 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
227 data1 = readl(adc->regs + S3C2410_ADCDAT1); 229 data1 = readl(adc->regs + S3C2410_ADCDAT1);
228 adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1); 230 adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1);
229 231
230 (client->convert_cb)(data0 & 0x3ff, data1 & 0x3ff); 232 client->nr_samples--;
233 (client->convert_cb)(data0 & 0x3ff, data1 & 0x3ff, &client->nr_samples);
231 234
232 if (--client->nr_samples > 0) { 235 if (client->nr_samples > 0) {
233 /* fire another conversion for this */ 236 /* fire another conversion for this */
234 237
235 client->select_cb(1); 238 client->select_cb(1);
diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c
index 16ac01d9b8ab..4eb378c89a39 100644
--- a/arch/arm/plat-s3c24xx/devs.c
+++ b/arch/arm/plat-s3c24xx/devs.c
@@ -136,36 +136,6 @@ struct platform_device *s3c24xx_uart_src[4] = {
136struct platform_device *s3c24xx_uart_devs[4] = { 136struct platform_device *s3c24xx_uart_devs[4] = {
137}; 137};
138 138
139/* USB Host Controller */
140
141static struct resource s3c_usb_resource[] = {
142 [0] = {
143 .start = S3C24XX_PA_USBHOST,
144 .end = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
145 .flags = IORESOURCE_MEM,
146 },
147 [1] = {
148 .start = IRQ_USBH,
149 .end = IRQ_USBH,
150 .flags = IORESOURCE_IRQ,
151 }
152};
153
154static u64 s3c_device_usb_dmamask = 0xffffffffUL;
155
156struct platform_device s3c_device_usb = {
157 .name = "s3c2410-ohci",
158 .id = -1,
159 .num_resources = ARRAY_SIZE(s3c_usb_resource),
160 .resource = s3c_usb_resource,
161 .dev = {
162 .dma_mask = &s3c_device_usb_dmamask,
163 .coherent_dma_mask = 0xffffffffUL
164 }
165};
166
167EXPORT_SYMBOL(s3c_device_usb);
168
169/* LCD Controller */ 139/* LCD Controller */
170 140
171static struct resource s3c_lcd_resource[] = { 141static struct resource s3c_lcd_resource[] = {
diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c
index 5c0491bf738b..4bac12dc0733 100644
--- a/arch/arm/plat-s3c24xx/gpiolib.c
+++ b/arch/arm/plat-s3c24xx/gpiolib.c
@@ -22,6 +22,7 @@
22#include <mach/gpio-core.h> 22#include <mach/gpio-core.h>
23#include <mach/hardware.h> 23#include <mach/hardware.h>
24#include <asm/irq.h> 24#include <asm/irq.h>
25#include <plat/pm.h>
25 26
26#include <mach/regs-gpio.h> 27#include <mach/regs-gpio.h>
27 28
@@ -78,6 +79,7 @@ static int s3c24xx_gpiolib_bankg_toirq(struct gpio_chip *chip, unsigned offset)
78struct s3c_gpio_chip s3c24xx_gpios[] = { 79struct s3c_gpio_chip s3c24xx_gpios[] = {
79 [0] = { 80 [0] = {
80 .base = S3C24XX_GPIO_BASE(S3C2410_GPA0), 81 .base = S3C24XX_GPIO_BASE(S3C2410_GPA0),
82 .pm = __gpio_pm(&s3c_gpio_pm_1bit),
81 .chip = { 83 .chip = {
82 .base = S3C2410_GPA0, 84 .base = S3C2410_GPA0,
83 .owner = THIS_MODULE, 85 .owner = THIS_MODULE,
@@ -89,6 +91,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
89 }, 91 },
90 [1] = { 92 [1] = {
91 .base = S3C24XX_GPIO_BASE(S3C2410_GPB0), 93 .base = S3C24XX_GPIO_BASE(S3C2410_GPB0),
94 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
92 .chip = { 95 .chip = {
93 .base = S3C2410_GPB0, 96 .base = S3C2410_GPB0,
94 .owner = THIS_MODULE, 97 .owner = THIS_MODULE,
@@ -98,6 +101,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
98 }, 101 },
99 [2] = { 102 [2] = {
100 .base = S3C24XX_GPIO_BASE(S3C2410_GPC0), 103 .base = S3C24XX_GPIO_BASE(S3C2410_GPC0),
104 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
101 .chip = { 105 .chip = {
102 .base = S3C2410_GPC0, 106 .base = S3C2410_GPC0,
103 .owner = THIS_MODULE, 107 .owner = THIS_MODULE,
@@ -107,6 +111,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
107 }, 111 },
108 [3] = { 112 [3] = {
109 .base = S3C24XX_GPIO_BASE(S3C2410_GPD0), 113 .base = S3C24XX_GPIO_BASE(S3C2410_GPD0),
114 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
110 .chip = { 115 .chip = {
111 .base = S3C2410_GPD0, 116 .base = S3C2410_GPD0,
112 .owner = THIS_MODULE, 117 .owner = THIS_MODULE,
@@ -116,6 +121,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
116 }, 121 },
117 [4] = { 122 [4] = {
118 .base = S3C24XX_GPIO_BASE(S3C2410_GPE0), 123 .base = S3C24XX_GPIO_BASE(S3C2410_GPE0),
124 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
119 .chip = { 125 .chip = {
120 .base = S3C2410_GPE0, 126 .base = S3C2410_GPE0,
121 .label = "GPIOE", 127 .label = "GPIOE",
@@ -125,6 +131,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
125 }, 131 },
126 [5] = { 132 [5] = {
127 .base = S3C24XX_GPIO_BASE(S3C2410_GPF0), 133 .base = S3C24XX_GPIO_BASE(S3C2410_GPF0),
134 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
128 .chip = { 135 .chip = {
129 .base = S3C2410_GPF0, 136 .base = S3C2410_GPF0,
130 .owner = THIS_MODULE, 137 .owner = THIS_MODULE,
@@ -135,6 +142,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
135 }, 142 },
136 [6] = { 143 [6] = {
137 .base = S3C24XX_GPIO_BASE(S3C2410_GPG0), 144 .base = S3C24XX_GPIO_BASE(S3C2410_GPG0),
145 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
138 .chip = { 146 .chip = {
139 .base = S3C2410_GPG0, 147 .base = S3C2410_GPG0,
140 .owner = THIS_MODULE, 148 .owner = THIS_MODULE,
diff --git a/arch/arm/plat-s3c24xx/include/plat/map.h b/arch/arm/plat-s3c24xx/include/plat/map.h
index eed8f78e7593..c4d133436fc7 100644
--- a/arch/arm/plat-s3c24xx/include/plat/map.h
+++ b/arch/arm/plat-s3c24xx/include/plat/map.h
@@ -58,7 +58,6 @@
58#define S3C24XX_SZ_SPI SZ_1M 58#define S3C24XX_SZ_SPI SZ_1M
59#define S3C24XX_SZ_SDI SZ_1M 59#define S3C24XX_SZ_SDI SZ_1M
60#define S3C24XX_SZ_NAND SZ_1M 60#define S3C24XX_SZ_NAND SZ_1M
61#define S3C24XX_SZ_USBHOST SZ_1M
62 61
63/* GPIO ports */ 62/* GPIO ports */
64 63
diff --git a/arch/arm/plat-s3c24xx/include/plat/pm-core.h b/arch/arm/plat-s3c24xx/include/plat/pm-core.h
index c75882113e04..fb45dd9adca5 100644
--- a/arch/arm/plat-s3c24xx/include/plat/pm-core.h
+++ b/arch/arm/plat-s3c24xx/include/plat/pm-core.h
@@ -57,3 +57,8 @@ static inline void s3c_pm_arch_show_resume_irqs(void)
57 s3c_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND), 57 s3c_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
58 s3c_irqwake_eintmask); 58 s3c_irqwake_eintmask);
59} 59}
60
61static inline void s3c_pm_arch_update_uart(void __iomem *regs,
62 struct pm_uart_save *save)
63{
64}
diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c
index 062a29339a91..5135c40a1b90 100644
--- a/arch/arm/plat-s3c24xx/pm.c
+++ b/arch/arm/plat-s3c24xx/pm.c
@@ -75,43 +75,10 @@ static struct sleep_save core_save[] = {
75 SAVE_ITEM(S3C2410_CLKSLOW), 75 SAVE_ITEM(S3C2410_CLKSLOW),
76}; 76};
77 77
78static struct gpio_sleep {
79 void __iomem *base;
80 unsigned int gpcon;
81 unsigned int gpdat;
82 unsigned int gpup;
83} gpio_save[] = {
84 [0] = {
85 .base = S3C2410_GPACON,
86 },
87 [1] = {
88 .base = S3C2410_GPBCON,
89 },
90 [2] = {
91 .base = S3C2410_GPCCON,
92 },
93 [3] = {
94 .base = S3C2410_GPDCON,
95 },
96 [4] = {
97 .base = S3C2410_GPECON,
98 },
99 [5] = {
100 .base = S3C2410_GPFCON,
101 },
102 [6] = {
103 .base = S3C2410_GPGCON,
104 },
105 [7] = {
106 .base = S3C2410_GPHCON,
107 },
108};
109
110static struct sleep_save misc_save[] = { 78static struct sleep_save misc_save[] = {
111 SAVE_ITEM(S3C2410_DCLKCON), 79 SAVE_ITEM(S3C2410_DCLKCON),
112}; 80};
113 81
114
115/* s3c_pm_check_resume_pin 82/* s3c_pm_check_resume_pin
116 * 83 *
117 * check to see if the pin is configured correctly for sleep mode, and 84 * check to see if the pin is configured correctly for sleep mode, and
@@ -165,186 +132,6 @@ void s3c_pm_configure_extint(void)
165 } 132 }
166} 133}
167 134
168/* offsets for CON/DAT/UP registers */
169
170#define OFFS_CON (S3C2410_GPACON - S3C2410_GPACON)
171#define OFFS_DAT (S3C2410_GPADAT - S3C2410_GPACON)
172#define OFFS_UP (S3C2410_GPBUP - S3C2410_GPBCON)
173
174/* s3c_pm_save_gpios()
175 *
176 * Save the state of the GPIOs
177 */
178
179void s3c_pm_save_gpios(void)
180{
181 struct gpio_sleep *gps = gpio_save;
182 unsigned int gpio;
183
184 for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
185 void __iomem *base = gps->base;
186
187 gps->gpcon = __raw_readl(base + OFFS_CON);
188 gps->gpdat = __raw_readl(base + OFFS_DAT);
189
190 if (gpio > 0)
191 gps->gpup = __raw_readl(base + OFFS_UP);
192
193 }
194}
195
196/* Test whether the given masked+shifted bits of an GPIO configuration
197 * are one of the SFN (special function) modes. */
198
199static inline int is_sfn(unsigned long con)
200{
201 return (con == 2 || con == 3);
202}
203
204/* Test if the given masked+shifted GPIO configuration is an input */
205
206static inline int is_in(unsigned long con)
207{
208 return con == 0;
209}
210
211/* Test if the given masked+shifted GPIO configuration is an output */
212
213static inline int is_out(unsigned long con)
214{
215 return con == 1;
216}
217
218/**
219 * s3c2410_pm_restore_gpio() - restore the given GPIO bank
220 * @index: The number of the GPIO bank being resumed.
221 * @gps: The sleep confgiuration for the bank.
222 *
223 * Restore one of the GPIO banks that was saved during suspend. This is
224 * not as simple as once thought, due to the possibility of glitches
225 * from the order that the CON and DAT registers are set in.
226 *
227 * The three states the pin can be are {IN,OUT,SFN} which gives us 9
228 * combinations of changes to check. Three of these, if the pin stays
229 * in the same configuration can be discounted. This leaves us with
230 * the following:
231 *
232 * { IN => OUT } Change DAT first
233 * { IN => SFN } Change CON first
234 * { OUT => SFN } Change CON first, so new data will not glitch
235 * { OUT => IN } Change CON first, so new data will not glitch
236 * { SFN => IN } Change CON first
237 * { SFN => OUT } Change DAT first, so new data will not glitch [1]
238 *
239 * We do not currently deal with the UP registers as these control
240 * weak resistors, so a small delay in change should not need to bring
241 * these into the calculations.
242 *
243 * [1] this assumes that writing to a pin DAT whilst in SFN will set the
244 * state for when it is next output.
245 */
246
247static void s3c2410_pm_restore_gpio(int index, struct gpio_sleep *gps)
248{
249 void __iomem *base = gps->base;
250 unsigned long gps_gpcon = gps->gpcon;
251 unsigned long gps_gpdat = gps->gpdat;
252 unsigned long old_gpcon;
253 unsigned long old_gpdat;
254 unsigned long old_gpup = 0x0;
255 unsigned long gpcon;
256 int nr;
257
258 old_gpcon = __raw_readl(base + OFFS_CON);
259 old_gpdat = __raw_readl(base + OFFS_DAT);
260
261 if (base == S3C2410_GPACON) {
262 /* GPACON only has one bit per control / data and no PULLUPs.
263 * GPACON[x] = 0 => Output, 1 => SFN */
264
265 /* first set all SFN bits to SFN */
266
267 gpcon = old_gpcon | gps->gpcon;
268 __raw_writel(gpcon, base + OFFS_CON);
269
270 /* now set all the other bits */
271
272 __raw_writel(gps_gpdat, base + OFFS_DAT);
273 __raw_writel(gps_gpcon, base + OFFS_CON);
274 } else {
275 unsigned long old, new, mask;
276 unsigned long change_mask = 0x0;
277
278 old_gpup = __raw_readl(base + OFFS_UP);
279
280 /* Create a change_mask of all the items that need to have
281 * their CON value changed before their DAT value, so that
282 * we minimise the work between the two settings.
283 */
284
285 for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
286 old = (old_gpcon & mask) >> nr;
287 new = (gps_gpcon & mask) >> nr;
288
289 /* If there is no change, then skip */
290
291 if (old == new)
292 continue;
293
294 /* If both are special function, then skip */
295
296 if (is_sfn(old) && is_sfn(new))
297 continue;
298
299 /* Change is IN => OUT, do not change now */
300
301 if (is_in(old) && is_out(new))
302 continue;
303
304 /* Change is SFN => OUT, do not change now */
305
306 if (is_sfn(old) && is_out(new))
307 continue;
308
309 /* We should now be at the case of IN=>SFN,
310 * OUT=>SFN, OUT=>IN, SFN=>IN. */
311
312 change_mask |= mask;
313 }
314
315 /* Write the new CON settings */
316
317 gpcon = old_gpcon & ~change_mask;
318 gpcon |= gps_gpcon & change_mask;
319
320 __raw_writel(gpcon, base + OFFS_CON);
321
322 /* Now change any items that require DAT,CON */
323
324 __raw_writel(gps_gpdat, base + OFFS_DAT);
325 __raw_writel(gps_gpcon, base + OFFS_CON);
326 __raw_writel(gps->gpup, base + OFFS_UP);
327 }
328
329 S3C_PMDBG("GPIO[%d] CON %08lx => %08lx, DAT %08lx => %08lx\n",
330 index, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
331}
332
333
334/** s3c2410_pm_restore_gpios()
335 *
336 * Restore the state of the GPIOs
337 */
338
339void s3c_pm_restore_gpios(void)
340{
341 struct gpio_sleep *gps = gpio_save;
342 int gpio;
343
344 for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
345 s3c2410_pm_restore_gpio(gpio, gps);
346 }
347}
348 135
349void s3c_pm_restore_core(void) 136void s3c_pm_restore_core(void)
350{ 137{
diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig
index 9ce66151fd95..5ebd8b425a54 100644
--- a/arch/arm/plat-s3c64xx/Kconfig
+++ b/arch/arm/plat-s3c64xx/Kconfig
@@ -19,6 +19,7 @@ config PLAT_S3C64XX
19 select S3C_GPIO_PULL_UPDOWN 19 select S3C_GPIO_PULL_UPDOWN
20 select S3C_GPIO_CFG_S3C24XX 20 select S3C_GPIO_CFG_S3C24XX
21 select S3C_GPIO_CFG_S3C64XX 21 select S3C_GPIO_CFG_S3C64XX
22 select USB_ARCH_HAS_OHCI
22 help 23 help
23 Base platform code for any Samsung S3C64XX device 24 Base platform code for any Samsung S3C64XX device
24 25
@@ -63,4 +64,9 @@ config S3C64XX_SETUP_FB_24BPP
63 help 64 help
64 Common setup code for S3C64XX with an 24bpp RGB display helper. 65 Common setup code for S3C64XX with an 24bpp RGB display helper.
65 66
67config S3C64XX_SETUP_SDHCI_GPIO
68 bool
69 help
70 Common setup code for S3C64XX SDHCI GPIO configurations
71
66endif 72endif
diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile
index 61bdb67e2f6d..2ed5df34f9ea 100644
--- a/arch/arm/plat-s3c64xx/Makefile
+++ b/arch/arm/plat-s3c64xx/Makefile
@@ -24,6 +24,12 @@ obj-y += gpiolib.o
24obj-$(CONFIG_CPU_S3C6400_INIT) += s3c6400-init.o 24obj-$(CONFIG_CPU_S3C6400_INIT) += s3c6400-init.o
25obj-$(CONFIG_CPU_S3C6400_CLOCK) += s3c6400-clock.o 25obj-$(CONFIG_CPU_S3C6400_CLOCK) += s3c6400-clock.o
26 26
27# PM support
28
29obj-$(CONFIG_PM) += pm.o
30obj-$(CONFIG_PM) += sleep.o
31obj-$(CONFIG_PM) += irq-pm.o
32
27# DMA support 33# DMA support
28 34
29obj-$(CONFIG_S3C64XX_DMA) += dma.o 35obj-$(CONFIG_S3C64XX_DMA) += dma.o
@@ -33,3 +39,4 @@ obj-$(CONFIG_S3C64XX_DMA) += dma.o
33obj-$(CONFIG_S3C64XX_SETUP_I2C0) += setup-i2c0.o 39obj-$(CONFIG_S3C64XX_SETUP_I2C0) += setup-i2c0.o
34obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o 40obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o
35obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o 41obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o
42obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o \ No newline at end of file
diff --git a/arch/arm/plat-s3c64xx/clock.c b/arch/arm/plat-s3c64xx/clock.c
index ad1b9682c9c3..0bc2fa1dfc40 100644
--- a/arch/arm/plat-s3c64xx/clock.c
+++ b/arch/arm/plat-s3c64xx/clock.c
@@ -27,6 +27,12 @@
27#include <plat/devs.h> 27#include <plat/devs.h>
28#include <plat/clock.h> 28#include <plat/clock.h>
29 29
30struct clk clk_h2 = {
31 .name = "hclk2",
32 .id = -1,
33 .rate = 0,
34};
35
30struct clk clk_27m = { 36struct clk clk_27m = {
31 .name = "clk_27m", 37 .name = "clk_27m",
32 .id = -1, 38 .id = -1,
@@ -152,6 +158,18 @@ static struct clk init_clocks_disable[] = {
152 .parent = &clk_48m, 158 .parent = &clk_48m,
153 .enable = s3c64xx_sclk_ctrl, 159 .enable = s3c64xx_sclk_ctrl,
154 .ctrlbit = S3C_CLKCON_SCLK_MMC2_48, 160 .ctrlbit = S3C_CLKCON_SCLK_MMC2_48,
161 }, {
162 .name = "dma0",
163 .id = -1,
164 .parent = &clk_h,
165 .enable = s3c64xx_hclk_ctrl,
166 .ctrlbit = S3C_CLKCON_HCLK_DMA0,
167 }, {
168 .name = "dma1",
169 .id = -1,
170 .parent = &clk_h,
171 .enable = s3c64xx_hclk_ctrl,
172 .ctrlbit = S3C_CLKCON_HCLK_DMA1,
155 }, 173 },
156}; 174};
157 175
@@ -246,6 +264,7 @@ static struct clk *clks[] __initdata = {
246 &clk_epll, 264 &clk_epll,
247 &clk_27m, 265 &clk_27m,
248 &clk_48m, 266 &clk_48m,
267 &clk_h2,
249}; 268};
250 269
251void __init s3c64xx_register_clocks(void) 270void __init s3c64xx_register_clocks(void)
diff --git a/arch/arm/plat-s3c64xx/cpu.c b/arch/arm/plat-s3c64xx/cpu.c
index 91f49a3a665d..b1fdd83940a6 100644
--- a/arch/arm/plat-s3c64xx/cpu.c
+++ b/arch/arm/plat-s3c64xx/cpu.c
@@ -16,6 +16,7 @@
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/interrupt.h> 17#include <linux/interrupt.h>
18#include <linux/ioport.h> 18#include <linux/ioport.h>
19#include <linux/sysdev.h>
19#include <linux/serial_core.h> 20#include <linux/serial_core.h>
20#include <linux/platform_device.h> 21#include <linux/platform_device.h>
21#include <linux/io.h> 22#include <linux/io.h>
@@ -101,9 +102,24 @@ static struct map_desc s3c_iodesc[] __initdata = {
101 .pfn = __phys_to_pfn(S3C64XX_PA_MODEM), 102 .pfn = __phys_to_pfn(S3C64XX_PA_MODEM),
102 .length = SZ_4K, 103 .length = SZ_4K,
103 .type = MT_DEVICE, 104 .type = MT_DEVICE,
105 }, {
106 .virtual = (unsigned long)S3C_VA_WATCHDOG,
107 .pfn = __phys_to_pfn(S3C64XX_PA_WATCHDOG),
108 .length = SZ_4K,
109 .type = MT_DEVICE,
104 }, 110 },
105}; 111};
106 112
113
114struct sysdev_class s3c64xx_sysclass = {
115 .name = "s3c64xx-core",
116};
117
118static struct sys_device s3c64xx_sysdev = {
119 .cls = &s3c64xx_sysclass,
120};
121
122
107/* read cpu identification code */ 123/* read cpu identification code */
108 124
109void __init s3c64xx_init_io(struct map_desc *mach_desc, int size) 125void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
@@ -115,5 +131,21 @@ void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
115 iotable_init(mach_desc, size); 131 iotable_init(mach_desc, size);
116 132
117 idcode = __raw_readl(S3C_VA_SYS + 0x118); 133 idcode = __raw_readl(S3C_VA_SYS + 0x118);
134 if (!idcode) {
135 /* S3C6400 has the ID register in a different place,
136 * and needs a write before it can be read. */
137
138 __raw_writel(0x0, S3C_VA_SYS + 0xA1C);
139 idcode = __raw_readl(S3C_VA_SYS + 0xA1C);
140 }
141
118 s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids)); 142 s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
119} 143}
144
145static __init int s3c64xx_sysdev_init(void)
146{
147 sysdev_class_register(&s3c64xx_sysclass);
148 return sysdev_register(&s3c64xx_sysdev);
149}
150
151core_initcall(s3c64xx_sysdev_init);
diff --git a/arch/arm/plat-s3c64xx/gpiolib.c b/arch/arm/plat-s3c64xx/gpiolib.c
index ee9188add8fb..ccb82e854962 100644
--- a/arch/arm/plat-s3c64xx/gpiolib.c
+++ b/arch/arm/plat-s3c64xx/gpiolib.c
@@ -385,12 +385,19 @@ static __init void s3c64xx_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
385{ 385{
386 chip->chip.direction_input = s3c64xx_gpiolib_4bit_input; 386 chip->chip.direction_input = s3c64xx_gpiolib_4bit_input;
387 chip->chip.direction_output = s3c64xx_gpiolib_4bit_output; 387 chip->chip.direction_output = s3c64xx_gpiolib_4bit_output;
388 chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
388} 389}
389 390
390static __init void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip *chip) 391static __init void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
391{ 392{
392 chip->chip.direction_input = s3c64xx_gpiolib_4bit2_input; 393 chip->chip.direction_input = s3c64xx_gpiolib_4bit2_input;
393 chip->chip.direction_output = s3c64xx_gpiolib_4bit2_output; 394 chip->chip.direction_output = s3c64xx_gpiolib_4bit2_output;
395 chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
396}
397
398static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
399{
400 chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
394} 401}
395 402
396static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips, 403static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
@@ -412,7 +419,8 @@ static __init int s3c64xx_gpiolib_init(void)
412 s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2), 419 s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
413 s3c64xx_gpiolib_add_4bit2); 420 s3c64xx_gpiolib_add_4bit2);
414 421
415 s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit), NULL); 422 s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
423 s3c64xx_gpiolib_add_2bit);
416 424
417 return 0; 425 return 0;
418} 426}
diff --git a/arch/arm/plat-s3c64xx/include/plat/irqs.h b/arch/arm/plat-s3c64xx/include/plat/irqs.h
index f865bf4d709e..743a70094d04 100644
--- a/arch/arm/plat-s3c64xx/include/plat/irqs.h
+++ b/arch/arm/plat-s3c64xx/include/plat/irqs.h
@@ -157,6 +157,7 @@
157 157
158#define S3C_EINT(x) ((x) + S3C_IRQ_EINT_BASE) 158#define S3C_EINT(x) ((x) + S3C_IRQ_EINT_BASE)
159#define IRQ_EINT(x) S3C_EINT(x) 159#define IRQ_EINT(x) S3C_EINT(x)
160#define IRQ_EINT_BIT(x) ((x) - S3C_EINT(0))
160 161
161/* Next the external interrupt groups. These are similar to the IRQ_EINT(x) 162/* Next the external interrupt groups. These are similar to the IRQ_EINT(x)
162 * that they are sourced from the GPIO pins but with a different scheme for 163 * that they are sourced from the GPIO pins but with a different scheme for
diff --git a/arch/arm/plat-s3c64xx/include/plat/pm-core.h b/arch/arm/plat-s3c64xx/include/plat/pm-core.h
new file mode 100644
index 000000000000..d347de3ba0dc
--- /dev/null
+++ b/arch/arm/plat-s3c64xx/include/plat/pm-core.h
@@ -0,0 +1,98 @@
1/* linux/arch/arm/plat-s3c64xx/include/plat/pm-core.h
2 *
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
7 *
8 * S3C64XX - PM core support for arch/arm/plat-s3c/pm.c
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <plat/regs-gpio.h>
16
17static inline void s3c_pm_debug_init_uart(void)
18{
19 u32 tmp = __raw_readl(S3C_PCLK_GATE);
20
21 /* As a note, since the S3C64XX UARTs generally have multiple
22 * clock sources, we simply enable PCLK at the moment and hope
23 * that the resume settings for the UART are suitable for the
24 * use with PCLK.
25 */
26
27 tmp |= S3C_CLKCON_PCLK_UART0;
28 tmp |= S3C_CLKCON_PCLK_UART1;
29 tmp |= S3C_CLKCON_PCLK_UART2;
30 tmp |= S3C_CLKCON_PCLK_UART3;
31
32 __raw_writel(tmp, S3C_PCLK_GATE);
33 udelay(10);
34}
35
36static inline void s3c_pm_arch_prepare_irqs(void)
37{
38 /* VIC should have already been taken care of */
39
40 /* clear any pending EINT0 interrupts */
41 __raw_writel(__raw_readl(S3C64XX_EINT0PEND), S3C64XX_EINT0PEND);
42}
43
44static inline void s3c_pm_arch_stop_clocks(void)
45{
46}
47
48static inline void s3c_pm_arch_show_resume_irqs(void)
49{
50}
51
52/* make these defines, we currently do not have any need to change
53 * the IRQ wake controls depending on the CPU we are running on */
54
55#define s3c_irqwake_eintallow ((1 << 28) - 1)
56#define s3c_irqwake_intallow (0)
57
58static inline void s3c_pm_arch_update_uart(void __iomem *regs,
59 struct pm_uart_save *save)
60{
61 u32 ucon = __raw_readl(regs + S3C2410_UCON);
62 u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK;
63 u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK;
64 u32 new_ucon;
65 u32 delta;
66
67 /* S3C64XX UART blocks only support level interrupts, so ensure that
68 * when we restore unused UART blocks we force the level interrupt
69 * settigs. */
70 save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL;
71
72 /* We have a constraint on changing the clock type of the UART
73 * between UCLKx and PCLK, so ensure that when we restore UCON
74 * that the CLK field is correctly modified if the bootloader
75 * has changed anything.
76 */
77 if (ucon_clk != save_clk) {
78 new_ucon = save->ucon;
79 delta = ucon_clk ^ save_clk;
80
81 /* change from UCLKx => wrong PCLK,
82 * either UCLK can be tested for by a bit-test
83 * with UCLK0 */
84 if (ucon_clk & S3C6400_UCON_UCLK0 &&
85 !(save_clk & S3C6400_UCON_UCLK0) &&
86 delta & S3C6400_UCON_PCLK2) {
87 new_ucon &= ~S3C6400_UCON_UCLK0;
88 } else if (delta == S3C6400_UCON_PCLK2) {
89 /* as an precaution, don't change from
90 * PCLK2 => PCLK or vice-versa */
91 new_ucon ^= S3C6400_UCON_PCLK2;
92 }
93
94 S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n",
95 ucon, new_ucon, save->ucon);
96 save->ucon = new_ucon;
97 }
98}
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-clock.h b/arch/arm/plat-s3c64xx/include/plat/regs-clock.h
index b1082c163247..52836d41e333 100644
--- a/arch/arm/plat-s3c64xx/include/plat/regs-clock.h
+++ b/arch/arm/plat-s3c64xx/include/plat/regs-clock.h
@@ -32,6 +32,7 @@
32#define S3C_HCLK_GATE S3C_CLKREG(0x30) 32#define S3C_HCLK_GATE S3C_CLKREG(0x30)
33#define S3C_PCLK_GATE S3C_CLKREG(0x34) 33#define S3C_PCLK_GATE S3C_CLKREG(0x34)
34#define S3C_SCLK_GATE S3C_CLKREG(0x38) 34#define S3C_SCLK_GATE S3C_CLKREG(0x38)
35#define S3C_MEM0_GATE S3C_CLKREG(0x3C)
35 36
36/* CLKDIV0 */ 37/* CLKDIV0 */
37#define S3C6400_CLKDIV0_MFC_MASK (0xf << 28) 38#define S3C6400_CLKDIV0_MFC_MASK (0xf << 28)
diff --git a/arch/arm/plat-s3c64xx/include/plat/s3c6400.h b/arch/arm/plat-s3c64xx/include/plat/s3c6400.h
index 571eaa2e54f1..11f2e1e119b0 100644
--- a/arch/arm/plat-s3c64xx/include/plat/s3c6400.h
+++ b/arch/arm/plat-s3c64xx/include/plat/s3c6400.h
@@ -15,12 +15,13 @@
15/* Common init code for S3C6400 related SoCs */ 15/* Common init code for S3C6400 related SoCs */
16 16
17extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no); 17extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
18extern void s3c6400_register_clocks(void); 18extern void s3c6400_register_clocks(unsigned armclk_divlimit);
19extern void s3c6400_setup_clocks(void); 19extern void s3c6400_setup_clocks(void);
20 20
21#ifdef CONFIG_CPU_S3C6400 21#ifdef CONFIG_CPU_S3C6400
22 22
23extern int s3c6400_init(void); 23extern int s3c6400_init(void);
24extern void s3c6400_init_irq(void);
24extern void s3c6400_map_io(void); 25extern void s3c6400_map_io(void);
25extern void s3c6400_init_clocks(int xtal); 26extern void s3c6400_init_clocks(int xtal);
26 27
diff --git a/arch/arm/plat-s3c64xx/irq-eint.c b/arch/arm/plat-s3c64xx/irq-eint.c
index 47e5155bb13e..f81b7b818ba0 100644
--- a/arch/arm/plat-s3c64xx/irq-eint.c
+++ b/arch/arm/plat-s3c64xx/irq-eint.c
@@ -14,6 +14,7 @@
14 14
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/sysdev.h>
17#include <linux/gpio.h> 18#include <linux/gpio.h>
18#include <linux/irq.h> 19#include <linux/irq.h>
19#include <linux/io.h> 20#include <linux/io.h>
@@ -26,6 +27,7 @@
26 27
27#include <mach/map.h> 28#include <mach/map.h>
28#include <plat/cpu.h> 29#include <plat/cpu.h>
30#include <plat/pm.h>
29 31
30#define eint_offset(irq) ((irq) - IRQ_EINT(0)) 32#define eint_offset(irq) ((irq) - IRQ_EINT(0))
31#define eint_irq_to_bit(irq) (1 << eint_offset(irq)) 33#define eint_irq_to_bit(irq) (1 << eint_offset(irq))
@@ -134,6 +136,7 @@ static struct irq_chip s3c_irq_eint = {
134 .mask_ack = s3c_irq_eint_maskack, 136 .mask_ack = s3c_irq_eint_maskack,
135 .ack = s3c_irq_eint_ack, 137 .ack = s3c_irq_eint_ack,
136 .set_type = s3c_irq_eint_set_type, 138 .set_type = s3c_irq_eint_set_type,
139 .set_wake = s3c_irqext_wake,
137}; 140};
138 141
139/* s3c_irq_demux_eint 142/* s3c_irq_demux_eint
diff --git a/arch/arm/plat-s3c64xx/irq-pm.c b/arch/arm/plat-s3c64xx/irq-pm.c
new file mode 100644
index 000000000000..ca523b5d4c17
--- /dev/null
+++ b/arch/arm/plat-s3c64xx/irq-pm.c
@@ -0,0 +1,111 @@
1/* arch/arm/plat-s3c64xx/irq-pm.c
2 *
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
7 *
8 * S3C64XX - Interrupt handling Power Management
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/kernel.h>
16#include <linux/sysdev.h>
17#include <linux/interrupt.h>
18#include <linux/serial_core.h>
19#include <linux/irq.h>
20#include <linux/io.h>
21
22#include <mach/map.h>
23
24#include <plat/regs-serial.h>
25#include <plat/regs-timer.h>
26#include <plat/regs-gpio.h>
27#include <plat/cpu.h>
28#include <plat/pm.h>
29
30/* We handled all the IRQ types in this code, to save having to make several
31 * small files to handle each different type separately. Having the EINT_GRP
32 * code here shouldn't be as much bloat as the IRQ table space needed when
33 * they are enabled. The added benefit is we ensure that these registers are
34 * in the same state as we suspended.
35 */
36
37static struct sleep_save irq_save[] = {
38 SAVE_ITEM(S3C64XX_PRIORITY),
39 SAVE_ITEM(S3C64XX_EINT0CON0),
40 SAVE_ITEM(S3C64XX_EINT0CON1),
41 SAVE_ITEM(S3C64XX_EINT0FLTCON0),
42 SAVE_ITEM(S3C64XX_EINT0FLTCON1),
43 SAVE_ITEM(S3C64XX_EINT0FLTCON2),
44 SAVE_ITEM(S3C64XX_EINT0FLTCON3),
45 SAVE_ITEM(S3C64XX_EINT0MASK),
46 SAVE_ITEM(S3C64XX_TINT_CSTAT),
47};
48
49static struct irq_grp_save {
50 u32 fltcon;
51 u32 con;
52 u32 mask;
53} eint_grp_save[5];
54
55static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS];
56
57static int s3c64xx_irq_pm_suspend(struct sys_device *dev, pm_message_t state)
58{
59 struct irq_grp_save *grp = eint_grp_save;
60 int i;
61
62 S3C_PMDBG("%s: suspending IRQs\n", __func__);
63
64 s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
65
66 for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
67 irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM);
68
69 for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
70 grp->con = __raw_readl(S3C64XX_EINT12CON + (i * 4));
71 grp->mask = __raw_readl(S3C64XX_EINT12MASK + (i * 4));
72 grp->fltcon = __raw_readl(S3C64XX_EINT12FLTCON + (i * 4));
73 }
74
75 return 0;
76}
77
78static int s3c64xx_irq_pm_resume(struct sys_device *dev)
79{
80 struct irq_grp_save *grp = eint_grp_save;
81 int i;
82
83 S3C_PMDBG("%s: resuming IRQs\n", __func__);
84
85 s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
86
87 for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
88 __raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM);
89
90 for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
91 __raw_writel(grp->con, S3C64XX_EINT12CON + (i * 4));
92 __raw_writel(grp->mask, S3C64XX_EINT12MASK + (i * 4));
93 __raw_writel(grp->fltcon, S3C64XX_EINT12FLTCON + (i * 4));
94 }
95
96 S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
97 return 0;
98}
99
100static struct sysdev_driver s3c64xx_irq_driver = {
101 .suspend = s3c64xx_irq_pm_suspend,
102 .resume = s3c64xx_irq_pm_resume,
103};
104
105static int __init s3c64xx_irq_pm_init(void)
106{
107 return sysdev_driver_register(&s3c64xx_sysclass, &s3c64xx_irq_driver);
108}
109
110arch_initcall(s3c64xx_irq_pm_init);
111
diff --git a/arch/arm/plat-s3c64xx/irq.c b/arch/arm/plat-s3c64xx/irq.c
index f22edf7c2d2d..8dc5b6da9789 100644
--- a/arch/arm/plat-s3c64xx/irq.c
+++ b/arch/arm/plat-s3c64xx/irq.c
@@ -14,12 +14,14 @@
14 14
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/serial_core.h>
17#include <linux/irq.h> 18#include <linux/irq.h>
18#include <linux/io.h> 19#include <linux/io.h>
19 20
20#include <asm/hardware/vic.h> 21#include <asm/hardware/vic.h>
21 22
22#include <mach/map.h> 23#include <mach/map.h>
24#include <plat/regs-serial.h>
23#include <plat/regs-timer.h> 25#include <plat/regs-timer.h>
24#include <plat/cpu.h> 26#include <plat/cpu.h>
25 27
@@ -135,9 +137,6 @@ static inline unsigned int s3c_irq_uart_bit(unsigned int irq)
135} 137}
136 138
137/* UART interrupt registers, not worth adding to seperate include header */ 139/* UART interrupt registers, not worth adding to seperate include header */
138#define S3C64XX_UINTP 0x30
139#define S3C64XX_UINTSP 0x34
140#define S3C64XX_UINTM 0x38
141 140
142static void s3c_irq_uart_mask(unsigned int irq) 141static void s3c_irq_uart_mask(unsigned int irq)
143{ 142{
@@ -233,8 +232,8 @@ void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
233 printk(KERN_DEBUG "%s: initialising interrupts\n", __func__); 232 printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);
234 233
235 /* initialise the pair of VICs */ 234 /* initialise the pair of VICs */
236 vic_init(S3C_VA_VIC0, S3C_VIC0_BASE, vic0_valid); 235 vic_init(S3C_VA_VIC0, S3C_VIC0_BASE, vic0_valid, 0);
237 vic_init(S3C_VA_VIC1, S3C_VIC1_BASE, vic1_valid); 236 vic_init(S3C_VA_VIC1, S3C_VIC1_BASE, vic1_valid, 0);
238 237
239 /* add the timer sub-irqs */ 238 /* add the timer sub-irqs */
240 239
diff --git a/arch/arm/plat-s3c64xx/pm.c b/arch/arm/plat-s3c64xx/pm.c
new file mode 100644
index 000000000000..07a6516a4f3c
--- /dev/null
+++ b/arch/arm/plat-s3c64xx/pm.c
@@ -0,0 +1,175 @@
1/* linux/arch/arm/plat-s3c64xx/pm.c
2 *
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
7 *
8 * S3C64XX CPU PM support.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/init.h>
16#include <linux/suspend.h>
17#include <linux/serial_core.h>
18#include <linux/io.h>
19
20#include <mach/map.h>
21
22#include <plat/pm.h>
23#include <plat/regs-sys.h>
24#include <plat/regs-gpio.h>
25#include <plat/regs-clock.h>
26#include <plat/regs-syscon-power.h>
27#include <plat/regs-gpio-memport.h>
28
29#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
30#include <plat/gpio-bank-n.h>
31
32void s3c_pm_debug_smdkled(u32 set, u32 clear)
33{
34 unsigned long flags;
35 u32 reg;
36
37 local_irq_save(flags);
38 reg = __raw_readl(S3C64XX_GPNCON);
39 reg &= ~(S3C64XX_GPN_CONMASK(12) | S3C64XX_GPN_CONMASK(13) |
40 S3C64XX_GPN_CONMASK(14) | S3C64XX_GPN_CONMASK(15));
41 reg |= S3C64XX_GPN_OUTPUT(12) | S3C64XX_GPN_OUTPUT(13) |
42 S3C64XX_GPN_OUTPUT(14) | S3C64XX_GPN_OUTPUT(15);
43 __raw_writel(reg, S3C64XX_GPNCON);
44
45 reg = __raw_readl(S3C64XX_GPNDAT);
46 reg &= ~(clear << 12);
47 reg |= set << 12;
48 __raw_writel(reg, S3C64XX_GPNDAT);
49
50 local_irq_restore(flags);
51}
52#endif
53
54static struct sleep_save core_save[] = {
55 SAVE_ITEM(S3C_APLL_LOCK),
56 SAVE_ITEM(S3C_MPLL_LOCK),
57 SAVE_ITEM(S3C_EPLL_LOCK),
58 SAVE_ITEM(S3C_CLK_SRC),
59 SAVE_ITEM(S3C_CLK_DIV0),
60 SAVE_ITEM(S3C_CLK_DIV1),
61 SAVE_ITEM(S3C_CLK_DIV2),
62 SAVE_ITEM(S3C_CLK_OUT),
63 SAVE_ITEM(S3C_HCLK_GATE),
64 SAVE_ITEM(S3C_PCLK_GATE),
65 SAVE_ITEM(S3C_SCLK_GATE),
66 SAVE_ITEM(S3C_MEM0_GATE),
67
68 SAVE_ITEM(S3C_EPLL_CON1),
69 SAVE_ITEM(S3C_EPLL_CON0),
70
71 SAVE_ITEM(S3C64XX_MEM0DRVCON),
72 SAVE_ITEM(S3C64XX_MEM1DRVCON),
73
74#ifndef CONFIG_CPU_FREQ
75 SAVE_ITEM(S3C_APLL_CON),
76 SAVE_ITEM(S3C_MPLL_CON),
77#endif
78};
79
80static struct sleep_save misc_save[] = {
81 SAVE_ITEM(S3C64XX_AHB_CON0),
82 SAVE_ITEM(S3C64XX_AHB_CON1),
83 SAVE_ITEM(S3C64XX_AHB_CON2),
84
85 SAVE_ITEM(S3C64XX_SPCON),
86
87 SAVE_ITEM(S3C64XX_MEM0CONSTOP),
88 SAVE_ITEM(S3C64XX_MEM1CONSTOP),
89 SAVE_ITEM(S3C64XX_MEM0CONSLP0),
90 SAVE_ITEM(S3C64XX_MEM0CONSLP1),
91 SAVE_ITEM(S3C64XX_MEM1CONSLP),
92};
93
94void s3c_pm_configure_extint(void)
95{
96 __raw_writel(s3c_irqwake_eintmask, S3C64XX_EINT_MASK);
97}
98
99void s3c_pm_restore_core(void)
100{
101 __raw_writel(0, S3C64XX_EINT_MASK);
102
103 s3c_pm_debug_smdkled(1 << 2, 0);
104
105 s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
106 s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
107}
108
109void s3c_pm_save_core(void)
110{
111 s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
112 s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
113}
114
115/* since both s3c6400 and s3c6410 share the same sleep pm calls, we
116 * put the per-cpu code in here until any new cpu comes along and changes
117 * this.
118 */
119
120#include <plat/regs-gpio.h>
121
122static void s3c64xx_cpu_suspend(void)
123{
124 unsigned long tmp;
125
126 /* set our standby method to sleep */
127
128 tmp = __raw_readl(S3C64XX_PWR_CFG);
129 tmp &= ~S3C64XX_PWRCFG_CFG_WFI_MASK;
130 tmp |= S3C64XX_PWRCFG_CFG_WFI_SLEEP;
131 __raw_writel(tmp, S3C64XX_PWR_CFG);
132
133 /* clear any old wakeup */
134
135 __raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT),
136 S3C64XX_WAKEUP_STAT);
137
138 /* set the LED state to 0110 over sleep */
139 s3c_pm_debug_smdkled(3 << 1, 0xf);
140
141 /* issue the standby signal into the pm unit. Note, we
142 * issue a write-buffer drain just in case */
143
144 tmp = 0;
145
146 asm("b 1f\n\t"
147 ".align 5\n\t"
148 "1:\n\t"
149 "mcr p15, 0, %0, c7, c10, 5\n\t"
150 "mcr p15, 0, %0, c7, c10, 4\n\t"
151 "mcr p15, 0, %0, c7, c0, 4" :: "r" (tmp));
152
153 /* we should never get past here */
154
155 panic("sleep resumed to originator?");
156}
157
158static void s3c64xx_pm_prepare(void)
159{
160 /* store address of resume. */
161 __raw_writel(virt_to_phys(s3c_cpu_resume), S3C64XX_INFORM0);
162
163 /* ensure previous wakeup state is cleared before sleeping */
164 __raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT), S3C64XX_WAKEUP_STAT);
165}
166
167static int s3c64xx_pm_init(void)
168{
169 pm_cpu_prep = s3c64xx_pm_prepare;
170 pm_cpu_sleep = s3c64xx_cpu_suspend;
171 pm_uart_udivslot = 1;
172 return 0;
173}
174
175arch_initcall(s3c64xx_pm_init);
diff --git a/arch/arm/plat-s3c64xx/s3c6400-clock.c b/arch/arm/plat-s3c64xx/s3c6400-clock.c
index 05b17528041e..1debc1f9f987 100644
--- a/arch/arm/plat-s3c64xx/s3c6400-clock.c
+++ b/arch/arm/plat-s3c64xx/s3c6400-clock.c
@@ -133,6 +133,65 @@ static struct clksrc_clk clk_mout_mpll = {
133 .sources = &clk_src_mpll, 133 .sources = &clk_src_mpll,
134}; 134};
135 135
136static unsigned int armclk_mask;
137
138static unsigned long s3c64xx_clk_arm_get_rate(struct clk *clk)
139{
140 unsigned long rate = clk_get_rate(clk->parent);
141 u32 clkdiv;
142
143 /* divisor mask starts at bit0, so no need to shift */
144 clkdiv = __raw_readl(S3C_CLK_DIV0) & armclk_mask;
145
146 return rate / (clkdiv + 1);
147}
148
149static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk,
150 unsigned long rate)
151{
152 unsigned long parent = clk_get_rate(clk->parent);
153 u32 div;
154
155 if (parent < rate)
156 return rate;
157
158 div = (parent / rate) - 1;
159 if (div > armclk_mask)
160 div = armclk_mask;
161
162 return parent / (div + 1);
163}
164
165static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
166{
167 unsigned long parent = clk_get_rate(clk->parent);
168 u32 div;
169 u32 val;
170
171 if (rate < parent / (armclk_mask + 1))
172 return -EINVAL;
173
174 rate = clk_round_rate(clk, rate);
175 div = clk_get_rate(clk->parent) / rate;
176
177 val = __raw_readl(S3C_CLK_DIV0);
178 val &= armclk_mask;
179 val |= (div - 1);
180 __raw_writel(val, S3C_CLK_DIV0);
181
182 return 0;
183
184}
185
186static struct clk clk_arm = {
187 .name = "armclk",
188 .id = -1,
189 .parent = &clk_mout_apll.clk,
190 .get_rate = s3c64xx_clk_arm_get_rate,
191 .set_rate = s3c64xx_clk_arm_set_rate,
192 .round_rate = s3c64xx_clk_arm_round_rate,
193};
194
136static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk) 195static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
137{ 196{
138 unsigned long rate = clk_get_rate(clk->parent); 197 unsigned long rate = clk_get_rate(clk->parent);
@@ -520,6 +579,33 @@ static struct clksrc_clk clk_irda = {
520 .reg_divider = S3C_CLK_DIV2, 579 .reg_divider = S3C_CLK_DIV2,
521}; 580};
522 581
582static struct clk *clkset_camif_list[] = {
583 &clk_h2,
584};
585
586static struct clk_sources clkset_camif = {
587 .sources = clkset_camif_list,
588 .nr_sources = ARRAY_SIZE(clkset_camif_list),
589};
590
591static struct clksrc_clk clk_camif = {
592 .clk = {
593 .name = "camera",
594 .id = -1,
595 .ctrlbit = S3C_CLKCON_SCLK_CAM,
596 .enable = s3c64xx_sclk_ctrl,
597 .set_parent = s3c64xx_setparent_clksrc,
598 .get_rate = s3c64xx_getrate_clksrc,
599 .set_rate = s3c64xx_setrate_clksrc,
600 .round_rate = s3c64xx_roundrate_clksrc,
601 },
602 .shift = 0,
603 .mask = 0,
604 .sources = &clkset_camif,
605 .divider_shift = S3C6400_CLKDIV0_CAM_SHIFT,
606 .reg_divider = S3C_CLK_DIV0,
607};
608
523/* Clock initialisation code */ 609/* Clock initialisation code */
524 610
525static struct clksrc_clk *init_parents[] = { 611static struct clksrc_clk *init_parents[] = {
@@ -536,6 +622,7 @@ static struct clksrc_clk *init_parents[] = {
536 &clk_audio0, 622 &clk_audio0,
537 &clk_audio1, 623 &clk_audio1,
538 &clk_irda, 624 &clk_irda,
625 &clk_camif,
539}; 626};
540 627
541static void __init_or_cpufreq s3c6400_set_clksrc(struct clksrc_clk *clk) 628static void __init_or_cpufreq s3c6400_set_clksrc(struct clksrc_clk *clk)
@@ -608,6 +695,7 @@ void __init_or_cpufreq s3c6400_setup_clocks(void)
608 clk_fout_epll.rate = epll; 695 clk_fout_epll.rate = epll;
609 clk_fout_apll.rate = apll; 696 clk_fout_apll.rate = apll;
610 697
698 clk_h2.rate = hclk2;
611 clk_h.rate = hclk; 699 clk_h.rate = hclk;
612 clk_p.rate = pclk; 700 clk_p.rate = pclk;
613 clk_f.rate = fclk; 701 clk_f.rate = fclk;
@@ -635,14 +723,30 @@ static struct clk *clks[] __initdata = {
635 &clk_audio0.clk, 723 &clk_audio0.clk,
636 &clk_audio1.clk, 724 &clk_audio1.clk,
637 &clk_irda.clk, 725 &clk_irda.clk,
726 &clk_camif.clk,
727 &clk_arm,
638}; 728};
639 729
640void __init s3c6400_register_clocks(void) 730/**
731 * s3c6400_register_clocks - register clocks for s3c6400 and above
732 * @armclk_divlimit: Divisor mask for ARMCLK
733 *
734 * Register the clocks for the S3C6400 and above SoC range, such
735 * as ARMCLK and the clocks which have divider chains attached.
736 *
737 * This call does not setup the clocks, which is left to the
738 * s3c6400_setup_clocks() call which may be needed by the cpufreq
739 * or resume code to re-set the clocks if the bootloader has changed
740 * them.
741 */
742void __init s3c6400_register_clocks(unsigned armclk_divlimit)
641{ 743{
642 struct clk *clkp; 744 struct clk *clkp;
643 int ret; 745 int ret;
644 int ptr; 746 int ptr;
645 747
748 armclk_mask = armclk_divlimit;
749
646 for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) { 750 for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
647 clkp = clks[ptr]; 751 clkp = clks[ptr];
648 ret = s3c24xx_register_clock(clkp); 752 ret = s3c24xx_register_clock(clkp);
diff --git a/arch/arm/plat-s3c64xx/setup-sdhci-gpio.c b/arch/arm/plat-s3c64xx/setup-sdhci-gpio.c
new file mode 100644
index 000000000000..5417123b0ac1
--- /dev/null
+++ b/arch/arm/plat-s3c64xx/setup-sdhci-gpio.c
@@ -0,0 +1,55 @@
1/* linux/arch/arm/plat-s3c64xx/setup-sdhci-gpio.c
2 *
3 * Copyright 2008 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 * http://armlinux.simtec.co.uk/
6 *
7 * S3C64XX - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12*/
13
14#include <linux/kernel.h>
15#include <linux/types.h>
16#include <linux/interrupt.h>
17#include <linux/platform_device.h>
18#include <linux/io.h>
19
20#include <mach/gpio.h>
21#include <plat/gpio-cfg.h>
22
23void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
24{
25 unsigned int gpio;
26 unsigned int end;
27
28 end = S3C64XX_GPG(2 + width);
29
30 /* Set all the necessary GPG pins to special-function 0 */
31 for (gpio = S3C64XX_GPG(0); gpio < end; gpio++) {
32 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
33 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
34 }
35
36 s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
37 s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(2));
38}
39
40void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
41{
42 unsigned int gpio;
43 unsigned int end;
44
45 end = S3C64XX_GPH(2 + width);
46
47 /* Set all the necessary GPG pins to special-function 0 */
48 for (gpio = S3C64XX_GPH(0); gpio < end; gpio++) {
49 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
50 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
51 }
52
53 s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
54 s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(3));
55}
diff --git a/arch/arm/plat-s3c64xx/sleep.S b/arch/arm/plat-s3c64xx/sleep.S
new file mode 100644
index 000000000000..8e71fe90a373
--- /dev/null
+++ b/arch/arm/plat-s3c64xx/sleep.S
@@ -0,0 +1,144 @@
1/* linux/0arch/arm/plat-s3c64xx/sleep.S
2 *
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
7 *
8 * S3C64XX CPU sleep code
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/linkage.h>
16#include <asm/assembler.h>
17#include <mach/map.h>
18
19#undef S3C64XX_VA_GPIO
20#define S3C64XX_VA_GPIO (0x0)
21
22#include <plat/regs-gpio.h>
23#include <plat/gpio-bank-n.h>
24
25#define LL_UART (S3C_PA_UART + (0x400 * CONFIG_S3C_LOWLEVEL_UART_PORT))
26
27 .text
28
29 /* s3c_cpu_save
30 *
31 * Save enough processor state to allow the restart of the pm.c
32 * code after resume.
33 *
34 * entry:
35 * r0 = pointer to the save block
36 */
37
38ENTRY(s3c_cpu_save)
39 stmfd sp!, { r4 - r12, lr }
40
41 mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
42 mrc p15, 0, r5, c3, c0, 0 @ Domain ID
43 mrc p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
44 mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
45 mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control
46 mrc p15, 0, r9, c1, c0, 0 @ Control register
47 mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register
48 mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls
49
50 stmia r0, { r4 - r13 } @ Save CP registers and SP
51
52 @@ save our state to ram
53 bl s3c_pm_cb_flushcache
54
55 @@ call final suspend code
56 ldr r0, =pm_cpu_sleep
57 ldr pc, [r0]
58
59 @@ return to the caller, after the MMU is turned on.
60 @@ restore the last bits of the stack and return.
61resume_with_mmu:
62 ldmfd sp!, { r4 - r12, pc } @ return, from sp from s3c_cpu_save
63
64 .data
65
66 /* the next bit is code, but it requires easy access to the
67 * s3c_sleep_save_phys data before the MMU is switched on, so
68 * we store the code that needs this variable in the .data where
69 * the value can be written to (the .text segment is RO).
70 */
71
72 .global s3c_sleep_save_phys
73s3c_sleep_save_phys:
74 .word 0
75
76 /* Sleep magic, the word before the resume entry point so that the
77 * bootloader can check for a resumeable image. */
78
79 .word 0x2bedf00d
80
81 /* s3c_cpu_reusme
82 *
83 * This is the entry point, stored by whatever method the bootloader
84 * requires to get the kernel runnign again. This code expects to be
85 * entered with no caches live and the MMU disabled. It will then
86 * restore the MMU and other basic CP registers saved and restart
87 * the kernel C code to finish the resume code.
88 */
89
90ENTRY(s3c_cpu_resume)
91 msr cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
92 ldr r2, =LL_UART /* for debug */
93
94#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
95 /* Initialise the GPIO state if we are debugging via the SMDK LEDs,
96 * as the uboot version supplied resets these to inputs during the
97 * resume checks.
98 */
99
100 ldr r3, =S3C64XX_PA_GPIO
101 ldr r0, [ r3, #S3C64XX_GPNCON ]
102 bic r0, r0, #(S3C64XX_GPN_CONMASK(12) | S3C64XX_GPN_CONMASK(13) | \
103 S3C64XX_GPN_CONMASK(14) | S3C64XX_GPN_CONMASK(15))
104 orr r0, r0, #(S3C64XX_GPN_OUTPUT(12) | S3C64XX_GPN_OUTPUT(13) | \
105 S3C64XX_GPN_OUTPUT(14) | S3C64XX_GPN_OUTPUT(15))
106 str r0, [ r3, #S3C64XX_GPNCON ]
107
108 ldr r0, [ r3, #S3C64XX_GPNDAT ]
109 bic r0, r0, #0xf << 12 @ GPN12..15
110 orr r0, r0, #1 << 15 @ GPN15
111 str r0, [ r3, #S3C64XX_GPNDAT ]
112#endif
113
114 /* __v6_setup from arch/arm/mm/proc-v6.S, ensure that the caches
115 * are thoroughly cleaned just in case the bootloader didn't do it
116 * for us. */
117 mov r0, #0
118 mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache
119 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
120 mcr p15, 0, r0, c7, c15, 0 @ clean+invalidate cache
121 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
122 @@mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
123 @@mcr p15, 0, r0, c7, c7, 0 @ Invalidate I + D caches
124
125 ldr r0, s3c_sleep_save_phys
126 ldmia r0, { r4 - r13 }
127
128 mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
129 mcr p15, 0, r5, c3, c0, 0 @ Domain ID
130 mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
131 mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
132 mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control
133 mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register
134
135 mov r0, #0 @ restore copro access controls
136 mcr p15, 0, r11, c1, c0, 2 @ Co-processor access controls
137 mcr p15, 0, r0, c7, c5, 4
138
139 ldr r2, =resume_with_mmu
140 mcr p15, 0, r9, c1, c0, 0 /* turn mmu back on */
141 nop
142 mov pc, r2 /* jump back */
143
144 .end