mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
add sdio wifi power
This commit is contained in:
@@ -162,7 +162,7 @@ void rk2818_sdmmc1_cfg_gpio(struct platform_device *dev)
|
||||
{
|
||||
rk2818_mux_api_set(GPIOG_MMC1_SEL_NAME, IOMUXA_SDMMC1_CMD_DATA0_CLKOUT);
|
||||
rk2818_mux_api_set(GPIOG_MMC1D_SEL_NAME, IOMUXA_SDMMC1_DATA123);
|
||||
#if 1
|
||||
#if 0
|
||||
/* wifi power up (gpio control) */
|
||||
rk2818_mux_api_set(GPIOH7_HSADCCLK_SEL_NAME,IOMUXB_GPIO1_D7);
|
||||
rk2818_mux_api_set(GPIOF5_APWM3_DPWM3_NAME,IOMUXB_GPIO1_B5);
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
|
||||
#include "rk2818-sdmmc.h"
|
||||
|
||||
struct mmc_host *wifi_mmc_host = NULL;
|
||||
|
||||
#define RK2818_MCI_DATA_ERROR_FLAGS (SDMMC_INT_DRTO | SDMMC_INT_DCRC | SDMMC_INT_HTO | SDMMC_INT_SBE | SDMMC_INT_EBE)
|
||||
#define RK2818_MCI_CMD_ERROR_FLAGS (SDMMC_INT_RTO | SDMMC_INT_RCRC | SDMMC_INT_RE | SDMMC_INT_HLE)
|
||||
#define RK2818_MCI_ERROR_FLAGS (RK2818_MCI_DATA_ERROR_FLAGS | RK2818_MCI_CMD_ERROR_FLAGS | SDMMC_INT_HLE)
|
||||
@@ -1300,6 +1302,8 @@ static int rk2818_sdmmc_probe(struct platform_device *pdev)
|
||||
|
||||
dev_info(&pdev->dev, "RK2818 MMC controller used as %s, at irq %d\n",
|
||||
host->dma_name, host->irq);
|
||||
if (strncmp(host->dma_name, "sdio", 4) == 0)
|
||||
wifi_mmc_host = mmc;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1321,6 +1325,9 @@ static int __exit rk2818_sdmmc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rk2818_sdmmc_host *host = platform_get_drvdata(pdev);
|
||||
|
||||
if (strncmp(host->dma_name, "sdio", 4) == 0)
|
||||
wifi_mmc_host = NULL;
|
||||
|
||||
writel(0xFFFFFFFF, host->regs + SDMMC_RINTSTS);
|
||||
writel(0, host->regs + SDMMC_INTMASK); // disable all mmc interrupt first
|
||||
|
||||
|
||||
@@ -9,5 +9,5 @@ libertas_spi-objs += if_spi.o
|
||||
obj-$(CONFIG_LIBERTAS) += libertas.o
|
||||
obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o
|
||||
obj-$(CONFIG_LIBERTAS_CS) += libertas_cs.o
|
||||
obj-$(CONFIG_LIBERTAS_SDIO) += libertas_sdio.o
|
||||
obj-$(CONFIG_LIBERTAS_SDIO) += libertas_sdio.o wifi_power.o
|
||||
obj-$(CONFIG_LIBERTAS_SPI) += libertas_spi.o
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,6 +34,7 @@
|
||||
#include <linux/mmc/card.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/mmc/sdio_ids.h>
|
||||
#include <linux/mmc/host.h>
|
||||
|
||||
#include "host.h"
|
||||
#include "decl.h"
|
||||
@@ -41,6 +42,9 @@
|
||||
#include "dev.h"
|
||||
#include "cmd.h"
|
||||
#include "if_sdio.h"
|
||||
#include "wifi_power.h"
|
||||
|
||||
extern struct mmc_host *wifi_mmc_host;
|
||||
|
||||
/* The if_sdio_remove() callback function is called when
|
||||
* user removes this module from kernel space or ejects
|
||||
@@ -1141,21 +1145,48 @@ static struct sdio_driver if_sdio_driver = {
|
||||
|
||||
//static int __init if_sdio_init_module2(void)
|
||||
//void if_sdio_init_module2(struct work_struct *work)
|
||||
int wifi_no_power_gpio = 0; /* 0-No 1-Yes */
|
||||
void if_sdio_init_module2(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_SDIO);
|
||||
int ret = 0,timeout;
|
||||
|
||||
wifi_sdio_func = NULL;
|
||||
wifi_no_power_gpio = 0;
|
||||
|
||||
//lbs_deb_enter(LBS_DEB_SDIO);
|
||||
|
||||
printk(KERN_INFO "libertas_sdio: Libertas SDIO driver\n");
|
||||
printk(KERN_INFO "libertas_sdio: Copyright Pierre Ossman\n");
|
||||
|
||||
ret = sdio_register_driver(&if_sdio_driver);
|
||||
|
||||
/* Clear the flag in case user removes the card. */
|
||||
user_rmmod = 0;
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
|
||||
///lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
|
||||
|
||||
ret = sdio_register_driver(&if_sdio_driver);
|
||||
|
||||
#ifdef WIFI_GPIO_POWER_CONTROL
|
||||
if (wifi_mmc_host->bus_ops != NULL) /* mmc/card is attached already. */
|
||||
{
|
||||
printk("SDIO maybe be attached already.\n");
|
||||
wifi_no_power_gpio = 1;
|
||||
return ;
|
||||
}
|
||||
|
||||
wifi_turn_on_card();
|
||||
wifi_power_up_wifi();
|
||||
|
||||
mmc_detect_change(wifi_mmc_host, 2);
|
||||
|
||||
for (timeout = 100; timeout >=0; timeout--)
|
||||
{
|
||||
if (wifi_sdio_func != NULL)
|
||||
break;
|
||||
msleep(50);
|
||||
}
|
||||
if (timeout <= 0)
|
||||
printk("No WiFi function card has been attached.\n");
|
||||
#endif
|
||||
return ;
|
||||
}
|
||||
EXPORT_SYMBOL(if_sdio_init_module2);
|
||||
|
||||
@@ -1173,20 +1204,47 @@ static int __init if_sdio_init_module(void)
|
||||
#endif
|
||||
|
||||
|
||||
static void __exit if_sdio_exit_module(void)
|
||||
void if_sdio_exit_module(void)
|
||||
{
|
||||
int timeout;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_SDIO);
|
||||
|
||||
/* Set the flag as user is removing this module. */
|
||||
user_rmmod = 1;
|
||||
|
||||
sdio_unregister_driver(&if_sdio_driver);
|
||||
|
||||
#ifdef WIFI_GPIO_POWER_CONTROL
|
||||
|
||||
if (wifi_no_power_gpio == 1)
|
||||
return;
|
||||
|
||||
if (wifi_mmc_host == NULL)
|
||||
{
|
||||
printk("No SDIO host is present.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wifi_power_down_wifi();
|
||||
wifi_turn_off_card();
|
||||
|
||||
mmc_detect_change(wifi_mmc_host, 2);
|
||||
|
||||
for (timeout = 50; timeout >= 0; timeout--)
|
||||
{
|
||||
msleep(100);
|
||||
if (wifi_mmc_host->bus_ops == NULL)
|
||||
break;
|
||||
}
|
||||
if (timeout < 0)
|
||||
printk("Fail to release SDIO card.\n");
|
||||
#endif
|
||||
lbs_deb_leave(LBS_DEB_SDIO);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(if_sdio_exit_module);
|
||||
//module_init(if_sdio_init_module);
|
||||
module_exit(if_sdio_exit_module);
|
||||
//module_exit(if_sdio_exit_module);
|
||||
|
||||
MODULE_DESCRIPTION("Libertas SDIO WLAN Driver");
|
||||
MODULE_AUTHOR("Pierre Ossman");
|
||||
|
||||
110
drivers/net/wireless/libertas/wifi_power.c
Normal file
110
drivers/net/wireless/libertas/wifi_power.c
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* wifi_power.c
|
||||
*
|
||||
* Power control for WIFI module.
|
||||
*
|
||||
* There are Power supply and Power Up/Down controls for WIFI typically.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "wifi_power.h"
|
||||
#if (WIFI_GPIO_POWER_CONTROL == 1)
|
||||
struct wifi_power power_gpio =
|
||||
{
|
||||
POWER_USE_GPIO, POWER_GPIO_IOMUX, GPIOH7_HSADCCLK_SEL_NAME,
|
||||
IOMUXB_GPIO1_D7, RK2818_PIN_PH7, GPIO_HIGH
|
||||
|
||||
};
|
||||
|
||||
struct wifi_power power_save_gpio =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
int wifi_gpio_operate(struct wifi_power *gpio, int flag)
|
||||
{
|
||||
int sensitive;
|
||||
|
||||
if (gpio->use_gpio == POWER_NOT_USE_GPIO)
|
||||
return 0;
|
||||
if (gpio->gpio_iomux == POWER_GPIO_IOMUX)
|
||||
{
|
||||
rk2818_mux_api_set(gpio->iomux_name, gpio->iomux_value);
|
||||
}
|
||||
|
||||
if (flag == GPIO_SWITCH_ON)
|
||||
sensitive = gpio->sensi_level;
|
||||
else
|
||||
sensitive = 1 - gpio->sensi_level;
|
||||
gpio_request(gpio->gpio_id, "wifi_power");
|
||||
gpio_direction_output(gpio->gpio_id,sensitive);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wifi_turn_on_card(void)
|
||||
{
|
||||
|
||||
if (wifi_gpio_operate(&power_gpio, GPIO_SWITCH_ON) != 0)
|
||||
{
|
||||
printk("Couldn't set GPIO [ON] successfully for power supply.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wifi_turn_off_card(void)
|
||||
{
|
||||
|
||||
if (wifi_gpio_operate(&power_gpio, GPIO_SWITCH_OFF) != 0)
|
||||
{
|
||||
printk("Couldn't set GPIO [OFF] successfully for power supply.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wifi_power_up_wifi(void)
|
||||
{
|
||||
|
||||
if (wifi_gpio_operate(&power_save_gpio, GPIO_SWITCH_ON) != 0)
|
||||
{
|
||||
printk("Couldn't set GPIO [ON] successfully for power up.\n");
|
||||
return -1;
|
||||
}
|
||||
mdelay(5);
|
||||
|
||||
if (wifi_gpio_operate(&power_save_gpio, GPIO_SWITCH_OFF) != 0)
|
||||
{
|
||||
printk("Couldn't set GPIO [ON] successfully for power up.\n");
|
||||
return -1;
|
||||
}
|
||||
msleep(150);
|
||||
|
||||
if (wifi_gpio_operate(&power_save_gpio, GPIO_SWITCH_ON) != 0)
|
||||
{
|
||||
printk("Couldn't set GPIO [ON] successfully for power up.\n");
|
||||
return -1;
|
||||
}
|
||||
msleep(50);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wifi_power_down_wifi(void)
|
||||
{
|
||||
if (wifi_gpio_operate(&power_save_gpio, GPIO_SWITCH_OFF) != 0)
|
||||
{
|
||||
printk("Couldn't set GPIO [OFF] successfully for power down.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WIFI_GPIO_POWER_CONTROL */
|
||||
|
||||
56
drivers/net/wireless/libertas/wifi_power.h
Normal file
56
drivers/net/wireless/libertas/wifi_power.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* wifi_power.h
|
||||
*
|
||||
* WIFI power control.
|
||||
*
|
||||
* Yongle Lai
|
||||
*/
|
||||
|
||||
#ifndef WIFI_POWER_H
|
||||
#define WIFI_POWER_H
|
||||
|
||||
#define WIFI_GPIO_POWER_CONTROL 1
|
||||
|
||||
#if (WIFI_GPIO_POWER_CONTROL == 1)
|
||||
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/iomux.h>
|
||||
|
||||
#define POWER_NOT_USE_GPIO 0
|
||||
#define POWER_USE_GPIO 1
|
||||
|
||||
#define POWER_GPIO_NOT_IOMUX 0
|
||||
#define POWER_GPIO_IOMUX 1
|
||||
|
||||
#define GPIO_SWITCH_OFF 0
|
||||
#define GPIO_SWITCH_ON 1
|
||||
|
||||
struct wifi_power
|
||||
{
|
||||
u8 use_gpio; /* If uses GPIO to control wifi power supply. 0 - no, 1 - yes. */
|
||||
u8 gpio_iomux; /* If the GPIO is iomux. 0 - no, 1 - yes. */
|
||||
char *iomux_name; /* IOMUX name */
|
||||
u8 iomux_value; /* IOMUX value - which function is choosen. */
|
||||
u8 gpio_id; /* GPIO number */
|
||||
u8 sensi_level; /* GPIO sensitive level. */
|
||||
};
|
||||
|
||||
/*
|
||||
* Power supply via control GPIO.
|
||||
*/
|
||||
#define POWER_VIA_GPIO 1 /* */
|
||||
#define POWER_GPIO_MUTEX 1 /* 1 - GPIO is a io mutexed IO */
|
||||
#define POWER_GPIO_MUTEX_NAME GPIOH6_IQ_SEL_NAME
|
||||
#define POWER_GPIO_MUTEXT_VAL IOMUXB_GPIO1_D6
|
||||
#define POWER_GPIO_ID GPIOPortH_Pin6
|
||||
#define POWER_LEVEL_SENSITIVE GPIO_HIGH
|
||||
|
||||
int wifi_turn_on_card(void);
|
||||
int wifi_turn_off_card(void);
|
||||
int wifi_power_up_wifi(void);
|
||||
int wifi_power_down_wifi(void);
|
||||
int wifi_power_reset(void);
|
||||
|
||||
#endif /* WIFI_GPIO_POWER_CONTROL */
|
||||
|
||||
#endif /* WIFI_POWER_H */
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
extern void if_sdio_init_module2(void);
|
||||
extern void if_sdio_exit_module(void);
|
||||
|
||||
static int wlan_init_module(void)
|
||||
{
|
||||
@@ -12,6 +13,12 @@ static int wlan_init_module(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(wlan_init_module);
|
||||
static int wlan_exit_module(void)
|
||||
{
|
||||
printk("move wlan driver..........\n");
|
||||
if_sdio_exit_module();
|
||||
|
||||
//module_exit(wlan_exit_module);
|
||||
return 0;
|
||||
}
|
||||
module_init(wlan_init_module);
|
||||
module_exit(wlan_exit_module);
|
||||
|
||||
Reference in New Issue
Block a user