1 // SPDX-License-Identifier: GPL-2.0-only
3 * AMD Platform Security Processor (PSP) interface
5 * Copyright (C) 2016,2019 Advanced Micro Devices, Inc.
7 * Author: Brijesh Singh <brijesh.singh@amd.com>
10 #include <linux/kernel.h>
11 #include <linux/irqreturn.h>
18 struct psp_device *psp_master;
20 static struct psp_device *psp_alloc_struct(struct sp_device *sp)
22 struct device *dev = sp->dev;
23 struct psp_device *psp;
25 psp = devm_kzalloc(dev, sizeof(*psp), GFP_KERNEL);
32 snprintf(psp->name, sizeof(psp->name), "psp-%u", sp->ord);
37 static irqreturn_t psp_irq_handler(int irq, void *data)
39 struct psp_device *psp = data;
42 /* Read the interrupt status: */
43 status = ioread32(psp->io_regs + psp->vdata->intsts_reg);
45 /* invoke subdevice interrupt handlers */
47 if (psp->sev_irq_handler)
48 psp->sev_irq_handler(irq, psp->sev_irq_data, status);
50 if (psp->tee_irq_handler)
51 psp->tee_irq_handler(irq, psp->tee_irq_data, status);
54 /* Clear the interrupt status by writing the same value we read. */
55 iowrite32(status, psp->io_regs + psp->vdata->intsts_reg);
60 static unsigned int psp_get_capability(struct psp_device *psp)
62 unsigned int val = ioread32(psp->io_regs + psp->vdata->feature_reg);
65 * Check for a access to the registers. If this read returns
66 * 0xffffffff, it's likely that the system is running a broken
67 * BIOS which disallows access to the device. Stop here and
68 * fail the PSP initialization (but not the load, as the CCP
69 * could get properly initialized).
71 if (val == 0xffffffff) {
72 dev_notice(psp->dev, "psp: unable to access the device: you might be running a broken BIOS.\n");
75 psp->capability = val;
80 static int psp_check_sev_support(struct psp_device *psp)
82 /* Check if device supports SEV feature */
83 if (!(psp->capability & PSP_CAPABILITY_SEV)) {
84 dev_dbg(psp->dev, "psp does not support SEV\n");
91 static int psp_check_tee_support(struct psp_device *psp)
93 /* Check if device supports TEE feature */
94 if (!(psp->capability & PSP_CAPABILITY_TEE)) {
95 dev_dbg(psp->dev, "psp does not support TEE\n");
102 static int psp_init(struct psp_device *psp)
106 if (!psp_check_sev_support(psp)) {
107 ret = sev_dev_init(psp);
112 if (!psp_check_tee_support(psp)) {
113 ret = tee_dev_init(psp);
121 int psp_dev_init(struct sp_device *sp)
123 struct device *dev = sp->dev;
124 struct psp_device *psp;
128 psp = psp_alloc_struct(sp);
134 psp->vdata = (struct psp_vdata *)sp->dev_vdata->psp_vdata;
137 dev_err(dev, "missing driver data\n");
141 psp->io_regs = sp->io_map;
143 ret = psp_get_capability(psp);
147 /* Disable and clear interrupts until ready */
148 iowrite32(0, psp->io_regs + psp->vdata->inten_reg);
149 iowrite32(-1, psp->io_regs + psp->vdata->intsts_reg);
152 ret = sp_request_psp_irq(psp->sp, psp_irq_handler, psp->name, psp);
154 dev_err(dev, "psp: unable to allocate an IRQ\n");
162 if (sp->set_psp_master_device)
163 sp->set_psp_master_device(sp);
165 /* Enable interrupt */
166 iowrite32(-1, psp->io_regs + psp->vdata->inten_reg);
168 dev_notice(dev, "psp enabled\n");
173 sp_free_psp_irq(psp->sp, psp);
177 dev_notice(dev, "psp initialization failed\n");
187 void psp_dev_destroy(struct sp_device *sp)
189 struct psp_device *psp = sp->psp_data;
194 sev_dev_destroy(psp);
196 tee_dev_destroy(psp);
198 sp_free_psp_irq(sp, psp);
200 if (sp->clear_psp_master_device)
201 sp->clear_psp_master_device(sp);
204 void psp_set_sev_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
207 psp->sev_irq_data = data;
208 psp->sev_irq_handler = handler;
211 void psp_clear_sev_irq_handler(struct psp_device *psp)
213 psp_set_sev_irq_handler(psp, NULL, NULL);
216 void psp_set_tee_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
219 psp->tee_irq_data = data;
220 psp->tee_irq_handler = handler;
223 void psp_clear_tee_irq_handler(struct psp_device *psp)
225 psp_set_tee_irq_handler(psp, NULL, NULL);
228 struct psp_device *psp_get_master_device(void)
230 struct sp_device *sp = sp_get_psp_master_device();
232 return sp ? sp->psp_data : NULL;
235 void psp_pci_init(void)
237 psp_master = psp_get_master_device();
245 void psp_pci_exit(void)