wifi: add pci reinit and remove_reinit function [4/7]

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>
This commit is contained in:
Weiguang Ruan
2017-08-31 16:16:54 +08:00
committed by Jianxin Pan
parent 0d1f23ae52
commit 038eab447d
4 changed files with 81 additions and 5 deletions

View File

@@ -574,6 +574,7 @@
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";

View File

@@ -574,6 +574,7 @@
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";

View 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:

View File

@@ -20,7 +20,17 @@
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_ */