wifi: add broadcom 4329 wireless lan driver support
authorlbt <lbt@rock-chips.com>
Thu, 9 Dec 2010 06:06:38 +0000 (14:06 +0800)
committerlbt <lbt@rock-chips.com>
Thu, 9 Dec 2010 06:06:38 +0000 (14:06 +0800)
arch/arm/configs/rk29_sdk_defconfig
arch/arm/mach-rk29/Kconfig
arch/arm/mach-rk29/board-rk29sdk.c
arch/arm/mach-rk29/include/mach/board.h
drivers/mmc/host/rk29_sdmmc.c [changed mode: 0644->0755]
drivers/net/wireless/Makefile
drivers/net/wireless/bcm4329/dhd_custom_gpio.c
drivers/net/wireless/bcm4329/dhd_linux.c

index 7e24eec06a4eb4a72e39c54a27db25914344c882..87d7ff9d535aaba99105c64f23bb2b947a7e6370 100755 (executable)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.32.9
-# Wed Dec  8 09:41:39 2010
+# Thu Dec  9 14:06:05 2010
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -194,6 +194,7 @@ CONFIG_MMU=y
 # CONFIG_ARCH_BCMRING is not set
 # CONFIG_ARCH_RK2818 is not set
 CONFIG_ARCH_RK29=y
+CONFIG_WIFI_CONTROL_FUNC=y
 CONFIG_MACH_RK29SDK=y
 
 #
@@ -412,7 +413,17 @@ CONFIG_ANDROID_PARANOID_NETWORK=y
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-# CONFIG_WIRELESS is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_CFG80211_DEFAULT_PS_VALUE=0
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -565,7 +576,14 @@ CONFIG_NETDEVICES=y
 # CONFIG_NET_ETHERNET is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
-# CONFIG_WLAN is not set
+CONFIG_WLAN=y
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_HOSTAP is not set
+CONFIG_BCM4329=m
+CONFIG_BCM4329_FW_PATH="/etc/firmware/fw_bcm4329.bin"
+CONFIG_BCM4329_NVRAM_PATH="/etc/firmware/nvram_bcm4329_B23.txt"
 
 #
 # Enable WiMAX (Networking options) to see the WiMAX drivers
index d2c7dd516f5368829458e45162e8ed68ec977c23..97ca0b7e00788d47c4d927de3e690ad1b55a4a02 100644 (file)
@@ -6,6 +6,11 @@ config MACH_RK29SDK
         help
          Support for the ROCKCHIP Board For Rk29 Sdk.
 
+config WIFI_CONTROL_FUNC
+        bool "Enable WiFi control function abstraction"
+        help
+          Enables Power/Reset/Carddetect function abstraction
+
 menu "RK29 VPU (Video Processing Unit) support"
 
 config RK29_VPU
index f498c4c9be37910dae89536f56bc1dd2234cb9b8..842ebed25f715e7e162be4b3642313e6b962b463 100755 (executable)
@@ -770,10 +770,15 @@ static int rk29_sdmmc1_cfg_gpio(void)
        rk29_mux_api_set(GPIO1C4_SDMMC1DATA1_NAME, GPIO1H_SDMMC1_DATA1);\r
        rk29_mux_api_set(GPIO1C5_SDMMC1DATA2_NAME, GPIO1H_SDMMC1_DATA2);\r
        rk29_mux_api_set(GPIO1C6_SDMMC1DATA3_NAME, GPIO1H_SDMMC1_DATA3);\r
-       rk29_mux_api_set(GPIO1C0_UART0CTSN_SDMMC1DETECTN_NAME, GPIO1H_SDMMC1_DETECT_N);\r
+       //rk29_mux_api_set(GPIO1C0_UART0CTSN_SDMMC1DETECTN_NAME, GPIO1H_SDMMC1_DETECT_N);\r
        return 0;\r
 }\r
