File Index
Files and directories
Sign in
FILE

sp-platform.c

File preview with syntax highlighting.

linux-6.19.14/drivers/crypto/ccp/sp-platform.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * AMD Secure Processor device driver
  4 *
  5 * Copyright (C) 2014,2018 Advanced Micro Devices, Inc.
  6 *
  7 * Author: Tom Lendacky <thomas.lendacky@amd.com>
  8 */
  9
 10#include <linux/module.h>
 11#include <linux/kernel.h>
 12#include <linux/device.h>
 13#include <linux/platform_device.h>
 14#include <linux/ioport.h>
 15#include <linux/dma-mapping.h>
 16#include <linux/kthread.h>
 17#include <linux/sched.h>
 18#include <linux/interrupt.h>
 19#include <linux/spinlock.h>
 20#include <linux/delay.h>
 21#include <linux/ccp.h>
 22#include <linux/of.h>
 23#include <linux/of_address.h>
 24#include <linux/acpi.h>
 25
 26#include "ccp-dev.h"
 27
 28struct sp_platform {
 29	int coherent;
 30	unsigned int irq_count;
 31};
 32
 33static const struct sp_dev_vdata dev_vdata[] = {
 34	{
 35		.bar = 0,
 36#ifdef CONFIG_CRYPTO_DEV_SP_CCP
 37		.ccp_vdata = &ccpv3_platform,
 38#endif
 39	},
 40};
 41
 42static const struct acpi_device_id sp_acpi_match[] = {
 43	{ "AMDI0C00", (kernel_ulong_t)&dev_vdata[0] },
 44	{ },
 45};
 46MODULE_DEVICE_TABLE(acpi, sp_acpi_match);
 47
 48static const struct of_device_id sp_of_match[] = {
 49	{ .compatible = "amd,ccp-seattle-v1a",
 50	  .data = (const void *)&dev_vdata[0] },
 51	{ },
 52};
 53MODULE_DEVICE_TABLE(of, sp_of_match);
 54
 55static const struct sp_dev_vdata *sp_get_acpi_version(struct platform_device *pdev)
 56{
 57	const struct acpi_device_id *match;
 58
 59	match = acpi_match_device(sp_acpi_match, &pdev->dev);
 60	if (match && match->driver_data)
 61		return (const struct sp_dev_vdata *)match->driver_data;
 62
 63	return NULL;
 64}
 65
 66static int sp_get_irqs(struct sp_device *sp)
 67{
 68	struct sp_platform *sp_platform = sp->dev_specific;
 69	struct device *dev = sp->dev;
 70	struct platform_device *pdev = to_platform_device(dev);
 71	int ret;
 72
 73	sp_platform->irq_count = platform_irq_count(pdev);
 74
 75	ret = platform_get_irq(pdev, 0);
 76	if (ret < 0) {
 77		dev_notice(dev, "unable to get IRQ (%d)\n", ret);
 78		return ret;
 79	}
 80
 81	sp->psp_irq = ret;
 82	if (sp_platform->irq_count == 1) {
 83		sp->ccp_irq = ret;
 84	} else {
 85		ret = platform_get_irq(pdev, 1);
 86		if (ret < 0) {
 87			dev_notice(dev, "unable to get IRQ (%d)\n", ret);
 88			return ret;
 89		}
 90
 91		sp->ccp_irq = ret;
 92	}
 93
 94	return 0;
 95}
 96
 97static int sp_platform_probe(struct platform_device *pdev)
 98{
 99	struct sp_device *sp;
100	struct sp_platform *sp_platform;
101	struct device *dev = &pdev->dev;
102	enum dev_dma_attr attr;
103	int ret;
104
105	ret = -ENOMEM;
106	sp = sp_alloc_struct(dev);
107	if (!sp)
108		goto e_err;
109
110	sp_platform = devm_kzalloc(dev, sizeof(*sp_platform), GFP_KERNEL);
111	if (!sp_platform)
112		goto e_err;
113
114	sp->dev_specific = sp_platform;
115	sp->dev_vdata = pdev->dev.of_node ? of_device_get_match_data(&pdev->dev)
116					 : sp_get_acpi_version(pdev);
117	if (!sp->dev_vdata) {
118		ret = -ENODEV;
119		dev_err(dev, "missing driver data\n");
120		goto e_err;
121	}
122
123	sp->io_map = devm_platform_ioremap_resource(pdev, 0);
124	if (IS_ERR(sp->io_map)) {
125		ret = PTR_ERR(sp->io_map);
126		goto e_err;
127	}
128
129	attr = device_get_dma_attr(dev);
130	if (attr == DEV_DMA_NOT_SUPPORTED) {
131		dev_err(dev, "DMA is not supported");
132		goto e_err;
133	}
134
135	sp_platform->coherent = (attr == DEV_DMA_COHERENT);
136	if (sp_platform->coherent)
137		sp->axcache = CACHE_WB_NO_ALLOC;
138	else
139		sp->axcache = CACHE_NONE;
140
141	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
142	if (ret) {
143		dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n", ret);
144		goto e_err;
145	}
146
147	ret = sp_get_irqs(sp);
148	if (ret)
149		goto e_err;
150
151	dev_set_drvdata(dev, sp);
152
153	ret = sp_init(sp);
154	if (ret)
155		goto e_err;
156
157	dev_notice(dev, "enabled\n");
158
159	return 0;
160
161e_err:
162	dev_notice(dev, "initialization failed\n");
163	return ret;
164}
165
166static void sp_platform_remove(struct platform_device *pdev)
167{
168	struct device *dev = &pdev->dev;
169	struct sp_device *sp = dev_get_drvdata(dev);
170
171	sp_destroy(sp);
172
173	dev_notice(dev, "disabled\n");
174}
175
176#ifdef CONFIG_PM
177static int sp_platform_suspend(struct platform_device *pdev,
178				pm_message_t state)
179{
180	struct device *dev = &pdev->dev;
181	struct sp_device *sp = dev_get_drvdata(dev);
182
183	return sp_suspend(sp);
184}
185
186static int sp_platform_resume(struct platform_device *pdev)
187{
188	struct device *dev = &pdev->dev;
189	struct sp_device *sp = dev_get_drvdata(dev);
190
191	return sp_resume(sp);
192}
193#endif
194
195static struct platform_driver sp_platform_driver = {
196	.driver = {
197		.name = "ccp",
198		.acpi_match_table = sp_acpi_match,
199		.of_match_table = sp_of_match,
200	},
201	.probe = sp_platform_probe,
202	.remove = sp_platform_remove,
203#ifdef CONFIG_PM
204	.suspend = sp_platform_suspend,
205	.resume = sp_platform_resume,
206#endif
207};
208
209int sp_platform_init(void)
210{
211	return platform_driver_register(&sp_platform_driver);
212}
213
214void sp_platform_exit(void)
215{
216	platform_driver_unregister(&sp_platform_driver);
217}
~/ Read-only file preview.