1// SPDX-License-Identifier: GPL-2.0-only
2// Copyright (c) 2018-2021 Intel Corporation
3
4#include <linux/bitfield.h>
5#include <linux/peci.h>
6#include <linux/peci-cpu.h>
7#include <linux/slab.h>
8
9#include "internal.h"
10
11/*
12 * PECI device can be removed using sysfs, but the removal can also happen as
13 * a result of controller being removed.
14 * Mutex is used to protect PECI device from being double-deleted.
15 */
16static DEFINE_MUTEX(peci_device_del_lock);
17
18#define REVISION_NUM_MASK GENMASK(15, 8)
19static int peci_get_revision(struct peci_device *device, u8 *revision)
20{
21	struct peci_request *req;
22	u64 dib;
23
24	req = peci_xfer_get_dib(device);
25	if (IS_ERR(req))
26		return PTR_ERR(req);
27
28	/*
29	 * PECI device may be in a state where it is unable to return a proper
30	 * DIB, in which case it returns 0 as DIB value.
31	 * Let's treat this as an error to avoid carrying on with the detection
32	 * using invalid revision.
33	 */
34	dib = peci_request_dib_read(req);
35	if (dib == 0) {
36		peci_request_free(req);
37		return -EIO;
38	}
39
40	*revision = FIELD_GET(REVISION_NUM_MASK, dib);
41
42	peci_request_free(req);
43
44	return 0;
45}
46
47static int peci_get_cpu_id(struct peci_device *device, u32 *cpu_id)
48{
49	struct peci_request *req;
50	int ret;
51
52	req = peci_xfer_pkg_cfg_readl(device, PECI_PCS_PKG_ID, PECI_PKG_ID_CPU_ID);
53	if (IS_ERR(req))
54		return PTR_ERR(req);
55
56	ret = peci_request_status(req);
57	if (ret)
58		goto out_req_free;
59
60	*cpu_id = peci_request_data_readl(req);
61out_req_free:
62	peci_request_free(req);
63
64	return ret;
65}
66
67static unsigned int peci_x86_cpu_family(unsigned int sig)
68{
69	unsigned int x86;
70
71	x86 = (sig >> 8) & 0xf;
72
73	if (x86 == 0xf)
74		x86 += (sig >> 20) & 0xff;
75
76	return x86;
77}
78
79static unsigned int peci_x86_cpu_model(unsigned int sig)
80{
81	unsigned int fam, model;
82
83	fam = peci_x86_cpu_family(sig);
84
85	model = (sig >> 4) & 0xf;
86
87	if (fam >= 0x6)
88		model += ((sig >> 16) & 0xf) << 4;
89
90	return model;
91}
92
93static int peci_device_info_init(struct peci_device *device)
94{
95	u8 revision;
96	u32 cpu_id;
97	int ret;
98
99	ret = peci_get_cpu_id(device, &cpu_id);
100	if (ret)
101		return ret;
102
103	device->info.family = peci_x86_cpu_family(cpu_id);
104	device->info.model = peci_x86_cpu_model(cpu_id);
105
106	ret = peci_get_revision(device, &revision);
107	if (ret)
108		return ret;
109	device->info.peci_revision = revision;
110
111	device->info.socket_id = device->addr - PECI_BASE_ADDR;
112
113	return 0;
114}
115
116static int peci_detect(struct peci_controller *controller, u8 addr)
117{
118	/*
119	 * PECI Ping is a command encoded by tx_len = 0, rx_len = 0.
120	 * We expect correct Write FCS if the device at the target address
121	 * is able to respond.
122	 */
123	struct peci_request req = { 0 };
124	int ret;
125
126	mutex_lock(&controller->bus_lock);
127	ret = controller->ops->xfer(controller, addr, &req);
128	mutex_unlock(&controller->bus_lock);
129
130	return ret;
131}
132
133static bool peci_addr_valid(u8 addr)
134{
135	return addr >= PECI_BASE_ADDR && addr < PECI_BASE_ADDR + PECI_DEVICE_NUM_MAX;
136}
137
138static int peci_dev_exists(struct device *dev, void *data)
139{
140	struct peci_device *device = to_peci_device(dev);
141	u8 *addr = data;
142
143	if (device->addr == *addr)
144		return -EBUSY;
145
146	return 0;
147}
148
149int peci_device_create(struct peci_controller *controller, u8 addr)
150{
151	struct peci_device *device;
152	int ret;
153
154	if (!peci_addr_valid(addr))
155		return -EINVAL;
156
157	/* Check if we have already detected this device before. */
158	ret = device_for_each_child(&controller->dev, &addr, peci_dev_exists);
159	if (ret)
160		return 0;
161
162	ret = peci_detect(controller, addr);
163	if (ret) {
164		/*
165		 * Device not present or host state doesn't allow successful
166		 * detection at this time.
167		 */
168		if (ret == -EIO || ret == -ETIMEDOUT)
169			return 0;
170
171		return ret;
172	}
173
174	device = kzalloc(sizeof(*device), GFP_KERNEL);
175	if (!device)
176		return -ENOMEM;
177
178	device_initialize(&device->dev);
179
180	device->addr = addr;
181	device->dev.parent = &controller->dev;
182	device->dev.bus = &peci_bus_type;
183	device->dev.type = &peci_device_type;
184
185	ret = peci_device_info_init(device);
186	if (ret)
187		goto err_put;
188
189	ret = dev_set_name(&device->dev, "%d-%02x", controller->id, device->addr);
190	if (ret)
191		goto err_put;
192
193	ret = device_add(&device->dev);
194	if (ret)
195		goto err_put;
196
197	return 0;
198
199err_put:
200	put_device(&device->dev);
201
202	return ret;
203}
204
205void peci_device_destroy(struct peci_device *device)
206{
207	mutex_lock(&peci_device_del_lock);
208	if (!device->deleted) {
209		device_unregister(&device->dev);
210		device->deleted = true;
211	}
212	mutex_unlock(&peci_device_del_lock);
213}
214
215int __peci_driver_register(struct peci_driver *driver, struct module *owner,
216			   const char *mod_name)
217{
218	driver->driver.bus = &peci_bus_type;
219	driver->driver.owner = owner;
220	driver->driver.mod_name = mod_name;
221
222	if (!driver->probe) {
223		pr_err("peci: trying to register driver without probe callback\n");
224		return -EINVAL;
225	}
226
227	if (!driver->id_table) {
228		pr_err("peci: trying to register driver without device id table\n");
229		return -EINVAL;
230	}
231
232	return driver_register(&driver->driver);
233}
234EXPORT_SYMBOL_NS_GPL(__peci_driver_register, PECI);
235
236void peci_driver_unregister(struct peci_driver *driver)
237{
238	driver_unregister(&driver->driver);
239}
240EXPORT_SYMBOL_NS_GPL(peci_driver_unregister, PECI);
241
242static void peci_device_release(struct device *dev)
243{
244	struct peci_device *device = to_peci_device(dev);
245
246	kfree(device);
247}
248
249struct device_type peci_device_type = {
250	.groups		= peci_device_groups,
251	.release	= peci_device_release,
252};
253