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 /* VDDARM is controlled by DVS1 connected to GPK(0) */
357 static struct wm831x_buckv_pdata vddarm_pdata
= {
358 .dvs_control_src
= 1,
359 .dvs_gpio
= S3C64XX_GPK(0),
362 static struct regulator_consumer_supply vddarm_consumers
[] __initdata
= {
363 REGULATOR_SUPPLY("vddarm", NULL
),
366 static struct regulator_init_data vddarm __initdata
= {
372 .valid_ops_mask
= REGULATOR_CHANGE_VOLTAGE
,
374 .num_consumer_supplies
= ARRAY_SIZE(vddarm_consumers
),
375 .consumer_supplies
= vddarm_consumers
,
376 .supply_regulator
= "WALLVDD",
377 .driver_data
= &vddarm_pdata
,
380 static struct regulator_init_data vddint __initdata
= {
386 .valid_ops_mask
= REGULATOR_CHANGE_VOLTAGE
,
390 static struct regulator_init_data vddmem __initdata
= {
397 static struct regulator_init_data vddsys __initdata
= {
399 .name
= "VDDSYS,VDDEXT,VDDPCM,VDDSS",
404 static struct regulator_consumer_supply vddmmc_consumers
[] __initdata
= {
405 REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
406 REGULATOR_SUPPLY("vmmc", "s3c-sdhci.1"),
407 REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"),
410 static struct regulator_init_data vddmmc __initdata
= {
415 .num_consumer_supplies
= ARRAY_SIZE(vddmmc_consumers
),
416 .consumer_supplies
= vddmmc_consumers
,
417 .supply_regulator
= "WALLVDD",
420 static struct regulator_init_data vddotgi __initdata
= {
425 .supply_regulator
= "WALLVDD",
428 static struct regulator_init_data vddotg __initdata
= {
433 .supply_regulator
= "WALLVDD",
436 static struct regulator_init_data vddhi __initdata
= {
441 .supply_regulator
= "WALLVDD",
444 static struct regulator_init_data vddadc __initdata
= {
446 .name
= "VDDADC,VDDDAC",
449 .supply_regulator
= "WALLVDD",
452 static struct regulator_init_data vddmem0 __initdata
= {
457 .supply_regulator
= "WALLVDD",
460 static struct regulator_init_data vddpll __initdata
= {
465 .supply_regulator
= "WALLVDD",
468 static struct regulator_init_data vddlcd __initdata
= {
473 .supply_regulator
= "WALLVDD",
476 static struct regulator_init_data vddalive __initdata
= {
481 .supply_regulator
= "WALLVDD",
484 static struct wm831x_backup_pdata banff_backup_pdata __initdata
= {
486 .vlim
= 2500, /* mV */
487 .ilim
= 200, /* uA */
490 static struct wm831x_status_pdata banff_red_led __initdata
= {
491 .name
= "banff:red:",
492 .default_src
= WM831X_STATUS_MANUAL
,
495 static struct wm831x_status_pdata banff_green_led __initdata
= {
496 .name
= "banff:green:",
497 .default_src
= WM831X_STATUS_MANUAL
,
500 static struct wm831x_touch_pdata touch_pdata __initdata
= {
501 .data_irq
= S3C_EINT(26),
502 .pd_irq
= S3C_EINT(27),
505 static struct wm831x_pdata crag_pmic_pdata __initdata
= {
507 .irq_base
= BANFF_PMIC_IRQ_BASE
,
508 .gpio_base
= GPIO_BOARD_START
+ 8,
510 .backup
= &banff_backup_pdata
,
513 /* GPIO5: DVS1_REQ - CMOS, DBVDD, active high */
514 [4] = WM831X_GPN_DIR
| WM831X_GPN_POL
| WM831X_GPN_ENA
| 0x8,
515 /* GPIO11: Touchscreen data - CMOS, DBVDD, active high*/
516 [10] = WM831X_GPN_POL
| WM831X_GPN_ENA
| 0x6,
517 /* GPIO12: Touchscreen pen down - CMOS, DBVDD, active high*/
518 [11] = WM831X_GPN_POL
| WM831X_GPN_ENA
| 0x7,
538 &vddalive
, /* LDO11 */
546 .touch
= &touch_pdata
,
549 static struct i2c_board_info i2c_devs0
[] __initdata
= {
550 { I2C_BOARD_INFO("24c08", 0x50), },
551 { I2C_BOARD_INFO("tca6408", 0x20),
552 .platform_data
= &crag6410_pca_data
,
554 { I2C_BOARD_INFO("wm8312", 0x34),
555 .platform_data
= &crag_pmic_pdata
,
560 static struct s3c2410_platform_i2c i2c0_pdata
= {
564 static struct regulator_init_data pvdd_1v2 __initdata
= {
571 static struct regulator_consumer_supply pvdd_1v8_consumers
[] __initdata
= {
572 REGULATOR_SUPPLY("PLLVDD", "1-001a"),
573 REGULATOR_SUPPLY("DBVDD", "1-001a"),
574 REGULATOR_SUPPLY("CPVDD", "1-001a"),
575 REGULATOR_SUPPLY("AVDD2", "1-001a"),
576 REGULATOR_SUPPLY("DCVDD", "1-001a"),
577 REGULATOR_SUPPLY("AVDD", "1-001a"),
580 static struct regulator_init_data pvdd_1v8 __initdata
= {
586 .consumer_supplies
= pvdd_1v8_consumers
,
587 .num_consumer_supplies
= ARRAY_SIZE(pvdd_1v8_consumers
),
590 static struct regulator_consumer_supply pvdd_3v3_consumers
[] __initdata
= {
591 REGULATOR_SUPPLY("MICVDD", "1-001a"),
592 REGULATOR_SUPPLY("AVDD1", "1-001a"),
595 static struct regulator_init_data pvdd_3v3 __initdata
= {
601 .consumer_supplies
= pvdd_3v3_consumers
,
602 .num_consumer_supplies
= ARRAY_SIZE(pvdd_3v3_consumers
),
605 static struct wm831x_pdata glenfarclas_pmic_pdata __initdata
= {
607 .irq_base
= GLENFARCLAS_PMIC_IRQ_BASE
,
608 .gpio_base
= GLENFARCLAS_PMIC_GPIO_BASE
,
611 /* GPIO1-3: IRQ inputs, rising edge triggered, CMOS */
612 [0] = WM831X_GPN_DIR
| WM831X_GPN_POL
| WM831X_GPN_ENA
,
613 [1] = WM831X_GPN_DIR
| WM831X_GPN_POL
| WM831X_GPN_ENA
,
614 [2] = WM831X_GPN_DIR
| WM831X_GPN_POL
| WM831X_GPN_ENA
,
618 &pvdd_1v2
, /* DCDC1 */
619 &pvdd_1v8
, /* DCDC2 */
620 &pvdd_3v3
, /* DCDC3 */
623 .disable_touch
= true,
626 static struct wm8996_retune_mobile_config wm8996_retune
[] = {
631 0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
632 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
633 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
640 0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
641 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
642 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
647 static struct wm8996_pdata wm8996_pdata __initdata
= {
648 .ldo_ena
= S3C64XX_GPN(7),
649 .gpio_base
= CODEC_GPIO_BASE
,
651 .inl_mode
= WM8996_DIFFERRENTIAL_1
,
652 .inr_mode
= WM8996_DIFFERRENTIAL_1
,
654 .irq_flags
= IRQF_TRIGGER_RISING
,
657 0x8001, /* GPIO1 == ADCLRCLK1 */
658 0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
659 0x0141, /* GPIO3 == HP_SEL */
660 0x0002, /* GPIO4 == IRQ */
661 0x020e, /* GPIO5 == CLKOUT */
664 .retune_mobile_cfgs
= wm8996_retune
,
665 .num_retune_mobile_cfgs
= ARRAY_SIZE(wm8996_retune
),
668 static struct wm8962_pdata wm8962_pdata __initdata
= {
671 WM8962_GPIO_FN_OPCLK
,
672 WM8962_GPIO_FN_DMICCLK
,
674 0x8000 | WM8962_GPIO_FN_DMICDAT
,
675 WM8962_GPIO_FN_IRQ
, /* Open drain mode */
677 .irq_active_low
= true,
680 static struct wm9081_pdata wm9081_pdata __initdata
= {
685 static struct i2c_board_info i2c_devs1
[] __initdata
= {
686 { I2C_BOARD_INFO("wm8311", 0x34),
688 .platform_data
= &glenfarclas_pmic_pdata
},
690 { I2C_BOARD_INFO("wm1250-ev1", 0x27) },
691 { I2C_BOARD_INFO("wm8996", 0x1a),
692 .platform_data
= &wm8996_pdata
,
693 .irq
= GLENFARCLAS_PMIC_IRQ_BASE
+ WM831X_IRQ_GPIO_2
,
695 { I2C_BOARD_INFO("wm9081", 0x6c),
696 .platform_data
= &wm9081_pdata
, },
697 { I2C_BOARD_INFO("wm8962", 0x1a),
698 .platform_data
= &wm8962_pdata
,
699 .irq
= GLENFARCLAS_PMIC_IRQ_BASE
+ WM831X_IRQ_GPIO_2
,
703 static void __init
crag6410_map_io(void)
705 s3c64xx_init_io(NULL
, 0);
706 s3c24xx_init_clocks(12000000);
707 s3c24xx_init_uarts(crag6410_uartcfgs
, ARRAY_SIZE(crag6410_uartcfgs
));
709 /* LCD type and Bypass set by bootloader */
712 static struct s3c_sdhci_platdata crag6410_hsmmc2_pdata
= {
714 .cd_type
= S3C_SDHCI_CD_PERMANENT
,
717 static struct s3c_sdhci_platdata crag6410_hsmmc1_pdata
= {
719 .cd_type
= S3C_SDHCI_CD_GPIO
,
720 .ext_cd_gpio
= S3C64XX_GPF(11),
723 static void crag6410_cfg_sdhci0(struct platform_device
*dev
, int width
)
725 /* Set all the necessary GPG pins to special-function 2 */
726 s3c_gpio_cfgrange_nopull(S3C64XX_GPG(0), 2 + width
, S3C_GPIO_SFN(2));
728 /* force card-detected for prototype 0 */
729 s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_DOWN
);
732 static struct s3c_sdhci_platdata crag6410_hsmmc0_pdata
= {
734 .cd_type
= S3C_SDHCI_CD_INTERNAL
,
735 .cfg_gpio
= crag6410_cfg_sdhci0
,
738 static void __init
crag6410_machine_init(void)
740 /* Open drain IRQs need pullups */
741 s3c_gpio_setpull(S3C64XX_GPM(0), S3C_GPIO_PULL_UP
);
742 s3c_gpio_setpull(S3C64XX_GPN(0), S3C_GPIO_PULL_UP
);
744 gpio_request(S3C64XX_GPB(0), "LCD power");
745 gpio_direction_output(S3C64XX_GPB(0), 0);
747 gpio_request(S3C64XX_GPF(14), "LCD PWM");
748 gpio_direction_output(S3C64XX_GPF(14), 0); /* turn off */
750 gpio_request(S3C64XX_GPB(1), "SD power");
751 gpio_direction_output(S3C64XX_GPB(1), 0);
753 gpio_request(S3C64XX_GPF(10), "nRESETSEL");
754 gpio_direction_output(S3C64XX_GPF(10), 1);
756 s3c_sdhci0_set_platdata(&crag6410_hsmmc0_pdata
);
757 s3c_sdhci1_set_platdata(&crag6410_hsmmc1_pdata
);
758 s3c_sdhci2_set_platdata(&crag6410_hsmmc2_pdata
);
760 s3c_i2c0_set_platdata(&i2c0_pdata
);
761 s3c_i2c1_set_platdata(NULL
);
762 s3c_fb_set_platdata(&crag6410_lcd_pdata
);
764 i2c_register_board_info(0, i2c_devs0
, ARRAY_SIZE(i2c_devs0
));
765 i2c_register_board_info(1, i2c_devs1
, ARRAY_SIZE(i2c_devs1
));
767 samsung_keypad_set_platdata(&crag6410_keypad_data
);
769 platform_add_devices(crag6410_devices
, ARRAY_SIZE(crag6410_devices
));
771 regulator_has_full_constraints();
776 MACHINE_START(WLF_CRAGG_6410
, "Wolfson Cragganmore 6410")
777 /* Maintainer: Mark Brown <broonie@opensource.wolfsonmicro.com> */
778 .boot_params
= S3C64XX_PA_SDRAM
+ 0x100,
779 .init_irq
= s3c6410_init_irq
,
780 .map_io
= crag6410_map_io
,
781 .init_machine
= crag6410_machine_init
,
782 .timer
= &s3c24xx_timer
,