File Index
Files and directories
Sign in
FILE

processor_thermal_mbox.c

File preview with syntax highlighting.

linux-6.19.14/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c 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
 19static DEFINE_MUTEX(mbox_lock);
 20
 21static 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
 41static 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
 60static 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
 87int 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}
 97EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_read_cmd, "INT340X_THERMAL");
 98
 99int 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}
109EXPORT_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
116int 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
151unlock:
152	mutex_unlock(&mbox_lock);
153
154	return ret;
155}
156EXPORT_SYMBOL_NS_GPL(processor_thermal_mbox_interrupt_config, "INT340X_THERMAL");
157
158MODULE_LICENSE("GPL v2");
159MODULE_DESCRIPTION("Processor Thermal Mail Box Interface");
~/ Read-only file preview.