sp-pci.c 7.5 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
 * AMD Secure Processor device driver
4
 *
5
 * Copyright (C) 2013,2019 Advanced Micro Devices, Inc.
6 7
 *
 * Author: Tom Lendacky <thomas.lendacky@amd.com>
8
 * Author: Gary R Hook <gary.hook@amd.com>
9 10 11 12
 */

#include <linux/module.h>
#include <linux/kernel.h>
13
#include <linux/device.h>
14 15
#include <linux/pci.h>
#include <linux/pci_ids.h>
16
#include <linux/dma-mapping.h>
17 18 19 20 21 22 23 24
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/ccp.h>

#include "ccp-dev.h"
25
#include "psp-dev.h"
26 27 28

#define MSIX_VECTORS			2

29
struct sp_pci {
30
	int msix_count;
31
	struct msix_entry msix_entry[MSIX_VECTORS];
32
};
33
static struct sp_device *sp_dev_master;
34

35
static int sp_get_msix_irqs(struct sp_device *sp)
36
{
37
	struct sp_pci *sp_pci = sp->dev_specific;
38
	struct device *dev = sp->dev;
39
	struct pci_dev *pdev = to_pci_dev(dev);
40 41
	int v, ret;

42 43
	for (v = 0; v < ARRAY_SIZE(sp_pci->msix_entry); v++)
		sp_pci->msix_entry[v].entry = v;
44

45
	ret = pci_enable_msix_range(pdev, sp_pci->msix_entry, 1, v);
46
	if (ret < 0)
47 48
		return ret;

49
	sp_pci->msix_count = ret;
50
	sp->use_tasklet = true;
51

52 53 54
	sp->psp_irq = sp_pci->msix_entry[0].vector;
	sp->ccp_irq = (sp_pci->msix_count > 1) ? sp_pci->msix_entry[1].vector
					       : sp_pci->msix_entry[0].vector;
55 56 57
	return 0;
}

58
static int sp_get_msi_irq(struct sp_device *sp)
59
{
60
	struct device *dev = sp->dev;
61
	struct pci_dev *pdev = to_pci_dev(dev);
62 63 64 65 66 67
	int ret;

	ret = pci_enable_msi(pdev);
	if (ret)
		return ret;

68 69
	sp->ccp_irq = pdev->irq;
	sp->psp_irq = pdev->irq;
70 71 72 73

	return 0;
}

74
static int sp_get_irqs(struct sp_device *sp)
75
{
76
	struct device *dev = sp->dev;
77 78
	int ret;

79
	ret = sp_get_msix_irqs(sp);
80 81 82 83 84
	if (!ret)
		return 0;

	/* Couldn't get MSI-X vectors, try MSI */
	dev_notice(dev, "could not enable MSI-X (%d), trying MSI\n", ret);
85
	ret = sp_get_msi_irq(sp);
86 87 88 89 90 91 92 93 94
	if (!ret)
		return 0;

	/* Couldn't get MSI interrupt */
	dev_notice(dev, "could not enable MSI (%d)\n", ret);

	return ret;
}

95
static void sp_free_irqs(struct sp_device *sp)
96
{
97
	struct sp_pci *sp_pci = sp->dev_specific;
98
	struct device *dev = sp->dev;
99
	struct pci_dev *pdev = to_pci_dev(dev);
100

101
	if (sp_pci->msix_count)
102
		pci_disable_msix(pdev);
103
	else if (sp->psp_irq)
104
		pci_disable_msi(pdev);
105 106 107

	sp->ccp_irq = 0;
	sp->psp_irq = 0;
108 109
}

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
static bool sp_pci_is_master(struct sp_device *sp)
{
	struct device *dev_cur, *dev_new;
	struct pci_dev *pdev_cur, *pdev_new;

	dev_new = sp->dev;
	dev_cur = sp_dev_master->dev;

	pdev_new = to_pci_dev(dev_new);
	pdev_cur = to_pci_dev(dev_cur);

	if (pdev_new->bus->number < pdev_cur->bus->number)
		return true;

	if (PCI_SLOT(pdev_new->devfn) < PCI_SLOT(pdev_cur->devfn))
		return true;

	if (PCI_FUNC(pdev_new->devfn) < PCI_FUNC(pdev_cur->devfn))
		return true;

	return false;
}

