sp-pci.c 7.0 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
 * AMD Secure Processor device driver
4
 *
5
 * Copyright (C) 2013,2018 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 277 278
};

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

static const struct psp_vdata pspv1 = {
	.sev			= &sevv1,
279 280 281
	.feature_reg		= 0x105fc,
	.inten_reg		= 0x10610,
	.intsts_reg		= 0x10614,
282
};
283 284

static const struct psp_vdata pspv2 = {
285
	.sev			= &sevv2,
286 287 288 289
	.feature_reg		= 0x109fc,
	.inten_reg		= 0x10690,
	.intsts_reg		= 0x10694,
};
290 291
#endif

292
static const struct sp_dev_vdata dev_vdata[] = {
293
	{	/* 0 */
294 295 296 297 298
		.bar = 2,
#ifdef CONFIG_CRYPTO_DEV_SP_CCP
		.ccp_vdata = &ccpv3,
#endif
	},
299
	{	/* 1 */
300 301 302
		.bar = 2,
#ifdef CONFIG_CRYPTO_DEV_SP_CCP
		.ccp_vdata = &ccpv5a,
303 304
#endif
#ifdef CONFIG_CRYPTO_DEV_SP_PSP
305
		.psp_vdata = &pspv1,
306 307
#endif
	},
308
	{	/* 2 */
309 310 311
		.bar = 2,
#ifdef CONFIG_CRYPTO_DEV_SP_CCP
		.ccp_vdata = &ccpv5b,
312 313 314 315 316 317 318 319 320
#endif
	},
	{	/* 3 */
		.bar = 2,
#ifdef CONFIG_CRYPTO_DEV_SP_CCP
		.ccp_vdata = &ccpv5a,
#endif
#ifdef CONFIG_CRYPTO_DEV_SP_PSP
		.psp_vdata = &pspv2,
321 322 323
#endif
	},
};
324
static const struct pci_device_id sp_pci_table[] = {
325 326 327
	{ 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] },
328
	{ PCI_VDEVICE(AMD, 0x1486), (kernel_ulong_t)&dev_vdata[3] },
329 330 331
	/* Last entry must be zero */
	{ 0, }
};
332
MODULE_DEVICE_TABLE(pci, sp_pci_table);
333

334
static struct pci_driver sp_pci_driver = {
335
	.name = "ccp",
336 337 338
	.id_table = sp_pci_table,
	.probe = sp_pci_probe,
	.remove = sp_pci_remove,
339
#ifdef CONFIG_PM
340 341
	.suspend = sp_pci_suspend,
	.resume = sp_pci_resume,
342 343 344
#endif
};

345
int sp_pci_init(void)
346
{
347
	return pci_register_driver(&sp_pci_driver);
348 349
}

350
void sp_pci_exit(void)
351
{
352
	pci_unregister_driver(&sp_pci_driver);
353
}