]> Git Repo - linux.git/blob - drivers/platform/x86/intel/sdsi.c
platform/x86: amd-pmc: Move to later in the suspend process
[linux.git] / drivers / platform / x86 / intel / sdsi.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Intel Software Defined Silicon driver
4  *
5  * Copyright (c) 2022, Intel Corporation.
6  * All Rights Reserved.
7  *
8  * Author: "David E. Box" <[email protected]>
9  */
10
11 #include <linux/auxiliary_bus.h>
12 #include <linux/bits.h>
13 #include <linux/bitfield.h>
14 #include <linux/device.h>
15 #include <linux/iopoll.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/pci.h>
19 #include <linux/slab.h>
20 #include <linux/sysfs.h>
21 #include <linux/types.h>
22 #include <linux/uaccess.h>
23
24 #include "vsec.h"
25
26 #define ACCESS_TYPE_BARID               2
27 #define ACCESS_TYPE_LOCAL               3
28
29 #define SDSI_MIN_SIZE_DWORDS            276
30 #define SDSI_SIZE_CONTROL               8
31 #define SDSI_SIZE_MAILBOX               1024
32 #define SDSI_SIZE_REGS                  72
33 #define SDSI_SIZE_CMD                   sizeof(u64)
34
35 /*
36  * Write messages are currently up to the size of the mailbox
37  * while read messages are up to 4 times the size of the
38  * mailbox, sent in packets
39  */
40 #define SDSI_SIZE_WRITE_MSG             SDSI_SIZE_MAILBOX
41 #define SDSI_SIZE_READ_MSG              (SDSI_SIZE_MAILBOX * 4)
42
43 #define SDSI_ENABLED_FEATURES_OFFSET    16
44 #define SDSI_ENABLED                    BIT(3)
45 #define SDSI_SOCKET_ID_OFFSET           64
46 #define SDSI_SOCKET_ID                  GENMASK(3, 0)
47
48 #define SDSI_MBOX_CMD_SUCCESS           0x40
49 #define SDSI_MBOX_CMD_TIMEOUT           0x80
50
51 #define MBOX_TIMEOUT_US                 2000
52 #define MBOX_TIMEOUT_ACQUIRE_US         1000
53 #define MBOX_POLLING_PERIOD_US          100
54 #define MBOX_MAX_PACKETS                4
55
56 #define MBOX_OWNER_NONE                 0x00
57 #define MBOX_OWNER_INBAND               0x01
58
59 #define CTRL_RUN_BUSY                   BIT(0)
60 #define CTRL_READ_WRITE                 BIT(1)
61 #define CTRL_SOM                        BIT(2)
62 #define CTRL_EOM                        BIT(3)
63 #define CTRL_OWNER                      GENMASK(5, 4)
64 #define CTRL_COMPLETE                   BIT(6)
65 #define CTRL_READY                      BIT(7)
66 #define CTRL_STATUS                     GENMASK(15, 8)
67 #define CTRL_PACKET_SIZE                GENMASK(31, 16)
68 #define CTRL_MSG_SIZE                   GENMASK(63, 48)
69
70 #define DISC_TABLE_SIZE                 12
71 #define DT_ACCESS_TYPE                  GENMASK(3, 0)
72 #define DT_SIZE                         GENMASK(27, 12)
73 #define DT_TBIR                         GENMASK(2, 0)
74 #define DT_OFFSET(v)                    ((v) & GENMASK(31, 3))
75
76 enum sdsi_command {
77         SDSI_CMD_PROVISION_AKC          = 0x04,
78         SDSI_CMD_PROVISION_CAP          = 0x08,
79         SDSI_CMD_READ_STATE             = 0x10,
80 };
81
82 struct sdsi_mbox_info {
83         u64     *payload;
84         u64     *buffer;
85         int     size;
86 };
87
88 struct disc_table {
89         u32     access_info;
90         u32     guid;
91         u32     offset;
92 };
93
94 struct sdsi_priv {
95         struct mutex            mb_lock;        /* Mailbox access lock */
96         struct device           *dev;
97         void __iomem            *control_addr;
98         void __iomem            *mbox_addr;
99         void __iomem            *regs_addr;
100         u32                     guid;
101         bool                    sdsi_enabled;
102 };
103
104 /* SDSi mailbox operations must be performed using 64bit mov instructions */
105 static __always_inline void
106 sdsi_memcpy64_toio(u64 __iomem *to, const u64 *from, size_t count_bytes)
107 {
108         size_t count = count_bytes / sizeof(*to);
109         int i;
110
111         for (i = 0; i < count; i++)
112                 writeq(from[i], &to[i]);
113 }
114
115 static __always_inline void
116 sdsi_memcpy64_fromio(u64 *to, const u64 __iomem *from, size_t count_bytes)
117 {
118         size_t count = count_bytes / sizeof(*to);
119         int i;
120
121         for (i = 0; i < count; i++)
122                 to[i] = readq(&from[i]);
123 }
124
125 static inline void sdsi_complete_transaction(struct sdsi_priv *priv)
126 {
127         u64 control = FIELD_PREP(CTRL_COMPLETE, 1);
128
129         lockdep_assert_held(&priv->mb_lock);
130         writeq(control, priv->control_addr);
131 }
132
133 static int sdsi_status_to_errno(u32 status)
134 {
135         switch (status) {
136         case SDSI_MBOX_CMD_SUCCESS:
137                 return 0;
138         case SDSI_MBOX_CMD_TIMEOUT:
139                 return -ETIMEDOUT;
140         default:
141                 return -EIO;
142         }
143 }
144
145 static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
146                               size_t *data_size)
147 {
148         struct device *dev = priv->dev;
149         u32 total, loop, eom, status, message_size;
150         u64 control;
151         int ret;
152
153         lockdep_assert_held(&priv->mb_lock);
154
155         /* Format and send the read command */
156         control = FIELD_PREP(CTRL_EOM, 1) |
157                   FIELD_PREP(CTRL_SOM, 1) |
158                   FIELD_PREP(CTRL_RUN_BUSY, 1) |
159                   FIELD_PREP(CTRL_PACKET_SIZE, info->size);
160         writeq(control, priv->control_addr);
161
162         /* For reads, data sizes that are larger than the mailbox size are read in packets. */
163         total = 0;
164         loop = 0;
165         do {
166                 int offset = SDSI_SIZE_MAILBOX * loop;
167                 void __iomem *addr = priv->mbox_addr + offset;
168                 u64 *buf = info->buffer + offset / SDSI_SIZE_CMD;
169                 u32 packet_size;
170
171                 /* Poll on ready bit */
172                 ret = readq_poll_timeout(priv->control_addr, control, control & CTRL_READY,
173                                          MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_US);
174                 if (ret)
175                         break;
176
177                 eom = FIELD_GET(CTRL_EOM, control);
178                 status = FIELD_GET(CTRL_STATUS, control);
179                 packet_size = FIELD_GET(CTRL_PACKET_SIZE, control);
180                 message_size = FIELD_GET(CTRL_MSG_SIZE, control);
181
182                 ret = sdsi_status_to_errno(status);
183                 if (ret)
184                         break;
185
186                 /* Only the last packet can be less than the mailbox size. */
187                 if (!eom && packet_size != SDSI_SIZE_MAILBOX) {
188                         dev_err(dev, "Invalid packet size\n");
189                         ret = -EPROTO;
190                         break;
191                 }
192
193                 if (packet_size > SDSI_SIZE_MAILBOX) {
194                         dev_err(dev, "Packet size too large\n");
195                         ret = -EPROTO;
196                         break;
197                 }
198
199                 sdsi_memcpy64_fromio(buf, addr, round_up(packet_size, SDSI_SIZE_CMD));
200
201                 total += packet_size;
202
203                 sdsi_complete_transaction(priv);
204         } while (!eom && ++loop < MBOX_MAX_PACKETS);
205
206         if (ret) {
207                 sdsi_complete_transaction(priv);
208                 return ret;
209         }
210
211         if (!eom) {
212                 dev_err(dev, "Exceeded read attempts\n");
213                 return -EPROTO;
214         }
215
216         /* Message size check is only valid for multi-packet transfers */
217         if (loop && total != message_size)
218                 dev_warn(dev, "Read count %u differs from expected count %u\n",
219                          total, message_size);
220
221         *data_size = total;
222
223         return 0;
224 }
225
226 static int sdsi_mbox_cmd_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
227 {
228         u64 control;
229         u32 status;
230         int ret;
231
232         lockdep_assert_held(&priv->mb_lock);
233
234         /* Write rest of the payload */
235         sdsi_memcpy64_toio(priv->mbox_addr + SDSI_SIZE_CMD, info->payload + 1,
236                            info->size - SDSI_SIZE_CMD);
237
238         /* Format and send the write command */
239         control = FIELD_PREP(CTRL_EOM, 1) |
240                   FIELD_PREP(CTRL_SOM, 1) |
241                   FIELD_PREP(CTRL_RUN_BUSY, 1) |
242                   FIELD_PREP(CTRL_READ_WRITE, 1) |
243                   FIELD_PREP(CTRL_PACKET_SIZE, info->size);
244         writeq(control, priv->control_addr);
245
246         /* Poll on run_busy bit */
247         ret = readq_poll_timeout(priv->control_addr, control, !(control & CTRL_RUN_BUSY),
248                                  MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_US);
249
250         if (ret)
251                 goto release_mbox;
252
253         status = FIELD_GET(CTRL_STATUS, control);
254         ret = sdsi_status_to_errno(status);
255
256 release_mbox:
257         sdsi_complete_transaction(priv);
258
259         return ret;
260 }
261
262 static int sdsi_mbox_acquire(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
263 {
264         u64 control;
265         u32 owner;
266         int ret;
267
268         lockdep_assert_held(&priv->mb_lock);
269
270         /* Check mailbox is available */
271         control = readq(priv->control_addr);
272         owner = FIELD_GET(CTRL_OWNER, control);
273         if (owner != MBOX_OWNER_NONE)
274                 return -EBUSY;
275
276         /* Write first qword of payload */
277         writeq(info->payload[0], priv->mbox_addr);
278
279         /* Check for ownership */
280         ret = readq_poll_timeout(priv->control_addr, control,
281                                  FIELD_GET(CTRL_OWNER, control) & MBOX_OWNER_INBAND,
282                                  MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_ACQUIRE_US);
283
284         return ret;
285 }
286
287 static int sdsi_mbox_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
288 {
289         int ret;
290
291         lockdep_assert_held(&priv->mb_lock);
292
293         ret = sdsi_mbox_acquire(priv, info);
294         if (ret)
295                 return ret;
296
297         return sdsi_mbox_cmd_write(priv, info);
298 }
299
300 static int sdsi_mbox_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info, size_t *data_size)
301 {
302         int ret;
303
304         lockdep_assert_held(&priv->mb_lock);
305
306         ret = sdsi_mbox_acquire(priv, info);
307         if (ret)
308                 return ret;
309
310         return sdsi_mbox_cmd_read(priv, info, data_size);
311 }
312
313 static ssize_t sdsi_provision(struct sdsi_priv *priv, char *buf, size_t count,
314                               enum sdsi_command command)
315 {
316         struct sdsi_mbox_info info;
317         int ret;
318
319         if (!priv->sdsi_enabled)
320                 return -EPERM;
321
322         if (count > (SDSI_SIZE_WRITE_MSG - SDSI_SIZE_CMD))
323                 return -EOVERFLOW;
324
325         /* Qword aligned message + command qword */
326         info.size = round_up(count, SDSI_SIZE_CMD) + SDSI_SIZE_CMD;
327
328         info.payload = kzalloc(info.size, GFP_KERNEL);
329         if (!info.payload)
330                 return -ENOMEM;
331
332         /* Copy message to payload buffer */
333         memcpy(info.payload, buf, count);
334
335         /* Command is last qword of payload buffer */
336         info.payload[(info.size - SDSI_SIZE_CMD) / SDSI_SIZE_CMD] = command;
337
338         ret = mutex_lock_interruptible(&priv->mb_lock);
339         if (ret)
340                 goto free_payload;
341         ret = sdsi_mbox_write(priv, &info);
342         mutex_unlock(&priv->mb_lock);
343
344 free_payload:
345         kfree(info.payload);
346
347         if (ret)
348                 return ret;
349
350         return count;
351 }
352
353 static ssize_t provision_akc_write(struct file *filp, struct kobject *kobj,
354                                    struct bin_attribute *attr, char *buf, loff_t off,
355                                    size_t count)
356 {
357         struct device *dev = kobj_to_dev(kobj);
358         struct sdsi_priv *priv = dev_get_drvdata(dev);
359
360         if (off)
361                 return -ESPIPE;
362
363         return sdsi_provision(priv, buf, count, SDSI_CMD_PROVISION_AKC);
364 }
365 static BIN_ATTR_WO(provision_akc, SDSI_SIZE_WRITE_MSG);
366
367 static ssize_t provision_cap_write(struct file *filp, struct kobject *kobj,
368                                    struct bin_attribute *attr, char *buf, loff_t off,
369                                    size_t count)
370 {
371         struct device *dev = kobj_to_dev(kobj);
372         struct sdsi_priv *priv = dev_get_drvdata(dev);
373
374         if (off)
375                 return -ESPIPE;
376
377         return sdsi_provision(priv, buf, count, SDSI_CMD_PROVISION_CAP);
378 }
379 static BIN_ATTR_WO(provision_cap, SDSI_SIZE_WRITE_MSG);
380
381 static long state_certificate_read(struct file *filp, struct kobject *kobj,
382                                    struct bin_attribute *attr, char *buf, loff_t off,
383                                    size_t count)
384 {
385         struct device *dev = kobj_to_dev(kobj);
386         struct sdsi_priv *priv = dev_get_drvdata(dev);
387         u64 command = SDSI_CMD_READ_STATE;
388         struct sdsi_mbox_info info;
389         size_t size;
390         int ret;
391
392         if (!priv->sdsi_enabled)
393                 return -EPERM;
394
395         if (off)
396                 return 0;
397
398         /* Buffer for return data */
399         info.buffer = kmalloc(SDSI_SIZE_READ_MSG, GFP_KERNEL);
400         if (!info.buffer)
401                 return -ENOMEM;
402
403         info.payload = &command;
404         info.size = sizeof(command);
405
406         ret = mutex_lock_interruptible(&priv->mb_lock);
407         if (ret)
408                 goto free_buffer;
409         ret = sdsi_mbox_read(priv, &info, &size);
410         mutex_unlock(&priv->mb_lock);
411         if (ret < 0)
412                 goto free_buffer;
413
414         if (size > count)
415                 size = count;
416
417         memcpy(buf, info.buffer, size);
418
419 free_buffer:
420         kfree(info.buffer);
421
422         if (ret)
423                 return ret;
424
425         return size;
426 }
427 static BIN_ATTR(state_certificate, 0400, state_certificate_read, NULL, SDSI_SIZE_READ_MSG);
428
429 static ssize_t registers_read(struct file *filp, struct kobject *kobj,
430                               struct bin_attribute *attr, char *buf, loff_t off,
431                               size_t count)
432 {
433         struct device *dev = kobj_to_dev(kobj);
434         struct sdsi_priv *priv = dev_get_drvdata(dev);
435         void __iomem *addr = priv->regs_addr;
436
437         memcpy_fromio(buf, addr + off, count);
438
439         return count;
440 }
441 static BIN_ATTR(registers, 0400, registers_read, NULL, SDSI_SIZE_REGS);
442
443 static struct bin_attribute *sdsi_bin_attrs[] = {
444         &bin_attr_registers,
445         &bin_attr_state_certificate,
446         &bin_attr_provision_akc,
447         &bin_attr_provision_cap,
448         NULL
449 };
450
451 static ssize_t guid_show(struct device *dev, struct device_attribute *attr, char *buf)
452 {
453         struct sdsi_priv *priv = dev_get_drvdata(dev);
454
455         return sysfs_emit(buf, "0x%x\n", priv->guid);
456 }
457 static DEVICE_ATTR_RO(guid);
458
459 static struct attribute *sdsi_attrs[] = {
460         &dev_attr_guid.attr,
461         NULL
462 };
463
464 static const struct attribute_group sdsi_group = {
465         .attrs = sdsi_attrs,
466         .bin_attrs = sdsi_bin_attrs,
467 };
468 __ATTRIBUTE_GROUPS(sdsi);
469
470 static int sdsi_map_mbox_registers(struct sdsi_priv *priv, struct pci_dev *parent,
471                                    struct disc_table *disc_table, struct resource *disc_res)
472 {
473         u32 access_type = FIELD_GET(DT_ACCESS_TYPE, disc_table->access_info);
474         u32 size = FIELD_GET(DT_SIZE, disc_table->access_info);
475         u32 tbir = FIELD_GET(DT_TBIR, disc_table->offset);
476         u32 offset = DT_OFFSET(disc_table->offset);
477         u32 features_offset;
478         struct resource res = {};
479
480         /* Starting location of SDSi MMIO region based on access type */
481         switch (access_type) {
482         case ACCESS_TYPE_LOCAL:
483                 if (tbir) {
484                         dev_err(priv->dev, "Unsupported BAR index %u for access type %u\n",
485                                 tbir, access_type);
486                         return -EINVAL;
487                 }
488
489                 /*
490                  * For access_type LOCAL, the base address is as follows:
491                  * base address = end of discovery region + base offset + 1
492                  */
493                 res.start = disc_res->end + offset + 1;
494                 break;
495
496         case ACCESS_TYPE_BARID:
497                 res.start = pci_resource_start(parent, tbir) + offset;
498                 break;
499
500         default:
501                 dev_err(priv->dev, "Unrecognized access_type %u\n", access_type);
502                 return -EINVAL;
503         }
504
505         res.end = res.start + size * sizeof(u32) - 1;
506         res.flags = IORESOURCE_MEM;
507
508         priv->control_addr = devm_ioremap_resource(priv->dev, &res);
509         if (IS_ERR(priv->control_addr))
510                 return PTR_ERR(priv->control_addr);
511
512         priv->mbox_addr = priv->control_addr + SDSI_SIZE_CONTROL;
513         priv->regs_addr = priv->mbox_addr + SDSI_SIZE_MAILBOX;
514
515         features_offset = readq(priv->regs_addr + SDSI_ENABLED_FEATURES_OFFSET);
516         priv->sdsi_enabled = !!(features_offset & SDSI_ENABLED);
517
518         return 0;
519 }
520
521 static int sdsi_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id)
522 {
523         struct intel_vsec_device *intel_cap_dev = auxdev_to_ivdev(auxdev);
524         struct disc_table disc_table;
525         struct resource *disc_res;
526         void __iomem *disc_addr;
527         struct sdsi_priv *priv;
528         int ret;
529
530         priv = devm_kzalloc(&auxdev->dev, sizeof(*priv), GFP_KERNEL);
531         if (!priv)
532                 return -ENOMEM;
533
534         priv->dev = &auxdev->dev;
535         mutex_init(&priv->mb_lock);
536         auxiliary_set_drvdata(auxdev, priv);
537
538         /* Get the SDSi discovery table */
539         disc_res = &intel_cap_dev->resource[0];
540         disc_addr = devm_ioremap_resource(&auxdev->dev, disc_res);
541         if (IS_ERR(disc_addr))
542                 return PTR_ERR(disc_addr);
543
544         memcpy_fromio(&disc_table, disc_addr, DISC_TABLE_SIZE);
545
546         priv->guid = disc_table.guid;
547
548         /* Map the SDSi mailbox registers */
549         ret = sdsi_map_mbox_registers(priv, intel_cap_dev->pcidev, &disc_table, disc_res);
550         if (ret)
551                 return ret;
552
553         return 0;
554 }
555
556 static const struct auxiliary_device_id sdsi_aux_id_table[] = {
557         { .name = "intel_vsec.sdsi" },
558         {}
559 };
560 MODULE_DEVICE_TABLE(auxiliary, sdsi_aux_id_table);
561
562 static struct auxiliary_driver sdsi_aux_driver = {
563         .driver = {
564                 .dev_groups = sdsi_groups,
565         },
566         .id_table       = sdsi_aux_id_table,
567         .probe          = sdsi_probe,
568         /* No remove. All resources are handled under devm */
569 };
570 module_auxiliary_driver(sdsi_aux_driver);
571
572 MODULE_AUTHOR("David E. Box <[email protected]>");
573 MODULE_DESCRIPTION("Intel Software Defined Silicon driver");
574 MODULE_LICENSE("GPL");
This page took 0.066332 seconds and 4 git commands to generate.