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