-\r
+
+static int rk29sdk_wifi_status(struct device *dev);
+static int rk29sdk_wifi_status_register(void (*callback)(int card_presend, void *dev_id), void *dev_id);\r
+
+#define RK29SDK_WIFI_SDIO_CARD_DETECT_N    RK29_PIN1_PD6
+
 struct rk29_sdmmc_platform_data default_sdmmc1_data = {\r
        .host_ocr_avail = (MMC_VDD_25_26|MMC_VDD_26_27|MMC_VDD_27_28|MMC_VDD_28_29|\r
                                           MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32|\r
@@ -787,9 +792,126 @@ struct rk29_sdmmc_platform_data default_sdmmc1_data = {
 #else\r
        .use_dma = 0,\r
 #endif\r
+#ifdef CONFIG_WIFI_CONTROL_FUNC
+        .status = rk29sdk_wifi_status,
+        .register_status_notify = rk29sdk_wifi_status_register,
+#endif
+        .detect_irq = RK29SDK_WIFI_SDIO_CARD_DETECT_N,
 };\r
 #endif\r
-\r
+
+#ifdef CONFIG_WIFI_CONTROL_FUNC
+#define RK29SDK_WIFI_BT_GPIO_POWER_N       RK29_PIN5_PD6
+#define RK29SDK_WIFI_GPIO_RESET_N          RK29_PIN6_PC0
+#define RK29SDK_BT_GPIO_RESET_N            RK29_PIN6_PC4
+
+static int rk29sdk_wifi_cd = 0;   /* wifi virtual 'card detect' status */
+static void (*wifi_status_cb)(int card_present, void *dev_id);
+static void *wifi_status_cb_devid;
+int rk29sdk_wifi_power_state = 0;
+int rk29sdk_bt_power_state = 0;
+
+static int rk29sdk_wifi_status(struct device *dev)
+{
+        return rk29sdk_wifi_cd;
+}
+
+static int rk29sdk_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 rk29sdk_wifi_bt_gpio_control_init(void)
+{
+    if (gpio_request(RK29SDK_WIFI_BT_GPIO_POWER_N, "wifi_bt_power")) {
+           pr_info("%s: request wifi_bt power gpio failed\n", __func__);
+           return -1; 
+    }
+   
+    if (gpio_request(RK29SDK_WIFI_GPIO_RESET_N, "wifi reset")) {
+           pr_info("%s: request wifi reset gpio failed\n", __func__);
+           gpio_free(RK29SDK_WIFI_BT_GPIO_POWER_N);
+           return -1;
+    }
+   
+    if (gpio_request(RK29SDK_BT_GPIO_RESET_N, "bt reset")) {
+          pr_info("%s: request bt reset gpio failed\n", __func__);
+          gpio_free(RK29SDK_WIFI_GPIO_RESET_N);
+          return -1;
+    }
+   
+    gpio_direction_output(RK29SDK_WIFI_BT_GPIO_POWER_N, GPIO_LOW);
+    gpio_direction_output(RK29SDK_WIFI_GPIO_RESET_N,    GPIO_LOW);
+    gpio_direction_output(RK29SDK_BT_GPIO_RESET_N,      GPIO_LOW); 
+    
+    pr_info("%s: init finished\n",__func__);
+   
+    return 0;
+}
+
+static int rk29sdk_wifi_power(int on)
+{
+        pr_info("%s: %d\n", __func__, on);
+        if (on){
+                gpio_set_value(RK29SDK_WIFI_BT_GPIO_POWER_N, on);
+                mdelay(100);
+                pr_info("wifi turn on power\n");
+        }else{
+                if (!rk29sdk_bt_power_state){
+                        gpio_set_value(RK29SDK_WIFI_BT_GPIO_POWER_N, on);
+                        mdelay(100);
+                        pr_info("wifi shut off power\n");
+                }else
+                {
+                        pr_info("wifi shouldn't shut off power, bt is using it!\n");
+                }
+
+        }
+
+        rk29sdk_wifi_power_state = on;
+        return 0;
+}
+
+static int rk29sdk_wifi_reset_state;
+static int rk29sdk_wifi_reset(int on)
+{
+        pr_info("%s: %d\n", __func__, on);
+        gpio_set_value(RK29SDK_WIFI_GPIO_RESET_N, on);
+        mdelay(100);
+        rk29sdk_wifi_reset_state = on;
+        return 0;
+}
+
+static int rk29sdk_wifi_set_carddetect(int val)
+{
+        pr_info("%s:%d\n", __func__, val);
+        rk29sdk_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 rk29sdk_wifi_control = {
+        .set_power = rk29sdk_wifi_power,
+        .set_reset = rk29sdk_wifi_reset,
+        .set_carddetect = rk29sdk_wifi_set_carddetect,
+};
+static struct platform_device rk29sdk_wifi_device = {
+        .name = "bcm4329_wlan",
+        .id = 1,
+        .dev = {
+                .platform_data = &rk29sdk_wifi_control,
+         },
+};
+#endif
+
 #ifdef CONFIG_VIVANTE\r
 static struct resource resources_gpu[] = {\r
     [0] = {\r
@@ -920,6 +1042,9 @@ static struct platform_device *devices[] __initdata = {
        &rk29xx_device_nand,\r
 #endif\r
 \r
+#ifdef CONFIG_WIFI_CONTROL_FUNC
+        &rk29sdk_wifi_device,
+#endif
 #ifdef CONFIG_MTD_NAND_RK29\r
        &rk29_device_nand,\r
 #endif\r
@@ -1155,6 +1280,8 @@ static void __init machine_rk29_board_init(void)
 \r
                gpio_set_value(POWER_ON_PIN, 1);\r
                gpio_direction_output(POWER_ON_PIN, 1);\r
+
+                rk29sdk_wifi_bt_gpio_control_init();
 \r
                platform_add_devices(devices, ARRAY_SIZE(devices));\r
 #ifdef CONFIG_I2C0_RK29\r
index 905d218fd9de244079c37cda631fe8b1c39ba9a9..b627bc0a9056667a59218093dad54119a58d3566 100755 (executable)
@@ -77,6 +77,13 @@ struct rk29_bl_info{
     struct notifier_block freq_transition;
 };
 
+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 rk29_sdmmc_platform_data {
        unsigned int host_caps;
        unsigned int host_ocr_avail;
@@ -86,6 +93,7 @@ struct rk29_sdmmc_platform_data {
        int (*io_deinit)(void);
        int (*status)(struct device *);
        int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
+        int detect_irq;
 };
 struct rk29_i2c_platform_data {
        int     bus_num;        
old mode 100644 (file)
new mode 100755 (executable)
index 28360d3..abce25f
@@ -1021,6 +1021,42 @@ static void rk29_sdmmc_cmd_interrupt(struct rk29_sdmmc *host, u32 status)
        tasklet_schedule(&host->tasklet);
 }
 
+static int rk29_sdmmc1_card_get_cd(struct mmc_host *mmc)
+{
+        struct rk29_sdmmc *host = mmc_priv(mmc);
+        struct rk29_sdmmc_platform_data *pdata = host->pdev->dev.platform_data;
+        return gpio_get_value(pdata->detect_irq);
+}
+
+static int rk29_sdmmc1_card_change_cd_trigger_type(struct mmc_host *mmc, unsigned int type)
+{
+       struct rk29_sdmmc *host = mmc_priv(mmc);
+       struct rk29_sdmmc_platform_data *pdata = host->pdev->dev.platform_data;
+       return set_irq_type(gpio_to_irq(pdata->detect_irq), type);
+}
+
+
+static irqreturn_t rk29_sdmmc1_card_detect_interrupt(int irq, void *dev_id)
+{
+       struct rk29_sdmmc *host = dev_id;
+       bool present, present_old; 
+       
+       present = rk29_sdmmc1_card_get_cd(host->mmc);
+       present_old = test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+       if (present != present_old) {
+             if (present != 0) {
+                  set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+             } else {
+                  clear_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+             }
+             mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(200));
+       }
+       rk29_sdmmc1_card_change_cd_trigger_type(host->mmc, (present ? IRQF_TRIGGER_FALLING: IRQF_TRIGGER_RISING)); 
+   
+       return IRQ_HANDLED;
+
+}
+
 static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
 {
        struct rk29_sdmmc       *host = dev_id;
@@ -1096,6 +1132,10 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
                    rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_CMD_DONE);  //  clear interrupt
                    rk29_sdmmc_cmd_interrupt(host, status);
                }
+               if(pending & SDMMC_INT_SDIO) {
+                               rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_SDIO);
+                               mmc_signal_sdio_irq(host->mmc);
+               }
        } while (pass_count++ < 5);
        
        spin_unlock(&host->lock);
@@ -1112,7 +1152,7 @@ static void rk29_sdmmc_detect_change(unsigned long data)
 {
        struct mmc_request *mrq;
        struct rk29_sdmmc *host = (struct rk29_sdmmc *)data;;
-
+   
        smp_rmb();
        if (test_bit(RK29_SDMMC_SHUTDOWN, &host->flags))
                return;         
@@ -1229,7 +1269,6 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
        clk_enable(host->clk);
        clk_enable(clk_get(&pdev->dev, "sdmmc_ahb"));
        host->bus_hz = clk_get_rate(host->clk);  ///40000000;  ////cgu_get_clk_freq(CGU_SB_SD_MMC_CCLK_IN_ID); 
-       printk("Enter:%s %d host->bus_hz =%d\n",__FUNCTION__,__LINE__,host->bus_hz);
 
        /* reset all blocks */
        rk29_sdmmc_write(host->regs, SDMMC_CTRL,(SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET));
@@ -1251,6 +1290,22 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
        ret = request_irq(irq, rk29_sdmmc_interrupt, 0, dev_name(&pdev->dev), host);
        if (ret)
            goto err_dmaunmap;
+        
+        /* register sdmmc1 card detect interrupt route */ 
+        if ((pdev->id == 1) && (pdata->detect_irq != 0)) {
+            irq = gpio_to_irq(pdata->detect_irq);
+            if (irq < 0)  {
+               printk("%s: request gpio irq failed\n", __FUNCTION__);
+               goto err_dmaunmap;
+            }
+            
+            ret = request_irq(irq, rk29_sdmmc1_card_detect_interrupt, IRQF_TRIGGER_RISING, dev_name(&pdev->dev), host);
+            if (ret) {
+               printk("%s: sdmmc1 request detect interrupt failed\n", __FUNCTION__);
+               goto err_dmaunmap;
+            }
+             
+        }
        platform_set_drvdata(pdev, host);       
        mmc->ops = &rk29_sdmmc_ops[pdev->id];
        mmc->f_min = host->bus_hz/510;
@@ -1268,6 +1323,7 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
                set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
        else
                clear_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+        
 
        mmc_add_host(mmc);
 #if defined (CONFIG_DEBUG_FS)
index 63665859a02900b0b91e77d1893c55a0674670b8..81e81f7b5250d089407ae216c0dbbf6141941a77 100644 (file)
@@ -63,4 +63,4 @@ obj-$(CONFIG_WL12XX)  += wl12xx/
 
 obj-$(CONFIG_IWM)      += iwmc3200wifi/
 obj-$(CONFIG_BCM4329)   += bcm4329/
-obj-m  += wlan/
+#obj-m += wlan/
index 35d0b97fb4df04e64b31de2d743c8938fa0a156d..f2b7adbed0d32421f577328571802131f6094bb8 100644 (file)
@@ -48,8 +48,10 @@ int wifi_set_power(int on, unsigned long msec);
 int wifi_get_irq_number(unsigned long *irq_flags_ptr);
 #endif
 
+#if defined(CONFIG_WIFI_CONTROL_FUNC)
 int wifi_set_power(int on, unsigned long msec);
 int wifi_set_reset(int on, unsigned long msec);
+#endif
 
 #if defined(OOB_INTR_ONLY)
 
@@ -117,8 +119,10 @@ dhd_customer_gpio_wlan_ctrl(int onoff)
 #ifdef CUSTOMER_HW2
                        wifi_set_power(0, 0);
 #endif
+#if defined(CONFIG_WIFI_CONTROL_FUNC)
                        wifi_set_power(0, 0);
                         wifi_set_reset(0, 0);
+#endif
                        WL_ERROR(("=========== WLAN placed in RESET ========\n"));
                break;
 
@@ -131,8 +135,10 @@ dhd_customer_gpio_wlan_ctrl(int onoff)
 #ifdef CUSTOMER_HW2
                        wifi_set_power(1, 0);
 #endif
+#if defined(CONFIG_WIFI_CONTROL_FUNC)
                        wifi_set_power(1, 0);
                         wifi_set_reset(1, 0);
+#endif
                        WL_ERROR(("=========== WLAN going back to live  ========\n"));
                break;
 
index 164b170abc14526ee23979f470bf71958a4999d4..e610b4b0d7eafe46e32e87646ac1ab6d1cbd793c 100644 (file)
@@ -2387,7 +2387,7 @@ dhd_detach(dhd_pub_t *dhdp)
        }
 }
 }
-static void 
+static void __exit
 dhd_module_cleanup(void)
 {
        DHD_TRACE(("%s: Enter\n", __FUNCTION__));
@@ -2401,7 +2401,7 @@ dhd_module_cleanup(void)
 }
 
 
-static int 
+static int __init
 dhd_module_init(void)
 {
        int error;
@@ -2474,21 +2474,8 @@ faild:
        return -EINVAL;
 }
 
-//module_init(dhd_module_init);
-//module_exit(dhd_module_cleanup);
-
-int if_sdio_init_module2(void)
-{
-    return dhd_module_init();
-}
-
-void if_sdio_exit_module(void)
-{
-   dhd_module_cleanup();
-}
-
-EXPORT_SYMBOL(if_sdio_init_module2);
-EXPORT_SYMBOL(if_sdio_exit_module);
+module_init(dhd_module_init);
+module_exit(dhd_module_cleanup);
 
 /*
  * OS specific functions required to implement DHD driver in OS independent way