2 * AMD Secure Processor device driver
4 * Copyright (C) 2014,2016 Advanced Micro Devices, Inc.
6 * Author: Tom Lendacky <thomas.lendacky@amd.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/device.h>
16 #include <linux/platform_device.h>
17 #include <linux/ioport.h>
18 #include <linux/dma-mapping.h>
19 #include <linux/kthread.h>
20 #include <linux/sched.h>
21 #include <linux/interrupt.h>
22 #include <linux/spinlock.h>
23 #include <linux/delay.h>
24 #include <linux/ccp.h>
26 #include <linux/of_address.h>
27 #include <linux/acpi.h>
33 unsigned int irq_count
;
36 static const struct acpi_device_id sp_acpi_match
[];
37 static const struct of_device_id sp_of_match
[];
39 static struct sp_dev_vdata
*sp_get_of_version(struct platform_device
*pdev
)
42 const struct of_device_id
*match
;
44 match
= of_match_node(sp_of_match
, pdev
->dev
.of_node
);
45 if (match
&& match
->data
)
46 return (struct sp_dev_vdata
*)match
->data
;
51 static struct sp_dev_vdata
*sp_get_acpi_version(struct platform_device
*pdev
)
54 const struct acpi_device_id
*match
;
56 match
= acpi_match_device(sp_acpi_match
, &pdev
->dev
);
57 if (match
&& match
->driver_data
)
58 return (struct sp_dev_vdata
*)match
->driver_data
;
63 static int sp_get_irqs(struct sp_device
*sp
)
65 struct sp_platform
*sp_platform
= sp
->dev_specific
;
66 struct device
*dev
= sp
->dev
;
67 struct platform_device
*pdev
= to_platform_device(dev
);
68 unsigned int i
, count
;
71 for (i
= 0, count
= 0; i
< pdev
->num_resources
; i
++) {
72 struct resource
*res
= &pdev
->resource
[i
];
74 if (resource_type(res
) == IORESOURCE_IRQ
)
78 sp_platform
->irq_count
= count
;
80 ret
= platform_get_irq(pdev
, 0);
82 dev_notice(dev
, "unable to get IRQ (%d)\n", ret
);
90 ret
= platform_get_irq(pdev
, 1);
92 dev_notice(dev
, "unable to get IRQ (%d)\n", ret
);
102 static int sp_platform_probe(struct platform_device
*pdev
)
104 struct sp_device
*sp
;
105 struct sp_platform
*sp_platform
;
106 struct device
*dev
= &pdev
->dev
;
107 enum dev_dma_attr attr
;
108 struct resource
*ior
;
112 sp
= sp_alloc_struct(dev
);
116 sp_platform
= devm_kzalloc(dev
, sizeof(*sp_platform
), GFP_KERNEL
);
120 sp
->dev_specific
= sp_platform
;
121 sp
->dev_vdata
= pdev
->dev
.of_node
? sp_get_of_version(pdev
)
122 : sp_get_acpi_version(pdev
);
123 if (!sp
->dev_vdata
) {
125 dev_err(dev
, "missing driver data\n");
129 ior
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
130 sp
->io_map
= devm_ioremap_resource(dev
, ior
);
131 if (IS_ERR(sp
->io_map
)) {
132 ret
= PTR_ERR(sp
->io_map
);
136 attr
= device_get_dma_attr(dev
);
137 if (attr
== DEV_DMA_NOT_SUPPORTED
) {
138 dev_err(dev
, "DMA is not supported");
142 sp_platform
->coherent
= (attr
== DEV_DMA_COHERENT
);
143 if (sp_platform
->coherent
)
144 sp
->axcache
= CACHE_WB_NO_ALLOC
;
146 sp
->axcache
= CACHE_NONE
;
148 ret
= dma_set_mask_and_coherent(dev
, DMA_BIT_MASK(48));
150 dev_err(dev
, "dma_set_mask_and_coherent failed (%d)\n", ret
);
154 ret
= sp_get_irqs(sp
);
158 dev_set_drvdata(dev
, sp
);
164 dev_notice(dev
, "enabled\n");
169 dev_notice(dev
, "initialization failed\n");
173 static int sp_platform_remove(struct platform_device
*pdev
)
175 struct device
*dev
= &pdev
->dev
;
176 struct sp_device
*sp
= dev_get_drvdata(dev
);
180 dev_notice(dev
, "disabled\n");
186 static int sp_platform_suspend(struct platform_device
*pdev
,
189 struct device
*dev
= &pdev
->dev
;
190 struct sp_device
*sp
= dev_get_drvdata(dev
);
192 return sp_suspend(sp
, state
);
195 static int sp_platform_resume(struct platform_device
*pdev
)
197 struct device
*dev
= &pdev
->dev
;
198 struct sp_device
*sp
= dev_get_drvdata(dev
);
200 return sp_resume(sp
);
204 static const struct sp_dev_vdata dev_vdata
[] = {
207 #ifdef CONFIG_CRYPTO_DEV_SP_CCP
208 .ccp_vdata
= &ccpv3_platform
,
214 static const struct acpi_device_id sp_acpi_match
[] = {
215 { "AMDI0C00", (kernel_ulong_t
)&dev_vdata
[0] },
218 MODULE_DEVICE_TABLE(acpi
, sp_acpi_match
);
222 static const struct of_device_id sp_of_match
[] = {
223 { .compatible
= "amd,ccp-seattle-v1a",
224 .data
= (const void *)&dev_vdata
[0] },
227 MODULE_DEVICE_TABLE(of
, sp_of_match
);
230 static struct platform_driver sp_platform_driver
= {
234 .acpi_match_table
= sp_acpi_match
,
237 .of_match_table
= sp_of_match
,
240 .probe
= sp_platform_probe
,
241 .remove
= sp_platform_remove
,
243 .suspend
= sp_platform_suspend
,
244 .resume
= sp_platform_resume
,
248 int sp_platform_init(void)
250 return platform_driver_register(&sp_platform_driver
);
253 void sp_platform_exit(void)
255 platform_driver_unregister(&sp_platform_driver
);