[PATCH v3 13/17] crypto: talitos - adapt interrupts and reset functions to SEC1

2015-04-17 Thread Christophe Leroy
This patch adapts the interrupts handling and reset function for
SEC1. On SEC1, registers are almost similar to SEC2+, but bits
are sometimes located at different places. So we need to define
TALITOS1 and TALITOS2 versions of some fields, and manage according
to whether it is SEC1 or SEC2.

On SEC1, only one interrupt vector is dedicated to the SEC, so only
interrupt_4ch is needed.

On SEC1, interrupts are enabled by clearing related bits in IMR,
while on SEC2, interrupts are enabled by seting the bits in IMR.

SEC1 also performs parity verification in the DES Unit. We have
to disable this feature because the test vectors provided in
the kernel have parity errors.

In reset functions, only SEC2 supports continuation after error.
For SEC1, we have to reset in all cases.

For errors handling, SEC2+ names have been kept, but displayed
text have been amended to reflect exact meaning on SEC1.

Signed-off-by: Christophe Leroy 
---
 drivers/crypto/talitos.c | 227 +++
 drivers/crypto/talitos.h |  39 +---
 2 files changed, 199 insertions(+), 67 deletions(-)

diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 6d77699..1265405 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -124,12 +124,23 @@ static int reset_channel(struct device *dev, int ch)
 {
struct talitos_private *priv = dev_get_drvdata(dev);
unsigned int timeout = TALITOS_TIMEOUT;
+   bool is_sec1 = has_ftr_sec1(priv);
 
-   setbits32(priv->chan[ch].reg + TALITOS_CCCR, TALITOS_CCCR_RESET);
+   if (is_sec1) {
+   setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
+ TALITOS1_CCCR_LO_RESET);
 
-   while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) & TALITOS_CCCR_RESET)
-  && --timeout)
-   cpu_relax();
+   while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
+   TALITOS1_CCCR_LO_RESET) && --timeout)
+   cpu_relax();
+   } else {
+   setbits32(priv->chan[ch].reg + TALITOS_CCCR,
+ TALITOS2_CCCR_RESET);
+
+   while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
+   TALITOS2_CCCR_RESET) && --timeout)
+   cpu_relax();
+   }
 
