aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s3c24xx
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-s3c24xx')
-rw-r--r--arch/arm/mach-s3c24xx/Kconfig169
-rw-r--r--arch/arm/mach-s3c24xx/Makefile17
-rw-r--r--arch/arm/mach-s3c24xx/clock-s3c2440.c194
-rw-r--r--arch/arm/mach-s3c24xx/clock-s3c244x.c141
-rw-r--r--arch/arm/mach-s3c24xx/common.h6
-rw-r--r--arch/arm/mach-s3c24xx/dma-s3c2440.c196
-rw-r--r--arch/arm/mach-s3c24xx/include/mach/gta02.h84
-rw-r--r--arch/arm/mach-s3c24xx/irq-s3c2440.c128
-rw-r--r--arch/arm/mach-s3c24xx/irq-s3c244x.c142
-rw-r--r--arch/arm/mach-s3c24xx/mach-anubis.c491
-rw-r--r--arch/arm/mach-s3c24xx/mach-at2440evb.c226
-rw-r--r--arch/arm/mach-s3c24xx/mach-gta02.c605
-rw-r--r--arch/arm/mach-s3c24xx/mach-mini2440.c705
-rw-r--r--arch/arm/mach-s3c24xx/mach-nexcoder.c162
-rw-r--r--arch/arm/mach-s3c24xx/mach-osiris-dvs.c194
-rw-r--r--arch/arm/mach-s3c24xx/mach-osiris.c440
-rw-r--r--arch/arm/mach-s3c24xx/mach-rx1950.c826
-rw-r--r--arch/arm/mach-s3c24xx/mach-rx3715.c217
-rw-r--r--arch/arm/mach-s3c24xx/mach-smdk2440.c187
-rw-r--r--arch/arm/mach-s3c24xx/s3c2440.c88
-rw-r--r--arch/arm/mach-s3c24xx/s3c2442.c188
-rw-r--r--arch/arm/mach-s3c24xx/s3c244x.c198
22 files changed, 5602 insertions, 2 deletions
diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig
index 9dda29e82bbe..d8d156c0881c 100644
--- a/arch/arm/mach-s3c24xx/Kconfig
+++ b/arch/arm/mach-s3c24xx/Kconfig
@@ -47,12 +47,35 @@ config CPU_S3C2416
47 help 47 help
48 Support for the S3C2416 SoC from the S3C24XX line 48 Support for the S3C2416 SoC from the S3C24XX line
49 49
50config CPU_S3C2440
51 bool "SAMSUNG S3C2440"
52 select CPU_ARM920T
53 select CPU_LLSERIAL_S3C2440
54 select S3C2410_CLOCK
55 select S3C2410_PM if PM
56 select S3C2440_DMA if S3C24XX_DMA
57 help
58 Support for S3C2440 Samsung Mobile CPU based systems.
59
60config CPU_S3C2442
61 bool "SAMSUNG S3C2442"
62 select CPU_ARM920T
63 select CPU_LLSERIAL_S3C2440
64 select S3C2410_CLOCK
65 select S3C2410_PM if PM
66 help
67 Support for S3C2442 Samsung Mobile CPU based systems.
68
69config CPU_S3C244X
70 def_bool y
71 depends on CPU_S3C2440 || CPU_S3C2442
72
50if CPU_S3C2410 73if CPU_S3C2410
51 74
52config S3C2410_DMA 75config S3C2410_DMA
53 bool 76 bool
54 depends on S3C24XX_DMA && CPU_S3C2410 77 depends on S3C24XX_DMA && (CPU_S3C2410 || CPU_S3C2442)
55 default y if CPU_S3C2410 78 default y if CPU_S3C2410 || CPU_S3C2442
56 help 79 help
57 DMA device selection for S3C2410 and compatible CPUs 80 DMA device selection for S3C2410 and compatible CPUs
58 81
@@ -295,6 +318,148 @@ config MACH_SMDK2416
295 318
296endif # CPU_S3C2416 319endif # CPU_S3C2416
297 320
321if CPU_S3C2440
322
323config S3C2440_DMA
324 bool
325 help
326 Support for S3C2440 specific DMA code5A
327
328comment "S3C2440 Boards"
329
330#
331# The "S3C2440 Boards" list is ordered alphabetically by option text.
332# (without ARCH_ or MACH_)
333#
334
335config MACH_ANUBIS
336 bool "Simtec Electronics ANUBIS"
337 select S3C24XX_DCLK
338 select PM_SIMTEC if PM
339 select HAVE_PATA_PLATFORM
340 select S3C24XX_GPIO_EXTRA64
341 select S3C2440_XTAL_12000000
342 select S3C_DEV_USB_HOST
343 help
344 Say Y here if you are using the Simtec Electronics ANUBIS
345 development system
346
347config MACH_AT2440EVB
348 bool "Avantech AT2440EVB development board"
349 select S3C_DEV_USB_HOST
350 select S3C_DEV_NAND
351 help
352 Say Y here if you are using the AT2440EVB development board
353
354config MACH_MINI2440
355 bool "MINI2440 development board"
356 select EEPROM_AT24
357 select NEW_LEDS
358 select LEDS_CLASS
359 select LEDS_TRIGGER
360 select LEDS_TRIGGER_BACKLIGHT
361 select S3C_DEV_NAND
362 select S3C_DEV_USB_HOST
363 help
364 Say Y here to select support for the MINI2440. Is a 10cm x 10cm board
365 available via various sources. It can come with a 3.5" or 7" touch LCD.
366
367config MACH_NEXCODER_2440
368 bool "NexVision NEXCODER 2440 Light Board"
369 select S3C2440_XTAL_12000000
370 select S3C_DEV_USB_HOST
371 select S3C_DEV_NAND
372 help
373 Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
374
375config MACH_OSIRIS
376 bool "Simtec IM2440D20 (OSIRIS) module"
377 select S3C24XX_DCLK
378 select PM_SIMTEC if PM
379 select S3C24XX_GPIO_EXTRA128
380 select S3C2440_XTAL_12000000
381 select S3C2410_IOTIMING if S3C2440_CPUFREQ
382 select S3C_DEV_USB_HOST
383 select S3C_DEV_NAND
384 help
385 Say Y here if you are using the Simtec IM2440D20 module, also
386 known as the Osiris.
387
388config MACH_OSIRIS_DVS
389 tristate "Simtec IM2440D20 (OSIRIS) Dynamic Voltage Scaling driver"
390 depends on MACH_OSIRIS
391 select TPS65010
392 help
393 Say Y/M here if you want to have dynamic voltage scaling support
394 on the Simtec IM2440D20 (OSIRIS) module via the TPS65011.
395
396 The DVS driver alters the voltage supplied to the ARM core
397 depending on the frequency it is running at. The driver itself
398 does not do any of the frequency alteration, which is left up
399 to the cpufreq driver.
400
401config MACH_RX3715
402 bool "HP iPAQ rx3715"
403 select S3C2440_XTAL_16934400
404 select PM_H1940 if PM
405 select S3C_DEV_NAND
406 help
407 Say Y here if you are using the HP iPAQ rx3715.
408
409config ARCH_S3C2440
410 bool "SMDK2440"
411 select S3C2440_XTAL_16934400
412 select MACH_SMDK
413 select S3C_DEV_USB_HOST
414 select S3C_DEV_NAND
415 help
416 Say Y here if you are using the SMDK2440.
417
418config SMDK2440_CPU2440
419 bool "SMDK2440 with S3C2440 CPU module"
420 default y if ARCH_S3C2440
421 select S3C2440_XTAL_16934400
422
423endif # CPU_S3C2440
424
425if CPU_S3C2442
426
427comment "S3C2442 Boards"
428
429#
430# The "S3C2442 Boards" list is ordered alphabetically by option text.
431# (without ARCH_ or MACH_)
432#
433
434config MACH_NEO1973_GTA02
435 bool "Openmoko GTA02 / Freerunner phone"
436 select MFD_PCF50633
437 select PCF50633_GPIO
438 select I2C
439 select POWER_SUPPLY
440 select MACH_NEO1973
441 select S3C2410_PWM
442 select S3C_DEV_USB_HOST
443 help
444 Say Y here if you are using the Openmoko GTA02 / Freerunner GSM Phone
445
446config MACH_RX1950
447 bool "HP iPAQ rx1950"
448 select S3C24XX_DCLK
449 select PM_H1940 if PM
450 select I2C
451 select S3C2410_PWM
452 select S3C_DEV_NAND
453 select S3C2410_IOTIMING if S3C2440_CPUFREQ
454 select S3C2440_XTAL_16934400
455 help
456 Say Y here if you're using HP iPAQ rx1950
457
458config SMDK2440_CPU2442
459 bool "SMDM2440 with S3C2442 CPU module"
460
461endif # CPU_S3C2440
462
298endmenu # SAMSUNG S3C24XX SoCs Support 463endmenu # SAMSUNG S3C24XX SoCs Support
299 464
300endif # ARCH_S3C24XX 465endif # ARCH_S3C24XX
diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile
index 789aa5ca4e01..f458cf2e1dd8 100644
--- a/arch/arm/mach-s3c24xx/Makefile
+++ b/arch/arm/mach-s3c24xx/Makefile
@@ -26,6 +26,11 @@ obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o
26obj-$(CONFIG_CPU_S3C2416) += s3c2416.o irq-s3c2416.o clock-s3c2416.o 26obj-$(CONFIG_CPU_S3C2416) += s3c2416.o irq-s3c2416.o clock-s3c2416.o
27obj-$(CONFIG_S3C2416_PM) += pm-s3c2416.o 27obj-$(CONFIG_S3C2416_PM) += pm-s3c2416.o
28 28
29obj-$(CONFIG_CPU_S3C2440) += s3c2440.o irq-s3c2440.o clock-s3c2440.o
30obj-$(CONFIG_CPU_S3C2442) += s3c2442.o
31obj-$(CONFIG_CPU_S3C244X) += s3c244x.o irq-s3c244x.o clock-s3c244x.o
32obj-$(CONFIG_S3C2440_DMA) += dma-s3c2440.o
33
29# 34#
30# machine support 35# machine support
31# following is ordered alphabetically by option text. 36# following is ordered alphabetically by option text.
@@ -50,6 +55,17 @@ obj-$(CONFIG_MACH_VSTMS) += mach-vstms.o
50 55
51obj-$(CONFIG_MACH_SMDK2416) += mach-smdk2416.o 56obj-$(CONFIG_MACH_SMDK2416) += mach-smdk2416.o
52 57
58obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o
59obj-$(CONFIG_MACH_AT2440EVB) += mach-at2440evb.o
60obj-$(CONFIG_MACH_MINI2440) += mach-mini2440.o
61obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
62obj-$(CONFIG_MACH_OSIRIS) += mach-osiris.o
63obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o
64obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o
65
66obj-$(CONFIG_MACH_NEO1973_GTA02) += mach-gta02.o
67obj-$(CONFIG_MACH_RX1950) += mach-rx1950.o
68
53# common bits of machine support 69# common bits of machine support
54 70
55obj-$(CONFIG_SIMTEC_NOR) += nor-simtec.o 71obj-$(CONFIG_SIMTEC_NOR) += nor-simtec.o
@@ -57,6 +73,7 @@ obj-$(CONFIG_SIMTEC_NOR) += nor-simtec.o
57# machine additions 73# machine additions
58 74
59obj-$(CONFIG_MACH_BAST_IDE) += bast-ide.o 75obj-$(CONFIG_MACH_BAST_IDE) += bast-ide.o
76obj-$(CONFIG_MACH_OSIRIS_DVS) += mach-osiris-dvs.o
60 77
61# device setup 78# device setup
62 79
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2440.c b/arch/arm/mach-s3c24xx/clock-s3c2440.c
new file mode 100644
index 000000000000..bedbc87a3426
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/clock-s3c2440.c
@@ -0,0 +1,194 @@
1/* linux/arch/arm/mach-s3c2440/clock.c
2 *
3 * Copyright (c) 2004-2005 Simtec Electronics
4 * http://armlinux.simtec.co.uk/
5 * Ben Dooks <ben@simtec.co.uk>
6 *
7 * S3C2440 Clock support
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 as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22*/
23
24#include <linux/init.h>
25#include <linux/module.h>
26#include <linux/kernel.h>
27#include <linux/list.h>
28#include <linux/errno.h>
29#include <linux/err.h>
30#include <linux/device.h>
31#include <linux/interrupt.h>
32#include <linux/ioport.h>
33#include <linux/mutex.h>
34#include <linux/clk.h>
35#include <linux/io.h>
36#include <linux/serial_core.h>
37
38#include <mach/hardware.h>
39#include <linux/atomic.h>
40#include <asm/irq.h>
41
42#include <mach/regs-clock.h>
43
44#include <plat/clock.h>
45#include <plat/cpu.h>
46#include <plat/regs-serial.h>
47
48/* S3C2440 extended clock support */
49
50static unsigned long s3c2440_camif_upll_round(struct clk *clk,
51 unsigned long rate)
52{
53 unsigned long parent_rate = clk_get_rate(clk->parent);
54 int div;
55
56 if (rate > parent_rate)
57 return parent_rate;
58
59 /* note, we remove the +/- 1 calculations for the divisor */
60
61 div = (parent_rate / rate) / 2;
62
63 if (div < 1)
64 div = 1;
65 else if (div > 16)
66 div = 16;
67
68 return parent_rate / (div * 2);
69}
70
71static int s3c2440_camif_upll_setrate(struct clk *clk, unsigned long rate)
72{
73 unsigned long parent_rate = clk_get_rate(clk->parent);
74 unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
75
76 rate = s3c2440_camif_upll_round(clk, rate);
77
78 camdivn &= ~(S3C2440_CAMDIVN_CAMCLK_SEL | S3C2440_CAMDIVN_CAMCLK_MASK);
79
80 if (rate != parent_rate) {
81 camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
82 camdivn |= (((parent_rate / rate) / 2) - 1);
83 }
84
85 __raw_writel(camdivn, S3C2440_CAMDIVN);
86
87 return 0;
88}
89
90/* Extra S3C2440 clocks */
91
92static struct clk s3c2440_clk_cam = {
93 .name = "camif",
94 .enable = s3c2410_clkcon_enable,
95 .ctrlbit = S3C2440_CLKCON_CAMERA,
96};
97
98static struct clk s3c2440_clk_cam_upll = {
99 .name = "camif-upll",
100 .ops = &(struct clk_ops) {
101 .set_rate = s3c2440_camif_upll_setrate,
102 .round_rate = s3c2440_camif_upll_round,
103 },
104};
105
106static struct clk s3c2440_clk_ac97 = {
107 .name = "ac97",
108 .enable = s3c2410_clkcon_enable,
109 .ctrlbit = S3C2440_CLKCON_CAMERA,
110};
111
112static unsigned long s3c2440_fclk_n_getrate(struct clk *clk)
113{
114 unsigned long ucon0, ucon1, ucon2, divisor;
115
116 /* the fun of calculating the uart divisors on the s3c2440 */
117 ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON);
118 ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON);
119 ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON);
120
121 ucon0 &= S3C2440_UCON0_DIVMASK;
122 ucon1 &= S3C2440_UCON1_DIVMASK;
123 ucon2 &= S3C2440_UCON2_DIVMASK;
124
125 if (ucon0 != 0)
126 divisor = (ucon0 >> S3C2440_UCON_DIVSHIFT) + 6;
127 else if (ucon1 != 0)
128 divisor = (ucon1 >> S3C2440_UCON_DIVSHIFT) + 21;
129 else if (ucon2 != 0)
130 divisor = (ucon2 >> S3C2440_UCON_DIVSHIFT) + 36;
131 else
132 /* manual calims 44, seems to be 9 */
133 divisor = 9;
134
135 return clk_get_rate(clk->parent) / divisor;
136}
137
138static struct clk s3c2440_clk_fclk_n = {
139 .name = "fclk_n",
140 .parent = &clk_f,
141 .ops = &(struct clk_ops) {
142 .get_rate = s3c2440_fclk_n_getrate,
143 },
144};
145
146static struct clk_lookup s3c2440_clk_lookup[] = {
147 CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
148 CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
149 CLKDEV_INIT(NULL, "clk_uart_baud3", &s3c2440_clk_fclk_n),
150};
151
152static int s3c2440_clk_add(struct device *dev)
153{
154 struct clk *clock_upll;
155 struct clk *clock_h;
156 struct clk *clock_p;
157
158 clock_p = clk_get(NULL, "pclk");
159 clock_h = clk_get(NULL, "hclk");
160 clock_upll = clk_get(NULL, "upll");
161
162 if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) {
163 printk(KERN_ERR "S3C2440: Failed to get parent clocks\n");
164 return -EINVAL;
165 }
166
167 s3c2440_clk_cam.parent = clock_h;
168 s3c2440_clk_ac97.parent = clock_p;
169 s3c2440_clk_cam_upll.parent = clock_upll;
170 s3c24xx_register_clock(&s3c2440_clk_fclk_n);
171
172 s3c24xx_register_clock(&s3c2440_clk_ac97);
173 s3c24xx_register_clock(&s3c2440_clk_cam);
174 s3c24xx_register_clock(&s3c2440_clk_cam_upll);
175 clkdev_add_table(s3c2440_clk_lookup, ARRAY_SIZE(s3c2440_clk_lookup));
176
177 clk_disable(&s3c2440_clk_ac97);
178 clk_disable(&s3c2440_clk_cam);
179
180 return 0;
181}
182
183static struct subsys_interface s3c2440_clk_interface = {
184 .name = "s3c2440_clk",
185 .subsys = &s3c2440_subsys,
186 .add_dev = s3c2440_clk_add,
187};
188
189static __init int s3c24xx_clk_init(void)
190{
191 return subsys_interface_register(&s3c2440_clk_interface);
192}
193
194arch_initcall(s3c24xx_clk_init);
diff --git a/arch/arm/mach-s3c24xx/clock-s3c244x.c b/arch/arm/mach-s3c24xx/clock-s3c244x.c
new file mode 100644
index 000000000000..b3fdbdda3d5f
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/clock-s3c244x.c
@@ -0,0 +1,141 @@
1/* linux/arch/arm/plat-s3c24xx/s3c24xx-clock.c
2 *
3 * Copyright (c) 2004-2008 Simtec Electronics
4 * http://armlinux.simtec.co.uk/
5 * Ben Dooks <ben@simtec.co.uk>
6 *
7 * S3C2440/S3C2442 Common clock support
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 as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22*/
23
24#include <linux/init.h>
25#include <linux/module.h>
26#include <linux/kernel.h>
27#include <linux/list.h>
28#include <linux/errno.h>
29#include <linux/err.h>
30#include <linux/device.h>
31#include <linux/interrupt.h>
32#include <linux/ioport.h>
33#include <linux/clk.h>
34#include <linux/io.h>
35
36#include <mach/hardware.h>
37#include <linux/atomic.h>
38#include <asm/irq.h>
39
40#include <mach/regs-clock.h>
41
42#include <plat/clock.h>
43#include <plat/cpu.h>
44
45static int s3c2440_setparent_armclk(struct clk *clk, struct clk *parent)
46{
47 unsigned long camdivn;
48 unsigned long dvs;
49
50 if (parent == &clk_f)
51 dvs = 0;
52 else if (parent == &clk_h)
53 dvs = S3C2440_CAMDIVN_DVSEN;
54 else
55 return -EINVAL;
56
57 clk->parent = parent;
58
59 camdivn = __raw_readl(S3C2440_CAMDIVN);
60 camdivn &= ~S3C2440_CAMDIVN_DVSEN;
61 camdivn |= dvs;
62 __raw_writel(camdivn, S3C2440_CAMDIVN);
63
64 return 0;
65}
66
67static struct clk clk_arm = {
68 .name = "armclk",
69 .id = -1,
70 .ops = &(struct clk_ops) {
71 .set_parent = s3c2440_setparent_armclk,
72 },
73};
74
75static int s3c244x_clk_add(struct device *dev)
76{
77 unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
78 unsigned long clkdivn;
79 struct clk *clock_upll;
80 int ret;
81
82 printk("S3C244X: Clock Support, DVS %s\n",
83 (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
84
85 clk_arm.parent = (camdivn & S3C2440_CAMDIVN_DVSEN) ? &clk_h : &clk_f;
86
87 ret = s3c24xx_register_clock(&clk_arm);
88 if (ret < 0) {
89 printk(KERN_ERR "S3C24XX: Failed to add armclk (%d)\n", ret);
90 return ret;
91 }
92
93 clock_upll = clk_get(NULL, "upll");
94 if (IS_ERR(clock_upll)) {
95 printk(KERN_ERR "S3C244X: Failed to get upll clock\n");
96 return -ENOENT;
97 }
98
99 /* check rate of UPLL, and if it is near 96MHz, then change
100 * to using half the UPLL rate for the system */
101
102 if (clk_get_rate(clock_upll) > (94 * MHZ)) {
103 clk_usb_bus.rate = clk_get_rate(clock_upll) / 2;
104
105 spin_lock(&clocks_lock);
106
107 clkdivn = __raw_readl(S3C2410_CLKDIVN);
108 clkdivn |= S3C2440_CLKDIVN_UCLK;
109 __raw_writel(clkdivn, S3C2410_CLKDIVN);
110
111 spin_unlock(&clocks_lock);
112 }
113
114 return 0;
115}
116
117static struct subsys_interface s3c2440_clk_interface = {
118 .name = "s3c2440_clk",
119 .subsys = &s3c2440_subsys,
120 .add_dev = s3c244x_clk_add,
121};
122
123static int s3c2440_clk_init(void)
124{
125 return subsys_interface_register(&s3c2440_clk_interface);
126}
127
128arch_initcall(s3c2440_clk_init);
129
130static struct subsys_interface s3c2442_clk_interface = {
131 .name = "s3c2442_clk",
132 .subsys = &s3c2442_subsys,
133 .add_dev = s3c244x_clk_add,
134};
135
136static int s3c2442_clk_init(void)
137{
138 return subsys_interface_register(&s3c2442_clk_interface);
139}
140
141arch_initcall(s3c2442_clk_init);
diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h
index f65dc8062961..62a2e196a68e 100644
--- a/arch/arm/mach-s3c24xx/common.h
+++ b/arch/arm/mach-s3c24xx/common.h
@@ -12,6 +12,12 @@
12#ifndef __ARCH_ARM_MACH_S3C2410_COMMON_H 12#ifndef __ARCH_ARM_MACH_S3C2410_COMMON_H
13#define __ARCH_ARM_MACH_S3C2410_COMMON_H 13#define __ARCH_ARM_MACH_S3C2410_COMMON_H
14 14
15#ifdef CONFIG_CPU_S3C2410
15void s3c2410_restart(char mode, const char *cmd); 16void s3c2410_restart(char mode, const char *cmd);
17#endif
18
19#ifdef CONFIG_CPU_S3C2440
20void s3c2440_restart(char mode, const char *cmd);
21#endif
16 22
17#endif /* __ARCH_ARM_MACH_S3C2410_COMMON_H */ 23#endif /* __ARCH_ARM_MACH_S3C2410_COMMON_H */
diff --git a/arch/arm/mach-s3c24xx/dma-s3c2440.c b/arch/arm/mach-s3c24xx/dma-s3c2440.c
new file mode 100644
index 000000000000..15b1ddf8f626
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/dma-s3c2440.c
@@ -0,0 +1,196 @@
1/* linux/arch/arm/mach-s3c2440/dma.c
2 *
3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C2440 DMA selection
7 *
8 * http://armlinux.simtec.co.uk/
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/init.h>
17#include <linux/device.h>
18#include <linux/serial_core.h>
19
20#include <mach/map.h>
21#include <mach/dma.h>
22
23#include <plat/dma-s3c24xx.h>
24#include <plat/cpu.h>
25
26#include <plat/regs-serial.h>
27#include <mach/regs-gpio.h>
28#include <plat/regs-ac97.h>
29#include <plat/regs-dma.h>
30#include <mach/regs-mem.h>
31#include <mach/regs-lcd.h>
32#include <mach/regs-sdi.h>
33#include <plat/regs-iis.h>
34#include <plat/regs-spi.h>
35
36static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
37 [DMACH_XD0] = {
38 .name = "xdreq0",
39 .channels[0] = S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
40 },
41 [DMACH_XD1] = {
42 .name = "xdreq1",
43 .channels[1] = S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
44 },
45 [DMACH_SDI] = {
46 .name = "sdi",
47 .channels[0] = S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
48 .channels[1] = S3C2440_DCON_CH1_SDI | DMA_CH_VALID,
49 .channels[2] = S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
50 .channels[3] = S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
51 },
52 [DMACH_SPI0] = {
53 .name = "spi0",
54 .channels[1] = S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
55 },
56 [DMACH_SPI1] = {
57 .name = "spi1",
58 .channels[3] = S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
59 },
60 [DMACH_UART0] = {
61 .name = "uart0",
62 .channels[0] = S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
63 },
64 [DMACH_UART1] = {
65 .name = "uart1",
66 .channels[1] = S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
67 },
68 [DMACH_UART2] = {
69 .name = "uart2",
70 .channels[3] = S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
71 },
72 [DMACH_TIMER] = {
73 .name = "timer",
74 .channels[0] = S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
75 .channels[2] = S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
76 .channels[3] = S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
77 },
78 [DMACH_I2S_IN] = {
79 .name = "i2s-sdi",
80 .channels[1] = S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
81 .channels[2] = S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
82 },
83 [DMACH_I2S_OUT] = {
84 .name = "i2s-sdo",
85 .channels[0] = S3C2440_DCON_CH0_I2SSDO | DMA_CH_VALID,
86 .channels[2] = S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
87 },
88 [DMACH_PCM_IN] = {
89 .name = "pcm-in",
90 .channels[0] = S3C2440_DCON_CH0_PCMIN | DMA_CH_VALID,
91 .channels[2] = S3C2440_DCON_CH2_PCMIN | DMA_CH_VALID,
92 },
93 [DMACH_PCM_OUT] = {
94 .name = "pcm-out",
95 .channels[1] = S3C2440_DCON_CH1_PCMOUT | DMA_CH_VALID,
96 .channels[3] = S3C2440_DCON_CH3_PCMOUT | DMA_CH_VALID,
97 },
98 [DMACH_MIC_IN] = {
99 .name = "mic-in",
100 .channels[2] = S3C2440_DCON_CH2_MICIN | DMA_CH_VALID,
101 .channels[3] = S3C2440_DCON_CH3_MICIN | DMA_CH_VALID,
102 },
103 [DMACH_USB_EP1] = {
104 .name = "usb-ep1",
105 .channels[0] = S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
106 },
107 [DMACH_USB_EP2] = {
108 .name = "usb-ep2",
109 .channels[1] = S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
110 },
111 [DMACH_USB_EP3] = {
112 .name = "usb-ep3",
113 .channels[2] = S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
114 },
115 [DMACH_USB_EP4] = {
116 .name = "usb-ep4",
117 .channels[3] = S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
118 },
119};
120
121static void s3c2440_dma_select(struct s3c2410_dma_chan *chan,
122 struct s3c24xx_dma_map *map)
123{
124 chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
125}
126
127static struct s3c24xx_dma_selection __initdata s3c2440_dma_sel = {
128 .select = s3c2440_dma_select,
129 .dcon_mask = 7 << 24,
130 .map = s3c2440_dma_mappings,
131 .map_size = ARRAY_SIZE(s3c2440_dma_mappings),
132};
133
134static struct s3c24xx_dma_order __initdata s3c2440_dma_order = {
135 .channels = {
136 [DMACH_SDI] = {
137 .list = {
138 [0] = 3 | DMA_CH_VALID,
139 [1] = 2 | DMA_CH_VALID,
140 [2] = 1 | DMA_CH_VALID,
141 [3] = 0 | DMA_CH_VALID,
142 },
143 },
144 [DMACH_I2S_IN] = {
145 .list = {
146 [0] = 1 | DMA_CH_VALID,
147 [1] = 2 | DMA_CH_VALID,
148 },
149 },
150 [DMACH_I2S_OUT] = {
151 .list = {
152 [0] = 2 | DMA_CH_VALID,
153 [1] = 1 | DMA_CH_VALID,
154 },
155 },
156 [DMACH_PCM_IN] = {
157 .list = {
158 [0] = 2 | DMA_CH_VALID,
159 [1] = 1 | DMA_CH_VALID,
160 },
161 },
162 [DMACH_PCM_OUT] = {
163 .list = {
164 [0] = 1 | DMA_CH_VALID,
165 [1] = 3 | DMA_CH_VALID,
166 },
167 },
168 [DMACH_MIC_IN] = {
169 .list = {
170 [0] = 3 | DMA_CH_VALID,
171 [1] = 2 | DMA_CH_VALID,
172 },
173 },
174 },
175};
176
177static int __init s3c2440_dma_add(struct device *dev)
178{
179 s3c2410_dma_init();
180 s3c24xx_dma_order_set(&s3c2440_dma_order);
181 return s3c24xx_dma_init_map(&s3c2440_dma_sel);
182}
183
184static struct subsys_interface s3c2440_dma_interface = {
185 .name = "s3c2440_dma",
186 .subsys = &s3c2440_subsys,
187 .add_dev = s3c2440_dma_add,
188};
189
190static int __init s3c2440_dma_init(void)
191{
192 return subsys_interface_register(&s3c2440_dma_interface);
193}
194
195arch_initcall(s3c2440_dma_init);
196
diff --git a/arch/arm/mach-s3c24xx/include/mach/gta02.h b/arch/arm/mach-s3c24xx/include/mach/gta02.h
new file mode 100644
index 000000000000..3a56a229cac6
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/include/mach/gta02.h
@@ -0,0 +1,84 @@
1#ifndef _GTA02_H
2#define _GTA02_H
3
4#include <mach/regs-gpio.h>
5
6/* Different hardware revisions, passed in ATAG_REVISION by u-boot */
7#define GTA02v1_SYSTEM_REV 0x00000310
8#define GTA02v2_SYSTEM_REV 0x00000320
9#define GTA02v3_SYSTEM_REV 0x00000330
10#define GTA02v4_SYSTEM_REV 0x00000340
11#define GTA02v5_SYSTEM_REV 0x00000350
12/* since A7 is basically same as A6, we use A6 PCB ID */
13#define GTA02v6_SYSTEM_REV 0x00000360
14
15#define GTA02_GPIO_n3DL_GSM S3C2410_GPA(13) /* v1 + v2 + v3 only */
16
17#define GTA02_GPIO_PWR_LED1 S3C2410_GPB(0)
18#define GTA02_GPIO_PWR_LED2 S3C2410_GPB(1)
19#define GTA02_GPIO_AUX_LED S3C2410_GPB(2)
20#define GTA02_GPIO_VIBRATOR_ON S3C2410_GPB(3)
21#define GTA02_GPIO_MODEM_RST S3C2410_GPB(5)
22#define GTA02_GPIO_BT_EN S3C2410_GPB(6)
23#define GTA02_GPIO_MODEM_ON S3C2410_GPB(7)
24#define GTA02_GPIO_EXTINT8 S3C2410_GPB(8)
25#define GTA02_GPIO_USB_PULLUP S3C2410_GPB(9)
26
27#define GTA02_GPIO_PIO5 S3C2410_GPC(5) /* v3 + v4 only */
28
29#define GTA02v3_GPIO_nG1_CS S3C2410_GPD(12) /* v3 + v4 only */
30#define GTA02v3_GPIO_nG2_CS S3C2410_GPD(13) /* v3 + v4 only */
31#define GTA02v5_GPIO_HDQ S3C2410_GPD(14) /* v5 + */
32
33#define GTA02_GPIO_nG1_INT S3C2410_GPF(0)
34#define GTA02_GPIO_IO1 S3C2410_GPF(1)
35#define GTA02_GPIO_PIO_2 S3C2410_GPF(2) /* v2 + v3 + v4 only */
36#define GTA02_GPIO_JACK_INSERT S3C2410_GPF(4)
37#define GTA02_GPIO_WLAN_GPIO1 S3C2410_GPF(5) /* v2 + v3 + v4 only */
38#define GTA02_GPIO_AUX_KEY S3C2410_GPF(6)
39#define GTA02_GPIO_HOLD_KEY S3C2410_GPF(7)
40
41#define GTA02_GPIO_3D_IRQ S3C2410_GPG(4)
42#define GTA02v2_GPIO_nG2_INT S3C2410_GPG(8) /* v2 + v3 + v4 only */
43#define GTA02v3_GPIO_nUSB_OC S3C2410_GPG(9) /* v3 + v4 only */
44#define GTA02v3_GPIO_nUSB_FLT S3C2410_GPG(10) /* v3 + v4 only */
45#define GTA02v3_GPIO_nGSM_OC S3C2410_GPG(11) /* v3 + v4 only */
46
47#define GTA02_GPIO_AMP_SHUT S3C2410_GPJ(1) /* v2 + v3 + v4 only */
48#define GTA02v1_GPIO_WLAN_GPIO10 S3C2410_GPJ(2)
49#define GTA02_GPIO_HP_IN S3C2410_GPJ(2) /* v2 + v3 + v4 only */
50#define GTA02_GPIO_INT0 S3C2410_GPJ(3) /* v2 + v3 + v4 only */
51#define GTA02_GPIO_nGSM_EN S3C2410_GPJ(4)
52#define GTA02_GPIO_3D_RESET S3C2410_GPJ(5)
53#define GTA02_GPIO_nDL_GSM S3C2410_GPJ(6) /* v4 + v5 only */
54#define GTA02_GPIO_WLAN_GPIO0 S3C2410_GPJ(7)
55#define GTA02v1_GPIO_BAT_ID S3C2410_GPJ(8)
56#define GTA02_GPIO_KEEPACT S3C2410_GPJ(8)
57#define GTA02v1_GPIO_HP_IN S3C2410_GPJ(10)
58#define GTA02_CHIP_PWD S3C2410_GPJ(11) /* v2 + v3 + v4 only */
59#define GTA02_GPIO_nWLAN_RESET S3C2410_GPJ(12) /* v2 + v3 + v4 only */
60
61#define GTA02_IRQ_GSENSOR_1 IRQ_EINT0
62#define GTA02_IRQ_MODEM IRQ_EINT1
63#define GTA02_IRQ_PIO_2 IRQ_EINT2 /* v2 + v3 + v4 only */
64#define GTA02_IRQ_nJACK_INSERT IRQ_EINT4
65#define GTA02_IRQ_WLAN_GPIO1 IRQ_EINT5
66#define GTA02_IRQ_AUX IRQ_EINT6
67#define GTA02_IRQ_nHOLD IRQ_EINT7
68#define GTA02_IRQ_PCF50633 IRQ_EINT9
69#define GTA02_IRQ_3D IRQ_EINT12
70#define GTA02_IRQ_GSENSOR_2 IRQ_EINT16 /* v2 + v3 + v4 only */
71#define GTA02v3_IRQ_nUSB_OC IRQ_EINT17 /* v3 + v4 only */
72#define GTA02v3_IRQ_nUSB_FLT IRQ_EINT18 /* v3 + v4 only */
73#define GTA02v3_IRQ_nGSM_OC IRQ_EINT19 /* v3 + v4 only */
74
75/* returns 00 000 on GTA02 A5 and earlier, A6 returns 01 001 */
76#define GTA02_PCB_ID1_0 S3C2410_GPC(13)
77#define GTA02_PCB_ID1_1 S3C2410_GPC(15)
78#define GTA02_PCB_ID1_2 S3C2410_GPD(0)
79#define GTA02_PCB_ID2_0 S3C2410_GPD(3)
80#define GTA02_PCB_ID2_1 S3C2410_GPD(4)
81
82int gta02_get_pcb_revision(void);
83
84#endif /* _GTA02_H */
diff --git a/arch/arm/mach-s3c24xx/irq-s3c2440.c b/arch/arm/mach-s3c24xx/irq-s3c2440.c
new file mode 100644
index 000000000000..4fee9bc6bcb5
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/irq-s3c2440.c
@@ -0,0 +1,128 @@
1/* linux/arch/arm/mach-s3c2440/irq.c
2 *
3 * Copyright (c) 2003-2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
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 as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20*/
21
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/interrupt.h>
25#include <linux/ioport.h>
26#include <linux/device.h>
27#include <linux/io.h>
28
29#include <mach/hardware.h>
30#include <asm/irq.h>
31
32#include <asm/mach/irq.h>
33
34#include <mach/regs-irq.h>
35#include <mach/regs-gpio.h>
36
37#include <plat/cpu.h>
38#include <plat/pm.h>
39#include <plat/irq.h>
40
41/* WDT/AC97 */
42
43static void s3c_irq_demux_wdtac97(unsigned int irq,
44 struct irq_desc *desc)
45{
46 unsigned int subsrc, submsk;
47
48 /* read the current pending interrupts, and the mask
49 * for what it is available */
50
51 subsrc = __raw_readl(S3C2410_SUBSRCPND);
52 submsk = __raw_readl(S3C2410_INTSUBMSK);
53
54 subsrc &= ~submsk;
55 subsrc >>= 13;
56 subsrc &= 3;
57
58 if (subsrc != 0) {
59 if (subsrc & 1) {
60 generic_handle_irq(IRQ_S3C2440_WDT);
61 }
62 if (subsrc & 2) {
63 generic_handle_irq(IRQ_S3C2440_AC97);
64 }
65 }
66}
67
68
69#define INTMSK_WDT (1UL << (IRQ_WDT - IRQ_EINT0))
70
71static void
72s3c_irq_wdtac97_mask(struct irq_data *data)
73{
74 s3c_irqsub_mask(data->irq, INTMSK_WDT, 3 << 13);
75}
76
77static void
78s3c_irq_wdtac97_unmask(struct irq_data *data)
79{
80 s3c_irqsub_unmask(data->irq, INTMSK_WDT);
81}
82
83static void
84s3c_irq_wdtac97_ack(struct irq_data *data)
85{
86 s3c_irqsub_maskack(data->irq, INTMSK_WDT, 3 << 13);
87}
88
89static struct irq_chip s3c_irq_wdtac97 = {
90 .irq_mask = s3c_irq_wdtac97_mask,
91 .irq_unmask = s3c_irq_wdtac97_unmask,
92 .irq_ack = s3c_irq_wdtac97_ack,
93};
94
95static int s3c2440_irq_add(struct device *dev)
96{
97 unsigned int irqno;
98
99 printk("S3C2440: IRQ Support\n");
100
101 /* add new chained handler for wdt, ac7 */
102
103 irq_set_chip_and_handler(IRQ_WDT, &s3c_irq_level_chip,
104 handle_level_irq);
105 irq_set_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
106
107 for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
108 irq_set_chip_and_handler(irqno, &s3c_irq_wdtac97,
109 handle_level_irq);
110 set_irq_flags(irqno, IRQF_VALID);
111 }
112
113 return 0;
114}
115
116static struct subsys_interface s3c2440_irq_interface = {
117 .name = "s3c2440_irq",
118 .subsys = &s3c2440_subsys,
119 .add_dev = s3c2440_irq_add,
120};
121
122static int s3c2440_irq_init(void)
123{
124 return subsys_interface_register(&s3c2440_irq_interface);
125}
126
127arch_initcall(s3c2440_irq_init);
128
diff --git a/arch/arm/mach-s3c24xx/irq-s3c244x.c b/arch/arm/mach-s3c24xx/irq-s3c244x.c
new file mode 100644
index 000000000000..74d3dcf46a48
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/irq-s3c244x.c
@@ -0,0 +1,142 @@
1/* linux/arch/arm/plat-s3c24xx/s3c244x-irq.c
2 *
3 * Copyright (c) 2003-2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
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 as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20*/
21
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/interrupt.h>
25#include <linux/ioport.h>
26#include <linux/device.h>
27#include <linux/io.h>
28
29#include <mach/hardware.h>
30#include <asm/irq.h>
31
32#include <asm/mach/irq.h>
33
34#include <mach/regs-irq.h>
35#include <mach/regs-gpio.h>
36
37#include <plat/cpu.h>
38#include <plat/pm.h>
39#include <plat/irq.h>
40
41/* camera irq */
42
43static void s3c_irq_demux_cam(unsigned int irq,
44 struct irq_desc *desc)
45{
46 unsigned int subsrc, submsk;
47
48 /* read the current pending interrupts, and the mask
49 * for what it is available */
50
51 subsrc = __raw_readl(S3C2410_SUBSRCPND);
52 submsk = __raw_readl(S3C2410_INTSUBMSK);
53
54 subsrc &= ~submsk;
55 subsrc >>= 11;
56 subsrc &= 3;
57
58 if (subsrc != 0) {
59 if (subsrc & 1) {
60 generic_handle_irq(IRQ_S3C2440_CAM_C);
61 }
62 if (subsrc & 2) {
63 generic_handle_irq(IRQ_S3C2440_CAM_P);
64 }
65 }
66}
67
68#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
69
70static void
71s3c_irq_cam_mask(struct irq_data *data)
72{
73 s3c_irqsub_mask(data->irq, INTMSK_CAM, 3 << 11);
74}
75
76static void
77s3c_irq_cam_unmask(struct irq_data *data)
78{
79 s3c_irqsub_unmask(data->irq, INTMSK_CAM);
80}
81
82static void
83s3c_irq_cam_ack(struct irq_data *data)
84{
85 s3c_irqsub_maskack(data->irq, INTMSK_CAM, 3 << 11);
86}
87
88static struct irq_chip s3c_irq_cam = {
89 .irq_mask = s3c_irq_cam_mask,
90 .irq_unmask = s3c_irq_cam_unmask,
91 .irq_ack = s3c_irq_cam_ack,
92};
93
94static int s3c244x_irq_add(struct device *dev)
95{
96 unsigned int irqno;
97
98 irq_set_chip_and_handler(IRQ_NFCON, &s3c_irq_level_chip,
99 handle_level_irq);
100 set_irq_flags(IRQ_NFCON, IRQF_VALID);
101
102 /* add chained handler for camera */
103
104 irq_set_chip_and_handler(IRQ_CAM, &s3c_irq_level_chip,
105 handle_level_irq);
106 irq_set_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
107
108 for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
109 irq_set_chip_and_handler(irqno, &s3c_irq_cam,
110 handle_level_irq);
111 set_irq_flags(irqno, IRQF_VALID);
112 }
113
114 return 0;
115}
116
117static struct subsys_interface s3c2440_irq_interface = {
118 .name = "s3c2440_irq",
119 .subsys = &s3c2440_subsys,
120 .add_dev = s3c244x_irq_add,
121};
122
123static int s3c2440_irq_init(void)
124{
125 return subsys_interface_register(&s3c2440_irq_interface);
126}
127
128arch_initcall(s3c2440_irq_init);
129
130static struct subsys_interface s3c2442_irq_interface = {
131 .name = "s3c2442_irq",
132 .subsys = &s3c2442_subsys,
133 .add_dev = s3c244x_irq_add,
134};
135
136
137static int s3c2442_irq_init(void)
138{
139 return subsys_interface_register(&s3c2442_irq_interface);
140}
141
142arch_initcall(s3c2442_irq_init);
diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c
new file mode 100644
index 000000000000..24569550de1a
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/mach-anubis.c
@@ -0,0 +1,491 @@
1/* linux/arch/arm/mach-s3c2440/mach-anubis.c
2 *
3 * Copyright 2003-2009 Simtec Electronics
4 * http://armlinux.simtec.co.uk/
5 * Ben Dooks <ben@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/gpio.h>
19#include <linux/serial_core.h>
20#include <linux/platform_device.h>
21#include <linux/ata_platform.h>
22#include <linux/i2c.h>
23#include <linux/io.h>
24#include <linux/sm501.h>
25#include <linux/sm501-regs.h>
26
27#include <asm/mach/arch.h>
28#include <asm/mach/map.h>
29#include <asm/mach/irq.h>
30
31#include <mach/anubis-map.h>
32#include <mach/anubis-irq.h>
33#include <mach/anubis-cpld.h>
34
35#include <mach/hardware.h>
36#include <asm/irq.h>
37#include <asm/mach-types.h>
38
39#include <plat/regs-serial.h>
40#include <mach/regs-gpio.h>
41#include <mach/regs-mem.h>
42#include <mach/regs-lcd.h>
43#include <plat/nand.h>
44#include <plat/iic.h>
45
46#include <linux/mtd/mtd.h>
47#include <linux/mtd/nand.h>
48#include <linux/mtd/nand_ecc.h>
49#include <linux/mtd/partitions.h>
50
51#include <net/ax88796.h>
52
53#include <plat/clock.h>
54#include <plat/devs.h>
55#include <plat/cpu.h>
56#include <plat/audio-simtec.h>
57
58#include "common.h"
59
60#define COPYRIGHT ", Copyright 2005-2009 Simtec Electronics"
61
62static struct map_desc anubis_iodesc[] __initdata = {
63 /* ISA IO areas */
64
65 {
66 .virtual = (u32)S3C24XX_VA_ISA_BYTE,
67 .pfn = __phys_to_pfn(0x0),
68 .length = SZ_4M,
69 .type = MT_DEVICE,
70 }, {
71 .virtual = (u32)S3C24XX_VA_ISA_WORD,
72 .pfn = __phys_to_pfn(0x0),
73 .length = SZ_4M,
74 .type = MT_DEVICE,
75 },
76
77 /* we could possibly compress the next set down into a set of smaller tables
78 * pagetables, but that would mean using an L2 section, and it still means
79 * we cannot actually feed the same register to an LDR due to 16K spacing
80 */
81
82 /* CPLD control registers */
83
84 {
85 .virtual = (u32)ANUBIS_VA_CTRL1,
86 .pfn = __phys_to_pfn(ANUBIS_PA_CTRL1),
87 .length = SZ_4K,
88 .type = MT_DEVICE,
89 }, {
90 .virtual = (u32)ANUBIS_VA_IDREG,
91 .pfn = __phys_to_pfn(ANUBIS_PA_IDREG),
92 .length = SZ_4K,
93 .type = MT_DEVICE,
94 },
95};
96
97#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
98#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
99#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
100
101static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = {
102 [0] = {
103 .hwport = 0,
104 .flags = 0,
105 .ucon = UCON,
106 .ulcon = ULCON,
107 .ufcon = UFCON,
108 .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
109 },
110 [1] = {
111 .hwport = 2,
112 .flags = 0,
113 .ucon = UCON,
114 .ulcon = ULCON,
115 .ufcon = UFCON,
116 .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
117 },
118};
119
120/* NAND Flash on Anubis board */
121
122static int external_map[] = { 2 };
123static int chip0_map[] = { 0 };
124static int chip1_map[] = { 1 };
125
126static struct mtd_partition __initdata anubis_default_nand_part[] = {
127 [0] = {
128 .name = "Boot Agent",
129 .size = SZ_16K,
130 .offset = 0,
131 },
132 [1] = {
133 .name = "/boot",
134 .size = SZ_4M - SZ_16K,
135 .offset = SZ_16K,
136 },
137 [2] = {
138 .name = "user1",
139 .offset = SZ_4M,
140 .size = SZ_32M - SZ_4M,
141 },
142 [3] = {
143 .name = "user2",
144 .offset = SZ_32M,
145 .size = MTDPART_SIZ_FULL,
146 }
147};
148
149static struct mtd_partition __initdata anubis_default_nand_part_large[] = {
150 [0] = {
151 .name = "Boot Agent",
152 .size = SZ_128K,
153 .offset = 0,
154 },
155 [1] = {
156 .name = "/boot",
157 .size = SZ_4M - SZ_128K,
158 .offset = SZ_128K,
159 },
160 [2] = {
161 .name = "user1",
162 .offset = SZ_4M,
163 .size = SZ_32M - SZ_4M,
164 },
165 [3] = {
166 .name = "user2",
167 .offset = SZ_32M,
168 .size = MTDPART_SIZ_FULL,
169 }
170};
171
172/* the Anubis has 3 selectable slots for nand-flash, the two
173 * on-board chip areas, as well as the external slot.
174 *
175 * Note, there is no current hot-plug support for the External
176 * socket.
177*/
178
179static struct s3c2410_nand_set __initdata anubis_nand_sets[] = {
180 [1] = {
181 .name = "External",
182 .nr_chips = 1,
183 .nr_map = external_map,
184 .nr_partitions = ARRAY_SIZE(anubis_default_nand_part),
185 .partitions = anubis_default_nand_part,
186 },
187 [0] = {
188 .name = "chip0",
189 .nr_chips = 1,
190 .nr_map = chip0_map,
191 .nr_partitions = ARRAY_SIZE(anubis_default_nand_part),
192 .partitions = anubis_default_nand_part,
193 },
194 [2] = {
195 .name = "chip1",
196 .nr_chips = 1,
197 .nr_map = chip1_map,
198 .nr_partitions = ARRAY_SIZE(anubis_default_nand_part),
199 .partitions = anubis_default_nand_part,
200 },
201};
202
203static void anubis_nand_select(struct s3c2410_nand_set *set, int slot)
204{
205 unsigned int tmp;
206
207 slot = set->nr_map[slot] & 3;
208
209 pr_debug("anubis_nand: selecting slot %d (set %p,%p)\n",
210 slot, set, set->nr_map);
211
212 tmp = __raw_readb(ANUBIS_VA_CTRL1);
213 tmp &= ~ANUBIS_CTRL1_NANDSEL;
214 tmp |= slot;
215
216 pr_debug("anubis_nand: ctrl1 now %02x\n", tmp);
217
218 __raw_writeb(tmp, ANUBIS_VA_CTRL1);
219}
220
221static struct s3c2410_platform_nand __initdata anubis_nand_info = {
222 .tacls = 25,
223 .twrph0 = 55,
224 .twrph1 = 40,
225 .nr_sets = ARRAY_SIZE(anubis_nand_sets),
226 .sets = anubis_nand_sets,
227 .select_chip = anubis_nand_select,
228};
229
230/* IDE channels */
231
232static struct pata_platform_info anubis_ide_platdata = {
233 .ioport_shift = 5,
234};
235
236static struct resource anubis_ide0_resource[] = {
237 {
238 .start = S3C2410_CS3,
239 .end = S3C2410_CS3 + (8*32) - 1,
240 .flags = IORESOURCE_MEM,
241 }, {
242 .start = S3C2410_CS3 + (1<<26) + (6*32),
243 .end = S3C2410_CS3 + (1<<26) + (7*32) - 1,
244 .flags = IORESOURCE_MEM,
245 }, {
246 .start = IRQ_IDE0,
247 .end = IRQ_IDE0,
248 .flags = IORESOURCE_IRQ,
249 },
250};
251
252static struct platform_device anubis_device_ide0 = {
253 .name = "pata_platform",
254 .id = 0,
255 .num_resources = ARRAY_SIZE(anubis_ide0_resource),
256 .resource = anubis_ide0_resource,
257 .dev = {
258 .platform_data = &anubis_ide_platdata,
259 .coherent_dma_mask = ~0,
260 },
261};
262
263static struct resource anubis_ide1_resource[] = {
264 {
265 .start = S3C2410_CS4,
266 .end = S3C2410_CS4 + (8*32) - 1,
267 .flags = IORESOURCE_MEM,
268 }, {
269 .start = S3C2410_CS4 + (1<<26) + (6*32),
270 .end = S3C2410_CS4 + (1<<26) + (7*32) - 1,
271 .flags = IORESOURCE_MEM,
272 }, {
273 .start = IRQ_IDE0,
274 .end = IRQ_IDE0,
275 .flags = IORESOURCE_IRQ,
276 },
277};
278
279static struct platform_device anubis_device_ide1 = {
280 .name = "pata_platform",
281 .id = 1,
282 .num_resources = ARRAY_SIZE(anubis_ide1_resource),
283 .resource = anubis_ide1_resource,
284 .dev = {
285 .platform_data = &anubis_ide_platdata,
286 .coherent_dma_mask = ~0,
287 },
288};
289
290/* Asix AX88796 10/100 ethernet controller */
291
292static struct ax_plat_data anubis_asix_platdata = {
293 .flags = AXFLG_MAC_FROMDEV,
294 .wordlength = 2,
295 .dcr_val = 0x48,
296 .rcr_val = 0x40,
297};
298
299static struct resource anubis_asix_resource[] = {
300 [0] = {
301 .start = S3C2410_CS5,
302 .end = S3C2410_CS5 + (0x20 * 0x20) -1,
303 .flags = IORESOURCE_MEM
304 },
305 [1] = {
306 .start = IRQ_ASIX,
307 .end = IRQ_ASIX,
308 .flags = IORESOURCE_IRQ
309 }
310};
311
312static struct platform_device anubis_device_asix = {
313 .name = "ax88796",
314 .id = 0,
315 .num_resources = ARRAY_SIZE(anubis_asix_resource),
316 .resource = anubis_asix_resource,
317 .dev = {
318 .platform_data = &anubis_asix_platdata,
319 }
320};
321
322/* SM501 */
323
324static struct resource anubis_sm501_resource[] = {
325 [0] = {
326 .start = S3C2410_CS2,
327 .end = S3C2410_CS2 + SZ_8M,
328 .flags = IORESOURCE_MEM,
329 },
330 [1] = {
331 .start = S3C2410_CS2 + SZ_64M - SZ_2M,
332 .end = S3C2410_CS2 + SZ_64M - 1,
333 .flags = IORESOURCE_MEM,
334 },
335 [2] = {
336 .start = IRQ_EINT0,
337 .end = IRQ_EINT0,
338 .flags = IORESOURCE_IRQ,
339 },
340};
341
342static struct sm501_initdata anubis_sm501_initdata = {
343 .gpio_high = {
344 .set = 0x3F000000, /* 24bit panel */
345 .mask = 0x0,
346 },
347 .misc_timing = {
348 .set = 0x010100, /* SDRAM timing */
349 .mask = 0x1F1F00,
350 },
351 .misc_control = {
352 .set = SM501_MISC_PNL_24BIT,
353 .mask = 0,
354 },
355
356 .devices = SM501_USE_GPIO,
357
358 /* set the SDRAM and bus clocks */
359 .mclk = 72 * MHZ,
360 .m1xclk = 144 * MHZ,
361};
362
363static struct sm501_platdata_gpio_i2c anubis_sm501_gpio_i2c[] = {
364 [0] = {
365 .bus_num = 1,
366 .pin_scl = 44,
367 .pin_sda = 45,
368 },
369 [1] = {
370 .bus_num = 2,
371 .pin_scl = 40,
372 .pin_sda = 41,
373 },
374};
375
376static struct sm501_platdata anubis_sm501_platdata = {
377 .init = &anubis_sm501_initdata,
378 .gpio_base = -1,
379 .gpio_i2c = anubis_sm501_gpio_i2c,
380 .gpio_i2c_nr = ARRAY_SIZE(anubis_sm501_gpio_i2c),
381};
382
383static struct platform_device anubis_device_sm501 = {
384 .name = "sm501",
385 .id = 0,
386 .num_resources = ARRAY_SIZE(anubis_sm501_resource),
387 .resource = anubis_sm501_resource,
388 .dev = {
389 .platform_data = &anubis_sm501_platdata,
390 },
391};
392
393/* Standard Anubis devices */
394
395static struct platform_device *anubis_devices[] __initdata = {
396 &s3c_device_ohci,
397 &s3c_device_wdt,
398 &s3c_device_adc,
399 &s3c_device_i2c0,
400 &s3c_device_rtc,
401 &s3c_device_nand,
402 &anubis_device_ide0,
403 &anubis_device_ide1,
404 &anubis_device_asix,
405 &anubis_device_sm501,
406};
407
408static struct clk *anubis_clocks[] __initdata = {
409 &s3c24xx_dclk0,
410 &s3c24xx_dclk1,
411 &s3c24xx_clkout0,
412 &s3c24xx_clkout1,
413 &s3c24xx_uclk,
414};
415
416/* I2C devices. */
417
418static struct i2c_board_info anubis_i2c_devs[] __initdata = {
419 {
420 I2C_BOARD_INFO("tps65011", 0x48),
421 .irq = IRQ_EINT20,
422 }
423};
424
425/* Audio setup */
426static struct s3c24xx_audio_simtec_pdata __initdata anubis_audio = {
427 .have_mic = 1,
428 .have_lout = 1,
429 .output_cdclk = 1,
430 .use_mpllin = 1,
431 .amp_gpio = S3C2410_GPB(2),
432 .amp_gain[0] = S3C2410_GPD(10),
433 .amp_gain[1] = S3C2410_GPD(11),
434};
435
436static void __init anubis_map_io(void)
437{
438 /* initialise the clocks */
439
440 s3c24xx_dclk0.parent = &clk_upll;
441 s3c24xx_dclk0.rate = 12*1000*1000;
442
443 s3c24xx_dclk1.parent = &clk_upll;
444 s3c24xx_dclk1.rate = 24*1000*1000;
445
446 s3c24xx_clkout0.parent = &s3c24xx_dclk0;
447 s3c24xx_clkout1.parent = &s3c24xx_dclk1;
448
449 s3c24xx_uclk.parent = &s3c24xx_clkout1;
450
451 s3c24xx_register_clocks(anubis_clocks, ARRAY_SIZE(anubis_clocks));
452
453 s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
454 s3c24xx_init_clocks(0);
455 s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
456
457 /* check for the newer revision boards with large page nand */
458
459 if ((__raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK) >= 4) {
460 printk(KERN_INFO "ANUBIS-B detected (revision %d)\n",
461 __raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK);
462 anubis_nand_sets[0].partitions = anubis_default_nand_part_large;
463 anubis_nand_sets[0].nr_partitions = ARRAY_SIZE(anubis_default_nand_part_large);
464 } else {
465 /* ensure that the GPIO is setup */
466 s3c2410_gpio_setpin(S3C2410_GPA(0), 1);
467 }
468}
469
470static void __init anubis_init(void)
471{
472 s3c_i2c0_set_platdata(NULL);
473 s3c_nand_set_platdata(&anubis_nand_info);
474 simtec_audio_add(NULL, false, &anubis_audio);
475
476 platform_add_devices(anubis_devices, ARRAY_SIZE(anubis_devices));
477
478 i2c_register_board_info(0, anubis_i2c_devs,
479 ARRAY_SIZE(anubis_i2c_devs));
480}
481
482
483MACHINE_START(ANUBIS, "Simtec-Anubis")
484 /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
485 .atag_offset = 0x100,
486 .map_io = anubis_map_io,
487 .init_machine = anubis_init,
488 .init_irq = s3c24xx_init_irq,
489 .timer = &s3c24xx_timer,
490 .restart = s3c2440_restart,
491MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-at2440evb.c b/arch/arm/mach-s3c24xx/mach-at2440evb.c
new file mode 100644
index 000000000000..d6a9763110cd
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/mach-at2440evb.c
@@ -0,0 +1,226 @@
1/* linux/arch/arm/mach-s3c2440/mach-at2440evb.c
2 *
3 * Copyright (c) 2008 Ramax Lo <ramaxlo@gmail.com>
4 * Based on mach-anubis.c by Ben Dooks <ben@simtec.co.uk>
5 * and modifications by SBZ <sbz@spgui.org> and
6 * Weibing <http://weibing.blogbus.com>
7 *
8 * For product information, visit http://www.arm.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#include <linux/kernel.h>
16#include <linux/types.h>
17#include <linux/interrupt.h>
18#include <linux/list.h>
19#include <linux/timer.h>
20#include <linux/init.h>
21#include <linux/io.h>
22#include <linux/serial_core.h>
23#include <linux/dm9000.h>
24#include <linux/platform_device.h>
25
26#include <asm/mach/arch.h>
27#include <asm/mach/map.h>
28#include <asm/mach/irq.h>
29
30#include <mach/hardware.h>
31#include <mach/fb.h>
32#include <asm/irq.h>
33#include <asm/mach-types.h>
34
35#include <plat/regs-serial.h>
36#include <mach/regs-gpio.h>
37#include <mach/regs-mem.h>
38#include <mach/regs-lcd.h>
39#include <plat/nand.h>
40#include <plat/iic.h>
41
42#include <linux/mtd/mtd.h>
43#include <linux/mtd/nand.h>
44#include <linux/mtd/nand_ecc.h>
45#include <linux/mtd/partitions.h>
46
47#include <plat/clock.h>
48#include <plat/devs.h>
49#include <plat/cpu.h>
50#include <plat/mci.h>
51
52#include "common.h"
53
54static struct map_desc at2440evb_iodesc[] __initdata = {
55 /* Nothing here */
56};
57
58#define UCON S3C2410_UCON_DEFAULT
59#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE)
60#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
61
62static struct s3c2410_uartcfg at2440evb_uartcfgs[] __initdata = {
63 [0] = {
64 .hwport = 0,
65 .flags = 0,
66 .ucon = UCON,
67 .ulcon = ULCON,
68 .ufcon = UFCON,
69 .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
70 },
71 [1] = {
72 .hwport = 1,
73 .flags = 0,
74 .ucon = UCON,
75 .ulcon = ULCON,
76 .ufcon = UFCON,
77 .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
78 },
79};
80
81/* NAND Flash on AT2440EVB board */
82
83static struct mtd_partition __initdata at2440evb_default_nand_part[] = {
84 [0] = {
85 .name = "Boot Agent",
86 .size = SZ_256K,
87 .offset = 0,
88 },
89 [1] = {
90 .name = "Kernel",
91 .size = SZ_2M,
92 .offset = SZ_256K,
93 },
94 [2] = {
95 .name = "Root",
96 .offset = SZ_256K + SZ_2M,
97 .size = MTDPART_SIZ_FULL,
98 },
99};
100
101static struct s3c2410_nand_set __initdata at2440evb_nand_sets[] = {
102 [0] = {
103 .name = "nand",
104 .nr_chips = 1,
105 .nr_partitions = ARRAY_SIZE(at2440evb_default_nand_part),
106 .partitions = at2440evb_default_nand_part,
107 },
108};
109
110static struct s3c2410_platform_nand __initdata at2440evb_nand_info = {
111 .tacls = 25,
112 .twrph0 = 55,
113 .twrph1 = 40,
114 .nr_sets = ARRAY_SIZE(at2440evb_nand_sets),
115 .sets = at2440evb_nand_sets,
116};
117
118/* DM9000AEP 10/100 ethernet controller */
119
120static struct resource at2440evb_dm9k_resource[] = {
121 [0] = {
122 .start = S3C2410_CS3,
123 .end = S3C2410_CS3 + 3,
124 .flags = IORESOURCE_MEM
125 },
126 [1] = {
127 .start = S3C2410_CS3 + 4,
128 .end = S3C2410_CS3 + 7,
129 .flags = IORESOURCE_MEM
130 },
131 [2] = {
132 .start = IRQ_EINT7,
133 .end = IRQ_EINT7,
134 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
135 }
136};
137
138static struct dm9000_plat_data at2440evb_dm9k_pdata = {
139 .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
140};
141
142static struct platform_device at2440evb_device_eth = {
143 .name = "dm9000",
144 .id = -1,
145 .num_resources = ARRAY_SIZE(at2440evb_dm9k_resource),
146 .resource = at2440evb_dm9k_resource,
147 .dev = {
148 .platform_data = &at2440evb_dm9k_pdata,
149 },
150};
151
152static struct s3c24xx_mci_pdata at2440evb_mci_pdata __initdata = {
153 .gpio_detect = S3C2410_GPG(10),
154};
155
156/* 7" LCD panel */
157
158static struct s3c2410fb_display at2440evb_lcd_cfg __initdata = {
159
160 .lcdcon5 = S3C2410_LCDCON5_FRM565 |
161 S3C2410_LCDCON5_INVVLINE |
162 S3C2410_LCDCON5_INVVFRAME |
163 S3C2410_LCDCON5_PWREN |
164 S3C2410_LCDCON5_HWSWP,
165
166 .type = S3C2410_LCDCON1_TFT,
167
168 .width = 800,
169 .height = 480,
170
171 .pixclock = 33333, /* HCLK 60 MHz, divisor 2 */
172 .xres = 800,
173 .yres = 480,
174 .bpp = 16,
175 .left_margin = 88,
176 .right_margin = 40,
177 .hsync_len = 128,
178 .upper_margin = 32,
179 .lower_margin = 11,
180 .vsync_len = 2,
181};
182
183static struct s3c2410fb_mach_info at2440evb_fb_info __initdata = {
184 .displays = &at2440evb_lcd_cfg,
185 .num_displays = 1,
186 .default_display = 0,
187};
188
189static struct platform_device *at2440evb_devices[] __initdata = {
190 &s3c_device_ohci,
191 &s3c_device_wdt,
192 &s3c_device_adc,
193 &s3c_device_i2c0,
194 &s3c_device_rtc,
195 &s3c_device_nand,
196 &s3c_device_sdi,
197 &s3c_device_lcd,
198 &at2440evb_device_eth,
199};
200
201static void __init at2440evb_map_io(void)
202{
203 s3c24xx_init_io(at2440evb_iodesc, ARRAY_SIZE(at2440evb_iodesc));
204 s3c24xx_init_clocks(16934400);
205 s3c24xx_init_uarts(at2440evb_uartcfgs, ARRAY_SIZE(at2440evb_uartcfgs));
206}
207
208static void __init at2440evb_init(void)
209{
210 s3c24xx_fb_set_platdata(&at2440evb_fb_info);
211 s3c24xx_mci_set_platdata(&at2440evb_mci_pdata);
212 s3c_nand_set_platdata(&at2440evb_nand_info);
213 s3c_i2c0_set_platdata(NULL);
214
215 platform_add_devices(at2440evb_devices, ARRAY_SIZE(at2440evb_devices));
216}
217
218
219MACHINE_START(AT2440EVB, "AT2440EVB")
220 .atag_offset = 0x100,
221 .map_io = at2440evb_map_io,
222 .init_machine = at2440evb_init,
223 .init_irq = s3c24xx_init_irq,
224 .timer = &s3c24xx_timer,
225 .restart = s3c2440_restart,
226MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c
new file mode 100644
index 000000000000..cf270f51d149
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/mach-gta02.c
@@ -0,0 +1,605 @@
1/*
2 * linux/arch/arm/mach-s3c2442/mach-gta02.c
3 *
4 * S3C2442 Machine Support for Openmoko GTA02 / FreeRunner.
5 *
6 * Copyright (C) 2006-2009 by Openmoko, Inc.
7 * Authors: Harald Welte <laforge@openmoko.org>
8 * Andy Green <andy@openmoko.org>
9 * Werner Almesberger <werner@openmoko.org>
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * MA 02111-1307 USA
26 *
27 */
28
29#include <linux/kernel.h>
30#include <linux/types.h>
31#include <linux/interrupt.h>
32#include <linux/list.h>
33#include <linux/delay.h>
34#include <linux/timer.h>
35#include <linux/init.h>
36#include <linux/gpio.h>
37#include <linux/workqueue.h>
38#include <linux/platform_device.h>
39#include <linux/serial_core.h>
40#include <linux/spi/spi.h>
41#include <linux/spi/s3c24xx.h>
42
43#include <linux/mmc/host.h>
44
45#include <linux/mtd/mtd.h>
46#include <linux/mtd/nand.h>
47#include <linux/mtd/nand_ecc.h>
48#include <linux/mtd/partitions.h>
49#include <linux/mtd/physmap.h>
50#include <linux/io.h>
51
52#include <linux/i2c.h>
53#include <linux/regulator/machine.h>
54
55#include <linux/mfd/pcf50633/core.h>
56#include <linux/mfd/pcf50633/mbc.h>
57#include <linux/mfd/pcf50633/adc.h>
58#include <linux/mfd/pcf50633/gpio.h>
59#include <linux/mfd/pcf50633/pmic.h>
60#include <linux/mfd/pcf50633/backlight.h>
61
62#include <linux/input.h>
63#include <linux/gpio_keys.h>
64
65#include <asm/mach/arch.h>
66#include <asm/mach/map.h>
67#include <asm/mach/irq.h>
68
69#include <asm/irq.h>
70#include <asm/mach-types.h>
71
72#include <mach/regs-irq.h>
73#include <mach/regs-gpio.h>
74#include <mach/regs-gpioj.h>
75#include <mach/fb.h>
76
77#include <plat/usb-control.h>
78#include <mach/regs-mem.h>
79#include <mach/hardware.h>
80
81#include <mach/gta02.h>
82
83#include <plat/regs-serial.h>
84#include <plat/nand.h>
85#include <plat/devs.h>
86#include <plat/cpu.h>
87#include <plat/pm.h>
88#include <plat/udc.h>
89#include <plat/gpio-cfg.h>
90#include <plat/iic.h>
91#include <plat/ts.h>
92
93#include "common.h"
94
95static struct pcf50633 *gta02_pcf;
96
97/*
98 * This gets called frequently when we paniced.
99 */
100
101static long gta02_panic_blink(int state)
102{
103 long delay = 0;
104 char led;
105
106 led = (state) ? 1 : 0;
107 gpio_direction_output(GTA02_GPIO_AUX_LED, led);
108
109 return delay;
110}
111
112
113static struct map_desc gta02_iodesc[] __initdata = {
114 {
115 .virtual = 0xe0000000,
116 .pfn = __phys_to_pfn(S3C2410_CS3 + 0x01000000),
117 .length = SZ_1M,
118 .type = MT_DEVICE
119 },
120};
121
122#define UCON (S3C2410_UCON_DEFAULT | S3C2443_UCON_RXERR_IRQEN)
123#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
124#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
125
126static struct s3c2410_uartcfg gta02_uartcfgs[] = {
127 [0] = {
128 .hwport = 0,
129 .flags = 0,
130 .ucon = UCON,
131 .ulcon = ULCON,
132 .ufcon = UFCON,
133 },
134 [1] = {
135 .hwport = 1,
136 .flags = 0,
137 .ucon = UCON,
138 .ulcon = ULCON,
139 .ufcon = UFCON,
140 },
141 [2] = {
142 .hwport = 2,
143 .flags = 0,
144 .ucon = UCON,
145 .ulcon = ULCON,
146 .ufcon = UFCON,
147 },
148};
149
150#ifdef CONFIG_CHARGER_PCF50633
151/*
152 * On GTA02 the 1A charger features a 48K resistor to 0V on the ID pin.
153 * We use this to recognize that we can pull 1A from the USB socket.
154 *
155 * These constants are the measured pcf50633 ADC levels with the 1A
156 * charger / 48K resistor, and with no pulldown resistor.
157 */
158
159#define ADC_NOM_CHG_DETECT_1A 6
160#define ADC_NOM_CHG_DETECT_USB 43
161
162static void
163gta02_configure_pmu_for_charger(struct pcf50633 *pcf, void *unused, int res)
164{
165 int ma;
166
167 /* Interpret charger type */
168 if (res < ((ADC_NOM_CHG_DETECT_USB + ADC_NOM_CHG_DETECT_1A) / 2)) {
169
170 /*
171 * Sanity - stop GPO driving out now that we have a 1A charger
172 * GPO controls USB Host power generation on GTA02
173 */
174 pcf50633_gpio_set(pcf, PCF50633_GPO, 0);
175
176 ma = 1000;
177 } else
178 ma = 100;
179
180 pcf50633_mbc_usb_curlim_set(pcf, ma);
181}
182
183static struct delayed_work gta02_charger_work;
184static int gta02_usb_vbus_draw;
185
186static void gta02_charger_worker(struct work_struct *work)
187{
188 if (gta02_usb_vbus_draw) {
189 pcf50633_mbc_usb_curlim_set(gta02_pcf, gta02_usb_vbus_draw);
190 return;
191 }
192
193#ifdef CONFIG_PCF50633_ADC
194 pcf50633_adc_async_read(gta02_pcf,
195 PCF50633_ADCC1_MUX_ADCIN1,
196 PCF50633_ADCC1_AVERAGE_16,
197 gta02_configure_pmu_for_charger,
198 NULL);
199#else
200 /*
201 * If the PCF50633 ADC is disabled we fallback to a
202 * 100mA limit for safety.
203 */
204 pcf50633_mbc_usb_curlim_set(pcf, 100);
205#endif
206}
207
208#define GTA02_CHARGER_CONFIGURE_TIMEOUT ((3000 * HZ) / 1000)
209
210static void gta02_pmu_event_callback(struct pcf50633 *pcf, int irq)
211{
212 if (irq == PCF50633_IRQ_USBINS) {
213 schedule_delayed_work(&gta02_charger_work,
214 GTA02_CHARGER_CONFIGURE_TIMEOUT);
215
216 return;
217 }
218
219 if (irq == PCF50633_IRQ_USBREM) {
220 cancel_delayed_work_sync(&gta02_charger_work);
221 gta02_usb_vbus_draw = 0;
222 }
223}
224
225static void gta02_udc_vbus_draw(unsigned int ma)
226{
227 if (!gta02_pcf)
228 return;
229
230 gta02_usb_vbus_draw = ma;
231
232 schedule_delayed_work(&gta02_charger_work,
233 GTA02_CHARGER_CONFIGURE_TIMEOUT);
234}
235#else /* !CONFIG_CHARGER_PCF50633 */
236#define gta02_pmu_event_callback NULL
237#define gta02_udc_vbus_draw NULL
238#endif
239
240/*
241 * This is called when pc50633 is probed, unfortunately quite late in the
242 * day since it is an I2C bus device. Here we can belatedly define some
243 * platform devices with the advantage that we can mark the pcf50633 as the
244 * parent. This makes them get suspended and resumed with their parent
245 * the pcf50633 still around.
246 */
247
248static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf);
249
250
251static char *gta02_batteries[] = {
252 "battery",
253};
254
255static struct pcf50633_bl_platform_data gta02_backlight_data = {
256 .default_brightness = 0x3f,
257 .default_brightness_limit = 0,
258 .ramp_time = 5,
259};
260
261struct pcf50633_platform_data gta02_pcf_pdata = {
262 .resumers = {
263 [0] = PCF50633_INT1_USBINS |
264 PCF50633_INT1_USBREM |
265 PCF50633_INT1_ALARM,
266 [1] = PCF50633_INT2_ONKEYF,
267 [2] = PCF50633_INT3_ONKEY1S,
268 [3] = PCF50633_INT4_LOWSYS |
269 PCF50633_INT4_LOWBAT |
270 PCF50633_INT4_HIGHTMP,
271 },
272
273 .batteries = gta02_batteries,
274 .num_batteries = ARRAY_SIZE(gta02_batteries),
275
276 .charger_reference_current_ma = 1000,
277
278 .backlight_data = &gta02_backlight_data,
279
280 .reg_init_data = {
281 [PCF50633_REGULATOR_AUTO] = {
282 .constraints = {
283 .min_uV = 3300000,
284 .max_uV = 3300000,
285 .valid_modes_mask = REGULATOR_MODE_NORMAL,
286 .always_on = 1,
287 .apply_uV = 1,
288 },
289 },
290 [PCF50633_REGULATOR_DOWN1] = {
291 .constraints = {
292 .min_uV = 1300000,
293 .max_uV = 1600000,
294 .valid_modes_mask = REGULATOR_MODE_NORMAL,
295 .always_on = 1,
296 .apply_uV = 1,
297 },
298 },
299 [PCF50633_REGULATOR_DOWN2] = {
300 .constraints = {
301 .min_uV = 1800000,
302 .max_uV = 1800000,
303 .valid_modes_mask = REGULATOR_MODE_NORMAL,
304 .apply_uV = 1,
305 .always_on = 1,
306 },
307 },
308 [PCF50633_REGULATOR_HCLDO] = {
309 .constraints = {
310 .min_uV = 2000000,
311 .max_uV = 3300000,
312 .valid_modes_mask = REGULATOR_MODE_NORMAL,
313 .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
314 REGULATOR_CHANGE_STATUS,
315 },
316 },
317 [PCF50633_REGULATOR_LDO1] = {
318 .constraints = {
319 .min_uV = 3300000,
320 .max_uV = 3300000,
321 .valid_modes_mask = REGULATOR_MODE_NORMAL,
322 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
323 .apply_uV = 1,
324 },
325 },
326 [PCF50633_REGULATOR_LDO2] = {
327 .constraints = {
328 .min_uV = 3300000,
329 .max_uV = 3300000,
330 .valid_modes_mask = REGULATOR_MODE_NORMAL,
331 .apply_uV = 1,
332 },
333 },
334 [PCF50633_REGULATOR_LDO3] = {
335 .constraints = {
336 .min_uV = 3000000,
337 .max_uV = 3000000,
338 .valid_modes_mask = REGULATOR_MODE_NORMAL,
339 .apply_uV = 1,
340 },
341 },
342 [PCF50633_REGULATOR_LDO4] = {
343 .constraints = {
344 .min_uV = 3200000,
345 .max_uV = 3200000,
346 .valid_modes_mask = REGULATOR_MODE_NORMAL,
347 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
348 .apply_uV = 1,
349 },
350 },
351 [PCF50633_REGULATOR_LDO5] = {
352 .constraints = {
353 .min_uV = 3000000,
354 .max_uV = 3000000,
355 .valid_modes_mask = REGULATOR_MODE_NORMAL,
356 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
357 .apply_uV = 1,
358 },
359 },
360 [PCF50633_REGULATOR_LDO6] = {
361 .constraints = {
362 .min_uV = 3000000,
363 .max_uV = 3000000,
364 .valid_modes_mask = REGULATOR_MODE_NORMAL,
365 },
366 },
367 [PCF50633_REGULATOR_MEMLDO] = {
368 .constraints = {
369 .min_uV = 1800000,
370 .max_uV = 1800000,
371 .valid_modes_mask = REGULATOR_MODE_NORMAL,
372 },
373 },
374
375 },
376 .probe_done = gta02_pmu_attach_child_devices,
377 .mbc_event_callback = gta02_pmu_event_callback,
378};
379
380
381/* NOR Flash. */
382
383#define GTA02_FLASH_BASE 0x18000000 /* GCS3 */
384#define GTA02_FLASH_SIZE 0x200000 /* 2MBytes */
385
386static struct physmap_flash_data gta02_nor_flash_data = {
387 .width = 2,
388};
389
390static struct resource gta02_nor_flash_resource = {
391 .start = GTA02_FLASH_BASE,
392 .end = GTA02_FLASH_BASE + GTA02_FLASH_SIZE - 1,
393 .flags = IORESOURCE_MEM,
394};
395
396static struct platform_device gta02_nor_flash = {
397 .name = "physmap-flash",
398 .id = 0,
399 .dev = {
400 .platform_data = &gta02_nor_flash_data,
401 },
402 .resource = &gta02_nor_flash_resource,
403 .num_resources = 1,
404};
405
406
407struct platform_device s3c24xx_pwm_device = {
408 .name = "s3c24xx_pwm",
409 .num_resources = 0,
410};
411
412static struct platform_device gta02_dfbmcs320_device = {
413 .name = "dfbmcs320",
414};
415
416static struct i2c_board_info gta02_i2c_devs[] __initdata = {
417 {
418 I2C_BOARD_INFO("pcf50633", 0x73),
419 .irq = GTA02_IRQ_PCF50633,
420 .platform_data = &gta02_pcf_pdata,
421 },
422 {
423 I2C_BOARD_INFO("wm8753", 0x1a),
424 },
425};
426
427static struct s3c2410_nand_set __initdata gta02_nand_sets[] = {
428 [0] = {
429 /*
430 * This name is also hard-coded in the boot loaders, so
431 * changing it would would require all users to upgrade
432 * their boot loaders, some of which are stored in a NOR
433 * that is considered to be immutable.
434 */
435 .name = "neo1973-nand",
436 .nr_chips = 1,
437 .flash_bbt = 1,
438 },
439};
440
441/*
442 * Choose a set of timings derived from S3C@2442B MCP54
443 * data sheet (K5D2G13ACM-D075 MCP Memory).
444 */
445
446static struct s3c2410_platform_nand __initdata gta02_nand_info = {
447 .tacls = 0,
448 .twrph0 = 25,
449 .twrph1 = 15,
450 .nr_sets = ARRAY_SIZE(gta02_nand_sets),
451 .sets = gta02_nand_sets,
452};
453
454
455/* Get PMU to set USB current limit accordingly. */
456static struct s3c2410_udc_mach_info gta02_udc_cfg __initdata = {
457 .vbus_draw = gta02_udc_vbus_draw,
458 .pullup_pin = GTA02_GPIO_USB_PULLUP,
459};
460
461/* USB */
462static struct s3c2410_hcd_info gta02_usb_info __initdata = {
463 .port[0] = {
464 .flags = S3C_HCDFLG_USED,
465 },
466 .port[1] = {
467 .flags = 0,
468 },
469};
470
471/* Touchscreen */
472static struct s3c2410_ts_mach_info gta02_ts_info = {
473 .delay = 10000,
474 .presc = 0xff, /* slow as we can go */
475 .oversampling_shift = 2,
476};
477
478/* Buttons */
479static struct gpio_keys_button gta02_buttons[] = {
480 {
481 .gpio = GTA02_GPIO_AUX_KEY,
482 .code = KEY_PHONE,
483 .desc = "Aux",
484 .type = EV_KEY,
485 .debounce_interval = 100,
486 },
487 {
488 .gpio = GTA02_GPIO_HOLD_KEY,
489 .code = KEY_PAUSE,
490 .desc = "Hold",
491 .type = EV_KEY,
492 .debounce_interval = 100,
493 },
494};
495
496static struct gpio_keys_platform_data gta02_buttons_pdata = {
497 .buttons = gta02_buttons,
498 .nbuttons = ARRAY_SIZE(gta02_buttons),
499};
500
501static struct platform_device gta02_buttons_device = {
502 .name = "gpio-keys",
503 .id = -1,
504 .dev = {
505 .platform_data = &gta02_buttons_pdata,
506 },
507};
508
509static void __init gta02_map_io(void)
510{
511 s3c24xx_init_io(gta02_iodesc, ARRAY_SIZE(gta02_iodesc));
512 s3c24xx_init_clocks(12000000);
513 s3c24xx_init_uarts(gta02_uartcfgs, ARRAY_SIZE(gta02_uartcfgs));
514}
515
516
517/* These are the guys that don't need to be children of PMU. */
518
519static struct platform_device *gta02_devices[] __initdata = {
520 &s3c_device_ohci,
521 &s3c_device_wdt,
522 &s3c_device_sdi,
523 &s3c_device_usbgadget,
524 &s3c_device_nand,
525 &gta02_nor_flash,
526 &s3c24xx_pwm_device,
527 &s3c_device_iis,
528 &samsung_asoc_dma,
529 &s3c_device_i2c0,
530 &gta02_dfbmcs320_device,
531 &gta02_buttons_device,
532 &s3c_device_adc,
533 &s3c_device_ts,
534};
535
536/* These guys DO need to be children of PMU. */
537
538static struct platform_device *gta02_devices_pmu_children[] = {
539};
540
541
542/*
543 * This is called when pc50633 is probed, quite late in the day since it is an
544 * I2C bus device. Here we can define platform devices with the advantage that
545 * we can mark the pcf50633 as the parent. This makes them get suspended and
546 * resumed with their parent the pcf50633 still around. All devices whose
547 * operation depends on something from pcf50633 must have this relationship
548 * made explicit like this, or suspend and resume will become an unreliable
549 * hellworld.
550 */
551
552static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf)
553{
554 int n;
555
556 /* Grab a copy of the now probed PMU pointer. */
557 gta02_pcf = pcf;
558
559 for (n = 0; n < ARRAY_SIZE(gta02_devices_pmu_children); n++)
560 gta02_devices_pmu_children[n]->dev.parent = pcf->dev;
561
562 platform_add_devices(gta02_devices_pmu_children,
563 ARRAY_SIZE(gta02_devices_pmu_children));
564}
565
566static void gta02_poweroff(void)
567{
568 pcf50633_reg_set_bit_mask(gta02_pcf, PCF50633_REG_OOCSHDWN, 1, 1);
569}
570
571static void __init gta02_machine_init(void)
572{
573 /* Set the panic callback to turn AUX LED on or off. */
574 panic_blink = gta02_panic_blink;
575
576 s3c_pm_init();
577
578#ifdef CONFIG_CHARGER_PCF50633
579 INIT_DELAYED_WORK(&gta02_charger_work, gta02_charger_worker);
580#endif
581
582 s3c24xx_udc_set_platdata(&gta02_udc_cfg);
583 s3c24xx_ts_set_platdata(&gta02_ts_info);
584 s3c_ohci_set_platdata(&gta02_usb_info);
585 s3c_nand_set_platdata(&gta02_nand_info);
586 s3c_i2c0_set_platdata(NULL);
587
588 i2c_register_board_info(0, gta02_i2c_devs, ARRAY_SIZE(gta02_i2c_devs));
589
590 platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices));
591 pm_power_off = gta02_poweroff;
592
593 regulator_has_full_constraints();
594}
595
596
597MACHINE_START(NEO1973_GTA02, "GTA02")
598 /* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */
599 .atag_offset = 0x100,
600 .map_io = gta02_map_io,
601 .init_irq = s3c24xx_init_irq,
602 .init_machine = gta02_machine_init,
603 .timer = &s3c24xx_timer,
604 .restart = s3c2440_restart,
605MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c
new file mode 100644
index 000000000000..adbbb85bc4cd
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/mach-mini2440.c
@@ -0,0 +1,705 @@
1/* linux/arch/arm/mach-s3c2440/mach-mini2440.c
2 *
3 * Copyright (c) 2008 Ramax Lo <ramaxlo@gmail.com>
4 * Based on mach-anubis.c by Ben Dooks <ben@simtec.co.uk>
5 * and modifications by SBZ <sbz@spgui.org> and
6 * Weibing <http://weibing.blogbus.com> and
7 * Michel Pollet <buserror@gmail.com>
8 *
9 * For product information, visit http://code.google.com/p/mini2440/
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/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/gpio.h>
23#include <linux/input.h>
24#include <linux/io.h>
25#include <linux/serial_core.h>
26#include <linux/dm9000.h>
27#include <linux/i2c/at24.h>
28#include <linux/platform_device.h>
29#include <linux/gpio_keys.h>
30#include <linux/i2c.h>
31#include <linux/mmc/host.h>
32
33#include <asm/mach/arch.h>
34#include <asm/mach/map.h>
35
36#include <mach/hardware.h>
37#include <mach/fb.h>
38#include <asm/mach-types.h>
39
40#include <plat/regs-serial.h>
41#include <mach/regs-gpio.h>
42#include <mach/leds-gpio.h>
43#include <mach/regs-mem.h>
44#include <mach/regs-lcd.h>
45#include <mach/irqs.h>
46#include <plat/nand.h>
47#include <plat/iic.h>
48#include <plat/mci.h>
49#include <plat/udc.h>
50
51#include <linux/mtd/mtd.h>
52#include <linux/mtd/nand.h>
53#include <linux/mtd/nand_ecc.h>
54#include <linux/mtd/partitions.h>
55
56#include <plat/gpio-cfg.h>
57#include <plat/clock.h>
58#include <plat/devs.h>
59#include <plat/cpu.h>
60
61#include <sound/s3c24xx_uda134x.h>
62
63#include "common.h"
64
65#define MACH_MINI2440_DM9K_BASE (S3C2410_CS4 + 0x300)
66
67static struct map_desc mini2440_iodesc[] __initdata = {
68 /* nothing to declare, move along */
69};
70
71#define UCON S3C2410_UCON_DEFAULT
72#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
73#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
74
75
76static struct s3c2410_uartcfg mini2440_uartcfgs[] __initdata = {
77 [0] = {
78 .hwport = 0,
79 .flags = 0,
80 .ucon = UCON,
81 .ulcon = ULCON,
82 .ufcon = UFCON,
83 },
84 [1] = {
85 .hwport = 1,
86 .flags = 0,
87 .ucon = UCON,
88 .ulcon = ULCON,
89 .ufcon = UFCON,
90 },
91 [2] = {
92 .hwport = 2,
93 .flags = 0,
94 .ucon = UCON,
95 .ulcon = ULCON,
96 .ufcon = UFCON,
97 },
98};
99
100/* USB device UDC support */
101
102static struct s3c2410_udc_mach_info mini2440_udc_cfg __initdata = {
103 .pullup_pin = S3C2410_GPC(5),
104};
105
106
107/* LCD timing and setup */
108
109/*
110 * This macro simplifies the table bellow
111 */
112#define _LCD_DECLARE(_clock,_xres,margin_left,margin_right,hsync, \
113 _yres,margin_top,margin_bottom,vsync, refresh) \
114 .width = _xres, \
115 .xres = _xres, \
116 .height = _yres, \
117 .yres = _yres, \
118 .left_margin = margin_left, \
119 .right_margin = margin_right, \
120 .upper_margin = margin_top, \
121 .lower_margin = margin_bottom, \
122 .hsync_len = hsync, \
123 .vsync_len = vsync, \
124 .pixclock = ((_clock*100000000000LL) / \
125 ((refresh) * \
126 (hsync + margin_left + _xres + margin_right) * \
127 (vsync + margin_top + _yres + margin_bottom))), \
128 .bpp = 16,\
129 .type = (S3C2410_LCDCON1_TFT16BPP |\
130 S3C2410_LCDCON1_TFT)
131
132static struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = {
133 [0] = { /* mini2440 + 3.5" TFT + touchscreen */
134 _LCD_DECLARE(
135 7, /* The 3.5 is quite fast */
136 240, 21, 38, 6, /* x timing */
137 320, 4, 4, 2, /* y timing */
138 60), /* refresh rate */
139 .lcdcon5 = (S3C2410_LCDCON5_FRM565 |
140 S3C2410_LCDCON5_INVVLINE |
141 S3C2410_LCDCON5_INVVFRAME |
142 S3C2410_LCDCON5_INVVDEN |
143 S3C2410_LCDCON5_PWREN),
144 },
145 [1] = { /* mini2440 + 7" TFT + touchscreen */
146 _LCD_DECLARE(
147 10, /* the 7" runs slower */
148 800, 40, 40, 48, /* x timing */
149 480, 29, 3, 3, /* y timing */
150 50), /* refresh rate */
151 .lcdcon5 = (S3C2410_LCDCON5_FRM565 |
152 S3C2410_LCDCON5_INVVLINE |
153 S3C2410_LCDCON5_INVVFRAME |
154 S3C2410_LCDCON5_PWREN),
155 },
156 /* The VGA shield can outout at several resolutions. All share
157 * the same timings, however, anything smaller than 1024x768
158 * will only be displayed in the top left corner of a 1024x768
159 * XGA output unless you add optional dip switches to the shield.
160 * Therefore timings for other resolutions have been omitted here.
161 */
162 [2] = {
163 _LCD_DECLARE(
164 10,
165 1024, 1, 2, 2, /* y timing */
166 768, 200, 16, 16, /* x timing */
167 24), /* refresh rate, maximum stable,
168 tested with the FPGA shield */
169 .lcdcon5 = (S3C2410_LCDCON5_FRM565 |
170 S3C2410_LCDCON5_HWSWP),
171 },
172 /* mini2440 + 3.5" TFT (LCD-W35i, LQ035Q1DG06 type) + touchscreen*/
173 [3] = {
174 _LCD_DECLARE(
175 /* clock */
176 7,
177 /* xres, margin_right, margin_left, hsync */
178 320, 68, 66, 4,
179 /* yres, margin_top, margin_bottom, vsync */
180 240, 4, 4, 9,
181 /* refresh rate */
182 60),
183 .lcdcon5 = (S3C2410_LCDCON5_FRM565 |
184 S3C2410_LCDCON5_INVVDEN |
185 S3C2410_LCDCON5_INVVFRAME |
186 S3C2410_LCDCON5_INVVLINE |
187 S3C2410_LCDCON5_INVVCLK |
188 S3C2410_LCDCON5_HWSWP),
189 },
190};
191
192/* todo - put into gpio header */
193
194#define S3C2410_GPCCON_MASK(x) (3 << ((x) * 2))
195#define S3C2410_GPDCON_MASK(x) (3 << ((x) * 2))
196
197static struct s3c2410fb_mach_info mini2440_fb_info __initdata = {
198 .displays = &mini2440_lcd_cfg[0], /* not constant! see init */
199 .num_displays = 1,
200 .default_display = 0,
201
202 /* Enable VD[2..7], VD[10..15], VD[18..23] and VCLK, syncs, VDEN
203 * and disable the pull down resistors on pins we are using for LCD
204 * data. */
205
206 .gpcup = (0xf << 1) | (0x3f << 10),
207
208 .gpccon = (S3C2410_GPC1_VCLK | S3C2410_GPC2_VLINE |
209 S3C2410_GPC3_VFRAME | S3C2410_GPC4_VM |
210 S3C2410_GPC10_VD2 | S3C2410_GPC11_VD3 |
211 S3C2410_GPC12_VD4 | S3C2410_GPC13_VD5 |
212 S3C2410_GPC14_VD6 | S3C2410_GPC15_VD7),
213
214 .gpccon_mask = (S3C2410_GPCCON_MASK(1) | S3C2410_GPCCON_MASK(2) |
215 S3C2410_GPCCON_MASK(3) | S3C2410_GPCCON_MASK(4) |
216 S3C2410_GPCCON_MASK(10) | S3C2410_GPCCON_MASK(11) |
217 S3C2410_GPCCON_MASK(12) | S3C2410_GPCCON_MASK(13) |
218 S3C2410_GPCCON_MASK(14) | S3C2410_GPCCON_MASK(15)),
219
220 .gpdup = (0x3f << 2) | (0x3f << 10),
221
222 .gpdcon = (S3C2410_GPD2_VD10 | S3C2410_GPD3_VD11 |
223 S3C2410_GPD4_VD12 | S3C2410_GPD5_VD13 |
224 S3C2410_GPD6_VD14 | S3C2410_GPD7_VD15 |
225 S3C2410_GPD10_VD18 | S3C2410_GPD11_VD19 |
226 S3C2410_GPD12_VD20 | S3C2410_GPD13_VD21 |
227 S3C2410_GPD14_VD22 | S3C2410_GPD15_VD23),
228
229 .gpdcon_mask = (S3C2410_GPDCON_MASK(2) | S3C2410_GPDCON_MASK(3) |
230 S3C2410_GPDCON_MASK(4) | S3C2410_GPDCON_MASK(5) |
231 S3C2410_GPDCON_MASK(6) | S3C2410_GPDCON_MASK(7) |
232 S3C2410_GPDCON_MASK(10) | S3C2410_GPDCON_MASK(11)|
233 S3C2410_GPDCON_MASK(12) | S3C2410_GPDCON_MASK(13)|
234 S3C2410_GPDCON_MASK(14) | S3C2410_GPDCON_MASK(15)),
235};
236
237/* MMC/SD */
238
239static struct s3c24xx_mci_pdata mini2440_mmc_cfg __initdata = {
240 .gpio_detect = S3C2410_GPG(8),
241 .gpio_wprotect = S3C2410_GPH(8),
242 .set_power = NULL,
243 .ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34,
244};
245
246/* NAND Flash on MINI2440 board */
247
248static struct mtd_partition mini2440_default_nand_part[] __initdata = {
249 [0] = {
250 .name = "u-boot",
251 .size = SZ_256K,
252 .offset = 0,
253 },
254 [1] = {
255 .name = "u-boot-env",
256 .size = SZ_128K,
257 .offset = SZ_256K,
258 },
259 [2] = {
260 .name = "kernel",
261 /* 5 megabytes, for a kernel with no modules
262 * or a uImage with a ramdisk attached */
263 .size = 0x00500000,
264 .offset = SZ_256K + SZ_128K,
265 },
266 [3] = {
267 .name = "root",
268 .offset = SZ_256K + SZ_128K + 0x00500000,
269 .size = MTDPART_SIZ_FULL,
270 },
271};
272
273static struct s3c2410_nand_set mini2440_nand_sets[] __initdata = {
274 [0] = {
275 .name = "nand",
276 .nr_chips = 1,
277 .nr_partitions = ARRAY_SIZE(mini2440_default_nand_part),
278 .partitions = mini2440_default_nand_part,
279 .flash_bbt = 1, /* we use u-boot to create a BBT */
280 },
281};
282
283static struct s3c2410_platform_nand mini2440_nand_info __initdata = {
284 .tacls = 0,
285 .twrph0 = 25,
286 .twrph1 = 15,
287 .nr_sets = ARRAY_SIZE(mini2440_nand_sets),
288 .sets = mini2440_nand_sets,
289 .ignore_unset_ecc = 1,
290};
291
292/* DM9000AEP 10/100 ethernet controller */
293
294static struct resource mini2440_dm9k_resource[] = {
295 [0] = {
296 .start = MACH_MINI2440_DM9K_BASE,
297 .end = MACH_MINI2440_DM9K_BASE + 3,
298 .flags = IORESOURCE_MEM
299 },
300 [1] = {
301 .start = MACH_MINI2440_DM9K_BASE + 4,
302 .end = MACH_MINI2440_DM9K_BASE + 7,
303 .flags = IORESOURCE_MEM
304 },
305 [2] = {
306 .start = IRQ_EINT7,
307 .end = IRQ_EINT7,
308 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
309 }
310};
311
312/*
313 * The DM9000 has no eeprom, and it's MAC address is set by
314 * the bootloader before starting the kernel.
315 */
316static struct dm9000_plat_data mini2440_dm9k_pdata = {
317 .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
318};
319
320static struct platform_device mini2440_device_eth = {
321 .name = "dm9000",
322 .id = -1,
323 .num_resources = ARRAY_SIZE(mini2440_dm9k_resource),
324 .resource = mini2440_dm9k_resource,
325 .dev = {
326 .platform_data = &mini2440_dm9k_pdata,
327 },
328};
329
330/* CON5
331 * +--+ /-----\
332 * | | | |
333 * | | | BAT |
334 * | | \_____/
335 * | |
336 * | | +----+ +----+
337 * | | | K5 | | K1 |
338 * | | +----+ +----+
339 * | | +----+ +----+
340 * | | | K4 | | K2 |
341 * | | +----+ +----+
342 * | | +----+ +----+
343 * | | | K6 | | K3 |
344 * | | +----+ +----+
345 * .....
346 */
347static struct gpio_keys_button mini2440_buttons[] = {
348 {
349 .gpio = S3C2410_GPG(0), /* K1 */
350 .code = KEY_F1,
351 .desc = "Button 1",
352 .active_low = 1,
353 },
354 {
355 .gpio = S3C2410_GPG(3), /* K2 */
356 .code = KEY_F2,
357 .desc = "Button 2",
358 .active_low = 1,
359 },
360 {
361 .gpio = S3C2410_GPG(5), /* K3 */
362 .code = KEY_F3,
363 .desc = "Button 3",
364 .active_low = 1,
365 },
366 {
367 .gpio = S3C2410_GPG(6), /* K4 */
368 .code = KEY_POWER,
369 .desc = "Power",
370 .active_low = 1,
371 },
372 {
373 .gpio = S3C2410_GPG(7), /* K5 */
374 .code = KEY_F5,
375 .desc = "Button 5",
376 .active_low = 1,
377 },
378#if 0
379 /* this pin is also known as TCLK1 and seems to already
380 * marked as "in use" somehow in the kernel -- possibly wrongly */
381 {
382 .gpio = S3C2410_GPG(11), /* K6 */
383 .code = KEY_F6,
384 .desc = "Button 6",
385 .active_low = 1,
386 },
387#endif
388};
389
390static struct gpio_keys_platform_data mini2440_button_data = {
391 .buttons = mini2440_buttons,
392 .nbuttons = ARRAY_SIZE(mini2440_buttons),
393};
394
395static struct platform_device mini2440_button_device = {
396 .name = "gpio-keys",
397 .id = -1,
398 .dev = {
399 .platform_data = &mini2440_button_data,
400 }
401};
402
403/* LEDS */
404
405static struct s3c24xx_led_platdata mini2440_led1_pdata = {
406 .name = "led1",
407 .gpio = S3C2410_GPB(5),
408 .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
409 .def_trigger = "heartbeat",
410};
411
412static struct s3c24xx_led_platdata mini2440_led2_pdata = {
413 .name = "led2",
414 .gpio = S3C2410_GPB(6),
415 .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
416 .def_trigger = "nand-disk",
417};
418
419static struct s3c24xx_led_platdata mini2440_led3_pdata = {
420 .name = "led3",
421 .gpio = S3C2410_GPB(7),
422 .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
423 .def_trigger = "mmc0",
424};
425
426static struct s3c24xx_led_platdata mini2440_led4_pdata = {
427 .name = "led4",
428 .gpio = S3C2410_GPB(8),
429 .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
430 .def_trigger = "",
431};
432
433static struct s3c24xx_led_platdata mini2440_led_backlight_pdata = {
434 .name = "backlight",
435 .gpio = S3C2410_GPG(4),
436 .def_trigger = "backlight",
437};
438
439static struct platform_device mini2440_led1 = {
440 .name = "s3c24xx_led",
441 .id = 1,
442 .dev = {
443 .platform_data = &mini2440_led1_pdata,
444 },
445};
446
447static struct platform_device mini2440_led2 = {
448 .name = "s3c24xx_led",
449 .id = 2,
450 .dev = {
451 .platform_data = &mini2440_led2_pdata,
452 },
453};
454
455static struct platform_device mini2440_led3 = {
456 .name = "s3c24xx_led",
457 .id = 3,
458 .dev = {
459 .platform_data = &mini2440_led3_pdata,
460 },
461};
462
463static struct platform_device mini2440_led4 = {
464 .name = "s3c24xx_led",
465 .id = 4,
466 .dev = {
467 .platform_data = &mini2440_led4_pdata,
468 },
469};
470
471static struct platform_device mini2440_led_backlight = {
472 .name = "s3c24xx_led",
473 .id = 5,
474 .dev = {
475 .platform_data = &mini2440_led_backlight_pdata,
476 },
477};
478
479/* AUDIO */
480
481static struct s3c24xx_uda134x_platform_data mini2440_audio_pins = {
482 .l3_clk = S3C2410_GPB(4),
483 .l3_mode = S3C2410_GPB(2),
484 .l3_data = S3C2410_GPB(3),
485 .model = UDA134X_UDA1341
486};
487
488static struct platform_device mini2440_audio = {
489 .name = "s3c24xx_uda134x",
490 .id = 0,
491 .dev = {
492 .platform_data = &mini2440_audio_pins,
493 },
494};
495
496/*
497 * I2C devices
498 */
499static struct at24_platform_data at24c08 = {
500 .byte_len = SZ_8K / 8,
501 .page_size = 16,
502};
503
504static struct i2c_board_info mini2440_i2c_devs[] __initdata = {
505 {
506 I2C_BOARD_INFO("24c08", 0x50),
507 .platform_data = &at24c08,
508 },
509};
510
511static struct platform_device uda1340_codec = {
512 .name = "uda134x-codec",
513 .id = -1,
514};
515
516static struct platform_device *mini2440_devices[] __initdata = {
517 &s3c_device_ohci,
518 &s3c_device_wdt,
519 &s3c_device_i2c0,
520 &s3c_device_rtc,
521 &s3c_device_usbgadget,
522 &mini2440_device_eth,
523 &mini2440_led1,
524 &mini2440_led2,
525 &mini2440_led3,
526 &mini2440_led4,
527 &mini2440_button_device,
528 &s3c_device_nand,
529 &s3c_device_sdi,
530 &s3c_device_iis,
531 &uda1340_codec,
532 &mini2440_audio,
533 &samsung_asoc_dma,
534};
535
536static void __init mini2440_map_io(void)
537{
538 s3c24xx_init_io(mini2440_iodesc, ARRAY_SIZE(mini2440_iodesc));
539 s3c24xx_init_clocks(12000000);
540 s3c24xx_init_uarts(mini2440_uartcfgs, ARRAY_SIZE(mini2440_uartcfgs));
541}
542
543/*
544 * mini2440_features string
545 *
546 * t = Touchscreen present
547 * b = backlight control
548 * c = camera [TODO]
549 * 0-9 LCD configuration
550 *
551 */
552static char mini2440_features_str[12] __initdata = "0tb";
553
554static int __init mini2440_features_setup(char *str)
555{
556 if (str)
557 strlcpy(mini2440_features_str, str, sizeof(mini2440_features_str));
558 return 1;
559}
560
561__setup("mini2440=", mini2440_features_setup);
562
563#define FEATURE_SCREEN (1 << 0)
564#define FEATURE_BACKLIGHT (1 << 1)
565#define FEATURE_TOUCH (1 << 2)
566#define FEATURE_CAMERA (1 << 3)
567
568struct mini2440_features_t {
569 int count;
570 int done;
571 int lcd_index;
572 struct platform_device *optional[8];
573};
574
575static void __init mini2440_parse_features(
576 struct mini2440_features_t * features,
577 const char * features_str )
578{
579 const char * fp = features_str;
580
581 features->count = 0;
582 features->done = 0;
583 features->lcd_index = -1;
584
585 while (*fp) {
586 char f = *fp++;
587
588 switch (f) {
589 case '0'...'9': /* tft screen */
590 if (features->done & FEATURE_SCREEN) {
591 printk(KERN_INFO "MINI2440: '%c' ignored, "
592 "screen type already set\n", f);
593 } else {
594 int li = f - '0';
595 if (li >= ARRAY_SIZE(mini2440_lcd_cfg))
596 printk(KERN_INFO "MINI2440: "
597 "'%c' out of range LCD mode\n", f);
598 else {
599 features->optional[features->count++] =
600 &s3c_device_lcd;
601 features->lcd_index = li;
602 }
603 }
604 features->done |= FEATURE_SCREEN;
605 break;
606 case 'b':
607 if (features->done & FEATURE_BACKLIGHT)
608 printk(KERN_INFO "MINI2440: '%c' ignored, "
609 "backlight already set\n", f);
610 else {
611 features->optional[features->count++] =
612 &mini2440_led_backlight;
613 }
614 features->done |= FEATURE_BACKLIGHT;
615 break;
616 case 't':
617 printk(KERN_INFO "MINI2440: '%c' ignored, "
618 "touchscreen not compiled in\n", f);
619 break;
620 case 'c':
621 if (features->done & FEATURE_CAMERA)
622 printk(KERN_INFO "MINI2440: '%c' ignored, "
623 "camera already registered\n", f);
624 else
625 features->optional[features->count++] =
626 &s3c_device_camif;
627 features->done |= FEATURE_CAMERA;
628 break;
629 }
630 }
631}
632
633static void __init mini2440_init(void)
634{
635 struct mini2440_features_t features = { 0 };
636 int i;
637
638 printk(KERN_INFO "MINI2440: Option string mini2440=%s\n",
639 mini2440_features_str);
640
641 /* Parse the feature string */
642 mini2440_parse_features(&features, mini2440_features_str);
643
644 /* turn LCD on */
645 s3c_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND);
646
647 /* Turn the backlight early on */
648 WARN_ON(gpio_request(S3C2410_GPG(4), "backlight"));
649 gpio_direction_output(S3C2410_GPG(4), 1);
650
651 /* remove pullup on optional PWM backlight -- unused on 3.5 and 7"s */
652 s3c_gpio_setpull(S3C2410_GPB(1), S3C_GPIO_PULL_UP);
653 s3c2410_gpio_setpin(S3C2410_GPB(1), 0);
654 s3c_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPIO_INPUT);
655
656 /* mark the key as input, without pullups (there is one on the board) */
657 for (i = 0; i < ARRAY_SIZE(mini2440_buttons); i++) {
658 s3c_gpio_setpull(mini2440_buttons[i].gpio, S3C_GPIO_PULL_UP);
659 s3c_gpio_cfgpin(mini2440_buttons[i].gpio, S3C2410_GPIO_INPUT);
660 }
661 if (features.lcd_index != -1) {
662 int li;
663
664 mini2440_fb_info.displays =
665 &mini2440_lcd_cfg[features.lcd_index];
666
667 printk(KERN_INFO "MINI2440: LCD");
668 for (li = 0; li < ARRAY_SIZE(mini2440_lcd_cfg); li++)
669 if (li == features.lcd_index)
670 printk(" [%d:%dx%d]", li,
671 mini2440_lcd_cfg[li].width,
672 mini2440_lcd_cfg[li].height);
673 else
674 printk(" %d:%dx%d", li,
675 mini2440_lcd_cfg[li].width,
676 mini2440_lcd_cfg[li].height);
677 printk("\n");
678 s3c24xx_fb_set_platdata(&mini2440_fb_info);
679 }
680
681 s3c24xx_udc_set_platdata(&mini2440_udc_cfg);
682 s3c24xx_mci_set_platdata(&mini2440_mmc_cfg);
683 s3c_nand_set_platdata(&mini2440_nand_info);
684 s3c_i2c0_set_platdata(NULL);
685
686 i2c_register_board_info(0, mini2440_i2c_devs,
687 ARRAY_SIZE(mini2440_i2c_devs));
688
689 platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));
690
691 if (features.count) /* the optional features */
692 platform_add_devices(features.optional, features.count);
693
694}
695
696
697MACHINE_START(MINI2440, "MINI2440")
698 /* Maintainer: Michel Pollet <buserror@gmail.com> */
699 .atag_offset = 0x100,
700 .map_io = mini2440_map_io,
701 .init_machine = mini2440_init,
702 .init_irq = s3c24xx_init_irq,
703 .timer = &s3c24xx_timer,
704 .restart = s3c2440_restart,
705MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-nexcoder.c b/arch/arm/mach-s3c24xx/mach-nexcoder.c
new file mode 100644
index 000000000000..40eaf844bc1f
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/mach-nexcoder.c
@@ -0,0 +1,162 @@
1/* linux/arch/arm/mach-s3c2440/mach-nexcoder.c
2 *
3 * Copyright (c) 2004 Nex Vision
4 * Guillaume GOURAT <guillaume.gourat@nexvision.tv>
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 * Modifications:
11 * 15-10-2004 GG Created initial version
12 * 12-03-2005 BJD Updated for release
13 */
14
15#include <linux/kernel.h>
16#include <linux/types.h>
17#include <linux/interrupt.h>
18#include <linux/list.h>
19#include <linux/timer.h>
20#include <linux/init.h>
21#include <linux/gpio.h>
22#include <linux/string.h>
23#include <linux/serial_core.h>
24#include <linux/platform_device.h>
25#include <linux/io.h>
26
27#include <linux/mtd/map.h>
28
29#include <asm/mach/arch.h>
30#include <asm/mach/map.h>
31#include <asm/mach/irq.h>
32
33#include <asm/setup.h>
34#include <mach/hardware.h>
35#include <asm/irq.h>
36#include <asm/mach-types.h>
37
38//#include <asm/debug-ll.h>
39#include <mach/regs-gpio.h>
40#include <plat/regs-serial.h>
41#include <plat/iic.h>
42
43#include <plat/gpio-cfg.h>
44#include <plat/s3c2410.h>
45#include <plat/s3c244x.h>
46#include <plat/clock.h>
47#include <plat/devs.h>
48#include <plat/cpu.h>
49
50#include "common.h"
51
52static struct map_desc nexcoder_iodesc[] __initdata = {
53 /* nothing here yet */
54};
55
56#define UCON S3C2410_UCON_DEFAULT
57#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
58#define UFCON S3C2410_UFCON_RXTRIG12 | S3C2410_UFCON_FIFOMODE
59
60static struct s3c2410_uartcfg nexcoder_uartcfgs[] __initdata = {
61 [0] = {
62 .hwport = 0,
63 .flags = 0,
64 .ucon = UCON,
65 .ulcon = ULCON,
66 .ufcon = UFCON,
67 },
68 [1] = {
69 .hwport = 1,
70 .flags = 0,
71 .ucon = UCON,
72 .ulcon = ULCON,
73 .ufcon = UFCON,
74 },
75 [2] = {
76 .hwport = 2,
77 .flags = 0,
78 .ucon = UCON,
79 .ulcon = ULCON,
80 .ufcon = UFCON,
81 }
82};
83
84/* NOR Flash on NexVision NexCoder 2440 board */
85
86static struct resource nexcoder_nor_resource[] = {
87 [0] = {
88 .start = S3C2410_CS0,
89 .end = S3C2410_CS0 + (8*1024*1024) - 1,
90 .flags = IORESOURCE_MEM,
91 }
92};
93
94static struct map_info nexcoder_nor_map = {
95 .bankwidth = 2,
96};
97
98static struct platform_device nexcoder_device_nor = {
99 .name = "mtd-flash",
100 .id = -1,
101 .num_resources = ARRAY_SIZE(nexcoder_nor_resource),
102 .resource = nexcoder_nor_resource,
103 .dev =
104 {
105 .platform_data = &nexcoder_nor_map,
106 }
107};
108
109/* Standard Nexcoder devices */
110
111static struct platform_device *nexcoder_devices[] __initdata = {
112 &s3c_device_ohci,
113 &s3c_device_lcd,
114 &s3c_device_wdt,
115 &s3c_device_i2c0,
116 &s3c_device_iis,
117 &s3c_device_rtc,
118 &s3c_device_camif,
119 &s3c_device_spi0,
120 &s3c_device_spi1,
121 &nexcoder_device_nor,
122};
123
124static void __init nexcoder_sensorboard_init(void)
125{
126 // Initialize SCCB bus
127 s3c2410_gpio_setpin(S3C2410_GPE(14), 1); // IICSCL
128 s3c_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPIO_OUTPUT);
129 s3c2410_gpio_setpin(S3C2410_GPE(15), 1); // IICSDA
130 s3c_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPIO_OUTPUT);
131
132 // Power up the sensor board
133 s3c2410_gpio_setpin(S3C2410_GPF(1), 1);
134 s3c_gpio_cfgpin(S3C2410_GPF(1), S3C2410_GPIO_OUTPUT); // CAM_GPIO7 => nLDO_PWRDN
135 s3c2410_gpio_setpin(S3C2410_GPF(2), 0);
136 s3c_gpio_cfgpin(S3C2410_GPF(2), S3C2410_GPIO_OUTPUT); // CAM_GPIO6 => CAM_PWRDN
137}
138
139static void __init nexcoder_map_io(void)
140{
141 s3c24xx_init_io(nexcoder_iodesc, ARRAY_SIZE(nexcoder_iodesc));
142 s3c24xx_init_clocks(0);
143 s3c24xx_init_uarts(nexcoder_uartcfgs, ARRAY_SIZE(nexcoder_uartcfgs));
144
145 nexcoder_sensorboard_init();
146}
147
148static void __init nexcoder_init(void)
149{
150 s3c_i2c0_set_platdata(NULL);
151 platform_add_devices(nexcoder_devices, ARRAY_SIZE(nexcoder_devices));
152};
153
154MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
155 /* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
156 .atag_offset = 0x100,
157 .map_io = nexcoder_map_io,
158 .init_machine = nexcoder_init,
159 .init_irq = s3c24xx_init_irq,
160 .timer = &s3c24xx_timer,
161 .restart = s3c2440_restart,
162MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-osiris-dvs.c b/arch/arm/mach-s3c24xx/mach-osiris-dvs.c
new file mode 100644
index 000000000000..ad2792dfbee1
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/mach-osiris-dvs.c
@@ -0,0 +1,194 @@
1/* linux/arch/arm/mach-s3c2440/mach-osiris-dvs.c
2 *
3 * Copyright (c) 2009 Simtec Electronics
4 * http://armlinux.simtec.co.uk/
5 * Ben Dooks <ben@simtec.co.uk>
6 *
7 * Simtec Osiris Dynamic Voltage Scaling support.
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/module.h>
16#include <linux/platform_device.h>
17#include <linux/cpufreq.h>
18#include <linux/gpio.h>
19
20#include <linux/i2c/tps65010.h>
21
22#include <plat/cpu-freq.h>
23
24#define OSIRIS_GPIO_DVS S3C2410_GPB(5)
25
26static bool dvs_en;
27
28static void osiris_dvs_tps_setdvs(bool on)
29{
30 unsigned vregs1 = 0, vdcdc2 = 0;
31
32 if (!on) {
33 vdcdc2 = TPS_VCORE_DISCH | TPS_LP_COREOFF;
34 vregs1 = TPS_LDO1_OFF; /* turn off in low-power mode */
35 }
36
37 dvs_en = on;
38 vdcdc2 |= TPS_VCORE_1_3V | TPS_VCORE_LP_1_0V;
39 vregs1 |= TPS_LDO2_ENABLE | TPS_LDO1_ENABLE;
40
41 tps65010_config_vregs1(vregs1);
42 tps65010_config_vdcdc2(vdcdc2);
43}
44
45static bool is_dvs(struct s3c_freq *f)
46{
47 /* at the moment, we assume ARMCLK = HCLK => DVS */
48 return f->armclk == f->hclk;
49}
50
51/* keep track of current state */
52static bool cur_dvs = false;
53
54static int osiris_dvs_notify(struct notifier_block *nb,
55 unsigned long val, void *data)
56{
57 struct cpufreq_freqs *cf = data;
58 struct s3c_cpufreq_freqs *freqs = to_s3c_cpufreq(cf);
59 bool old_dvs = is_dvs(&freqs->old);
60 bool new_dvs = is_dvs(&freqs->new);
61 int ret = 0;
62
63 if (!dvs_en)
64 return 0;
65
66 printk(KERN_DEBUG "%s: old %ld,%ld new %ld,%ld\n", __func__,
67 freqs->old.armclk, freqs->old.hclk,
68 freqs->new.armclk, freqs->new.hclk);
69
70 switch (val) {
71 case CPUFREQ_PRECHANGE:
72 if (old_dvs & !new_dvs ||
73 cur_dvs & !new_dvs) {
74 pr_debug("%s: exiting dvs\n", __func__);
75 cur_dvs = false;
76 gpio_set_value(OSIRIS_GPIO_DVS, 1);
77 }
78 break;
79 case CPUFREQ_POSTCHANGE:
80 if (!old_dvs & new_dvs ||
81 !cur_dvs & new_dvs) {
82 pr_debug("entering dvs\n");
83 cur_dvs = true;
84 gpio_set_value(OSIRIS_GPIO_DVS, 0);
85 }
86 break;
87 }
88
89 return ret;
90}
91
92static struct notifier_block osiris_dvs_nb = {
93 .notifier_call = osiris_dvs_notify,
94};
95
96static int __devinit osiris_dvs_probe(struct platform_device *pdev)
97{
98 int ret;
99
100 dev_info(&pdev->dev, "initialising\n");
101
102 ret = gpio_request(OSIRIS_GPIO_DVS, "osiris-dvs");
103 if (ret) {
104 dev_err(&pdev->dev, "cannot claim gpio\n");
105 goto err_nogpio;
106 }
107
108 /* start with dvs disabled */
109 gpio_direction_output(OSIRIS_GPIO_DVS, 1);
110
111 ret = cpufreq_register_notifier(&osiris_dvs_nb,
112 CPUFREQ_TRANSITION_NOTIFIER);
113 if (ret) {
114 dev_err(&pdev->dev, "failed to register with cpufreq\n");
115 goto err_nofreq;
116 }
117
118 osiris_dvs_tps_setdvs(true);
119
120 return 0;
121
122err_nofreq:
123 gpio_free(OSIRIS_GPIO_DVS);
124
125err_nogpio:
126 return ret;
127}
128
129static int __devexit osiris_dvs_remove(struct platform_device *pdev)
130{
131 dev_info(&pdev->dev, "exiting\n");
132
133 /* disable any current dvs */
134 gpio_set_value(OSIRIS_GPIO_DVS, 1);
135 osiris_dvs_tps_setdvs(false);
136
137 cpufreq_unregister_notifier(&osiris_dvs_nb,
138 CPUFREQ_TRANSITION_NOTIFIER);
139
140 gpio_free(OSIRIS_GPIO_DVS);
141
142 return 0;
143}
144
145/* the CONFIG_PM block is so small, it isn't worth actaully compiling it
146 * out if the configuration isn't set. */
147
148static int osiris_dvs_suspend(struct device *dev)
149{
150 gpio_set_value(OSIRIS_GPIO_DVS, 1);
151 osiris_dvs_tps_setdvs(false);
152 cur_dvs = false;
153
154 return 0;
155}
156
157static int osiris_dvs_resume(struct device *dev)
158{
159 osiris_dvs_tps_setdvs(true);
160 return 0;
161}
162
163static const struct dev_pm_ops osiris_dvs_pm = {
164 .suspend = osiris_dvs_suspend,
165 .resume = osiris_dvs_resume,
166};
167
168static struct platform_driver osiris_dvs_driver = {
169 .probe = osiris_dvs_probe,
170 .remove = __devexit_p(osiris_dvs_remove),
171 .driver = {
172 .name = "osiris-dvs",
173 .owner = THIS_MODULE,
174 .pm = &osiris_dvs_pm,
175 },
176};
177
178static int __init osiris_dvs_init(void)
179{
180 return platform_driver_register(&osiris_dvs_driver);
181}
182
183static void __exit osiris_dvs_exit(void)
184{
185 platform_driver_unregister(&osiris_dvs_driver);
186}
187
188module_init(osiris_dvs_init);
189module_exit(osiris_dvs_exit);
190
191MODULE_DESCRIPTION("Simtec OSIRIS DVS support");
192MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
193MODULE_LICENSE("GPL");
194MODULE_ALIAS("platform:osiris-dvs");
diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c
new file mode 100644
index 000000000000..4c480ef734f6
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/mach-osiris.c
@@ -0,0 +1,440 @@
1/* linux/arch/arm/mach-s3c2440/mach-osiris.c
2 *
3 * Copyright (c) 2005-2008 Simtec Electronics
4 * http://armlinux.simtec.co.uk/
5 * Ben Dooks <ben@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/gpio.h>
19#include <linux/device.h>
20#include <linux/syscore_ops.h>
21#include <linux/serial_core.h>
22#include <linux/clk.h>
23#include <linux/i2c.h>
24#include <linux/io.h>
25
26#include <linux/i2c/tps65010.h>
27
28#include <asm/mach/arch.h>
29#include <asm/mach/map.h>
30#include <asm/mach/irq.h>
31
32#include <mach/osiris-map.h>
33#include <mach/osiris-cpld.h>
34
35#include <mach/hardware.h>
36#include <asm/irq.h>
37#include <asm/mach-types.h>
38
39#include <plat/cpu-freq.h>
40#include <plat/regs-serial.h>
41#include <mach/regs-gpio.h>
42#include <mach/regs-mem.h>
43#include <mach/regs-lcd.h>
44#include <plat/nand.h>
45#include <plat/iic.h>
46
47#include <linux/mtd/mtd.h>
48#include <linux/mtd/nand.h>
49#include <linux/mtd/nand_ecc.h>
50#include <linux/mtd/partitions.h>
51
52#include <plat/gpio-cfg.h>
53#include <plat/clock.h>
54#include <plat/devs.h>
55#include <plat/cpu.h>
56
57#include "common.h"
58
59/* onboard perihperal map */
60
61static struct map_desc osiris_iodesc[] __initdata = {
62 /* ISA IO areas (may be over-written later) */
63
64 {
65 .virtual = (u32)S3C24XX_VA_ISA_BYTE,
66 .pfn = __phys_to_pfn(S3C2410_CS5),
67 .length = SZ_16M,
68 .type = MT_DEVICE,
69 }, {
70 .virtual = (u32)S3C24XX_VA_ISA_WORD,
71 .pfn = __phys_to_pfn(S3C2410_CS5),
72 .length = SZ_16M,
73 .type = MT_DEVICE,
74 },
75
76 /* CPLD control registers */
77
78 {
79 .virtual = (u32)OSIRIS_VA_CTRL0,
80 .pfn = __phys_to_pfn(OSIRIS_PA_CTRL0),
81 .length = SZ_16K,
82 .type = MT_DEVICE,
83 }, {
84 .virtual = (u32)OSIRIS_VA_CTRL1,
85 .pfn = __phys_to_pfn(OSIRIS_PA_CTRL1),
86 .length = SZ_16K,
87 .type = MT_DEVICE,
88 }, {
89 .virtual = (u32)OSIRIS_VA_CTRL2,
90 .pfn = __phys_to_pfn(OSIRIS_PA_CTRL2),
91 .length = SZ_16K,
92 .type = MT_DEVICE,
93 }, {
94 .virtual = (u32)OSIRIS_VA_IDREG,
95 .pfn = __phys_to_pfn(OSIRIS_PA_IDREG),
96 .length = SZ_16K,
97 .type = MT_DEVICE,
98 },
99};
100
101#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
102#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
103#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
104
105static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = {
106 [0] = {
107 .hwport = 0,
108 .flags = 0,
109 .ucon = UCON,
110 .ulcon = ULCON,
111 .ufcon = UFCON,
112 .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
113 },
114 [1] = {
115 .hwport = 1,
116 .flags = 0,
117 .ucon = UCON,
118 .ulcon = ULCON,
119 .ufcon = UFCON,
120 .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
121 },
122 [2] = {
123 .hwport = 2,
124 .flags = 0,
125 .ucon = UCON,
126 .ulcon = ULCON,
127 .ufcon = UFCON,
128 .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
129 }
130};
131
132/* NAND Flash on Osiris board */
133
134static int external_map[] = { 2 };
135static int chip0_map[] = { 0 };
136static int chip1_map[] = { 1 };
137
138static struct mtd_partition __initdata osiris_default_nand_part[] = {
139 [0] = {
140 .name = "Boot Agent",
141 .size = SZ_16K,
142 .offset = 0,
143 },
144 [1] = {
145 .name = "/boot",
146 .size = SZ_4M - SZ_16K,
147 .offset = SZ_16K,
148 },
149 [2] = {
150 .name = "user1",
151 .offset = SZ_4M,
152 .size = SZ_32M - SZ_4M,
153 },
154 [3] = {
155 .name = "user2",
156 .offset = SZ_32M,
157 .size = MTDPART_SIZ_FULL,
158 }
159};
160
161static struct mtd_partition __initdata osiris_default_nand_part_large[] = {
162 [0] = {
163 .name = "Boot Agent",
164 .size = SZ_128K,
165 .offset = 0,
166 },
167 [1] = {
168 .name = "/boot",
169 .size = SZ_4M - SZ_128K,
170 .offset = SZ_128K,
171 },
172 [2] = {
173 .name = "user1",
174 .offset = SZ_4M,
175 .size = SZ_32M - SZ_4M,
176 },
177 [3] = {
178 .name = "user2",
179 .offset = SZ_32M,
180 .size = MTDPART_SIZ_FULL,
181 }
182};
183
184/* the Osiris has 3 selectable slots for nand-flash, the two
185 * on-board chip areas, as well as the external slot.
186 *
187 * Note, there is no current hot-plug support for the External
188 * socket.
189*/
190
191static struct s3c2410_nand_set __initdata osiris_nand_sets[] = {
192 [1] = {
193 .name = "External",
194 .nr_chips = 1,
195 .nr_map = external_map,
196 .options = NAND_SCAN_SILENT_NODEV,
197 .nr_partitions = ARRAY_SIZE(osiris_default_nand_part),
198 .partitions = osiris_default_nand_part,
199 },
200 [0] = {
201 .name = "chip0",
202 .nr_chips = 1,
203 .nr_map = chip0_map,
204 .nr_partitions = ARRAY_SIZE(osiris_default_nand_part),
205 .partitions = osiris_default_nand_part,
206 },
207 [2] = {
208 .name = "chip1",
209 .nr_chips = 1,
210 .nr_map = chip1_map,
211 .options = NAND_SCAN_SILENT_NODEV,
212 .nr_partitions = ARRAY_SIZE(osiris_default_nand_part),
213 .partitions = osiris_default_nand_part,
214 },
215};
216
217static void osiris_nand_select(struct s3c2410_nand_set *set, int slot)
218{
219 unsigned int tmp;
220
221 slot = set->nr_map[slot] & 3;
222
223 pr_debug("osiris_nand: selecting slot %d (set %p,%p)\n",
224 slot, set, set->nr_map);
225
226 tmp = __raw_readb(OSIRIS_VA_CTRL0);
227 tmp &= ~OSIRIS_CTRL0_NANDSEL;
228 tmp |= slot;
229
230 pr_debug("osiris_nand: ctrl0 now %02x\n", tmp);
231
232 __raw_writeb(tmp, OSIRIS_VA_CTRL0);
233}
234
235static struct s3c2410_platform_nand __initdata osiris_nand_info = {
236 .tacls = 25,
237 .twrph0 = 60,
238 .twrph1 = 60,
239 .nr_sets = ARRAY_SIZE(osiris_nand_sets),
240 .sets = osiris_nand_sets,
241 .select_chip = osiris_nand_select,
242};
243
244/* PCMCIA control and configuration */
245
246static struct resource osiris_pcmcia_resource[] = {
247 [0] = {
248 .start = 0x0f000000,
249 .end = 0x0f100000,
250 .flags = IORESOURCE_MEM,
251 },
252 [1] = {
253 .start = 0x0c000000,
254 .end = 0x0c100000,
255 .flags = IORESOURCE_MEM,
256 }
257};
258
259static struct platform_device osiris_pcmcia = {
260 .name = "osiris-pcmcia",
261 .id = -1,
262 .num_resources = ARRAY_SIZE(osiris_pcmcia_resource),
263 .resource = osiris_pcmcia_resource,
264};
265
266/* Osiris power management device */
267
268#ifdef CONFIG_PM
269static unsigned char pm_osiris_ctrl0;
270
271static int osiris_pm_suspend(void)
272{
273 unsigned int tmp;
274
275 pm_osiris_ctrl0 = __raw_readb(OSIRIS_VA_CTRL0);
276 tmp = pm_osiris_ctrl0 & ~OSIRIS_CTRL0_NANDSEL;
277
278 /* ensure correct NAND slot is selected on resume */
279 if ((pm_osiris_ctrl0 & OSIRIS_CTRL0_BOOT_INT) == 0)
280 tmp |= 2;
281
282 __raw_writeb(tmp, OSIRIS_VA_CTRL0);
283
284 /* ensure that an nRESET is not generated on resume. */
285 s3c2410_gpio_setpin(S3C2410_GPA(21), 1);
286 s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPIO_OUTPUT);
287
288 return 0;
289}
290
291static void osiris_pm_resume(void)
292{
293 if (pm_osiris_ctrl0 & OSIRIS_CTRL0_FIX8)
294 __raw_writeb(OSIRIS_CTRL1_FIX8, OSIRIS_VA_CTRL1);
295
296 __raw_writeb(pm_osiris_ctrl0, OSIRIS_VA_CTRL0);
297
298 s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT);
299}
300
301#else
302#define osiris_pm_suspend NULL
303#define osiris_pm_resume NULL
304#endif
305
306static struct syscore_ops osiris_pm_syscore_ops = {
307 .suspend = osiris_pm_suspend,
308 .resume = osiris_pm_resume,
309};
310
311/* Link for DVS driver to TPS65011 */
312
313static void osiris_tps_release(struct device *dev)
314{
315 /* static device, do not need to release anything */
316}
317
318static struct platform_device osiris_tps_device = {
319 .name = "osiris-dvs",
320 .id = -1,
321 .dev.release = osiris_tps_release,
322};
323
324static int osiris_tps_setup(struct i2c_client *client, void *context)
325{
326 osiris_tps_device.dev.parent = &client->dev;
327 return platform_device_register(&osiris_tps_device);
328}
329
330static int osiris_tps_remove(struct i2c_client *client, void *context)
331{
332 platform_device_unregister(&osiris_tps_device);
333 return 0;
334}
335
336static struct tps65010_board osiris_tps_board = {
337 .base = -1, /* GPIO can go anywhere at the moment */
338 .setup = osiris_tps_setup,
339 .teardown = osiris_tps_remove,
340};
341
342/* I2C devices fitted. */
343
344static struct i2c_board_info osiris_i2c_devs[] __initdata = {
345 {
346 I2C_BOARD_INFO("tps65011", 0x48),
347 .irq = IRQ_EINT20,
348 .platform_data = &osiris_tps_board,
349 },
350};
351
352/* Standard Osiris devices */
353
354static struct platform_device *osiris_devices[] __initdata = {
355 &s3c_device_i2c0,
356 &s3c_device_wdt,
357 &s3c_device_nand,
358 &osiris_pcmcia,
359};
360
361static struct clk *osiris_clocks[] __initdata = {
362 &s3c24xx_dclk0,
363 &s3c24xx_dclk1,
364 &s3c24xx_clkout0,
365 &s3c24xx_clkout1,
366 &s3c24xx_uclk,
367};
368
369static struct s3c_cpufreq_board __initdata osiris_cpufreq = {
370 .refresh = 7800, /* refresh period is 7.8usec */
371 .auto_io = 1,
372 .need_io = 1,
373};
374
375static void __init osiris_map_io(void)
376{
377 unsigned long flags;
378
379 /* initialise the clocks */
380
381 s3c24xx_dclk0.parent = &clk_upll;
382 s3c24xx_dclk0.rate = 12*1000*1000;
383
384 s3c24xx_dclk1.parent = &clk_upll;
385 s3c24xx_dclk1.rate = 24*1000*1000;
386
387 s3c24xx_clkout0.parent = &s3c24xx_dclk0;
388 s3c24xx_clkout1.parent = &s3c24xx_dclk1;
389
390 s3c24xx_uclk.parent = &s3c24xx_clkout1;
391
392 s3c24xx_register_clocks(osiris_clocks, ARRAY_SIZE(osiris_clocks));
393
394 s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc));
395 s3c24xx_init_clocks(0);
396 s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
397
398 /* check for the newer revision boards with large page nand */
399
400 if ((__raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK) >= 4) {
401 printk(KERN_INFO "OSIRIS-B detected (revision %d)\n",
402 __raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK);
403 osiris_nand_sets[0].partitions = osiris_default_nand_part_large;
404 osiris_nand_sets[0].nr_partitions = ARRAY_SIZE(osiris_default_nand_part_large);
405 } else {
406 /* write-protect line to the NAND */
407 s3c2410_gpio_setpin(S3C2410_GPA(0), 1);
408 }
409
410 /* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */
411
412 local_irq_save(flags);
413 __raw_writel(__raw_readl(S3C2410_BWSCON) | S3C2410_BWSCON_ST1 | S3C2410_BWSCON_ST2 | S3C2410_BWSCON_ST3 | S3C2410_BWSCON_ST4 | S3C2410_BWSCON_ST5, S3C2410_BWSCON);
414 local_irq_restore(flags);
415}
416
417static void __init osiris_init(void)
418{
419 register_syscore_ops(&osiris_pm_syscore_ops);
420
421 s3c_i2c0_set_platdata(NULL);
422 s3c_nand_set_platdata(&osiris_nand_info);
423
424 s3c_cpufreq_setboard(&osiris_cpufreq);
425
426 i2c_register_board_info(0, osiris_i2c_devs,
427 ARRAY_SIZE(osiris_i2c_devs));
428
429 platform_add_devices(osiris_devices, ARRAY_SIZE(osiris_devices));
430};
431
432MACHINE_START(OSIRIS, "Simtec-OSIRIS")
433 /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
434 .atag_offset = 0x100,
435 .map_io = osiris_map_io,
436 .init_irq = s3c24xx_init_irq,
437 .init_machine = osiris_init,
438 .timer = &s3c24xx_timer,
439 .restart = s3c2440_restart,
440MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c
new file mode 100644
index 000000000000..80077f6472ee
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/mach-rx1950.c
@@ -0,0 +1,826 @@
1/* linux/arch/arm/mach-s3c2440/mach-rx1950.c
2 *
3 * Copyright (c) 2006-2009 Victor Chukhantsev, Denis Grigoriev,
4 * Copyright (c) 2007-2010 Vasily Khoruzhick
5 *
6 * based on smdk2440 written by Ben Dooks
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
14#include <linux/kernel.h>
15#include <linux/types.h>
16#include <linux/interrupt.h>
17#include <linux/list.h>
18#include <linux/memblock.h>
19#include <linux/delay.h>
20#include <linux/timer.h>
21#include <linux/init.h>
22#include <linux/gpio.h>
23#include <linux/platform_device.h>
24#include <linux/serial_core.h>
25#include <linux/input.h>
26#include <linux/gpio_keys.h>
27#include <linux/device.h>
28#include <linux/pda_power.h>
29#include <linux/pwm_backlight.h>
30#include <linux/pwm.h>
31#include <linux/s3c_adc_battery.h>
32#include <linux/leds.h>
33#include <linux/i2c.h>
34
35#include <linux/mtd/mtd.h>
36#include <linux/mtd/partitions.h>
37
38#include <linux/mmc/host.h>
39
40#include <asm/mach/arch.h>
41#include <asm/mach/map.h>
42#include <asm/mach-types.h>
43
44#include <mach/regs-gpio.h>
45#include <mach/regs-gpioj.h>
46#include <mach/regs-lcd.h>
47#include <mach/h1940.h>
48#include <mach/fb.h>
49
50#include <plat/clock.h>
51#include <plat/regs-serial.h>
52#include <plat/regs-iic.h>
53#include <plat/mci.h>
54#include <plat/udc.h>
55#include <plat/nand.h>
56#include <plat/iic.h>
57#include <plat/devs.h>
58#include <plat/cpu.h>
59#include <plat/pm.h>
60#include <plat/irq.h>
61#include <plat/ts.h>
62
63#include <sound/uda1380.h>
64
65#include "common.h"
66
67#define LCD_PWM_PERIOD 192960
68#define LCD_PWM_DUTY 127353
69
70static struct map_desc rx1950_iodesc[] __initdata = {
71};
72
73static struct s3c2410_uartcfg rx1950_uartcfgs[] __initdata = {
74 [0] = {
75 .hwport = 0,
76 .flags = 0,
77 .ucon = 0x3c5,
78 .ulcon = 0x03,
79 .ufcon = 0x51,
80 .clk_sel = S3C2410_UCON_CLKSEL3,
81 },
82 [1] = {
83 .hwport = 1,
84 .flags = 0,
85 .ucon = 0x3c5,
86 .ulcon = 0x03,
87 .ufcon = 0x51,
88 .clk_sel = S3C2410_UCON_CLKSEL3,
89 },
90 /* IR port */
91 [2] = {
92 .hwport = 2,
93 .flags = 0,
94 .ucon = 0x3c5,
95 .ulcon = 0x43,
96 .ufcon = 0xf1,
97 .clk_sel = S3C2410_UCON_CLKSEL3,
98 },
99};
100
101static struct s3c2410fb_display rx1950_display = {
102 .type = S3C2410_LCDCON1_TFT,
103 .width = 240,
104 .height = 320,
105 .xres = 240,
106 .yres = 320,
107 .bpp = 16,
108
109 .pixclock = 260000,
110 .left_margin = 10,
111 .right_margin = 20,
112 .hsync_len = 10,
113 .upper_margin = 2,
114 .lower_margin = 2,
115 .vsync_len = 2,
116
117 .lcdcon5 = S3C2410_LCDCON5_FRM565 |
118 S3C2410_LCDCON5_INVVCLK |
119 S3C2410_LCDCON5_INVVLINE |
120 S3C2410_LCDCON5_INVVFRAME |
121 S3C2410_LCDCON5_HWSWP |
122 (0x02 << 13) |
123 (0x02 << 15),
124
125};
126
127static int power_supply_init(struct device *dev)
128{
129 return gpio_request(S3C2410_GPF(2), "cable plugged");
130}
131
132static int rx1950_is_ac_online(void)
133{
134 return !gpio_get_value(S3C2410_GPF(2));
135}
136
137static void power_supply_exit(struct device *dev)
138{
139 gpio_free(S3C2410_GPF(2));
140}
141
142static char *rx1950_supplicants[] = {
143 "main-battery"
144};
145
146static struct pda_power_pdata power_supply_info = {
147 .init = power_supply_init,
148 .is_ac_online = rx1950_is_ac_online,
149 .exit = power_supply_exit,
150 .supplied_to = rx1950_supplicants,
151 .num_supplicants = ARRAY_SIZE(rx1950_supplicants),
152};
153
154static struct resource power_supply_resources[] = {
155 [0] = {
156 .name = "ac",
157 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE |
158 IORESOURCE_IRQ_HIGHEDGE,
159 .start = IRQ_EINT2,
160 .end = IRQ_EINT2,
161 },
162};
163
164static struct platform_device power_supply = {
165 .name = "pda-power",
166 .id = -1,
167 .dev = {
168 .platform_data =
169 &power_supply_info,
170 },
171 .resource = power_supply_resources,
172 .num_resources = ARRAY_SIZE(power_supply_resources),
173};
174
175static const struct s3c_adc_bat_thresh bat_lut_noac[] = {
176 { .volt = 4100, .cur = 156, .level = 100},
177 { .volt = 4050, .cur = 156, .level = 95},
178 { .volt = 4025, .cur = 141, .level = 90},
179 { .volt = 3995, .cur = 144, .level = 85},
180 { .volt = 3957, .cur = 162, .level = 80},
181 { .volt = 3931, .cur = 147, .level = 75},
182 { .volt = 3902, .cur = 147, .level = 70},
183 { .volt = 3863, .cur = 153, .level = 65},
184 { .volt = 3838, .cur = 150, .level = 60},
185 { .volt = 3800, .cur = 153, .level = 55},
186 { .volt = 3765, .cur = 153, .level = 50},
187 { .volt = 3748, .cur = 172, .level = 45},
188 { .volt = 3740, .cur = 153, .level = 40},
189 { .volt = 3714, .cur = 175, .level = 35},
190 { .volt = 3710, .cur = 156, .level = 30},
191 { .volt = 3963, .cur = 156, .level = 25},
192 { .volt = 3672, .cur = 178, .level = 20},
193 { .volt = 3651, .cur = 178, .level = 15},
194 { .volt = 3629, .cur = 178, .level = 10},
195 { .volt = 3612, .cur = 162, .level = 5},
196 { .volt = 3605, .cur = 162, .level = 0},
197};
198
199static const struct s3c_adc_bat_thresh bat_lut_acin[] = {
200 { .volt = 4200, .cur = 0, .level = 100},
201 { .volt = 4190, .cur = 0, .level = 99},
202 { .volt = 4178, .cur = 0, .level = 95},
203 { .volt = 4110, .cur = 0, .level = 70},
204 { .volt = 4076, .cur = 0, .level = 65},
205 { .volt = 4046, .cur = 0, .level = 60},
206 { .volt = 4021, .cur = 0, .level = 55},
207 { .volt = 3999, .cur = 0, .level = 50},
208 { .volt = 3982, .cur = 0, .level = 45},
209 { .volt = 3965, .cur = 0, .level = 40},
210 { .volt = 3957, .cur = 0, .level = 35},
211 { .volt = 3948, .cur = 0, .level = 30},
212 { .volt = 3936, .cur = 0, .level = 25},
213 { .volt = 3927, .cur = 0, .level = 20},
214 { .volt = 3906, .cur = 0, .level = 15},
215 { .volt = 3880, .cur = 0, .level = 10},
216 { .volt = 3829, .cur = 0, .level = 5},
217 { .volt = 3820, .cur = 0, .level = 0},
218};
219
220int rx1950_bat_init(void)
221{
222 int ret;
223
224 ret = gpio_request(S3C2410_GPJ(2), "rx1950-charger-enable-1");
225 if (ret)
226 goto err_gpio1;
227 ret = gpio_request(S3C2410_GPJ(3), "rx1950-charger-enable-2");
228 if (ret)
229 goto err_gpio2;
230
231 return 0;
232
233err_gpio2:
234 gpio_free(S3C2410_GPJ(2));
235err_gpio1:
236 return ret;
237}
238
239void rx1950_bat_exit(void)
240{
241 gpio_free(S3C2410_GPJ(2));
242 gpio_free(S3C2410_GPJ(3));
243}
244
245void rx1950_enable_charger(void)
246{
247 gpio_direction_output(S3C2410_GPJ(2), 1);
248 gpio_direction_output(S3C2410_GPJ(3), 1);
249}
250
251void rx1950_disable_charger(void)
252{
253 gpio_direction_output(S3C2410_GPJ(2), 0);
254 gpio_direction_output(S3C2410_GPJ(3), 0);
255}
256
257DEFINE_SPINLOCK(rx1950_blink_spin);
258
259static int rx1950_led_blink_set(unsigned gpio, int state,
260 unsigned long *delay_on, unsigned long *delay_off)
261{
262 int blink_gpio, check_gpio;
263
264 switch (gpio) {
265 case S3C2410_GPA(6):
266 blink_gpio = S3C2410_GPA(4);
267 check_gpio = S3C2410_GPA(3);
268 break;
269 case S3C2410_GPA(7):
270 blink_gpio = S3C2410_GPA(3);
271 check_gpio = S3C2410_GPA(4);
272 break;
273 default:
274 return -EINVAL;
275 break;
276 }
277
278 if (delay_on && delay_off && !*delay_on && !*delay_off)
279 *delay_on = *delay_off = 500;
280
281 spin_lock(&rx1950_blink_spin);
282
283 switch (state) {
284 case GPIO_LED_NO_BLINK_LOW:
285 case GPIO_LED_NO_BLINK_HIGH:
286 if (!gpio_get_value(check_gpio))
287 gpio_set_value(S3C2410_GPJ(6), 0);
288 gpio_set_value(blink_gpio, 0);
289 gpio_set_value(gpio, state);
290 break;
291 case GPIO_LED_BLINK:
292 gpio_set_value(gpio, 0);
293 gpio_set_value(S3C2410_GPJ(6), 1);
294 gpio_set_value(blink_gpio, 1);
295 break;
296 }
297
298 spin_unlock(&rx1950_blink_spin);
299
300 return 0;
301}
302
303static struct gpio_led rx1950_leds_desc[] = {
304 {
305 .name = "Green",
306 .default_trigger = "main-battery-full",
307 .gpio = S3C2410_GPA(6),
308 .retain_state_suspended = 1,
309 },
310 {
311 .name = "Red",
312 .default_trigger
313 = "main-battery-charging-blink-full-solid",
314 .gpio = S3C2410_GPA(7),
315 .retain_state_suspended = 1,
316 },
317 {
318 .name = "Blue",
319 .default_trigger = "rx1950-acx-mem",
320 .gpio = S3C2410_GPA(11),
321 .retain_state_suspended = 1,
322 },
323};
324
325static struct gpio_led_platform_data rx1950_leds_pdata = {
326 .num_leds = ARRAY_SIZE(rx1950_leds_desc),
327 .leds = rx1950_leds_desc,
328 .gpio_blink_set = rx1950_led_blink_set,
329};
330
331static struct platform_device rx1950_leds = {
332 .name = "leds-gpio",
333 .id = -1,
334 .dev = {
335 .platform_data = &rx1950_leds_pdata,
336 },
337};
338
339static struct s3c_adc_bat_pdata rx1950_bat_cfg = {
340 .init = rx1950_bat_init,
341 .exit = rx1950_bat_exit,
342 .enable_charger = rx1950_enable_charger,
343 .disable_charger = rx1950_disable_charger,
344 .gpio_charge_finished = S3C2410_GPF(3),
345 .lut_noac = bat_lut_noac,
346 .lut_noac_cnt = ARRAY_SIZE(bat_lut_noac),
347 .lut_acin = bat_lut_acin,
348 .lut_acin_cnt = ARRAY_SIZE(bat_lut_acin),
349 .volt_channel = 0,
350 .current_channel = 1,
351 .volt_mult = 4235,
352 .current_mult = 2900,
353 .internal_impedance = 200,
354};
355
356static struct platform_device rx1950_battery = {
357 .name = "s3c-adc-battery",
358 .id = -1,
359 .dev = {
360 .parent = &s3c_device_adc.dev,
361 .platform_data = &rx1950_bat_cfg,
362 },
363};
364
365static struct s3c2410fb_mach_info rx1950_lcd_cfg = {
366 .displays = &rx1950_display,
367 .num_displays = 1,
368 .default_display = 0,
369
370 .lpcsel = 0x02,
371 .gpccon = 0xaa9556a9,
372 .gpccon_mask = 0xffc003fc,
373 .gpcup = 0x0000ffff,
374 .gpcup_mask = 0xffffffff,
375
376 .gpdcon = 0xaa90aaa1,
377 .gpdcon_mask = 0xffc0fff0,
378 .gpdup = 0x0000fcfd,
379 .gpdup_mask = 0xffffffff,
380
381};
382
383static struct pwm_device *lcd_pwm;
384
385void rx1950_lcd_power(int enable)
386{
387 int i;
388 static int enabled;
389 if (enabled == enable)
390 return;
391 if (!enable) {
392
393 /* GPC11-GPC15->OUTPUT */
394 for (i = 11; i < 16; i++)
395 gpio_direction_output(S3C2410_GPC(i), 1);
396
397 /* Wait a bit here... */
398 mdelay(100);
399
400 /* GPD2-GPD7->OUTPUT */
401 /* GPD11-GPD15->OUTPUT */
402 /* GPD2-GPD7->1, GPD11-GPD15->1 */
403 for (i = 2; i < 8; i++)
404 gpio_direction_output(S3C2410_GPD(i), 1);
405 for (i = 11; i < 16; i++)
406 gpio_direction_output(S3C2410_GPD(i), 1);
407
408 /* Wait a bit here...*/
409 mdelay(100);
410
411 /* GPB0->OUTPUT, GPB0->0 */
412 gpio_direction_output(S3C2410_GPB(0), 0);
413
414 /* GPC1-GPC4->OUTPUT, GPC1-4->0 */
415 for (i = 1; i < 5; i++)
416 gpio_direction_output(S3C2410_GPC(i), 0);
417
418 /* GPC15-GPC11->0 */
419 for (i = 11; i < 16; i++)
420 gpio_direction_output(S3C2410_GPC(i), 0);
421
422 /* GPD15-GPD11->0, GPD2->GPD7->0 */
423 for (i = 11; i < 16; i++)
424 gpio_direction_output(S3C2410_GPD(i), 0);
425
426 for (i = 2; i < 8; i++)
427 gpio_direction_output(S3C2410_GPD(i), 0);
428
429 /* GPC6->0, GPC7->0, GPC5->0 */
430 gpio_direction_output(S3C2410_GPC(6), 0);
431 gpio_direction_output(S3C2410_GPC(7), 0);
432 gpio_direction_output(S3C2410_GPC(5), 0);
433
434 /* GPB1->OUTPUT, GPB1->0 */
435 gpio_direction_output(S3C2410_GPB(1), 0);
436 pwm_config(lcd_pwm, 0, LCD_PWM_PERIOD);
437 pwm_disable(lcd_pwm);
438
439 /* GPC0->0, GPC10->0 */
440 gpio_direction_output(S3C2410_GPC(0), 0);
441 gpio_direction_output(S3C2410_GPC(10), 0);
442 } else {
443 pwm_config(lcd_pwm, LCD_PWM_DUTY, LCD_PWM_PERIOD);
444 pwm_enable(lcd_pwm);
445
446 gpio_direction_output(S3C2410_GPC(0), 1);
447 gpio_direction_output(S3C2410_GPC(5), 1);
448
449 s3c_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPB1_TOUT1);
450 gpio_direction_output(S3C2410_GPC(7), 1);
451
452 for (i = 1; i < 5; i++)
453 s3c_gpio_cfgpin(S3C2410_GPC(i), S3C_GPIO_SFN(2));
454
455 for (i = 11; i < 16; i++)
456 s3c_gpio_cfgpin(S3C2410_GPC(i), S3C_GPIO_SFN(2));
457
458 for (i = 2; i < 8; i++)
459 s3c_gpio_cfgpin(S3C2410_GPD(i), S3C_GPIO_SFN(2));
460
461 for (i = 11; i < 16; i++)
462 s3c_gpio_cfgpin(S3C2410_GPD(i), S3C_GPIO_SFN(2));
463
464 gpio_direction_output(S3C2410_GPC(10), 1);
465 gpio_direction_output(S3C2410_GPC(6), 1);
466 }
467 enabled = enable;
468}
469
470static void rx1950_bl_power(int enable)
471{
472 static int enabled;
473 if (enabled == enable)
474 return;
475 if (!enable) {
476 gpio_direction_output(S3C2410_GPB(0), 0);
477 } else {
478 /* LED driver need a "push" to power on */
479 gpio_direction_output(S3C2410_GPB(0), 1);
480 /* Warm up backlight for one period of PWM.
481 * Without this trick its almost impossible to
482 * enable backlight with low brightness value
483 */
484 ndelay(48000);
485 s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);
486 }
487 enabled = enable;
488}
489
490static int rx1950_backlight_init(struct device *dev)
491{
492 WARN_ON(gpio_request(S3C2410_GPB(0), "Backlight"));
493 lcd_pwm = pwm_request(1, "RX1950 LCD");
494 if (IS_ERR(lcd_pwm)) {
495 dev_err(dev, "Unable to request PWM for LCD power!\n");
496 return PTR_ERR(lcd_pwm);
497 }
498
499 rx1950_lcd_power(1);
500 rx1950_bl_power(1);
501
502 return 0;
503}
504
505static void rx1950_backlight_exit(struct device *dev)
506{
507 rx1950_bl_power(0);
508 rx1950_lcd_power(0);
509
510 pwm_free(lcd_pwm);
511 gpio_free(S3C2410_GPB(0));
512}
513
514
515static int rx1950_backlight_notify(struct device *dev, int brightness)
516{
517 if (!brightness) {
518 rx1950_bl_power(0);
519 rx1950_lcd_power(0);
520 } else {
521 rx1950_lcd_power(1);
522 rx1950_bl_power(1);
523 }
524 return brightness;
525}
526
527static struct platform_pwm_backlight_data rx1950_backlight_data = {
528 .pwm_id = 0,
529 .max_brightness = 24,
530 .dft_brightness = 4,
531 .pwm_period_ns = 48000,
532 .init = rx1950_backlight_init,
533 .notify = rx1950_backlight_notify,
534 .exit = rx1950_backlight_exit,
535};
536
537static struct platform_device rx1950_backlight = {
538 .name = "pwm-backlight",
539 .dev = {
540 .parent = &s3c_device_timer[0].dev,
541 .platform_data = &rx1950_backlight_data,
542 },
543};
544
545static void rx1950_set_mmc_power(unsigned char power_mode, unsigned short vdd)
546{
547 switch (power_mode) {
548 case MMC_POWER_OFF:
549 gpio_direction_output(S3C2410_GPJ(1), 0);
550 break;
551 case MMC_POWER_UP:
552 case MMC_POWER_ON:
553 gpio_direction_output(S3C2410_GPJ(1), 1);
554 break;
555 default:
556 break;
557 }
558}
559
560static struct s3c24xx_mci_pdata rx1950_mmc_cfg __initdata = {
561 .gpio_detect = S3C2410_GPF(5),
562 .gpio_wprotect = S3C2410_GPH(8),
563 .set_power = rx1950_set_mmc_power,
564 .ocr_avail = MMC_VDD_32_33,
565};
566
567static struct mtd_partition rx1950_nand_part[] = {
568 [0] = {
569 .name = "Boot0",
570 .offset = 0,
571 .size = 0x4000,
572 .mask_flags = MTD_WRITEABLE,
573 },
574 [1] = {
575 .name = "Boot1",
576 .offset = MTDPART_OFS_APPEND,
577 .size = 0x40000,
578 .mask_flags = MTD_WRITEABLE,
579 },
580 [2] = {
581 .name = "Kernel",
582 .offset = MTDPART_OFS_APPEND,
583 .size = 0x300000,
584 .mask_flags = 0,
585 },
586 [3] = {
587 .name = "Filesystem",
588 .offset = MTDPART_OFS_APPEND,
589 .size = MTDPART_SIZ_FULL,
590 .mask_flags = 0,
591 },
592};
593
594static struct s3c2410_nand_set rx1950_nand_sets[] = {
595 [0] = {
596 .name = "Internal",
597 .nr_chips = 1,
598 .nr_partitions = ARRAY_SIZE(rx1950_nand_part),
599 .partitions = rx1950_nand_part,
600 },
601};
602
603static struct s3c2410_platform_nand rx1950_nand_info = {
604 .tacls = 25,
605 .twrph0 = 50,
606 .twrph1 = 15,
607 .nr_sets = ARRAY_SIZE(rx1950_nand_sets),
608 .sets = rx1950_nand_sets,
609};
610
611static struct s3c2410_udc_mach_info rx1950_udc_cfg __initdata = {
612 .vbus_pin = S3C2410_GPG(5),
613 .vbus_pin_inverted = 1,
614 .pullup_pin = S3C2410_GPJ(5),
615};
616
617static struct s3c2410_ts_mach_info rx1950_ts_cfg __initdata = {
618 .delay = 10000,
619 .presc = 49,
620 .oversampling_shift = 3,
621};
622
623static struct gpio_keys_button rx1950_gpio_keys_table[] = {
624 {
625 .code = KEY_POWER,
626 .gpio = S3C2410_GPF(0),
627 .active_low = 1,
628 .desc = "Power button",
629 .wakeup = 1,
630 },
631 {
632 .code = KEY_F5,
633 .gpio = S3C2410_GPF(7),
634 .active_low = 1,
635 .desc = "Record button",
636 },
637 {
638 .code = KEY_F1,
639 .gpio = S3C2410_GPG(0),
640 .active_low = 1,
641 .desc = "Calendar button",
642 },
643 {
644 .code = KEY_F2,
645 .gpio = S3C2410_GPG(2),
646 .active_low = 1,
647 .desc = "Contacts button",
648 },
649 {
650 .code = KEY_F3,
651 .gpio = S3C2410_GPG(3),
652 .active_low = 1,
653 .desc = "Mail button",
654 },
655 {
656 .code = KEY_F4,
657 .gpio = S3C2410_GPG(7),
658 .active_low = 1,
659 .desc = "WLAN button",
660 },
661 {
662 .code = KEY_LEFT,
663 .gpio = S3C2410_GPG(10),
664 .active_low = 1,
665 .desc = "Left button",
666 },
667 {
668 .code = KEY_RIGHT,
669 .gpio = S3C2410_GPG(11),
670 .active_low = 1,
671 .desc = "Right button",
672 },
673 {
674 .code = KEY_UP,
675 .gpio = S3C2410_GPG(4),
676 .active_low = 1,
677 .desc = "Up button",
678 },
679 {
680 .code = KEY_DOWN,
681 .gpio = S3C2410_GPG(6),
682 .active_low = 1,
683 .desc = "Down button",
684 },
685 {
686 .code = KEY_ENTER,
687 .gpio = S3C2410_GPG(9),
688 .active_low = 1,
689 .desc = "Ok button"
690 },
691};
692
693static struct gpio_keys_platform_data rx1950_gpio_keys_data = {
694 .buttons = rx1950_gpio_keys_table,
695 .nbuttons = ARRAY_SIZE(rx1950_gpio_keys_table),
696};
697
698static struct platform_device rx1950_device_gpiokeys = {
699 .name = "gpio-keys",
700 .dev.platform_data = &rx1950_gpio_keys_data,
701};
702
703static struct uda1380_platform_data uda1380_info = {
704 .gpio_power = S3C2410_GPJ(0),
705 .gpio_reset = S3C2410_GPD(0),
706 .dac_clk = UDA1380_DAC_CLK_SYSCLK,
707};
708
709static struct i2c_board_info rx1950_i2c_devices[] = {
710 {
711 I2C_BOARD_INFO("uda1380", 0x1a),
712 .platform_data = &uda1380_info,
713 },
714};
715
716static struct platform_device *rx1950_devices[] __initdata = {
717 &s3c_device_lcd,
718 &s3c_device_wdt,
719 &s3c_device_i2c0,
720 &s3c_device_iis,
721 &samsung_asoc_dma,
722 &s3c_device_usbgadget,
723 &s3c_device_rtc,
724 &s3c_device_nand,
725 &s3c_device_sdi,
726 &s3c_device_adc,
727 &s3c_device_ts,
728 &s3c_device_timer[0],
729 &s3c_device_timer[1],
730 &rx1950_backlight,
731 &rx1950_device_gpiokeys,
732 &power_supply,
733 &rx1950_battery,
734 &rx1950_leds,
735};
736
737static struct clk *rx1950_clocks[] __initdata = {
738 &s3c24xx_clkout0,
739 &s3c24xx_clkout1,
740};
741
742static void __init rx1950_map_io(void)
743{
744 s3c24xx_clkout0.parent = &clk_h;
745 s3c24xx_clkout1.parent = &clk_f;
746
747 s3c24xx_register_clocks(rx1950_clocks, ARRAY_SIZE(rx1950_clocks));
748
749 s3c24xx_init_io(rx1950_iodesc, ARRAY_SIZE(rx1950_iodesc));
750 s3c24xx_init_clocks(16934000);
751 s3c24xx_init_uarts(rx1950_uartcfgs, ARRAY_SIZE(rx1950_uartcfgs));
752
753 /* setup PM */
754
755#ifdef CONFIG_PM_H1940
756 memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 8);
757#endif
758
759 s3c_pm_init();
760}
761
762static void __init rx1950_init_machine(void)
763{
764 int i;
765
766 s3c24xx_fb_set_platdata(&rx1950_lcd_cfg);
767 s3c24xx_udc_set_platdata(&rx1950_udc_cfg);
768 s3c24xx_ts_set_platdata(&rx1950_ts_cfg);
769 s3c24xx_mci_set_platdata(&rx1950_mmc_cfg);
770 s3c_i2c0_set_platdata(NULL);
771 s3c_nand_set_platdata(&rx1950_nand_info);
772
773 /* Turn off suspend on both USB ports, and switch the
774 * selectable USB port to USB device mode. */
775 s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
776 S3C2410_MISCCR_USBSUSPND0 |
777 S3C2410_MISCCR_USBSUSPND1, 0x0);
778
779 /* mmc power is disabled by default */
780 WARN_ON(gpio_request(S3C2410_GPJ(1), "MMC power"));
781 gpio_direction_output(S3C2410_GPJ(1), 0);
782
783 for (i = 0; i < 8; i++)
784 WARN_ON(gpio_request(S3C2410_GPC(i), "LCD power"));
785
786 for (i = 10; i < 16; i++)
787 WARN_ON(gpio_request(S3C2410_GPC(i), "LCD power"));
788
789 for (i = 2; i < 8; i++)
790 WARN_ON(gpio_request(S3C2410_GPD(i), "LCD power"));
791
792 for (i = 11; i < 16; i++)
793 WARN_ON(gpio_request(S3C2410_GPD(i), "LCD power"));
794
795 WARN_ON(gpio_request(S3C2410_GPB(1), "LCD power"));
796
797 WARN_ON(gpio_request(S3C2410_GPA(3), "Red blink"));
798 WARN_ON(gpio_request(S3C2410_GPA(4), "Green blink"));
799 WARN_ON(gpio_request(S3C2410_GPJ(6), "LED blink"));
800 gpio_direction_output(S3C2410_GPA(3), 0);
801 gpio_direction_output(S3C2410_GPA(4), 0);
802 gpio_direction_output(S3C2410_GPJ(6), 0);
803
804 platform_add_devices(rx1950_devices, ARRAY_SIZE(rx1950_devices));
805
806 i2c_register_board_info(0, rx1950_i2c_devices,
807 ARRAY_SIZE(rx1950_i2c_devices));
808}
809
810/* H1940 and RX3715 need to reserve this for suspend */
811static void __init rx1950_reserve(void)
812{
813 memblock_reserve(0x30003000, 0x1000);
814 memblock_reserve(0x30081000, 0x1000);
815}
816
817MACHINE_START(RX1950, "HP iPAQ RX1950")
818 /* Maintainers: Vasily Khoruzhick */
819 .atag_offset = 0x100,
820 .map_io = rx1950_map_io,
821 .reserve = rx1950_reserve,
822 .init_irq = s3c24xx_init_irq,
823 .init_machine = rx1950_init_machine,
824 .timer = &s3c24xx_timer,
825 .restart = s3c2440_restart,
826MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-rx3715.c b/arch/arm/mach-s3c24xx/mach-rx3715.c
new file mode 100644
index 000000000000..20103bafbd4b
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/mach-rx3715.c
@@ -0,0 +1,217 @@
1/* linux/arch/arm/mach-s3c2440/mach-rx3715.c
2 *
3 * Copyright (c) 2003-2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * http://www.handhelds.org/projects/rx3715.html
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
14#include <linux/kernel.h>
15#include <linux/types.h>
16#include <linux/interrupt.h>
17#include <linux/list.h>
18#include <linux/memblock.h>
19#include <linux/timer.h>
20#include <linux/init.h>
21#include <linux/tty.h>
22#include <linux/console.h>
23#include <linux/device.h>
24#include <linux/platform_device.h>
25#include <linux/serial_core.h>
26#include <linux/serial.h>
27#include <linux/io.h>
28#include <linux/mtd/mtd.h>
29#include <linux/mtd/nand.h>
30#include <linux/mtd/nand_ecc.h>
31#include <linux/mtd/partitions.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 <asm/irq.h>
39#include <asm/mach-types.h>
40
41#include <plat/regs-serial.h>
42#include <mach/regs-gpio.h>
43#include <mach/regs-lcd.h>
44
45#include <mach/h1940.h>
46#include <plat/nand.h>
47#include <mach/fb.h>
48
49#include <plat/clock.h>
50#include <plat/devs.h>
51#include <plat/cpu.h>
52#include <plat/pm.h>
53
54#include "common.h"
55
56static struct map_desc rx3715_iodesc[] __initdata = {
57 /* dump ISA space somewhere unused */
58
59 {
60 .virtual = (u32)S3C24XX_VA_ISA_WORD,
61 .pfn = __phys_to_pfn(S3C2410_CS3),
62 .length = SZ_1M,
63 .type = MT_DEVICE,
64 }, {
65 .virtual = (u32)S3C24XX_VA_ISA_BYTE,
66 .pfn = __phys_to_pfn(S3C2410_CS3),
67 .length = SZ_1M,
68 .type = MT_DEVICE,
69 },
70};
71
72static struct s3c2410_uartcfg rx3715_uartcfgs[] = {
73 [0] = {
74 .hwport = 0,
75 .flags = 0,
76 .ucon = 0x3c5,
77 .ulcon = 0x03,
78 .ufcon = 0x51,
79 .clk_sel = S3C2410_UCON_CLKSEL3,
80 },
81 [1] = {
82 .hwport = 1,
83 .flags = 0,
84 .ucon = 0x3c5,
85 .ulcon = 0x03,
86 .ufcon = 0x00,
87 .clk_sel = S3C2410_UCON_CLKSEL3,
88 },
89 /* IR port */
90 [2] = {
91 .hwport = 2,
92 .uart_flags = UPF_CONS_FLOW,
93 .ucon = 0x3c5,
94 .ulcon = 0x43,
95 .ufcon = 0x51,
96 .clk_sel = S3C2410_UCON_CLKSEL3,
97 }
98};
99
100/* framebuffer lcd controller information */
101
102static struct s3c2410fb_display rx3715_lcdcfg __initdata = {
103 .lcdcon5 = S3C2410_LCDCON5_INVVLINE |
104 S3C2410_LCDCON5_FRM565 |
105 S3C2410_LCDCON5_HWSWP,
106
107 .type = S3C2410_LCDCON1_TFT,
108 .width = 240,
109 .height = 320,
110
111 .pixclock = 260000,
112 .xres = 240,
113 .yres = 320,
114 .bpp = 16,
115 .left_margin = 36,
116 .right_margin = 36,
117 .hsync_len = 8,
118 .upper_margin = 6,
119 .lower_margin = 7,
120 .vsync_len = 3,
121};
122
123static struct s3c2410fb_mach_info rx3715_fb_info __initdata = {
124
125 .displays = &rx3715_lcdcfg,
126 .num_displays = 1,
127 .default_display = 0,
128
129 .lpcsel = 0xf82,
130
131 .gpccon = 0xaa955699,
132 .gpccon_mask = 0xffc003cc,
133 .gpcup = 0x0000ffff,
134 .gpcup_mask = 0xffffffff,
135
136 .gpdcon = 0xaa95aaa1,
137 .gpdcon_mask = 0xffc0fff0,
138 .gpdup = 0x0000faff,
139 .gpdup_mask = 0xffffffff,
140};
141
142static struct mtd_partition __initdata rx3715_nand_part[] = {
143 [0] = {
144 .name = "Whole Flash",
145 .offset = 0,
146 .size = MTDPART_SIZ_FULL,
147 .mask_flags = MTD_WRITEABLE,
148 }
149};
150
151static struct s3c2410_nand_set __initdata rx3715_nand_sets[] = {
152 [0] = {
153 .name = "Internal",
154 .nr_chips = 1,
155 .nr_partitions = ARRAY_SIZE(rx3715_nand_part),
156 .partitions = rx3715_nand_part,
157 },
158};
159
160static struct s3c2410_platform_nand __initdata rx3715_nand_info = {
161 .tacls = 25,
162 .twrph0 = 50,
163 .twrph1 = 15,
164 .nr_sets = ARRAY_SIZE(rx3715_nand_sets),
165 .sets = rx3715_nand_sets,
166};
167
168static struct platform_device *rx3715_devices[] __initdata = {
169 &s3c_device_ohci,
170 &s3c_device_lcd,
171 &s3c_device_wdt,
172 &s3c_device_i2c0,
173 &s3c_device_iis,
174 &s3c_device_nand,
175};
176
177static void __init rx3715_map_io(void)
178{
179 s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc));
180 s3c24xx_init_clocks(16934000);
181 s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs));
182}
183
184/* H1940 and RX3715 need to reserve this for suspend */
185static void __init rx3715_reserve(void)
186{
187 memblock_reserve(0x30003000, 0x1000);
188 memblock_reserve(0x30081000, 0x1000);
189}
190
191static void __init rx3715_init_irq(void)
192{
193 s3c24xx_init_irq();
194}
195
196static void __init rx3715_init_machine(void)
197{
198#ifdef CONFIG_PM_H1940
199 memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024);
200#endif
201 s3c_pm_init();
202
203 s3c_nand_set_platdata(&rx3715_nand_info);
204 s3c24xx_fb_set_platdata(&rx3715_fb_info);
205 platform_add_devices(rx3715_devices, ARRAY_SIZE(rx3715_devices));
206}
207
208MACHINE_START(RX3715, "IPAQ-RX3715")
209 /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
210 .atag_offset = 0x100,
211 .map_io = rx3715_map_io,
212 .reserve = rx3715_reserve,
213 .init_irq = rx3715_init_irq,
214 .init_machine = rx3715_init_machine,
215 .timer = &s3c24xx_timer,
216 .restart = s3c2440_restart,
217MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2440.c b/arch/arm/mach-s3c24xx/mach-smdk2440.c
new file mode 100644
index 000000000000..1deb60d12a60
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/mach-smdk2440.c
@@ -0,0 +1,187 @@
1/* linux/arch/arm/mach-s3c2440/mach-smdk2440.c
2 *
3 * Copyright (c) 2004-2005 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * http://www.fluff.org/ben/smdk2440/
7 *
8 * Thanks to Dimity Andric and TomTom for the loan of an SMDK2440.
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
26#include <asm/mach/arch.h>
27#include <asm/mach/map.h>
28#include <asm/mach/irq.h>
29
30#include <mach/hardware.h>
31#include <asm/irq.h>
32#include <asm/mach-types.h>
33
34#include <plat/regs-serial.h>
35#include <mach/regs-gpio.h>
36#include <mach/regs-lcd.h>
37
38#include <mach/idle.h>
39#include <mach/fb.h>
40#include <plat/iic.h>
41
42#include <plat/s3c2410.h>
43#include <plat/s3c244x.h>
44#include <plat/clock.h>
45#include <plat/devs.h>
46#include <plat/cpu.h>
47
48#include <plat/common-smdk.h>
49
50#include "common.h"
51
52static struct map_desc smdk2440_iodesc[] __initdata = {
53 /* ISA IO Space map (memory space selected by A24) */
54
55 {
56 .virtual = (u32)S3C24XX_VA_ISA_WORD,
57 .pfn = __phys_to_pfn(S3C2410_CS2),
58 .length = 0x10000,
59 .type = MT_DEVICE,
60 }, {
61 .virtual = (u32)S3C24XX_VA_ISA_WORD + 0x10000,
62 .pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)),
63 .length = SZ_4M,
64 .type = MT_DEVICE,
65 }, {
66 .virtual = (u32)S3C24XX_VA_ISA_BYTE,
67 .pfn = __phys_to_pfn(S3C2410_CS2),
68 .length = 0x10000,
69 .type = MT_DEVICE,
70 }, {
71 .virtual = (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
72 .pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)),
73 .length = SZ_4M,
74 .type = MT_DEVICE,
75 }
76};
77
78#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
79#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
80#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
81
82static struct s3c2410_uartcfg smdk2440_uartcfgs[] __initdata = {
83 [0] = {
84 .hwport = 0,
85 .flags = 0,
86 .ucon = 0x3c5,
87 .ulcon = 0x03,
88 .ufcon = 0x51,
89 },
90 [1] = {
91 .hwport = 1,
92 .flags = 0,
93 .ucon = 0x3c5,
94 .ulcon = 0x03,
95 .ufcon = 0x51,
96 },
97 /* IR port */
98 [2] = {
99 .hwport = 2,
100 .flags = 0,
101 .ucon = 0x3c5,
102 .ulcon = 0x43,
103 .ufcon = 0x51,
104 }
105};
106
107/* LCD driver info */
108
109static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = {
110
111 .lcdcon5 = S3C2410_LCDCON5_FRM565 |
112 S3C2410_LCDCON5_INVVLINE |
113 S3C2410_LCDCON5_INVVFRAME |
114 S3C2410_LCDCON5_PWREN |
115 S3C2410_LCDCON5_HWSWP,
116
117 .type = S3C2410_LCDCON1_TFT,
118
119 .width = 240,
120 .height = 320,
121
122 .pixclock = 166667, /* HCLK 60 MHz, divisor 10 */
123 .xres = 240,
124 .yres = 320,
125 .bpp = 16,
126 .left_margin = 20,
127 .right_margin = 8,
128 .hsync_len = 4,
129 .upper_margin = 8,
130 .lower_margin = 7,
131 .vsync_len = 4,
132};
133
134static struct s3c2410fb_mach_info smdk2440_fb_info __initdata = {
135 .displays = &smdk2440_lcd_cfg,
136 .num_displays = 1,
137 .default_display = 0,
138
139#if 0
140 /* currently setup by downloader */
141 .gpccon = 0xaa940659,
142 .gpccon_mask = 0xffffffff,
143 .gpcup = 0x0000ffff,
144 .gpcup_mask = 0xffffffff,
145 .gpdcon = 0xaa84aaa0,
146 .gpdcon_mask = 0xffffffff,
147 .gpdup = 0x0000faff,
148 .gpdup_mask = 0xffffffff,
149#endif
150
151 .lpcsel = ((0xCE6) & ~7) | 1<<4,
152};
153
154static struct platform_device *smdk2440_devices[] __initdata = {
155 &s3c_device_ohci,
156 &s3c_device_lcd,
157 &s3c_device_wdt,
158 &s3c_device_i2c0,
159 &s3c_device_iis,
160};
161
162static void __init smdk2440_map_io(void)
163{
164 s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
165 s3c24xx_init_clocks(16934400);
166 s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
167}
168
169static void __init smdk2440_machine_init(void)
170{
171 s3c24xx_fb_set_platdata(&smdk2440_fb_info);
172 s3c_i2c0_set_platdata(NULL);
173
174 platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));
175 smdk_machine_init();
176}
177
178MACHINE_START(S3C2440, "SMDK2440")
179 /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
180 .atag_offset = 0x100,
181
182 .init_irq = s3c24xx_init_irq,
183 .map_io = smdk2440_map_io,
184 .init_machine = smdk2440_machine_init,
185 .timer = &s3c24xx_timer,
186 .restart = s3c2440_restart,
187MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/s3c2440.c b/arch/arm/mach-s3c24xx/s3c2440.c
new file mode 100644
index 000000000000..517623a09fc5
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/s3c2440.c
@@ -0,0 +1,88 @@
1/* linux/arch/arm/mach-s3c2440/s3c2440.c
2 *
3 * Copyright (c) 2004-2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Samsung S3C2440 Mobile CPU support
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 <linux/kernel.h>
14#include <linux/types.h>
15#include <linux/interrupt.h>
16#include <linux/list.h>
17#include <linux/timer.h>
18#include <linux/init.h>
19#include <linux/platform_device.h>
20#include <linux/serial_core.h>
21#include <linux/device.h>
22#include <linux/syscore_ops.h>
23#include <linux/gpio.h>
24#include <linux/clk.h>
25#include <linux/io.h>
26
27#include <asm/mach/arch.h>
28#include <asm/mach/map.h>
29#include <asm/mach/irq.h>
30
31#include <mach/hardware.h>
32#include <asm/irq.h>
33
34#include <plat/devs.h>
35#include <plat/cpu.h>
36#include <plat/s3c244x.h>
37#include <plat/pm.h>
38#include <plat/watchdog-reset.h>
39
40#include <plat/gpio-core.h>
41#include <plat/gpio-cfg.h>
42#include <plat/gpio-cfg-helpers.h>
43
44static struct device s3c2440_dev = {
45 .bus = &s3c2440_subsys,
46};
47
48int __init s3c2440_init(void)
49{
50 printk("S3C2440: Initialising architecture\n");
51
52 /* change irq for watchdog */
53
54 s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
55 s3c_device_wdt.resource[1].end = IRQ_S3C2440_WDT;
56
57 /* register suspend/resume handlers */
58
59#ifdef CONFIG_PM
60 register_syscore_ops(&s3c2410_pm_syscore_ops);
61#endif
62 register_syscore_ops(&s3c244x_pm_syscore_ops);
63 register_syscore_ops(&s3c24xx_irq_syscore_ops);
64
65 /* register our system device for everything else */
66
67 return device_register(&s3c2440_dev);
68}
69
70void __init s3c2440_map_io(void)
71{
72 s3c244x_map_io();
73
74 s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1up;
75 s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1up;
76}
77
78void s3c2440_restart(char mode, const char *cmd)
79{
80 if (mode == 's') {
81 soft_restart(0);
82 }
83
84 arch_wdt_reset();
85
86 /* we'll take a jump through zero as a poor second */
87 soft_restart(0);
88}
diff --git a/arch/arm/mach-s3c24xx/s3c2442.c b/arch/arm/mach-s3c24xx/s3c2442.c
new file mode 100644
index 000000000000..8004e0497bf4
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/s3c2442.c
@@ -0,0 +1,188 @@
1/* linux/arch/arm/mach-s3c2442/s3c2442.c
2 *
3 * Copyright (c) 2004-2005 Simtec Electronics
4 * http://armlinux.simtec.co.uk/
5 * Ben Dooks <ben@simtec.co.uk>
6 *
7 * S3C2442 core and lock support
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 as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22*/
23
24#include <linux/init.h>
25#include <linux/module.h>
26#include <linux/kernel.h>
27#include <linux/list.h>
28#include <linux/errno.h>
29#include <linux/err.h>
30#include <linux/device.h>
31#include <linux/syscore_ops.h>
32#include <linux/interrupt.h>
33#include <linux/ioport.h>
34#include <linux/mutex.h>
35#include <linux/gpio.h>
36#include <linux/clk.h>
37#include <linux/io.h>
38
39#include <mach/hardware.h>
40#include <linux/atomic.h>
41#include <asm/irq.h>
42
43#include <mach/regs-clock.h>
44
45#include <plat/clock.h>
46#include <plat/cpu.h>
47#include <plat/s3c244x.h>
48#include <plat/pm.h>
49
50#include <plat/gpio-core.h>
51#include <plat/gpio-cfg.h>
52#include <plat/gpio-cfg-helpers.h>
53
54/* S3C2442 extended clock support */
55
56static unsigned long s3c2442_camif_upll_round(struct clk *clk,
57 unsigned long rate)
58{
59 unsigned long parent_rate = clk_get_rate(clk->parent);
60 int div;
61
62 if (rate > parent_rate)
63 return parent_rate;
64
65 div = parent_rate / rate;
66
67 if (div == 3)
68 return parent_rate / 3;
69
70 /* note, we remove the +/- 1 calculations for the divisor */
71
72 div /= 2;
73
74 if (div < 1)
75 div = 1;
76 else if (div > 16)
77 div = 16;
78
79 return parent_rate / (div * 2);
80}
81
82static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate)
83{
84 unsigned long parent_rate = clk_get_rate(clk->parent);
85 unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
86
87 rate = s3c2442_camif_upll_round(clk, rate);
88
89 camdivn &= ~S3C2442_CAMDIVN_CAMCLK_DIV3;
90
91 if (rate == parent_rate) {
92 camdivn &= ~S3C2440_CAMDIVN_CAMCLK_SEL;
93 } else if ((parent_rate / rate) == 3) {
94 camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
95 camdivn |= S3C2442_CAMDIVN_CAMCLK_DIV3;
96 } else {
97 camdivn &= ~S3C2440_CAMDIVN_CAMCLK_MASK;
98 camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
99 camdivn |= (((parent_rate / rate) / 2) - 1);
100 }
101
102 __raw_writel(camdivn, S3C2440_CAMDIVN);
103
104 return 0;
105}
106
107/* Extra S3C2442 clocks */
108
109static struct clk s3c2442_clk_cam = {
110 .name = "camif",
111 .id = -1,
112 .enable = s3c2410_clkcon_enable,
113 .ctrlbit = S3C2440_CLKCON_CAMERA,
114};
115
116static struct clk s3c2442_clk_cam_upll = {
117 .name = "camif-upll",
118 .id = -1,
119 .ops = &(struct clk_ops) {
120 .set_rate = s3c2442_camif_upll_setrate,
121 .round_rate = s3c2442_camif_upll_round,
122 },
123};
124
125static int s3c2442_clk_add(struct device *dev)
126{
127 struct clk *clock_upll;
128 struct clk *clock_h;
129 struct clk *clock_p;
130
131 clock_p = clk_get(NULL, "pclk");
132 clock_h = clk_get(NULL, "hclk");
133 clock_upll = clk_get(NULL, "upll");
134
135 if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) {
136 printk(KERN_ERR "S3C2442: Failed to get parent clocks\n");
137 return -EINVAL;
138 }
139
140 s3c2442_clk_cam.parent = clock_h;
141 s3c2442_clk_cam_upll.parent = clock_upll;
142
143 s3c24xx_register_clock(&s3c2442_clk_cam);
144 s3c24xx_register_clock(&s3c2442_clk_cam_upll);
145
146 clk_disable(&s3c2442_clk_cam);
147
148 return 0;
149}
150
151static struct subsys_interface s3c2442_clk_interface = {
152 .name = "s3c2442_clk",
153 .subsys = &s3c2442_subsys,
154 .add_dev = s3c2442_clk_add,
155};
156
157static __init int s3c2442_clk_init(void)
158{
159 return subsys_interface_register(&s3c2442_clk_interface);
160}
161
162arch_initcall(s3c2442_clk_init);
163
164
165static struct device s3c2442_dev = {
166 .bus = &s3c2442_subsys,
167};
168
169int __init s3c2442_init(void)
170{
171 printk("S3C2442: Initialising architecture\n");
172
173#ifdef CONFIG_PM
174 register_syscore_ops(&s3c2410_pm_syscore_ops);
175#endif
176 register_syscore_ops(&s3c244x_pm_syscore_ops);
177 register_syscore_ops(&s3c24xx_irq_syscore_ops);
178
179 return device_register(&s3c2442_dev);
180}
181
182void __init s3c2442_map_io(void)
183{
184 s3c244x_map_io();
185
186 s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1down;
187 s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1down;
188}
diff --git a/arch/arm/mach-s3c24xx/s3c244x.c b/arch/arm/mach-s3c24xx/s3c244x.c
new file mode 100644
index 000000000000..36bc60f61d0a
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/s3c244x.c
@@ -0,0 +1,198 @@
1/* linux/arch/arm/plat-s3c24xx/s3c244x.c
2 *
3 * Copyright (c) 2004-2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Samsung S3C2440 and S3C2442 Mobile CPU support (not S3C2443)
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 <linux/kernel.h>
14#include <linux/types.h>
15#include <linux/interrupt.h>
16#include <linux/list.h>
17#include <linux/timer.h>
18#include <linux/init.h>
19#include <linux/serial_core.h>
20#include <linux/platform_device.h>
21#include <linux/device.h>
22#include <linux/syscore_ops.h>
23#include <linux/clk.h>
24#include <linux/io.h>
25
26#include <asm/mach/arch.h>
27#include <asm/mach/map.h>
28#include <asm/mach/irq.h>
29
30#include <mach/hardware.h>
31#include <asm/irq.h>
32
33#include <plat/cpu-freq.h>
34
35#include <mach/regs-clock.h>
36#include <plat/regs-serial.h>
37#include <mach/regs-gpio.h>
38#include <mach/regs-gpioj.h>
39#include <mach/regs-dsc.h>
40
41#include <plat/s3c2410.h>
42#include <plat/s3c244x.h>
43#include <plat/clock.h>
44#include <plat/devs.h>
45#include <plat/cpu.h>
46#include <plat/pm.h>
47#include <plat/pll.h>
48#include <plat/nand-core.h>
49
50static struct map_desc s3c244x_iodesc[] __initdata = {
51 IODESC_ENT(CLKPWR),
52 IODESC_ENT(TIMER),
53 IODESC_ENT(WATCHDOG),
54};
55
56/* uart initialisation */
57
58void __init s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no)
59{
60 s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
61}
62
63void __init s3c244x_map_io(void)
64{
65 /* register our io-tables */
66
67 iotable_init(s3c244x_iodesc, ARRAY_SIZE(s3c244x_iodesc));
68
69 /* rename any peripherals used differing from the s3c2410 */
70
71 s3c_device_sdi.name = "s3c2440-sdi";
72 s3c_device_i2c0.name = "s3c2440-i2c";
73 s3c_nand_setname("s3c2440-nand");
74 s3c_device_ts.name = "s3c2440-ts";
75 s3c_device_usbgadget.name = "s3c2440-usbgadget";
76}
77
78void __init_or_cpufreq s3c244x_setup_clocks(void)
79{
80 struct clk *xtal_clk;
81 unsigned long clkdiv;
82 unsigned long camdiv;
83 unsigned long xtal;
84 unsigned long hclk, fclk, pclk;
85 int hdiv = 1;
86
87 xtal_clk = clk_get(NULL, "xtal");
88 xtal = clk_get_rate(xtal_clk);
89 clk_put(xtal_clk);
90
91 fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;
92
93 clkdiv = __raw_readl(S3C2410_CLKDIVN);
94 camdiv = __raw_readl(S3C2440_CAMDIVN);
95
96 /* work out clock scalings */
97
98 switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
99 case S3C2440_CLKDIVN_HDIVN_1:
100 hdiv = 1;
101 break;
102
103 case S3C2440_CLKDIVN_HDIVN_2:
104 hdiv = 2;
105 break;
106
107 case S3C2440_CLKDIVN_HDIVN_4_8:
108 hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
109 break;
110
111 case S3C2440_CLKDIVN_HDIVN_3_6:
112 hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
113 break;
114 }
115
116 hclk = fclk / hdiv;
117 pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN) ? 2 : 1);
118
119 /* print brief summary of clocks, etc */
120
121 printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
122 print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
123
124 s3c24xx_setup_clocks(fclk, hclk, pclk);
125}
126
127void __init s3c244x_init_clocks(int xtal)
128{
129 /* initialise the clocks here, to allow other things like the
130 * console to use them, and to add new ones after the initialisation
131 */
132
133 s3c24xx_register_baseclocks(xtal);
134 s3c244x_setup_clocks();
135 s3c2410_baseclk_add();
136}
137
138/* Since the S3C2442 and S3C2440 share items, put both subsystems here */
139
140struct bus_type s3c2440_subsys = {
141 .name = "s3c2440-core",
142 .dev_name = "s3c2440-core",
143};
144
145struct bus_type s3c2442_subsys = {
146 .name = "s3c2442-core",
147 .dev_name = "s3c2442-core",
148};
149
150/* need to register the subsystem before we actually register the device, and
151 * we also need to ensure that it has been initialised before any of the
152 * drivers even try to use it (even if not on an s3c2440 based system)
153 * as a driver which may support both 2410 and 2440 may try and use it.
154*/
155
156static int __init s3c2440_core_init(void)
157{
158 return subsys_system_register(&s3c2440_subsys, NULL);
159}
160
161core_initcall(s3c2440_core_init);
162
163static int __init s3c2442_core_init(void)
164{
165 return subsys_system_register(&s3c2442_subsys, NULL);
166}
167
168core_initcall(s3c2442_core_init);
169
170
171#ifdef CONFIG_PM
172static struct sleep_save s3c244x_sleep[] = {
173 SAVE_ITEM(S3C2440_DSC0),
174 SAVE_ITEM(S3C2440_DSC1),
175 SAVE_ITEM(S3C2440_GPJDAT),
176 SAVE_ITEM(S3C2440_GPJCON),
177 SAVE_ITEM(S3C2440_GPJUP)
178};
179
180static int s3c244x_suspend(void)
181{
182 s3c_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
183 return 0;
184}
185
186static void s3c244x_resume(void)
187{
188 s3c_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
189}
190#else
191#define s3c244x_suspend NULL
192#define s3c244x_resume NULL
193#endif
194
195struct syscore_ops s3c244x_pm_syscore_ops = {
196 .suspend = s3c244x_suspend,
197 .resume = s3c244x_resume,
198};