xref: /linux/drivers/crypto/ccp/sp-pci.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2d0ebbc0cSBrijesh Singh /*
3d0ebbc0cSBrijesh Singh  * AMD Secure Processor device driver
4d0ebbc0cSBrijesh Singh  *
533960accSRijo Thomas  * Copyright (C) 2013,2019 Advanced Micro Devices, Inc.
6d0ebbc0cSBrijesh Singh  *
7d0ebbc0cSBrijesh Singh  * Author: Tom Lendacky <thomas.lendacky@amd.com>
8d0ebbc0cSBrijesh Singh  * Author: Gary R Hook <gary.hook@amd.com>
9d0ebbc0cSBrijesh Singh  */
10d0ebbc0cSBrijesh Singh 
112e424c33SMario Limonciello #include <linux/bitfield.h>
12d0ebbc0cSBrijesh Singh #include <linux/module.h>
13d0ebbc0cSBrijesh Singh #include <linux/kernel.h>
14d0ebbc0cSBrijesh Singh #include <linux/device.h>
15d0ebbc0cSBrijesh Singh #include <linux/pci.h>
16d0ebbc0cSBrijesh Singh #include <linux/pci_ids.h>
17d0ebbc0cSBrijesh Singh #include <linux/dma-mapping.h>
18d0ebbc0cSBrijesh Singh #include <linux/kthread.h>
19d0ebbc0cSBrijesh Singh #include <linux/sched.h>
20d0ebbc0cSBrijesh Singh #include <linux/interrupt.h>
21d0ebbc0cSBrijesh Singh #include <linux/spinlock.h>
22d0ebbc0cSBrijesh Singh #include <linux/delay.h>
23d0ebbc0cSBrijesh Singh #include <linux/ccp.h>
24d0ebbc0cSBrijesh Singh 
25d0ebbc0cSBrijesh Singh #include "ccp-dev.h"
26b93566f1SRijo Thomas #include "psp-dev.h"
2756e0d883SMario Limonciello #include "hsti.h"
28d0ebbc0cSBrijesh Singh 
292e424c33SMario Limonciello /* used for version string AA.BB.CC.DD */
302e424c33SMario Limonciello #define AA				GENMASK(31, 24)
312e424c33SMario Limonciello #define BB				GENMASK(23, 16)
322e424c33SMario Limonciello #define CC				GENMASK(15, 8)
332e424c33SMario Limonciello #define DD				GENMASK(7, 0)
342e424c33SMario Limonciello 
35d0ebbc0cSBrijesh Singh #define MSIX_VECTORS			2
36d0ebbc0cSBrijesh Singh 
37d0ebbc0cSBrijesh Singh struct sp_pci {
38d0ebbc0cSBrijesh Singh 	int msix_count;
39d0ebbc0cSBrijesh Singh 	struct msix_entry msix_entry[MSIX_VECTORS];
40d0ebbc0cSBrijesh Singh };
412a6170dfSBrijesh Singh static struct sp_device *sp_dev_master;
42d0ebbc0cSBrijesh Singh 
432e424c33SMario Limonciello #define version_attribute_show(name, _offset)					\
442e424c33SMario Limonciello static ssize_t name##_show(struct device *d, struct device_attribute *attr,	\
452e424c33SMario Limonciello 			   char *buf)						\
462e424c33SMario Limonciello {										\
472e424c33SMario Limonciello 	struct sp_device *sp = dev_get_drvdata(d);				\
482e424c33SMario Limonciello 	struct psp_device *psp = sp->psp_data;					\
492e424c33SMario Limonciello 	unsigned int val = ioread32(psp->io_regs + _offset);			\
502e424c33SMario Limonciello 	return sysfs_emit(buf, "%02lx.%02lx.%02lx.%02lx\n",			\
512e424c33SMario Limonciello 			  FIELD_GET(AA, val),			\
522e424c33SMario Limonciello 			  FIELD_GET(BB, val),			\
532e424c33SMario Limonciello 			  FIELD_GET(CC, val),			\
542e424c33SMario Limonciello 			  FIELD_GET(DD, val));			\
552e424c33SMario Limonciello }
562e424c33SMario Limonciello 
572e424c33SMario Limonciello version_attribute_show(bootloader_version, psp->vdata->bootloader_info_reg)
582e424c33SMario Limonciello static DEVICE_ATTR_RO(bootloader_version);
592e424c33SMario Limonciello version_attribute_show(tee_version, psp->vdata->tee->info_reg)
602e424c33SMario Limonciello static DEVICE_ATTR_RO(tee_version);
612e424c33SMario Limonciello 
622e424c33SMario Limonciello static struct attribute *psp_firmware_attrs[] = {
632e424c33SMario Limonciello 	&dev_attr_bootloader_version.attr,
642e424c33SMario Limonciello 	&dev_attr_tee_version.attr,
652e424c33SMario Limonciello 	NULL,
662e424c33SMario Limonciello };
672e424c33SMario Limonciello 
psp_firmware_is_visible(struct kobject * kobj,struct attribute * attr,int idx)682e424c33SMario Limonciello static umode_t psp_firmware_is_visible(struct kobject *kobj, struct attribute *attr, int idx)
692e424c33SMario Limonciello {
702e424c33SMario Limonciello 	struct device *dev = kobj_to_dev(kobj);
712e424c33SMario Limonciello 	struct sp_device *sp = dev_get_drvdata(dev);
722e424c33SMario Limonciello 	struct psp_device *psp = sp->psp_data;
732e424c33SMario Limonciello 	unsigned int val = 0xffffffff;
742e424c33SMario Limonciello 
752e424c33SMario Limonciello 	if (!psp)
762e424c33SMario Limonciello 		return 0;
772e424c33SMario Limonciello 
782e424c33SMario Limonciello 	if (attr == &dev_attr_bootloader_version.attr &&
792e424c33SMario Limonciello 	    psp->vdata->bootloader_info_reg)
802e424c33SMario Limonciello 		val = ioread32(psp->io_regs + psp->vdata->bootloader_info_reg);
812e424c33SMario Limonciello 
828609dd25SMario Limonciello 	if (attr == &dev_attr_tee_version.attr && psp->capability.tee &&
832e424c33SMario Limonciello 	    psp->vdata->tee->info_reg)
842e424c33SMario Limonciello 		val = ioread32(psp->io_regs + psp->vdata->tee->info_reg);
852e424c33SMario Limonciello 
862e424c33SMario Limonciello 	/* If platform disallows accessing this register it will be all f's */
872e424c33SMario Limonciello 	if (val != 0xffffffff)
882e424c33SMario Limonciello 		return 0444;
892e424c33SMario Limonciello 
902e424c33SMario Limonciello 	return 0;
912e424c33SMario Limonciello }
922e424c33SMario Limonciello 
932e424c33SMario Limonciello static struct attribute_group psp_firmware_attr_group = {
942e424c33SMario Limonciello 	.attrs = psp_firmware_attrs,
952e424c33SMario Limonciello 	.is_visible = psp_firmware_is_visible,
962e424c33SMario Limonciello };
972e424c33SMario Limonciello 
9850c4deccSMario Limonciello static const struct attribute_group *psp_groups[] = {
9956e0d883SMario Limonciello #ifdef CONFIG_CRYPTO_DEV_SP_PSP
100b5827637SMario Limonciello 	&psp_security_attr_group,
10156e0d883SMario Limonciello #endif
1022e424c33SMario Limonciello 	&psp_firmware_attr_group,
10350c4deccSMario Limonciello 	NULL,
10450c4deccSMario Limonciello };
10550c4deccSMario Limonciello 
sp_get_msix_irqs(struct sp_device * sp)106d0ebbc0cSBrijesh Singh static int sp_get_msix_irqs(struct sp_device *sp)
107d0ebbc0cSBrijesh Singh {
108d0ebbc0cSBrijesh Singh 	struct sp_pci *sp_pci = sp->dev_specific;
109d0ebbc0cSBrijesh Singh 	struct device *dev = sp->dev;
110d0ebbc0cSBrijesh Singh 	struct pci_dev *pdev = to_pci_dev(dev);
111d0ebbc0cSBrijesh Singh 	int v, ret;
112d0ebbc0cSBrijesh Singh 
113d0ebbc0cSBrijesh Singh 	for (v = 0; v < ARRAY_SIZE(sp_pci->msix_entry); v++)
114d0ebbc0cSBrijesh Singh 		sp_pci->msix_entry[v].entry = v;
115d0ebbc0cSBrijesh Singh 
116d0ebbc0cSBrijesh Singh 	ret = pci_enable_msix_range(pdev, sp_pci->msix_entry, 1, v);
117d0ebbc0cSBrijesh Singh 	if (ret < 0)
118d0ebbc0cSBrijesh Singh 		return ret;
119d0ebbc0cSBrijesh Singh 
120d0ebbc0cSBrijesh Singh 	sp_pci->msix_count = ret;
121d0ebbc0cSBrijesh Singh 	sp->use_tasklet = true;
122d0ebbc0cSBrijesh Singh 
123d0ebbc0cSBrijesh Singh 	sp->psp_irq = sp_pci->msix_entry[0].vector;
124d0ebbc0cSBrijesh Singh 	sp->ccp_irq = (sp_pci->msix_count > 1) ? sp_pci->msix_entry[1].vector
125d0ebbc0cSBrijesh Singh 					       : sp_pci->msix_entry[0].vector;
126d0ebbc0cSBrijesh Singh 	return 0;
127d0ebbc0cSBrijesh Singh }
128d0ebbc0cSBrijesh Singh 
sp_get_msi_irq(struct sp_device * sp)129d0ebbc0cSBrijesh Singh static int sp_get_msi_irq(struct sp_device *sp)
130d0ebbc0cSBrijesh Singh {
131d0ebbc0cSBrijesh Singh 	struct device *dev = sp->dev;
132d0ebbc0cSBrijesh Singh 	struct pci_dev *pdev = to_pci_dev(dev);
133d0ebbc0cSBrijesh Singh 	int ret;
134d0ebbc0cSBrijesh Singh 
135d0ebbc0cSBrijesh Singh 	ret = pci_enable_msi(pdev);
136d0ebbc0cSBrijesh Singh 	if (ret)
137d0ebbc0cSBrijesh Singh 		return ret;
138d0ebbc0cSBrijesh Singh 
139d0ebbc0cSBrijesh Singh 	sp->ccp_irq = pdev->irq;
140d0ebbc0cSBrijesh Singh 	sp->psp_irq = pdev->irq;
141d0ebbc0cSBrijesh Singh 
142d0ebbc0cSBrijesh Singh 	return 0;
143d0ebbc0cSBrijesh Singh }
144d0ebbc0cSBrijesh Singh 
sp_get_irqs(struct sp_device * sp)145d0ebbc0cSBrijesh Singh static int sp_get_irqs(struct sp_device *sp)
146d0ebbc0cSBrijesh Singh {
147d0ebbc0cSBrijesh Singh 	struct device *dev = sp->dev;
148d0ebbc0cSBrijesh Singh 	int ret;
149d0ebbc0cSBrijesh Singh 
150d0ebbc0cSBrijesh Singh 	ret = sp_get_msix_irqs(sp);
151d0ebbc0cSBrijesh Singh 	if (!ret)
152d0ebbc0cSBrijesh Singh 		return 0;
153d0ebbc0cSBrijesh Singh 
154d0ebbc0cSBrijesh Singh 	/* Couldn't get MSI-X vectors, try MSI */
155d0ebbc0cSBrijesh Singh 	dev_notice(dev, "could not enable MSI-X (%d), trying MSI\n", ret);
156d0ebbc0cSBrijesh Singh 	ret = sp_get_msi_irq(sp);
157d0ebbc0cSBrijesh Singh 	if (!ret)
158d0ebbc0cSBrijesh Singh 		return 0;
159d0ebbc0cSBrijesh Singh 
160d0ebbc0cSBrijesh Singh 	/* Couldn't get MSI interrupt */
161d0ebbc0cSBrijesh Singh 	dev_notice(dev, "could not enable MSI (%d)\n", ret);
162d0ebbc0cSBrijesh Singh 
163d0ebbc0cSBrijesh Singh 	return ret;
164d0ebbc0cSBrijesh Singh }
165d0ebbc0cSBrijesh Singh 
sp_free_irqs(struct sp_device * sp)166d0ebbc0cSBrijesh Singh static void sp_free_irqs(struct sp_device *sp)
167d0ebbc0cSBrijesh Singh {
168d0ebbc0cSBrijesh Singh 	struct sp_pci *sp_pci = sp->dev_specific;
169d0ebbc0cSBrijesh Singh 	struct device *dev = sp->dev;
170d0ebbc0cSBrijesh Singh 	struct pci_dev *pdev = to_pci_dev(dev);
171d0ebbc0cSBrijesh Singh 
172d0ebbc0cSBrijesh Singh 	if (sp_pci->msix_count)
173d0ebbc0cSBrijesh Singh 		pci_disable_msix(pdev);
174d0ebbc0cSBrijesh Singh 	else if (sp->psp_irq)
175d0ebbc0cSBrijesh Singh 		pci_disable_msi(pdev);
176d0ebbc0cSBrijesh Singh 
177d0ebbc0cSBrijesh Singh 	sp->ccp_irq = 0;
178d0ebbc0cSBrijesh Singh 	sp->psp_irq = 0;
179d0ebbc0cSBrijesh Singh }
180d0ebbc0cSBrijesh Singh 
sp_pci_is_master(struct sp_device * sp)1812a6170dfSBrijesh Singh static bool sp_pci_is_master(struct sp_device *sp)
1822a6170dfSBrijesh Singh {
1832a6170dfSBrijesh Singh 	struct device *dev_cur, *dev_new;
1842a6170dfSBrijesh Singh 	struct pci_dev *pdev_cur, *pdev_new;
1852a6170dfSBrijesh Singh 
1862a6170dfSBrijesh Singh 	dev_new = sp->dev;
1872a6170dfSBrijesh Singh 	dev_cur = sp_dev_master->dev;
1882a6170dfSBrijesh Singh 
1892a6170dfSBrijesh Singh 	pdev_new = to_pci_dev(dev_new);
1902a6170dfSBrijesh Singh 	pdev_cur = to_pci_dev(dev_cur);
1912a6170dfSBrijesh Singh 
1922a6170dfSBrijesh Singh 	if (pdev_new->bus->number < pdev_cur->bus->number)
1932a6170dfSBrijesh Singh 		return true;
1942a6170dfSBrijesh Singh 
1952a6170dfSBrijesh Singh 	if (PCI_SLOT(pdev_new->devfn) < PCI_SLOT(pdev_cur->devfn))
1962a6170dfSBrijesh Singh 		return true;
1972a6170dfSBrijesh Singh 
1982a6170dfSBrijesh Singh 	if (PCI_FUNC(pdev_new->devfn) < PCI_FUNC(pdev_cur->devfn))
1992a6170dfSBrijesh Singh 		return true;
2002a6170dfSBrijesh Singh 
2012a6170dfSBrijesh Singh 	return false;
2022a6170dfSBrijesh Singh }
2032a6170dfSBrijesh Singh 
psp_set_master(struct sp_device * sp)2042a6170dfSBrijesh Singh static void psp_set_master(struct sp_device *sp)
2052a6170dfSBrijesh Singh {
2062a6170dfSBrijesh Singh 	if (!sp_dev_master) {
2072a6170dfSBrijesh Singh 		sp_dev_master = sp;
2082a6170dfSBrijesh Singh 		return;
2092a6170dfSBrijesh Singh 	}
2102a6170dfSBrijesh Singh 
2112a6170dfSBrijesh Singh 	if (sp_pci_is_master(sp))
2122a6170dfSBrijesh Singh 		sp_dev_master = sp;
2132a6170dfSBrijesh Singh }
2142a6170dfSBrijesh Singh 
psp_get_master(void)2152a6170dfSBrijesh Singh static struct sp_device *psp_get_master(void)
2162a6170dfSBrijesh Singh {
2172a6170dfSBrijesh Singh 	return sp_dev_master;
2182a6170dfSBrijesh Singh }
2192a6170dfSBrijesh Singh 
psp_clear_master(struct sp_device * sp)22015f7a4c6SJohn Allen static void psp_clear_master(struct sp_device *sp)
22115f7a4c6SJohn Allen {
22215f7a4c6SJohn Allen 	if (sp == sp_dev_master) {
22315f7a4c6SJohn Allen 		sp_dev_master = NULL;
22415f7a4c6SJohn Allen 		dev_dbg(sp->dev, "Cleared sp_dev_master\n");
22515f7a4c6SJohn Allen 	}
22615f7a4c6SJohn Allen }
22715f7a4c6SJohn Allen 
sp_pci_probe(struct pci_dev * pdev,const struct pci_device_id * id)228d0ebbc0cSBrijesh Singh static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
229d0ebbc0cSBrijesh Singh {
230d0ebbc0cSBrijesh Singh 	struct sp_device *sp;
231d0ebbc0cSBrijesh Singh 	struct sp_pci *sp_pci;
232d0ebbc0cSBrijesh Singh 	struct device *dev = &pdev->dev;
233d0ebbc0cSBrijesh Singh 	void __iomem * const *iomap_table;
234d0ebbc0cSBrijesh Singh 	int bar_mask;
235d0ebbc0cSBrijesh Singh 	int ret;
236d0ebbc0cSBrijesh Singh 
237d0ebbc0cSBrijesh Singh 	ret = -ENOMEM;
238d0ebbc0cSBrijesh Singh 	sp = sp_alloc_struct(dev);
239d0ebbc0cSBrijesh Singh 	if (!sp)
240d0ebbc0cSBrijesh Singh 		goto e_err;
241d0ebbc0cSBrijesh Singh 
242d0ebbc0cSBrijesh Singh 	sp_pci = devm_kzalloc(dev, sizeof(*sp_pci), GFP_KERNEL);
243d0ebbc0cSBrijesh Singh 	if (!sp_pci)
244d0ebbc0cSBrijesh Singh 		goto e_err;
245d0ebbc0cSBrijesh Singh 
246d0ebbc0cSBrijesh Singh 	sp->dev_specific = sp_pci;
247d0ebbc0cSBrijesh Singh 	sp->dev_vdata = (struct sp_dev_vdata *)id->driver_data;
248d0ebbc0cSBrijesh Singh 	if (!sp->dev_vdata) {
249d0ebbc0cSBrijesh Singh 		ret = -ENODEV;
250d0ebbc0cSBrijesh Singh 		dev_err(dev, "missing driver data\n");
251d0ebbc0cSBrijesh Singh 		goto e_err;
252d0ebbc0cSBrijesh Singh 	}
253d0ebbc0cSBrijesh Singh 
254d0ebbc0cSBrijesh Singh 	ret = pcim_enable_device(pdev);
255d0ebbc0cSBrijesh Singh 	if (ret) {
256d0ebbc0cSBrijesh Singh 		dev_err(dev, "pcim_enable_device failed (%d)\n", ret);
257d0ebbc0cSBrijesh Singh 		goto e_err;
258d0ebbc0cSBrijesh Singh 	}
259d0ebbc0cSBrijesh Singh 
260d0ebbc0cSBrijesh Singh 	bar_mask = pci_select_bars(pdev, IORESOURCE_MEM);
261d0ebbc0cSBrijesh Singh 	ret = pcim_iomap_regions(pdev, bar_mask, "ccp");
262d0ebbc0cSBrijesh Singh 	if (ret) {
263d0ebbc0cSBrijesh Singh 		dev_err(dev, "pcim_iomap_regions failed (%d)\n", ret);
264d0ebbc0cSBrijesh Singh 		goto e_err;
265d0ebbc0cSBrijesh Singh 	}
266d0ebbc0cSBrijesh Singh 
267d0ebbc0cSBrijesh Singh 	iomap_table = pcim_iomap_table(pdev);
268d0ebbc0cSBrijesh Singh 	if (!iomap_table) {
269d0ebbc0cSBrijesh Singh 		dev_err(dev, "pcim_iomap_table failed\n");
270d0ebbc0cSBrijesh Singh 		ret = -ENOMEM;
271d0ebbc0cSBrijesh Singh 		goto e_err;
272d0ebbc0cSBrijesh Singh 	}
273d0ebbc0cSBrijesh Singh 
274d0ebbc0cSBrijesh Singh 	sp->io_map = iomap_table[sp->dev_vdata->bar];
275d0ebbc0cSBrijesh Singh 	if (!sp->io_map) {
276d0ebbc0cSBrijesh Singh 		dev_err(dev, "ioremap failed\n");
277d0ebbc0cSBrijesh Singh 		ret = -ENOMEM;
278d0ebbc0cSBrijesh Singh 		goto e_err;
279d0ebbc0cSBrijesh Singh 	}
280d0ebbc0cSBrijesh Singh 
281d0ebbc0cSBrijesh Singh 	ret = sp_get_irqs(sp);
282d0ebbc0cSBrijesh Singh 	if (ret)
283d0ebbc0cSBrijesh Singh 		goto e_err;
284d0ebbc0cSBrijesh Singh 
285d0ebbc0cSBrijesh Singh 	pci_set_master(pdev);
2862a6170dfSBrijesh Singh 	sp->set_psp_master_device = psp_set_master;
2872a6170dfSBrijesh Singh 	sp->get_psp_master_device = psp_get_master;
28815f7a4c6SJohn Allen 	sp->clear_psp_master_device = psp_clear_master;
289d0ebbc0cSBrijesh Singh 
290d0ebbc0cSBrijesh Singh 	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
291d0ebbc0cSBrijesh Singh 	if (ret) {
292d0ebbc0cSBrijesh Singh 		ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
293d0ebbc0cSBrijesh Singh 		if (ret) {
294d0ebbc0cSBrijesh Singh 			dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n",
295d0ebbc0cSBrijesh Singh 				ret);
296a6f8e68eSChristophe JAILLET 			goto free_irqs;
297d0ebbc0cSBrijesh Singh 		}
298d0ebbc0cSBrijesh Singh 	}
299d0ebbc0cSBrijesh Singh 
300d0ebbc0cSBrijesh Singh 	dev_set_drvdata(dev, sp);
301d0ebbc0cSBrijesh Singh 
302d0ebbc0cSBrijesh Singh 	ret = sp_init(sp);
303d0ebbc0cSBrijesh Singh 	if (ret)
304a6f8e68eSChristophe JAILLET 		goto free_irqs;
305d0ebbc0cSBrijesh Singh 
306d0ebbc0cSBrijesh Singh 	return 0;
307d0ebbc0cSBrijesh Singh 
308a6f8e68eSChristophe JAILLET free_irqs:
309a6f8e68eSChristophe JAILLET 	sp_free_irqs(sp);
310d0ebbc0cSBrijesh Singh e_err:
311d0ebbc0cSBrijesh Singh 	dev_notice(dev, "initialization failed\n");
312d0ebbc0cSBrijesh Singh 	return ret;
313d0ebbc0cSBrijesh Singh }
314d0ebbc0cSBrijesh Singh 
sp_pci_shutdown(struct pci_dev * pdev)3155441a07aSBrijesh Singh static void sp_pci_shutdown(struct pci_dev *pdev)
3165441a07aSBrijesh Singh {
3175441a07aSBrijesh Singh 	struct device *dev = &pdev->dev;
3185441a07aSBrijesh Singh 	struct sp_device *sp = dev_get_drvdata(dev);
3195441a07aSBrijesh Singh 
3205441a07aSBrijesh Singh 	if (!sp)
3215441a07aSBrijesh Singh 		return;
3225441a07aSBrijesh Singh 
3235441a07aSBrijesh Singh 	sp_destroy(sp);
3245441a07aSBrijesh Singh }
3255441a07aSBrijesh Singh 
sp_pci_remove(struct pci_dev * pdev)326d0ebbc0cSBrijesh Singh static void sp_pci_remove(struct pci_dev *pdev)
327d0ebbc0cSBrijesh Singh {
328d0ebbc0cSBrijesh Singh 	struct device *dev = &pdev->dev;
329d0ebbc0cSBrijesh Singh 	struct sp_device *sp = dev_get_drvdata(dev);
330d0ebbc0cSBrijesh Singh 
331d0ebbc0cSBrijesh Singh 	if (!sp)
332d0ebbc0cSBrijesh Singh 		return;
333d0ebbc0cSBrijesh Singh 
334d0ebbc0cSBrijesh Singh 	sp_destroy(sp);
335d0ebbc0cSBrijesh Singh 
336d0ebbc0cSBrijesh Singh 	sp_free_irqs(sp);
337d0ebbc0cSBrijesh Singh }
338d0ebbc0cSBrijesh Singh 
sp_pci_suspend(struct device * dev)339f892a21fSVaibhav Gupta static int __maybe_unused sp_pci_suspend(struct device *dev)
340d0ebbc0cSBrijesh Singh {
341d0ebbc0cSBrijesh Singh 	struct sp_device *sp = dev_get_drvdata(dev);
342d0ebbc0cSBrijesh Singh 
343f892a21fSVaibhav Gupta 	return sp_suspend(sp);
344d0ebbc0cSBrijesh Singh }
345d0ebbc0cSBrijesh Singh 
sp_pci_resume(struct device * dev)346f892a21fSVaibhav Gupta static int __maybe_unused sp_pci_resume(struct device *dev)
347d0ebbc0cSBrijesh Singh {
348d0ebbc0cSBrijesh Singh 	struct sp_device *sp = dev_get_drvdata(dev);
349d0ebbc0cSBrijesh Singh 
350d0ebbc0cSBrijesh Singh 	return sp_resume(sp);
351d0ebbc0cSBrijesh Singh }
352d0ebbc0cSBrijesh Singh 
3532a6170dfSBrijesh Singh #ifdef CONFIG_CRYPTO_DEV_SP_PSP
3546eb0cc72SRijo Thomas static const struct sev_vdata sevv1 = {
355675c3919STom Lendacky 	.cmdresp_reg		= 0x10580,	/* C2PMSG_32 */
356675c3919STom Lendacky 	.cmdbuff_addr_lo_reg	= 0x105e0,	/* C2PMSG_56 */
357675c3919STom Lendacky 	.cmdbuff_addr_hi_reg	= 0x105e4,	/* C2PMSG_57 */
3586eb0cc72SRijo Thomas };
3596eb0cc72SRijo Thomas 
3606eb0cc72SRijo Thomas static const struct sev_vdata sevv2 = {
361675c3919STom Lendacky 	.cmdresp_reg		= 0x10980,	/* C2PMSG_32 */
362675c3919STom Lendacky 	.cmdbuff_addr_lo_reg	= 0x109e0,	/* C2PMSG_56 */
363675c3919STom Lendacky 	.cmdbuff_addr_hi_reg	= 0x109e4,	/* C2PMSG_57 */
3646eb0cc72SRijo Thomas };
3656eb0cc72SRijo Thomas 
36633960accSRijo Thomas static const struct tee_vdata teev1 = {
367675c3919STom Lendacky 	.ring_wptr_reg          = 0x10550,	/* C2PMSG_20 */
368675c3919STom Lendacky 	.ring_rptr_reg          = 0x10554,	/* C2PMSG_21 */
369e938b08aSMario Limonciello 	.info_reg		= 0x109e8,	/* C2PMSG_58 */
37033960accSRijo Thomas };
37133960accSRijo Thomas 
3724aa0931bSMario Limonciello static const struct tee_vdata teev2 = {
3734aa0931bSMario Limonciello 	.ring_wptr_reg		= 0x10950,	/* C2PMSG_20 */
3744aa0931bSMario Limonciello 	.ring_rptr_reg		= 0x10954,	/* C2PMSG_21 */
3754aa0931bSMario Limonciello };
3764aa0931bSMario Limonciello 
37722351239SMario Limonciello static const struct platform_access_vdata pa_v1 = {
37822351239SMario Limonciello 	.cmdresp_reg		= 0x10570,	/* C2PMSG_28 */
37922351239SMario Limonciello 	.cmdbuff_addr_lo_reg	= 0x10574,	/* C2PMSG_29 */
38022351239SMario Limonciello 	.cmdbuff_addr_hi_reg	= 0x10578,	/* C2PMSG_30 */
381d5812571SMario Limonciello 	.doorbell_button_reg	= 0x10a24,	/* C2PMSG_73 */
382d5812571SMario Limonciello 	.doorbell_cmd_reg	= 0x10a40,	/* C2PMSG_80 */
38322351239SMario Limonciello };
38422351239SMario Limonciello 
3854aa0931bSMario Limonciello static const struct platform_access_vdata pa_v2 = {
3864aa0931bSMario Limonciello 	.doorbell_button_reg	= 0x10a24,	/* C2PMSG_73 */
3874aa0931bSMario Limonciello 	.doorbell_cmd_reg	= 0x10a40,	/* C2PMSG_80 */
3884aa0931bSMario Limonciello };
3894aa0931bSMario Limonciello 
3906eb0cc72SRijo Thomas static const struct psp_vdata pspv1 = {
3916eb0cc72SRijo Thomas 	.sev			= &sevv1,
392e938b08aSMario Limonciello 	.bootloader_info_reg	= 0x105ec,	/* C2PMSG_59 */
393675c3919STom Lendacky 	.feature_reg		= 0x105fc,	/* C2PMSG_63 */
394675c3919STom Lendacky 	.inten_reg		= 0x10610,	/* P2CMSG_INTEN */
395675c3919STom Lendacky 	.intsts_reg		= 0x10614,	/* P2CMSG_INTSTS */
3962a6170dfSBrijesh Singh };
397dcbc0c6eSTom Lendacky 
398dcbc0c6eSTom Lendacky static const struct psp_vdata pspv2 = {
3996eb0cc72SRijo Thomas 	.sev			= &sevv2,
400*82f9327fSMario Limonciello 	.platform_access	= &pa_v1,
401e938b08aSMario Limonciello 	.bootloader_info_reg	= 0x109ec,	/* C2PMSG_59 */
402675c3919STom Lendacky 	.feature_reg		= 0x109fc,	/* C2PMSG_63 */
403675c3919STom Lendacky 	.inten_reg		= 0x10690,	/* P2CMSG_INTEN */
404675c3919STom Lendacky 	.intsts_reg		= 0x10694,	/* P2CMSG_INTSTS */
405*82f9327fSMario Limonciello 	.platform_features	= PLATFORM_FEATURE_HSTI,
406dcbc0c6eSTom Lendacky };
40733960accSRijo Thomas 
40833960accSRijo Thomas static const struct psp_vdata pspv3 = {
40933960accSRijo Thomas 	.tee			= &teev1,
41022351239SMario Limonciello 	.platform_access	= &pa_v1,
411949a0c8dSTom Lendacky 	.cmdresp_reg		= 0x10544,	/* C2PMSG_17 */
412949a0c8dSTom Lendacky 	.cmdbuff_addr_lo_reg	= 0x10548,	/* C2PMSG_18 */
413949a0c8dSTom Lendacky 	.cmdbuff_addr_hi_reg	= 0x1054c,	/* C2PMSG_19 */
414e938b08aSMario Limonciello 	.bootloader_info_reg	= 0x109ec,	/* C2PMSG_59 */
415675c3919STom Lendacky 	.feature_reg		= 0x109fc,	/* C2PMSG_63 */
416675c3919STom Lendacky 	.inten_reg		= 0x10690,	/* P2CMSG_INTEN */
417675c3919STom Lendacky 	.intsts_reg		= 0x10694,	/* P2CMSG_INTSTS */
418*82f9327fSMario Limonciello 	.platform_features	= PLATFORM_FEATURE_DBC |
419*82f9327fSMario Limonciello 				  PLATFORM_FEATURE_HSTI,
42033960accSRijo Thomas };
42110da230aSMario Limonciello 
42210da230aSMario Limonciello static const struct psp_vdata pspv4 = {
42310da230aSMario Limonciello 	.sev			= &sevv2,
42410da230aSMario Limonciello 	.tee			= &teev1,
425949a0c8dSTom Lendacky 	.cmdresp_reg		= 0x10544,	/* C2PMSG_17 */
426949a0c8dSTom Lendacky 	.cmdbuff_addr_lo_reg	= 0x10548,	/* C2PMSG_18 */
427949a0c8dSTom Lendacky 	.cmdbuff_addr_hi_reg	= 0x1054c,	/* C2PMSG_19 */
428e938b08aSMario Limonciello 	.bootloader_info_reg	= 0x109ec,	/* C2PMSG_59 */
429675c3919STom Lendacky 	.feature_reg		= 0x109fc,	/* C2PMSG_63 */
430675c3919STom Lendacky 	.inten_reg		= 0x10690,	/* P2CMSG_INTEN */
431675c3919STom Lendacky 	.intsts_reg		= 0x10694,	/* P2CMSG_INTSTS */
43210da230aSMario Limonciello };
43310da230aSMario Limonciello 
4344aa0931bSMario Limonciello static const struct psp_vdata pspv5 = {
4354aa0931bSMario Limonciello 	.tee			= &teev2,
4364aa0931bSMario Limonciello 	.platform_access	= &pa_v2,
437949a0c8dSTom Lendacky 	.cmdresp_reg		= 0x10944,	/* C2PMSG_17 */
438949a0c8dSTom Lendacky 	.cmdbuff_addr_lo_reg	= 0x10948,	/* C2PMSG_18 */
439949a0c8dSTom Lendacky 	.cmdbuff_addr_hi_reg	= 0x1094c,	/* C2PMSG_19 */
4404aa0931bSMario Limonciello 	.feature_reg		= 0x109fc,	/* C2PMSG_63 */
4414aa0931bSMario Limonciello 	.inten_reg		= 0x10510,	/* P2CMSG_INTEN */
4424aa0931bSMario Limonciello 	.intsts_reg		= 0x10514,	/* P2CMSG_INTSTS */
4434aa0931bSMario Limonciello };
4444aa0931bSMario Limonciello 
445bb4185e5SJohn Allen static const struct psp_vdata pspv6 = {
446bb4185e5SJohn Allen 	.sev                    = &sevv2,
447bb4185e5SJohn Allen 	.tee                    = &teev2,
448949a0c8dSTom Lendacky 	.cmdresp_reg		= 0x10944,	/* C2PMSG_17 */
449949a0c8dSTom Lendacky 	.cmdbuff_addr_lo_reg	= 0x10948,	/* C2PMSG_18 */
450949a0c8dSTom Lendacky 	.cmdbuff_addr_hi_reg	= 0x1094c,	/* C2PMSG_19 */
451bb4185e5SJohn Allen 	.feature_reg            = 0x109fc,	/* C2PMSG_63 */
452bb4185e5SJohn Allen 	.inten_reg              = 0x10510,	/* P2CMSG_INTEN */
453bb4185e5SJohn Allen 	.intsts_reg             = 0x10514,	/* P2CMSG_INTSTS */
454bb4185e5SJohn Allen };
455bb4185e5SJohn Allen 
4562a6170dfSBrijesh Singh #endif
4572a6170dfSBrijesh Singh 
458d0ebbc0cSBrijesh Singh static const struct sp_dev_vdata dev_vdata[] = {
459dcbc0c6eSTom Lendacky 	{	/* 0 */
460d0ebbc0cSBrijesh Singh 		.bar = 2,
461d0ebbc0cSBrijesh Singh #ifdef CONFIG_CRYPTO_DEV_SP_CCP
462d0ebbc0cSBrijesh Singh 		.ccp_vdata = &ccpv3,
463d0ebbc0cSBrijesh Singh #endif
464d0ebbc0cSBrijesh Singh 	},
465dcbc0c6eSTom Lendacky 	{	/* 1 */
466d0ebbc0cSBrijesh Singh 		.bar = 2,
467d0ebbc0cSBrijesh Singh #ifdef CONFIG_CRYPTO_DEV_SP_CCP
468d0ebbc0cSBrijesh Singh 		.ccp_vdata = &ccpv5a,
469d0ebbc0cSBrijesh Singh #endif
4702a6170dfSBrijesh Singh #ifdef CONFIG_CRYPTO_DEV_SP_PSP
471dcbc0c6eSTom Lendacky 		.psp_vdata = &pspv1,
4722a6170dfSBrijesh Singh #endif
473d0ebbc0cSBrijesh Singh 	},
474dcbc0c6eSTom Lendacky 	{	/* 2 */
475d0ebbc0cSBrijesh Singh 		.bar = 2,
476d0ebbc0cSBrijesh Singh #ifdef CONFIG_CRYPTO_DEV_SP_CCP
477d0ebbc0cSBrijesh Singh 		.ccp_vdata = &ccpv5b,
478d0ebbc0cSBrijesh Singh #endif
479d0ebbc0cSBrijesh Singh 	},
480dcbc0c6eSTom Lendacky 	{	/* 3 */
481dcbc0c6eSTom Lendacky 		.bar = 2,
482dcbc0c6eSTom Lendacky #ifdef CONFIG_CRYPTO_DEV_SP_CCP
483dcbc0c6eSTom Lendacky 		.ccp_vdata = &ccpv5a,
484dcbc0c6eSTom Lendacky #endif
485dcbc0c6eSTom Lendacky #ifdef CONFIG_CRYPTO_DEV_SP_PSP
486dcbc0c6eSTom Lendacky 		.psp_vdata = &pspv2,
487dcbc0c6eSTom Lendacky #endif
488dcbc0c6eSTom Lendacky 	},
48933960accSRijo Thomas 	{	/* 4 */
49033960accSRijo Thomas 		.bar = 2,
49133960accSRijo Thomas #ifdef CONFIG_CRYPTO_DEV_SP_CCP
49233960accSRijo Thomas 		.ccp_vdata = &ccpv5a,
49333960accSRijo Thomas #endif
49433960accSRijo Thomas #ifdef CONFIG_CRYPTO_DEV_SP_PSP
49533960accSRijo Thomas 		.psp_vdata = &pspv3,
49633960accSRijo Thomas #endif
49733960accSRijo Thomas 	},
4983438de03SJohn Allen 	{	/* 5 */
4993438de03SJohn Allen 		.bar = 2,
5003438de03SJohn Allen #ifdef CONFIG_CRYPTO_DEV_SP_PSP
50110da230aSMario Limonciello 		.psp_vdata = &pspv4,
5023438de03SJohn Allen #endif
5033438de03SJohn Allen 	},
50496ec8dfdSMario Limonciello 	{	/* 6 */
50596ec8dfdSMario Limonciello 		.bar = 2,
50696ec8dfdSMario Limonciello #ifdef CONFIG_CRYPTO_DEV_SP_PSP
50796ec8dfdSMario Limonciello 		.psp_vdata = &pspv3,
50896ec8dfdSMario Limonciello #endif
50996ec8dfdSMario Limonciello 	},
5104aa0931bSMario Limonciello 	{	/* 7 */
5114aa0931bSMario Limonciello 		.bar = 2,
5124aa0931bSMario Limonciello #ifdef CONFIG_CRYPTO_DEV_SP_PSP
5134aa0931bSMario Limonciello 		.psp_vdata = &pspv5,
5144aa0931bSMario Limonciello #endif
5154aa0931bSMario Limonciello 	},
516bb4185e5SJohn Allen 	{	/* 8 */
517bb4185e5SJohn Allen 		.bar = 2,
518bb4185e5SJohn Allen #ifdef CONFIG_CRYPTO_DEV_SP_PSP
519bb4185e5SJohn Allen 		.psp_vdata = &pspv6,
520bb4185e5SJohn Allen #endif
521bb4185e5SJohn Allen 	},
522d0ebbc0cSBrijesh Singh };
523d0ebbc0cSBrijesh Singh static const struct pci_device_id sp_pci_table[] = {
524d0ebbc0cSBrijesh Singh 	{ PCI_VDEVICE(AMD, 0x1537), (kernel_ulong_t)&dev_vdata[0] },
525d0ebbc0cSBrijesh Singh 	{ PCI_VDEVICE(AMD, 0x1456), (kernel_ulong_t)&dev_vdata[1] },
526d0ebbc0cSBrijesh Singh 	{ PCI_VDEVICE(AMD, 0x1468), (kernel_ulong_t)&dev_vdata[2] },
527dcbc0c6eSTom Lendacky 	{ PCI_VDEVICE(AMD, 0x1486), (kernel_ulong_t)&dev_vdata[3] },
52833960accSRijo Thomas 	{ PCI_VDEVICE(AMD, 0x15DF), (kernel_ulong_t)&dev_vdata[4] },
5293438de03SJohn Allen 	{ PCI_VDEVICE(AMD, 0x14CA), (kernel_ulong_t)&dev_vdata[5] },
53096ec8dfdSMario Limonciello 	{ PCI_VDEVICE(AMD, 0x15C7), (kernel_ulong_t)&dev_vdata[6] },
531c79a3169SMario Limonciello 	{ PCI_VDEVICE(AMD, 0x1649), (kernel_ulong_t)&dev_vdata[6] },
5324aa0931bSMario Limonciello 	{ PCI_VDEVICE(AMD, 0x17E0), (kernel_ulong_t)&dev_vdata[7] },
533bb4185e5SJohn Allen 	{ PCI_VDEVICE(AMD, 0x156E), (kernel_ulong_t)&dev_vdata[8] },
534d0ebbc0cSBrijesh Singh 	/* Last entry must be zero */
535d0ebbc0cSBrijesh Singh 	{ 0, }
536d0ebbc0cSBrijesh Singh };
537d0ebbc0cSBrijesh Singh MODULE_DEVICE_TABLE(pci, sp_pci_table);
538d0ebbc0cSBrijesh Singh 
539f892a21fSVaibhav Gupta static SIMPLE_DEV_PM_OPS(sp_pci_pm_ops, sp_pci_suspend, sp_pci_resume);
540f892a21fSVaibhav Gupta 
541d0ebbc0cSBrijesh Singh static struct pci_driver sp_pci_driver = {
542d0ebbc0cSBrijesh Singh 	.name = "ccp",
543d0ebbc0cSBrijesh Singh 	.id_table = sp_pci_table,
544d0ebbc0cSBrijesh Singh 	.probe = sp_pci_probe,
545d0ebbc0cSBrijesh Singh 	.remove = sp_pci_remove,
5465441a07aSBrijesh Singh 	.shutdown = sp_pci_shutdown,
547f892a21fSVaibhav Gupta 	.driver.pm = &sp_pci_pm_ops,
54850c4deccSMario Limonciello 	.dev_groups = psp_groups,
549d0ebbc0cSBrijesh Singh };
550d0ebbc0cSBrijesh Singh 
sp_pci_init(void)551d0ebbc0cSBrijesh Singh int sp_pci_init(void)
552d0ebbc0cSBrijesh Singh {
553d0ebbc0cSBrijesh Singh 	return pci_register_driver(&sp_pci_driver);
554d0ebbc0cSBrijesh Singh }
555d0ebbc0cSBrijesh Singh 
sp_pci_exit(void)556d0ebbc0cSBrijesh Singh void sp_pci_exit(void)
557d0ebbc0cSBrijesh Singh {
558d0ebbc0cSBrijesh Singh 	pci_unregister_driver(&sp_pci_driver);
559d0ebbc0cSBrijesh Singh }
560