[ARM] JIVE: Add setup information for the S3C2412 LCD controller
[linux-2.6-block.git] / arch / arm / mach-s3c2412 / mach-jive.c
CommitLineData
9db829f4
BD
1/* linux/arch/arm/mach-s3c2410/mach-jive.c
2 *
3 * Copyright 2007 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * http://armlinux.simtec.co.uk/
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/sysdev.h>
20#include <linux/serial_core.h>
21#include <linux/platform_device.h>
22
23#include <linux/mtd/mtd.h>
24#include <linux/mtd/partitions.h>
25
26#include <asm/mach/arch.h>
27#include <asm/mach/map.h>
28#include <asm/mach/irq.h>
29
30#include <asm/plat-s3c/regs-serial.h>
31#include <asm/plat-s3c/nand.h>
32
33#include <asm/arch/regs-power.h>
34#include <asm/arch/regs-gpio.h>
35#include <asm/arch/regs-mem.h>
36#include <asm/arch/regs-lcd.h>
0f99263c 37#include <asm/arch/fb.h>
9db829f4
BD
38
39#include <asm/mach-types.h>
40
41#include <linux/mtd/mtd.h>
42#include <linux/mtd/nand.h>
43#include <linux/mtd/nand_ecc.h>
44#include <linux/mtd/partitions.h>
45
46#include <asm/plat-s3c24xx/clock.h>
47#include <asm/plat-s3c24xx/devs.h>
48#include <asm/plat-s3c24xx/cpu.h>
49#include <asm/plat-s3c24xx/pm.h>
50#include <asm/plat-s3c24xx/udc.h>
51
52static struct map_desc jive_iodesc[] __initdata = {
53};
54
55#define UCON S3C2410_UCON_DEFAULT
56#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE
57#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
58
59static struct s3c2410_uartcfg jive_uartcfgs[] = {
60 [0] = {
61 .hwport = 0,
62 .flags = 0,
63 .ucon = UCON,
64 .ulcon = ULCON,
65 .ufcon = UFCON,
66 },
67 [1] = {
68 .hwport = 1,
69 .flags = 0,
70 .ucon = UCON,
71 .ulcon = ULCON,
72 .ufcon = UFCON,
73 },
74 [2] = {
75 .hwport = 2,
76 .flags = 0,
77 .ucon = UCON,
78 .ulcon = ULCON,
79 .ufcon = UFCON,
80 }
81};
82
83/* Jive flash assignment
84 *
85 * 0x00000000-0x00028000 : uboot
86 * 0x00028000-0x0002c000 : uboot env
87 * 0x0002c000-0x00030000 : spare
88 * 0x00030000-0x00200000 : zimage A
89 * 0x00200000-0x01600000 : cramfs A
90 * 0x01600000-0x017d0000 : zimage B
91 * 0x017d0000-0x02bd0000 : cramfs B
92 * 0x02bd0000-0x03fd0000 : yaffs
93 */
94static struct mtd_partition jive_imageA_nand_part[] = {
95
96#ifdef CONFIG_MACH_JIVE_SHOW_BOOTLOADER
97 /* Don't allow access to the bootloader from linux */
98 {
99 .name = "uboot",
100 .offset = 0,
101 .size = (160 * SZ_1K),
102 .mask_flags = MTD_WRITEABLE, /* force read-only */
103 },
104
105 /* spare */
106 {
107 .name = "spare",
108 .offset = (176 * SZ_1K),
109 .size = (16 * SZ_1K),
110 },
111#endif
112
113 /* booted images */
114 {
115 .name = "kernel (ro)",
116 .offset = (192 * SZ_1K),
117 .size = (SZ_2M) - (192 * SZ_1K),
118 .mask_flags = MTD_WRITEABLE, /* force read-only */
119 }, {
120 .name = "root (ro)",
121 .offset = (SZ_2M),
122 .size = (20 * SZ_1M),
123 .mask_flags = MTD_WRITEABLE, /* force read-only */
124 },
125
126 /* yaffs */
127 {
128 .name = "yaffs",
129 .offset = (44 * SZ_1M),
130 .size = (20 * SZ_1M),
131 },
132
133 /* bootloader environment */
134 {
135 .name = "env",
136 .offset = (160 * SZ_1K),
137 .size = (16 * SZ_1K),
138 },
139
140 /* upgrade images */
141 {
142 .name = "zimage",
143 .offset = (22 * SZ_1M),
144 .size = (2 * SZ_1M) - (192 * SZ_1K),
145 }, {
146 .name = "cramfs",
147 .offset = (24 * SZ_1M) - (192*SZ_1K),
148 .size = (20 * SZ_1M),
149 },
150};
151
152static struct mtd_partition jive_imageB_nand_part[] = {
153
154#ifdef CONFIG_MACH_JIVE_SHOW_BOOTLOADER
155 /* Don't allow access to the bootloader from linux */
156 {
157 .name = "uboot",
158 .offset = 0,
159 .size = (160 * SZ_1K),
160 .mask_flags = MTD_WRITEABLE, /* force read-only */
161 },
162
163 /* spare */
164 {
165 .name = "spare",
166 .offset = (176 * SZ_1K),
167 .size = (16 * SZ_1K),
168 },
169#endif
170
171 /* booted images */
172 {
173 .name = "kernel (ro)",
174 .offset = (22 * SZ_1M),
175 .size = (2 * SZ_1M) - (192 * SZ_1K),
176 .mask_flags = MTD_WRITEABLE, /* force read-only */
177 },
178 {
179 .name = "root (ro)",
180 .offset = (24 * SZ_1M) - (192 * SZ_1K),
181 .size = (20 * SZ_1M),
182 .mask_flags = MTD_WRITEABLE, /* force read-only */
183 },
184
185 /* yaffs */
186 {
187 .name = "yaffs",
188 .offset = (44 * SZ_1M),
189 .size = (20 * SZ_1M),
190 },
191
192 /* bootloader environment */
193 {
194 .name = "env",
195 .offset = (160 * SZ_1K),
196 .size = (16 * SZ_1K),
197 },
198
199 /* upgrade images */
200 {
201 .name = "zimage",
202 .offset = (192 * SZ_1K),
203 .size = (2 * SZ_1M) - (192 * SZ_1K),
204 }, {
205 .name = "cramfs",
206 .offset = (2 * SZ_1M),
207 .size = (20 * SZ_1M),
208 },
209};
210
211static struct s3c2410_nand_set jive_nand_sets[] = {
212 [0] = {
213 .name = "flash",
214 .nr_chips = 1,
215 .nr_partitions = ARRAY_SIZE(jive_imageA_nand_part),
216 .partitions = jive_imageA_nand_part,
217 },
218};
219
220static struct s3c2410_platform_nand jive_nand_info = {
221 /* set taken from osiris nand timings, possibly still conservative */
222 .tacls = 30,
223 .twrph0 = 55,
224 .twrph1 = 40,
225 .sets = jive_nand_sets,
226 .nr_sets = ARRAY_SIZE(jive_nand_sets),
227};
228
229static int __init jive_mtdset(char *options)
230{
231 struct s3c2410_nand_set *nand = &jive_nand_sets[0];
232 unsigned long set;
233
234 if (options == NULL || options[0] == '\0')
235 return 0;
236
237 if (strict_strtoul(options, 10, &set)) {
238 printk(KERN_ERR "failed to parse mtdset=%s\n", options);
239 return 0;
240 }
241
242 switch (set) {
243 case 1:
244 nand->nr_partitions = ARRAY_SIZE(jive_imageB_nand_part);
245 nand->partitions = jive_imageB_nand_part;
246 case 0:
247 /* this is already setup in the nand info */
248 break;
249 default:
250 printk(KERN_ERR "Unknown mtd set %ld specified,"
251 "using default.", set);
252 }
253
254 return 0;
255}
256
257/* parse the mtdset= option given to the kernel command line */
258__setup("mtdset=", jive_mtdset);
259
0f99263c
BD
260/* LCD timing and setup */
261
262#define LCD_XRES (240)
263#define LCD_YRES (320)
264#define LCD_LEFT_MARGIN (12)
265#define LCD_RIGHT_MARGIN (12)
266#define LCD_LOWER_MARGIN (12)
267#define LCD_UPPER_MARGIN (12)
268#define LCD_VSYNC (2)
269#define LCD_HSYNC (2)
270
271#define LCD_REFRESH (60)
272
273#define LCD_HTOT (LCD_HSYNC + LCD_LEFT_MARGIN + LCD_XRES + LCD_RIGHT_MARGIN)
274#define LCD_VTOT (LCD_VSYNC + LCD_LOWER_MARGIN + LCD_YRES + LCD_UPPER_MARGIN)
275
276struct s3c2410fb_display jive_vgg2432a4_display[] = {
277 [0] = {
278 .width = LCD_XRES,
279 .height = LCD_YRES,
280 .xres = LCD_XRES,
281 .yres = LCD_YRES,
282 .left_margin = LCD_LEFT_MARGIN,
283 .right_margin = LCD_RIGHT_MARGIN,
284 .upper_margin = LCD_UPPER_MARGIN,
285 .lower_margin = LCD_LOWER_MARGIN,
286 .hsync_len = LCD_HSYNC,
287 .vsync_len = LCD_VSYNC,
288
289 .pixclock = (1000000000000LL /
290 (LCD_REFRESH * LCD_HTOT * LCD_VTOT)),
291
292 .bpp = 16,
293 .type = (S3C2410_LCDCON1_TFT16BPP |
294 S3C2410_LCDCON1_TFT),
295
296 .lcdcon5 = (S3C2410_LCDCON5_FRM565 |
297 S3C2410_LCDCON5_INVVLINE |
298 S3C2410_LCDCON5_INVVFRAME |
299 S3C2410_LCDCON5_INVVDEN |
300 S3C2410_LCDCON5_PWREN),
301 },
302};
303
304/* todo - put into gpio header */
305
306#define S3C2410_GPCCON_MASK(x) (3 << ((x) * 2))
307#define S3C2410_GPDCON_MASK(x) (3 << ((x) * 2))
308
309struct s3c2410fb_mach_info jive_lcd_config = {
310 .displays = jive_vgg2432a4_display,
311 .num_displays = ARRAY_SIZE(jive_vgg2432a4_display),
312 .default_display = 0,
313
314 /* Enable VD[2..7], VD[10..15], VD[18..23] and VCLK, syncs, VDEN
315 * and disable the pull down resistors on pins we are using for LCD
316 * data. */
317
318 .gpcup = (0xf << 1) | (0x3f << 10),
319
320 .gpccon = (S3C2410_GPC1_VCLK | S3C2410_GPC2_VLINE |
321 S3C2410_GPC3_VFRAME | S3C2410_GPC4_VM |
322 S3C2410_GPC10_VD2 | S3C2410_GPC11_VD3 |
323 S3C2410_GPC12_VD4 | S3C2410_GPC13_VD5 |
324 S3C2410_GPC14_VD6 | S3C2410_GPC15_VD7),
325
326 .gpccon_mask = (S3C2410_GPCCON_MASK(1) | S3C2410_GPCCON_MASK(2) |
327 S3C2410_GPCCON_MASK(3) | S3C2410_GPCCON_MASK(4) |
328 S3C2410_GPCCON_MASK(10) | S3C2410_GPCCON_MASK(11) |
329 S3C2410_GPCCON_MASK(12) | S3C2410_GPCCON_MASK(13) |
330 S3C2410_GPCCON_MASK(14) | S3C2410_GPCCON_MASK(15)),
331
332 .gpdup = (0x3f << 2) | (0x3f << 10),
333
334 .gpdcon = (S3C2410_GPD2_VD10 | S3C2410_GPD3_VD11 |
335 S3C2410_GPD4_VD12 | S3C2410_GPD5_VD13 |
336 S3C2410_GPD6_VD14 | S3C2410_GPD7_VD15 |
337 S3C2410_GPD10_VD18 | S3C2410_GPD11_VD19 |
338 S3C2410_GPD12_VD20 | S3C2410_GPD13_VD21 |
339 S3C2410_GPD14_VD22 | S3C2410_GPD15_VD23),
340
341 .gpdcon_mask = (S3C2410_GPDCON_MASK(2) | S3C2410_GPDCON_MASK(3) |
342 S3C2410_GPDCON_MASK(4) | S3C2410_GPDCON_MASK(5) |
343 S3C2410_GPDCON_MASK(6) | S3C2410_GPDCON_MASK(7) |
344 S3C2410_GPDCON_MASK(10) | S3C2410_GPDCON_MASK(11)|
345 S3C2410_GPDCON_MASK(12) | S3C2410_GPDCON_MASK(13)|
346 S3C2410_GPDCON_MASK(14) | S3C2410_GPDCON_MASK(15)),
347};
348
9db829f4
BD
349static struct platform_device *jive_devices[] __initdata = {
350 &s3c_device_usb,
351 &s3c_device_rtc,
352 &s3c_device_wdt,
353 &s3c_device_i2c,
0f99263c 354 &s3c_device_lcd,
9db829f4
BD
355 &s3c_device_nand,
356 &s3c_device_usbgadget,
357};
358
359static struct s3c2410_udc_mach_info jive_udc_cfg __initdata = {
360 .vbus_pin = S3C2410_GPG1, /* detect is on GPG1 */
361};
362
363/* Jive power management device */
364
365#ifdef CONFIG_PM
366static int jive_pm_suspend(struct sys_device *sd, pm_message_t state)
367{
368 /* Write the magic value u-boot uses to check for resume into
369 * the INFORM0 register, and ensure INFORM1 is set to the
370 * correct address to resume from. */
371
372 __raw_writel(0x2BED, S3C2412_INFORM0);
373 __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2412_INFORM1);
374
375 return 0;
376}
377
378static int jive_pm_resume(struct sys_device *sd)
379{
380 __raw_writel(0x0, S3C2412_INFORM0);
381 return 0;
382}
383
384#else
385#define jive_pm_suspend NULL
386#define jive_pm_resume NULL
387#endif
388
389static struct sysdev_class jive_pm_sysclass = {
390 .name = "jive-pm",
391 .suspend = jive_pm_suspend,
392 .resume = jive_pm_resume,
393};
394
395static struct sys_device jive_pm_sysdev = {
396 .cls = &jive_pm_sysclass,
397};
398
399static void __init jive_map_io(void)
400{
401 s3c24xx_init_io(jive_iodesc, ARRAY_SIZE(jive_iodesc));
402 s3c24xx_init_clocks(12000000);
403 s3c24xx_init_uarts(jive_uartcfgs, ARRAY_SIZE(jive_uartcfgs));
404}
405
406static void __init jive_machine_init(void)
407{
408 /* register system devices for managing low level suspend */
409
410 sysdev_class_register(&jive_pm_sysclass);
411 sysdev_register(&jive_pm_sysdev);
412
54c272ac
BD
413 /* write our sleep configurations for the IO. Pull down all unused
414 * IO, ensure that we have turned off all peripherals we do not
415 * need, and configure the ones we do need. */
416
417 /* Port B sleep */
418
419 __raw_writel(S3C2412_SLPCON_IN(0) |
420 S3C2412_SLPCON_PULL(1) |
421 S3C2412_SLPCON_HIGH(2) |
422 S3C2412_SLPCON_PULL(3) |
423 S3C2412_SLPCON_PULL(4) |
424 S3C2412_SLPCON_PULL(5) |
425 S3C2412_SLPCON_PULL(6) |
426 S3C2412_SLPCON_HIGH(7) |
427 S3C2412_SLPCON_PULL(8) |
428 S3C2412_SLPCON_PULL(9) |
429 S3C2412_SLPCON_PULL(10), S3C2412_GPBSLPCON);
430
431 /* Port C sleep */
432
433 __raw_writel(S3C2412_SLPCON_PULL(0) |
434 S3C2412_SLPCON_PULL(1) |
435 S3C2412_SLPCON_PULL(2) |
436 S3C2412_SLPCON_PULL(3) |
437 S3C2412_SLPCON_PULL(4) |
438 S3C2412_SLPCON_PULL(5) |
439 S3C2412_SLPCON_LOW(6) |
440 S3C2412_SLPCON_PULL(6) |
441 S3C2412_SLPCON_PULL(7) |
442 S3C2412_SLPCON_PULL(8) |
443 S3C2412_SLPCON_PULL(9) |
444 S3C2412_SLPCON_PULL(10) |
445 S3C2412_SLPCON_PULL(11) |
446 S3C2412_SLPCON_PULL(12) |
447 S3C2412_SLPCON_PULL(13) |
448 S3C2412_SLPCON_PULL(14) |
449 S3C2412_SLPCON_PULL(15), S3C2412_GPCSLPCON);
450
451 /* Port D sleep */
452
453 __raw_writel(S3C2412_SLPCON_ALL_PULL, S3C2412_GPDSLPCON);
454
455 /* Port F sleep */
456
457 __raw_writel(S3C2412_SLPCON_LOW(0) |
458 S3C2412_SLPCON_LOW(1) |
459 S3C2412_SLPCON_LOW(2) |
460 S3C2412_SLPCON_EINT(3) |
461 S3C2412_SLPCON_EINT(4) |
462 S3C2412_SLPCON_EINT(5) |
463 S3C2412_SLPCON_EINT(6) |
464 S3C2412_SLPCON_EINT(7), S3C2412_GPFSLPCON);
465
466 /* Port G sleep */
467
468 __raw_writel(S3C2412_SLPCON_IN(0) |
469 S3C2412_SLPCON_IN(1) |
470 S3C2412_SLPCON_IN(2) |
471 S3C2412_SLPCON_IN(3) |
472 S3C2412_SLPCON_IN(4) |
473 S3C2412_SLPCON_IN(5) |
474 S3C2412_SLPCON_IN(6) |
475 S3C2412_SLPCON_IN(7) |
476 S3C2412_SLPCON_PULL(8) |
477 S3C2412_SLPCON_PULL(9) |
478 S3C2412_SLPCON_IN(10) |
479 S3C2412_SLPCON_PULL(11) |
480 S3C2412_SLPCON_PULL(12) |
481 S3C2412_SLPCON_PULL(13) |
482 S3C2412_SLPCON_IN(14) |
483 S3C2412_SLPCON_PULL(15), S3C2412_GPGSLPCON);
484
485 /* Port H sleep */
486
487 __raw_writel(S3C2412_SLPCON_PULL(0) |
488 S3C2412_SLPCON_PULL(1) |
489 S3C2412_SLPCON_PULL(2) |
490 S3C2412_SLPCON_PULL(3) |
491 S3C2412_SLPCON_PULL(4) |
492 S3C2412_SLPCON_PULL(5) |
493 S3C2412_SLPCON_PULL(6) |
494 S3C2412_SLPCON_IN(7) |
495 S3C2412_SLPCON_IN(8) |
496 S3C2412_SLPCON_PULL(9) |
497 S3C2412_SLPCON_IN(10), S3C2412_GPHSLPCON);
498
499 /* initialise the power management now we've setup everything. */
500
9db829f4
BD
501 s3c2410_pm_init();
502
503 s3c_device_nand.dev.platform_data = &jive_nand_info;
504
505 /* Turn off suspend on both USB ports, and switch the
506 * selectable USB port to USB device mode. */
507
508 s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
509 S3C2410_MISCCR_USBSUSPND0 |
510 S3C2410_MISCCR_USBSUSPND1, 0x0);
511
512 s3c24xx_udc_set_platdata(&jive_udc_cfg);
0f99263c 513 s3c24xx_fb_set_platdata(&jive_lcd_config);
9db829f4
BD
514
515 platform_add_devices(jive_devices, ARRAY_SIZE(jive_devices));
516}
517
518MACHINE_START(JIVE, "JIVE")
519 /* Maintainer: Ben Dooks <ben@fluff.org> */
520 .phys_io = S3C2410_PA_UART,
521 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
522 .boot_params = S3C2410_SDRAM_PA + 0x100,
523
524 .init_irq = s3c24xx_init_irq,
525 .map_io = jive_map_io,
526 .init_machine = jive_machine_init,
527 .timer = &s3c24xx_timer,
528MACHINE_END