0001
0002
0003
0004 #include <linux/auxiliary_bus.h>
0005 #include <linux/module.h>
0006 #include <linux/peci.h>
0007 #include <linux/peci-cpu.h>
0008 #include <linux/slab.h>
0009
0010 #include "internal.h"
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 int peci_temp_read(struct peci_device *device, s16 *temp_raw)
0022 {
0023 struct peci_request *req;
0024
0025 req = peci_xfer_get_temp(device);
0026 if (IS_ERR(req))
0027 return PTR_ERR(req);
0028
0029 *temp_raw = peci_request_temp_read(req);
0030
0031 peci_request_free(req);
0032
0033 return 0;
0034 }
0035 EXPORT_SYMBOL_NS_GPL(peci_temp_read, PECI_CPU);
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 int peci_pcs_read(struct peci_device *device, u8 index, u16 param, u32 *data)
0049 {
0050 struct peci_request *req;
0051 int ret;
0052
0053 req = peci_xfer_pkg_cfg_readl(device, index, param);
0054 if (IS_ERR(req))
0055 return PTR_ERR(req);
0056
0057 ret = peci_request_status(req);
0058 if (ret)
0059 goto out_req_free;
0060
0061 *data = peci_request_data_readl(req);
0062 out_req_free:
0063 peci_request_free(req);
0064
0065 return ret;
0066 }
0067 EXPORT_SYMBOL_NS_GPL(peci_pcs_read, PECI_CPU);
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 int peci_pci_local_read(struct peci_device *device, u8 bus, u8 dev, u8 func,
0083 u16 reg, u32 *data)
0084 {
0085 struct peci_request *req;
0086 int ret;
0087
0088 req = peci_xfer_pci_cfg_local_readl(device, bus, dev, func, reg);
0089 if (IS_ERR(req))
0090 return PTR_ERR(req);
0091
0092 ret = peci_request_status(req);
0093 if (ret)
0094 goto out_req_free;
0095
0096 *data = peci_request_data_readl(req);
0097 out_req_free:
0098 peci_request_free(req);
0099
0100 return ret;
0101 }
0102 EXPORT_SYMBOL_NS_GPL(peci_pci_local_read, PECI_CPU);
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118 int peci_ep_pci_local_read(struct peci_device *device, u8 seg,
0119 u8 bus, u8 dev, u8 func, u16 reg, u32 *data)
0120 {
0121 struct peci_request *req;
0122 int ret;
0123
0124 req = peci_xfer_ep_pci_cfg_local_readl(device, seg, bus, dev, func, reg);
0125 if (IS_ERR(req))
0126 return PTR_ERR(req);
0127
0128 ret = peci_request_status(req);
0129 if (ret)
0130 goto out_req_free;
0131
0132 *data = peci_request_data_readl(req);
0133 out_req_free:
0134 peci_request_free(req);
0135
0136 return ret;
0137 }
0138 EXPORT_SYMBOL_NS_GPL(peci_ep_pci_local_read, PECI_CPU);
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155 int peci_mmio_read(struct peci_device *device, u8 bar, u8 seg,
0156 u8 bus, u8 dev, u8 func, u64 address, u32 *data)
0157 {
0158 struct peci_request *req;
0159 int ret;
0160
0161 req = peci_xfer_ep_mmio64_readl(device, bar, seg, bus, dev, func, address);
0162 if (IS_ERR(req))
0163 return PTR_ERR(req);
0164
0165 ret = peci_request_status(req);
0166 if (ret)
0167 goto out_req_free;
0168
0169 *data = peci_request_data_readl(req);
0170 out_req_free:
0171 peci_request_free(req);
0172
0173 return ret;
0174 }
0175 EXPORT_SYMBOL_NS_GPL(peci_mmio_read, PECI_CPU);
0176
0177 static const char * const peci_adev_types[] = {
0178 "cputemp",
0179 "dimmtemp",
0180 };
0181
0182 struct peci_cpu {
0183 struct peci_device *device;
0184 const struct peci_device_id *id;
0185 };
0186
0187 static void adev_release(struct device *dev)
0188 {
0189 struct auxiliary_device *adev = to_auxiliary_dev(dev);
0190
0191 kfree(adev->name);
0192 kfree(adev);
0193 }
0194
0195 static struct auxiliary_device *adev_alloc(struct peci_cpu *priv, int idx)
0196 {
0197 struct peci_controller *controller = to_peci_controller(priv->device->dev.parent);
0198 struct auxiliary_device *adev;
0199 const char *name;
0200 int ret;
0201
0202 adev = kzalloc(sizeof(*adev), GFP_KERNEL);
0203 if (!adev)
0204 return ERR_PTR(-ENOMEM);
0205
0206 name = kasprintf(GFP_KERNEL, "%s.%s", peci_adev_types[idx], (const char *)priv->id->data);
0207 if (!name) {
0208 ret = -ENOMEM;
0209 goto free_adev;
0210 }
0211
0212 adev->name = name;
0213 adev->dev.parent = &priv->device->dev;
0214 adev->dev.release = adev_release;
0215 adev->id = (controller->id << 16) | (priv->device->addr);
0216
0217 ret = auxiliary_device_init(adev);
0218 if (ret)
0219 goto free_name;
0220
0221 return adev;
0222
0223 free_name:
0224 kfree(name);
0225 free_adev:
0226 kfree(adev);
0227 return ERR_PTR(ret);
0228 }
0229
0230 static void unregister_adev(void *_adev)
0231 {
0232 struct auxiliary_device *adev = _adev;
0233
0234 auxiliary_device_delete(adev);
0235 auxiliary_device_uninit(adev);
0236 }
0237
0238 static int devm_adev_add(struct device *dev, int idx)
0239 {
0240 struct peci_cpu *priv = dev_get_drvdata(dev);
0241 struct auxiliary_device *adev;
0242 int ret;
0243
0244 adev = adev_alloc(priv, idx);
0245 if (IS_ERR(adev))
0246 return PTR_ERR(adev);
0247
0248 ret = auxiliary_device_add(adev);
0249 if (ret) {
0250 auxiliary_device_uninit(adev);
0251 return ret;
0252 }
0253
0254 ret = devm_add_action_or_reset(&priv->device->dev, unregister_adev, adev);
0255 if (ret)
0256 return ret;
0257
0258 return 0;
0259 }
0260
0261 static void peci_cpu_add_adevices(struct peci_cpu *priv)
0262 {
0263 struct device *dev = &priv->device->dev;
0264 int ret, i;
0265
0266 for (i = 0; i < ARRAY_SIZE(peci_adev_types); i++) {
0267 ret = devm_adev_add(dev, i);
0268 if (ret) {
0269 dev_warn(dev, "Failed to register PECI auxiliary: %s, ret = %d\n",
0270 peci_adev_types[i], ret);
0271 continue;
0272 }
0273 }
0274 }
0275
0276 static int
0277 peci_cpu_probe(struct peci_device *device, const struct peci_device_id *id)
0278 {
0279 struct device *dev = &device->dev;
0280 struct peci_cpu *priv;
0281
0282 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0283 if (!priv)
0284 return -ENOMEM;
0285
0286 dev_set_drvdata(dev, priv);
0287 priv->device = device;
0288 priv->id = id;
0289
0290 peci_cpu_add_adevices(priv);
0291
0292 return 0;
0293 }
0294
0295 static const struct peci_device_id peci_cpu_device_ids[] = {
0296 {
0297 .family = 6,
0298 .model = INTEL_FAM6_HASWELL_X,
0299 .data = "hsx",
0300 },
0301 {
0302 .family = 6,
0303 .model = INTEL_FAM6_BROADWELL_X,
0304 .data = "bdx",
0305 },
0306 {
0307 .family = 6,
0308 .model = INTEL_FAM6_BROADWELL_D,
0309 .data = "bdxd",
0310 },
0311 {
0312 .family = 6,
0313 .model = INTEL_FAM6_SKYLAKE_X,
0314 .data = "skx",
0315 },
0316 {
0317 .family = 6,
0318 .model = INTEL_FAM6_ICELAKE_X,
0319 .data = "icx",
0320 },
0321 {
0322 .family = 6,
0323 .model = INTEL_FAM6_ICELAKE_D,
0324 .data = "icxd",
0325 },
0326 { }
0327 };
0328 MODULE_DEVICE_TABLE(peci, peci_cpu_device_ids);
0329
0330 static struct peci_driver peci_cpu_driver = {
0331 .probe = peci_cpu_probe,
0332 .id_table = peci_cpu_device_ids,
0333 .driver = {
0334 .name = "peci-cpu",
0335 },
0336 };
0337 module_peci_driver(peci_cpu_driver);
0338
0339 MODULE_AUTHOR("Iwona Winiarska <iwona.winiarska@intel.com>");
0340 MODULE_DESCRIPTION("PECI CPU driver");
0341 MODULE_LICENSE("GPL");
0342 MODULE_IMPORT_NS(PECI);