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/wm8915.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,
335 &s3c_device_timer[0],
336 &s3c64xx_device_iis0,
337 &s3c64xx_device_iis1,
339 &samsung_device_keypad,
340 &crag6410_gpio_keydev,
341 &crag6410_dm9k_device,
342 &s3c64xx_device_spi0,
344 &crag6410_lcd_powerdev,
345 &crag6410_backlight_device,
347 &speyside_wm8962_device,
351 static struct pca953x_platform_data crag6410_pca_data = {
352 .gpio_base = PCA935X_GPIO_BASE,
356 static struct regulator_consumer_supply vddarm_consumers[] __initdata = {
357 REGULATOR_SUPPLY("vddarm", NULL),
360 static struct regulator_init_data vddarm __initdata = {
366 .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
368 .num_consumer_supplies = ARRAY_SIZE(vddarm_consumers),
369 .consumer_supplies = vddarm_consumers,
370 .supply_regulator = "WALLVDD",
373 static struct regulator_init_data vddint __initdata = {
379 .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
383 static struct regulator_init_data vddmem __initdata = {
390 static struct regulator_init_data vddsys __initdata = {
392 .name = "VDDSYS,VDDEXT,VDDPCM,VDDSS",
397 static struct regulator_consumer_supply vddmmc_consumers[] __initdata = {
398 REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
399 REGULATOR_SUPPLY("vmmc", "s3c-sdhci.1"),
400 REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"),
403 static struct regulator_init_data vddmmc __initdata = {
408 .num_consumer_supplies = ARRAY_SIZE(vddmmc_consumers),
409 .consumer_supplies = vddmmc_consumers,
410 .supply_regulator = "WALLVDD",
413 static struct regulator_init_data vddotgi __initdata = {
418 .supply_regulator = "WALLVDD",
421 static struct regulator_init_data vddotg __initdata = {
426 .supply_regulator = "WALLVDD",
429 static struct regulator_init_data vddhi __initdata = {
434 .supply_regulator = "WALLVDD",
437 static struct regulator_init_data vddadc __initdata = {
439 .name = "VDDADC,VDDDAC",
442 .supply_regulator = "WALLVDD",
445 static struct regulator_init_data vddmem0 __initdata = {
450 .supply_regulator = "WALLVDD",
453 static struct regulator_init_data vddpll __initdata = {
458 .supply_regulator = "WALLVDD",
461 static struct regulator_init_data vddlcd __initdata = {
466 .supply_regulator = "WALLVDD",
469 static struct regulator_init_data vddalive __initdata = {
474 .supply_regulator = "WALLVDD",
477 static struct wm831x_status_pdata banff_red_led __initdata = {
478 .name = "banff:red:",
479 .default_src = WM831X_STATUS_MANUAL,
482 static struct wm831x_status_pdata banff_green_led __initdata = {
483 .name = "banff:green:",
484 .default_src = WM831X_STATUS_MANUAL,
487 static struct wm831x_touch_pdata touch_pdata __initdata = {
488 .data_irq = S3C_EINT(26),
489 .pd_irq = S3C_EINT(27),
492 static struct wm831x_pdata crag_pmic_pdata __initdata = {
494 .irq_base = BANFF_PMIC_IRQ_BASE,
495 .gpio_base = GPIO_BOARD_START + 8,
498 /* GPIO11: Touchscreen data - CMOS, DBVDD, active high*/
499 [10] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x6,
500 /* GPIO12: Touchscreen pen down - CMOS, DBVDD, active high*/
501 [11] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x7,
521 &vddalive, /* LDO11 */
529 .touch = &touch_pdata,
532 static struct i2c_board_info i2c_devs0[] __initdata = {
533 { I2C_BOARD_INFO("24c08", 0x50), },
534 { I2C_BOARD_INFO("tca6408", 0x20),
535 .platform_data = &crag6410_pca_data,
537 { I2C_BOARD_INFO("wm8312", 0x34),
538 .platform_data = &crag_pmic_pdata,
543 static struct s3c2410_platform_i2c i2c0_pdata = {
547 static struct regulator_init_data pvdd_1v2 __initdata = {
554 static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = {
555 REGULATOR_SUPPLY("PLLVDD", "1-001a"),
556 REGULATOR_SUPPLY("DBVDD", "1-001a"),
557 REGULATOR_SUPPLY("CPVDD", "1-001a"),
558 REGULATOR_SUPPLY("AVDD2", "1-001a"),
559 REGULATOR_SUPPLY("DCVDD", "1-001a"),
560 REGULATOR_SUPPLY("AVDD", "1-001a"),
563 static struct regulator_init_data pvdd_1v8 __initdata = {
569 .consumer_supplies = pvdd_1v8_consumers,
570 .num_consumer_supplies = ARRAY_SIZE(pvdd_1v8_consumers),
573 static struct regulator_consumer_supply pvdd_3v3_consumers[] __initdata = {
574 REGULATOR_SUPPLY("MICVDD", "1-001a"),
575 REGULATOR_SUPPLY("AVDD1", "1-001a"),
578 static struct regulator_init_data pvdd_3v3 __initdata = {
584 .consumer_supplies = pvdd_3v3_consumers,
585 .num_consumer_supplies = ARRAY_SIZE(pvdd_3v3_consumers),
588 static struct wm831x_pdata glenfarclas_pmic_pdata __initdata = {
590 .irq_base = GLENFARCLAS_PMIC_IRQ_BASE,
591 .gpio_base = GLENFARCLAS_PMIC_GPIO_BASE,
594 /* GPIO1-3: IRQ inputs, rising edge triggered, CMOS */
595 [0] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
596 [1] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
597 [2] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
601 &pvdd_1v2, /* DCDC1 */
602 &pvdd_1v8, /* DCDC2 */
603 &pvdd_3v3, /* DCDC3 */
606 .disable_touch = true,
609 static struct wm8915_retune_mobile_config wm8915_retune[] = {
614 0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
615 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
616 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
623 0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
624 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
625 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
630 static struct wm8915_pdata wm8915_pdata __initdata = {
631 .ldo_ena = S3C64XX_GPN(7),
632 .gpio_base = CODEC_GPIO_BASE,
634 .inl_mode = WM8915_DIFFERRENTIAL_1,
635 .inr_mode = WM8915_DIFFERRENTIAL_1,
637 .irq_flags = IRQF_TRIGGER_RISING,
640 0x8001, /* GPIO1 == ADCLRCLK1 */
641 0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
642 0x0141, /* GPIO3 == HP_SEL */
643 0x0002, /* GPIO4 == IRQ */
644 0x020e, /* GPIO5 == CLKOUT */
647 .retune_mobile_cfgs = wm8915_retune,
648 .num_retune_mobile_cfgs = ARRAY_SIZE(wm8915_retune),
651 static struct wm8962_pdata wm8962_pdata __initdata = {
654 WM8962_GPIO_FN_OPCLK,
655 WM8962_GPIO_FN_DMICCLK,
657 0x8000 | WM8962_GPIO_FN_DMICDAT,
658 WM8962_GPIO_FN_IRQ, /* Open drain mode */
660 .irq_active_low = true,
663 static struct wm9081_pdata wm9081_pdata __initdata = {
668 static struct i2c_board_info i2c_devs1[] __initdata = {
669 { I2C_BOARD_INFO("wm8311", 0x34),
671 .platform_data = &glenfarclas_pmic_pdata },
673 { I2C_BOARD_INFO("wm1250-ev1", 0x27) },
674 { I2C_BOARD_INFO("wm8915", 0x1a),
675 .platform_data = &wm8915_pdata,
676 .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
678 { I2C_BOARD_INFO("wm9081", 0x6c),
679 .platform_data = &wm9081_pdata, },
680 { I2C_BOARD_INFO("wm8962", 0x1a),
681 .platform_data = &wm8962_pdata,
682 .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
686 static void __init crag6410_map_io(void)
688 s3c64xx_init_io(NULL, 0);
689 s3c24xx_init_clocks(12000000);
690 s3c24xx_init_uarts(crag6410_uartcfgs, ARRAY_SIZE(crag6410_uartcfgs));
692 /* LCD type and Bypass set by bootloader */
695 static struct s3c_sdhci_platdata crag6410_hsmmc2_pdata = {
697 .cd_type = S3C_SDHCI_CD_PERMANENT,
700 static struct s3c_sdhci_platdata crag6410_hsmmc1_pdata = {
702 .cd_type = S3C_SDHCI_CD_GPIO,
703 .ext_cd_gpio = S3C64XX_GPF(11),
706 static void crag6410_cfg_sdhci0(struct platform_device *dev, int width)
708 /* Set all the necessary GPG pins to special-function 2 */
709 s3c_gpio_cfgrange_nopull(S3C64XX_GPG(0), 2 + width, S3C_GPIO_SFN(2));
711 /* force card-detected for prototype 0 */
712 s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_DOWN);
715 static struct s3c_sdhci_platdata crag6410_hsmmc0_pdata = {
717 .cd_type = S3C_SDHCI_CD_INTERNAL,
718 .cfg_gpio = crag6410_cfg_sdhci0,
721 static void __init crag6410_machine_init(void)
723 /* Open drain IRQs need pullups */
724 s3c_gpio_setpull(S3C64XX_GPM(0), S3C_GPIO_PULL_UP);
725 s3c_gpio_setpull(S3C64XX_GPN(0), S3C_GPIO_PULL_UP);
727 gpio_request(S3C64XX_GPB(0), "LCD power");
728 gpio_direction_output(S3C64XX_GPB(0), 0);
730 gpio_request(S3C64XX_GPF(14), "LCD PWM");
731 gpio_direction_output(S3C64XX_GPF(14), 0); /* turn off */
733 gpio_request(S3C64XX_GPB(1), "SD power");
734 gpio_direction_output(S3C64XX_GPB(1), 0);
736 gpio_request(S3C64XX_GPF(10), "nRESETSEL");
737 gpio_direction_output(S3C64XX_GPF(10), 1);
739 s3c_sdhci0_set_platdata(&crag6410_hsmmc0_pdata);
740 s3c_sdhci1_set_platdata(&crag6410_hsmmc1_pdata);
741 s3c_sdhci2_set_platdata(&crag6410_hsmmc2_pdata);
743 s3c_i2c0_set_platdata(&i2c0_pdata);
744 s3c_i2c1_set_platdata(NULL);
745 s3c_fb_set_platdata(&crag6410_lcd_pdata);
747 i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
748 i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
750 samsung_keypad_set_platdata(&crag6410_keypad_data);
752 platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));
754 regulator_has_full_constraints();
759 MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410")
760 /* Maintainer: Mark Brown <broonie@opensource.wolfsonmicro.com> */
761 .boot_params = S3C64XX_PA_SDRAM + 0x100,
762 .init_irq = s3c6410_init_irq,
763 .map_io = crag6410_map_io,
764 .init_machine = crag6410_machine_init,
765 .timer = &s3c24xx_timer,