Skip to content

Commit c4f4b32

Browse files
tlendackyherbertx
authored andcommitted
crypto: ccp - Add platform device support for arm64
Add support for the CCP on arm64 as a platform device. Signed-off-by: Tom Lendacky <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent 1ad348f commit c4f4b32

File tree

5 files changed

+270
-2
lines changed

5 files changed

+270
-2
lines changed

drivers/crypto/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ config CRYPTO_DEV_ATMEL_SHA
391391

392392
config CRYPTO_DEV_CCP
393393
bool "Support for AMD Cryptographic Coprocessor"
394-
depends on X86 && PCI
394+
depends on (X86 && PCI) || ARM64
395395
default n
396396
help
397397
The AMD Cryptographic Coprocessor provides hardware support

drivers/crypto/ccp/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
obj-$(CONFIG_CRYPTO_DEV_CCP_DD) += ccp.o
22
ccp-objs := ccp-dev.o ccp-ops.o
3+
ifdef CONFIG_X86
34
ccp-objs += ccp-pci.o
5+
endif
6+
ifdef CONFIG_ARM64
7+
ccp-objs += ccp-platform.o
8+
endif
49

510
obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
611
ccp-crypto-objs := ccp-crypto-main.o \

drivers/crypto/ccp/ccp-dev.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
#include <linux/delay.h>
2121
#include <linux/hw_random.h>
2222
#include <linux/cpu.h>
23+
#ifdef CONFIG_X86
2324
#include <asm/cpu_device_id.h>
25+
#endif
2426
#include <linux/ccp.h>
2527

2628
#include "ccp-dev.h"
@@ -360,6 +362,12 @@ int ccp_init(struct ccp_device *ccp)
360362
/* Build queue interrupt mask (two interrupts per queue) */
361363
qim |= cmd_q->int_ok | cmd_q->int_err;
362364

365+
#ifdef CONFIG_ARM64
366+
/* For arm64 set the recommended queue cache settings */
367+
iowrite32(CACHE_WB_NO_ALLOC, ccp->io_regs + CMD_Q_CACHE_BASE +
368+
(CMD_Q_CACHE_INC * i));
369+
#endif
370+
363371
dev_dbg(dev, "queue #%u available\n", i);
364372
}
365373
if (ccp->cmd_q_count == 0) {
@@ -558,12 +566,15 @@ bool ccp_queues_suspended(struct ccp_device *ccp)
558566
}
559567
#endif
560568

569+
#ifdef CONFIG_X86
561570
static const struct x86_cpu_id ccp_support[] = {
562571
{ X86_VENDOR_AMD, 22, },
563572
};
573+
#endif
564574

565575
static int __init ccp_mod_init(void)
566576
{
577+
#ifdef CONFIG_X86
567578
struct cpuinfo_x86 *cpuinfo = &boot_cpu_data;
568579
int ret;
569580

@@ -589,19 +600,42 @@ static int __init ccp_mod_init(void)
589600

590601
break;
591602
}
603+
#endif
604+
605+
#ifdef CONFIG_ARM64
606+
int ret;
607+
608+
ret = ccp_platform_init();
609+
if (ret)
610+
return ret;
611+
612+
/* Don't leave the driver loaded if init failed */
613+
if (!ccp_get_device()) {
614+
ccp_platform_exit();
615+
return -ENODEV;
616+
}
617+
618+
return 0;
619+
#endif
592620

593621
return -ENODEV;
594622
}
595623

596624
static void __exit ccp_mod_exit(void)
597625
{
626+
#ifdef CONFIG_X86
598627
struct cpuinfo_x86 *cpuinfo = &boot_cpu_data;
599628

600629
switch (cpuinfo->x86) {
601630
case 22:
602631
ccp_pci_exit();
603632
break;
604633
}
634+
#endif
635+
636+
#ifdef CONFIG_ARM64
637+
ccp_platform_exit();
638+
#endif
605639
}
606640

607641
module_init(ccp_mod_init);

drivers/crypto/ccp/ccp-dev.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030

3131
#define TRNG_RETRIES 10
3232

