summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPreetham Chandru <pchandru@nvidia.com>2011-08-18 17:04:56 +0530
committerRohan Somvanshi <rsomvanshi@nvidia.com>2011-08-22 08:12:36 -0700
commit08d01641bcfe7402cd5aaf23b7c88fc7bc1ea279 (patch)
tree242d409207675a47e174429ac4e0dd3837209941
parent112bad447414fdc33e4c72393ffbbfb04d3caa78 (diff)
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 <pchandru@nvidia.com> Reviewed-on: http://git-master/r/47808 Reviewed-by: Allen R Martin <amartin@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/board-harmony-pinmux.c24
-rw-r--r--arch/arm/mach-tegra/board-harmony-power.c111
-rw-r--r--arch/arm/mach-tegra/board-harmony.c36
-rw-r--r--arch/arm/mach-tegra/board-harmony.h13
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 <linux/platform_device.h>
#include <linux/resource.h>
#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
#include <linux/mfd/tps6586x.h>
#include <linux/gpio.h>
#include <mach/suspend.h>
@@ -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 <linux/i2c-tegra.h>
#include <linux/io.h>
#include <linux/delay.h>
+#include <linux/gpio.h>
#include <linux/platform_data/tegra_usb.h>
#include <asm/mach-types.h>
@@ -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