wifi: add pci reinit and remove_reinit function [4/7]
authorWeiguang Ruan <Weiguang.ruan@amlogic.com>
Thu, 31 Aug 2017 08:16:54 +0000 (16:16 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Thu, 7 Sep 2017 03:04:21 +0000 (20:04 -0700)
PD#148564: add pci reinit and remove_reinit function

pci_reinit: power on/off then rescan pci device.

pci_remove_reinit: remove pci device first,
then power on/off, rescan pci device.

Change-Id: I03f3ceb7b526ce686b835eaacddbbd7f2ed2c384
Signed-off-by: Weiguang Ruan <Weiguang.ruan@amlogic.com>
arch/arm64/boot/dts/amlogic/axg_s400.dts
arch/arm64/boot/dts/amlogic/axg_s400_v03.dts
drivers/amlogic/wifi/wifi_dt.c
include/linux/amlogic/wifi_dt.h

index 708613b..af4ccef 100644 (file)
                interrupt_pin = <&gpio       GPIOX_6       GPIO_ACTIVE_HIGH>;
                interrupts = <  0 67 4>;
                irq_trigger_type = "GPIO_IRQ_LOW";
+               power_on_pin2 = <&gpio       GPIOX_16       GPIO_ACTIVE_HIGH>;
                power_on_pin = <&gpio       GPIOX_7       GPIO_ACTIVE_HIGH>;
                dhd_static_buf; //if use bcm wifi, config dhd_static_buf
                pinctrl-names = "default";
index 4a3fff1..803894e 100644 (file)
                interrupt_pin = <&gpio       GPIOX_6       GPIO_ACTIVE_HIGH>;
                interrupts = <  0 67 4>;
                irq_trigger_type = "GPIO_IRQ_LOW";
+               power_on_pin2 = <&gpio       GPIOX_16       GPIO_ACTIVE_HIGH>;
                power_on_pin = <&gpio       GPIOX_7       GPIO_ACTIVE_HIGH>;
                dhd_static_buf; //if use bcm wifi, config dhd_static_buf
                pinctrl-names = "default";
index a8923c7..aaadd98 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 #include <linux/pwm.h>
+#include <linux/pci.h>
 #include <linux/amlogic/pwm_meson.h>
 #include "../../gpio/gpiolib.h"
 #define OWNER_NAME "sdio_wifi"
@@ -92,8 +93,8 @@ struct wifi_plat_info {
 
 #define USB_POWER_UP    _IO('m', 1)
 #define USB_POWER_DOWN  _IO('m', 2)
-#define SDIO_POWER_UP    _IO('m', 3)
-#define SDIO_POWER_DOWN  _IO('m', 4)
+#define WIFI_POWER_UP    _IO('m', 3)
+#define WIFI_POWER_DOWN  _IO('m', 4)
 #define SDIO_GET_DEV_TYPE  _IO('m', 5)
 static struct wifi_plat_info wifi_info;
 static dev_t wifi_power_devno;
@@ -242,6 +243,68 @@ static int  wifi_power_release(struct inode *inode, struct file *file)
 {
        return 0;
 }
+
+
+void pci_reinit(void)
+{
+       struct pci_bus *bus = NULL;
+       int cnt = 20;
+
+       WIFI_INFO("pci wifi reinit!\n");
+
+       pci_lock_rescan_remove();
+       while ((bus = pci_find_next_bus(bus)) != NULL) {
+               pci_rescan_bus(bus);
+               WIFI_INFO("rescanning pci device\n");
+               cnt--;
+               if (cnt <= 0)
+                       break;
+       }
+       pci_unlock_rescan_remove();
+
+}
+EXPORT_SYMBOL(pci_reinit);
+
+void pci_remove_reinit(unsigned int vid, unsigned int pid, unsigned int delBus)
+{
+       struct pci_bus *bus = NULL;
+       struct pci_dev *devDevice, *devBus;
+       int cnt = 20;
+
+       WIFI_INFO("pci wifi remove and reinit\n");
+       devDevice = pci_get_device(vid, pid, NULL);
+
+       if (devDevice != NULL) {
+               WIFI_INFO("device 0x%x:0x%x found, remove it\n", vid, pid);
+               devBus = devDevice->bus->self;
+               pci_stop_and_remove_bus_device_locked(devDevice);
+
+               if ((devBus > 0) && (devBus != NULL)) {
+                       WIFI_INFO("remove ths bus this device on!\n");
+                       pci_stop_and_remove_bus_device_locked(devBus);
+               }
+       } else {
+               WIFI_INFO("target pci device not found 0x%x:0x%x\n", vid, pid);
+       }
+
+       extern_wifi_set_enable(0);
+       msleep(200);
+       extern_wifi_set_enable(1);
+       msleep(200);
+
+       pci_lock_rescan_remove();
+       while ((bus = pci_find_next_bus(bus)) != NULL) {
+               pci_rescan_bus(bus);
+               WIFI_INFO("rescanning pci device\n");
+               cnt--;
+               if (cnt <= 0)
+                       break;
+       }
+       pci_unlock_rescan_remove();
+
+}
+EXPORT_SYMBOL(pci_remove_reinit);
+
 static long wifi_power_ioctl(struct file *filp,
        unsigned int cmd, unsigned long arg)
 {
@@ -255,17 +318,18 @@ static long wifi_power_ioctl(struct file *filp,
                break;
        case USB_POWER_DOWN:
                set_usb_wifi_power(0);
-               WIFI_INFO(KERN_INFO "Set usb_sdio wifi power down!\n");
+               WIFI_INFO("Set usb_sdio wifi power down!\n");
                break;
-       case SDIO_POWER_UP:
+       case WIFI_POWER_UP:
                extern_wifi_set_enable(0);
                mdelay(200);
                extern_wifi_set_enable(1);
                mdelay(200);
                sdio_reinit();
+               pci_reinit();
                WIFI_INFO("Set sdio wifi power up!\n");
                break;
-       case SDIO_POWER_DOWN:
+       case WIFI_POWER_DOWN:
                extern_wifi_set_enable(0);
                break;
        case SDIO_GET_DEV_TYPE:
index 43ee4ed..64cc1e3 100644 (file)
 
 extern void sdio_reinit(void);
 extern char *get_wifi_inf(void);
+
 void extern_wifi_set_enable(int is_on);
 int wifi_irq_num(void);
 
+/*amlogic 4.9 kernel support pci interface wifi*/
+extern void pci_lock_rescan_remove(void);
+extern struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
+extern unsigned int pci_rescan_bus(struct pci_bus *bus);
+extern void pci_unlock_rescan_remove(void);
+extern struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
+                              struct pci_dev *from);
+extern void pci_stop_and_remove_bus_device_locked(struct pci_dev *dev);
+
 #endif /* _wifi_dt_h_ */