1 // SPDX-License-Identifier: GPL-2.0-only
3 * AMD Secure Processor device driver
5 * Copyright (C) 2014,2018 Advanced Micro Devices, Inc.
7 * Author: Tom Lendacky <thomas.lendacky@amd.com>
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>
23 #include <linux/of_address.h>
24 #include <linux/acpi.h>
30 unsigned int irq_count
;
33 static const struct sp_dev_vdata dev_vdata
[] = {
36 #ifdef CONFIG_CRYPTO_DEV_SP_CCP
37 .ccp_vdata
= &ccpv3_platform
,
42 static const struct acpi_device_id sp_acpi_match
[] = {
43 { "AMDI0C00", (kernel_ulong_t
)&dev_vdata
[0] },
46 MODULE_DEVICE_TABLE(acpi
, sp_acpi_match
);
48 static const struct of_device_id sp_of_match
[] = {
49 { .compatible
= "amd,ccp-seattle-v1a",
50 .data
= (const void *)&dev_vdata
[0] },
53 MODULE_DEVICE_TABLE(of
, sp_of_match
);
55 static struct sp_dev_vdata
*sp_get_of_version(struct platform_device
*pdev
)
57 const struct of_device_id
*match
;
59 match
= of_match_node(sp_of_match
, pdev
->dev
.of_node
);
60 if (match
&& match
->data
)
61 return (struct sp_dev_vdata
*)match
->data
;
66 static struct sp_dev_vdata
*sp_get_acpi_version(struct platform_device
*pdev
)
68 const struct acpi_device_id
*match
;
70 match
= acpi_match_device(sp_acpi_match
, &pdev
->dev
);
71 if (match
&& match
->driver_data
)
72 return (struct sp_dev_vdata
*)match
->driver_data
;
77 static int sp_get_irqs(struct sp_device
*sp
)
79 struct sp_platform
*sp_platform
= sp
->dev_specific
;
80 struct device
*dev
= sp
->dev
;
81 struct platform_device
*pdev
= to_platform_device(dev
);
84 sp_platform
->irq_count
= platform_irq_count(pdev
);
86 ret
= platform_get_irq(pdev
, 0);
88 dev_notice(dev
, "unable to get IRQ (%d)\n", ret
);
93 if (sp_platform
->irq_count
== 1) {
96 ret
= platform_get_irq(pdev
, 1);
98 dev_notice(dev
, "unable to get IRQ (%d)\n", ret
);
108 static int sp_platform_probe(struct platform_device
*pdev
)
110 struct sp_device
*sp
;
111 struct sp_platform
*sp_platform
;
112 struct device
*dev
= &pdev
->dev
;
113 enum dev_dma_attr attr
;
117 sp
= sp_alloc_struct(dev
);
121 sp_platform
= devm_kzalloc(dev
, sizeof(*sp_platform
), GFP_KERNEL
);
125 sp
->dev_specific
= sp_platform
;
126 sp
->dev_vdata
= pdev
->dev
.of_node
? sp_get_of_version(pdev
)
127 : sp_get_acpi_version(pdev
);
128 if (!sp
->dev_vdata
) {
130 dev_err(dev
, "missing driver data\n");
134 sp
->io_map
= devm_platform_ioremap_resource(pdev
, 0);
135 if (IS_ERR(sp
->io_map
)) {
136 ret
= PTR_ERR(sp
->io_map
);
140 attr
= device_get_dma_attr(dev
);
141 if (attr
== DEV_DMA_NOT_SUPPORTED
) {
142 dev_err(dev
, "DMA is not supported");
146 sp_platform
->coherent
= (attr
== DEV_DMA_COHERENT
);
147 if (sp_platform
->coherent
)
148 sp
->axcache
= CACHE_WB_NO_ALLOC
;
150 sp
->axcache
= CACHE_NONE
;
152 ret
= dma_set_mask_and_coherent(dev
, DMA_BIT_MASK(48));
154 dev_err(dev
, "dma_set_mask_and_coherent failed (%d)\n", ret
);
158 ret
= sp_get_irqs(sp
);
162 dev_set_drvdata(dev
, sp
);
168 dev_notice(dev
, "enabled\n");
173 dev_notice(dev
, "initialization failed\n");
177 static void sp_platform_remove(struct platform_device
*pdev
)
179 struct device
*dev
= &pdev
->dev
;
180 struct sp_device
*sp
= dev_get_drvdata(dev
);
184 dev_notice(dev
, "disabled\n");
188 static int sp_platform_suspend(struct platform_device
*pdev
,
191 struct device
*dev
= &pdev
->dev
;
192 struct sp_device
*sp
= dev_get_drvdata(dev
);
194 return sp_suspend(sp
);
197 static int sp_platform_resume(struct platform_device
*pdev
)
199 struct device
*dev
= &pdev
->dev
;
200 struct sp_device
*sp
= dev_get_drvdata(dev
);
202 return sp_resume(sp
);
206 static struct platform_driver sp_platform_driver
= {
209 .acpi_match_table
= sp_acpi_match
,
210 .of_match_table
= sp_of_match
,
212 .probe
= sp_platform_probe
,
213 .remove
= sp_platform_remove
,
215 .suspend
= sp_platform_suspend
,
216 .resume
= sp_platform_resume
,
220 int sp_platform_init(void)
222 return platform_driver_register(&sp_platform_driver
);
225 void sp_platform_exit(void)
227 platform_driver_unregister(&sp_platform_driver
);