if (timeout == 0) {
dev_err(dev, "failed to reset channel %d\n", ch);
@@ -152,11 +163,12 @@ static int reset_device(struct device *dev)
 {
struct talitos_private *priv = dev_get_drvdata(dev);
unsigned int timeout = TALITOS_TIMEOUT;
-   u32 mcr = TALITOS_MCR_SWR;
+   bool is_sec1 = has_ftr_sec1(priv);
+   u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
 
setbits32(priv->reg + TALITOS_MCR, mcr);
 
-   while ((in_be32(priv->reg + TALITOS_MCR) & TALITOS_MCR_SWR)
+   while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
   && --timeout)
cpu_relax();
 
@@ -180,6 +192,7 @@ static int init_device(struct device *dev)
 {
struct talitos_private *priv = dev_get_drvdata(dev);
int ch, err;
+   bool is_sec1 = has_ftr_sec1(priv);
 
/*
 * Master reset
@@ -203,8 +216,15 @@ static int init_device(struct device *dev)
}
 
/* enable channel done and error interrupts */
-   setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_INIT);
-   setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT);
+   if (is_sec1) {
+   clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
+   clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
+   /* disable parity error check in DEU (erroneous? test vect.) */
+   setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
+   } else {
+   setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
+   setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
+   }
 
/* disable integrity check error interrupts (use writeback instead) */
if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
@@ -349,8 +369,37 @@ static void flush_channel(struct device *dev, int ch, int 
error, int reset_ch)
 /*
  * process completed requests for channels that have done status
  */
-#define DEF_TALITOS_DONE(name, ch_done_mask)   \
-static void talitos_done_##name(unsigned long data)\
+#define DEF_TALITOS1_DONE(name, ch_done_mask)  \
+static void talitos1_done_##name(unsigned long data)   \
+{  \
+   struct device *dev = (struct device *)data; \
+   struct talitos_private *priv = dev_get_drvdata(dev);\
+   unsigned long flags;\
+   \
+   if (ch_done_mask & 0x1000)

[PATCH v3 13/17] crypto: talitos - adapt interrupts and reset functions to SEC1

2015-04-17 Thread Christophe Leroy
This patch adapts the interrupts handling and reset function for
SEC1. On SEC1, registers are almost similar to SEC2+, but bits
are sometimes located at different places. So we need to define
TALITOS1 and TALITOS2 versions of some fields, and manage according
to whether it is SEC1 or SEC2.

On SEC1, only one interrupt vector is dedicated to the SEC, so only
interrupt_4ch is needed.

On SEC1, interrupts are enabled by clearing related bits in IMR,
while on SEC2, interrupts are enabled by seting the bits in IMR.

SEC1 also performs parity verification in the DES Unit. We have
to disable this feature because the test vectors provided in
the kernel have parity errors.

In reset functions, only SEC2 supports continuation after error.
For SEC1, we have to reset in all cases.

For errors handling, SEC2+ names have been kept, but displayed
text have been amended to reflect exact meaning on SEC1.

Signed-off-by: Christophe Leroy 
---
 drivers/crypto/talitos.c | 227 +++
 drivers/crypto/talitos.h |  39 +---
 2 files changed, 199 insertions(+), 67 deletions(-)

diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 6d77699..1265405 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -124,12 +124,23 @@ static int reset_channel(struct device *dev, int ch)
 {
struct talitos_private *priv = dev_get_drvdata(dev);
unsigned int timeout = TALITOS_TIMEOUT;
+   bool is_sec1 = has_ftr_sec1(priv);
 
-   setbits32(priv->chan[ch].reg + TALITOS_CCCR, TALITOS_CCCR_RESET);
+   if (is_sec1) {
+   setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
+ TALITOS1_CCCR_LO_RESET);
 
-   while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) & TALITOS_CCCR_RESET)
-  && --timeout)
-   cpu_relax();
+   while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
+   TALITOS1_CCCR_LO_RESET) && --timeout)
+   cpu_relax();
+   } else {
+   setbits32(priv->chan[ch].reg + TALITOS_CCCR,
+ TALITOS2_CCCR_RESET);
+
+   while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
+   TALITOS2_CCCR_RESET) && --timeout)
+   cpu_relax();
+   }
 
if (timeout == 0) {
dev_err(dev, "failed to reset channel %d\n", ch);
@@ -152,11 +163,12 @@ static int reset_device(struct device *dev)
 {
struct talitos_private *priv = dev_get_drvdata(dev);
unsigned int timeout = TALITOS_TIMEOUT;
-   u32 mcr = TALITOS_MCR_SWR;
+   bool is_sec1 = has_ftr_sec1(priv);
+   u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
 
setbits32(priv->reg + TALITOS_MCR, mcr);
 
-   while ((in_be32(priv->reg + TALITOS_MCR) & TALITOS_MCR_SWR)
+   while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
   && --timeout)
cpu_relax();
 
@@ -180,6 +192,7 @@ static int init_device(struct device *dev)
 {
struct talitos_private *priv = dev_get_drvdata(dev);
int ch, err;
+   bool is_sec1 = has_ftr_sec1(priv);
 
/*
 * Master reset
@@ -203,8 +216,15 @@ static int init_device(struct device *dev)
}
 
/* enable channel done and error interrupts */
-   setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_INIT);
-   setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT);
+   if (is_sec1) {
+   clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
+   clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
+   /* disable parity error check in DEU (erroneous? test vect.) */
+   setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
+   } else {
+   setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
+   setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
+   }
 
/* disable integrity check error interrupts (use writeback instead) */
if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
@@ -349,8 +369,37 @@ static void flush_channel(struct device *dev, int ch, int 
error, int reset_ch)
 /*
  * process completed requests for channels that have done status
  */
-#define DEF_TALITOS_DONE(name, ch_done_mask)   \
-static void talitos_done_##name(unsigned long data)\
+#define DEF_TALITOS1_DONE(name, ch_done_mask)  \
+static void talitos1_done_##name(unsigned long data)   \
+{  \
+   struct device *dev = (struct device *)data; \
+   struct talitos_private *priv = dev_get_drvdata(dev);\
+   unsigned long flags;\
+   \
+   if (ch_done_mask & 0x1000)