Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 318373
b: refs/heads/master
c: 281922a
h: refs/heads/master
i:
  318371: e4c66d4
v: v3
  • Loading branch information
Kim Phillips authored and Herbert Xu committed Jun 27, 2012
1 parent 71ef80b commit cf30065
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 15 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e13af18a3e33259e264c7fb47b54fbf608137976
refs/heads/master: 281922a1d4f59bdebbe78c1d9f4c50a967eb6cff
129 changes: 127 additions & 2 deletions trunk/drivers/crypto/caam/ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
* CAAM control-plane driver backend
* Controller-level driver, kernel property detection, initialization
*
* Copyright 2008-2011 Freescale Semiconductor, Inc.
* Copyright 2008-2012 Freescale Semiconductor, Inc.
*/

#include "compat.h"
#include "regs.h"
#include "intern.h"
#include "jr.h"
#include "desc_constr.h"
#include "error.h"

static int caam_remove(struct platform_device *pdev)
{
Expand Down Expand Up @@ -43,10 +45,120 @@ static int caam_remove(struct platform_device *pdev)
return ret;
}

/*
* Descriptor to instantiate RNG State Handle 0 in normal mode and
* load the JDKEK, TDKEK and TDSK registers
*/
static void build_instantiation_desc(u32 *desc)
{
u32 *jump_cmd;

init_job_desc(desc, 0);

/* INIT RNG in non-test mode */
append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
OP_ALG_AS_INIT);

/* wait for done */
jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
set_jump_tgt_here(desc, jump_cmd);

/*
* load 1 to clear written reg:
* resets the done interrrupt and returns the RNG to idle.
*/
append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);

/* generate secure keys (non-test) */
append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
OP_ALG_RNG4_SK);
}

struct instantiate_result {
struct completion completion;
int err;
};

static void rng4_init_done(struct device *dev, u32 *desc, u32 err,
void *context)
{
struct instantiate_result *instantiation = context;

if (err) {
char tmp[CAAM_ERROR_STR_MAX];

dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
}

instantiation->err = err;
complete(&instantiation->completion);
}

static int instantiate_rng(struct device *jrdev)
{
struct instantiate_result instantiation;

dma_addr_t desc_dma;
u32 *desc;
int ret;

desc = kmalloc(CAAM_CMD_SZ * 6, GFP_KERNEL | GFP_DMA);
if (!desc) {
dev_err(jrdev, "cannot allocate RNG init descriptor memory\n");
return -ENOMEM;
}

build_instantiation_desc(desc);
desc_dma = dma_map_single(jrdev, desc, desc_bytes(desc), DMA_TO_DEVICE);
init_completion(&instantiation.completion);
ret = caam_jr_enqueue(jrdev, desc, rng4_init_done, &instantiation);
if (!ret) {
wait_for_completion_interruptible(&instantiation.completion);
ret = instantiation.err;
if (ret)
dev_err(jrdev, "unable to instantiate RNG\n");
}

dma_unmap_single(jrdev, desc_dma, desc_bytes(desc), DMA_TO_DEVICE);

kfree(desc);

return ret;
}

/*
* By default, the TRNG runs for 200 clocks per sample;
* 800 clocks per sample generates better entropy.
*/
static void kick_trng(struct platform_device *pdev)
{
struct device *ctrldev = &pdev->dev;
struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
struct caam_full __iomem *topregs;
struct rng4tst __iomem *r4tst;
u32 val;

topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
r4tst = &topregs->ctrl.r4tst[0];

/* put RNG4 into program mode */
setbits32(&r4tst->rtmctl, RTMCTL_PRGM);
/* 800 clocks per sample */
val = rd_reg32(&r4tst->rtsdctl);
val = (val & ~RTSDCTL_ENT_DLY_MASK) | (800 << RTSDCTL_ENT_DLY_SHIFT);
wr_reg32(&r4tst->rtsdctl, val);
/* min. freq. count */
wr_reg32(&r4tst->rtfrqmin, 400);
/* max. freq. count */
wr_reg32(&r4tst->rtfrqmax, 6400);
/* put RNG4 into run mode */
clrbits32(&r4tst->rtmctl, RTMCTL_PRGM);
}