33+
#define CACHE_WB_NO_ALLOC 0xb7
34+
3335

3436
/****** Register Mappings ******/
3537
#define Q_MASK_REG 0x000
@@ -48,7 +50,7 @@
4850
#define CMD_Q_INT_STATUS_BASE 0x214
4951
#define CMD_Q_STATUS_INCR 0x20
5052

51-
#define CMD_Q_CACHE 0x228
53+
#define CMD_Q_CACHE_BASE 0x228
5254
#define CMD_Q_CACHE_INC 0x20
5355

5456
#define CMD_Q_ERROR(__qs) ((__qs) & 0x0000003f);
@@ -259,6 +261,9 @@ struct ccp_device {
259261
int ccp_pci_init(void);
260262
void ccp_pci_exit(void);
261263

264+
int ccp_platform_init(void);
265+
void ccp_platform_exit(void);
266+
262267
struct ccp_device *ccp_alloc_struct(struct device *dev);
263268
int ccp_init(struct ccp_device *ccp);
264269
void ccp_destroy(struct ccp_device *ccp);

drivers/crypto/ccp/ccp-platform.c

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/*
2+
* AMD Cryptographic Coprocessor (CCP) driver
3+
*
4+
* Copyright (C) 2014 Advanced Micro Devices, Inc.
5+
*
6+
* Author: Tom Lendacky <[email protected]>
7+
*
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.
11+
*/
12+
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>
25+
26+
#include "ccp-dev.h"
27+
28+
29+
static int ccp_get_irq(struct ccp_device *ccp)
30+
{
31+
struct device *dev = ccp->dev;
32+
struct platform_device *pdev = container_of(dev,
33+
struct platform_device, dev);
34+
int ret;
35+
36+
ret = platform_get_irq(pdev, 0);
37+
if (ret < 0)
38+
return ret;
39+
40+
ccp->irq = ret;
41+
ret = request_irq(ccp->irq, ccp_irq_handler, 0, "ccp", dev);
42+
if (ret) {
43+
dev_notice(dev, "unable to allocate IRQ (%d)\n", ret);
44+
return ret;
45+
}
46+
47+
return 0;
48+
}
49+
50+
static int ccp_get_irqs(struct ccp_device *ccp)
51+
{
52+
struct device *dev = ccp->dev;
53+
int ret;
54+
55+
ret = ccp_get_irq(ccp);
56+
if (!ret)
57+
return 0;
58+
59+
/* Couldn't get an interrupt */
60+
dev_notice(dev, "could not enable interrupts (%d)\n", ret);
61+
62+
return ret;
63+
}
64+
65+
static void ccp_free_irqs(struct ccp_device *ccp)
66+
{
67+
struct device *dev = ccp->dev;
68+
69+
free_irq(ccp->irq, dev);
70+
}
71+
72+
static struct resource *ccp_find_mmio_area(struct ccp_device *ccp)
73+
{
74+
struct device *dev = ccp->dev;
75+
struct platform_device *pdev = container_of(dev,
76+
struct platform_device, dev);
77+
struct resource *ior;
78+
79+
ior = platform_get_resource(pdev, IORESOURCE_MEM, 0);
80+
if (ior && (resource_size(ior) >= 0x800))
81+
return ior;
82+
83+
return NULL;
84+
}
85+
86+
static int ccp_platform_probe(struct platform_device *pdev)
87+
{
88+
struct ccp_device *ccp;
89+
struct device *dev = &pdev->dev;
90+
struct resource *ior;
91+
int ret;
92+
93+
ret = -ENOMEM;
94+
ccp = ccp_alloc_struct(dev);
95+
if (!ccp)
96+
goto e_err;
97+
98+
ccp->dev_specific = NULL;
99+
ccp->get_irq = ccp_get_irqs;
100+
ccp->free_irq = ccp_free_irqs;
101+
102+
ior = ccp_find_mmio_area(ccp);
103+
ccp->io_map = devm_ioremap_resource(dev, ior);
104+
if (IS_ERR(ccp->io_map)) {
105+
ret = PTR_ERR(ccp->io_map);
106+
goto e_free;
107+
}
108+
ccp->io_regs = ccp->io_map;
109+
110+
if (!dev->dma_mask)
111+
dev->dma_mask = &dev->coherent_dma_mask;
112+
*(dev->dma_mask) = DMA_BIT_MASK(48);
113+
dev->coherent_dma_mask = DMA_BIT_MASK(48);
114+
115+
dev_set_drvdata(dev, ccp);
116+
117+
ret = ccp_init(ccp);
118+
if (ret)
119+
goto e_free;
120+
121+
dev_notice(dev, "enabled\n");
122+
123+
return 0;
124+
125+
e_free:
126+
kfree(ccp);
127+
128+
e_err:
129+
dev_notice(dev, "initialization failed\n");
130+
return ret;
131+
}
132+
133+
static int ccp_platform_remove(struct platform_device *pdev)
134+
{
135+
struct device *dev = &pdev->dev;
136+
struct ccp_device *ccp = dev_get_drvdata(dev);
137+
138+
ccp_destroy(ccp);
139+
140+
kfree(ccp);
141+
142+
dev_notice(dev, "disabled\n");
143+
144+
return 0;
145+
}
146+
147+
#ifdef CONFIG_PM
148+
static int ccp_platform_suspend(struct platform_device *pdev,
149+
pm_message_t state)
150+
{
151+
struct device *dev = &pdev->dev;
152+
struct ccp_device *ccp = dev_get_drvdata(dev);
153+
unsigned long flags;
154+
unsigned int i;
155+
156+
spin_lock_irqsave(&ccp->cmd_lock, flags);
157+
158+
ccp->suspending = 1;
159+
160+
/* Wake all the queue kthreads to prepare for suspend */
161+
for (i = 0; i < ccp->cmd_q_count; i++)
162+
wake_up_process(ccp->cmd_q[i].kthread);
163+
164+
spin_unlock_irqrestore(&ccp->cmd_lock, flags);
165+
166+
/* Wait for all queue kthreads to say they're done */
167+
while (!ccp_queues_suspended(ccp))
168+
wait_event_interruptible(ccp->suspend_queue,
169+
ccp_queues_suspended(ccp));
170+
171+
return 0;
172+
}
173+
174+
static int ccp_platform_resume(struct platform_device *pdev)
175+
{
176+
struct device *dev = &pdev->dev;
177+
struct ccp_device *ccp = dev_get_drvdata(dev);
178+
unsigned long flags;
179+
unsigned int i;
180+
181+
spin_lock_irqsave(&ccp->cmd_lock, flags);
182+
183+
ccp->suspending = 0;
184+
185+
/* Wake up all the kthreads */
186+
for (i = 0; i < ccp->cmd_q_count; i++) {
187+
ccp->cmd_q[i].suspended = 0;
188+
wake_up_process(ccp->cmd_q[i].kthread);
189+
}
190+
191+
spin_unlock_irqrestore(&ccp->cmd_lock, flags);
192+
193+
return 0;
194+
}
195+
#endif
196+
197+
static const struct of_device_id ccp_platform_ids[] = {
198+
{ .compatible = "amd,ccp-seattle-v1a" },
199+
{ },
200+
};
201+
202+
static struct platform_driver ccp_platform_driver = {
203+
.driver = {
204+
.name = "AMD Cryptographic Coprocessor",
205+
.owner = THIS_MODULE,
206+
.of_match_table = ccp_platform_ids,
207+
},
208+
.probe = ccp_platform_probe,
209+
.remove = ccp_platform_remove,
210+
#ifdef CONFIG_PM
211+
.suspend = ccp_platform_suspend,
212+
.resume = ccp_platform_resume,
213+
#endif
214+
};
215+
216+
int ccp_platform_init(void)
217+
{
218+
return platform_driver_register(&ccp_platform_driver);
219+
}
220+
221+
void ccp_platform_exit(void)
222+
{
223+
platform_driver_unregister(&ccp_platform_driver);
224+
}

0 commit comments

Comments
 (0)