From 13fd8332dfe65106360c3954599582e926273e99 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 30 Aug 2010 19:28:56 +0800 Subject: [PATCH] net:wireless:bcm4329: add wifi power gpio control. wifi devce is on the board, it has no real card insert/remove action. we simulate card detection by power/reset on or off the card. --- arch/arm/mach-rk2818/Kconfig | 4 + arch/arm/mach-rk2818/board-infosdk.c | 85 +++++++++-- arch/arm/mach-rk2818/include/mach/board.h | 18 +++ drivers/mmc/host/rk2818-sdmmc.c | 40 ++++++ drivers/net/wireless/bcm4329/Makefile | 2 +- .../net/wireless/bcm4329/bcmsdh_sdmmc_linux.c | 38 +---- drivers/net/wireless/bcm4329/dhd_linux.c | 27 ++-- drivers/net/wireless/bcm4329/wifi_power.c | 135 ------------------ drivers/net/wireless/bcm4329/wifi_power.h | 56 -------- 9 files changed, 152 insertions(+), 253 deletions(-) delete mode 100644 drivers/net/wireless/bcm4329/wifi_power.c delete mode 100644 drivers/net/wireless/bcm4329/wifi_power.h diff --git a/arch/arm/mach-rk2818/Kconfig b/arch/arm/mach-rk2818/Kconfig index 58ed1edb186b..80f6dc76efd7 100644 --- a/arch/arm/mach-rk2818/Kconfig +++ b/arch/arm/mach-rk2818/Kconfig @@ -50,4 +50,8 @@ config RK28_USB_WAKE Select this option if you want to have your system wake up from USB. +config WIFI_CONTROL_FUNC + bool "Enable WiFi control function abstraction" + help + Enables Power/Reset/Carddetect function abstraction endif diff --git a/arch/arm/mach-rk2818/board-infosdk.c b/arch/arm/mach-rk2818/board-infosdk.c index 9f482fbb3a17..ce66c041a0cd 100755 --- a/arch/arm/mach-rk2818/board-infosdk.c +++ b/arch/arm/mach-rk2818/board-infosdk.c @@ -160,6 +160,7 @@ static struct map_desc rk2818_io_desc[] __initdata = { * SDMMC devices *author: kfx *****************************************************************************************/ + static int rk2818_sdmmc0_io_init(void) { rk2818_mux_api_set(GPIOF3_APWM1_MMC0DETN_NAME, IOMUXA_SDMMC1_DETECT_N); @@ -191,6 +192,9 @@ struct rk2818_sdmmc_platform_data default_sdmmc0_data = { .use_dma = 0, #endif }; + +static int info_wifi_status(struct device *dev); +static int info_wifi_status_register(void (*callback)(int card_presend, void *dev_id), void *dev_id); struct rk2818_sdmmc_platform_data default_sdmmc1_data = { .host_ocr_avail = (MMC_VDD_26_27|MMC_VDD_27_28|MMC_VDD_28_29| MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32| @@ -205,8 +209,74 @@ struct rk2818_sdmmc_platform_data default_sdmmc1_data = { #else .use_dma = 0, #endif + .status = info_wifi_status, + .register_status_notify = info_wifi_status_register, }; +static int info_wifi_cd; /* wifi virtual 'card detect' status */ +static void (*wifi_status_cb)(int card_present, void *dev_id); +static void *wifi_status_cb_devid; + +static int info_wifi_status(struct device *dev) +{ + return info_wifi_cd; +} + +static int info_wifi_status_register(void (*callback)(int card_present, void *dev_id), void *dev_id) +{ + if(wifi_status_cb) + return -EAGAIN; + wifi_status_cb = callback; + wifi_status_cb_devid = dev_id; + return 0; +} + +static int info_wifi_power_state; +static int info_wifi_power(int on) +{ + pr_info("%s: %d\n", __func__, on); + gpio_set_value(TCA6424_P25, on); + mdelay(100); + info_wifi_power_state = on; + return 0; +} + +static int info_wifi_reset_state; +static int info_wifi_reset(int on) +{ + pr_info("%s: %d\n", __func__, on); + gpio_set_value(TCA6424_P27, on); + mdelay(100); + info_wifi_reset_state = on; + return 0; +} + +static int info_wifi_set_carddetect(int val) +{ + pr_info("%s:%d\n", __func__, val); + info_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 info_wifi_control = { + .set_power = info_wifi_power, + .set_reset = info_wifi_reset, + .set_carddetect = info_wifi_set_carddetect, +}; +static struct platform_device info_wifi_device = { + .name = "bcm4329_wlan", + .id = 1, + .dev = { + .platform_data = &info_wifi_control, + }, +}; + + /***************************************************************************************** * extern gpio devices *author: xxx @@ -317,23 +387,13 @@ struct rk2818_gpio_expander_info extgpio_tca6424_settinginfo[] = { { .gpio_num = TCA6424_P25, //wifi reg on .pin_type = GPIO_OUT, - .pin_value = GPIO_HIGH, + .pin_value = GPIO_LOW, }, { .gpio_num = TCA6424_P27, //wifi reset .pin_type = GPIO_OUT, - .pin_value = GPIO_HIGH, + .pin_value = GPIO_LOW, }, -{ - .gpio_num = TCA6424_P25, //wifi reg on - .pin_type = GPIO_OUT, - .pin_value = GPIO_HIGH, - }, - { - .gpio_num = TCA6424_P27, //wifi reset - .pin_type = GPIO_OUT, - .pin_value = GPIO_HIGH, - }, }; void tca6424_reset_itr(void) @@ -1341,6 +1401,7 @@ static struct platform_device *devices[] __initdata = { #endif #ifdef CONFIG_SDMMC1_RK2818 &rk2818_device_sdmmc1, + &info_wifi_device, #endif &rk2818_device_spim, &rk2818_device_i2s, diff --git a/arch/arm/mach-rk2818/include/mach/board.h b/arch/arm/mach-rk2818/include/mach/board.h index a12827b85b77..da9cd0960895 100755 --- a/arch/arm/mach-rk2818/include/mach/board.h +++ b/arch/arm/mach-rk2818/include/mach/board.h @@ -41,6 +41,24 @@ struct rk2818_sdmmc_platform_data { char dma_name[8]; int (*io_init)(void); int (*io_deinit)(void); + int (*status)(struct device *); + int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id); +}; + +struct wifi_platform_data { + int (*set_power)(int val); + int (*set_reset)(int val); + int (*set_carddetect)(int val); + void *(*mem_prealloc)(int section, unsigned long size); +}; + +struct wifi_power_gpio_control_data { + unsigned int use_gpio; /* If uses GPIO to control wifi power supply. 0 - no, 1 - yes. */ + unsigned int gpio_iomux; /* If the GPIO is iomux. 0 - no, 1 - yes. */ + char *iomux_name; /* IOMUX name */ + unsigned int iomux_value; /* IOMUX value - which function is choosen. */ + unsigned int gpio_id; /* GPIO number */ + unsigned int sensi_level; /* GPIO sensitive level. */ }; struct rk2818_i2c_spi_data { diff --git a/drivers/mmc/host/rk2818-sdmmc.c b/drivers/mmc/host/rk2818-sdmmc.c index 765f51b07994..6cd5b6f22295 100755 --- a/drivers/mmc/host/rk2818-sdmmc.c +++ b/drivers/mmc/host/rk2818-sdmmc.c @@ -119,6 +119,7 @@ struct rk2818_sdmmc_host { struct mmc_command stop_mannual; struct timer_list detect_timer; + unsigned int oldstatus; /* save old status */ }; #define MMC_DEBUG 0 @@ -1717,6 +1718,40 @@ static int rk28_sdmmc0_add_attr( struct platform_device *pdev ) return result; } +static void rk2818_sdmmc_check_status(unsigned long data) +{ + struct rk2818_sdmmc_host *host = (struct rk2818_sdmmc_host *)data; + struct rk2818_sdmmc_platform_data *pdata = host->pdev->dev.platform_data; + unsigned int status; + + if (!pdata->status) + { + mmc_detect_change(host->mmc, 0); + return; + } + + status = pdata->status(mmc_dev(host->mmc)); + + if (status ^ host->oldstatus) + { + pr_info("%s: slot status change detected(%d-%d)\n",mmc_hostname(host->mmc), host->oldstatus, status); + if (status) + mmc_detect_change(host->mmc, 100); + else + mmc_detect_change(host->mmc, 0); + } + + host->oldstatus = status; + +} + +static void rk2818_sdmmc_status_notify_cb(int card_present, void *dev_id) +{ + struct rk2818_sdmmc_host *host = dev_id; + printk(KERN_INFO "%s, card_present %d\n", mmc_hostname(host->mmc), card_present); + rk2818_sdmmc_check_status((unsigned long)host); +} + /*-------------------end of add communication interface with applications ---------------------------------*/ static int rk2818_sdmmc_probe(struct platform_device *pdev) @@ -1782,6 +1817,11 @@ static int rk2818_sdmmc_probe(struct platform_device *pdev) goto err_free_map; } + /* setup wifi card detect change */ + if (pdata->register_status_notify) + { + pdata->register_status_notify(rk2818_sdmmc_status_notify_cb, host); + } spin_lock_init(&host->lock); INIT_LIST_HEAD(&host->queue); diff --git a/drivers/net/wireless/bcm4329/Makefile b/drivers/net/wireless/bcm4329/Makefile index 34625ba387ab..6e295d49286b 100755 --- a/drivers/net/wireless/bcm4329/Makefile +++ b/drivers/net/wireless/bcm4329/Makefile @@ -19,7 +19,7 @@ shared-objs := aiutils.o bcmutils.o bcmwifi.o hndpmu.o \ wl-objs := wl_iw.o -bcm4329-objs := $(bcmsdio-objs) $(dhd-objs) $(shared-objs) $(wl-objs) wifi_power.o +bcm4329-objs := $(bcmsdio-objs) $(dhd-objs) $(shared-objs) $(wl-objs) obj-$(CONFIG_BCM4329) += bcm4329.o diff --git a/drivers/net/wireless/bcm4329/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcm4329/bcmsdh_sdmmc_linux.c index 7175000ce089..5260b482a8df 100644 --- a/drivers/net/wireless/bcm4329/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcm4329/bcmsdh_sdmmc_linux.c @@ -52,18 +52,9 @@ #include -#include "wifi_power.h" - extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd); extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd); -extern struct mmc_host *wifi_mmc_host; -extern void mmc_detect_change(struct mmc_host *host, unsigned long delay); -extern int wifi_turn_on_card(void); -extern int wifi_turn_off_card(void); -extern int wifi_power_up_wifi(void); -extern int wifi_power_down_wifi(void); - int sdio_function_init(void); void sdio_function_cleanup(void); @@ -241,7 +232,7 @@ MODULE_AUTHOR(AUTHOR); */ int sdio_function_init(void) { - int error = 0, timeout; + int error = 0; sd_trace(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__)); gInstance = kzalloc(sizeof(BCMSDH_SDMMC_INSTANCE), GFP_KERNEL); @@ -251,33 +242,6 @@ int sdio_function_init(void) bzero(&sdmmc_dev, sizeof(sdmmc_dev)); error = sdio_register_driver(&bcmsdh_sdmmc_driver); -#ifdef WIFI_GPIO_POWER_CONTROL - - if (wifi_mmc_host->bus_ops != NULL) - { - printk(KERN_INFO "SDIO card maybe be attached already\n"); - return 0; - } - - wifi_turn_on_card(); - wifi_power_up_wifi(); - - mmc_detect_change(wifi_mmc_host, 5); - - timeout = 100; - - do{ - if (gInstance->func[0] != NULL) - break; - msleep(20); - }while(--timeout); - - if (timeout <= 0){ - printk(KERN_INFO "no wifi card is found\n"); - error = 0; - } -#endif - return error; } diff --git a/drivers/net/wireless/bcm4329/dhd_linux.c b/drivers/net/wireless/bcm4329/dhd_linux.c index 80aa6701f459..715913d71d7c 100644 --- a/drivers/net/wireless/bcm4329/dhd_linux.c +++ b/drivers/net/wireless/bcm4329/dhd_linux.c @@ -25,6 +25,7 @@ * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.89 2010/07/21 18:07:11 Exp $ */ + #ifdef CONFIG_WIFI_CONTROL_FUNC #include #endif @@ -58,17 +59,16 @@ #include #include - -#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) -#include +#if defined(CONFIG_WIFI_CONTROL_FUNC) +#include struct semaphore wifi_control_sem; struct dhd_bus *g_bus; static struct wifi_platform_data *wifi_control_data = NULL; -static struct resource *wifi_irqres = NULL; - +//static struct resource *wifi_irqres = NULL; +#if 0 int wifi_get_irq_number(unsigned long *irq_flags_ptr) { if (wifi_irqres) { @@ -81,6 +81,7 @@ int wifi_get_irq_number(unsigned long *irq_flags_ptr) return -1; #endif } +#endif int wifi_set_carddetect(int on) { @@ -118,10 +119,11 @@ static int wifi_probe(struct platform_device *pdev) (struct wifi_platform_data *)(pdev->dev.platform_data); printk("## %s\n", __FUNCTION__); - wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcm4329_wlan_irq"); +// wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcm4329_wlan_irq"); wifi_control_data = wifi_ctrl; wifi_set_power(1, 0); /* Power On */ + wifi_set_reset(1, 0); wifi_set_carddetect(1); /* CardDetect (0->1) */ up(&wifi_control_sem); @@ -135,9 +137,10 @@ static int wifi_remove(struct platform_device *pdev) printk("## %s\n", __FUNCTION__); wifi_control_data = wifi_ctrl; - + + wifi_set_power(0, 0); + wifi_set_reset(0, 0); wifi_set_carddetect(0); /* CardDetect (1->0) */ - wifi_set_power(0, 0); /* Power Off */ up(&wifi_control_sem); return 0; @@ -174,7 +177,7 @@ void wifi_del_dev(void) DHD_TRACE(("## Unregister platform_driver_register\n")); platform_driver_unregister(&wifi_device); } -#endif /* defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */ +#endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) @@ -2012,7 +2015,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) */ memcpy(netdev_priv(net), &dhd, sizeof(dhd)); -#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) +#if defined(CONFIG_WIFI_CONTROL_FUNC) g_bus = bus; #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) && 1 @@ -2390,7 +2393,7 @@ dhd_module_cleanup(void) DHD_TRACE(("%s: Enter\n", __FUNCTION__)); dhd_bus_unregister(); -#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) +#if defined(CONFIG_WIFI_CONTROL_FUNC) wifi_del_dev(); #endif /* Call customer gpio to turn off power with WL_REG_ON signal */ @@ -2421,7 +2424,7 @@ dhd_module_init(void) /* Call customer gpio to turn on power with WL_REG_ON signal */ dhd_customer_gpio_wlan_ctrl(WLAN_POWER_ON); -#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) +#if defined(CONFIG_WIFI_CONTROL_FUNC) sema_init(&wifi_control_sem, 0); error = wifi_add_dev(); diff --git a/drivers/net/wireless/bcm4329/wifi_power.c b/drivers/net/wireless/bcm4329/wifi_power.c deleted file mode 100644 index 23dfd0dd9709..000000000000 --- a/drivers/net/wireless/bcm4329/wifi_power.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * wifi_power.c - * - * Power control for WIFI module. - * - * There are Power supply and Power Up/Down controls for WIFI typically. - */ -#include -#include -#include -#if defined(CONFIG_MACH_RAHO) -#include -#include -#elif defined(CONFIG_MACH_RK2818INFO) -/* include gpio definition header file */ -#endif -#include "wifi_power.h" - -#if (WIFI_GPIO_POWER_CONTROL == 1) -#if defined(CONFIG_MACH_RAHO) -struct wifi_power power_gpio = -{ - POWER_USE_GPIO, 0, 0, 0, SPI_GPIO_P1_06, SPI_GPIO_HIGH -}; - -struct wifi_power power_save_gpio = -{ - POWER_USE_GPIO, 0, 0, 0, SPI_GPIO_P1_03, SPI_GPIO_HIGH -}; -#elif defined(CONFIG_MACH_RK2818INFO) -struct wifi_power power_gpio = { - 0,0,0,0,0,0 -}; - -struct wifi_power power_save_gpio = { - 0,0,0,0,0,0 -}; -#endif - -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 defined(CONFIG_MACH_RAHO) - spi_gpio_set_pindirection(gpio->gpio_id, SPI_GPIO_OUT); -#elif defined(CONFIG_MACH_RK2818INFO) - /* set pin direction */ -#endif - - if (flag == GPIO_SWITCH_ON) - sensitive = gpio->sensi_level; - else - sensitive = 1 - gpio->sensi_level; - -#if defined(CONFIG_MACH_RAHO) - spi_gpio_set_pinlevel(gpio->gpio_id, sensitive); -#elif defined(CONFIG_MACH_RK2818INFO) - /* set pin level */ -#endif - - 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 */ - diff --git a/drivers/net/wireless/bcm4329/wifi_power.h b/drivers/net/wireless/bcm4329/wifi_power.h deleted file mode 100644 index d90a510ff15a..000000000000 --- a/drivers/net/wireless/bcm4329/wifi_power.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 -#include - -#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 */ -- 2.34.1