1 /* linux/arch/arm/mach-s3c64xx/mach-crag6410.c
3 * Copyright 2011 Wolfson Microelectronics plc
4 * Mark Brown <broonie@opensource.wolfsonmicro.com>
6 * Copyright 2011 Simtec Electronics
7 * Ben Dooks <ben@simtec.co.uk>
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.
14 #include <linux/kernel.h>
15 #include <linux/list.h>
16 #include <linux/serial_core.h>
17 #include <linux/platform_device.h>
20 #include <linux/init.h>
21 #include <linux/gpio.h>
22 #include <linux/delay.h>
23 #include <linux/regulator/machine.h>
24 #include <linux/regulator/fixed.h>
25 #include <linux/pwm_backlight.h>
26 #include <linux/dm9000.h>
27 #include <linux/gpio_keys.h>
28 #include <linux/basic_mmio_gpio.h>
29 #include <linux/spi/spi.h>
31 #include <linux/i2c/pca953x.h>
33 #include <video/platform_lcd.h>
35 #include <linux/mfd/wm831x/core.h>
36 #include <linux/mfd/wm831x/pdata.h>
37 #include <linux/mfd/wm831x/irq.h>
38 #include <linux/mfd/wm831x/gpio.h>
40 #include <asm/mach/arch.h>
41 #include <asm/mach-types.h>
43 #include <mach/hardware.h>
46 #include <mach/s3c6410.h>
47 #include <mach/regs-sys.h>
48 #include <mach/regs-gpio.h>
49 #include <mach/regs-modem.h>
51 #include <mach/regs-gpio-memport.h>
53 #include <plat/regs-serial.h>
54 #include <plat/regs-fb-v4.h>
56 #include <plat/sdhci.h>
57 #include <plat/gpio-cfg.h>
58 #include <plat/s3c64xx-spi.h>
60 #include <plat/keypad.h>
61 #include <plat/clock.h>
62 #include <plat/devs.h>
68 #include <sound/wm8996.h>
69 #include <sound/wm8962.h>
70 #include <sound/wm9081.h>
72 #define BANFF_PMIC_IRQ_BASE IRQ_BOARD_START
73 #define GLENFARCLAS_PMIC_IRQ_BASE (IRQ_BOARD_START + 64)
75 #define PCA935X_GPIO_BASE GPIO_BOARD_START
76 #define CODEC_GPIO_BASE (GPIO_BOARD_START + 8)
77 #define GLENFARCLAS_PMIC_GPIO_BASE (GPIO_BOARD_START + 16)
79 /* serial port setup */
81 #define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
82 #define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
83 #define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
85 static struct s3c2410_uartcfg crag6410_uartcfgs[] __initdata = {
116 static struct platform_pwm_backlight_data crag6410_backlight_data = {
118 .max_brightness = 1000,
119 .dft_brightness = 600,
120 .pwm_period_ns = 100000, /* about 1kHz */
123 static struct platform_device crag6410_backlight_device = {
124 .name = "pwm-backlight",
127 .parent = &s3c_device_timer[0].dev,
128 .platform_data = &crag6410_backlight_data,
132 static void crag6410_lcd_power_set(struct plat_lcd_data *pd, unsigned int power)
134 pr_debug("%s: setting power %d\n", __func__, power);
137 gpio_set_value(S3C64XX_GPB(0), 1);
139 s3c_gpio_cfgpin(S3C64XX_GPF(14), S3C_GPIO_SFN(2));
141 gpio_direction_output(S3C64XX_GPF(14), 0);
142 gpio_set_value(S3C64XX_GPB(0), 0);
146 static struct platform_device crag6410_lcd_powerdev = {
147 .name = "platform-lcd",
149 .dev.parent = &s3c_device_fb.dev,
150 .dev.platform_data = &(struct plat_lcd_data) {
151 .set_power = crag6410_lcd_power_set,
156 static struct s3c_fb_pd_win crag6410_fb_win0 = {
157 /* this is to ensure we use win0 */
170 .virtual_y = 480 * 2,
174 /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
175 static struct s3c_fb_platdata crag6410_lcd_pdata __initdata = {
176 .setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
177 .win[0] = &crag6410_fb_win0,
178 .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
179 .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
184 static uint32_t crag6410_keymap[] __initdata = {
185 /* KEY(row, col, keycode) */
186 KEY(0, 0, KEY_VOLUMEUP),
188 KEY(0, 2, KEY_VOLUMEDOWN),
191 KEY(0, 5, KEY_MEDIA),
196 KEY(1, 4, KEY_RIGHT),
197 KEY(1, 5, KEY_CAMERA),
200 static struct matrix_keymap_data crag6410_keymap_data __initdata = {
201 .keymap = crag6410_keymap,
202 .keymap_size = ARRAY_SIZE(crag6410_keymap),
205 static struct samsung_keypad_platdata crag6410_keypad_data __initdata = {
206 .keymap_data = &crag6410_keymap_data,
211 static struct gpio_keys_button crag6410_gpio_keys[] = {
214 .gpio = S3C64XX_GPL(10), /* EINT 18 */
220 .code = SW_FRONT_PROXIMITY,
221 .gpio = S3C64XX_GPN(11), /* EINT 11 */
226 static struct gpio_keys_platform_data crag6410_gpio_keydata = {
227 .buttons = crag6410_gpio_keys,
228 .nbuttons = ARRAY_SIZE(crag6410_gpio_keys),
231 static struct platform_device crag6410_gpio_keydev = {
234 .dev.platform_data = &crag6410_gpio_keydata,
237 static struct resource crag6410_dm9k_resource[] = {
239 .start = S3C64XX_PA_XM0CSN5,
240 .end = S3C64XX_PA_XM0CSN5 + 1,
241 .flags = IORESOURCE_MEM,
244 .start = S3C64XX_PA_XM0CSN5 + (1 << 8),
245 .end = S3C64XX_PA_XM0CSN5 + (1 << 8) + 1,
246 .flags = IORESOURCE_MEM,
249 .start = S3C_EINT(17),
251 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
255 static struct dm9000_plat_data mini6410_dm9k_pdata = {
256 .flags = DM9000_PLATF_16BITONLY,
259 static struct platform_device crag6410_dm9k_device = {
262 .num_resources = ARRAY_SIZE(crag6410_dm9k_resource),
263 .resource = crag6410_dm9k_resource,
264 .dev.platform_data = &mini6410_dm9k_pdata,
267 static struct resource crag6410_mmgpio_resource[] = {
269 .start = S3C64XX_PA_XM0CSN4 + 1,
270 .end = S3C64XX_PA_XM0CSN4 + 1,
271 .flags = IORESOURCE_MEM,
275 static struct platform_device crag6410_mmgpio = {
276 .name = "basic-mmio-gpio",
278 .resource = crag6410_mmgpio_resource,
279 .num_resources = ARRAY_SIZE(crag6410_mmgpio_resource),
280 .dev.platform_data = &(struct bgpio_pdata) {
285 static struct platform_device speyside_device = {
290 static struct platform_device speyside_wm8962_device = {
291 .name = "speyside-wm8962",
295 static struct regulator_consumer_supply wallvdd_consumers[] = {
296 REGULATOR_SUPPLY("SPKVDD1", "1-001a"),
297 REGULATOR_SUPPLY("SPKVDD2", "1-001a"),
300 static struct regulator_init_data wallvdd_data = {
304 .num_consumer_supplies = ARRAY_SIZE(wallvdd_consumers),
305 .consumer_supplies = wallvdd_consumers,
308 static struct fixed_voltage_config wallvdd_pdata = {
309 .supply_name = "WALLVDD",
310 .microvolts = 5000000,
311 .init_data = &wallvdd_data,
315 static struct platform_device wallvdd_device = {
316 .name = "reg-fixed-voltage",
319 .platform_data = &wallvdd_pdata,
323 static struct platform_device *crag6410_devices[] __initdata = {
331 &s3c_device_usb_hsotg,
332 &s3c_device_timer[0],
333 &s3c64xx_device_iis0,
334 &s3c64xx_device_iis1,
336 &samsung_device_keypad,
337 &crag6410_gpio_keydev,
338 &crag6410_dm9k_device,
339 &s3c64xx_device_spi0,
341 &crag6410_lcd_powerdev,
342 &crag6410_backlight_device,
344 &speyside_wm8962_device,
348 static struct pca953x_platform_data crag6410_pca_data = {
349 .gpio_base = PCA935X_GPIO_BASE,
353 static struct regulator_consumer_supply vddarm_consumers[] __initdata = {
354 REGULATOR_SUPPLY("vddarm", NULL),
357 static struct regulator_init_data vddarm __initdata = {
363 .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
365 .num_consumer_supplies = ARRAY_SIZE(vddarm_consumers),
366 .consumer_supplies = vddarm_consumers,
367 .supply_regulator = "WALLVDD",
370 static struct regulator_init_data vddint __initdata = {
376 .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
380 static struct regulator_init_data vddmem __initdata = {
387 static struct regulator_init_data vddsys __initdata = {
389 .name = "VDDSYS,VDDEXT,VDDPCM,VDDSS",
394 static struct regulator_consumer_supply vddmmc_consumers[] __initdata = {
395 REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
396 REGULATOR_SUPPLY("vmmc", "s3c-sdhci.1"),
397 REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"),
400 static struct regulator_init_data vddmmc __initdata = {
405 .num_consumer_supplies = ARRAY_SIZE(vddmmc_consumers),
406 .consumer_supplies = vddmmc_consumers,
407 .supply_regulator = "WALLVDD",
410 static struct regulator_init_data vddotgi __initdata = {
415 .supply_regulator = "WALLVDD",
418 static struct regulator_init_data vddotg __initdata = {
423 .supply_regulator = "WALLVDD",
426 static struct regulator_init_data vddhi __initdata = {
431 .supply_regulator = "WALLVDD",
434 static struct regulator_init_data vddadc __initdata = {
436 .name = "VDDADC,VDDDAC",
439 .supply_regulator = "WALLVDD",
442 static struct regulator_init_data vddmem0 __initdata = {
447 .supply_regulator = "WALLVDD",
450 static struct regulator_init_data vddpll __initdata = {
455 .supply_regulator = "WALLVDD",
458 static struct regulator_init_data vddlcd __initdata = {
463 .supply_regulator = "WALLVDD",
466 static struct regulator_init_data vddalive __initdata = {
471 .supply_regulator = "WALLVDD",
474 static struct wm831x_backup_pdata banff_backup_pdata __initdata = {
476 .vlim = 2500, /* mV */
477 .ilim = 200, /* uA */
480 static struct wm831x_status_pdata banff_red_led __initdata = {
481 .name = "banff:red:",
482 .default_src = WM831X_STATUS_MANUAL,
485 static struct wm831x_status_pdata banff_green_led __initdata = {
486 .name = "banff:green:",
487 .default_src = WM831X_STATUS_MANUAL,
490 static struct wm831x_touch_pdata touch_pdata __initdata = {
491 .data_irq = S3C_EINT(26),
492 .pd_irq = S3C_EINT(27),
495 static struct wm831x_pdata crag_pmic_pdata __initdata = {
497 .irq_base = BANFF_PMIC_IRQ_BASE,
498 .gpio_base = GPIO_BOARD_START + 8,
500 .backup = &banff_backup_pdata,
503 /* GPIO11: Touchscreen data - CMOS, DBVDD, active high*/
504 [10] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x6,
505 /* GPIO12: Touchscreen pen down - CMOS, DBVDD, active high*/
506 [11] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x7,
526 &vddalive, /* LDO11 */
534 .touch = &touch_pdata,
537 static struct i2c_board_info i2c_devs0[] __initdata = {
538 { I2C_BOARD_INFO("24c08", 0x50), },
539 { I2C_BOARD_INFO("tca6408", 0x20),
540 .platform_data = &crag6410_pca_data,
542 { I2C_BOARD_INFO("wm8312", 0x34),
543 .platform_data = &crag_pmic_pdata,
548 static struct s3c2410_platform_i2c i2c0_pdata = {
552 static struct regulator_init_data pvdd_1v2 __initdata = {
559 static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = {
560 REGULATOR_SUPPLY("PLLVDD", "1-001a"),
561 REGULATOR_SUPPLY("DBVDD", "1-001a"),
562 REGULATOR_SUPPLY("CPVDD", "1-001a"),
563 REGULATOR_SUPPLY("AVDD2", "1-001a"),
564 REGULATOR_SUPPLY("DCVDD", "1-001a"),
565 REGULATOR_SUPPLY("AVDD", "1-001a"),
568 static struct regulator_init_data pvdd_1v8 __initdata = {
574 .consumer_supplies = pvdd_1v8_consumers,
575 .num_consumer_supplies = ARRAY_SIZE(pvdd_1v8_consumers),
578 static struct regulator_consumer_supply pvdd_3v3_consumers[] __initdata = {
579 REGULATOR_SUPPLY("MICVDD", "1-001a"),
580 REGULATOR_SUPPLY("AVDD1", "1-001a"),
583 static struct regulator_init_data pvdd_3v3 __initdata = {
589 .consumer_supplies = pvdd_3v3_consumers,
590 .num_consumer_supplies = ARRAY_SIZE(pvdd_3v3_consumers),
593 static struct wm831x_pdata glenfarclas_pmic_pdata __initdata = {
595 .irq_base = GLENFARCLAS_PMIC_IRQ_BASE,
596 .gpio_base = GLENFARCLAS_PMIC_GPIO_BASE,
599 /* GPIO1-3: IRQ inputs, rising edge triggered, CMOS */
600 [0] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
601 [1] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
602 [2] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
606 &pvdd_1v2, /* DCDC1 */
607 &pvdd_1v8, /* DCDC2 */
608 &pvdd_3v3, /* DCDC3 */
611 .disable_touch = true,
614 static struct wm8996_retune_mobile_config wm8996_retune[] = {
619 0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
620 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
621 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
628 0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
629 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
630 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
635 static struct wm8996_pdata wm8996_pdata __initdata = {
636 .ldo_ena = S3C64XX_GPN(7),
637 .gpio_base = CODEC_GPIO_BASE,
639 .inl_mode = WM8996_DIFFERRENTIAL_1,
640 .inr_mode = WM8996_DIFFERRENTIAL_1,
642 .irq_flags = IRQF_TRIGGER_RISING,
645 0x8001, /* GPIO1 == ADCLRCLK1 */
646 0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
647 0x0141, /* GPIO3 == HP_SEL */
648 0x0002, /* GPIO4 == IRQ */
649 0x020e, /* GPIO5 == CLKOUT */
652 .retune_mobile_cfgs = wm8996_retune,
653 .num_retune_mobile_cfgs = ARRAY_SIZE(wm8996_retune),
656 static struct wm8962_pdata wm8962_pdata __initdata = {
659 WM8962_GPIO_FN_OPCLK,
660 WM8962_GPIO_FN_DMICCLK,
662 0x8000 | WM8962_GPIO_FN_DMICDAT,
663 WM8962_GPIO_FN_IRQ, /* Open drain mode */
665 .irq_active_low = true,
668 static struct wm9081_pdata wm9081_pdata __initdata = {
673 static struct i2c_board_info i2c_devs1[] __initdata = {
674 { I2C_BOARD_INFO("wm8311", 0x34),
676 .platform_data = &glenfarclas_pmic_pdata },
678 { I2C_BOARD_INFO("wm1250-ev1", 0x27) },
679 { I2C_BOARD_INFO("wm8996", 0x1a),
680 .platform_data = &wm8996_pdata,
681 .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
683 { I2C_BOARD_INFO("wm9081", 0x6c),
684 .platform_data = &wm9081_pdata, },
685 { I2C_BOARD_INFO("wm8962", 0x1a),
686 .platform_data = &wm8962_pdata,
687 .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
691 static void __init crag6410_map_io(void)
693 s3c64xx_init_io(NULL, 0);
694 s3c24xx_init_clocks(12000000);
695 s3c24xx_init_uarts(crag6410_uartcfgs, ARRAY_SIZE(crag6410_uartcfgs));
697 /* LCD type and Bypass set by bootloader */
700 static struct s3c_sdhci_platdata crag6410_hsmmc2_pdata = {
702 .cd_type = S3C_SDHCI_CD_PERMANENT,
705 static struct s3c_sdhci_platdata crag6410_hsmmc1_pdata = {
707 .cd_type = S3C_SDHCI_CD_GPIO,
708 .ext_cd_gpio = S3C64XX_GPF(11),
711 static void crag6410_cfg_sdhci0(struct platform_device *dev, int width)
713 /* Set all the necessary GPG pins to special-function 2 */
714 s3c_gpio_cfgrange_nopull(S3C64XX_GPG(0), 2 + width, S3C_GPIO_SFN(2));
716 /* force card-detected for prototype 0 */
717 s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_DOWN);
720 static struct s3c_sdhci_platdata crag6410_hsmmc0_pdata = {
722 .cd_type = S3C_SDHCI_CD_INTERNAL,
723 .cfg_gpio = crag6410_cfg_sdhci0,
726 static void __init crag6410_machine_init(void)
728 /* Open drain IRQs need pullups */
729 s3c_gpio_setpull(S3C64XX_GPM(0), S3C_GPIO_PULL_UP);
730 s3c_gpio_setpull(S3C64XX_GPN(0), S3C_GPIO_PULL_UP);
732 gpio_request(S3C64XX_GPB(0), "LCD power");
733 gpio_direction_output(S3C64XX_GPB(0), 0);
735 gpio_request(S3C64XX_GPF(14), "LCD PWM");
736 gpio_direction_output(S3C64XX_GPF(14), 0); /* turn off */
738 gpio_request(S3C64XX_GPB(1), "SD power");
739 gpio_direction_output(S3C64XX_GPB(1), 0);
741 gpio_request(S3C64XX_GPF(10), "nRESETSEL");
742 gpio_direction_output(S3C64XX_GPF(10), 1);
744 s3c_sdhci0_set_platdata(&crag6410_hsmmc0_pdata);
745 s3c_sdhci1_set_platdata(&crag6410_hsmmc1_pdata);
746 s3c_sdhci2_set_platdata(&crag6410_hsmmc2_pdata);
748 s3c_i2c0_set_platdata(&i2c0_pdata);
749 s3c_i2c1_set_platdata(NULL);
750 s3c_fb_set_platdata(&crag6410_lcd_pdata);
752 i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
753 i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
755 samsung_keypad_set_platdata(&crag6410_keypad_data);
757 platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));
759 regulator_has_full_constraints();
764 MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410")
765 /* Maintainer: Mark Brown <broonie@opensource.wolfsonmicro.com> */
766 .atag_offset = 0x100,
767 .init_irq = s3c6410_init_irq,
768 .map_io = crag6410_map_io,
769 .init_machine = crag6410_machine_init,
770 .timer = &s3c24xx_timer,