ARM: s3c: make headers local if possible
[linux-2.6-microblaze.git] / arch / arm / mach-s3c / mach-real6410.c
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Copyright 2010 Darius Augulis <augulis.darius@gmail.com>
4 // Copyright 2008 Openmoko, Inc.
5 // Copyright 2008 Simtec Electronics
6 //      Ben Dooks <ben@simtec.co.uk>
7 //      http://armlinux.simtec.co.uk/
8
9 #include <linux/init.h>
10 #include <linux/interrupt.h>
11 #include <linux/fb.h>
12 #include <linux/gpio.h>
13 #include <linux/kernel.h>
14 #include <linux/list.h>
15 #include <linux/dm9000.h>
16 #include <linux/mtd/mtd.h>
17 #include <linux/mtd/partitions.h>
18 #include <linux/platform_device.h>
19 #include <linux/serial_core.h>
20 #include <linux/serial_s3c.h>
21 #include <linux/types.h>
22
23 #include <asm/mach-types.h>
24 #include <asm/mach/arch.h>
25 #include <asm/mach/map.h>
26
27 #include "map.h"
28 #include "regs-gpio.h"
29 #include "gpio-samsung.h"
30 #include <mach/irqs.h>
31
32 #include <linux/soc/samsung/s3c-adc.h>
33 #include "cpu.h"
34 #include "devs.h"
35 #include "fb.h"
36 #include <linux/platform_data/mtd-nand-s3c2410.h>
37 #include <linux/platform_data/touchscreen-s3c2410.h>
38
39 #include <video/platform_lcd.h>
40 #include <video/samsung_fimd.h>
41
42 #include "s3c64xx.h"
43 #include "regs-modem-s3c64xx.h"
44 #include "regs-srom-s3c64xx.h"
45
46 #define UCON S3C2410_UCON_DEFAULT
47 #define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
48 #define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
49
50 static struct s3c2410_uartcfg real6410_uartcfgs[] __initdata = {
51         [0] = {
52                 .hwport = 0,
53                 .flags  = 0,
54                 .ucon   = UCON,
55                 .ulcon  = ULCON,
56                 .ufcon  = UFCON,
57         },
58         [1] = {
59                 .hwport = 1,
60                 .flags  = 0,
61                 .ucon   = UCON,
62                 .ulcon  = ULCON,
63                 .ufcon  = UFCON,
64         },
65         [2] = {
66                 .hwport = 2,
67                 .flags  = 0,
68                 .ucon   = UCON,
69                 .ulcon  = ULCON,
70                 .ufcon  = UFCON,
71         },
72         [3] = {
73                 .hwport = 3,
74                 .flags  = 0,
75                 .ucon   = UCON,
76                 .ulcon  = ULCON,
77                 .ufcon  = UFCON,
78         },
79 };
80
81 /* DM9000AEP 10/100 ethernet controller */
82
83 static struct resource real6410_dm9k_resource[] = {
84         [0] = DEFINE_RES_MEM(S3C64XX_PA_XM0CSN1, 2),
85         [1] = DEFINE_RES_MEM(S3C64XX_PA_XM0CSN1 + 4, 2),
86         [2] = DEFINE_RES_NAMED(S3C_EINT(7), 1, NULL, IORESOURCE_IRQ \
87                                         | IORESOURCE_IRQ_HIGHLEVEL),
88 };
89
90 static struct dm9000_plat_data real6410_dm9k_pdata = {
91         .flags          = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
92 };
93
94 static struct platform_device real6410_device_eth = {
95         .name           = "dm9000",
96         .id             = -1,
97         .num_resources  = ARRAY_SIZE(real6410_dm9k_resource),
98         .resource       = real6410_dm9k_resource,
99         .dev            = {
100                 .platform_data  = &real6410_dm9k_pdata,
101         },
102 };
103
104 static struct s3c_fb_pd_win real6410_lcd_type0_fb_win = {
105         .max_bpp        = 32,
106         .default_bpp    = 16,
107         .xres           = 480,
108         .yres           = 272,
109 };
110
111 static struct fb_videomode real6410_lcd_type0_timing = {
112         /* 4.3" 480x272 */
113         .left_margin    = 3,
114         .right_margin   = 2,
115         .upper_margin   = 1,
116         .lower_margin   = 1,
117         .hsync_len      = 40,
118         .vsync_len      = 1,
119 };
120
121 static struct s3c_fb_pd_win real6410_lcd_type1_fb_win = {
122         .max_bpp        = 32,
123         .default_bpp    = 16,
124         .xres           = 800,
125         .yres           = 480,
126 };
127
128 static struct fb_videomode real6410_lcd_type1_timing = {
129         /* 7.0" 800x480 */
130         .left_margin    = 8,
131         .right_margin   = 13,
132         .upper_margin   = 7,
133         .lower_margin   = 5,
134         .hsync_len      = 3,
135         .vsync_len      = 1,
136         .xres           = 800,
137         .yres           = 480,
138 };
139
140 static struct s3c_fb_platdata real6410_lcd_pdata[] __initdata = {
141         {
142                 .setup_gpio     = s3c64xx_fb_gpio_setup_24bpp,
143                 .vtiming        = &real6410_lcd_type0_timing,
144                 .win[0]         = &real6410_lcd_type0_fb_win,
145                 .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
146                 .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
147         }, {
148                 .setup_gpio     = s3c64xx_fb_gpio_setup_24bpp,
149                 .vtiming        = &real6410_lcd_type1_timing,
150                 .win[0]         = &real6410_lcd_type1_fb_win,
151                 .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
152                 .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
153         },
154         { },
155 };
156
157 static struct mtd_partition real6410_nand_part[] = {
158         [0] = {
159                 .name   = "uboot",
160                 .size   = SZ_1M,
161                 .offset = 0,
162         },
163         [1] = {
164                 .name   = "kernel",
165                 .size   = SZ_2M,
166                 .offset = SZ_1M,
167         },
168         [2] = {
169                 .name   = "rootfs",
170                 .size   = MTDPART_SIZ_FULL,
171                 .offset = SZ_1M + SZ_2M,
172         },
173 };
174
175 static struct s3c2410_nand_set real6410_nand_sets[] = {
176         [0] = {
177                 .name           = "nand",
178                 .nr_chips       = 1,
179                 .nr_partitions  = ARRAY_SIZE(real6410_nand_part),
180                 .partitions     = real6410_nand_part,
181         },
182 };
183
184 static struct s3c2410_platform_nand real6410_nand_info = {
185         .tacls          = 25,
186         .twrph0         = 55,
187         .twrph1         = 40,
188         .nr_sets        = ARRAY_SIZE(real6410_nand_sets),
189         .sets           = real6410_nand_sets,
190         .ecc_mode       = NAND_ECC_SOFT,
191 };
192
193 static struct platform_device *real6410_devices[] __initdata = {
194         &real6410_device_eth,
195         &s3c_device_hsmmc0,
196         &s3c_device_hsmmc1,
197         &s3c_device_fb,
198         &s3c_device_nand,
199         &s3c_device_adc,
200         &s3c_device_ohci,
201 };
202
203 static void __init real6410_map_io(void)
204 {
205         u32 tmp;
206
207         s3c64xx_init_io(NULL, 0);
208         s3c24xx_init_clocks(12000000);
209         s3c24xx_init_uarts(real6410_uartcfgs, ARRAY_SIZE(real6410_uartcfgs));
210         samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
211
212         /* set the LCD type */
213         tmp = __raw_readl(S3C64XX_SPCON);
214         tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
215         tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
216         __raw_writel(tmp, S3C64XX_SPCON);
217
218         /* remove the LCD bypass */
219         tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
220         tmp &= ~MIFPCON_LCD_BYPASS;
221         __raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
222 }
223
224 /*
225  * real6410_features string
226  *
227  * 0-9 LCD configuration
228  *
229  */
230 static char real6410_features_str[12] __initdata = "0";
231
232 static int __init real6410_features_setup(char *str)
233 {
234         if (str)
235                 strlcpy(real6410_features_str, str,
236                         sizeof(real6410_features_str));
237         return 1;
238 }
239
240 __setup("real6410=", real6410_features_setup);
241
242 #define FEATURE_SCREEN (1 << 0)
243
244 struct real6410_features_t {
245         int done;
246         int lcd_index;
247 };
248
249 static void real6410_parse_features(
250                 struct real6410_features_t *features,
251                 const char *features_str)
252 {
253         const char *fp = features_str;
254
255         features->done = 0;
256         features->lcd_index = 0;
257
258         while (*fp) {
259                 char f = *fp++;
260
261                 switch (f) {
262                 case '0'...'9': /* tft screen */
263                         if (features->done & FEATURE_SCREEN) {
264                                 printk(KERN_INFO "REAL6410: '%c' ignored, "
265                                         "screen type already set\n", f);
266                         } else {
267                                 int li = f - '0';
268                                 if (li >= ARRAY_SIZE(real6410_lcd_pdata))
269                                         printk(KERN_INFO "REAL6410: '%c' out "
270                                                 "of range LCD mode\n", f);
271                                 else {
272                                         features->lcd_index = li;
273                                 }
274                         }
275                         features->done |= FEATURE_SCREEN;
276                         break;
277                 }
278         }
279 }
280
281 static void __init real6410_machine_init(void)
282 {
283         u32 cs1;
284         struct real6410_features_t features = { 0 };
285
286         printk(KERN_INFO "REAL6410: Option string real6410=%s\n",
287                         real6410_features_str);
288
289         /* Parse the feature string */
290         real6410_parse_features(&features, real6410_features_str);
291
292         printk(KERN_INFO "REAL6410: selected LCD display is %dx%d\n",
293                 real6410_lcd_pdata[features.lcd_index].win[0]->xres,
294                 real6410_lcd_pdata[features.lcd_index].win[0]->yres);
295
296         s3c_fb_set_platdata(&real6410_lcd_pdata[features.lcd_index]);
297         s3c_nand_set_platdata(&real6410_nand_info);
298         s3c64xx_ts_set_platdata(NULL);
299
300         /* configure nCS1 width to 16 bits */
301
302         cs1 = __raw_readl(S3C64XX_SROM_BW) &
303                 ~(S3C64XX_SROM_BW__CS_MASK << S3C64XX_SROM_BW__NCS1__SHIFT);
304         cs1 |= ((1 << S3C64XX_SROM_BW__DATAWIDTH__SHIFT) |
305                 (1 << S3C64XX_SROM_BW__WAITENABLE__SHIFT) |
306                 (1 << S3C64XX_SROM_BW__BYTEENABLE__SHIFT)) <<
307                         S3C64XX_SROM_BW__NCS1__SHIFT;
308         __raw_writel(cs1, S3C64XX_SROM_BW);
309
310         /* set timing for nCS1 suitable for ethernet chip */
311
312         __raw_writel((0 << S3C64XX_SROM_BCX__PMC__SHIFT) |
313                 (6 << S3C64XX_SROM_BCX__TACP__SHIFT) |
314                 (4 << S3C64XX_SROM_BCX__TCAH__SHIFT) |
315                 (1 << S3C64XX_SROM_BCX__TCOH__SHIFT) |
316                 (13 << S3C64XX_SROM_BCX__TACC__SHIFT) |
317                 (4 << S3C64XX_SROM_BCX__TCOS__SHIFT) |
318                 (0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1);
319
320         gpio_request(S3C64XX_GPF(15), "LCD power");
321
322         platform_add_devices(real6410_devices, ARRAY_SIZE(real6410_devices));
323 }
324
325 MACHINE_START(REAL6410, "REAL6410")
326         /* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
327         .atag_offset    = 0x100,
328         .nr_irqs        = S3C64XX_NR_IRQS,
329         .init_irq       = s3c6410_init_irq,
330         .map_io         = real6410_map_io,
331         .init_machine   = real6410_machine_init,
332         .init_time      = samsung_timer_init,
333 MACHINE_END