diff --git a/core/pld/inc/pld_common.h b/core/pld/inc/pld_common.h index 58bbafb4da6c..22407634a154 100644 --- a/core/pld/inc/pld_common.h +++ b/core/pld/inc/pld_common.h @@ -385,6 +385,11 @@ enum pld_wlan_time_sync_trigger_type { * hardware or at the request of software. * @suspend_noirq: optional operation, complete the actions started by suspend() * @resume_noirq: optional operation, prepare for the execution of resume() + * @set_curr_therm_cdev_state: optional operation, will be called when there is + * change in the thermal level triggered by the thermal + * subsystem thus requiring mitigation actions. This will + * be called every time there is a change in the state + * and after driver load. */ struct pld_driver_ops { int (*probe)(struct device *dev, @@ -422,6 +427,9 @@ struct pld_driver_ops { enum pld_bus_type bus_type); int (*resume_noirq)(struct device *dev, enum pld_bus_type bus_type); + int (*set_curr_therm_cdev_state)(struct device *dev, + unsigned long state, + int mon_id); }; int pld_init(void); @@ -862,6 +870,37 @@ int pld_pci_read_config_dword(struct pci_dev *pdev, int offset, uint32_t *val); * Non zero failure code for errors */ int pld_pci_write_config_dword(struct pci_dev *pdev, int offset, uint32_t val); + +/** + * pld_thermal_register() - Register the thermal device with the thermal system + * @dev: The device structure + * @state: The max state to be configured on registration + * @mon_id: Thermal cooling device ID + * + * Return: Error code on error + */ +int pld_thermal_register(struct device *dev, unsigned long state, int mon_id); + +/** + * pld_thermal_unregister() - Unregister the device with the thermal system + * @dev: The device structure + * @mon_id: Thermal cooling device ID + * + * Return: None + */ +void pld_thermal_unregister(struct device *dev, int mon_id); + +/** + * pld_get_thermal_state() - Get the current thermal state from the PLD + * @dev: The device structure + * @thermal_state: param to store the current thermal state + * @mon_id: Thermal cooling device ID + * + * Return: Non-zero code for error; zero for success + */ +int pld_get_thermal_state(struct device *dev, unsigned long *thermal_state, + int mon_id); + #if IS_ENABLED(CONFIG_WCNSS_MEM_PRE_ALLOC) && defined(FEATURE_SKB_PRE_ALLOC) /** diff --git a/core/pld/src/pld_common.c b/core/pld/src/pld_common.c index aa353165285b..4aa92c1eac0a 100644 --- a/core/pld/src/pld_common.c +++ b/core/pld/src/pld_common.c @@ -2862,6 +2862,94 @@ int pld_idle_restart(struct device *dev, return errno; } +int pld_thermal_register(struct device *dev, + unsigned long max_state, int mon_id) +{ + int errno = -EINVAL; + enum pld_bus_type type; + + type = pld_get_bus_type(dev); + switch (type) { + case PLD_BUS_TYPE_SDIO: + case PLD_BUS_TYPE_USB: + case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_PCIE: + case PLD_BUS_TYPE_PCIE_FW_SIM: + break; + case PLD_BUS_TYPE_IPCI_FW_SIM: + errno = pld_pcie_fw_sim_thermal_register(dev, max_state, + mon_id); + break; + case PLD_BUS_TYPE_SNOC_FW_SIM: + break; + case PLD_BUS_TYPE_IPCI: + errno = pld_ipci_thermal_register(dev, max_state, mon_id); + break; + default: + pr_err("Invalid device type %d\n", type); + break; + } + + return errno; +} + +void pld_thermal_unregister(struct device *dev, int mon_id) +{ + enum pld_bus_type type; + + type = pld_get_bus_type(dev); + switch (type) { + case PLD_BUS_TYPE_SDIO: + case PLD_BUS_TYPE_USB: + case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_PCIE: + case PLD_BUS_TYPE_PCIE_FW_SIM: + break; + case PLD_BUS_TYPE_IPCI_FW_SIM: + pld_pcie_fw_sim_thermal_unregister(dev, mon_id); + break; + case PLD_BUS_TYPE_SNOC_FW_SIM: + break; + case PLD_BUS_TYPE_IPCI: + pld_ipci_thermal_unregister(dev, mon_id); + break; + default: + pr_err("Invalid device type %d\n", type); + break; + } +} + +int pld_get_thermal_state(struct device *dev, unsigned long *thermal_state, + int mon_id) +{ + int errno = -EINVAL; + enum pld_bus_type type; + + type = pld_get_bus_type(dev); + switch (type) { + case PLD_BUS_TYPE_SDIO: + case PLD_BUS_TYPE_USB: + case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_PCIE: + case PLD_BUS_TYPE_PCIE_FW_SIM: + break; + case PLD_BUS_TYPE_IPCI_FW_SIM: + errno = pld_pcie_fw_sim_get_thermal_state(dev, thermal_state, + mon_id); + break; + case PLD_BUS_TYPE_SNOC_FW_SIM: + break; + case PLD_BUS_TYPE_IPCI: + errno = pld_ipci_get_thermal_state(dev, thermal_state, mon_id); + break; + default: + pr_err("Invalid device type %d\n", type); + break; + } + + return errno; +} + #ifdef FEATURE_WLAN_TIME_SYNC_FTM /** * pld_get_audio_wlan_timestamp() - Get audio timestamp diff --git a/core/pld/src/pld_ipci.c b/core/pld/src/pld_ipci.c index 15c0208f5e38..fbffa4da6fec 100644 --- a/core/pld/src/pld_ipci.c +++ b/core/pld/src/pld_ipci.c @@ -373,6 +373,36 @@ static int pld_ipci_idle_shutdown_cb(struct device *dev) return -ENODEV; } +/** + * pld_ipci_set_thermal_state() - Set thermal state for thermal mitigation + * @dev: device + * @thermal_state: Thermal state set by thermal subsystem + * @mon_id: Thermal cooling device ID + * + * This function will be called when thermal subsystem notifies platform + * driver about change in thermal state. + * + * Return: 0 for success + * Non zero failure code for errors + */ +static int pld_ipci_set_thermal_state(struct device *dev, + unsigned long thermal_state, + int mon_id) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (!pld_context) + return -EINVAL; + + if (pld_context->ops->set_curr_therm_cdev_state) + return pld_context->ops->set_curr_therm_cdev_state(dev, + thermal_state, + mon_id); + + return -ENOTSUPP; +} + #ifdef MULTI_IF_NAME #define PLD_IPCI_OPS_NAME "pld_ipci_" MULTI_IF_NAME #else @@ -395,6 +425,7 @@ struct icnss_driver_ops pld_ipci_ops = { .uevent = pld_ipci_uevent, .idle_restart = pld_ipci_idle_restart_cb, .idle_shutdown = pld_ipci_idle_shutdown_cb, + .set_therm_cdev_state = pld_ipci_set_thermal_state, }; /** diff --git a/core/pld/src/pld_ipci.h b/core/pld/src/pld_ipci.h index 116202fbe1d1..2ae349c5f0ce 100644 --- a/core/pld/src/pld_ipci.h +++ b/core/pld/src/pld_ipci.h @@ -156,6 +156,26 @@ pld_ipci_qmi_send(struct device *dev, int type, void *cmd, { return 0; } + +static inline int pld_ipci_thermal_register(struct device *dev, + unsigned long max_state, + int mon_id) +{ + return 0; +} + +static inline void pld_ipci_thermal_unregister(struct device *dev, + int mon_id) +{ +} + +static inline int pld_ipci_get_thermal_state(struct device *dev, + unsigned long *thermal_state, + int mon_id) +{ + return 0; +} + #else int pld_ipci_register_driver(void); void pld_ipci_unregister_driver(void); @@ -269,5 +289,26 @@ pld_ipci_qmi_send(struct device *dev, int type, void *cmd, { return icnss_qmi_send(dev, type, cmd, cmd_len, cb_ctx, cb); } + +static inline int pld_ipci_thermal_register(struct device *dev, + unsigned long max_state, + int mon_id) +{ + return icnss_thermal_cdev_register(dev, max_state, mon_id); +} + +static inline void pld_ipci_thermal_unregister(struct device *dev, + int mon_id) +{ + icnss_thermal_cdev_unregister(dev, mon_id); +} + +static inline int pld_ipci_get_thermal_state(struct device *dev, + unsigned long *thermal_state, + int mon_id) +{ + return icnss_get_curr_therm_cdev_state(dev, thermal_state, mon_id); +} + #endif #endif diff --git a/core/pld/src/pld_pcie_fw_sim.c b/core/pld/src/pld_pcie_fw_sim.c index 1c445a951dbe..6a337e3d6f8f 100644 --- a/core/pld/src/pld_pcie_fw_sim.c +++ b/core/pld/src/pld_pcie_fw_sim.c @@ -263,6 +263,36 @@ out: return; } +/** + * pld_pcie_fw_sim_set_thermal_state: Set thermal state for thermal mitigation + * @dev: device + * @thermal_state: Thermal state set by thermal subsystem + * @mon_id: Thermal cooling device ID + * + * This function will be called when thermal subsystem notifies platform + * driver about change in thermal state. + * + * Return: 0 for success + * Non zero failure code for errors + */ +static int pld_pcie_fw_sim_set_thermal_state(struct device *dev, + unsigned long thermal_state, + int mon_id) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (!pld_context) + return -EINVAL; + + if (pld_context->ops->set_curr_therm_cdev_state) + return pld_context->ops->set_curr_therm_cdev_state(dev, + thermal_state, + mon_id); + + return -ENOTSUPP; +} + static struct pci_device_id pld_pcie_fw_sim_id_table[] = { { 0x168c, 0x003c, PCI_ANY_ID, PCI_ANY_ID }, { 0x168c, 0x003e, PCI_ANY_ID, PCI_ANY_ID }, @@ -509,6 +539,36 @@ out: return; } +/** + * pld_pcie_fw_sim_set_thermal_state: Set thermal state for thermal mitigation + * @dev: device + * @thermal_state: Thermal state set by thermal subsystem + * @mon_id: Thermal cooling device ID + * + * This function will be called when thermal subsystem notifies platform + * driver about change in thermal state. + * + * Return: 0 for success + * Non zero failure code for errors + */ +static int pld_pcie_fw_sim_set_thermal_state(struct device *dev, + unsigned long thermal_state, + int mon_id) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (!pld_context) + return -EINVAL; + + if (pld_context->ops->set_curr_therm_cdev_state) + return pld_context->ops->set_curr_therm_cdev_state(dev, + thermal_state, + mon_id); + + return -ENOTSUPP; +} + static struct pci_device_id pld_pcie_fw_sim_id_table[] = { { 0x168c, 0x003c, PCI_ANY_ID, PCI_ANY_ID }, { 0x168c, 0x003e, PCI_ANY_ID, PCI_ANY_ID }, @@ -539,6 +599,7 @@ struct cnss_wlan_driver pld_pcie_fw_sim_ops = { .crash_shutdown = pld_pcie_fw_sim_crash_shutdown, .modem_status = pld_pcie_fw_sim_notify_handler, .update_status = pld_pcie_fw_sim_uevent, + .set_therm_cdev_state = pld_pcie_fw_sim_set_thermal_state, }; /** diff --git a/core/pld/src/pld_pcie_fw_sim.h b/core/pld/src/pld_pcie_fw_sim.h index a7773ce8bfe5..c23f5871e083 100644 --- a/core/pld/src/pld_pcie_fw_sim.h +++ b/core/pld/src/pld_pcie_fw_sim.h @@ -128,6 +128,25 @@ static inline int pld_pcie_fw_sim_idle_restart(struct device *dev) { return 0; } + +static inline int pld_pcie_fw_sim_thermal_register(struct device *dev, + unsigned long max_state, + int mon_id) +{ + return 0; +} + +static inline void pld_pcie_fw_sim_thermal_unregister(struct device *dev, + int mon_id) +{ +} + +static inline int pld_pcie_fw_sim_get_thermal_state(struct device *dev, + unsigned long *therm_state, + int mon_id) +{ + return 0; +} #else #include @@ -206,5 +225,27 @@ static inline int pld_pcie_fw_sim_idle_restart(struct device *dev) { return cnss_fw_sim_idle_restart(dev); } + +static inline int pld_pcie_fw_sim_thermal_register(struct device *dev, + unsigned long max_state, + int mon_id) +{ + return cnss_fw_sim_thermal_cdev_register(dev, max_state, mon_id); +} + +static inline void pld_pcie_fw_sim_thermal_unregister(struct device *dev, + int mon_id) +{ + cnss_fw_sim_thermal_cdev_unregister(dev, mon_id); +} + +static inline int pld_pcie_fw_sim_get_thermal_state(struct device *dev, + unsigned long *therm_state, + int mon_id) +{ + return cnss_fw_sim_get_curr_therm_cdev_state(dev, therm_state, + mon_id); +} + #endif #endif