1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * processor thermal device mailbox driver for Workload type hints 4 * Copyright (c) 2020, Intel Corporation. 5 */ 6 7 #include <linux/kernel.h> 8 #include <linux/module.h> 9 #include <linux/pci.h> 10 #include <linux/io-64-nonatomic-lo-hi.h> 11 #include "processor_thermal_device.h" 12 13 #define MBOX_OFFSET_DATA 0x5810 14 #define MBOX_OFFSET_INTERFACE 0x5818 15 16 #define MBOX_BUSY_BIT 31 17 #define MBOX_RETRY_COUNT 100 18 19 static DEFINE_MUTEX(mbox_lock); 20 21 static int wait_for_mbox_ready(struct proc_thermal_device *proc_priv) 22 { 23 u32 retries, data; 24 int ret; 25 26 /* Poll for rb bit == 0 */ 27 retries = MBOX_RETRY_COUNT; 28 do { 29 data = readl(proc_priv->mmio_base + MBOX_OFFSET_INTERFACE); 30 if (data & BIT_ULL(MBOX_BUSY_BIT)) { 31 ret = -EBUSY; 32 continue; 33 } 34 ret = 0; 35 break; 36 } while (--retries); 37 38 return ret; 39 } 40 41 static int send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data) 42 { 43 struct proc_thermal_device *proc_priv; 44 u32 reg_data; 45 int ret; 46 47 proc_priv = pci_get_drvdata(pdev); 48 ret = wait_for_mbox_ready(proc_priv); 49 if (ret) 50 return ret; 51 52 writel(data, (proc_priv->mmio_base + MBOX_OFFSET_DATA)); 53 /* Write command register */ 54 reg_data = BIT_ULL(MBOX_BUSY_BIT) | id; 55 writel(reg_data, (proc_priv->mmio_base + MBOX_OFFSET_INTERFACE)); 56 57 return wait_for_mbox_ready(proc_priv); 58 } 59 60 static int send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp) 61 { 62 struct proc_thermal_device *proc_priv; 63 u32 reg_data; 64 int ret; 65 66 proc_priv = pci_get_drvdata(pdev); 67 ret = wait_for_mbox_ready(proc_priv); 68 if (ret) 69 return ret; 70 71 /* Write command register */ 72 reg_data = BIT_ULL(MBOX_BUSY_BIT) | id; 73 writel(reg_data, (proc_priv->mmio_base + MBOX_OFFSET_INTERFACE)); 74 75 ret = wait_for_mbox_ready(proc_priv); 76 if (ret) 77 return ret; 78 79 if (id == MBOX_CMD_WORKLOAD_TYPE_READ) 80 *resp = readl(proc_priv->mmio_base + MBOX_OFFSET_DATA); 81 else 82 *resp = readq(proc_priv->mmio_base + MBOX_OFFSET_DATA); 83 84 return 0; 85 } 86 87 int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp) 88 { 89 int ret; 90 91 mutex_lock(&mbox_lock); 92 ret = send_mbox_read_cmd(pdev, id, resp); 93 mutex_unlock(&mbox_lock); 94 95 return ret; 96 } 97 EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_read_cmd, INT340X_THERMAL); 98 99 int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data) 100 { 101 int ret; 102 103 mutex_lock(&mbox_lock); 104 ret = send_mbox_write_cmd(pdev, id, data); 105 mutex_unlock(&mbox_lock); 106 107 return ret; 108 } 109 EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_write_cmd, INT340X_THERMAL); 110 111 #define MBOX_CAMARILLO_RD_INTR_CONFIG 0x1E 112 #define MBOX_CAMARILLO_WR_INTR_CONFIG 0x1F 113 #define WLT_TW_MASK GENMASK_ULL(30, 24) 114 #define SOC_PREDICTION_TW_SHIFT 24 115 116 int processor_thermal_mbox_interrupt_config(struct pci_dev *pdev, bool enable, 117 int enable_bit, int time_window) 118 { 119 u64 data; 120 int ret; 121 122 if (!pdev) 123 return -ENODEV; 124 125 mutex_lock(&mbox_lock); 126 127 /* Do read modify write for MBOX_CAMARILLO_RD_INTR_CONFIG */ 128 129 ret = send_mbox_read_cmd(pdev, MBOX_CAMARILLO_RD_INTR_CONFIG, &data); 130 if (ret) { 131 dev_err(&pdev->dev, "MBOX_CAMARILLO_RD_INTR_CONFIG failed\n"); 132 goto unlock; 133 } 134 135 if (time_window >= 0) { 136 data &= ~WLT_TW_MASK; 137 138 /* Program notification delay */ 139 data |= ((u64)time_window << SOC_PREDICTION_TW_SHIFT) & WLT_TW_MASK; 140 } 141 142 if (enable) 143 data |= BIT(enable_bit); 144 else 145 data &= ~BIT(enable_bit); 146 147 ret = send_mbox_write_cmd(pdev, MBOX_CAMARILLO_WR_INTR_CONFIG, data); 148 if (ret) 149 dev_err(&pdev->dev, "MBOX_CAMARILLO_WR_INTR_CONFIG failed\n"); 150 151 unlock: 152 mutex_unlock(&mbox_lock); 153 154 return ret; 155 } 156 EXPORT_SYMBOL_NS_GPL(processor_thermal_mbox_interrupt_config, INT340X_THERMAL); 157 158 MODULE_LICENSE("GPL v2"); 159