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