static void psp_set_master(struct sp_device *sp)
{
	if (!sp_dev_master) {
		sp_dev_master = sp;
		return;
	}

	if (sp_pci_is_master(sp))
		sp_dev_master = sp;
}

static struct sp_device *psp_get_master(void)
{
	return sp_dev_master;
}

149
static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
150
{
151
	struct sp_device *sp;
152
	struct sp_pci *sp_pci;
153
	struct device *dev = &pdev->dev;
154 155
	void __iomem * const *iomap_table;
	int bar_mask;
156 157 158
	int ret;

	ret = -ENOMEM;
159 160
	sp = sp_alloc_struct(dev);
	if (!sp)
161 162
		goto e_err;

163 164
	sp_pci = devm_kzalloc(dev, sizeof(*sp_pci), GFP_KERNEL);
	if (!sp_pci)
165 166
		goto e_err;

167
	sp->dev_specific = sp_pci;
168 169
	sp->dev_vdata = (struct sp_dev_vdata *)id->driver_data;
	if (!sp->dev_vdata) {
170 171 172 173
		ret = -ENODEV;
		dev_err(dev, "missing driver data\n");
		goto e_err;
	}
174

175
	ret = pcim_enable_device(pdev);
176
	if (ret) {
177
		dev_err(dev, "pcim_enable_device failed (%d)\n", ret);
178
		goto e_err;
179 180
	}

181 182
	bar_mask = pci_select_bars(pdev, IORESOURCE_MEM);
	ret = pcim_iomap_regions(pdev, bar_mask, "ccp");
183
	if (ret) {
184 185
		dev_err(dev, "pcim_iomap_regions failed (%d)\n", ret);
		goto e_err;
186 187
	}

188 189 190 191 192 193
	iomap_table = pcim_iomap_table(pdev);
	if (!iomap_table) {
		dev_err(dev, "pcim_iomap_table failed\n");
		ret = -ENOMEM;
		goto e_err;
	}
194

195 196
	sp->io_map = iomap_table[sp->dev_vdata->bar];
	if (!sp->io_map) {
197 198 199
		dev_err(dev, "ioremap failed\n");
		ret = -ENOMEM;
		goto e_err;
200
	}
201

202
	ret = sp_get_irqs(sp);
203 204 205
	if (ret)
		goto e_err;

206
	pci_set_master(pdev);
207 208
	sp->set_psp_master_device = psp_set_master;
	sp->get_psp_master_device = psp_get_master;
209

210 211 212
	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
	if (ret) {
		ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
213
		if (ret) {
214
			dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n",
215
				ret);
216
			goto e_err;
217 218 219
		}
	}

220
	dev_set_drvdata(dev, sp);
221

222
	ret = sp_init(sp);
223
	if (ret)
224
		goto e_err;
225 226 227 228 229 230 231 232

	return 0;

e_err:
	dev_notice(dev, "initialization failed\n");
	return ret;
}

233
static void sp_pci_remove(struct pci_dev *pdev)
234 235
{
	struct device *dev = &pdev->dev;
236
	struct sp_device *sp = dev_get_drvdata(dev);
237

238
	if (!sp)
239 240
		return;

241
	sp_destroy(sp);
242

243
	sp_free_irqs(sp);
244 245 246
}

#ifdef CONFIG_PM
247
static int sp_pci_suspend(struct pci_dev *pdev, pm_message_t state)
248 249
{
	struct device *dev = &pdev->dev;
250
	struct sp_device *sp = dev_get_drvdata(dev);
251

252
	return sp_suspend(sp, state);
253 254
}

255
static int sp_pci_resume(struct pci_dev *pdev)
256 257
{
	struct device *dev = &pdev->dev;
258
	struct sp_device *sp = dev_get_drvdata(dev);
259

260
	return sp_resume(sp);
261 262 263
}
#endif

264
#ifdef CONFIG_CRYPTO_DEV_SP_PSP
265
static const struct sev_vdata sevv1 = {
266 267 268
	.cmdresp_reg		= 0x10580,
	.cmdbuff_addr_lo_reg	= 0x105e0,
	.cmdbuff_addr_hi_reg	= 0x105e4,
269 270 271 272 273 274 275 276
};

