1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * AMD Platform Security Processor (PSP) interface
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2016,2019 Advanced Micro Devices, Inc.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Author: Brijesh Singh <brijesh.singh@amd.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/kernel.h>
11*4882a593Smuzhiyun #include <linux/irqreturn.h>
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #include "sp-dev.h"
14*4882a593Smuzhiyun #include "psp-dev.h"
15*4882a593Smuzhiyun #include "sev-dev.h"
16*4882a593Smuzhiyun #include "tee-dev.h"
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun struct psp_device *psp_master;
19*4882a593Smuzhiyun
psp_alloc_struct(struct sp_device * sp)20*4882a593Smuzhiyun static struct psp_device *psp_alloc_struct(struct sp_device *sp)
21*4882a593Smuzhiyun {
22*4882a593Smuzhiyun struct device *dev = sp->dev;
23*4882a593Smuzhiyun struct psp_device *psp;
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun psp = devm_kzalloc(dev, sizeof(*psp), GFP_KERNEL);
26*4882a593Smuzhiyun if (!psp)
27*4882a593Smuzhiyun return NULL;
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun psp->dev = dev;
30*4882a593Smuzhiyun psp->sp = sp;
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun snprintf(psp->name, sizeof(psp->name), "psp-%u", sp->ord);
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun return psp;
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun
psp_irq_handler(int irq,void * data)37*4882a593Smuzhiyun static irqreturn_t psp_irq_handler(int irq, void *data)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun struct psp_device *psp = data;
40*4882a593Smuzhiyun unsigned int status;
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /* Read the interrupt status: */
43*4882a593Smuzhiyun status = ioread32(psp->io_regs + psp->vdata->intsts_reg);
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun /* invoke subdevice interrupt handlers */
46*4882a593Smuzhiyun if (status) {
47*4882a593Smuzhiyun if (psp->sev_irq_handler)
48*4882a593Smuzhiyun psp->sev_irq_handler(irq, psp->sev_irq_data, status);
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun if (psp->tee_irq_handler)
51*4882a593Smuzhiyun psp->tee_irq_handler(irq, psp->tee_irq_data, status);
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun /* Clear the interrupt status by writing the same value we read. */
55*4882a593Smuzhiyun iowrite32(status, psp->io_regs + psp->vdata->intsts_reg);
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun return IRQ_HANDLED;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
psp_get_capability(struct psp_device * psp)60*4882a593Smuzhiyun static unsigned int psp_get_capability(struct psp_device *psp)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun unsigned int val = ioread32(psp->io_regs + psp->vdata->feature_reg);
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun /*
65*4882a593Smuzhiyun * Check for a access to the registers. If this read returns
66*4882a593Smuzhiyun * 0xffffffff, it's likely that the system is running a broken
67*4882a593Smuzhiyun * BIOS which disallows access to the device. Stop here and
68*4882a593Smuzhiyun * fail the PSP initialization (but not the load, as the CCP
69*4882a593Smuzhiyun * could get properly initialized).
70*4882a593Smuzhiyun */
71*4882a593Smuzhiyun if (val == 0xffffffff) {
72*4882a593Smuzhiyun dev_notice(psp->dev, "psp: unable to access the device: you might be running a broken BIOS.\n");
73*4882a593Smuzhiyun return 0;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun return val;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun
psp_check_sev_support(struct psp_device * psp,unsigned int capability)79*4882a593Smuzhiyun static int psp_check_sev_support(struct psp_device *psp,
80*4882a593Smuzhiyun unsigned int capability)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun /* Check if device supports SEV feature */
83*4882a593Smuzhiyun if (!(capability & 1)) {
84*4882a593Smuzhiyun dev_dbg(psp->dev, "psp does not support SEV\n");
85*4882a593Smuzhiyun return -ENODEV;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun return 0;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
psp_check_tee_support(struct psp_device * psp,unsigned int capability)91*4882a593Smuzhiyun static int psp_check_tee_support(struct psp_device *psp,
92*4882a593Smuzhiyun unsigned int capability)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun /* Check if device supports TEE feature */
95*4882a593Smuzhiyun if (!(capability & 2)) {
96*4882a593Smuzhiyun dev_dbg(psp->dev, "psp does not support TEE\n");
97*4882a593Smuzhiyun return -ENODEV;
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun return 0;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
psp_check_support(struct psp_device * psp,unsigned int capability)103*4882a593Smuzhiyun static int psp_check_support(struct psp_device *psp,
104*4882a593Smuzhiyun unsigned int capability)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun int sev_support = psp_check_sev_support(psp, capability);
107*4882a593Smuzhiyun int tee_support = psp_check_tee_support(psp, capability);
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun /* Return error if device neither supports SEV nor TEE */
110*4882a593Smuzhiyun if (sev_support && tee_support)
111*4882a593Smuzhiyun return -ENODEV;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun return 0;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
psp_init(struct psp_device * psp,unsigned int capability)116*4882a593Smuzhiyun static int psp_init(struct psp_device *psp, unsigned int capability)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun int ret;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun if (!psp_check_sev_support(psp, capability)) {
121*4882a593Smuzhiyun ret = sev_dev_init(psp);
122*4882a593Smuzhiyun if (ret)
123*4882a593Smuzhiyun return ret;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun if (!psp_check_tee_support(psp, capability)) {
127*4882a593Smuzhiyun ret = tee_dev_init(psp);
128*4882a593Smuzhiyun if (ret)
129*4882a593Smuzhiyun return ret;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun return 0;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
psp_dev_init(struct sp_device * sp)135*4882a593Smuzhiyun int psp_dev_init(struct sp_device *sp)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun struct device *dev = sp->dev;
138*4882a593Smuzhiyun struct psp_device *psp;
139*4882a593Smuzhiyun unsigned int capability;
140*4882a593Smuzhiyun int ret;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun ret = -ENOMEM;
143*4882a593Smuzhiyun psp = psp_alloc_struct(sp);
144*4882a593Smuzhiyun if (!psp)
145*4882a593Smuzhiyun goto e_err;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun sp->psp_data = psp;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun psp->vdata = (struct psp_vdata *)sp->dev_vdata->psp_vdata;
150*4882a593Smuzhiyun if (!psp->vdata) {
151*4882a593Smuzhiyun ret = -ENODEV;
152*4882a593Smuzhiyun dev_err(dev, "missing driver data\n");
153*4882a593Smuzhiyun goto e_err;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun psp->io_regs = sp->io_map;
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun capability = psp_get_capability(psp);
159*4882a593Smuzhiyun if (!capability)
160*4882a593Smuzhiyun goto e_disable;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun ret = psp_check_support(psp, capability);
163*4882a593Smuzhiyun if (ret)
164*4882a593Smuzhiyun goto e_disable;
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun /* Disable and clear interrupts until ready */
167*4882a593Smuzhiyun iowrite32(0, psp->io_regs + psp->vdata->inten_reg);
168*4882a593Smuzhiyun iowrite32(-1, psp->io_regs + psp->vdata->intsts_reg);
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun /* Request an irq */
171*4882a593Smuzhiyun ret = sp_request_psp_irq(psp->sp, psp_irq_handler, psp->name, psp);
172*4882a593Smuzhiyun if (ret) {
173*4882a593Smuzhiyun dev_err(dev, "psp: unable to allocate an IRQ\n");
174*4882a593Smuzhiyun goto e_err;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun ret = psp_init(psp, capability);
178*4882a593Smuzhiyun if (ret)
179*4882a593Smuzhiyun goto e_irq;
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun if (sp->set_psp_master_device)
182*4882a593Smuzhiyun sp->set_psp_master_device(sp);
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun /* Enable interrupt */
185*4882a593Smuzhiyun iowrite32(-1, psp->io_regs + psp->vdata->inten_reg);
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun dev_notice(dev, "psp enabled\n");
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun return 0;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun e_irq:
192*4882a593Smuzhiyun sp_free_psp_irq(psp->sp, psp);
193*4882a593Smuzhiyun e_err:
194*4882a593Smuzhiyun sp->psp_data = NULL;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun dev_notice(dev, "psp initialization failed\n");
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun return ret;
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun e_disable:
201*4882a593Smuzhiyun sp->psp_data = NULL;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun return ret;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun
psp_dev_destroy(struct sp_device * sp)206*4882a593Smuzhiyun void psp_dev_destroy(struct sp_device *sp)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun struct psp_device *psp = sp->psp_data;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun if (!psp)
211*4882a593Smuzhiyun return;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun sev_dev_destroy(psp);
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun tee_dev_destroy(psp);
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun sp_free_psp_irq(sp, psp);
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun if (sp->clear_psp_master_device)
220*4882a593Smuzhiyun sp->clear_psp_master_device(sp);
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
psp_set_sev_irq_handler(struct psp_device * psp,psp_irq_handler_t handler,void * data)223*4882a593Smuzhiyun void psp_set_sev_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
224*4882a593Smuzhiyun void *data)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun psp->sev_irq_data = data;
227*4882a593Smuzhiyun psp->sev_irq_handler = handler;
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
psp_clear_sev_irq_handler(struct psp_device * psp)230*4882a593Smuzhiyun void psp_clear_sev_irq_handler(struct psp_device *psp)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun psp_set_sev_irq_handler(psp, NULL, NULL);
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
psp_set_tee_irq_handler(struct psp_device * psp,psp_irq_handler_t handler,void * data)235*4882a593Smuzhiyun void psp_set_tee_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
236*4882a593Smuzhiyun void *data)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun psp->tee_irq_data = data;
239*4882a593Smuzhiyun psp->tee_irq_handler = handler;
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun
psp_clear_tee_irq_handler(struct psp_device * psp)242*4882a593Smuzhiyun void psp_clear_tee_irq_handler(struct psp_device *psp)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun psp_set_tee_irq_handler(psp, NULL, NULL);
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
psp_get_master_device(void)247*4882a593Smuzhiyun struct psp_device *psp_get_master_device(void)
248*4882a593Smuzhiyun {
249*4882a593Smuzhiyun struct sp_device *sp = sp_get_psp_master_device();
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun return sp ? sp->psp_data : NULL;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
psp_pci_init(void)254*4882a593Smuzhiyun void psp_pci_init(void)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun psp_master = psp_get_master_device();
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun if (!psp_master)
259*4882a593Smuzhiyun return;
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun sev_pci_init();
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun
psp_pci_exit(void)264*4882a593Smuzhiyun void psp_pci_exit(void)
265*4882a593Smuzhiyun {
266*4882a593Smuzhiyun if (!psp_master)
267*4882a593Smuzhiyun return;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun sev_pci_exit();
270*4882a593Smuzhiyun }
271