]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
crypto: cavium/nitrox - Add support for loading asymmetric crypto firmware
authorPhani Kiran Hemadri <phemadri@marvell.com>
Tue, 9 Jul 2019 15:24:24 +0000 (15:24 +0000)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 26 Jul 2019 12:08:05 +0000 (22:08 +1000)
This patch adds support to load Asymmetric crypto firmware on
AE cores of CNN55XX device. Firmware is stored on UCD block 2
and all available AE cores are tagged to group 0.

Signed-off-by: Phani Kiran Hemadri <phemadri@marvell.com>
Reviewed-by: Srikanth Jampala <jsrikanth@marvell.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/cavium/nitrox/nitrox_csr.h
drivers/crypto/cavium/nitrox/nitrox_debugfs.c
drivers/crypto/cavium/nitrox/nitrox_dev.h
drivers/crypto/cavium/nitrox/nitrox_main.c

index a2a452642b3865a93db67fe2c0f53a7985524d92..da1d7330378074dbf7c71802e9c613c68417cd57 100644 (file)
 #define EMU_FUSE_MAPX(_i)      (0x1402708 + ((_i) * 0x40000))
 
 /* UCD registers */
+#define UCD_SE_EID_UCODE_BLOCK_NUMX(_i)        (0x12C0000 + ((_i) * 0x1000))
+#define UCD_AE_EID_UCODE_BLOCK_NUMX(_i)        (0x12C0008 + ((_i) * 0x800))
 #define UCD_UCODE_LOAD_BLOCK_NUM       0x12C0010
 #define UCD_UCODE_LOAD_IDX_DATAX(_i)   (0x12C0018 + ((_i) * 0x20))