static const struct sev_vdata sevv2 = {
	.cmdresp_reg		= 0x10980,
	.cmdbuff_addr_lo_reg	= 0x109e0,
	.cmdbuff_addr_hi_reg	= 0x109e4,
};

277 278 279 280 281 282 283 284
static const struct tee_vdata teev1 = {
	.cmdresp_reg		= 0x10544,
	.cmdbuff_addr_lo_reg	= 0x10548,
	.cmdbuff_addr_hi_reg	= 0x1054c,
	.ring_wptr_reg          = 0x10550,
	.ring_rptr_reg          = 0x10554,
};

285 286
static const struct psp_vdata pspv1 = {
	.sev			= &sevv1,
287 288 289
	.feature_reg		= 0x105fc,
	.inten_reg		= 0x10610,
	.intsts_reg		= 0x10614,
290
};
291 292

static const struct psp_vdata pspv2 = {
293
	.sev			= &sevv2,
294 295 296 297
	.feature_reg		= 0x109fc,
	.inten_reg		= 0x10690,
	.intsts_reg		= 0x10694,
};
298 299 300 301 302 303 304

static const struct psp_vdata pspv3 = {
	.tee			= &teev1,
	.feature_reg		= 0x109fc,
	.inten_reg		= 0x10690,
	.intsts_reg		= 0x10694,
};
305 306
#endif

307
static const struct sp_dev_vdata dev_vdata[] = {
308
	{	/* 0 */
309 310 311 312 313
		.bar = 2,
#ifdef CONFIG_CRYPTO_DEV_SP_CCP
		.ccp_vdata = &ccpv3,
#endif
	},
314
	{	/* 1 */
315 316 317
		.bar = 2,
#ifdef CONFIG_CRYPTO_DEV_SP_CCP
		.ccp_vdata = &ccpv5a,
318 319
#endif
#ifdef CONFIG_CRYPTO_DEV_SP_PSP
320
		.psp_vdata = &pspv1,
321 322
#endif
	},
323
	{	/* 2 */
324 325 326
		.bar = 2,
#ifdef CONFIG_CRYPTO_DEV_SP_CCP
		.ccp_vdata = &ccpv5b,
327 328 329 330 331 332 333 334 335
#endif
	},
	{	/* 3 */
		.bar = 2,
#ifdef CONFIG_CRYPTO_DEV_SP_CCP
		.ccp_vdata = &ccpv5a,
#endif
#ifdef CONFIG_CRYPTO_DEV_SP_PSP
		.psp_vdata = &pspv2,
336 337 338 339 340 341 342 343 344
#endif
	},
	{	/* 4 */
		.bar = 2,
#ifdef CONFIG_CRYPTO_DEV_SP_CCP
		.ccp_vdata = &ccpv5a,
#endif
#ifdef CONFIG_CRYPTO_DEV_SP_PSP
		.psp_vdata = &pspv3,
345 346 347
#endif
	},
};
348
static const struct pci_device_id sp_pci_table[] = {
349 350 351
	{ PCI_VDEVICE(AMD, 0x1537), (kernel_ulong_t)&dev_vdata[0] },
	{ PCI_VDEVICE(AMD, 0x1456), (kernel_ulong_t)&dev_vdata[1] },
	{ PCI_VDEVICE(AMD, 0x1468), (kernel_ulong_t)&dev_vdata[2] },
352
	{ PCI_VDEVICE(AMD, 0x1486), (kernel_ulong_t)&dev_vdata[3] },
353
	{ PCI_VDEVICE(AMD, 0x15DF), (kernel_ulong_t)&dev_vdata[4] },
354 355 356
	/* Last entry must be zero */
	{ 0, }
};
357
MODULE_DEVICE_TABLE(pci, sp_pci_table);
358

359
static struct pci_driver sp_pci_driver = {
360
	.name = "ccp",
361 362 363
	.id_table = sp_pci_table,
	.probe = sp_pci_probe,
	.remove = sp_pci_remove,
364
#ifdef CONFIG_PM
365 366
	.suspend = sp_pci_suspend,
	.resume = sp_pci_resume,
367 368 369
#endif
};

370
int sp_pci_init(void)
371
{
372
	return pci_register_driver(&sp_pci_driver);
373 374
}

375
void sp_pci_exit(void)
376
{
377
	pci_unregister_driver(&sp_pci_driver);
378
}