1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2018-2021 Intel Corporation
4 #include <linux/bitfield.h>
5 #include <linux/peci.h>
6 #include <linux/peci-cpu.h>
7 #include <linux/slab.h>
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.
16 static DEFINE_MUTEX(peci_device_del_lock
);
18 #define REVISION_NUM_MASK GENMASK(15, 8)
19 static int peci_get_revision(struct peci_device
*device
, u8
*revision
)
21 struct peci_request
*req
;
24 req
= peci_xfer_get_dib(device
);
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.
34 dib
= peci_request_dib_read(req
);
36 peci_request_free(req
);
40 *revision
= FIELD_GET(REVISION_NUM_MASK
, dib
);
42 peci_request_free(req
);
47 static int peci_get_cpu_id(struct peci_device
*device
, u32
*cpu_id
)
49 struct peci_request
*req
;
52 req
= peci_xfer_pkg_cfg_readl(device
, PECI_PCS_PKG_ID
, PECI_PKG_ID_CPU_ID
);
56 ret
= peci_request_status(req
);
60 *cpu_id
= peci_request_data_readl(req
);
62 peci_request_free(req
);
67 static unsigned int peci_x86_cpu_family(unsigned int sig
)
71 x86
= (sig
>> 8) & 0xf;
74 x86
+= (sig
>> 20) & 0xff;
79 static unsigned int peci_x86_cpu_model(unsigned int sig
)
81 unsigned int fam
, model
;
83 fam
= peci_x86_cpu_family(sig
);
85 model
= (sig
>> 4) & 0xf;
88 model
+= ((sig
>> 16) & 0xf) << 4;
93 static int peci_device_info_init(struct peci_device
*device
)
99 ret
= peci_get_cpu_id(device
, &cpu_id
);
103 device
->info
.x86_vfm
= IFM(peci_x86_cpu_family(cpu_id
), peci_x86_cpu_model(cpu_id
));
105 ret
= peci_get_revision(device
, &revision
);
108 device
->info
.peci_revision
= revision
;
110 device
->info
.socket_id
= device
->addr
- PECI_BASE_ADDR
;
115 static int peci_detect(struct peci_controller
*controller
, u8 addr
)
118 * PECI Ping is a command encoded by tx_len = 0, rx_len = 0.
119 * We expect correct Write FCS if the device at the target address
120 * is able to respond.
122 struct peci_request req
= { 0 };
125 mutex_lock(&controller
->bus_lock
);
126 ret
= controller
->ops
->xfer(controller
, addr
, &req
);
127 mutex_unlock(&controller
->bus_lock
);
132 static bool peci_addr_valid(u8 addr
)
134 return addr
>= PECI_BASE_ADDR
&& addr
< PECI_BASE_ADDR
+ PECI_DEVICE_NUM_MAX
;
137 static int peci_dev_exists(struct device
*dev
, void *data
)
139 struct peci_device
*device
= to_peci_device(dev
);
142 if (device
->addr
== *addr
)
148 int peci_device_create(struct peci_controller
*controller
, u8 addr
)
150 struct peci_device
*device
;
153 if (!peci_addr_valid(addr
))
156 /* Check if we have already detected this device before. */
157 ret
= device_for_each_child(&controller
->dev
, &addr
, peci_dev_exists
);
161 ret
= peci_detect(controller
, addr
);
164 * Device not present or host state doesn't allow successful
165 * detection at this time.
167 if (ret
== -EIO
|| ret
== -ETIMEDOUT
)
173 device
= kzalloc(sizeof(*device
), GFP_KERNEL
);
177 device_initialize(&device
->dev
);
180 device
->dev
.parent
= &controller
->dev
;
181 device
->dev
.bus
= &peci_bus_type
;
182 device
->dev
.type
= &peci_device_type
;
184 ret
= peci_device_info_init(device
);
188 ret
= dev_set_name(&device
->dev
, "%d-%02x", controller
->id
, device
->addr
);
192 ret
= device_add(&device
->dev
);
199 put_device(&device
->dev
);
204 void peci_device_destroy(struct peci_device
*device
)
206 mutex_lock(&peci_device_del_lock
);
207 if (!device
->deleted
) {
208 device_unregister(&device
->dev
);
209 device
->deleted
= true;
211 mutex_unlock(&peci_device_del_lock
);
214 int __peci_driver_register(struct peci_driver
*driver
, struct module
*owner
,
215 const char *mod_name
)
217 driver
->driver
.bus
= &peci_bus_type
;
218 driver
->driver
.owner
= owner
;
219 driver
->driver
.mod_name
= mod_name
;
221 if (!driver
->probe
) {
222 pr_err("peci: trying to register driver without probe callback\n");
226 if (!driver
->id_table
) {
227 pr_err("peci: trying to register driver without device id table\n");
231 return driver_register(&driver
->driver
);
233 EXPORT_SYMBOL_NS_GPL(__peci_driver_register
, PECI
);
235 void peci_driver_unregister(struct peci_driver
*driver
)
237 driver_unregister(&driver
->driver
);
239 EXPORT_SYMBOL_NS_GPL(peci_driver_unregister
, PECI
);
241 static void peci_device_release(struct device
*dev
)
243 struct peci_device
*device
= to_peci_device(dev
);
248 const struct device_type peci_device_type
= {
249 .groups
= peci_device_groups
,
250 .release
= peci_device_release
,