]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-s3c2412/mach-jive.c
[ARM] JIVE: Add setup information for the S3C2412 LCD controller
[linux-2.6-omap-h63xx.git] / arch / arm / mach-s3c2412 / mach-jive.c
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>
37 #include <asm/arch/fb.h>
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
52 static 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
59 static 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  */
94 static 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
152 static 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
211 static 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
220 static 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
229 static 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
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
276 struct 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
309 struct 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
349 static struct platform_device *jive_devices[] __initdata = {
350         &s3c_device_usb,
351         &s3c_device_rtc,
352         &s3c_device_wdt,
353         &s3c_device_i2c,
354         &s3c_device_lcd,
355         &s3c_device_nand,
356         &s3c_device_usbgadget,
357 };
358
359 static 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
366 static 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
378 static 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
389 static struct sysdev_class jive_pm_sysclass = {
390         .name           = "jive-pm",
391         .suspend        = jive_pm_suspend,
392         .resume         = jive_pm_resume,
393 };
394
395 static struct sys_device jive_pm_sysdev = {
396         .cls            = &jive_pm_sysclass,
397 };
398
399 static 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
406 static 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
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
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);
513         s3c24xx_fb_set_platdata(&jive_lcd_config);
514
515         platform_add_devices(jive_devices, ARRAY_SIZE(jive_devices));
516 }
517
518 MACHINE_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,
528 MACHINE_END