1 // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) 2 /* Copyright(c) 2022 Intel Corporation */ 3 #include <linux/bitfield.h> 4 #include <linux/iopoll.h> 5 #include "adf_accel_devices.h" 6 #include "adf_common_drv.h" 7 #include "adf_gen4_pm.h" 8 #include "adf_cfg_strings.h" 9 #include "icp_qat_fw_init_admin.h" 10 #include "adf_gen4_hw_data.h" 11 #include "adf_cfg.h" 12 13 enum qat_pm_host_msg { 14 PM_NO_CHANGE = 0, 15 PM_SET_MIN, 16 }; 17 18 struct adf_gen4_pm_data { 19 struct work_struct pm_irq_work; 20 struct adf_accel_dev *accel_dev; 21 u32 pm_int_sts; 22 }; 23 24 static int send_host_msg(struct adf_accel_dev *accel_dev) 25 { 26 void __iomem *pmisc = adf_get_pmisc_base(accel_dev); 27 u32 msg; 28 29 msg = ADF_CSR_RD(pmisc, ADF_GEN4_PM_HOST_MSG); 30 if (msg & ADF_GEN4_PM_MSG_PENDING) 31 return -EBUSY; 32 33 /* Send HOST_MSG */ 34 msg = FIELD_PREP(ADF_GEN4_PM_MSG_PAYLOAD_BIT_MASK, PM_SET_MIN); 35 msg |= ADF_GEN4_PM_MSG_PENDING; 36 ADF_CSR_WR(pmisc, ADF_GEN4_PM_HOST_MSG, msg); 37 38 /* Poll status register to make sure the HOST_MSG has been processed */ 39 return read_poll_timeout(ADF_CSR_RD, msg, 40 !(msg & ADF_GEN4_PM_MSG_PENDING), 41 ADF_GEN4_PM_MSG_POLL_DELAY_US, 42 ADF_GEN4_PM_POLL_TIMEOUT_US, true, pmisc, 43 ADF_GEN4_PM_HOST_MSG); 44 } 45 46 static void pm_bh_handler(struct work_struct *work) 47 { 48 struct adf_gen4_pm_data *pm_data = 49 container_of(work, struct adf_gen4_pm_data, pm_irq_work); 50 struct adf_accel_dev *accel_dev = pm_data->accel_dev; 51 void __iomem *pmisc = adf_get_pmisc_base(accel_dev); 52 u32 pm_int_sts = pm_data->pm_int_sts; 53 u32 val; 54 55 /* PM Idle interrupt */ 56 if (pm_int_sts & ADF_GEN4_PM_IDLE_STS) { 57 /* Issue host message to FW */ 58 if (send_host_msg(accel_dev)) 59 dev_warn_ratelimited(&GET_DEV(accel_dev), 60 "Failed to send host msg to FW\n"); 61 } 62 63 /* Clear interrupt status */ 64 ADF_CSR_WR(pmisc, ADF_GEN4_PM_INTERRUPT, pm_int_sts); 65 66 /* Reenable PM interrupt */ 67 val = ADF_CSR_RD(pmisc, ADF_GEN4_ERRMSK2); 68 val &= ~ADF_GEN4_PM_SOU; 69 ADF_CSR_WR(pmisc, ADF_GEN4_ERRMSK2, val); 70 71 kfree(pm_data); 72 } 73 74 bool adf_gen4_handle_pm_interrupt(struct adf_accel_dev *accel_dev) 75 { 76 void __iomem *pmisc = adf_get_pmisc_base(accel_dev); 77 struct adf_gen4_pm_data *pm_data = NULL; 78 u32 errsou2; 79 u32 errmsk2; 80 u32 val; 81 82 /* Only handle the interrupt triggered by PM */ 83 errmsk2 = ADF_CSR_RD(pmisc, ADF_GEN4_ERRMSK2); 84 if (errmsk2 & ADF_GEN4_PM_SOU) 85 return false; 86 87 errsou2 = ADF_CSR_RD(pmisc, ADF_GEN4_ERRSOU2); 88 if (!(errsou2 & ADF_GEN4_PM_SOU)) 89 return false; 90 91 /* Disable interrupt */ 92 val = ADF_CSR_RD(pmisc, ADF_GEN4_ERRMSK2); 93 val |= ADF_GEN4_PM_SOU; 94 ADF_CSR_WR(pmisc, ADF_GEN4_ERRMSK2, val); 95 96 val = ADF_CSR_RD(pmisc, ADF_GEN4_PM_INTERRUPT); 97 98 pm_data = kzalloc(sizeof(*pm_data), GFP_ATOMIC); 99 if (!pm_data) 100 return false; 101 102 pm_data->pm_int_sts = val; 103 pm_data->accel_dev = accel_dev; 104 105 INIT_WORK(&pm_data->pm_irq_work, pm_bh_handler); 106 adf_misc_wq_queue_work(&pm_data->pm_irq_work); 107 108 return true; 109 } 110 EXPORT_SYMBOL_GPL(adf_gen4_handle_pm_interrupt); 111 112 int adf_gen4_enable_pm(struct adf_accel_dev *accel_dev) 113 { 114 void __iomem *pmisc = adf_get_pmisc_base(accel_dev); 115 int ret; 116 u32 val; 117 118 ret = adf_init_admin_pm(accel_dev, ADF_GEN4_PM_DEFAULT_IDLE_FILTER); 119 if (ret) 120 return ret; 121 122 /* Enable default PM interrupts: IDLE, THROTTLE */ 123 val = ADF_CSR_RD(pmisc, ADF_GEN4_PM_INTERRUPT); 124 val |= ADF_GEN4_PM_INT_EN_DEFAULT; 125 126 /* Clear interrupt status */ 127 val |= ADF_GEN4_PM_INT_STS_MASK; 128 ADF_CSR_WR(pmisc, ADF_GEN4_PM_INTERRUPT, val); 129 130 /* Unmask PM Interrupt */ 131 val = ADF_CSR_RD(pmisc, ADF_GEN4_ERRMSK2); 132 val &= ~ADF_GEN4_PM_SOU; 133 ADF_CSR_WR(pmisc, ADF_GEN4_ERRMSK2, val); 134 135 return 0; 136 } 137 EXPORT_SYMBOL_GPL(adf_gen4_enable_pm); 138