diff --git a/arch/arm64/boot/dts/amlogic/axg_s400.dts b/arch/arm64/boot/dts/amlogic/axg_s400.dts index 708613b003c7..af4ccef6b86c 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400.dts @@ -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"; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts index 4a3fff18c070..803894e21750 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts @@ -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"; diff --git a/drivers/amlogic/wifi/wifi_dt.c b/drivers/amlogic/wifi/wifi_dt.c index a8923c7ebb41..aaadd9819b7b 100644 --- a/drivers/amlogic/wifi/wifi_dt.c +++ b/drivers/amlogic/wifi/wifi_dt.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #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: diff --git a/include/linux/amlogic/wifi_dt.h b/include/linux/amlogic/wifi_dt.h index 43ee4ed2a9d1..64cc1e3adc09 100644 --- a/include/linux/amlogic/wifi_dt.h +++ b/include/linux/amlogic/wifi_dt.h @@ -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_ */