/* Probe routine for CAAM top (controller) level */
static int caam_probe(struct platform_device *pdev)
{
int ring, rspec;
int ret, ring, rspec;
struct device *dev;
struct device_node *nprop, *np;
struct caam_ctrl __iomem *ctrl;
Expand Down Expand Up @@ -146,6 +258,19 @@ static int caam_probe(struct platform_device *pdev)
return -ENOMEM;
}

/*
* RNG4 based SECs (v5+) need special initialization prior
* to executing any descriptors
*/
if (of_device_is_compatible(nprop, "fsl,sec-v5.0")) {
kick_trng(pdev);
ret = instantiate_rng(ctrlpriv->jrdev[0]);
if (ret) {
caam_remove(pdev);
return ret;
}
}

/* NOTE: RTIC detection ought to go here, around Si time */

/* Initialize queue allocator lock */
Expand Down
5 changes: 5 additions & 0 deletions trunk/drivers/crypto/caam/desc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1172,6 +1172,11 @@ struct sec4_sg_entry {
#define OP_ALG_AAI_GSM (0x10 << OP_ALG_AAI_SHIFT)
#define OP_ALG_AAI_EDGE (0x20 << OP_ALG_AAI_SHIFT)

/* RNG4 set */
#define OP_ALG_RNG4_SHIFT 4
#define OP_ALG_RNG4_MASK (0x1f3 << OP_ALG_RNG4_SHIFT)

#define OP_ALG_RNG4_SK (0x100 << OP_ALG_RNG4_SHIFT)

#define OP_ALG_AS_SHIFT 2
#define OP_ALG_AS_MASK (0x3 << OP_ALG_AS_SHIFT)
Expand Down
44 changes: 34 additions & 10 deletions trunk/drivers/crypto/caam/error.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,20 @@ static void report_ccb_status(u32 status, char *outstr)
char *cha_id_list[] = {
"",
"AES",
"DES, 3DES",
"DES",
"ARC4",
"MD5, SHA-1, SH-224, SHA-256, SHA-384, SHA-512",
"MDHA",
"RNG",
"SNOW f8",
"Kasumi f8, f9",
"All Public Key Algorithms",
"CRC",
"Kasumi f8/9",
"PKHA",
"CRCA",
"SNOW f9",
"ZUCE",
"ZUCA",
};
char *err_id_list[] = {
"None. No error.",
"No error.",
"Mode error.",
"Data size error.",
"Key size error.",
Expand All @@ -67,6 +69,20 @@ static void report_ccb_status(u32 status, char *outstr)
"Invalid CHA combination was selected",
"Invalid CHA selected.",
};
char *rng_err_id_list[] = {
"",
"",
"",
"Instantiate",
"Not instantiated",
"Test instantiate",
"Prediction resistance",
"",
"Prediction resistance and test request",
"Uninstantiate",
"",
"Secure key generation",
};
u8 cha_id = (status & JRSTA_CCBERR_CHAID_MASK) >>
JRSTA_CCBERR_CHAID_SHIFT;
u8 err_id = status & JRSTA_CCBERR_ERRID_MASK;
Expand All @@ -81,7 +97,13 @@ static void report_ccb_status(u32 status, char *outstr)
cha_id, sizeof("ff"));
}

