1 // SPDX-License-Identifier: GPL-2.0-only
3 * processor thermal device mailbox driver for Workload type hints
4 * Copyright (c) 2020, Intel Corporation.
7 #include <linux/kernel.h>
8 #include <linux/module.h>
10 #include <linux/io-64-nonatomic-lo-hi.h>
11 #include "processor_thermal_device.h"
13 #define MBOX_OFFSET_DATA 0x5810
14 #define MBOX_OFFSET_INTERFACE 0x5818
16 #define MBOX_BUSY_BIT 31
17 #define MBOX_RETRY_COUNT 100
19 static DEFINE_MUTEX(mbox_lock
);
21 static int wait_for_mbox_ready(struct proc_thermal_device
*proc_priv
)
26 /* Poll for rb bit == 0 */
27 retries
= MBOX_RETRY_COUNT
;
29 data
= readl(proc_priv
->mmio_base
+ MBOX_OFFSET_INTERFACE
);
30 if (data
& BIT_ULL(MBOX_BUSY_BIT
)) {
41 static int send_mbox_write_cmd(struct pci_dev
*pdev
, u16 id
, u32 data
)
43 struct proc_thermal_device
*proc_priv
;
47 proc_priv
= pci_get_drvdata(pdev
);
48 ret
= wait_for_mbox_ready(proc_priv
);
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
));
57 return wait_for_mbox_ready(proc_priv
);
60 static int send_mbox_read_cmd(struct pci_dev
*pdev
, u16 id
, u64
*resp
)
62 struct proc_thermal_device
*proc_priv
;
66 proc_priv
= pci_get_drvdata(pdev
);
67 ret
= wait_for_mbox_ready(proc_priv
);
71 /* Write command register */
72 reg_data
= BIT_ULL(MBOX_BUSY_BIT
) | id
;
73 writel(reg_data
, (proc_priv
->mmio_base
+ MBOX_OFFSET_INTERFACE
));
75 ret
= wait_for_mbox_ready(proc_priv
);
79 if (id
== MBOX_CMD_WORKLOAD_TYPE_READ
)
80 *resp
= readl(proc_priv
->mmio_base
+ MBOX_OFFSET_DATA
);
82 *resp
= readq(proc_priv
->mmio_base
+ MBOX_OFFSET_DATA
);
87 int processor_thermal_send_mbox_read_cmd(struct pci_dev
*pdev
, u16 id
, u64
*resp
)
91 mutex_lock(&mbox_lock
);
92 ret
= send_mbox_read_cmd(pdev
, id
, resp
);
93 mutex_unlock(&mbox_lock
);
97 EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_read_cmd
, "INT340X_THERMAL");
99 int processor_thermal_send_mbox_write_cmd(struct pci_dev
*pdev
, u16 id
, u32 data
)
103 mutex_lock(&mbox_lock
);
104 ret
= send_mbox_write_cmd(pdev
, id
, data
);
105 mutex_unlock(&mbox_lock
);
109 EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_write_cmd
, "INT340X_THERMAL");
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
116 int processor_thermal_mbox_interrupt_config(struct pci_dev
*pdev
, bool enable
,
117 int enable_bit
, int time_window
)
125 mutex_lock(&mbox_lock
);
127 /* Do read modify write for MBOX_CAMARILLO_RD_INTR_CONFIG */
129 ret
= send_mbox_read_cmd(pdev
, MBOX_CAMARILLO_RD_INTR_CONFIG
, &data
);
131 dev_err(&pdev
->dev
, "MBOX_CAMARILLO_RD_INTR_CONFIG failed\n");
135 if (time_window
>= 0) {
136 data
&= ~WLT_TW_MASK
;
138 /* Program notification delay */
139 data
|= ((u64
)time_window
<< SOC_PREDICTION_TW_SHIFT
) & WLT_TW_MASK
;
143 data
|= BIT(enable_bit
);
145 data
&= ~BIT(enable_bit
);
147 ret
= send_mbox_write_cmd(pdev
, MBOX_CAMARILLO_WR_INTR_CONFIG
, data
);
149 dev_err(&pdev
->dev
, "MBOX_CAMARILLO_WR_INTR_CONFIG failed\n");
152 mutex_unlock(&mbox_lock
);
156 EXPORT_SYMBOL_NS_GPL(processor_thermal_mbox_interrupt_config
, "INT340X_THERMAL");
158 MODULE_LICENSE("GPL v2");
159 MODULE_DESCRIPTION("Processor Thermal Mail Box Interface");