aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/crypto/fsl-sec4.txt409
-rw-r--r--arch/powerpc/boot/dts/p4080ds.dts95
-rw-r--r--drivers/crypto/Kconfig2
-rw-r--r--drivers/crypto/Makefile1
-rw-r--r--drivers/crypto/caam/Kconfig72
-rw-r--r--drivers/crypto/caam/Makefile8
-rw-r--r--drivers/crypto/caam/caamalg.c1163
-rw-r--r--drivers/crypto/caam/compat.h35
-rw-r--r--drivers/crypto/caam/ctrl.c270
-rw-r--r--drivers/crypto/caam/desc.h1605
-rw-r--r--drivers/crypto/caam/desc_constr.h204
-rw-r--r--drivers/crypto/caam/error.c248
-rw-r--r--drivers/crypto/caam/error.h10
-rw-r--r--drivers/crypto/caam/intern.h113
-rw-r--r--drivers/crypto/caam/jr.c523
-rw-r--r--drivers/crypto/caam/jr.h21
-rw-r--r--drivers/crypto/caam/regs.h663
17 files changed, 5441 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
new file mode 100644
index 00000000000..fce16a85e2c
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
@@ -0,0 +1,409 @@
+=====================================================================
+SEC 4 Device Tree Binding
+Copyright (C) 2008-2011 Freescale Semiconductor Inc.
+
+ CONTENTS
+ -Overview
+ -SEC 4 Node
+ -Job Ring Node
+ -Run Time Integrity Check (RTIC) Node
+ -Run Time Integrity Check (RTIC) Memory Node
+ -Secure Non-Volatile Storage (SNVS) Node
+ -Full Example
+
+NOTE: the SEC 4 is also known as Freescale's Cryptographic Accelerator
+Accelerator and Assurance Module (CAAM).
+
+=====================================================================
+Overview
+
+DESCRIPTION
+
+SEC 4 h/w can process requests from 2 types of sources.
+1. DPAA Queue Interface (HW interface between Queue Manager & SEC 4).
+2. Job Rings (HW interface between cores & SEC 4 registers).
+
+High Speed Data Path Configuration:
+
+HW interface between QM & SEC 4 and also BM & SEC 4, on DPAA-enabled parts
+such as the P4080. The number of simultaneous dequeues the QI can make is
+equal to the number of Descriptor Controller (DECO) engines in a particular
+SEC version. E.g., the SEC 4.0 in the P4080 has 5 DECOs and can thus
+dequeue from 5 subportals simultaneously.
+
+Job Ring Data Path Configuration:
+
+Each JR is located on a separate 4k page, they may (or may not) be made visible
+in the memory partition devoted to a particular core. The P4080 has 4 JRs, so
+up to 4 JRs can be configured; and all 4 JRs process requests in parallel.
+
+=====================================================================
+P4080 SEC 4 Node
+
+Description
+
+ Node defines the base address of the SEC 4 block.
+ This block specifies the address range of all global
+ configuration registers for the SEC 4 block. It
+ also receives interrupts from the Run Time Integrity Check
+ (RTIC) function within the SEC 4 block.
+
+PROPERTIES
+
+ - compatible
+ Usage: required
+ Value type: <string>
+ Definition: Must include "fsl,p4080-sec4.0","fsl,sec-4.0"
+
+ - #address-cells
+ Usage: required
+ Value type: <u32>
+ Definition: A standard property. Defines the number of cells
+ for representing physical addresses in child nodes.
+
+ - #size-cells
+ Usage: required
+ Value type: <u32>
+ Definition: A standard property. Defines the number of cells
+ for representing the size of physical addresses in
+ child nodes.
+
+ - reg
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property. Specifies the physical
+ address and length of the SEC4.0 configuration registers.
+ registers
+
+ - ranges
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property. Specifies the physical address
+ range of the SEC 4.0 register space (-SNVS not included). A
+ triplet that includes the child address, parent address, &
+ length.
+
+ - interrupts
+ Usage: required
+ Value type: <prop_encoded-array>
+ Definition: Specifies the interrupts generated by this
+ device. The value of the interrupts property
+ consists of one interrupt specifier. The format
+ of the specifier is defined by the binding document
+ describing the node's interrupt parent.
+
+ - interrupt-parent
+ Usage: (required if interrupt property is defined)
+ Value type: <phandle>
+ Definition: A single <phandle> value that points
+ to the interrupt parent to which the child domain
+ is being mapped.
+
+ Note: All other standard properties (see the ePAPR) are allowed
+ but are optional.
+
+
+EXAMPLE
+ crypto@300000 {
+ compatible = "fsl,p4080-sec4.0", "fsl,sec4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x300000 0x10000>;
+ ranges = <0 0x300000 0x10000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <92 2>;
+ };
+
+=====================================================================
+P4080 Job Ring (JR) Node
+
+ Child of the crypto node defines data processing interface to SEC 4
+ across the peripheral bus for purposes of processing
+ cryptographic descriptors. The specified address
+ range can be made visible to one (or more) cores.
+ The interrupt defined for this node is controlled within
+ the address range of this node.
+
+ - compatible
+ Usage: required
+ Value type: <string>
+ Definition: Must include "fsl,p4080-sec4.0-job-ring","fsl,sec4.0-job-ring"
+
+ - reg
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: Specifies a two JR parameters: an offset from
+ the parent physical address and the length the JR registers.
+
+ - fsl,liodn
+ Usage: optional-but-recommended
+ Value type: <prop-encoded-array>
+ Definition:
+ Specifies the LIODN to be used in conjunction with
+ the ppid-to-liodn table that specifies the PPID to LIODN mapping.
+ Needed if the PAMU is used. Value is a 12 bit value
+ where value is a LIODN ID for this JR. This property is
+ normally set by boot firmware.
+
+ - interrupts
+ Usage: required
+ Value type: <prop_encoded-array>
+ Definition: Specifies the interrupts generated by this
+ device. The value of the interrupts property
+ consists of one interrupt specifier. The format
+ of the specifier is defined by the binding document
+ describing the node's interrupt parent.
+
+ - interrupt-parent
+ Usage: (required if interrupt property is defined)
+ Value type: <phandle>
+ Definition: A single <phandle> value that points
+ to the interrupt parent to which the child domain
+ is being mapped.
+
+EXAMPLE
+ jr@1000 {
+ compatible = "fsl,p4080-sec4.0-job-ring",
+ "fsl,sec4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ fsl,liodn = <0x081>;
+ interrupt-parent = <&mpic>;
+ interrupts = <88 2>;
+ };
+
+
+=====================================================================
+P4080 Run Time Integrity Check (RTIC) Node
+
+ Child node of the crypto node. Defines a register space that
+ contains up to 5 sets of addresses and their lengths (sizes) that
+ will be checked at run time. After an initial hash result is
+ calculated, these addresses are checked by HW to monitor any
+ change. If any memory is modified, a Security Violation is
+ triggered (see SNVS definition).
+
+
+ - compatible
+ Usage: required
+ Value type: <string>
+ Definition: Must include "fsl,p4080-sec4.0-rtic","fsl,sec4.0-rtic".
+
+ - #address-cells
+ Usage: required
+ Value type: <u32>
+ Definition: A standard property. Defines the number of cells
+ for representing physical addresses in child nodes. Must
+ have a value of 1.
+
+ - #size-cells
+ Usage: required
+ Value type: <u32>
+ Definition: A standard property. Defines the number of cells
+ for representing the size of physical addresses in
+ child nodes. Must have a value of 1.
+
+ - reg
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property. Specifies a two parameters:
+ an offset from the parent physical address and the length
+ the SEC4 registers.
+
+ - ranges
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property. Specifies the physical address
+ range of the SEC 4 register space (-SNVS not included). A
+ triplet that includes the child address, parent address, &
+ length.
+
+EXAMPLE
+ rtic@6000 {
+ compatible = "fsl,p4080-sec4.0-rtic",
+ "fsl,sec4.0-rtic";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x6000 0x100>;
+ ranges = <0x0 0x6100 0xe00>;
+ };
+
+=====================================================================
+P4080 Run Time Integrity Check (RTIC) Memory Node
+ A child node that defines individual RTIC memory regions that are used to
+ perform run-time integrity check of memory areas that should not modified.
+ The node defines a register that contains the memory address &
+ length (combined) and a second register that contains the hash result
+ in big endian format.
+
+ - compatible
+ Usage: required
+ Value type: <string>
+ Definition: Must include "fsl,p4080-sec4.0-rtic-memory","fsl,sec4.0-rtic-memory".
+
+ - reg
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property. Specifies two parameters:
+ an offset from the parent physical address and the length:
+
+ 1. The location of the RTIC memory address & length registers.
+ 2. The location RTIC hash result.
+
+ - fsl,rtic-region
+ Usage: optional-but-recommended
+ Value type: <prop-encoded-array>
+ Definition:
+ Specifies the HW address (36 bit address) for this region
+ followed by the length of the HW partition to be checked;
+ the address is represented as a 64 bit quantity followed
+ by a 32 bit length.
+
+ - fsl,liodn
+ Usage: optional-but-recommended
+ Value type: <prop-encoded-array>
+ Definition:
+ Specifies the LIODN to be used in conjunction with
+ the ppid-to-liodn table that specifies the PPID to LIODN
+ mapping. Needed if the PAMU is used. Value is a 12 bit value
+ where value is a LIODN ID for this RTIC memory region. This
+ property is normally set by boot firmware.
+
+EXAMPLE
+ rtic-a@0 {
+ compatible = "fsl,p4080-sec4.0-rtic-memory",
+ "fsl,sec4.0-rtic-memory";
+ reg = <0x00 0x20 0x100 0x80>;
+ fsl,liodn = <0x03c>;
+ fsl,rtic-region = <0x12345678 0x12345678 0x12345678>;
+ };
+
+=====================================================================
+P4080 Secure Non-Volatile Storage (SNVS) Node
+
+ Node defines address range and the associated
+ interrupt for the SNVS function. This function
+ monitors security state information & reports
+ security violations.
+
+ - compatible
+ Usage: required
+ Value type: <string>
+ Definition: Must include "fsl,p4080-sec4.0-mon", "fsl,sec4.0-mon".
+
+ - reg
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property. Specifies the physical
+ address and length of the SEC4 configuration
+ registers.
+
+ - interrupts
+ Usage: required
+ Value type: <prop_encoded-array>
+ Definition: Specifies the interrupts generated by this
+ device. The value of the interrupts property
+ consists of one interrupt specifier. The format
+ of the specifier is defined by the binding document
+ describing the node's interrupt parent.
+
+ - interrupt-parent
+ Usage: (required if interrupt property is defined)
+ Value type: <phandle>
+ Definition: A single <phandle> value that points
+ to the interrupt parent to which the child domain
+ is being mapped.
+
+EXAMPLE
+ sec_mon@314000 {
+ compatible = "fsl,p4080-sec4.0-mon", "fsl,sec4.0-mon";
+ reg = <0x314000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <93 2>;
+ };
+
+=====================================================================
+FULL EXAMPLE
+
+ crypto: crypto@300000 {
+ compatible = "fsl,p4080-sec4.0", "fsl,sec4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x300000 0x10000>;
+ ranges = <0 0x300000 0x10000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <92 2>;
+
+ sec_jr0: jr@1000 {
+ compatible = "fsl,p4080-sec4.0-job-ring",
+ "fsl,sec4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <88 2>;
+ };
+
+ sec_jr1: jr@2000 {
+ compatible = "fsl,p4080-sec4.0-job-ring",
+ "fsl,sec4.0-job-ring";
+ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <89 2>;
+ };
+
+ sec_jr2: jr@3000 {
+ compatible = "fsl,p4080-sec4.0-job-ring",
+ "fsl,sec4.0-job-ring";
+ reg = <0x3000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <90 2>;
+ };
+
+ sec_jr3: jr@4000 {
+ compatible = "fsl,p4080-sec4.0-job-ring",
+ "fsl,sec4.0-job-ring";
+ reg = <0x4000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <91 2>;
+ };
+
+ rtic@6000 {
+ compatible = "fsl,p4080-sec4.0-rtic",
+ "fsl,sec4.0-rtic";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x6000 0x100>;
+ ranges = <0x0 0x6100 0xe00>;
+
+ rtic_a: rtic-a@0 {
+ compatible = "fsl,p4080-sec4.0-rtic-memory",
+ "fsl,sec4.0-rtic-memory";
+ reg = <0x00 0x20 0x100 0x80>;
+ };
+
+ rtic_b: rtic-b@20 {
+ compatible = "fsl,p4080-sec4.0-rtic-memory",
+ "fsl,sec4.0-rtic-memory";
+ reg = <0x20 0x20 0x200 0x80>;
+ };
+
+ rtic_c: rtic-c@40 {
+ compatible = "fsl,p4080-sec4.0-rtic-memory",
+ "fsl,sec4.0-rtic-memory";
+ reg = <0x40 0x20 0x300 0x80>;
+ };
+
+ rtic_d: rtic-d@60 {
+ compatible = "fsl,p4080-sec4.0-rtic-memory",
+ "fsl,sec4.0-rtic-memory";
+ reg = <0x60 0x20 0x500 0x80>;
+ };
+ };
+ };
+
+ sec_mon: sec_mon@314000 {
+ compatible = "fsl,p4080-sec4.0-mon", "fsl,sec4.0-mon";
+ reg = <0x314000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <93 2>;
+ };
+
+=====================================================================
diff --git a/arch/powerpc/boot/dts/p4080ds.dts b/arch/powerpc/boot/dts/p4080ds.dts
index 5b7fc29dd6c..c78e8015501 100644
--- a/arch/powerpc/boot/dts/p4080ds.dts
+++ b/arch/powerpc/boot/dts/p4080ds.dts
@@ -1,7 +1,7 @@
/*
* P4080DS Device Tree Source
*
- * Copyright 2009 Freescale Semiconductor Inc.
+ * Copyright 2009-2011 Freescale Semiconductor Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -33,6 +33,17 @@
dma1 = &dma1;
sdhc = &sdhc;
+ crypto = &crypto;
+ sec_jr0 = &sec_jr0;
+ sec_jr1 = &sec_jr1;
+ sec_jr2 = &sec_jr2;
+ sec_jr3 = &sec_jr3;
+ rtic_a = &rtic_a;
+ rtic_b = &rtic_b;
+ rtic_c = &rtic_c;
+ rtic_d = &rtic_d;
+ sec_mon = &sec_mon;
+
rio0 = &rapidio0;
};
@@ -410,6 +421,88 @@
dr_mode = "host";
phy_type = "ulpi";
};
+
+ crypto: crypto@300000 {
+ compatible = "fsl,p4080-sec4.0", "fsl,sec4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x300000 0x10000>;
+ ranges = <0 0x300000 0x10000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <92 2>;
+
+ sec_jr0: jr@1000 {
+ compatible = "fsl,p4080-sec4.0-job-ring",
+ "fsl,sec4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <88 2>;
+ };
+
+ sec_jr1: jr@2000 {
+ compatible = "fsl,p4080-sec4.0-job-ring",
+ "fsl,sec4.0-job-ring";
+ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <89 2>;
+ };
+
+ sec_jr2: jr@3000 {
+ compatible = "fsl,p4080-sec4.0-job-ring",
+ "fsl,sec4.0-job-ring";
+ reg = <0x3000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <90 2>;
+ };
+
+ sec_jr3: jr@4000 {
+ compatible = "fsl,p4080-sec4.0-job-ring",
+ "fsl,sec4.0-job-ring";
+ reg = <0x4000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <91 2>;
+ };
+
+ rtic@6000 {
+ compatible = "fsl,p4080-sec4.0-rtic",
+ "fsl,sec4.0-rtic";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x6000 0x100>;
+ ranges = <0x0 0x6100 0xe00>;
+
+ rtic_a: rtic-a@0 {
+ compatible = "fsl,p4080-sec4.0-rtic-memory",
+ "fsl,sec4.0-rtic-memory";
+ reg = <0x00 0x20 0x100 0x80>;
+ };
+
+ rtic_b: rtic-b@20 {
+ compatible = "fsl,p4080-sec4.0-rtic-memory",
+ "fsl,sec4.0-rtic-memory";
+ reg = <0x20 0x20 0x200 0x80>;
+ };
+
+ rtic_c: rtic-c@40 {
+ compatible = "fsl,p4080-sec4.0-rtic-memory",
+ "fsl,sec4.0-rtic-memory";
+ reg = <0x40 0x20 0x300 0x80>;
+ };
+
+ rtic_d: rtic-d@60 {
+ compatible = "fsl,p4080-sec4.0-rtic-memory",
+ "fsl,sec4.0-rtic-memory";
+ reg = <0x60 0x20 0x500 0x80>;
+ };
+ };
+ };
+
+ sec_mon: sec_mon@314000 {
+ compatible = "fsl,p4080-sec4.0-mon", "fsl,sec4.0-mon";
+ reg = <0x314000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <93 2>;
+ };
};
rapidio0: rapidio@ffe0c0000 {
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index e54185223c8..a27224aa883 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -200,6 +200,8 @@ config CRYPTO_DEV_HIFN_795X_RNG
Select this option if you want to enable the random number generator
on the HIFN 795x crypto adapters.
+source drivers/crypto/caam/Kconfig
+
config CRYPTO_DEV_TALITOS
tristate "Talitos Freescale Security Engine (SEC)"
select CRYPTO_ALGAPI
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 5203e34248d..663c5efec13 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -6,6 +6,7 @@ n2_crypto-y := n2_core.o n2_asm.o
obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o
obj-$(CONFIG_CRYPTO_DEV_MV_CESA) += mv_cesa.o
obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam/
obj-$(CONFIG_CRYPTO_DEV_IXP4XX) += ixp4xx_crypto.o
obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/
obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o
diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
new file mode 100644
index 00000000000..2d876bb98ff
--- /dev/null
+++ b/drivers/crypto/caam/Kconfig
@@ -0,0 +1,72 @@
+config CRYPTO_DEV_FSL_CAAM
+ tristate "Freescale CAAM-Multicore driver backend"
+ depends on FSL_SOC
+ help
+ Enables the driver module for Freescale's Cryptographic Accelerator
+ and Assurance Module (CAAM), also known as the SEC version 4 (SEC4).
+ This module adds a job ring operation interface, and configures h/w
+ to operate as a DPAA component automatically, depending
+ on h/w feature availability.
+
+ To compile this driver as a module, choose M here: the module
+ will be called caam.
+
+config CRYPTO_DEV_FSL_CAAM_RINGSIZE
+ int "Job Ring size"
+ depends on CRYPTO_DEV_FSL_CAAM
+ range 2 9
+ default "9"
+ help
+ Select size of Job Rings as a power of 2, within the
+ range 2-9 (ring size 4-512).
+ Examples:
+ 2 => 4
+ 3 => 8
+ 4 => 16
+ 5 => 32
+ 6 => 64
+ 7 => 128
+ 8 => 256
+ 9 => 512
+
+config CRYPTO_DEV_FSL_CAAM_INTC
+ bool "Job Ring interrupt coalescing"
+ depends on CRYPTO_DEV_FSL_CAAM
+ default y
+ help
+ Enable the Job Ring's interrupt coalescing feature.
+
+config CRYPTO_DEV_FSL_CAAM_INTC_COUNT_THLD
+ int "Job Ring interrupt coalescing count threshold"
+ depends on CRYPTO_DEV_FSL_CAAM_INTC
+ range 1 255
+ default 255
+ help
+ Select number of descriptor completions to queue before
+ raising an interrupt, in the range 1-255. Note that a selection
+ of 1 functionally defeats the coalescing feature, and a selection
+ equal or greater than the job ring size will force timeouts.
+
+config CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD
+ int "Job Ring interrupt coalescing timer threshold"
+ depends on CRYPTO_DEV_FSL_CAAM_INTC
+ range 1 65535
+ default 2048
+ help
+ Select number of bus clocks/64 to timeout in the case that one or
+ more descriptor completions are queued without reaching the count
+ threshold. Range is 1-65535.
+
+config CRYPTO_DEV_FSL_CAAM_CRYPTO_API
+ tristate "Register algorithm implementations with the Crypto API"
+ depends on CRYPTO_DEV_FSL_CAAM
+ default y
+ select CRYPTO_ALGAPI
+ select CRYPTO_AUTHENC
+ help
+ Selecting this will offload crypto for users of the
+ scatterlist crypto API (such as the linux native IPSec
+ stack) to the SEC4 via job ring.
+
+ To compile this as a module, choose M here: the module
+ will be called caamalg.
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
new file mode 100644
index 00000000000..ef39011b450
--- /dev/null
+++ b/drivers/crypto/caam/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the CAAM backend and dependent components
+#
+
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
+
+caam-objs := ctrl.o jr.o error.o
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
new file mode 100644
index 00000000000..d7fe3d3d7db
--- /dev/null
+++ b/drivers/crypto/caam/caamalg.c
@@ -0,0 +1,1163 @@
+/*
+ * caam - Freescale FSL CAAM support for crypto API
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Based on talitos crypto API driver.
+ *
+ * relationship of job descriptors to shared descriptors (SteveC Dec 10 2008):
+ *
+ * --------------- ---------------
+ * | JobDesc #1 |-------------------->| ShareDesc |
+ * | *(packet 1) | | (PDB) |
+ * --------------- |------------->| (hashKey) |
+ * . | | (cipherKey) |
+ * . | |-------->| (operation) |
+ * --------------- | | ---------------
+ * | JobDesc #2 |------| |
+ * | *(packet 2) | |
+ * --------------- |
+ * . |
+ * . |
+ * --------------- |
+ * | JobDesc #3 |------------
+ * | *(packet 3) |
+ * ---------------
+ *
+ * The SharedDesc never changes for a connection unless rekeyed, but
+ * each packet will likely be in a different place. So all we need
+ * to know to process the packet is where the input is, where the
+ * output goes, and what context we want to process with. Context is
+ * in the SharedDesc, packet references in the JobDesc.
+ *
+ * So, a job desc looks like:
+ *
+ * ---------------------
+ * | Header |
+ * | ShareDesc Pointer |
+ * | SEQ_OUT_PTR |
+ * | (output buffer) |
+ * | SEQ_IN_PTR |
+ * | (input buffer) |
+ * | LOAD (to DECO) |
+ * ---------------------
+ */
+
+#include "compat.h"
+
+#include "regs.h"
+#include "intern.h"
+#include "desc_constr.h"
+#include "jr.h"
+#include "error.h"
+
+/*
+ * crypto alg
+ */
+#define CAAM_CRA_PRIORITY 3000
+/* max key is sum of AES_MAX_KEY_SIZE, max split key size */
+#define CAAM_MAX_KEY_SIZE (AES_MAX_KEY_SIZE + \
+ SHA512_DIGEST_SIZE * 2)
+/* max IV is max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
+#define CAAM_MAX_IV_LENGTH 16
+
+#ifdef DEBUG
+/* for print_hex_dumps with line references */
+#define xstr(s) str(s)
+#define str(s) #s
+#define debug(format, arg...) printk(format, arg)
+#else
+#define debug(format, arg...)
+#endif
+
+/*
+ * per-session context
+ */
+struct caam_ctx {
+ struct device *jrdev;
+ u32 *sh_desc;
+ dma_addr_t shared_desc_phys;
+ u32 class1_alg_type;
+ u32 class2_alg_type;
+ u32 alg_op;
+ u8 *key;
+ dma_addr_t key_phys;
+ unsigned int keylen;
+ unsigned int enckeylen;
+ unsigned int authkeylen;
+ unsigned int split_key_len;
+ unsigned int split_key_pad_len;
+ unsigned int authsize;
+};
+
+static int aead_authenc_setauthsize(struct crypto_aead *authenc,
+ unsigned int authsize)
+{
+ struct caam_ctx *ctx = crypto_aead_ctx(authenc);
+
+ ctx->authsize = authsize;
+
+ return 0;
+}
+
+struct split_key_result {
+ struct completion completion;
+ int err;
+};
+
+static void split_key_done(struct device *dev, u32 *desc, u32 err,
+ void *context)
+{
+ struct split_key_result *res = context;
+
+#ifdef DEBUG
+ dev_err(dev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
+#endif
+ if (err) {
+ char tmp[256];
+
+ dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+ }
+
+ res->err = err;
+
+ complete(&res->completion);
+}
+
+/*
+get a split ipad/opad key
+
+Split key generation-----------------------------------------------
+
+[00] 0xb0810008 jobdesc: stidx=1 share=never len=8
+[01] 0x04000014 key: class2->keyreg len=20
+ @0xffe01000
+[03] 0x84410014 operation: cls2-op sha1 hmac init dec
+[04] 0x24940000 fifold: class2 msgdata-last2 len=0 imm
+[05] 0xa4000001 jump: class2 local all ->1 [06]
+[06] 0x64260028 fifostr: class2 mdsplit-jdk len=40
+ @0xffe04000
+*/
+static u32 gen_split_key(struct caam_ctx *ctx, const u8 *key_in, u32 authkeylen)
+{
+ struct device *jrdev = ctx->jrdev;
+ u32 *desc;
+ struct split_key_result result;
+ dma_addr_t dma_addr_in, dma_addr_out;
+ int ret = 0;
+
+ desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
+
+ init_job_desc(desc, 0);
+
+ dma_addr_in = dma_map_single(jrdev, (void *)key_in, authkeylen,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, dma_addr_in)) {
+ dev_err(jrdev, "unable to map key input memory\n");
+ kfree(desc);
+ return -ENOMEM;
+ }
+ append_key(desc, dma_addr_in, authkeylen, CLASS_2 |
+ KEY_DEST_CLASS_REG);
+
+ /* Sets MDHA up into an HMAC-INIT */
+ append_operation(desc, ctx->alg_op | OP_ALG_DECRYPT |
+ OP_ALG_AS_INIT);
+
+ /*
+ * do a FIFO_LOAD of zero, this will trigger the internal key expansion
+ into both pads inside MDHA
+ */
+ append_fifo_load_as_imm(desc, NULL, 0, LDST_CLASS_2_CCB |
+ FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2);
+
+ /*
+ * FIFO_STORE with the explicit split-key content store
+ * (0x26 output type)
+ */
+ dma_addr_out = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(jrdev, dma_addr_out)) {
+ dev_err(jrdev, "unable to map key output memory\n");
+ kfree(desc);
+ return -ENOMEM;
+ }
+ append_fifo_store(desc, dma_addr_out, ctx->split_key_len,
+ LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, key_in, authkeylen, 1);
+ print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+
+ result.err = 0;
+ init_completion(&result.completion);
+
+ ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result);
+ if (!ret) {
+ /* in progress */
+ wait_for_completion_interruptible(&result.completion);
+ ret = result.err;
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, ctx->key,
+ ctx->split_key_pad_len, 1);
+#endif
+ }
+
+ dma_unmap_single(jrdev, dma_addr_out, ctx->split_key_pad_len,
+ DMA_FROM_DEVICE);
+ dma_unmap_single(jrdev, dma_addr_in, authkeylen, DMA_TO_DEVICE);
+
+ kfree(desc);
+
+ return ret;
+}
+
+static int build_sh_desc_ipsec(struct caam_ctx *ctx)
+{
+ struct device *jrdev = ctx->jrdev;
+ u32 *sh_desc;
+ u32 *jump_cmd;
+
+ /* build shared descriptor for this session */
+ sh_desc = kmalloc(CAAM_CMD_SZ * 4 + ctx->split_key_pad_len +
+ ctx->enckeylen, GFP_DMA | GFP_KERNEL);
+ if (!sh_desc) {
+ dev_err(jrdev, "could not allocate shared descriptor\n");
+ return -ENOMEM;
+ }
+
+ init_sh_desc(sh_desc, HDR_SAVECTX | HDR_SHARE_SERIAL);
+
+ jump_cmd = append_jump(sh_desc, CLASS_BOTH | JUMP_TEST_ALL |
+ JUMP_COND_SHRD | JUMP_COND_SELF);
+
+ /* process keys, starting with class 2/authentication */
+ append_key_as_imm(sh_desc, ctx->key, ctx->split_key_pad_len,
+ ctx->split_key_len,
+ CLASS_2 | KEY_DEST_MDHA_SPLIT | KEY_ENC);
+
+ append_key_as_imm(sh_desc, (void *)ctx->key + ctx->split_key_pad_len,
+ ctx->enckeylen, ctx->enckeylen,
+ CLASS_1 | KEY_DEST_CLASS_REG);
+
+ /* update jump cmd now that we are at the jump target */
+ set_jump_tgt_here(sh_desc, jump_cmd);
+
+ ctx->shared_desc_phys = dma_map_single(jrdev, sh_desc,
+ desc_bytes(sh_desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->shared_desc_phys)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ kfree(sh_desc);
+ return -ENOMEM;
+ }
+
+ ctx->sh_desc = sh_desc;
+
+ return 0;
+}
+
+static int aead_authenc_setkey(struct crypto_aead *aead,
+ const u8 *key, unsigned int keylen)
+{
+ /* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */
+ static const u8 mdpadlen[] = { 16, 20, 32, 32, 64, 64 };
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ struct device *jrdev = ctx->jrdev;
+ struct rtattr *rta = (void *)key;
+ struct crypto_authenc_key_param *param;
+ unsigned int authkeylen;
+ unsigned int enckeylen;
+ int ret = 0;
+
+ param = RTA_DATA(rta);
+ enckeylen = be32_to_cpu(param->enckeylen);
+
+ key += RTA_ALIGN(rta->rta_len);
+ keylen -= RTA_ALIGN(rta->rta_len);
+
+ if (keylen < enckeylen)
+ goto badkey;
+
+ authkeylen = keylen - enckeylen;
+
+ if (keylen > CAAM_MAX_KEY_SIZE)
+ goto badkey;
+
+ /* Pick class 2 key length from algorithm submask */
+ ctx->split_key_len = mdpadlen[(ctx->alg_op & OP_ALG_ALGSEL_SUBMASK) >>
+ OP_ALG_ALGSEL_SHIFT] * 2;
+ ctx->split_key_pad_len = ALIGN(ctx->split_key_len, 16);
+
+#ifdef DEBUG
+ printk(KERN_ERR "keylen %d enckeylen %d authkeylen %d\n",
+ keylen, enckeylen, authkeylen);
+ printk(KERN_ERR "split_key_len %d split_key_pad_len %d\n",
+ ctx->split_key_len, ctx->split_key_pad_len);
+ print_hex_dump(KERN_ERR, "key in @"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
+#endif
+ ctx->key = kmalloc(ctx->split_key_pad_len + enckeylen,
+ GFP_KERNEL | GFP_DMA);
+ if (!ctx->key) {
+ dev_err(jrdev, "could not allocate key output memory\n");
+ return -ENOMEM;
+ }
+
+ ret = gen_split_key(ctx, key, authkeylen);
+ if (ret) {
+ kfree(ctx->key);
+ goto badkey;
+ }
+
+ /* postpend encryption key to auth split key */
+ memcpy(ctx->key + ctx->split_key_pad_len, key + authkeylen, enckeylen);
+
+ ctx->key_phys = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len +
+ enckeylen, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->key_phys)) {
+ dev_err(jrdev, "unable to map key i/o memory\n");
+ kfree(ctx->key);
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, ctx->key,
+ ctx->split_key_pad_len + enckeylen, 1);
+#endif
+
+ ctx->keylen = keylen;
+ ctx->enckeylen = enckeylen;
+ ctx->authkeylen = authkeylen;
+
+ ret = build_sh_desc_ipsec(ctx);
+ if (ret) {