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
,
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_backup_pdata banff_backup_pdata __initdata
= {
479 .vlim
= 2500, /* mV */
480 .ilim
= 200, /* uA */
483 static struct wm831x_status_pdata banff_red_led __initdata
= {
484 .name
= "banff:red:",
485 .default_src
= WM831X_STATUS_MANUAL
,
488 static struct wm831x_status_pdata banff_green_led __initdata
= {
489 .name
= "banff:green:",
490 .default_src
= WM831X_STATUS_MANUAL
,
493 static struct wm831x_touch_pdata touch_pdata __initdata
= {
494 .data_irq
= S3C_EINT(26),
495 .pd_irq
= S3C_EINT(27),
498 static struct wm831x_pdata crag_pmic_pdata __initdata
= {
500 .irq_base
= BANFF_PMIC_IRQ_BASE
,
501 .gpio_base
= GPIO_BOARD_START
+ 8,
503 .backup
= &banff_backup_pdata
,
506 /* GPIO11: Touchscreen data - CMOS, DBVDD, active high*/
507 [10] = WM831X_GPN_POL
| WM831X_GPN_ENA
| 0x6,
508 /* GPIO12: Touchscreen pen down - CMOS, DBVDD, active high*/
509 [11] = WM831X_GPN_POL
| WM831X_GPN_ENA
| 0x7,
529 &vddalive
, /* LDO11 */
537 .touch
= &touch_pdata
,
540 static struct i2c_board_info i2c_devs0
[] __initdata
= {
541 { I2C_BOARD_INFO("24c08", 0x50), },
542 { I2C_BOARD_INFO("tca6408", 0x20),
543 .platform_data
= &crag6410_pca_data
,
545 { I2C_BOARD_INFO("wm8312", 0x34),
546 .platform_data
= &crag_pmic_pdata
,
551 static struct s3c2410_platform_i2c i2c0_pdata
= {
555 static struct regulator_init_data pvdd_1v2 __initdata
= {
562 static struct regulator_consumer_supply pvdd_1v8_consumers
[] __initdata
= {
563 REGULATOR_SUPPLY("PLLVDD", "1-001a"),
564 REGULATOR_SUPPLY("DBVDD", "1-001a"),
565 REGULATOR_SUPPLY("CPVDD", "1-001a"),
566 REGULATOR_SUPPLY("AVDD2", "1-001a"),
567 REGULATOR_SUPPLY("DCVDD", "1-001a"),
568 REGULATOR_SUPPLY("AVDD", "1-001a"),
571 static struct regulator_init_data pvdd_1v8 __initdata
= {
577 .consumer_supplies
= pvdd_1v8_consumers
,
578 .num_consumer_supplies
= ARRAY_SIZE(pvdd_1v8_consumers
),
581 static struct regulator_consumer_supply pvdd_3v3_consumers
[] __initdata
= {
582 REGULATOR_SUPPLY("MICVDD", "1-001a"),
583 REGULATOR_SUPPLY("AVDD1", "1-001a"),
586 static struct regulator_init_data pvdd_3v3 __initdata
= {
592 .consumer_supplies
= pvdd_3v3_consumers
,
593 .num_consumer_supplies
= ARRAY_SIZE(pvdd_3v3_consumers
),
596 static struct wm831x_pdata glenfarclas_pmic_pdata __initdata
= {
598 .irq_base
= GLENFARCLAS_PMIC_IRQ_BASE
,
599 .gpio_base
= GLENFARCLAS_PMIC_GPIO_BASE
,
602 /* GPIO1-3: IRQ inputs, rising edge triggered, CMOS */
603 [0] = WM831X_GPN_DIR
| WM831X_GPN_POL
| WM831X_GPN_ENA
,
604 [1] = WM831X_GPN_DIR
| WM831X_GPN_POL
| WM831X_GPN_ENA
,
605 [2] = WM831X_GPN_DIR
| WM831X_GPN_POL
| WM831X_GPN_ENA
,
609 &pvdd_1v2
, /* DCDC1 */
610 &pvdd_1v8
, /* DCDC2 */
611 &pvdd_3v3
, /* DCDC3 */
614 .disable_touch
= true,
617 static struct wm8996_retune_mobile_config wm8996_retune
[] = {
622 0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
623 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
624 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
631 0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
632 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
633 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
638 static struct wm8996_pdata wm8996_pdata __initdata
= {
639 .ldo_ena
= S3C64XX_GPN(7),
640 .gpio_base
= CODEC_GPIO_BASE
,
642 .inl_mode
= WM8996_DIFFERRENTIAL_1
,
643 .inr_mode
= WM8996_DIFFERRENTIAL_1
,
645 .irq_flags
= IRQF_TRIGGER_RISING
,
648 0x8001, /* GPIO1 == ADCLRCLK1 */
649 0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
650 0x0141, /* GPIO3 == HP_SEL */
651 0x0002, /* GPIO4 == IRQ */
652 0x020e, /* GPIO5 == CLKOUT */
655 .retune_mobile_cfgs
= wm8996_retune
,
656 .num_retune_mobile_cfgs
= ARRAY_SIZE(wm8996_retune
),
659 static struct wm8962_pdata wm8962_pdata __initdata
= {
662 WM8962_GPIO_FN_OPCLK
,
663 WM8962_GPIO_FN_DMICCLK
,
665 0x8000 | WM8962_GPIO_FN_DMICDAT
,
666 WM8962_GPIO_FN_IRQ
, /* Open drain mode */
668 .irq_active_low
= true,
671 static struct wm9081_pdata wm9081_pdata __initdata
= {
676 static struct i2c_board_info i2c_devs1
[] __initdata
= {
677 { I2C_BOARD_INFO("wm8311", 0x34),
679 .platform_data
= &glenfarclas_pmic_pdata
},
681 { I2C_BOARD_INFO("wm1250-ev1", 0x27) },
682 { I2C_BOARD_INFO("wm8996", 0x1a),
683 .platform_data
= &wm8996_pdata
,
684 .irq
= GLENFARCLAS_PMIC_IRQ_BASE
+ WM831X_IRQ_GPIO_2
,
686 { I2C_BOARD_INFO("wm9081", 0x6c),
687 .platform_data
= &wm9081_pdata
, },
688 { I2C_BOARD_INFO("wm8962", 0x1a),
689 .platform_data
= &wm8962_pdata
,
690 .irq
= GLENFARCLAS_PMIC_IRQ_BASE
+ WM831X_IRQ_GPIO_2
,
694 static void __init
crag6410_map_io(void)
696 s3c64xx_init_io(NULL
, 0);
697 s3c24xx_init_clocks(12000000);
698 s3c24xx_init_uarts(crag6410_uartcfgs
, ARRAY_SIZE(crag6410_uartcfgs
));
700 /* LCD type and Bypass set by bootloader */
703 static struct s3c_sdhci_platdata crag6410_hsmmc2_pdata
= {
705 .cd_type
= S3C_SDHCI_CD_PERMANENT
,
708 static struct s3c_sdhci_platdata crag6410_hsmmc1_pdata
= {
710 .cd_type
= S3C_SDHCI_CD_GPIO
,
711 .ext_cd_gpio
= S3C64XX_GPF(11),
714 static void crag6410_cfg_sdhci0(struct platform_device
*dev
, int width
)
716 /* Set all the necessary GPG pins to special-function 2 */
717 s3c_gpio_cfgrange_nopull(S3C64XX_GPG(0), 2 + width
, S3C_GPIO_SFN(2));
719 /* force card-detected for prototype 0 */
720 s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_DOWN
);
723 static struct s3c_sdhci_platdata crag6410_hsmmc0_pdata
= {
725 .cd_type
= S3C_SDHCI_CD_INTERNAL
,
726 .cfg_gpio
= crag6410_cfg_sdhci0
,
729 static void __init
crag6410_machine_init(void)
731 /* Open drain IRQs need pullups */
732 s3c_gpio_setpull(S3C64XX_GPM(0), S3C_GPIO_PULL_UP
);
733 s3c_gpio_setpull(S3C64XX_GPN(0), S3C_GPIO_PULL_UP
);
735 gpio_request(S3C64XX_GPB(0), "LCD power");
736 gpio_direction_output(S3C64XX_GPB(0), 0);
738 gpio_request(S3C64XX_GPF(14), "LCD PWM");
739 gpio_direction_output(S3C64XX_GPF(14), 0); /* turn off */
741 gpio_request(S3C64XX_GPB(1), "SD power");
742 gpio_direction_output(S3C64XX_GPB(1), 0);
744 gpio_request(S3C64XX_GPF(10), "nRESETSEL");
745 gpio_direction_output(S3C64XX_GPF(10), 1);
747 s3c_sdhci0_set_platdata(&crag6410_hsmmc0_pdata
);
748 s3c_sdhci1_set_platdata(&crag6410_hsmmc1_pdata
);
749 s3c_sdhci2_set_platdata(&crag6410_hsmmc2_pdata
);
751 s3c_i2c0_set_platdata(&i2c0_pdata
);
752 s3c_i2c1_set_platdata(NULL
);
753 s3c_fb_set_platdata(&crag6410_lcd_pdata
);
755 i2c_register_board_info(0, i2c_devs0
, ARRAY_SIZE(i2c_devs0
));
756 i2c_register_board_info(1, i2c_devs1
, ARRAY_SIZE(i2c_devs1
));
758 samsung_keypad_set_platdata(&crag6410_keypad_data
);
760 platform_add_devices(crag6410_devices
, ARRAY_SIZE(crag6410_devices
));
762 regulator_has_full_constraints();
767 MACHINE_START(WLF_CRAGG_6410
, "Wolfson Cragganmore 6410")
768 /* Maintainer: Mark Brown <broonie@opensource.wolfsonmicro.com> */
769 .boot_params
= S3C64XX_PA_SDRAM
+ 0x100,
770 .init_irq
= s3c6410_init_irq
,
771 .map_io
= crag6410_map_io
,
772 .init_machine
= crag6410_machine_init
,
773 .timer
= &s3c24xx_timer
,