Linux Audio

Check our new training course

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