-#define UCD_SE_EID_UCODE_BLOCK_NUMX(_i)        (0x12C0000 + ((_i) * 0x1000))
+#define UCD_SE_CNTX(_i)                        (0x12C0040 + ((_i) * 0x1000))
+#define UCD_AE_CNTX(_i)                        (0x12C0048 + ((_i) * 0x800))
+
+/* AQM registers */
+#define AQM_CTL                         0x1300000
+#define AQM_INT                         0x1300008
+#define AQM_DBELL_OVF_LO                0x1300010
+#define AQM_DBELL_OVF_HI                0x1300018
+#define AQM_DBELL_OVF_LO_W1S            0x1300020
+#define AQM_DBELL_OVF_LO_ENA_W1C        0x1300028
+#define AQM_DBELL_OVF_LO_ENA_W1S        0x1300030
+#define AQM_DBELL_OVF_HI_W1S            0x1300038
+#define AQM_DBELL_OVF_HI_ENA_W1C        0x1300040
+#define AQM_DBELL_OVF_HI_ENA_W1S        0x1300048
+#define AQM_DMA_RD_ERR_LO               0x1300050
+#define AQM_DMA_RD_ERR_HI               0x1300058
+#define AQM_DMA_RD_ERR_LO_W1S           0x1300060
+#define AQM_DMA_RD_ERR_LO_ENA_W1C       0x1300068
+#define AQM_DMA_RD_ERR_LO_ENA_W1S       0x1300070
+#define AQM_DMA_RD_ERR_HI_W1S           0x1300078
+#define AQM_DMA_RD_ERR_HI_ENA_W1C       0x1300080
+#define AQM_DMA_RD_ERR_HI_ENA_W1S       0x1300088
+#define AQM_EXEC_NA_LO                  0x1300090
+#define AQM_EXEC_NA_HI                  0x1300098
+#define AQM_EXEC_NA_LO_W1S              0x13000A0
+#define AQM_EXEC_NA_LO_ENA_W1C          0x13000A8
+#define AQM_EXEC_NA_LO_ENA_W1S          0x13000B0
+#define AQM_EXEC_NA_HI_W1S              0x13000B8
+#define AQM_EXEC_NA_HI_ENA_W1C          0x13000C0
+#define AQM_EXEC_NA_HI_ENA_W1S          0x13000C8
+#define AQM_EXEC_ERR_LO                 0x13000D0
+#define AQM_EXEC_ERR_HI                 0x13000D8
+#define AQM_EXEC_ERR_LO_W1S             0x13000E0
+#define AQM_EXEC_ERR_LO_ENA_W1C         0x13000E8
+#define AQM_EXEC_ERR_LO_ENA_W1S         0x13000F0
+#define AQM_EXEC_ERR_HI_W1S             0x13000F8
+#define AQM_EXEC_ERR_HI_ENA_W1C         0x1300100
+#define AQM_EXEC_ERR_HI_ENA_W1S         0x1300108
+#define AQM_ECC_INT                     0x1300110
+#define AQM_ECC_INT_W1S                 0x1300118
+#define AQM_ECC_INT_ENA_W1C             0x1300120
+#define AQM_ECC_INT_ENA_W1S             0x1300128
+#define AQM_ECC_CTL                     0x1300130
+#define AQM_BIST_STATUS                 0x1300138
+#define AQM_CMD_INF_THRX(x)             (0x1300400 + ((x) * 0x8))
+#define AQM_CMD_INFX(x)                 (0x1300800 + ((x) * 0x8))
+#define AQM_GRP_EXECMSK_LOX(x)          (0x1300C00 + ((x) * 0x10))
+#define AQM_GRP_EXECMSK_HIX(x)          (0x1300C08 + ((x) * 0x10))
+#define AQM_ACTIVITY_STAT_LO            0x1300C80
+#define AQM_ACTIVITY_STAT_HI            0x1300C88
+#define AQM_Q_CMD_PROCX(x)              (0x1301000 + ((x) * 0x8))
+#define AQM_PERF_CTL_LO                 0x1301400
+#define AQM_PERF_CTL_HI                 0x1301408
+#define AQM_PERF_CNT                    0x1301410
+
+#define AQMQ_DRBLX(x)                   (0x20000 + ((x) * 0x40000))
+#define AQMQ_QSZX(x)                    (0x20008 + ((x) * 0x40000))
+#define AQMQ_BADRX(x)                   (0x20010 + ((x) * 0x40000))
+#define AQMQ_NXT_CMDX(x)                (0x20018 + ((x) * 0x40000))
+#define AQMQ_CMD_CNTX(x)                (0x20020 + ((x) * 0x40000))
+#define AQMQ_CMP_THRX(x)                (0x20028 + ((x) * 0x40000))
+#define AQMQ_CMP_CNTX(x)                (0x20030 + ((x) * 0x40000))
+#define AQMQ_TIM_LDX(x)                 (0x20038 + ((x) * 0x40000))
+#define AQMQ_TIMERX(x)                  (0x20040 + ((x) * 0x40000))
+#define AQMQ_ENX(x)                     (0x20048 + ((x) * 0x40000))
+#define AQMQ_ACTIVITY_STATX(x)          (0x20050 + ((x) * 0x40000))
+#define AQM_VF_CMP_STATX(x)             (0x28000 + ((x) * 0x40000))
 
 /* NPS core registers */
 #define NPS_CORE_GBL_VFCFG     0x1000000
 /* PEM registers */
 #define PEM0_INT 0x1080428
 
