]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/crypto/ccp/sp-platform.c
treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500
[mirror_ubuntu-jammy-kernel.git] / drivers / crypto / ccp / sp-platform.c
CommitLineData
d2912cb1 1// SPDX-License-Identifier: GPL-2.0-only
c4f4b325 2/*
d0ebbc0c 3 * AMD Secure Processor device driver
c4f4b325 4 *
fa5cd1c7 5 * Copyright (C) 2014,2018 Advanced Micro Devices, Inc.
c4f4b325
TL
6 *
7 * Author: Tom Lendacky <thomas.lendacky@amd.com>
c4f4b325
TL
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>
126ae9ad 22#include <linux/of.h>
6c506343
TL
23#include <linux/of_address.h>
24#include <linux/acpi.h>
c4f4b325
TL
25
26#include "ccp-dev.h"
27
d0ebbc0c 28struct sp_platform {
6c506343 29 int coherent;
f4d18d65 30 unsigned int irq_count;
6c506343
TL
31};
32
3512dcb4
NC
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
42#ifdef CONFIG_ACPI
43static const struct acpi_device_id sp_acpi_match[] = {
44 { "AMDI0C00", (kernel_ulong_t)&dev_vdata[0] },
45 { },
46};
47MODULE_DEVICE_TABLE(acpi, sp_acpi_match);
48#endif
49
50#ifdef CONFIG_OF
51static const struct of_device_id sp_of_match[] = {
52 { .compatible = "amd,ccp-seattle-v1a",
53 .data = (const void *)&dev_vdata[0] },
54 { },
55};
56MODULE_DEVICE_TABLE(of, sp_of_match);
57#endif
c7019c4d 58
d0ebbc0c 59static struct sp_dev_vdata *sp_get_of_version(struct platform_device *pdev)
c7019c4d
GH
60{
61#ifdef CONFIG_OF
62 const struct of_device_id *match;
63
d0ebbc0c 64 match = of_match_node(sp_of_match, pdev->dev.of_node);
c7019c4d 65 if (match && match->data)
720419f0 66 return (struct sp_dev_vdata *)match->data;
c7019c4d 67#endif
9d1fb196 68 return NULL;
c7019c4d
GH
69}
70
d0ebbc0c 71static struct sp_dev_vdata *sp_get_acpi_version(struct platform_device *pdev)
c7019c4d
GH
72{
73#ifdef CONFIG_ACPI
74 const struct acpi_device_id *match;
75
d0ebbc0c 76 match = acpi_match_device(sp_acpi_match, &pdev->dev);
c7019c4d 77 if (match && match->driver_data)
720419f0 78 return (struct sp_dev_vdata *)match->driver_data;
c7019c4d 79#endif
9d1fb196 80 return NULL;
c7019c4d
GH
81}
82
d0ebbc0c 83static int sp_get_irqs(struct sp_device *sp)
c4f4b325 84{
d0ebbc0c 85 struct sp_platform *sp_platform = sp->dev_specific;
f4d18d65 86 struct device *dev = sp->dev;
c6c59bf2 87 struct platform_device *pdev = to_platform_device(dev);
f4d18d65 88 unsigned int i, count;
c4f4b325
TL
89 int ret;
90
f4d18d65
BS
91 for (i = 0, count = 0; i < pdev->num_resources; i++) {
92 struct resource *res = &pdev->resource[i];
93
94 if (resource_type(res) == IORESOURCE_IRQ)
95 count++;
96 }
97
d0ebbc0c 98 sp_platform->irq_count = count;
f4d18d65 99
c4f4b325 100 ret = platform_get_irq(pdev, 0);
28a2cc67
GS
101 if (ret < 0) {
102 dev_notice(dev, "unable to get IRQ (%d)\n", ret);
c4f4b325 103 return ret;
28a2cc67 104 }
c4f4b325 105
f4d18d65
BS
106 sp->psp_irq = ret;
107 if (count == 1) {
108 sp->ccp_irq = ret;
109 } else {
110 ret = platform_get_irq(pdev, 1);
111 if (ret < 0) {
112 dev_notice(dev, "unable to get IRQ (%d)\n", ret);
113 return ret;
114 }
115
116 sp->ccp_irq = ret;
c4f4b325
TL
117 }
118
119 return 0;
120}
121
d0ebbc0c 122static int sp_platform_probe(struct platform_device *pdev)
c4f4b325 123{
720419f0 124 struct sp_device *sp;
d0ebbc0c 125 struct sp_platform *sp_platform;
c4f4b325 126 struct device *dev = &pdev->dev;
1831eff8 127 enum dev_dma_attr attr;
c4f4b325
TL
128 struct resource *ior;
129 int ret;
130
131 ret = -ENOMEM;
720419f0
BS
132 sp = sp_alloc_struct(dev);
133 if (!sp)
c4f4b325
TL
134 goto e_err;
135
d0ebbc0c
BS
136 sp_platform = devm_kzalloc(dev, sizeof(*sp_platform), GFP_KERNEL);
137 if (!sp_platform)
6c506343
TL
138 goto e_err;
139
d0ebbc0c
BS
140 sp->dev_specific = sp_platform;
141 sp->dev_vdata = pdev->dev.of_node ? sp_get_of_version(pdev)
142 : sp_get_acpi_version(pdev);
720419f0 143 if (!sp->dev_vdata) {
c7019c4d
GH
144 ret = -ENODEV;
145 dev_err(dev, "missing driver data\n");
146 goto e_err;
147 }
c4f4b325 148
970e8303 149 ior = platform_get_resource(pdev, IORESOURCE_MEM, 0);
720419f0
BS
150 sp->io_map = devm_ioremap_resource(dev, ior);
151 if (IS_ERR(sp->io_map)) {
152 ret = PTR_ERR(sp->io_map);
be03a3a0 153 goto e_err;
c4f4b325 154 }
c4f4b325 155
1831eff8
SS
156 attr = device_get_dma_attr(dev);
157 if (attr == DEV_DMA_NOT_SUPPORTED) {
158 dev_err(dev, "DMA is not supported");
be03a3a0 159 goto e_err;
261bf074 160 }
c4f4b325 161
d0ebbc0c
BS
162 sp_platform->coherent = (attr == DEV_DMA_COHERENT);
163 if (sp_platform->coherent)
720419f0 164 sp->axcache = CACHE_WB_NO_ALLOC;
126ae9ad 165 else
720419f0 166 sp->axcache = CACHE_NONE;
126ae9ad 167
1831eff8
SS
168 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
169 if (ret) {
170 dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n", ret);
171 goto e_err;
172 }
173
d0ebbc0c 174 ret = sp_get_irqs(sp);
f4d18d65
BS
175 if (ret)
176 goto e_err;
177
720419f0 178 dev_set_drvdata(dev, sp);
c4f4b325 179
720419f0 180 ret = sp_init(sp);
c4f4b325 181 if (ret)
be03a3a0 182 goto e_err;
c4f4b325
TL
183
184 dev_notice(dev, "enabled\n");
185
186 return 0;
187
c4f4b325
TL
188e_err:
189 dev_notice(dev, "initialization failed\n");
190 return ret;
191}
192
d0ebbc0c 193static int sp_platform_remove(struct platform_device *pdev)
c4f4b325
TL
194{
195 struct device *dev = &pdev->dev;
720419f0 196 struct sp_device *sp = dev_get_drvdata(dev);
c4f4b325 197
720419f0 198 sp_destroy(sp);
c4f4b325 199
c4f4b325
TL
200 dev_notice(dev, "disabled\n");
201
202 return 0;
203}
204
205#ifdef CONFIG_PM
d0ebbc0c 206static int sp_platform_suspend(struct platform_device *pdev,
c4f4b325
TL
207 pm_message_t state)
208{
209 struct device *dev = &pdev->dev;
720419f0 210 struct sp_device *sp = dev_get_drvdata(dev);
c4f4b325 211
720419f0 212 return sp_suspend(sp, state);
c4f4b325
TL
213}
214
d0ebbc0c 215static int sp_platform_resume(struct platform_device *pdev)
c4f4b325
TL
216{
217 struct device *dev = &pdev->dev;
720419f0 218 struct sp_device *sp = dev_get_drvdata(dev);
c4f4b325 219
720419f0 220 return sp_resume(sp);
c4f4b325
TL
221}
222#endif
223
d0ebbc0c 224static struct platform_driver sp_platform_driver = {
c4f4b325 225 .driver = {
166db195 226 .name = "ccp",
6c506343 227#ifdef CONFIG_ACPI
d0ebbc0c 228 .acpi_match_table = sp_acpi_match,
6c506343
TL
229#endif
230#ifdef CONFIG_OF
d0ebbc0c 231 .of_match_table = sp_of_match,
6c506343 232#endif
c4f4b325 233 },
d0ebbc0c
BS
234 .probe = sp_platform_probe,
235 .remove = sp_platform_remove,
c4f4b325 236#ifdef CONFIG_PM
d0ebbc0c
BS
237 .suspend = sp_platform_suspend,
238 .resume = sp_platform_resume,
c4f4b325
TL
239#endif
240};
241
d0ebbc0c 242int sp_platform_init(void)
c4f4b325 243{
d0ebbc0c 244 return platform_driver_register(&sp_platform_driver);
c4f4b325
TL
245}
246
d0ebbc0c 247void sp_platform_exit(void)
c4f4b325 248{
d0ebbc0c 249 platform_driver_unregister(&sp_platform_driver);
c4f4b325 250}