Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  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	/* invoke subdevice interrupt handlers */
 46	if (status) {
 47		if (psp->sev_irq_handler)
 48			psp->sev_irq_handler(irq, psp->sev_irq_data, status);
 49
 50		if (psp->tee_irq_handler)
 51			psp->tee_irq_handler(irq, psp->tee_irq_data, status);
 52	}
 53
 54	/* Clear the interrupt status by writing the same value we read. */
 55	iowrite32(status, psp->io_regs + psp->vdata->intsts_reg);
 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}