+/**
+ * struct ucd_core_eid_ucode_block_num - Core Eid to Ucode Blk Mapping Registers
+ * @ucode_len: Ucode length identifier 32KB or 64KB
+ * @ucode_blk: Ucode Block Number
+ */
+union ucd_core_eid_ucode_block_num {
+       u64 value;
+       struct {
+#if (defined(__BIG_ENDIAN_BITFIELD))
+               u64 raz_4_63 : 60;
+               u64 ucode_len : 1;
+               u64 ucode_blk : 3;
+#else
+               u64 ucode_blk : 3;
+               u64 ucode_len : 1;
+               u64 raz_4_63 : 60;
+#endif
+       };
+};
+
+/**
+ * struct aqm_grp_execmsk_lo - Available AE engines for the group
+ * @exec_0_to_39: AE engines 0 to 39 status
+ */
+union aqm_grp_execmsk_lo {
+       u64 value;
+       struct {
+#if (defined(__BIG_ENDIAN_BITFIELD))
+               u64 raz_40_63 : 24;
+               u64 exec_0_to_39 : 40;
+#else
+               u64 exec_0_to_39 : 40;
+               u64 raz_40_63 : 24;
+#endif
+       };
+};
+
+/**
+ * struct aqm_grp_execmsk_hi - Available AE engines for the group
+ * @exec_40_to_79: AE engines 40 to 79 status
+ */
+union aqm_grp_execmsk_hi {
+       u64 value;
+       struct {
+#if (defined(__BIG_ENDIAN_BITFIELD))
+               u64 raz_40_63 : 24;
+               u64 exec_40_to_79 : 40;
+#else
+               u64 exec_40_to_79 : 40;
+               u64 raz_40_63 : 24;
+#endif
+       };
+};
+
 /**
  * struct emu_fuse_map - EMU Fuse Map Registers
  * @ae_fuse: Fuse settings for AE 19..0
index 848ec93d4333d0bb04bd89c78f1616a27d4407c0..16f7d0bd1303203c2d273737b7254d047b12ef7a 100644 (file)
@@ -9,7 +9,8 @@ static int firmware_show(struct seq_file *s, void *v)
 {
        struct nitrox_device *ndev = s->private;
 
-       seq_printf(s, "Version: %s\n", ndev->hw.fw_name);
+       seq_printf(s, "Version: %s\n", ndev->hw.fw_name[0]);
+       seq_printf(s, "Version: %s\n", ndev->hw.fw_name[1]);
        return 0;
 }
 
index 0338877b828f9844336fd0ee260390787291b315..5ee98eca728c0ce5a72ff89b25620cee2561cf60 100644 (file)
@@ -10,6 +10,8 @@
 #define VERSION_LEN 32
 /* Maximum queues in PF mode */
 #define MAX_PF_QUEUES  64
