diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 12fc8d1fea7c..7cd40841da01 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -230,6 +230,8 @@ static enum qdf_bus_type to_bus_type(enum pld_bus_type bus_type) return QDF_BUS_TYPE_SDIO; case PLD_BUS_TYPE_USB: return QDF_BUS_TYPE_USB; + case PLD_BUS_TYPE_IPCI: + return QDF_BUS_TYPE_IPCI; default: return QDF_BUS_TYPE_NONE; } diff --git a/core/pld/inc/pld_common.h b/core/pld/inc/pld_common.h index d07c8704fbab..0395a2ec0a41 100644 --- a/core/pld/inc/pld_common.h +++ b/core/pld/inc/pld_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -51,6 +51,7 @@ * @PLD_BUS_TYPE_USB : USB bus * @PLD_BUS_TYPE_SNOC_FW_SIM : SNOC FW SIM bus * @PLD_BUS_TYPE_PCIE_FW_SIM : PCIE FW SIM bus + * @PLD_BUS_TYPE_IPCI : IPCI bus */ enum pld_bus_type { PLD_BUS_TYPE_NONE = -1, @@ -60,6 +61,7 @@ enum pld_bus_type { PLD_BUS_TYPE_USB, PLD_BUS_TYPE_SNOC_FW_SIM, PLD_BUS_TYPE_PCIE_FW_SIM, + PLD_BUS_TYPE_IPCI, }; #define PLD_MAX_FIRMWARE_SIZE (1 * 1024 * 1024) diff --git a/core/pld/src/pld_common.c b/core/pld/src/pld_common.c index 25395d1533c8..6dcf82b4cb9a 100644 --- a/core/pld/src/pld_common.c +++ b/core/pld/src/pld_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -34,8 +34,12 @@ #ifdef CONFIG_PLD_SNOC_ICNSS #include #endif +#ifdef CONFIG_PLD_IPCI_ICNSS +#include +#endif #include "pld_pcie.h" +#include "pld_ipci.h" #include "pld_pcie_fw_sim.h" #include "pld_snoc_fw_sim.h" #include "pld_snoc.h" @@ -49,6 +53,8 @@ #define PLD_USB_REGISTERED BIT(3) #define PLD_SNOC_FW_SIM_REGISTERED BIT(4) #define PLD_PCIE_FW_SIM_REGISTERED BIT(5) +#define PLD_IPCI_REGISTERED BIT(6) + #define PLD_BUS_MASK 0xf static struct pld_context *pld_ctx; @@ -313,8 +319,17 @@ int pld_register_driver(struct pld_driver_ops *ops) } pld_context->pld_driver_state |= PLD_USB_REGISTERED; + ret = pld_ipci_register_driver(); + if (ret) { + pr_err("Fail to register ipci driver\n"); + goto fail_ipci; + } + pld_context->pld_driver_state |= PLD_IPCI_REGISTERED; + return ret; +fail_ipci: + pld_usb_unregister_driver(); fail_usb: pld_pcie_fw_sim_unregister_driver(); fail_pcie_fw_sim: @@ -363,6 +378,7 @@ void pld_unregister_driver(void) pld_snoc_unregister_driver(); pld_sdio_unregister_driver(); pld_usb_unregister_driver(); + pld_ipci_unregister_driver(); pld_context->pld_driver_state = 0; @@ -410,6 +426,9 @@ int pld_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config, ret = pld_usb_wlan_enable(ifdev, config, mode, QWLAN_VERSIONSTR); break; + case PLD_BUS_TYPE_IPCI: + ret = pld_ipci_wlan_enable(dev, config, mode, QWLAN_VERSIONSTR); + break; default: ret = -EINVAL; break; @@ -447,6 +466,9 @@ int pld_wlan_disable(struct device *dev, enum pld_driver_mode mode) break; case PLD_BUS_TYPE_SDIO: break; + case PLD_BUS_TYPE_IPCI: + ret = pld_ipci_wlan_disable(dev, mode); + break; default: ret = -EINVAL; break; @@ -480,6 +502,9 @@ int pld_set_fw_log_mode(struct device *dev, u8 fw_log_mode) case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SDIO: break; + case PLD_BUS_TYPE_IPCI: + ret = pld_ipci_set_fw_log_mode(dev, fw_log_mode); + break; default: ret = -EINVAL; break; @@ -543,6 +568,7 @@ int pld_get_fw_files_for_target(struct device *dev, case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_IPCI: break; case PLD_BUS_TYPE_SDIO: ret = pld_sdio_get_fw_files_for_target(pfw_files, @@ -580,6 +606,7 @@ void pld_is_pci_link_down(struct device *dev) break; case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_IPCI: break; default: pr_err("Invalid device type\n"); @@ -606,6 +633,7 @@ void pld_schedule_recovery_work(struct device *dev, case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_IPCI: break; default: pr_err("Invalid device type\n"); @@ -639,6 +667,8 @@ int pld_wlan_pm_control(struct device *dev, bool vote) break; case PLD_BUS_TYPE_SDIO: break; + case PLD_BUS_TYPE_IPCI: + break; default: ret = -EINVAL; break; @@ -665,6 +695,7 @@ void *pld_get_virt_ramdump_mem(struct device *dev, unsigned long *size) case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_IPCI: break; case PLD_BUS_TYPE_SDIO: mem = pld_sdio_get_virt_ramdump_mem(dev, size); @@ -686,6 +717,7 @@ void pld_release_virt_ramdump_mem(struct device *dev, void *address) case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_IPCI: break; case PLD_BUS_TYPE_SDIO: pld_sdio_release_virt_ramdump_mem(address); @@ -715,6 +747,8 @@ void pld_device_crashed(struct device *dev) case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: break; + case PLD_BUS_TYPE_IPCI: + break; case PLD_BUS_TYPE_SDIO: pld_sdio_device_crashed(dev); break; @@ -742,6 +776,8 @@ void pld_device_self_recovery(struct device *dev, case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: break; + case PLD_BUS_TYPE_IPCI: + break; case PLD_BUS_TYPE_SDIO: pld_sdio_device_self_recovery(dev); break; @@ -768,6 +804,7 @@ void pld_intr_notify_q6(struct device *dev) case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_IPCI: break; default: pr_err("Invalid device type\n"); @@ -794,6 +831,8 @@ void pld_request_pm_qos(struct device *dev, u32 qos_val) case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: break; + case PLD_BUS_TYPE_IPCI: + break; case PLD_BUS_TYPE_SDIO: /* To do Add call cns API */ break; @@ -823,6 +862,8 @@ void pld_remove_pm_qos(struct device *dev) case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: break; + case PLD_BUS_TYPE_IPCI: + break; case PLD_BUS_TYPE_SDIO: /* To do Add call cns API */ break; @@ -854,6 +895,8 @@ int pld_request_bus_bandwidth(struct device *dev, int bandwidth) case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: break; + case PLD_BUS_TYPE_IPCI: + break; case PLD_BUS_TYPE_SDIO: /* To do Add call cns API */ break; @@ -889,6 +932,8 @@ int pld_get_platform_cap(struct device *dev, struct pld_platform_cap *cap) case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: break; + case PLD_BUS_TYPE_IPCI: + break; case PLD_BUS_TYPE_SDIO: break; default: @@ -926,6 +971,8 @@ int pld_get_sha_hash(struct device *dev, const u8 *data, case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: break; + case PLD_BUS_TYPE_IPCI: + break; case PLD_BUS_TYPE_SDIO: break; default: @@ -953,6 +1000,7 @@ void *pld_get_fw_ptr(struct device *dev) case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_IPCI: break; case PLD_BUS_TYPE_SDIO: break; @@ -983,6 +1031,8 @@ int pld_auto_suspend(struct device *dev) case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: break; + case PLD_BUS_TYPE_IPCI: + break; case PLD_BUS_TYPE_SDIO: break; default: @@ -1012,6 +1062,8 @@ int pld_auto_resume(struct device *dev) case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: break; + case PLD_BUS_TYPE_IPCI: + break; case PLD_BUS_TYPE_SDIO: break; default: @@ -1043,6 +1095,7 @@ int pld_force_wake_request(struct device *dev) case PLD_BUS_TYPE_SNOC: case PLD_BUS_TYPE_SDIO: case PLD_BUS_TYPE_USB: + case PLD_BUS_TYPE_IPCI: break; default: pr_err("Invalid device type %d\n", type); @@ -1075,6 +1128,7 @@ int pld_is_device_awake(struct device *dev) case PLD_BUS_TYPE_SNOC: case PLD_BUS_TYPE_SDIO: case PLD_BUS_TYPE_USB: + case PLD_BUS_TYPE_IPCI: break; default: pr_err("Invalid device type %d\n", type); @@ -1106,6 +1160,7 @@ int pld_force_wake_release(struct device *dev) case PLD_BUS_TYPE_SNOC: case PLD_BUS_TYPE_SDIO: case PLD_BUS_TYPE_USB: + case PLD_BUS_TYPE_IPCI: break; default: pr_err("Invalid device type %d\n", type); @@ -1146,6 +1201,8 @@ int pld_ce_request_irq(struct device *dev, unsigned int ce_id, case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_PCIE: break; + case PLD_BUS_TYPE_IPCI: + break; default: ret = -EINVAL; break; @@ -1177,6 +1234,8 @@ int pld_ce_free_irq(struct device *dev, unsigned int ce_id, void *ctx) case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_PCIE: break; + case PLD_BUS_TYPE_IPCI: + break; default: ret = -EINVAL; break; @@ -1203,6 +1262,7 @@ void pld_enable_irq(struct device *dev, unsigned int ce_id) break; case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_PCIE: + case PLD_BUS_TYPE_IPCI: break; case PLD_BUS_TYPE_SDIO: break; @@ -1230,6 +1290,7 @@ void pld_disable_irq(struct device *dev, unsigned int ce_id) break; case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_PCIE: + case PLD_BUS_TYPE_IPCI: break; case PLD_BUS_TYPE_SDIO: break; @@ -1268,6 +1329,9 @@ int pld_get_soc_info(struct device *dev, struct pld_soc_info *info) break; case PLD_BUS_TYPE_SDIO: break; + case PLD_BUS_TYPE_IPCI: + ret = pld_ipci_get_soc_info(dev, info); + break; default: ret = -EINVAL; break; @@ -1299,6 +1363,8 @@ int pld_get_ce_id(struct device *dev, int irq) break; case PLD_BUS_TYPE_PCIE_FW_SIM: break; + case PLD_BUS_TYPE_IPCI: + break; default: ret = -EINVAL; break; @@ -1325,6 +1391,8 @@ int pld_get_irq(struct device *dev, int ce_id) case PLD_BUS_TYPE_SNOC_FW_SIM: ret = pld_snoc_fw_sim_get_irq(dev, ce_id); break; + case PLD_BUS_TYPE_IPCI: + break; case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_PCIE: default: @@ -1350,6 +1418,7 @@ void pld_lock_pm_sem(struct device *dev) case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_IPCI: break; case PLD_BUS_TYPE_SDIO: break; @@ -1376,6 +1445,7 @@ void pld_release_pm_sem(struct device *dev) case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_IPCI: break; case PLD_BUS_TYPE_SDIO: break; @@ -1405,6 +1475,7 @@ void pld_lock_reg_window(struct device *dev, unsigned long *flags) case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_IPCI: break; case PLD_BUS_TYPE_SDIO: break; @@ -1434,6 +1505,7 @@ void pld_unlock_reg_window(struct device *dev, unsigned long *flags) case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_IPCI: break; case PLD_BUS_TYPE_SDIO: break; @@ -1469,6 +1541,9 @@ int pld_power_on(struct device *dev) case PLD_BUS_TYPE_SNOC: ret = pld_snoc_power_on(dev); break; + case PLD_BUS_TYPE_IPCI: + ret = pld_ipci_power_on(dev); + break; default: pr_err("Invalid device type\n"); break; @@ -1501,6 +1576,9 @@ int pld_power_off(struct device *dev) case PLD_BUS_TYPE_SNOC: ret = pld_snoc_power_off(dev); break; + case PLD_BUS_TYPE_IPCI: + ret = pld_ipci_power_off(dev); + break; default: pr_err("Invalid device type\n"); break; @@ -1539,6 +1617,7 @@ int pld_athdiag_read(struct device *dev, uint32_t offset, case PLD_BUS_TYPE_USB: case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: + case PLD_BUS_TYPE_IPCI: break; default: ret = -EINVAL; @@ -1578,6 +1657,7 @@ int pld_athdiag_write(struct device *dev, uint32_t offset, case PLD_BUS_TYPE_USB: case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: + case PLD_BUS_TYPE_IPCI: break; default: ret = -EINVAL; @@ -1609,6 +1689,8 @@ void *pld_smmu_get_domain(struct device *dev) case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: break; + case PLD_BUS_TYPE_IPCI: + break; case PLD_BUS_TYPE_SDIO: case PLD_BUS_TYPE_USB: pr_err("Not supported on type %d\n", type); @@ -1639,6 +1721,8 @@ void *pld_smmu_get_mapping(struct device *dev) case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: break; + case PLD_BUS_TYPE_IPCI: + break; case PLD_BUS_TYPE_PCIE: ptr = pld_pcie_smmu_get_mapping(dev); break; @@ -1674,6 +1758,8 @@ int pld_smmu_map(struct device *dev, phys_addr_t paddr, case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: break; + case PLD_BUS_TYPE_IPCI: + break; case PLD_BUS_TYPE_PCIE: ret = pld_pcie_smmu_map(dev, paddr, iova_addr, size); break; @@ -1725,6 +1811,12 @@ int pld_get_user_msi_assignment(struct device *dev, char *user_name, pr_err("Not supported on type %d\n", type); ret = -ENODEV; break; + case PLD_BUS_TYPE_IPCI: + ret = pld_ipci_get_user_msi_assignment(dev, user_name, + num_vectors, + user_base_data, + base_vector); + break; default: pr_err("Invalid device type %d\n", type); ret = -EINVAL; @@ -1770,6 +1862,8 @@ int pld_srng_request_irq(struct device *dev, int irq, irq_handler_t handler, pr_err("Not supported on type %d\n", type); ret = -ENODEV; break; + case PLD_BUS_TYPE_IPCI: + break; default: pr_err("Invalid device type %d\n", type); ret = -EINVAL; @@ -1810,6 +1904,8 @@ int pld_srng_free_irq(struct device *dev, int irq, void *dev_data) pr_err("Not supported on type %d\n", type); ret = -ENODEV; break; + case PLD_BUS_TYPE_IPCI: + break; default: pr_err("Invalid device type %d\n", type); ret = -EINVAL; @@ -1840,6 +1936,8 @@ void pld_srng_enable_irq(struct device *dev, int irq) break; case PLD_BUS_TYPE_SDIO: break; + case PLD_BUS_TYPE_IPCI: + break; default: pr_err("Invalid device type\n"); break; @@ -1867,6 +1965,8 @@ void pld_srng_disable_irq(struct device *dev, int irq) break; case PLD_BUS_TYPE_SDIO: break; + case PLD_BUS_TYPE_IPCI: + break; default: pr_err("Invalid device type\n"); break; @@ -1892,6 +1992,8 @@ int pld_pci_read_config_word(struct pci_dev *pdev, int offset, uint16_t *val) break; case PLD_BUS_TYPE_PCIE_FW_SIM: break; + case PLD_BUS_TYPE_IPCI: + break; case PLD_BUS_TYPE_PCIE: ret = pci_read_config_word(pdev, offset, val); break; @@ -1929,6 +2031,8 @@ int pld_pci_write_config_word(struct pci_dev *pdev, int offset, uint16_t val) break; case PLD_BUS_TYPE_SDIO: break; + case PLD_BUS_TYPE_IPCI: + break; default: pr_err("Invalid device type\n"); break; @@ -1961,6 +2065,8 @@ int pld_pci_read_config_dword(struct pci_dev *pdev, int offset, uint32_t *val) break; case PLD_BUS_TYPE_SDIO: break; + case PLD_BUS_TYPE_IPCI: + break; default: pr_err("Invalid device type\n"); break; @@ -1993,6 +2099,8 @@ int pld_pci_write_config_dword(struct pci_dev *pdev, int offset, uint32_t val) break; case PLD_BUS_TYPE_SDIO: break; + case PLD_BUS_TYPE_IPCI: + break; default: pr_err("Invalid device type\n"); break; @@ -2028,6 +2136,9 @@ int pld_get_msi_irq(struct device *dev, unsigned int vector) pr_err("Not supported on type %d\n", type); ret = -ENODEV; break; + case PLD_BUS_TYPE_IPCI: + ret = pld_ipci_get_msi_irq(dev, vector); + break; default: pr_err("Invalid device type %d\n", type); ret = -EINVAL; @@ -2064,6 +2175,9 @@ void pld_get_msi_address(struct device *dev, uint32_t *msi_addr_low, case PLD_BUS_TYPE_SNOC_FW_SIM: pr_err("Not supported on type %d\n", type); break; + case PLD_BUS_TYPE_IPCI: + pld_ipci_get_msi_address(dev, msi_addr_low, msi_addr_high); + break; default: pr_err("Invalid device type %d\n", type); break; @@ -2092,6 +2206,7 @@ int pld_is_drv_connected(struct device *dev) case PLD_BUS_TYPE_SNOC: case PLD_BUS_TYPE_SDIO: case PLD_BUS_TYPE_USB: + case PLD_BUS_TYPE_IPCI: break; default: pr_err("Invalid device type %d\n", type); @@ -2123,6 +2238,8 @@ unsigned int pld_socinfo_get_serial_number(struct device *dev) break; case PLD_BUS_TYPE_SNOC_FW_SIM: break; + case PLD_BUS_TYPE_IPCI: + break; default: pr_err("Invalid device type %d\n", type); break; @@ -2150,6 +2267,8 @@ int pld_is_qmi_disable(struct device *dev) break; case PLD_BUS_TYPE_SNOC_FW_SIM: break; + case PLD_BUS_TYPE_IPCI: + break; case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_PCIE: case PLD_BUS_TYPE_SDIO: @@ -2200,6 +2319,9 @@ int pld_is_fw_down(struct device *dev) ifdev = pld_get_if_dev(dev); ret = pld_usb_is_fw_down(ifdev); break; + case PLD_BUS_TYPE_IPCI: + ret = pld_ipci_is_fw_down(dev); + break; default: pr_err("Invalid device type %d\n", type); ret = -EINVAL; @@ -2232,6 +2354,8 @@ int pld_force_assert_target(struct device *dev) case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SDIO: return -EINVAL; + case PLD_BUS_TYPE_IPCI: + return pld_ipci_force_assert_target(dev); default: pr_err("Invalid device type %d\n", type); return -EINVAL; @@ -2258,6 +2382,7 @@ int pld_collect_rddm(struct device *dev) case PLD_BUS_TYPE_SNOC: case PLD_BUS_TYPE_SDIO: case PLD_BUS_TYPE_USB: + case PLD_BUS_TYPE_IPCI: return 0; default: pr_err("Invalid device type %d\n", type); @@ -2285,6 +2410,7 @@ int pld_qmi_send_get(struct device *dev) case PLD_BUS_TYPE_SNOC: case PLD_BUS_TYPE_SDIO: case PLD_BUS_TYPE_USB: + case PLD_BUS_TYPE_IPCI: return 0; default: pr_err("Invalid device type %d\n", type); @@ -2312,6 +2438,7 @@ int pld_qmi_send_put(struct device *dev) case PLD_BUS_TYPE_SNOC: case PLD_BUS_TYPE_SDIO: case PLD_BUS_TYPE_USB: + case PLD_BUS_TYPE_IPCI: return 0; default: pr_err("Invalid device type %d\n", type); @@ -2345,6 +2472,7 @@ int pld_qmi_send(struct device *dev, int type, void *cmd, case PLD_BUS_TYPE_SNOC: case PLD_BUS_TYPE_SDIO: case PLD_BUS_TYPE_USB: + case PLD_BUS_TYPE_IPCI: return -EINVAL; default: pr_err("Invalid device type %d\n", bus_type); @@ -2372,6 +2500,7 @@ bool pld_is_fw_dump_skipped(struct device *dev) break; case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: + case PLD_BUS_TYPE_IPCI: default: break; } @@ -2389,6 +2518,7 @@ int pld_is_pdr(struct device *dev) break; case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: + case PLD_BUS_TYPE_IPCI: default: break; } @@ -2406,6 +2536,7 @@ int pld_is_fw_rejuvenate(struct device *dev) break; case PLD_BUS_TYPE_PCIE_FW_SIM: case PLD_BUS_TYPE_SNOC_FW_SIM: + case PLD_BUS_TYPE_IPCI: default: break; } @@ -2426,6 +2557,8 @@ bool pld_have_platform_driver_support(struct device *dev) case PLD_BUS_TYPE_SNOC_FW_SIM: case PLD_BUS_TYPE_SNOC: break; + case PLD_BUS_TYPE_IPCI: + break; case PLD_BUS_TYPE_SDIO: ret = pld_sdio_platform_driver_support(); break; @@ -2462,6 +2595,9 @@ int pld_idle_shutdown(struct device *dev, case PLD_BUS_TYPE_SNOC_FW_SIM: errno = pld_snoc_fw_sim_idle_shutdown(dev); break; + case PLD_BUS_TYPE_IPCI: + errno = pld_ipci_idle_shutdown(dev); + break; default: pr_err("Invalid device type %d\n", type); break; @@ -2495,6 +2631,9 @@ int pld_idle_restart(struct device *dev, case PLD_BUS_TYPE_SNOC_FW_SIM: errno = pld_snoc_fw_sim_idle_restart(dev); break; + case PLD_BUS_TYPE_IPCI: + errno = pld_ipci_idle_restart(dev); + break; default: pr_err("Invalid device type %d\n", type); break; diff --git a/core/pld/src/pld_ipci.c b/core/pld/src/pld_ipci.c new file mode 100644 index 000000000000..57dcafd8fae5 --- /dev/null +++ b/core/pld/src/pld_ipci.c @@ -0,0 +1,406 @@ +/* + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#ifdef CONFIG_PLD_IPCI_ICNSS +#include +#endif + +#include "pld_internal.h" +#include "pld_ipci.h" + +#ifdef CONFIG_PLD_IPCI_ICNSS +/** + * pld_ipci_probe() - Probe function for platform driver + * @dev: device + * + * The probe function will be called when platform device + * is detected. + * + * Return: int + */ +static int pld_ipci_probe(struct device *dev) +{ + struct pld_context *pld_context; + int ret = 0; + + pld_context = pld_get_global_context(); + if (!pld_context) { + ret = -ENODEV; + goto out; + } + + ret = pld_add_dev(pld_context, dev, NULL, PLD_BUS_TYPE_IPCI); + if (ret) + goto out; + + return pld_context->ops->probe(dev, PLD_BUS_TYPE_IPCI, + NULL, NULL); + +out: + return ret; +} + +/** + * pld_ipci_remove() - Remove function for platform device + * @dev: device + * + * The remove function will be called when platform device + * is disconnected + * + * Return: void + */ +static void pld_ipci_remove(struct device *dev) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + + if (!pld_context) + return; + + pld_context->ops->remove(dev, PLD_BUS_TYPE_SNOC); + + pld_del_dev(pld_context, dev); +} + +/** + * pld_ipci_reinit() - SSR re-initialize function for platform device + * @dev: device + * + * During subsystem restart(SSR), this function will be called to + * re-initialize platform device. + * + * Return: int + */ +static int pld_ipci_reinit(struct device *dev) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (pld_context->ops->reinit) + return pld_context->ops->reinit(dev, PLD_BUS_TYPE_IPCI, + NULL, NULL); + + return -ENODEV; +} + +/** + * pld_ipci_shutdown() - SSR shutdown function for platform device + * @dev: device + * + * During SSR, this function will be called to shutdown platform device. + * + * Return: void + */ +static void pld_ipci_shutdown(struct device *dev) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (pld_context->ops->shutdown) + pld_context->ops->shutdown(dev, PLD_BUS_TYPE_IPCI); +} + +/** + * pld_ipci_crash_shutdown() - Crash shutdown function for platform device + * @dev: device + * + * This function will be called when a crash is detected, it will shutdown + * platform device. + * + * Return: void + */ +static void pld_ipci_crash_shutdown(void *dev) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (pld_context->ops->crash_shutdown) + pld_context->ops->crash_shutdown(dev, PLD_BUS_TYPE_IPCI); +} + +/** + * pld_ipci_pm_suspend() - PM suspend callback function for power management + * @dev: device + * + * This function is to suspend the platform device when power management + * is enabled. + * + * Return: void + */ +static int pld_ipci_pm_suspend(struct device *dev) +{ + struct pld_context *pld_context; + pm_message_t state; + + state.event = PM_EVENT_SUSPEND; + pld_context = pld_get_global_context(); + return pld_context->ops->suspend(dev, PLD_BUS_TYPE_IPCI, state); +} + +/** + * pld_ipci_pm_resume() - PM resume callback function for power management + * @pdev: device + * + * This function is to resume the platform device when power management + * is enabled. + * + * Return: void + */ +static int pld_ipci_pm_resume(struct device *dev) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + return pld_context->ops->resume(dev, PLD_BUS_TYPE_IPCI); +} + +/** + * pld_ipci_suspend_noirq() - Complete the actions started by suspend() + * @dev: device + * + * Complete the actions started by suspend(). Carry out any + * additional operations required for suspending the device that might be + * racing with its driver's interrupt handler, which is guaranteed not to + * run while suspend_noirq() is being executed. + * + * Return: 0 for success + * Non zero failure code for errors + */ +static int pld_ipci_suspend_noirq(struct device *dev) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (!pld_context) + return -EINVAL; + + if (pld_context->ops->suspend_noirq) + return pld_context->ops->suspend_noirq(dev, PLD_BUS_TYPE_IPCI); + return 0; +} + +/** + * pld_ipci_resume_noirq() - Prepare for the execution of resume() + * @pdev: device + * + * Prepare for the execution of resume() by carrying out any + * operations required for resuming the device that might be racing with + * its driver's interrupt handler, which is guaranteed not to run while + * resume_noirq() is being executed. + * + * Return: 0 for success + * Non zero failure code for errors + */ +static int pld_ipci_resume_noirq(struct device *dev) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (!pld_context) + return -EINVAL; + + if (pld_context->ops->resume_noirq) + return pld_context->ops->resume_noirq(dev, PLD_BUS_TYPE_IPCI); + + return 0; +} + +static int pld_ipci_uevent(struct device *dev, + struct icnss_uevent_data *uevent) +{ + struct pld_context *pld_context; + struct icnss_uevent_fw_down_data *uevent_data = NULL; + struct pld_uevent_data data; + + pld_context = pld_get_global_context(); + if (!pld_context) + return -EINVAL; + + if (!pld_context->ops->uevent) + goto out; + + if (!uevent) + return -EINVAL; + + switch (uevent->uevent) { + case ICNSS_UEVENT_FW_CRASHED: + data.uevent = PLD_FW_CRASHED; + break; + case ICNSS_UEVENT_FW_DOWN: + if (!uevent->data) + return -EINVAL; + uevent_data = (struct icnss_uevent_fw_down_data *)uevent->data; + data.uevent = PLD_FW_DOWN; + data.fw_down.crashed = uevent_data->crashed; + break; + default: + goto out; + } + + pld_context->ops->uevent(dev, &data); +out: + return 0; +} + +#ifdef MULTI_IF_NAME +#define PLD_IPCI_OPS_NAME "pld_ipci_" MULTI_IF_NAME +#else +#define PLD_IPCI_OPS_NAME "pld_ipci" +#endif + +struct icnss_driver_ops pld_ipci_ops = { + .name = PLD_IPCI_OPS_NAME, + .probe = pld_ipci_probe, + .remove = pld_ipci_remove, + .shutdown = pld_ipci_shutdown, + .reinit = pld_ipci_reinit, + .crash_shutdown = pld_ipci_crash_shutdown, + .pm_suspend = pld_ipci_pm_suspend, + .pm_resume = pld_ipci_pm_resume, + .suspend_noirq = pld_ipci_suspend_noirq, + .resume_noirq = pld_ipci_resume_noirq, + .uevent = pld_ipci_uevent, +}; + +/** + * pld_ipci_register_driver() - Register platform device callback functions + * + * Return: int + */ +int pld_ipci_register_driver(void) +{ + return icnss_register_driver(&pld_ipci_ops); +} + +/** + * pld_ipci_unregister_driver() - Unregister platform device callback functions + * + * Return: void + */ +void pld_ipci_unregister_driver(void) +{ + icnss_unregister_driver(&pld_ipci_ops); +} + +/** + * pld_ipci_wlan_enable() - Enable WLAN + * @dev: device + * @config: WLAN configuration data + * @mode: WLAN mode + * @host_version: host software version + * + * This function enables WLAN FW. It passed WLAN configuration data, + * WLAN mode and host software version to FW. + * + * Return: 0 for success + * Non zero failure code for errors + */ + +int pld_ipci_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config, + enum pld_driver_mode mode, const char *host_version) +{ + struct icnss_wlan_enable_cfg cfg; + enum icnss_driver_mode icnss_mode; + + if (!dev) + return -ENODEV; + + cfg.num_ce_tgt_cfg = config->num_ce_tgt_cfg; + cfg.ce_tgt_cfg = (struct ce_tgt_pipe_cfg *) + config->ce_tgt_cfg; + cfg.num_ce_svc_pipe_cfg = config->num_ce_svc_pipe_cfg; + cfg.ce_svc_cfg = (struct ce_svc_pipe_cfg *) + config->ce_svc_cfg; + cfg.num_shadow_reg_cfg = config->num_shadow_reg_cfg; + cfg.shadow_reg_cfg = (struct icnss_shadow_reg_cfg *) + config->shadow_reg_cfg; + + switch (mode) { + case PLD_FTM: + icnss_mode = ICNSS_FTM; + break; + case PLD_EPPING: + icnss_mode = ICNSS_EPPING; + break; + default: + icnss_mode = ICNSS_MISSION; + break; + } + + return icnss_wlan_enable(dev, &cfg, icnss_mode, host_version); +} + +/** + * pld_ipci_wlan_disable() - Disable WLAN + * @dev: device + * @mode: WLAN mode + * + * This function disables WLAN FW. It passes WLAN mode to FW. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_ipci_wlan_disable(struct device *dev, enum pld_driver_mode mode) +{ + if (!dev) + return -ENODEV; + + return icnss_wlan_disable(dev, ICNSS_OFF); +} + +/** + * pld_ipci_get_soc_info() - Get SOC information + * @dev: device + * @info: buffer to SOC information + * + * Return SOC info to the buffer. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_ipci_get_soc_info(struct device *dev, struct pld_soc_info *info) +{ + int errno; + struct icnss_soc_info icnss_info = {0}; + + if (!info || !dev) + return -ENODEV; + + errno = icnss_get_soc_info(dev, &icnss_info); + if (errno) + return errno; + + info->v_addr = icnss_info.v_addr; + info->p_addr = icnss_info.p_addr; + info->chip_id = icnss_info.chip_id; + info->chip_family = icnss_info.chip_family; + info->board_id = icnss_info.board_id; + info->soc_id = icnss_info.soc_id; + info->fw_version = icnss_info.fw_version; + strlcpy(info->fw_build_timestamp, icnss_info.fw_build_timestamp, + sizeof(info->fw_build_timestamp)); + + return 0; +} +#endif diff --git a/core/pld/src/pld_ipci.h b/core/pld/src/pld_ipci.h new file mode 100644 index 000000000000..8de7006803c2 --- /dev/null +++ b/core/pld/src/pld_ipci.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __PLD_IPCI_H__ +#define __PLD_IPCI_H__ + +#ifdef CONFIG_PLD_IPCI_ICNSS +#include +#endif +#include "pld_internal.h" + +#ifndef CONFIG_PLD_IPCI_ICNSS +static inline int pld_ipci_register_driver(void) +{ + return 0; +} + +static inline void pld_ipci_unregister_driver(void) +{ +} + +static inline int pld_ipci_wlan_enable(struct device *dev, + struct pld_wlan_enable_cfg *config, + enum pld_driver_mode mode, + const char *host_version) +{ + return 0; +} + +static inline int pld_ipci_wlan_disable(struct device *dev, + enum pld_driver_mode mode) +{ + return 0; +} + +static inline int pld_ipci_get_soc_info(struct device *dev, + struct pld_soc_info *info) +{ + return 0; +} + +static inline int pld_ipci_power_on(struct device *dev) +{ + return 0; +} + +static inline int pld_ipci_power_off(struct device *dev) +{ + return 0; +} + +static inline int pld_ipci_idle_restart(struct device *dev) +{ + return 0; +} + +static inline int pld_ipci_idle_shutdown(struct device *dev) +{ + return 0; +} + +static inline int pld_ipci_force_assert_target(struct device *dev) +{ + return -EINVAL; +} + +static inline int pld_ipci_get_user_msi_assignment(struct device *dev, + char *user_name, + int *num_vectors, + uint32_t *user_base_data, + uint32_t *base_vector) +{ + return 0; +} + +static inline int pld_ipci_get_msi_irq(struct device *dev, unsigned int vector) +{ + return 0; +} + +static inline void pld_ipci_get_msi_address(struct device *dev, + uint32_t *msi_addr_low, + uint32_t *msi_addr_high) +{ +} + +static inline int pld_ipci_is_fw_down(struct device *dev) +{ + return 0; +} + +static inline int pld_ipci_set_fw_log_mode(struct device *dev, u8 fw_log_mode) +{ + return 0; +} + +#else +int pld_ipci_register_driver(void); +void pld_ipci_unregister_driver(void); +int pld_ipci_wlan_enable(struct device *dev, + struct pld_wlan_enable_cfg *config, + enum pld_driver_mode mode, const char *host_version); +int pld_ipci_wlan_disable(struct device *dev, enum pld_driver_mode mode); +int pld_ipci_get_soc_info(struct device *dev, struct pld_soc_info *info); + +static inline int pld_ipci_power_on(struct device *dev) +{ + return icnss_power_on(dev); +} + +static inline int pld_ipci_power_off(struct device *dev) +{ + return icnss_power_off(dev); +} + +static inline int pld_ipci_idle_restart(struct device *dev) +{ + return icnss_idle_restart(dev); +} + +static inline int pld_ipci_idle_shutdown(struct device *dev) +{ + return icnss_idle_shutdown(dev); +} + +static inline int pld_ipci_force_assert_target(struct device *dev) +{ + return icnss_trigger_recovery(dev); +} + +static inline int pld_ipci_get_user_msi_assignment(struct device *dev, + char *user_name, + int *num_vectors, + uint32_t *user_base_data, + uint32_t *base_vector) +{ + return icnss_get_user_msi_assignment(dev, user_name, num_vectors, + user_base_data, base_vector); +} + +static inline int pld_ipci_get_msi_irq(struct device *dev, unsigned int vector) +{ + return icnss_get_msi_irq(dev, vector); +} + +static inline void pld_ipci_get_msi_address(struct device *dev, + uint32_t *msi_addr_low, + uint32_t *msi_addr_high) +{ + icnss_get_msi_address(dev, msi_addr_low, msi_addr_high); +} + +static inline int pld_ipci_is_fw_down(struct device *dev) +{ + return icnss_is_fw_down(); +} + +static inline int pld_ipci_set_fw_log_mode(struct device *dev, u8 fw_log_mode) +{ + return icnss_set_fw_log_mode(dev, fw_log_mode); +} + +#endif +#endif