From 08d01641bcfe7402cd5aaf23b7c88fc7bc1ea279 Mon Sep 17 00:00:00 2001 From: Preetham Chandru Date: Thu, 18 Aug 2011 17:04:56 +0530 Subject: tegra: harmony: wifi: add board support for WiFi The SDIO WiFi module requires power from external PMU and 1.2V regulator. The module gets powered on if - (1) all power sources are enabled, and (2) power (down) and reset (down) pins are enabled as per spec. To enable mmc/SDIO driver to detect the WiFi hardware, the WiFi chip has to be powered-up before mmc driver does probing. So, steps should be as following: (1) required regulators are on, (2) power/reset of WiFi are enabled, (3) mmc does probing. Later time, when WiFi driver module is loaded and registers with SDIO, the SDIO driver knows which H/W the driver has to be associated with. Bug: 829647 Change-Id: I55724cf9dfb6bd2b9f9133632b31d6eef072a35f signed-off-by: Preetham Chandru Reviewed-on: http://git-master/r/47808 Reviewed-by: Allen R Martin --- arch/arm/mach-tegra/board-harmony-pinmux.c | 24 ++++++- arch/arm/mach-tegra/board-harmony-power.c | 111 ++++++++++++++++++++++++++++- arch/arm/mach-tegra/board-harmony.c | 36 ++++++++++ arch/arm/mach-tegra/board-harmony.h | 13 +++- 4 files changed, 179 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-tegra/board-harmony-pinmux.c b/arch/arm/mach-tegra/board-harmony-pinmux.c index e5451a1f55dc..d3e7146014be 100644 --- a/arch/arm/mach-tegra/board-harmony-pinmux.c +++ b/arch/arm/mach-tegra/board-harmony-pinmux.c @@ -20,6 +20,22 @@ #include "board-harmony.h" +#define DEFAULT_DRIVE(_name) \ + { \ + .pingroup = TEGRA_DRIVE_PINGROUP_##_name, \ + .hsm = TEGRA_HSM_DISABLE, \ + .schmitt = TEGRA_SCHMITT_ENABLE, \ + .drive = TEGRA_DRIVE_DIV_1, \ + .pull_down = TEGRA_PULL_31, \ + .pull_up = TEGRA_PULL_31, \ + .slew_rising = TEGRA_SLEW_SLOWEST, \ + .slew_falling = TEGRA_SLEW_SLOWEST, \ + } + +static __initdata struct tegra_drive_pingroup_config harmony_drive_pinmux[] = { + DEFAULT_DRIVE(SDIO1), +}; + static __initdata struct tegra_pingroup_config harmony_pinmux[] = { {TEGRA_PINGROUP_ATA, TEGRA_MUX_IDE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, {TEGRA_PINGROUP_ATB, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, @@ -106,13 +122,13 @@ static __initdata struct tegra_pingroup_config harmony_pinmux[] = { {TEGRA_PINGROUP_SDB, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_SDC, TEGRA_MUX_PWM, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, {TEGRA_PINGROUP_SDD, TEGRA_MUX_PWM, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, - {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, {TEGRA_PINGROUP_SLXA, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_SLXC, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_SLXD, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_SLXK, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, - {TEGRA_PINGROUP_SPDI, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, - {TEGRA_PINGROUP_SPDO, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_SPDI, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SPDO, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, {TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_SPIB, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, @@ -142,4 +158,6 @@ static __initdata struct tegra_pingroup_config harmony_pinmux[] = { void __init harmony_pinmux_init(void) { tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux)); + tegra_drive_pinmux_config_table(harmony_drive_pinmux, + ARRAY_SIZE(harmony_drive_pinmux)); } diff --git a/arch/arm/mach-tegra/board-harmony-power.c b/arch/arm/mach-tegra/board-harmony-power.c index f3e81532f9f9..5b5fb8d11d60 100644 --- a/arch/arm/mach-tegra/board-harmony-power.c +++ b/arch/arm/mach-tegra/board-harmony-power.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,7 @@ #include "power.h" #include "wakeups-t2.h" #include "board.h" +#include "board-harmony.h" #define PMC_CTRL 0x0 #define PMC_CTRL_INTR_LOW (1 << 17) @@ -95,6 +97,102 @@ static struct regulator_consumer_supply tps658621_ldo9_supply[] = { REGULATOR_SUPPLY("avdd_amp", NULL), }; +/* regulator supplies power to WWAN - by default disable */ +static struct regulator_consumer_supply vdd_1v5_consumer_supply[] = { + REGULATOR_SUPPLY("vdd_1v5", NULL), +}; + +static struct regulator_init_data vdd_1v5_initdata = { + .consumer_supplies = vdd_1v5_consumer_supply, + .num_consumer_supplies = 1, + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + .always_on = 0, + }, +}; + +static struct fixed_voltage_config vdd_1v5 = { + .supply_name = "vdd_1v5", + .microvolts = 1500000, /* Enable 1.5V */ + .gpio = TPS_GPIO_EN_1V5, /* GPIO BASE+0 */ + .startup_delay = 0, + .enable_high = 0, + .enabled_at_boot = 0, + .init_data = &vdd_1v5_initdata, +}; + +/* regulator supplies power to WLAN - enable here, to satisfy SDIO probing */ +static struct regulator_consumer_supply vdd_1v2_consumer_supply[] = { + REGULATOR_SUPPLY("vdd_1v2", NULL), +}; + +static struct regulator_init_data vdd_1v2_initdata = { + .consumer_supplies = vdd_1v2_consumer_supply, + .num_consumer_supplies = 1, + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + .always_on = 1, + }, +}; + +static struct fixed_voltage_config vdd_1v2 = { + .supply_name = "vdd_1v2", + .microvolts = 1200000, /* Enable 1.2V */ + .gpio = TPS_GPIO_EN_1V2, /* GPIO BASE+1 */ + .startup_delay = 0, + .enable_high = 1, + .enabled_at_boot = 1, + .init_data = &vdd_1v2_initdata, +}; + +/* regulator supplies power to PLL - enable here */ +static struct regulator_consumer_supply vdd_1v05_consumer_supply[] = { + REGULATOR_SUPPLY("vdd_1v05", NULL), +}; + +static struct regulator_init_data vdd_1v05_initdata = { + .consumer_supplies = vdd_1v05_consumer_supply, + .num_consumer_supplies = 1, + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + .always_on = 1, + }, +}; + +static struct fixed_voltage_config vdd_1v05 = { + .supply_name = "vdd_1v05", + .microvolts = 1050000, /* Enable 1.05V */ + .gpio = TPS_GPIO_EN_1V05, /* BASE+2 */ + .startup_delay = 0, + .enable_high = 1, + .enabled_at_boot = 0, + .init_data = &vdd_1v05_initdata, +}; + +/* mode pin for 1.05V regulator - enable here */ +static struct regulator_consumer_supply vdd_1v05_mode_consumer_supply[] = { + REGULATOR_SUPPLY("vdd_1v05_mode", NULL), +}; + +static struct regulator_init_data vdd_1v05_mode_initdata = { + .consumer_supplies = vdd_1v05_mode_consumer_supply, + .num_consumer_supplies = 1, + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + .always_on = 1, + }, +}; + +static struct fixed_voltage_config vdd_1v05_mode = { + .supply_name = "vdd_1v05_mode", + .microvolts = 1050000, /* Enable 1.05V */ + .gpio = TPS_GPIO_MODE_1V05, /* BASE+3 */ + .startup_delay = 0, + .enable_high = 1, + .enabled_at_boot = 0, + .init_data = &vdd_1v05_mode_initdata, +}; + #define REGULATOR_INIT(_id, _minmv, _maxmv) \ { \ .constraints = { \ @@ -116,7 +214,7 @@ static struct regulator_init_data sm2_data = REGULATOR_INIT(sm2, 3000, 4550); static struct regulator_init_data ldo0_data = REGULATOR_INIT(ldo0, 1250, 3300); static struct regulator_init_data ldo1_data = REGULATOR_INIT(ldo1, 725, 1500); static struct regulator_init_data ldo2_data = REGULATOR_INIT(ldo2, 725, 1500); -static struct regulator_init_data ldo3_data = REGULATOR_INIT(ldo3, 1250, 3300); +static struct regulator_init_data ldo3_data = REGULATOR_INIT(ldo3, 3300, 3300); static struct regulator_init_data ldo4_data = REGULATOR_INIT(ldo4, 1700, 2475); static struct regulator_init_data ldo5_data = REGULATOR_INIT(ldo5, 1250, 3300); static struct regulator_init_data ldo6_data = REGULATOR_INIT(ldo6, 1250, 3300); @@ -135,6 +233,13 @@ static struct tps6586x_rtc_platform_data rtc_data = { .platform_data = _data, \ } +#define TPS_GPIO_FIXED_REG(_id, _data) \ + { \ + .id = _id, \ + .name = "reg-fixed-voltage", \ + .platform_data = _data, \ + } + static struct tps6586x_subdev_info tps_devs[] = { TPS_REG(SM_0, &sm0_data), TPS_REG(SM_1, &sm1_data), @@ -149,6 +254,10 @@ static struct tps6586x_subdev_info tps_devs[] = { TPS_REG(LDO_7, &ldo7_data), TPS_REG(LDO_8, &ldo8_data), TPS_REG(LDO_9, &ldo9_data), + TPS_GPIO_FIXED_REG(0, &vdd_1v5), + TPS_GPIO_FIXED_REG(1, &vdd_1v2), + TPS_GPIO_FIXED_REG(2, &vdd_1v05), + TPS_GPIO_FIXED_REG(3, &vdd_1v05_mode), { .id = 0, .name = "tps6586x-rtc", diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c index d9e398e9fdf7..e861bfeef132 100644 --- a/arch/arm/mach-tegra/board-harmony.c +++ b/arch/arm/mach-tegra/board-harmony.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -377,6 +378,41 @@ static __initdata struct tegra_clk_init_table harmony_clk_init_table[] = { { NULL, NULL, 0, 0}, }; +static int __init harmony_wifi_init(void) +{ + int gpio_pwr, gpio_rst; + + if (!machine_is_harmony()) + return 0; + + /* WLAN - Power up (low) and Reset (low) */ + gpio_pwr = gpio_request(TEGRA_GPIO_WLAN_PWR_LOW, "wlan_pwr"); + gpio_rst = gpio_request(TEGRA_GPIO_WLAN_RST_LOW, "wlan_rst"); + if (gpio_pwr < 0 || gpio_rst < 0) + pr_warning("Unable to get gpio for WLAN Power and Reset\n"); + else { + + tegra_gpio_enable(TEGRA_GPIO_WLAN_PWR_LOW); + tegra_gpio_enable(TEGRA_GPIO_WLAN_RST_LOW); + /* toggle in this order as per spec */ + gpio_direction_output(TEGRA_GPIO_WLAN_PWR_LOW, 0); + gpio_direction_output(TEGRA_GPIO_WLAN_RST_LOW, 0); + udelay(5); + gpio_direction_output(TEGRA_GPIO_WLAN_PWR_LOW, 1); + gpio_direction_output(TEGRA_GPIO_WLAN_RST_LOW, 1); + } + + return 0; +} + +/* + * subsys_initcall_sync is good synch point to call harmony_wifi_init + * This makes sure that the required regulators (LDO3 + * supply of external PMU and 1.2V regulator) are properly enabled, + * and mmc driver has not yet probed for a device on SDIO bus. + */ +subsys_initcall_sync(harmony_wifi_init); + static void __init tegra_harmony_init(void) { tegra_common_init(); diff --git a/arch/arm/mach-tegra/board-harmony.h b/arch/arm/mach-tegra/board-harmony.h index 876ec21eb2e0..c8645ca44338 100644 --- a/arch/arm/mach-tegra/board-harmony.h +++ b/arch/arm/mach-tegra/board-harmony.h @@ -17,10 +17,21 @@ #ifndef _MACH_TEGRA_BOARD_HARMONY_H #define _MACH_TEGRA_BOARD_HARMONY_H +#define HARMONY_GPIO_TPS6586X(_x_) (TEGRA_NR_GPIOS + (_x_)) +/* fixed voltage regulator enable/mode gpios */ +#define TPS_GPIO_EN_1V5 (HARMONY_GPIO_TPS6586X(0)) +#define TPS_GPIO_EN_1V2 (HARMONY_GPIO_TPS6586X(1)) +#define TPS_GPIO_EN_1V05 (HARMONY_GPIO_TPS6586X(2)) +#define TPS_GPIO_MODE_1V05 (HARMONY_GPIO_TPS6586X(3)) + +/* WLAN pwr and reset gpio */ +#define TEGRA_GPIO_WLAN_PWR_LOW TEGRA_GPIO_PK5 +#define TEGRA_GPIO_WLAN_RST_LOW TEGRA_GPIO_PK6 + void harmony_pinmux_init(void); int harmony_panel_init(void); int harmony_sdhci_init(void); -void harmony_regulator_init(void); +int harmony_regulator_init(void); void harmony_power_off_init(void); #endif -- cgit v1.2.3