Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mach-jive.c
Go to the documentation of this file.
1 /* linux/arch/arm/mach-s3c2410/mach-jive.c
2  *
3  * Copyright 2007 Simtec Electronics
4  * Ben Dooks <[email protected]>
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/gpio.h>
20 #include <linux/syscore_ops.h>
21 #include <linux/serial_core.h>
22 #include <linux/platform_device.h>
23 #include <linux/i2c.h>
24 
25 #include <video/ili9320.h>
26 
27 #include <linux/spi/spi.h>
28 #include <linux/spi/spi_gpio.h>
29 
30 #include <asm/mach/arch.h>
31 #include <asm/mach/map.h>
32 #include <asm/mach/irq.h>
33 
34 #include <plat/regs-serial.h>
37 
38 #include <mach/regs-power.h>
39 #include <mach/regs-gpio.h>
40 #include <mach/regs-mem.h>
41 #include <mach/regs-lcd.h>
42 #include <mach/fb.h>
43 
44 #include <asm/mach-types.h>
45 
46 #include <linux/mtd/mtd.h>
47 #include <linux/mtd/nand.h>
48 #include <linux/mtd/nand_ecc.h>
49 #include <linux/mtd/partitions.h>
50 
51 #include <plat/s3c2412.h>
52 #include <plat/gpio-cfg.h>
53 #include <plat/clock.h>
54 #include <plat/devs.h>
55 #include <plat/cpu.h>
56 #include <plat/pm.h>
58 
59 static struct map_desc jive_iodesc[] __initdata = {
60 };
61 
62 #define UCON S3C2410_UCON_DEFAULT
63 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE
64 #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
65 
66 static struct s3c2410_uartcfg jive_uartcfgs[] = {
67  [0] = {
68  .hwport = 0,
69  .flags = 0,
70  .ucon = UCON,
71  .ulcon = ULCON,
72  .ufcon = UFCON,
73  },
74  [1] = {
75  .hwport = 1,
76  .flags = 0,
77  .ucon = UCON,
78  .ulcon = ULCON,
79  .ufcon = UFCON,
80  },
81  [2] = {
82  .hwport = 2,
83  .flags = 0,
84  .ucon = UCON,
85  .ulcon = ULCON,
86  .ufcon = UFCON,
87  }
88 };
89 
90 /* Jive flash assignment
91  *
92  * 0x00000000-0x00028000 : uboot
93  * 0x00028000-0x0002c000 : uboot env
94  * 0x0002c000-0x00030000 : spare
95  * 0x00030000-0x00200000 : zimage A
96  * 0x00200000-0x01600000 : cramfs A
97  * 0x01600000-0x017d0000 : zimage B
98  * 0x017d0000-0x02bd0000 : cramfs B
99  * 0x02bd0000-0x03fd0000 : yaffs
100  */
101 static struct mtd_partition __initdata jive_imageA_nand_part[] = {
102 
103 #ifdef CONFIG_MACH_JIVE_SHOW_BOOTLOADER
104  /* Don't allow access to the bootloader from linux */
105  {
106  .name = "uboot",
107  .offset = 0,
108  .size = (160 * SZ_1K),
109  .mask_flags = MTD_WRITEABLE, /* force read-only */
110  },
111 
112  /* spare */
113  {
114  .name = "spare",
115  .offset = (176 * SZ_1K),
116  .size = (16 * SZ_1K),
117  },
118 #endif
119 
120  /* booted images */
121  {
122  .name = "kernel (ro)",
123  .offset = (192 * SZ_1K),
124  .size = (SZ_2M) - (192 * SZ_1K),
125  .mask_flags = MTD_WRITEABLE, /* force read-only */
126  }, {
127  .name = "root (ro)",
128  .offset = (SZ_2M),
129  .size = (20 * SZ_1M),
130  .mask_flags = MTD_WRITEABLE, /* force read-only */
131  },
132 
133  /* yaffs */
134  {
135  .name = "yaffs",
136  .offset = (44 * SZ_1M),
137  .size = (20 * SZ_1M),
138  },
139 
140  /* bootloader environment */
141  {
142  .name = "env",
143  .offset = (160 * SZ_1K),
144  .size = (16 * SZ_1K),
145  },
146 
147  /* upgrade images */
148  {
149  .name = "zimage",
150  .offset = (22 * SZ_1M),
151  .size = (2 * SZ_1M) - (192 * SZ_1K),
152  }, {
153  .name = "cramfs",
154  .offset = (24 * SZ_1M) - (192*SZ_1K),
155  .size = (20 * SZ_1M),
156  },
157 };
158 
159 static struct mtd_partition __initdata jive_imageB_nand_part[] = {
160 
161 #ifdef CONFIG_MACH_JIVE_SHOW_BOOTLOADER
162  /* Don't allow access to the bootloader from linux */
163  {
164  .name = "uboot",
165  .offset = 0,
166  .size = (160 * SZ_1K),
167  .mask_flags = MTD_WRITEABLE, /* force read-only */
168  },
169 
170  /* spare */
171  {
172  .name = "spare",
173  .offset = (176 * SZ_1K),
174  .size = (16 * SZ_1K),
175  },
176 #endif
177 
178  /* booted images */
179  {
180  .name = "kernel (ro)",
181  .offset = (22 * SZ_1M),
182  .size = (2 * SZ_1M) - (192 * SZ_1K),
183  .mask_flags = MTD_WRITEABLE, /* force read-only */
184  },
185  {
186  .name = "root (ro)",
187  .offset = (24 * SZ_1M) - (192 * SZ_1K),
188  .size = (20 * SZ_1M),
189  .mask_flags = MTD_WRITEABLE, /* force read-only */
190  },
191 
192  /* yaffs */
193  {
194  .name = "yaffs",
195  .offset = (44 * SZ_1M),
196  .size = (20 * SZ_1M),
197  },
198 
199  /* bootloader environment */
200  {
201  .name = "env",
202  .offset = (160 * SZ_1K),
203  .size = (16 * SZ_1K),
204  },
205 
206  /* upgrade images */
207  {
208  .name = "zimage",
209  .offset = (192 * SZ_1K),
210  .size = (2 * SZ_1M) - (192 * SZ_1K),
211  }, {
212  .name = "cramfs",
213  .offset = (2 * SZ_1M),
214  .size = (20 * SZ_1M),
215  },
216 };
217 
218 static struct s3c2410_nand_set __initdata jive_nand_sets[] = {
219  [0] = {
220  .name = "flash",
221  .nr_chips = 1,
222  .nr_partitions = ARRAY_SIZE(jive_imageA_nand_part),
223  .partitions = jive_imageA_nand_part,
224  },
225 };
226 
227 static struct s3c2410_platform_nand __initdata jive_nand_info = {
228  /* set taken from osiris nand timings, possibly still conservative */
229  .tacls = 30,
230  .twrph0 = 55,
231  .twrph1 = 40,
232  .sets = jive_nand_sets,
233  .nr_sets = ARRAY_SIZE(jive_nand_sets),
234 };
235 
236 static int __init jive_mtdset(char *options)
237 {
238  struct s3c2410_nand_set *nand = &jive_nand_sets[0];
239  unsigned long set;
240 
241  if (options == NULL || options[0] == '\0')
242  return 0;
243 
244  if (strict_strtoul(options, 10, &set)) {
245  printk(KERN_ERR "failed to parse mtdset=%s\n", options);
246  return 0;
247  }
248 
249  switch (set) {
250  case 1:
251  nand->nr_partitions = ARRAY_SIZE(jive_imageB_nand_part);
252  nand->partitions = jive_imageB_nand_part;
253  case 0:
254  /* this is already setup in the nand info */
255  break;
256  default:
257  printk(KERN_ERR "Unknown mtd set %ld specified,"
258  "using default.", set);
259  }
260 
261  return 0;
262 }
263 
264 /* parse the mtdset= option given to the kernel command line */
265 __setup("mtdset=", jive_mtdset);
266 
267 /* LCD timing and setup */
268 
269 #define LCD_XRES (240)
270 #define LCD_YRES (320)
271 #define LCD_LEFT_MARGIN (12)
272 #define LCD_RIGHT_MARGIN (12)
273 #define LCD_LOWER_MARGIN (12)
274 #define LCD_UPPER_MARGIN (12)
275 #define LCD_VSYNC (2)
276 #define LCD_HSYNC (2)
277 
278 #define LCD_REFRESH (60)
279 
280 #define LCD_HTOT (LCD_HSYNC + LCD_LEFT_MARGIN + LCD_XRES + LCD_RIGHT_MARGIN)
281 #define LCD_VTOT (LCD_VSYNC + LCD_LOWER_MARGIN + LCD_YRES + LCD_UPPER_MARGIN)
282 
283 static struct s3c2410fb_display jive_vgg2432a4_display[] = {
284  [0] = {
285  .width = LCD_XRES,
286  .height = LCD_YRES,
287  .xres = LCD_XRES,
288  .yres = LCD_YRES,
289  .left_margin = LCD_LEFT_MARGIN,
290  .right_margin = LCD_RIGHT_MARGIN,
291  .upper_margin = LCD_UPPER_MARGIN,
292  .lower_margin = LCD_LOWER_MARGIN,
293  .hsync_len = LCD_HSYNC,
294  .vsync_len = LCD_VSYNC,
295 
296  .pixclock = (1000000000000LL /
298 
299  .bpp = 16,
300  .type = (S3C2410_LCDCON1_TFT16BPP |
302 
308  },
309 };
310 
311 /* todo - put into gpio header */
312 
313 #define S3C2410_GPCCON_MASK(x) (3 << ((x) * 2))
314 #define S3C2410_GPDCON_MASK(x) (3 << ((x) * 2))
315 
316 static struct s3c2410fb_mach_info jive_lcd_config = {
317  .displays = jive_vgg2432a4_display,
318  .num_displays = ARRAY_SIZE(jive_vgg2432a4_display),
319  .default_display = 0,
320 
321  /* Enable VD[2..7], VD[10..15], VD[18..23] and VCLK, syncs, VDEN
322  * and disable the pull down resistors on pins we are using for LCD
323  * data. */
324 
325  .gpcup = (0xf << 1) | (0x3f << 10),
326 
332 
338 
339  .gpdup = (0x3f << 2) | (0x3f << 10),
340 
347 
348  .gpdcon_mask = (S3C2410_GPDCON_MASK(2) | S3C2410_GPDCON_MASK(3) |
354 };
355 
356 /* ILI9320 support. */
357 
358 static void jive_lcm_reset(unsigned int set)
359 {
360  printk(KERN_DEBUG "%s(%d)\n", __func__, set);
361 
362  gpio_set_value(S3C2410_GPG(13), set);
363 }
364 
365 #undef LCD_UPPER_MARGIN
366 #define LCD_UPPER_MARGIN 2
367 
368 static struct ili9320_platdata jive_lcm_config = {
369  .hsize = LCD_XRES,
370  .vsize = LCD_YRES,
371 
372  .reset = jive_lcm_reset,
373  .suspend = ILI9320_SUSPEND_DEEP,
374 
375  .entry_mode = ILI9320_ENTRYMODE_ID(3) | ILI9320_ENTRYMODE_BGR,
376  .display2 = (ILI9320_DISPLAY2_FP(LCD_UPPER_MARGIN) |
378  .display3 = 0x0,
379  .display4 = 0x0,
382  .rgb_if2 = ILI9320_RGBIF2_DPL,
383  .interface2 = 0x0,
384  .interface3 = 0x3,
385  .interface4 = (ILI9320_INTERFACE4_RTNE(16) |
387  .interface5 = 0x0,
388  .interface6 = 0x0,
389 };
390 
391 /* LCD SPI support */
392 
393 static struct spi_gpio_platform_data jive_lcd_spi = {
394  .sck = S3C2410_GPG(8),
395  .mosi = S3C2410_GPB(8),
396  .miso = SPI_GPIO_NO_MISO,
397 };
398 
399 static struct platform_device jive_device_lcdspi = {
400  .name = "spi-gpio",
401  .id = 1,
402  .dev.platform_data = &jive_lcd_spi,
403 };
404 
405 
406 /* WM8750 audio code SPI definition */
407 
408 static struct spi_gpio_platform_data jive_wm8750_spi = {
409  .sck = S3C2410_GPB(4),
410  .mosi = S3C2410_GPB(9),
411  .miso = SPI_GPIO_NO_MISO,
412 };
413 
414 static struct platform_device jive_device_wm8750 = {
415  .name = "spi-gpio",
416  .id = 2,
417  .dev.platform_data = &jive_wm8750_spi,
418 };
419 
420 /* JIVE SPI devices. */
421 
422 static struct spi_board_info __initdata jive_spi_devs[] = {
423  [0] = {
424  .modalias = "VGG2432A4",
425  .bus_num = 1,
426  .chip_select = 0,
427  .mode = SPI_MODE_3, /* CPOL=1, CPHA=1 */
428  .max_speed_hz = 100000,
429  .platform_data = &jive_lcm_config,
430  .controller_data = (void *)S3C2410_GPB(7),
431  }, {
432  .modalias = "WM8750",
433  .bus_num = 2,
434  .chip_select = 0,
435  .mode = SPI_MODE_0, /* CPOL=0, CPHA=0 */
436  .max_speed_hz = 100000,
437  .controller_data = (void *)S3C2410_GPH(10),
438  },
439 };
440 
441 /* I2C bus and device configuration. */
442 
443 static struct s3c2410_platform_i2c jive_i2c_cfg __initdata = {
444  .frequency = 80 * 1000,
445  .flags = S3C_IICFLG_FILTER,
446  .sda_delay = 2,
447 };
448 
449 static struct i2c_board_info jive_i2c_devs[] __initdata = {
450  [0] = {
451  I2C_BOARD_INFO("lis302dl", 0x1c),
452  .irq = IRQ_EINT14,
453  },
454 };
455 
456 /* The platform devices being used. */
457 
458 static struct platform_device *jive_devices[] __initdata = {
464  &jive_device_lcdspi,
465  &jive_device_wm8750,
468 };
469 
470 static struct s3c2410_udc_mach_info jive_udc_cfg __initdata = {
471  .vbus_pin = S3C2410_GPG(1), /* detect is on GPG1 */
472 };
473 
474 /* Jive power management device */
475 
476 #ifdef CONFIG_PM
477 static int jive_pm_suspend(void)
478 {
479  /* Write the magic value u-boot uses to check for resume into
480  * the INFORM0 register, and ensure INFORM1 is set to the
481  * correct address to resume from. */
482 
483  __raw_writel(0x2BED, S3C2412_INFORM0);
485 
486  return 0;
487 }
488 
489 static void jive_pm_resume(void)
490 {
492 }
493 
494 #else
495 #define jive_pm_suspend NULL
496 #define jive_pm_resume NULL
497 #endif
498 
499 static struct syscore_ops jive_pm_syscore_ops = {
500  .suspend = jive_pm_suspend,
501  .resume = jive_pm_resume,
502 };
503 
504 static void __init jive_map_io(void)
505 {
506  s3c24xx_init_io(jive_iodesc, ARRAY_SIZE(jive_iodesc));
507  s3c24xx_init_clocks(12000000);
508  s3c24xx_init_uarts(jive_uartcfgs, ARRAY_SIZE(jive_uartcfgs));
509 }
510 
511 static void jive_power_off(void)
512 {
513  printk(KERN_INFO "powering system down...\n");
514 
517 }
518 
519 static void __init jive_machine_init(void)
520 {
521  /* register system core operations for managing low level suspend */
522 
523  register_syscore_ops(&jive_pm_syscore_ops);
524 
525  /* write our sleep configurations for the IO. Pull down all unused
526  * IO, ensure that we have turned off all peripherals we do not
527  * need, and configure the ones we do need. */
528 
529  /* Port B sleep */
530 
542 
543  /* Port C sleep */
544 
551  S3C2412_SLPCON_LOW(6) |
556  S3C2412_SLPCON_PULL(10) |
557  S3C2412_SLPCON_PULL(11) |
558  S3C2412_SLPCON_PULL(12) |
559  S3C2412_SLPCON_PULL(13) |
560  S3C2412_SLPCON_PULL(14) |
562 
563  /* Port D sleep */
564 
566 
567  /* Port F sleep */
568 
570  S3C2412_SLPCON_LOW(1) |
571  S3C2412_SLPCON_LOW(2) |
577 
578  /* Port G sleep */
579 
581  S3C2412_SLPCON_IN(1) |
582  S3C2412_SLPCON_IN(2) |
583  S3C2412_SLPCON_IN(3) |
584  S3C2412_SLPCON_IN(4) |
585  S3C2412_SLPCON_IN(5) |
586  S3C2412_SLPCON_IN(6) |
587  S3C2412_SLPCON_IN(7) |
590  S3C2412_SLPCON_IN(10) |
591  S3C2412_SLPCON_PULL(11) |
592  S3C2412_SLPCON_PULL(12) |
593  S3C2412_SLPCON_PULL(13) |
594  S3C2412_SLPCON_IN(14) |
596 
597  /* Port H sleep */
598 
606  S3C2412_SLPCON_IN(7) |
607  S3C2412_SLPCON_IN(8) |
610 
611  /* initialise the power management now we've setup everything. */
612 
613  s3c_pm_init();
614 
616  s3c_nand_set_platdata(&jive_nand_info);
617 
618  /* initialise the spi */
619 
620  gpio_request(S3C2410_GPG(13), "lcm reset");
622 
623  gpio_request(S3C2410_GPB(7), "jive spi");
625 
628 
631 
632  /* initialise the WM8750 spi */
633 
634  gpio_request(S3C2410_GPH(10), "jive wm8750 spi");
636 
637  /* Turn off suspend on both USB ports, and switch the
638  * selectable USB port to USB device mode. */
639 
643 
644  s3c24xx_udc_set_platdata(&jive_udc_cfg);
645  s3c24xx_fb_set_platdata(&jive_lcd_config);
646 
647  spi_register_board_info(jive_spi_devs, ARRAY_SIZE(jive_spi_devs));
648 
649  s3c_i2c0_set_platdata(&jive_i2c_cfg);
650  i2c_register_board_info(0, jive_i2c_devs, ARRAY_SIZE(jive_i2c_devs));
651 
652  pm_power_off = jive_power_off;
653 
654  platform_add_devices(jive_devices, ARRAY_SIZE(jive_devices));
655 }
656 
657 MACHINE_START(JIVE, "JIVE")
658  /* Maintainer: Ben Dooks <[email protected]> */
659  .atag_offset = 0x100,
660 
661  .init_irq = s3c24xx_init_irq,
662  .map_io = jive_map_io,
663  .init_machine = jive_machine_init,
664  .timer = &s3c24xx_timer,
665  .restart = s3c2412_restart,