net:wireless:bcm4329: add wifi power gpio control. wifi devce is on the board, it...
authorroot <root@lbt-desktop.(none)>
Mon, 30 Aug 2010 11:28:56 +0000 (19:28 +0800)
committerroot <root@lbt-desktop.(none)>
Mon, 30 Aug 2010 11:32:03 +0000 (19:32 +0800)
                      we simulate card detection by power/reset on or off the card.

arch/arm/mach-rk2818/Kconfig
arch/arm/mach-rk2818/board-infosdk.c
arch/arm/mach-rk2818/include/mach/board.h
drivers/mmc/host/rk2818-sdmmc.c
drivers/net/wireless/bcm4329/Makefile
drivers/net/wireless/bcm4329/bcmsdh_sdmmc_linux.c
drivers/net/wireless/bcm4329/dhd_linux.c
drivers/net/wireless/bcm4329/wifi_power.c [deleted file]
drivers/net/wireless/bcm4329/wifi_power.h [deleted file]

index 58ed1edb186b3e27c51f2f1247cae417e8f1bc9b..80f6dc76efd7ca6c3f73de0332a6490fbff563d9 100644 (file)
@@ -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
index 9f482fbb3a179e872467925c05007090cb238c6b..ce66c041a0cd84b3566a10f9229f903bdbf32360 100755 (executable)
@@ -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,
index a12827b85b7757407bbb15532e4f4f4e4e9b069a..da9cd0960895289b845ebbaee347de78984c63f8 100755 (executable)
@@ -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 {
index 765f51b07994c0e552620406ca9c97f972ff7d7c..6cd5b6f22295b5049035b166367806e1b1bd6ff7 100755 (executable)
@@ -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);
index 34625ba387ab1f991a7fd911f434003d2d1ba893..6e295d49286b8c43e6eb12b7823c486aa39e7e25 100755 (executable)
@@ -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
 
index 7175000ce0896d0b7881baf01a0531119fd9d282..5260b482a8df46d98dd8fb709657225c1408ecc9 100644 (file)
 
 #include <dhd_dbg.h>
 
-#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;
 }
 
index 80aa6701f4593d08dd6b2143bcc0a3fa300fd70f..715913d71d7ccf5542531e3adb1463deb1f3ac1a 100644 (file)
@@ -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 <linux/platform_device.h>
 #endif
 #include <dhd_proto.h>
 #include <dhd_dbg.h>
 
-
-#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
-#include <linux/wifi_tiwlan.h>
+#if defined(CONFIG_WIFI_CONTROL_FUNC)
+#include <mach/board.h>
 
 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 (file)
index 23dfd0d..0000000
+++ /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 <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#if defined(CONFIG_MACH_RAHO)
-#include <linux/i2c.h>
-#include <mach/spi_fpga.h>
-#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 (file)
index d90a510..0000000
+++ /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 <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 */