blob: 441b71a9b19cb048b31cb12c4bdd4b8e82b7a461 [file] [log] [blame]
Darius Augulise9debd92010-10-21 07:42:29 +09001/* linux/arch/arm/mach-s3c64xx/mach-mini6410.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>
Darius Augulis2abca872010-10-19 16:06:54 +090017#include <linux/fb.h>
Darius Augulise9debd92010-10-21 07:42:29 +090018#include <linux/gpio.h>
19#include <linux/kernel.h>
20#include <linux/list.h>
21#include <linux/dm9000.h>
Darius Augulis1c5d76e2010-10-19 16:04:16 +090022#include <linux/mtd/mtd.h>
23#include <linux/mtd/partitions.h>
Darius Augulise9debd92010-10-21 07:42:29 +090024#include <linux/serial_core.h>
25#include <linux/types.h>
26
27#include <asm/mach-types.h>
28#include <asm/mach/arch.h>
29#include <asm/mach/map.h>
30
31#include <mach/map.h>
Darius Augulis2abca872010-10-19 16:06:54 +090032#include <mach/regs-fb.h>
Darius Augulise9debd92010-10-21 07:42:29 +090033#include <mach/regs-gpio.h>
Darius Augulis2abca872010-10-19 16:06:54 +090034#include <mach/regs-modem.h>
Darius Augulise9debd92010-10-21 07:42:29 +090035#include <mach/regs-srom.h>
36#include <mach/s3c6410.h>
37
38#include <plat/cpu.h>
39#include <plat/devs.h>
Darius Augulis2abca872010-10-19 16:06:54 +090040#include <plat/fb.h>
Darius Augulis1c5d76e2010-10-19 16:04:16 +090041#include <plat/nand.h>
Darius Augulise9debd92010-10-21 07:42:29 +090042#include <plat/regs-serial.h>
43
44#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
45#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
46#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
47
48static struct s3c2410_uartcfg mini6410_uartcfgs[] __initdata = {
49 [0] = {
50 .hwport = 0,
51 .flags = 0,
52 .ucon = UCON,
53 .ulcon = ULCON,
54 .ufcon = UFCON,
55 },
56 [1] = {
57 .hwport = 1,
58 .flags = 0,
59 .ucon = UCON,
60 .ulcon = ULCON,
61 .ufcon = UFCON,
62 },
63 [2] = {
64 .hwport = 2,
65 .flags = 0,
66 .ucon = UCON,
67 .ulcon = ULCON,
68 .ufcon = UFCON,
69 },
70 [3] = {
71 .hwport = 3,
72 .flags = 0,
73 .ucon = UCON,
74 .ulcon = ULCON,
75 .ufcon = UFCON,
76 },
77};
78
79/* DM9000AEP 10/100 ethernet controller */
80
81static struct resource mini6410_dm9k_resource[] = {
82 [0] = {
83 .start = S3C64XX_PA_XM0CSN1,
84 .end = S3C64XX_PA_XM0CSN1 + 1,
85 .flags = IORESOURCE_MEM
86 },
87 [1] = {
88 .start = S3C64XX_PA_XM0CSN1 + 4,
89 .end = S3C64XX_PA_XM0CSN1 + 5,
90 .flags = IORESOURCE_MEM
91 },
92 [2] = {
93 .start = S3C_EINT(7),
94 .end = S3C_EINT(7),
95 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL
96 }
97};
98
99static struct dm9000_plat_data mini6410_dm9k_pdata = {
100 .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
101};
102
103static struct platform_device mini6410_device_eth = {
104 .name = "dm9000",
105 .id = -1,
106 .num_resources = ARRAY_SIZE(mini6410_dm9k_resource),
107 .resource = mini6410_dm9k_resource,
108 .dev = {
109 .platform_data = &mini6410_dm9k_pdata,
110 },
111};
112
Darius Augulis1c5d76e2010-10-19 16:04:16 +0900113static struct mtd_partition mini6410_nand_part[] = {
114 [0] = {
115 .name = "uboot",
116 .size = SZ_1M,
117 .offset = 0,
118 },
119 [1] = {
120 .name = "kernel",
121 .size = SZ_2M,
122 .offset = SZ_1M,
123 },
124 [2] = {
125 .name = "rootfs",
126 .size = MTDPART_SIZ_FULL,
127 .offset = SZ_1M + SZ_2M,
128 },
129};
130
131static struct s3c2410_nand_set mini6410_nand_sets[] = {
132 [0] = {
133 .name = "nand",
134 .nr_chips = 1,
135 .nr_partitions = ARRAY_SIZE(mini6410_nand_part),
136 .partitions = mini6410_nand_part,
137 },
138};
139
140static struct s3c2410_platform_nand mini6410_nand_info = {
141 .tacls = 25,
142 .twrph0 = 55,
143 .twrph1 = 40,
144 .nr_sets = ARRAY_SIZE(mini6410_nand_sets),
145 .sets = mini6410_nand_sets,
146};
147
Darius Augulis2abca872010-10-19 16:06:54 +0900148static struct s3c_fb_pd_win mini6410_fb_win[] = {
149 {
150 .win_mode = { /* 4.3" 480x272 */
151 .left_margin = 3,
152 .right_margin = 2,
153 .upper_margin = 1,
154 .lower_margin = 1,
155 .hsync_len = 40,
156 .vsync_len = 1,
157 .xres = 480,
158 .yres = 272,
159 },
160 .max_bpp = 32,
161 .default_bpp = 16,
162 }, {
163 .win_mode = { /* 7.0" 800x480 */
164 .left_margin = 8,
165 .right_margin = 13,
166 .upper_margin = 7,
167 .lower_margin = 5,
168 .hsync_len = 3,
169 .vsync_len = 1,
170 .xres = 800,
171 .yres = 480,
172 },
173 .max_bpp = 32,
174 .default_bpp = 16,
175 },
176};
177
178static struct s3c_fb_platdata mini6410_lcd_pdata __initdata = {
179 .setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
180 .win[0] = &mini6410_fb_win[0],
181 .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
182 .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
183};
184
Darius Augulise9debd92010-10-21 07:42:29 +0900185static struct platform_device *mini6410_devices[] __initdata = {
186 &mini6410_device_eth,
187 &s3c_device_hsmmc0,
188 &s3c_device_hsmmc1,
189 &s3c_device_ohci,
Darius Augulis1c5d76e2010-10-19 16:04:16 +0900190 &s3c_device_nand,
Darius Augulis2abca872010-10-19 16:06:54 +0900191 &s3c_device_fb,
Darius Augulise9debd92010-10-21 07:42:29 +0900192};
193
194static void __init mini6410_map_io(void)
195{
Darius Augulis2abca872010-10-19 16:06:54 +0900196 u32 tmp;
197
Darius Augulise9debd92010-10-21 07:42:29 +0900198 s3c64xx_init_io(NULL, 0);
199 s3c24xx_init_clocks(12000000);
200 s3c24xx_init_uarts(mini6410_uartcfgs, ARRAY_SIZE(mini6410_uartcfgs));
Darius Augulis2abca872010-10-19 16:06:54 +0900201
202 /* set the LCD type */
203 tmp = __raw_readl(S3C64XX_SPCON);
204 tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
205 tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
206 __raw_writel(tmp, S3C64XX_SPCON);
207
208 /* remove the LCD bypass */
209 tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
210 tmp &= ~MIFPCON_LCD_BYPASS;
211 __raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
212}
213
214/*
215 * mini6410_features string
216 *
217 * 0-9 LCD configuration
218 *
219 */
220static char mini6410_features_str[12] __initdata = "0";
221
222static int __init mini6410_features_setup(char *str)
223{
224 if (str)
225 strlcpy(mini6410_features_str, str,
226 sizeof(mini6410_features_str));
227 return 1;
228}
229
230__setup("mini6410=", mini6410_features_setup);
231
232#define FEATURE_SCREEN (1 << 0)
233
234struct mini6410_features_t {
235 int done;
236 int lcd_index;
237};
238
239static void mini6410_parse_features(
240 struct mini6410_features_t *features,
241 const char *features_str)
242{
243 const char *fp = features_str;
244
245 features->done = 0;
246 features->lcd_index = 0;
247
248 while (*fp) {
249 char f = *fp++;
250
251 switch (f) {
252 case '0'...'9': /* tft screen */
253 if (features->done & FEATURE_SCREEN) {
254 printk(KERN_INFO "MINI6410: '%c' ignored, "
255 "screen type already set\n", f);
256 } else {
257 int li = f - '0';
258 if (li >= ARRAY_SIZE(mini6410_fb_win))
259 printk(KERN_INFO "MINI6410: '%c' out "
260 "of range LCD mode\n", f);
261 else {
262 features->lcd_index = li;
263 }
264 }
265 features->done |= FEATURE_SCREEN;
266 break;
267 }
268 }
Darius Augulise9debd92010-10-21 07:42:29 +0900269}
270
271static void __init mini6410_machine_init(void)
272{
273 u32 cs1;
Darius Augulis2abca872010-10-19 16:06:54 +0900274 struct mini6410_features_t features = { 0 };
275
276 printk(KERN_INFO "MINI6410: Option string mini6410=%s\n",
277 mini6410_features_str);
278
279 /* Parse the feature string */
280 mini6410_parse_features(&features, mini6410_features_str);
281
282 mini6410_lcd_pdata.win[0] = &mini6410_fb_win[features.lcd_index];
283
284 printk(KERN_INFO "MINI6410: selected LCD display is %dx%d\n",
285 mini6410_lcd_pdata.win[0]->win_mode.xres,
286 mini6410_lcd_pdata.win[0]->win_mode.yres);
Darius Augulise9debd92010-10-21 07:42:29 +0900287
Darius Augulis1c5d76e2010-10-19 16:04:16 +0900288 s3c_nand_set_platdata(&mini6410_nand_info);
Darius Augulis2abca872010-10-19 16:06:54 +0900289 s3c_fb_set_platdata(&mini6410_lcd_pdata);
Darius Augulis1c5d76e2010-10-19 16:04:16 +0900290
Darius Augulise9debd92010-10-21 07:42:29 +0900291 /* configure nCS1 width to 16 bits */
292
293 cs1 = __raw_readl(S3C64XX_SROM_BW) &
294 ~(S3C64XX_SROM_BW__CS_MASK << S3C64XX_SROM_BW__NCS1__SHIFT);
295 cs1 |= ((1 << S3C64XX_SROM_BW__DATAWIDTH__SHIFT) |
296 (1 << S3C64XX_SROM_BW__WAITENABLE__SHIFT) |
297 (1 << S3C64XX_SROM_BW__BYTEENABLE__SHIFT)) <<
298 S3C64XX_SROM_BW__NCS1__SHIFT;
299 __raw_writel(cs1, S3C64XX_SROM_BW);
300
301 /* set timing for nCS1 suitable for ethernet chip */
302
303 __raw_writel((0 << S3C64XX_SROM_BCX__PMC__SHIFT) |
304 (6 << S3C64XX_SROM_BCX__TACP__SHIFT) |
305 (4 << S3C64XX_SROM_BCX__TCAH__SHIFT) |
306 (1 << S3C64XX_SROM_BCX__TCOH__SHIFT) |
307 (13 << S3C64XX_SROM_BCX__TACC__SHIFT) |
308 (4 << S3C64XX_SROM_BCX__TCOS__SHIFT) |
309 (0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1);
310
Darius Augulis2abca872010-10-19 16:06:54 +0900311 gpio_request(S3C64XX_GPF(15), "LCD power");
312 gpio_request(S3C64XX_GPE(0), "LCD power");
313
Darius Augulise9debd92010-10-21 07:42:29 +0900314 platform_add_devices(mini6410_devices, ARRAY_SIZE(mini6410_devices));
315}
316
317MACHINE_START(MINI6410, "MINI6410")
318 /* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
319 .boot_params = S3C64XX_PA_SDRAM + 0x100,
320 .init_irq = s3c6410_init_irq,
321 .map_io = mini6410_map_io,
322 .init_machine = mini6410_machine_init,
323 .timer = &s3c24xx_timer,
324MACHINE_END