+/* Maximum UCD Blocks */
+#define CNN55XX_MAX_UCD_BLOCKS 8
 
 /**
  * struct nitrox_cmdq - NITROX command queue
@@ -74,7 +76,7 @@ struct nitrox_cmdq {
  */
 struct nitrox_hw {
        char partname[IFNAMSIZ * 2];
-       char fw_name[VERSION_LEN];
+       char fw_name[CNN55XX_MAX_UCD_BLOCKS][VERSION_LEN];
 
        int freq;
        u16 vendor_id;
index fe825d0ef9cafe41ea7bb2fa6c8d67246da255cb..345d3ea10b1f388955e60cddb7703887981837b8 100644 (file)
 
 #define CNN55XX_DEV_ID 0x12
 #define UCODE_HLEN 48
-#define SE_GROUP 0
+#define DEFAULT_SE_GROUP 0
+#define DEFAULT_AE_GROUP 0
 
-#define DRIVER_VERSION "1.1"
+#define DRIVER_VERSION "1.2"
+#define CNN55XX_UCD_BLOCK_SIZE 32768
+#define CNN55XX_MAX_UCODE_SIZE (CNN55XX_UCD_BLOCK_SIZE * 2)
 #define FW_DIR "cavium/"
 /* SE microcode */
 #define SE_FW  FW_DIR "cnn55xx_se.fw"
+/* AE microcode */
+#define AE_FW  FW_DIR "cnn55xx_ae.fw"
 
 static const char nitrox_driver_name[] = "CNN55XX";
 
@@ -72,10 +77,10 @@ struct ucode {
 /**
  * write_to_ucd_unit - Write Firmware to NITROX UCD unit
  */
-static void write_to_ucd_unit(struct nitrox_device *ndev,
-                             struct ucode *ucode)
+static void write_to_ucd_unit(struct nitrox_device *ndev, u32 ucode_size,
+                             u64 *ucode_data, int block_num)
 {
-       u32 code_size = be32_to_cpu(ucode->code_size) * 2;
+       u32 code_size;
        u64 offset, data;
        int i = 0;
 
@@ -96,11 +101,12 @@ static void write_to_ucd_unit(struct nitrox_device *ndev,
 
        /* set the block number */
        offset = UCD_UCODE_LOAD_BLOCK_NUM;
-       nitrox_write_csr(ndev, offset, 0);
+       nitrox_write_csr(ndev, offset, block_num);
 
+       code_size = ucode_size;
        code_size = roundup(code_size, 8);
        while (code_size) {
-               data = ucode->code[i];
+               data = ucode_data[i];
                /* write 8 bytes at a time */
                offset = UCD_UCODE_LOAD_IDX_DATAX(i);
                nitrox_write_csr(ndev, offset, data);
@@ -108,29 +114,74 @@ static void write_to_ucd_unit(struct nitrox_device *ndev,
                i++;
        }
 
-       /* put all SE cores in group 0 */
-       offset = POM_GRP_EXECMASKX(SE_GROUP);
-       nitrox_write_csr(ndev, offset, (~0ULL));
-
-       for (i = 0; i < ndev->hw.se_cores; i++) {
-               /*
-                * write block number and firware length
-                * bit:<2:0> block number
-                * bit:3 is set SE uses 32KB microcode
-                * bit:3 is clear SE uses 64KB microcode
-                */
-               offset = UCD_SE_EID_UCODE_BLOCK_NUMX(i);
-               nitrox_write_csr(ndev, offset, 0x8);
-       }
        usleep_range(300, 400);
 }
 
-static int nitrox_load_fw(struct nitrox_device *ndev, const char *fw_name)
+static int nitrox_load_fw(struct nitrox_device *ndev)
 {
        const struct firmware *fw;
+       const char *fw_name;
        struct ucode *ucode;
-       int ret;
+       u64 *ucode_data;
+       u64 offset;
+       union ucd_core_eid_ucode_block_num core_2_eid_val;
+       union aqm_grp_execmsk_lo aqm_grp_execmask_lo;
+       union aqm_grp_execmsk_hi aqm_grp_execmask_hi;
+       u32 ucode_size;
+       int ret, i = 0;
+
+       fw_name = SE_FW;
+       dev_info(DEV(ndev), "Loading firmware \"%s\"\n", fw_name);
+
+       ret = request_firmware(&fw, fw_name, DEV(ndev));
+       if (ret < 0) {
+               dev_err(DEV(ndev), "failed to get firmware %s\n", fw_name);
+               return ret;
+       }
+
+       ucode = (struct ucode *)fw->data;
+
+       ucode_size = be32_to_cpu(ucode->code_size) * 2;
+       if (!ucode_size || ucode_size > CNN55XX_MAX_UCODE_SIZE) {
+               dev_err(DEV(ndev), "Invalid ucode size: %u for firmware %s\n",
+                       ucode_size, fw_name);
+               release_firmware(fw);
+               return -EINVAL;
+       }
+       ucode_data = ucode->code;
+
+       /* copy the firmware version */
+       memcpy(&ndev->hw.fw_name[0][0], ucode->version, (VERSION_LEN - 2));
+       ndev->hw.fw_name[0][VERSION_LEN - 1] = '\0';
+
+       /* Load SE Firmware on UCD Block 0 */
+       write_to_ucd_unit(ndev, ucode_size, ucode_data, 0);
 
+       release_firmware(fw);
+
+       /* put all SE cores in DEFAULT_SE_GROUP */
+       offset = POM_GRP_EXECMASKX(DEFAULT_SE_GROUP);
+       nitrox_write_csr(ndev, offset, (~0ULL));
+
+       /* write block number and firmware length
+        * bit:<2:0> block number
+        * bit:3 is set SE uses 32KB microcode
+        * bit:3 is clear SE uses 64KB microcode
+        */
+       core_2_eid_val.value = 0ULL;
+       core_2_eid_val.ucode_blk = 0;
+       if (ucode_size <= CNN55XX_UCD_BLOCK_SIZE)
+               core_2_eid_val.ucode_len = 1;
+       else
+               core_2_eid_val.ucode_len = 0;
+
+       for (i = 0; i < ndev->hw.se_cores; i++) {
+               offset = UCD_SE_EID_UCODE_BLOCK_NUMX(i);
+               nitrox_write_csr(ndev, offset, core_2_eid_val.value);
+       }
+
+
+       fw_name = AE_FW;
        dev_info(DEV(ndev), "Loading firmware \"%s\"\n", fw_name);
 
        ret = request_firmware(&fw, fw_name, DEV(ndev));
@@ -140,13 +191,50 @@ static int nitrox_load_fw(struct nitrox_device *ndev, const char *fw_name)
        }
 
        ucode = (struct ucode *)fw->data;
+
+       ucode_size = be32_to_cpu(ucode->code_size) * 2;
+       if (!ucode_size || ucode_size > CNN55XX_MAX_UCODE_SIZE) {
+               dev_err(DEV(ndev), "Invalid ucode size: %u for firmware %s\n",
+                       ucode_size, fw_name);
+               release_firmware(fw);
+               return -EINVAL;
+       }
+       ucode_data = ucode->code;
+
        /* copy the firmware version */
-       memcpy(ndev->hw.fw_name, ucode->version, (VERSION_LEN - 2));
-       ndev->hw.fw_name[VERSION_LEN - 1] = '\0';
+       memcpy(&ndev->hw.fw_name[1][0], ucode->version, (VERSION_LEN - 2));
+       ndev->hw.fw_name[1][VERSION_LEN - 1] = '\0';
+
+       /* Load AE Firmware on UCD Block 2 */
+       write_to_ucd_unit(ndev, ucode_size, ucode_data, 2);
 
-       write_to_ucd_unit(ndev, ucode);
        release_firmware(fw);
 
+       /* put all AE cores in DEFAULT_AE_GROUP */
+       offset = AQM_GRP_EXECMSK_LOX(DEFAULT_AE_GROUP);
+       aqm_grp_execmask_lo.exec_0_to_39 = 0xFFFFFFFFFFULL;
+       nitrox_write_csr(ndev, offset, aqm_grp_execmask_lo.value);
+       offset = AQM_GRP_EXECMSK_HIX(DEFAULT_AE_GROUP);
+       aqm_grp_execmask_hi.exec_40_to_79 = 0xFFFFFFFFFFULL;
+       nitrox_write_csr(ndev, offset, aqm_grp_execmask_hi.value);
+
+       /* write block number and firmware length
+        * bit:<2:0> block number
+        * bit:3 is set SE uses 32KB microcode
+        * bit:3 is clear SE uses 64KB microcode
+        */
+       core_2_eid_val.value = 0ULL;
+       core_2_eid_val.ucode_blk = 0;
+       if (ucode_size <= CNN55XX_UCD_BLOCK_SIZE)
+               core_2_eid_val.ucode_len = 1;
+       else
+               core_2_eid_val.ucode_len = 0;
+
+       for (i = 0; i < ndev->hw.ae_cores; i++) {
+               offset = UCD_AE_EID_UCODE_BLOCK_NUMX(i);
+               nitrox_write_csr(ndev, offset, core_2_eid_val.value);
+       }
+
        return 0;
 }
 
@@ -309,8 +397,8 @@ static int nitrox_pf_hw_init(struct nitrox_device *ndev)
        nitrox_config_lbc_unit(ndev);
        nitrox_config_rand_unit(ndev);
 
-       /* load firmware on SE cores */
-       err = nitrox_load_fw(ndev, SE_FW);
+       /* load firmware on cores */
+       err = nitrox_load_fw(ndev);
        if (err)
                return err;