if (err_id < ARRAY_SIZE(err_id_list)) {
if ((cha_id << JRSTA_CCBERR_CHAID_SHIFT) == JRSTA_CCBERR_CHAID_RNG &&
err_id < ARRAY_SIZE(rng_err_id_list) &&
strlen(rng_err_id_list[err_id])) {
/* RNG-only error */
SPRINTFCAT(outstr, "%s", rng_err_id_list[err_id],
strlen(rng_err_id_list[err_id]));
} else if (err_id < ARRAY_SIZE(err_id_list)) {
SPRINTFCAT(outstr, "%s", err_id_list[err_id],
strlen(err_id_list[err_id]));
} else {
Expand All @@ -101,10 +123,10 @@ static void report_deco_status(u32 status, char *outstr)
u8 value;
char *error_text;
} desc_error_list[] = {
{ 0x00, "None. No error." },
{ 0x00, "No error." },
{ 0x01, "SGT Length Error. The descriptor is trying to read "
"more data than is contained in the SGT table." },
{ 0x02, "Reserved." },
{ 0x02, "SGT Null Entry Error." },
{ 0x03, "Job Ring Control Error. There is a bad value in the "
"Job Ring Control register." },
{ 0x04, "Invalid Descriptor Command. The Descriptor Command "
Expand All @@ -116,7 +138,7 @@ static void report_deco_status(u32 status, char *outstr)
{ 0x09, "Invalid OPERATION Command" },
{ 0x0A, "Invalid FIFO LOAD Command" },
{ 0x0B, "Invalid FIFO STORE Command" },
{ 0x0C, "Invalid MOVE Command" },
{ 0x0C, "Invalid MOVE/MOVE_LEN Command" },
{ 0x0D, "Invalid JUMP Command. A nonlocal JUMP Command is "
"invalid because the target is not a Job Header "
"Command, or the jump is from a Trusted Descriptor to "
Expand Down Expand Up @@ -166,6 +188,8 @@ static void report_deco_status(u32 status, char *outstr)
"(input frame; block ciphers) and IPsec decap (output "
"frame, when doing the next header byte update) and "
"DCRC (output frame)." },
{ 0x23, "Read Input Frame error" },
{ 0x24, "JDKEK, TDKEK or TDSK not loaded error" },
{ 0x80, "DNR (do not run) error" },
{ 0x81, "undefined protocol command" },
{ 0x82, "invalid setting in PDB" },
Expand Down
32 changes: 30 additions & 2 deletions trunk/drivers/crypto/caam/regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ struct partid {
u32 pidr; /* partition ID, DECO */
};

/* RNG test mode (replicated twice in some configurations) */
/* RNGB test mode (replicated twice in some configurations) */
/* Padded out to 0x100 */
struct rngtst {
u32 mode; /* RTSTMODEx - Test mode */
Expand Down Expand Up @@ -200,6 +200,31 @@ struct rngtst {
u32 rsvd14[15];
};

/* RNG4 TRNG test registers */
struct rng4tst {
#define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */
u32 rtmctl; /* misc. control register */
u32 rtscmisc; /* statistical check misc. register */
u32 rtpkrrng; /* poker range register */
union {
u32 rtpkrmax; /* PRGM=1: poker max. limit register */
u32 rtpkrsq; /* PRGM=0: poker square calc. result register */
};
#define RTSDCTL_ENT_DLY_SHIFT 16
#define RTSDCTL_ENT_DLY_MASK (0xffff << RTSDCTL_ENT_DLY_SHIFT)
u32 rtsdctl; /* seed control register */
union {
u32 rtsblim; /* PRGM=1: sparse bit limit register */
u32 rttotsam; /* PRGM=0: total samples register */
};
u32 rtfrqmin; /* frequency count min. limit register */
union {
u32 rtfrqmax; /* PRGM=1: freq. count max. limit register */
u32 rtfrqcnt; /* PRGM=0: freq. count register */
};
u32 rsvd1[56];
};

/*
* caam_ctrl - basic core configuration
* starts base + 0x0000 padded out to 0x1000
Expand Down Expand Up @@ -249,7 +274,10 @@ struct caam_ctrl {

/* RNG Test/Verification/Debug Access 600-7ff */
/* (Useful in Test/Debug modes only...) */
struct rngtst rtst[2];
union {
struct rngtst rtst[2];
struct rng4tst r4tst[2];
};

u32 rsvd9[448];

Expand Down

0 comments on commit cf30065

Please sign in to comment.