]> Git Repo - J-linux.git/blob - drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / thermal / intel / int340x_thermal / processor_thermal_mbox.c
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 MODULE_DESCRIPTION("Processor Thermal Mail Box Interface");
This page took 0.060208 seconds and 4 git commands to generate.