summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRakesh Kumar <krakesh@nvidia.com>2010-09-23 12:15:39 +0530
committerBharat Nihalani <bnihalani@nvidia.com>2010-10-05 01:20:38 -0700
commitaae38757d090a317782df6247ff7fe0f802a21ff (patch)
tree9b6c33ff9d08b8ecd670bcdf3173b169d42d1309
parenta12c04e6a12dcc53ccc3811891a49c78ad397030 (diff)
[arm/tegra] provide wifi power/carddetect abstraction
When user switches on wifi, wifi driver need to poweron wifi card and ask sdhci stack to enumerate the card. Sdhci stack does not provide any interface to achieve this. Major wifi vendors depend on platform to provide wifi poweron/reset/carddetect abstraction function. Bug ID 739374 Change-Id: I988393352ff6cb54be3d70a59c94f67eedff06fb Reviewed-on: http://git-master/r/7097 Reviewed-by: Rakesh Kumar <krakesh@nvidia.com> Tested-by: Rakesh Kumar <krakesh@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/Makefile3
-rw-r--r--arch/arm/mach-tegra/board-generic.c2
-rwxr-xr-xarch/arm/mach-tegra/board-nvodm.c8
-rw-r--r--arch/arm/mach-tegra/board-ventana-wifi.c98
-rw-r--r--arch/arm/mach-tegra/board.h8
-rw-r--r--arch/arm/mach-tegra/include/mach/sdhci.h3
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/misc/ventana/nvodm_sdio.c86
-rwxr-xr-xdrivers/mmc/host/sdhci-tegra.c33
8 files changed, 146 insertions, 95 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index eda5208e5282..fd2d7e7bdb7b 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -53,4 +53,5 @@ obj-$(CONFIG_TEGRA_NVEC) += nvec/
obj-$(CONFIG_TEGRA_FUSE) += sysfs-fuse.o
obj-$(CONFIG_TEGRA_ODM_VIBRATE) += vibrate.o
-obj-$(CONFIG_TEGRA_AES_USER) += nvaes_user.o \ No newline at end of file
+obj-$(CONFIG_TEGRA_AES_USER) += nvaes_user.o
+obj-$(CONFIG_MACH_VENTANA) += board-ventana-wifi.o
diff --git a/arch/arm/mach-tegra/board-generic.c b/arch/arm/mach-tegra/board-generic.c
index fb84de21dc3b..f1f26ce2777f 100644
--- a/arch/arm/mach-tegra/board-generic.c
+++ b/arch/arm/mach-tegra/board-generic.c
@@ -359,6 +359,7 @@ static void __init tegra_harmony_init(void)
do_system_init(true, true);
}
+
static void __init tegra_ventana_init(void)
{
#ifdef CONFIG_USB_ANDROID
@@ -368,6 +369,7 @@ static void __init tegra_ventana_init(void)
i2c_device_setup();
tegra_setup_32khz_clock();
tegra_setup_bluesleep();
+ ventana_setup_wifi();
}
static void __init tegra_generic_init(void)
diff --git a/arch/arm/mach-tegra/board-nvodm.c b/arch/arm/mach-tegra/board-nvodm.c
index 029c432dba37..10314a967455 100755
--- a/arch/arm/mach-tegra/board-nvodm.c
+++ b/arch/arm/mach-tegra/board-nvodm.c
@@ -200,6 +200,7 @@ static void tegra_debug_port_resume(void)
uart_debug_port.nr_pins, TEGRA_TRI_NORMAL);
}
+
#ifdef CONFIG_MMC_SDHCI_TEGRA
extern struct tegra_nand_platform tegra_nand_plat;
static struct tegra_sdhci_platform_data tegra_sdhci_platform[] = {
@@ -356,6 +357,13 @@ static void __init tegra_setup_sdhci(void) {
plat->is_removable = prop->IsCardRemovable;
plat->is_always_on = prop->AlwaysON;
+
+#ifdef CONFIG_MACH_VENTANA
+ if (prop->usage == NvOdmQuerySdioSlotUsage_wlan)
+ plat->register_status_notify =
+ ventana_wifi_status_register;
+#endif
+
if (!gpio)
gpio_count = 0;
switch (gpio_count) {
diff --git a/arch/arm/mach-tegra/board-ventana-wifi.c b/arch/arm/mach-tegra/board-ventana-wifi.c
new file mode 100644
index 000000000000..0d686f5a1fb3
--- /dev/null
+++ b/arch/arm/mach-tegra/board-ventana-wifi.c
@@ -0,0 +1,98 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/wlan_plat.h>
+#include <linux/delay.h>
+
+#include "nvodm_query_discovery.h"
+#include "gpio-names.h"
+#include "board.h"
+
+#define VENTANA_WLAN_PWR TEGRA_GPIO_PK5
+#define VENTANA_WLAN_RST TEGRA_GPIO_PK6
+
+static void (*wifi_status_cb)(int card_present, void *dev_id);
+static void *wifi_status_cb_devid;
+
+
+int ventana_wifi_status_register(void (*callback)(int card_present,
+ void *dev_id), void *dev_id)
+{
+ pr_debug("%s:\n", __func__);
+ if (wifi_status_cb) {
+ pr_err("%s: callback already registered\n", __func__);
+ return -EAGAIN;
+ }
+ wifi_status_cb = callback;
+ wifi_status_cb_devid = dev_id;
+ return 0;
+}
+
+
+static int ventana_wifi_power_state;
+static int ventana_wifi_power(int on)
+{
+ pr_debug("%s: %d\n", __func__, on);
+
+ mdelay(100);
+ gpio_set_value(VENTANA_WLAN_PWR, on);
+ mdelay(100);
+ gpio_set_value(VENTANA_WLAN_RST, on);
+ mdelay(200);
+
+ ventana_wifi_power_state = on;
+ return 0;
+}
+
+static int ventana_wifi_reset_state;
+static int ventana_wifi_reset(int on)
+{
+ pr_debug("%s: %d do nothing\n", __func__, on);
+ ventana_wifi_reset_state = on;
+ return 0;
+}
+
+static int ventana_wifi_cd; /* WIFI virtual 'card detect' status */
+static int ventana_wifi_set_carddetect(int val)
+{
+ pr_debug("%s: %d\n", __func__, val);
+ ventana_wifi_cd = val;
+ if (wifi_status_cb)
+ wifi_status_cb(val, wifi_status_cb_devid);
+ else
+ pr_warning("%s: Nobody to notify\n", __func__);
+ return 0;
+}
+
+static struct wifi_platform_data ventana_wifi_control = {
+ .set_power = ventana_wifi_power,
+ .set_reset = ventana_wifi_reset,
+ .set_carddetect = ventana_wifi_set_carddetect,
+};
+
+static struct platform_device ventana_wifi_device = {
+ .name = "bcm4329_wlan",
+ .id = 1,
+ .dev = {
+ .platform_data = &ventana_wifi_control,
+ },
+};
+
+static void __init ventana_wlan_gpio(void)
+{
+ tegra_gpio_enable(VENTANA_WLAN_PWR);
+ gpio_request(VENTANA_WLAN_PWR, "wlan_pwr");
+ gpio_direction_output(VENTANA_WLAN_PWR, 0);
+
+ tegra_gpio_enable(VENTANA_WLAN_RST);
+ gpio_request(VENTANA_WLAN_RST, "wlan_rst");
+ gpio_direction_output(VENTANA_WLAN_RST, 0);
+}
+
+int __init ventana_setup_wifi(void)
+{
+ pr_debug("%s: start\n", __func__);
+ ventana_wlan_gpio();
+ return platform_device_register(&ventana_wifi_device);
+}
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
index 574cf83c96fa..b3e199dcbe3e 100644
--- a/arch/arm/mach-tegra/board.h
+++ b/arch/arm/mach-tegra/board.h
@@ -52,4 +52,12 @@ bool tegra_chip_compare(u32 chip, u32 major_rev, u32 minor_rev);
bool tegra_is_ap20_a03p(void);
extern struct sys_timer tegra_timer;
+
+#ifdef CONFIG_MACH_VENTANA
+extern int __init ventana_setup_wifi(void);
+int ventana_wifi_status_register(void (*callback)(int card_present,
+ void *dev_id), void *dev_id);
+#endif
+
+
#endif
diff --git a/arch/arm/mach-tegra/include/mach/sdhci.h b/arch/arm/mach-tegra/include/mach/sdhci.h
index bf620dd57a7a..31d426c21974 100644
--- a/arch/arm/mach-tegra/include/mach/sdhci.h
+++ b/arch/arm/mach-tegra/include/mach/sdhci.h
@@ -42,6 +42,9 @@ struct tegra_sdhci_platform_data {
#ifdef CONFIG_EMBEDDED_MMC_START_OFFSET
unsigned long offset; /* offset in blocks to MBR */
#endif
+ /* card detect callback registration function*/
+ int (*register_status_notify)(void (*callback)(int card_present,
+ void *dev_id), void *dev_id);
};
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/misc/ventana/nvodm_sdio.c b/arch/arm/mach-tegra/odm_kit/adaptations/misc/ventana/nvodm_sdio.c
index a837a3d3524b..ce45bb7c68b5 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/misc/ventana/nvodm_sdio.c
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/misc/ventana/nvodm_sdio.c
@@ -15,8 +15,6 @@
#include "nvodm_pmu.h"
#include "nvos.h"
-#define WLAN_GUID NV_ODM_GUID('s','d','i','o','w','l','a','n')
-
typedef struct NvOdmSdioRec
{
// NvODM PMU device handle
@@ -69,38 +67,15 @@ static void NvOdmSetPowerOnSdio(NvOdmSdioHandle pDevice, NvBool enable)
}
}
-static NvBool SdioOdmWlanPower(NvOdmSdioHandle hOdmSdio, NvBool IsEnable)
-{
- if (IsEnable)
- {
- // Wlan Power On Reset Sequence
- NvOdmGpioSetState(hOdmSdio->hGpio, hOdmSdio->hPwrPin, 0x0);
- NvOdmGpioSetState(hOdmSdio->hGpio, hOdmSdio->hResetPin, 0x0);
- NvOdmOsSleepMS(200);
- NvOdmGpioSetState(hOdmSdio->hGpio, hOdmSdio->hPwrPin, 0x1);
- NvOdmGpioSetState(hOdmSdio->hGpio, hOdmSdio->hResetPin, 0x1);
- NvOdmOsSleepMS(200);
- }
- else
- {
- // Power Off sequence
- NvOdmGpioSetState(hOdmSdio->hGpio, hOdmSdio->hPwrPin, 0x0);
- }
-
- return NV_TRUE;
-}
-
NvOdmSdioHandle NvOdmSdioOpen(NvU32 Instance)
{
static NvOdmSdio *pDevice = NULL;
- NvOdmServicesGpioHandle hGpioTemp = NULL;
const NvOdmPeripheralConnectivity *pConnectivity;
NvU32 NumOfGuids = 1;
NvU64 guid;
NvU32 searchVals[2];
const NvU32 *pOdmConfigs;
NvU32 NumOdmConfigs;
- NvBool Status = NV_TRUE;
const NvOdmPeripheralSearch searchAttrs[] =
{
NvOdmPeripheralSearch_IoModule,
@@ -144,52 +119,6 @@ NvOdmSdioHandle NvOdmSdioOpen(NvU32 Instance)
pDevice->pConnectivity = pConnectivity;
NvOdmSetPowerOnSdio(pDevice, NV_TRUE);
- if (pConnectivity->Guid == WLAN_GUID)
- {
- // Getting the OdmGpio Handle
- hGpioTemp = NvOdmGpioOpen();
- if (hGpioTemp == NULL)
- {
- NvOdmOsFree(pDevice);
- pDevice = NULL;
- return (pDevice);
- }
-
- // Search for the Vdd rail and set the proper volage to the rail.
- if (pConnectivity->AddressList[1].Interface == NvOdmIoModule_Gpio)
- {
- // Acquiring Pin Handles for Power Pin
- pDevice->hPwrPin= NvOdmGpioAcquirePinHandle(hGpioTemp,
- pConnectivity->AddressList[1].Instance,
- pConnectivity->AddressList[1].Address);
- }
-
- if (pConnectivity->AddressList[2].Interface == NvOdmIoModule_Gpio)
- {
- // Acquiring Pin Handles for Reset Pin
- pDevice->hResetPin= NvOdmGpioAcquirePinHandle(hGpioTemp,
- pConnectivity->AddressList[2].Instance,
- pConnectivity->AddressList[2].Address);
- }
-
- // Setting the ON/OFF pin to output mode.
- NvOdmGpioConfig(hGpioTemp, pDevice->hPwrPin, NvOdmGpioPinMode_Output);
- NvOdmGpioConfig(hGpioTemp, pDevice->hResetPin, NvOdmGpioPinMode_Output);
-
- // Setting the Output Pin to Low
- NvOdmGpioSetState(hGpioTemp, pDevice->hPwrPin, 0x0);
- NvOdmGpioSetState(hGpioTemp, pDevice->hResetPin, 0x0);
-
- pDevice->hGpio = hGpioTemp;
-
- Status = SdioOdmWlanPower(pDevice, NV_TRUE);
- if (Status != NV_TRUE)
- {
- NvOdmOsFree(pDevice);
- pDevice = NULL;
- return (pDevice);
- }
- }
pDevice->PoweredOn = NV_TRUE;
pDevice->Instance = Instance;
return pDevice;
@@ -197,15 +126,6 @@ NvOdmSdioHandle NvOdmSdioOpen(NvU32 Instance)
void NvOdmSdioClose(NvOdmSdioHandle hOdmSdio)
{
- if (hOdmSdio->pConnectivity->Guid == WLAN_GUID)
- {
- // Call Turn off power when close is Called
- (void)SdioOdmWlanPower(hOdmSdio, NV_FALSE);
-
- NvOdmGpioReleasePinHandle(hOdmSdio->hGpio, hOdmSdio->hPwrPin);
- NvOdmGpioReleasePinHandle(hOdmSdio->hGpio, hOdmSdio->hResetPin);
- NvOdmGpioClose(hOdmSdio->hGpio);
- }
NvOdmSetPowerOnSdio(hOdmSdio, NV_FALSE);
if (hOdmSdio->hPmu != NULL)
{
@@ -225,9 +145,6 @@ NvBool NvOdmSdioSuspend(NvOdmSdioHandle hOdmSdio)
NvOdmSetPowerOnSdio(hOdmSdio, NV_FALSE);
- if (hOdmSdio->pConnectivity->Guid == WLAN_GUID)
- Status = SdioOdmWlanPower(hOdmSdio, NV_FALSE);
-
hOdmSdio->PoweredOn = NV_FALSE;
return Status;
@@ -242,9 +159,6 @@ NvBool NvOdmSdioResume(NvOdmSdioHandle hOdmSdio)
NvOdmSetPowerOnSdio(hOdmSdio, NV_TRUE);
- if (hOdmSdio->pConnectivity->Guid == WLAN_GUID)
- Status = SdioOdmWlanPower(hOdmSdio, NV_TRUE);
-
hOdmSdio->PoweredOn = NV_TRUE;
return Status;
}
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 6061d713e7ca..8f9510c7dea7 100755
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -74,7 +74,7 @@ static irqreturn_t card_detect_isr(int irq, void *dev_id)
struct tegra_sdhci *host = sdhci_priv(sdhost);
host->card_present =
- (gpio_get_value(host->gpio_cd)==host->gpio_polarity_cd);
+ (gpio_get_value(host->gpio_cd) == host->gpio_polarity_cd);
smp_wmb();
sdhci_card_detect_callback(sdhost);
@@ -88,12 +88,24 @@ static bool tegra_sdhci_card_detect(struct sdhci_host *sdhost)
return host->card_present;
}
+static void tegra_sdhci_status_notify_cb(int card_present, void *dev_id)
+{
+ struct sdhci_host *sdhost = dev_id;
+ struct tegra_sdhci *host = sdhci_priv(sdhost);
+
+ dev_dbg(&host->pdev->dev, "%s: card_present %d\n",
+ mmc_hostname(sdhost->mmc), card_present);
+
+ host->card_present = card_present;
+ sdhci_card_detect_callback(sdhost);
+}
+
static int tegra_sdhci_get_ro(struct sdhci_host *sdhost)
{
struct tegra_sdhci *host = sdhci_priv(sdhost);
BUG_ON(host->gpio_wp == -1);
- return (gpio_get_value(host->gpio_wp)==host->gpio_polarity_wp);
+ return (gpio_get_value(host->gpio_wp) == host->gpio_polarity_wp);
}
static void tegra_sdhci_set_clock(struct sdhci_host *sdhost,
@@ -236,7 +248,7 @@ int __init tegra_sdhci_probe(struct platform_device *pdev)
host->gpio_cd = -1;
host->irq_cd = -1;
goto skip_gpio_cd;
- }
+ }
ret = gpio_direction_input(host->gpio_cd);
if (ret < 0) {
dev_err(&pdev->dev, "failed to configure GPIO\n");
@@ -255,7 +267,8 @@ int __init tegra_sdhci_probe(struct platform_device *pdev)
goto skip_gpio_cd;
}
host->card_present =
- (gpio_get_value(host->gpio_cd)==host->gpio_polarity_cd);
+ (gpio_get_value(host->gpio_cd) ==
+ host->gpio_polarity_cd);
}
skip_gpio_cd:
ret = 0;
@@ -309,6 +322,10 @@ skip_gpio_wp:
if (!plat->is_removable)
host->card_present = true;
+ if (plat->register_status_notify)
+ plat->register_status_notify(tegra_sdhci_status_notify_cb,
+ sdhost);
+
sdhost->data_width = plat->bus_width;
sdhost->dma_mask = DMA_BIT_MASK(32);
ret = sdhci_add_host(sdhost);
@@ -400,7 +417,7 @@ static void tegra_sdhci_restore_interrupts(struct sdhci_host *sdhost)
sdhci_writel(sdhost, ierr, SDHCI_INT_ENABLE);
sdhci_writel(sdhost, ierr, SDHCI_SIGNAL_ENABLE);
- if ( (host->sdhci_ints & SDHCI_INT_CARD_INT) &&
+ if ((host->sdhci_ints & SDHCI_INT_CARD_INT) &&
(sdhost->quirks & SDHCI_QUIRK_ENABLE_INTERRUPT_AT_BLOCK_GAP)) {
u8 gap_ctrl = sdhci_readb(sdhost, SDHCI_BLOCK_GAP_CONTROL);
gap_ctrl |= 0x8;
@@ -493,7 +510,7 @@ static int tegra_sdhci_resume(struct device *dev)
host->clk_enable = true;
}
- if(host->card_always_on && is_card_sdio(sdhost->mmc->card)) {
+ if (host->card_always_on && is_card_sdio(sdhost->mmc->card)) {
int ret = 0;
/* soft reset SD host controller and enable interrupts */
@@ -508,7 +525,7 @@ static int tegra_sdhci_resume(struct device *dev)
return 0;
}
- if(host->hOdmSdio)
+ if (host->hOdmSdio)
NvOdmSdioResume(host->hOdmSdio);
return sdhci_resume_host(sdhost);
@@ -517,7 +534,7 @@ static struct dev_pm_ops tegra_sdhci_pm = {
.suspend = tegra_sdhci_suspend,
.resume = tegra_sdhci_resume,
};
-#define tegra_sdhci_pm_ops &tegra_sdhci_pm
+#define tegra_sdhci_pm_ops (&tegra_sdhci_pm)
#else
#define tegra_sdhci_pm_ops NULL
#endif