aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto/caam/ctrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/crypto/caam/ctrl.c')
-rw-r--r--drivers/crypto/caam/ctrl.c129
1 files changed, 127 insertions, 2 deletions
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 9a2db9c30630..ac6abb375c8d 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -2,13 +2,15 @@
2 * CAAM control-plane driver backend 2 * CAAM control-plane driver backend
3 * Controller-level driver, kernel property detection, initialization 3 * Controller-level driver, kernel property detection, initialization
4 * 4 *
5 * Copyright 2008-2011 Freescale Semiconductor, Inc. 5 * Copyright 2008-2012 Freescale Semiconductor, Inc.
6 */ 6 */
7 7
8#include "compat.h" 8#include "compat.h"
9#include "regs.h" 9#include "regs.h"
10#include "intern.h" 10#include "intern.h"
11#include "jr.h" 11#include "jr.h"
12#include "desc_constr.h"
13#include "error.h"
12 14
13static int caam_remove(struct platform_device *pdev) 15static int caam_remove(struct platform_device *pdev)
14{ 16{
@@ -43,10 +45,120 @@ static int caam_remove(struct platform_device *pdev)
43 return ret; 45 return ret;
44} 46}
45 47
48/*
49 * Descriptor to instantiate RNG State Handle 0 in normal mode and
50 * load the JDKEK, TDKEK and TDSK registers
51 */
52static void build_instantiation_desc(u32 *desc)
53{
54 u32 *jump_cmd;
55
56 init_job_desc(desc, 0);
57
58 /* INIT RNG in non-test mode */
59 append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
60 OP_ALG_AS_INIT);
61
62 /* wait for done */
63 jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
64 set_jump_tgt_here(desc, jump_cmd);
65
66 /*
67 * load 1 to clear written reg:
68 * resets the done interrrupt and returns the RNG to idle.
69 */
70 append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
71
72 /* generate secure keys (non-test) */
73 append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
74 OP_ALG_RNG4_SK);
75}
76
77struct instantiate_result {
78 struct completion completion;
79 int err;
80};
81
82static void rng4_init_done(struct device *dev, u32 *desc, u32 err,
83 void *context)
84{
85 struct instantiate_result *instantiation = context;
86
87 if (err) {
88 char tmp[CAAM_ERROR_STR_MAX];
89
90 dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
91 }
92
93 instantiation->err = err;
94 complete(&instantiation->completion);
95}
96
97static int instantiate_rng(struct device *jrdev)
98{
99 struct instantiate_result instantiation;
100
101 dma_addr_t desc_dma;
102 u32 *desc;
103 int ret;
104
105 desc = kmalloc(CAAM_CMD_SZ * 6, GFP_KERNEL | GFP_DMA);
106 if (!desc) {
107 dev_err(jrdev, "cannot allocate RNG init descriptor memory\n");
108 return -ENOMEM;
109 }
110
111 build_instantiation_desc(desc);
112 desc_dma = dma_map_single(jrdev, desc, desc_bytes(desc), DMA_TO_DEVICE);
113 init_completion(&instantiation.completion);
114 ret = caam_jr_enqueue(jrdev, desc, rng4_init_done, &instantiation);
115 if (!ret) {
116 wait_for_completion_interruptible(&instantiation.completion);
117 ret = instantiation.err;
118 if (ret)
119 dev_err(jrdev, "unable to instantiate RNG\n");
120 }
121
122 dma_unmap_single(jrdev, desc_dma, desc_bytes(desc), DMA_TO_DEVICE);
123
124 kfree(desc);
125
126 return ret;
127}
128
129/*
130 * By default, the TRNG runs for 200 clocks per sample;
131 * 800 clocks per sample generates better entropy.
132 */
133static void kick_trng(struct platform_device *pdev)
134{
135 struct device *ctrldev = &pdev->dev;
136 struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
137 struct caam_full __iomem *topregs;
138 struct rng4tst __iomem *r4tst;
139 u32 val;
140
141 topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
142 r4tst = &topregs->ctrl.r4tst[0];
143
144 /* put RNG4 into program mode */
145 setbits32(&r4tst->rtmctl, RTMCTL_PRGM);
146 /* 800 clocks per sample */
147 val = rd_reg32(&r4tst->rtsdctl);
148 val = (val & ~RTSDCTL_ENT_DLY_MASK) | (800 << RTSDCTL_ENT_DLY_SHIFT);
149 wr_reg32(&r4tst->rtsdctl, val);
150 /* min. freq. count */
151 wr_reg32(&r4tst->rtfrqmin, 400);
152 /* max. freq. count */
153 wr_reg32(&r4tst->rtfrqmax, 6400);
154 /* put RNG4 into run mode */
155 clrbits32(&r4tst->rtmctl, RTMCTL_PRGM);
156}
157
46/* Probe routine for CAAM top (controller) level */ 158/* Probe routine for CAAM top (controller) level */
47static int caam_probe(struct platform_device *pdev) 159static int caam_probe(struct platform_device *pdev)
48{ 160{
49 int ring, rspec; 161 int ret, ring, rspec;
50 struct device *dev; 162 struct device *dev;
51 struct device_node *nprop, *np; 163 struct device_node *nprop, *np;
52 struct caam_ctrl __iomem *ctrl; 164 struct caam_ctrl __iomem *ctrl;
@@ -146,6 +258,19 @@ static int caam_probe(struct platform_device *pdev)
146 return -ENOMEM; 258 return -ENOMEM;
147 } 259 }
148 260
261 /*
262 * RNG4 based SECs (v5+) need special initialization prior
263 * to executing any descriptors
264 */
265 if (of_device_is_compatible(nprop, "fsl,sec-v5.0")) {
266 kick_trng(pdev);
267 ret = instantiate_rng(ctrlpriv->jrdev[0]);
268 if (ret) {
269 caam_remove(pdev);
270 return ret;
271 }
272 }
273
149 /* NOTE: RTIC detection ought to go here, around Si time */ 274 /* NOTE: RTIC detection ought to go here, around Si time */
150 275
151 /* Initialize queue allocator lock */ 276 /* Initialize queue allocator lock */