Path: blob/master/drivers/crypto/inside-secure/safexcel.c
26285 views
// SPDX-License-Identifier: GPL-2.01/*2* Copyright (C) 2017 Marvell3*4* Antoine Tenart <[email protected]>5*/67#include <linux/clk.h>8#include <linux/device.h>9#include <linux/dma-mapping.h>10#include <linux/dmapool.h>11#include <linux/firmware.h>12#include <linux/interrupt.h>13#include <linux/module.h>14#include <linux/of_platform.h>15#include <linux/of_irq.h>16#include <linux/pci.h>17#include <linux/platform_device.h>18#include <linux/workqueue.h>1920#include <crypto/internal/aead.h>21#include <crypto/internal/hash.h>22#include <crypto/internal/skcipher.h>2324#include "safexcel.h"2526static u32 max_rings = EIP197_MAX_RINGS;27module_param(max_rings, uint, 0644);28MODULE_PARM_DESC(max_rings, "Maximum number of rings to use.");2930static void eip197_trc_cache_setupvirt(struct safexcel_crypto_priv *priv)31{32int i;3334/*35* Map all interfaces/rings to register index 036* so they can share contexts. Without this, the EIP197 will37* assume each interface/ring to be in its own memory domain38* i.e. have its own subset of UNIQUE memory addresses.39* Which would cause records with the SAME memory address to40* use DIFFERENT cache buffers, causing both poor cache utilization41* AND serious coherence/invalidation issues.42*/43for (i = 0; i < 4; i++)44writel(0, priv->base + EIP197_FLUE_IFC_LUT(i));4546/*47* Initialize other virtualization regs for cache48* These may not be in their reset state ...49*/50for (i = 0; i < priv->config.rings; i++) {51writel(0, priv->base + EIP197_FLUE_CACHEBASE_LO(i));52writel(0, priv->base + EIP197_FLUE_CACHEBASE_HI(i));53writel(EIP197_FLUE_CONFIG_MAGIC,54priv->base + EIP197_FLUE_CONFIG(i));55}56writel(0, priv->base + EIP197_FLUE_OFFSETS);57writel(0, priv->base + EIP197_FLUE_ARC4_OFFSET);58}5960static void eip197_trc_cache_banksel(struct safexcel_crypto_priv *priv,61u32 addrmid, int *actbank)62{63u32 val;64int curbank;6566curbank = addrmid >> 16;67if (curbank != *actbank) {68val = readl(priv->base + EIP197_CS_RAM_CTRL);69val = (val & ~EIP197_CS_BANKSEL_MASK) |70(curbank << EIP197_CS_BANKSEL_OFS);71writel(val, priv->base + EIP197_CS_RAM_CTRL);72*actbank = curbank;73}74}7576static u32 eip197_trc_cache_probe(struct safexcel_crypto_priv *priv,77int maxbanks, u32 probemask, u32 stride)78{79u32 val, addrhi, addrlo, addrmid, addralias, delta, marker;80int actbank;8182/*83* And probe the actual size of the physically attached cache data RAM84* Using a binary subdivision algorithm downto 32 byte cache lines.85*/86addrhi = 1 << (16 + maxbanks);87addrlo = 0;88actbank = min(maxbanks - 1, 0);89while ((addrhi - addrlo) > stride) {90/* write marker to lowest address in top half */91addrmid = (addrhi + addrlo) >> 1;92marker = (addrmid ^ 0xabadbabe) & probemask; /* Unique */93eip197_trc_cache_banksel(priv, addrmid, &actbank);94writel(marker,95priv->base + EIP197_CLASSIFICATION_RAMS +96(addrmid & 0xffff));9798/* write invalid markers to possible aliases */99delta = 1 << __fls(addrmid);100while (delta >= stride) {101addralias = addrmid - delta;102eip197_trc_cache_banksel(priv, addralias, &actbank);103writel(~marker,104priv->base + EIP197_CLASSIFICATION_RAMS +105(addralias & 0xffff));106delta >>= 1;107}108109/* read back marker from top half */110eip197_trc_cache_banksel(priv, addrmid, &actbank);111val = readl(priv->base + EIP197_CLASSIFICATION_RAMS +112(addrmid & 0xffff));113114if ((val & probemask) == marker)115/* read back correct, continue with top half */116addrlo = addrmid;117else118/* not read back correct, continue with bottom half */119addrhi = addrmid;120}121return addrhi;122}123124static void eip197_trc_cache_clear(struct safexcel_crypto_priv *priv,125int cs_rc_max, int cs_ht_wc)126{127int i;128u32 htable_offset, val, offset;129130/* Clear all records in administration RAM */131for (i = 0; i < cs_rc_max; i++) {132offset = EIP197_CLASSIFICATION_RAMS + i * EIP197_CS_RC_SIZE;133134writel(EIP197_CS_RC_NEXT(EIP197_RC_NULL) |135EIP197_CS_RC_PREV(EIP197_RC_NULL),136priv->base + offset);137138val = EIP197_CS_RC_NEXT(i + 1) | EIP197_CS_RC_PREV(i - 1);139if (i == 0)140val |= EIP197_CS_RC_PREV(EIP197_RC_NULL);141else if (i == cs_rc_max - 1)142val |= EIP197_CS_RC_NEXT(EIP197_RC_NULL);143writel(val, priv->base + offset + 4);144/* must also initialize the address key due to ECC! */145writel(0, priv->base + offset + 8);146writel(0, priv->base + offset + 12);147}148149/* Clear the hash table entries */150htable_offset = cs_rc_max * EIP197_CS_RC_SIZE;151for (i = 0; i < cs_ht_wc; i++)152writel(GENMASK(29, 0),153priv->base + EIP197_CLASSIFICATION_RAMS +154htable_offset + i * sizeof(u32));155}156157static int eip197_trc_cache_init(struct safexcel_crypto_priv *priv)158{159u32 val, dsize, asize;160int cs_rc_max, cs_ht_wc, cs_trc_rec_wc, cs_trc_lg_rec_wc;161int cs_rc_abs_max, cs_ht_sz;162int maxbanks;163164/* Setup (dummy) virtualization for cache */165eip197_trc_cache_setupvirt(priv);166167/*168* Enable the record cache memory access and169* probe the bank select width170*/171val = readl(priv->base + EIP197_CS_RAM_CTRL);172val &= ~EIP197_TRC_ENABLE_MASK;173val |= EIP197_TRC_ENABLE_0 | EIP197_CS_BANKSEL_MASK;174writel(val, priv->base + EIP197_CS_RAM_CTRL);175val = readl(priv->base + EIP197_CS_RAM_CTRL);176maxbanks = ((val&EIP197_CS_BANKSEL_MASK)>>EIP197_CS_BANKSEL_OFS) + 1;177178/* Clear all ECC errors */179writel(0, priv->base + EIP197_TRC_ECCCTRL);180181/*182* Make sure the cache memory is accessible by taking record cache into183* reset. Need data memory access here, not admin access.184*/185val = readl(priv->base + EIP197_TRC_PARAMS);186val |= EIP197_TRC_PARAMS_SW_RESET | EIP197_TRC_PARAMS_DATA_ACCESS;187writel(val, priv->base + EIP197_TRC_PARAMS);188189/* Probed data RAM size in bytes */190dsize = eip197_trc_cache_probe(priv, maxbanks, 0xffffffff, 32);191192/*193* Now probe the administration RAM size pretty much the same way194* Except that only the lower 30 bits are writable and we don't need195* bank selects196*/197val = readl(priv->base + EIP197_TRC_PARAMS);198/* admin access now */199val &= ~(EIP197_TRC_PARAMS_DATA_ACCESS | EIP197_CS_BANKSEL_MASK);200writel(val, priv->base + EIP197_TRC_PARAMS);201202/* Probed admin RAM size in admin words */203asize = eip197_trc_cache_probe(priv, 0, 0x3fffffff, 16) >> 4;204205/* Clear any ECC errors detected while probing! */206writel(0, priv->base + EIP197_TRC_ECCCTRL);207208/* Sanity check probing results */209if (dsize < EIP197_MIN_DSIZE || asize < EIP197_MIN_ASIZE) {210dev_err(priv->dev, "Record cache probing failed (%d,%d).",211dsize, asize);212return -ENODEV;213}214215/*216* Determine optimal configuration from RAM sizes217* Note that we assume that the physical RAM configuration is sane218* Therefore, we don't do any parameter error checking here ...219*/220221/* For now, just use a single record format covering everything */222cs_trc_rec_wc = EIP197_CS_TRC_REC_WC;223cs_trc_lg_rec_wc = EIP197_CS_TRC_REC_WC;224225/*226* Step #1: How many records will physically fit?227* Hard upper limit is 1023!228*/229cs_rc_abs_max = min_t(uint, ((dsize >> 2) / cs_trc_lg_rec_wc), 1023);230/* Step #2: Need at least 2 words in the admin RAM per record */231cs_rc_max = min_t(uint, cs_rc_abs_max, (asize >> 1));232/* Step #3: Determine log2 of hash table size */233cs_ht_sz = __fls(asize - cs_rc_max) - 2;234/* Step #4: determine current size of hash table in dwords */235cs_ht_wc = 16 << cs_ht_sz; /* dwords, not admin words */236/* Step #5: add back excess words and see if we can fit more records */237cs_rc_max = min_t(uint, cs_rc_abs_max, asize - (cs_ht_wc >> 2));238239/* Clear the cache RAMs */240eip197_trc_cache_clear(priv, cs_rc_max, cs_ht_wc);241242/* Disable the record cache memory access */243val = readl(priv->base + EIP197_CS_RAM_CTRL);244val &= ~EIP197_TRC_ENABLE_MASK;245writel(val, priv->base + EIP197_CS_RAM_CTRL);246247/* Write head and tail pointers of the record free chain */248val = EIP197_TRC_FREECHAIN_HEAD_PTR(0) |249EIP197_TRC_FREECHAIN_TAIL_PTR(cs_rc_max - 1);250writel(val, priv->base + EIP197_TRC_FREECHAIN);251252/* Configure the record cache #1 */253val = EIP197_TRC_PARAMS2_RC_SZ_SMALL(cs_trc_rec_wc) |254EIP197_TRC_PARAMS2_HTABLE_PTR(cs_rc_max);255writel(val, priv->base + EIP197_TRC_PARAMS2);256257/* Configure the record cache #2 */258val = EIP197_TRC_PARAMS_RC_SZ_LARGE(cs_trc_lg_rec_wc) |259EIP197_TRC_PARAMS_BLK_TIMER_SPEED(1) |260EIP197_TRC_PARAMS_HTABLE_SZ(cs_ht_sz);261writel(val, priv->base + EIP197_TRC_PARAMS);262263dev_info(priv->dev, "TRC init: %dd,%da (%dr,%dh)\n",264dsize, asize, cs_rc_max, cs_ht_wc + cs_ht_wc);265return 0;266}267268static void eip197_init_firmware(struct safexcel_crypto_priv *priv)269{270int pe, i;271u32 val;272273for (pe = 0; pe < priv->config.pes; pe++) {274/* Configure the token FIFO's */275writel(3, EIP197_PE(priv) + EIP197_PE_ICE_PUTF_CTRL(pe));276writel(0, EIP197_PE(priv) + EIP197_PE_ICE_PPTF_CTRL(pe));277278/* Clear the ICE scratchpad memory */279val = readl(EIP197_PE(priv) + EIP197_PE_ICE_SCRATCH_CTRL(pe));280val |= EIP197_PE_ICE_SCRATCH_CTRL_CHANGE_TIMER |281EIP197_PE_ICE_SCRATCH_CTRL_TIMER_EN |282EIP197_PE_ICE_SCRATCH_CTRL_SCRATCH_ACCESS |283EIP197_PE_ICE_SCRATCH_CTRL_CHANGE_ACCESS;284writel(val, EIP197_PE(priv) + EIP197_PE_ICE_SCRATCH_CTRL(pe));285286/* clear the scratchpad RAM using 32 bit writes only */287for (i = 0; i < EIP197_NUM_OF_SCRATCH_BLOCKS; i++)288writel(0, EIP197_PE(priv) +289EIP197_PE_ICE_SCRATCH_RAM(pe) + (i << 2));290291/* Reset the IFPP engine to make its program mem accessible */292writel(EIP197_PE_ICE_x_CTRL_SW_RESET |293EIP197_PE_ICE_x_CTRL_CLR_ECC_CORR |294EIP197_PE_ICE_x_CTRL_CLR_ECC_NON_CORR,295EIP197_PE(priv) + EIP197_PE_ICE_FPP_CTRL(pe));296297/* Reset the IPUE engine to make its program mem accessible */298writel(EIP197_PE_ICE_x_CTRL_SW_RESET |299EIP197_PE_ICE_x_CTRL_CLR_ECC_CORR |300EIP197_PE_ICE_x_CTRL_CLR_ECC_NON_CORR,301EIP197_PE(priv) + EIP197_PE_ICE_PUE_CTRL(pe));302303/* Enable access to all IFPP program memories */304writel(EIP197_PE_ICE_RAM_CTRL_FPP_PROG_EN,305EIP197_PE(priv) + EIP197_PE_ICE_RAM_CTRL(pe));306307/* bypass the OCE, if present */308if (priv->flags & EIP197_OCE)309writel(EIP197_DEBUG_OCE_BYPASS, EIP197_PE(priv) +310EIP197_PE_DEBUG(pe));311}312313}314315static int eip197_write_firmware(struct safexcel_crypto_priv *priv,316const struct firmware *fw)317{318u32 val;319int i;320321/* Write the firmware */322for (i = 0; i < fw->size / sizeof(u32); i++) {323if (priv->data->fw_little_endian)324val = le32_to_cpu(((const __le32 *)fw->data)[i]);325else326val = be32_to_cpu(((const __be32 *)fw->data)[i]);327328writel(val,329priv->base + EIP197_CLASSIFICATION_RAMS +330i * sizeof(val));331}332333/* Exclude final 2 NOPs from size */334return i - EIP197_FW_TERMINAL_NOPS;335}336337/*338* If FW is actual production firmware, then poll for its initialization339* to complete and check if it is good for the HW, otherwise just return OK.340*/341static bool poll_fw_ready(struct safexcel_crypto_priv *priv, int fpp)342{343int pe, pollcnt;344u32 base, pollofs;345346if (fpp)347pollofs = EIP197_FW_FPP_READY;348else349pollofs = EIP197_FW_PUE_READY;350351for (pe = 0; pe < priv->config.pes; pe++) {352base = EIP197_PE_ICE_SCRATCH_RAM(pe);353pollcnt = EIP197_FW_START_POLLCNT;354while (pollcnt &&355(readl_relaxed(EIP197_PE(priv) + base +356pollofs) != 1)) {357pollcnt--;358}359if (!pollcnt) {360dev_err(priv->dev, "FW(%d) for PE %d failed to start\n",361fpp, pe);362return false;363}364}365return true;366}367368static bool eip197_start_firmware(struct safexcel_crypto_priv *priv,369int ipuesz, int ifppsz, int minifw)370{371int pe;372u32 val;373374for (pe = 0; pe < priv->config.pes; pe++) {375/* Disable access to all program memory */376writel(0, EIP197_PE(priv) + EIP197_PE_ICE_RAM_CTRL(pe));377378/* Start IFPP microengines */379if (minifw)380val = 0;381else382val = EIP197_PE_ICE_UENG_START_OFFSET((ifppsz - 1) &383EIP197_PE_ICE_UENG_INIT_ALIGN_MASK) |384EIP197_PE_ICE_UENG_DEBUG_RESET;385writel(val, EIP197_PE(priv) + EIP197_PE_ICE_FPP_CTRL(pe));386387/* Start IPUE microengines */388if (minifw)389val = 0;390else391val = EIP197_PE_ICE_UENG_START_OFFSET((ipuesz - 1) &392EIP197_PE_ICE_UENG_INIT_ALIGN_MASK) |393EIP197_PE_ICE_UENG_DEBUG_RESET;394writel(val, EIP197_PE(priv) + EIP197_PE_ICE_PUE_CTRL(pe));395}396397/* For miniFW startup, there is no initialization, so always succeed */398if (minifw)399return true;400401/* Wait until all the firmwares have properly started up */402if (!poll_fw_ready(priv, 1))403return false;404if (!poll_fw_ready(priv, 0))405return false;406407return true;408}409410static int eip197_load_firmwares(struct safexcel_crypto_priv *priv)411{412const char *fw_name[] = {"ifpp.bin", "ipue.bin"};413const struct firmware *fw[FW_NB];414char fw_path[37], *dir = NULL;415int i, j, ret = 0, pe;416int ipuesz, ifppsz, minifw = 0;417418if (priv->data->version == EIP197D_MRVL)419dir = "eip197d";420else if (priv->data->version == EIP197B_MRVL ||421priv->data->version == EIP197_DEVBRD)422dir = "eip197b";423else if (priv->data->version == EIP197C_MXL)424dir = "eip197c";425else426return -ENODEV;427428retry_fw:429for (i = 0; i < FW_NB; i++) {430snprintf(fw_path, 37, "inside-secure/%s/%s", dir, fw_name[i]);431ret = firmware_request_nowarn(&fw[i], fw_path, priv->dev);432if (ret) {433if (minifw || priv->data->version != EIP197B_MRVL)434goto release_fw;435436/* Fallback to the old firmware location for the437* EIP197b.438*/439ret = firmware_request_nowarn(&fw[i], fw_name[i],440priv->dev);441if (ret)442goto release_fw;443}444}445446eip197_init_firmware(priv);447448ifppsz = eip197_write_firmware(priv, fw[FW_IFPP]);449450/* Enable access to IPUE program memories */451for (pe = 0; pe < priv->config.pes; pe++)452writel(EIP197_PE_ICE_RAM_CTRL_PUE_PROG_EN,453EIP197_PE(priv) + EIP197_PE_ICE_RAM_CTRL(pe));454455ipuesz = eip197_write_firmware(priv, fw[FW_IPUE]);456457if (eip197_start_firmware(priv, ipuesz, ifppsz, minifw)) {458dev_dbg(priv->dev, "Firmware loaded successfully\n");459return 0;460}461462ret = -ENODEV;463464release_fw:465for (j = 0; j < i; j++)466release_firmware(fw[j]);467468if (!minifw) {469/* Retry with minifw path */470dev_dbg(priv->dev, "Firmware set not (fully) present or init failed, falling back to BCLA mode\n");471dir = "eip197_minifw";472minifw = 1;473goto retry_fw;474}475476dev_err(priv->dev, "Firmware load failed.\n");477478return ret;479}480481static int safexcel_hw_setup_cdesc_rings(struct safexcel_crypto_priv *priv)482{483u32 cd_size_rnd, val;484int i, cd_fetch_cnt;485486cd_size_rnd = (priv->config.cd_size +487(BIT(priv->hwconfig.hwdataw) - 1)) >>488priv->hwconfig.hwdataw;489/* determine number of CD's we can fetch into the CD FIFO as 1 block */490if (priv->flags & SAFEXCEL_HW_EIP197) {491/* EIP197: try to fetch enough in 1 go to keep all pipes busy */492cd_fetch_cnt = (1 << priv->hwconfig.hwcfsize) / cd_size_rnd;493cd_fetch_cnt = min_t(uint, cd_fetch_cnt,494(priv->config.pes * EIP197_FETCH_DEPTH));495} else {496/* for the EIP97, just fetch all that fits minus 1 */497cd_fetch_cnt = ((1 << priv->hwconfig.hwcfsize) /498cd_size_rnd) - 1;499}500/*501* Since we're using command desc's way larger than formally specified,502* we need to check whether we can fit even 1 for low-end EIP196's!503*/504if (!cd_fetch_cnt) {505dev_err(priv->dev, "Unable to fit even 1 command desc!\n");506return -ENODEV;507}508509for (i = 0; i < priv->config.rings; i++) {510/* ring base address */511writel(lower_32_bits(priv->ring[i].cdr.base_dma),512EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_RING_BASE_ADDR_LO);513writel(upper_32_bits(priv->ring[i].cdr.base_dma),514EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_RING_BASE_ADDR_HI);515516writel(EIP197_xDR_DESC_MODE_64BIT | EIP197_CDR_DESC_MODE_ADCP |517(priv->config.cd_offset << 14) | priv->config.cd_size,518EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_DESC_SIZE);519writel(((cd_fetch_cnt *520(cd_size_rnd << priv->hwconfig.hwdataw)) << 16) |521(cd_fetch_cnt * (priv->config.cd_offset / sizeof(u32))),522EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_CFG);523524/* Configure DMA tx control */525val = EIP197_HIA_xDR_CFG_WR_CACHE(WR_CACHE_3BITS);526val |= EIP197_HIA_xDR_CFG_RD_CACHE(RD_CACHE_3BITS);527writel(val, EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_DMA_CFG);528529/* clear any pending interrupt */530writel(GENMASK(5, 0),531EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_STAT);532}533534return 0;535}536537static int safexcel_hw_setup_rdesc_rings(struct safexcel_crypto_priv *priv)538{539u32 rd_size_rnd, val;540int i, rd_fetch_cnt;541542/* determine number of RD's we can fetch into the FIFO as one block */543rd_size_rnd = (EIP197_RD64_FETCH_SIZE +544(BIT(priv->hwconfig.hwdataw) - 1)) >>545priv->hwconfig.hwdataw;546if (priv->flags & SAFEXCEL_HW_EIP197) {547/* EIP197: try to fetch enough in 1 go to keep all pipes busy */548rd_fetch_cnt = (1 << priv->hwconfig.hwrfsize) / rd_size_rnd;549rd_fetch_cnt = min_t(uint, rd_fetch_cnt,550(priv->config.pes * EIP197_FETCH_DEPTH));551} else {552/* for the EIP97, just fetch all that fits minus 1 */553rd_fetch_cnt = ((1 << priv->hwconfig.hwrfsize) /554rd_size_rnd) - 1;555}556557for (i = 0; i < priv->config.rings; i++) {558/* ring base address */559writel(lower_32_bits(priv->ring[i].rdr.base_dma),560EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_RING_BASE_ADDR_LO);561writel(upper_32_bits(priv->ring[i].rdr.base_dma),562EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_RING_BASE_ADDR_HI);563564writel(EIP197_xDR_DESC_MODE_64BIT | (priv->config.rd_offset << 14) |565priv->config.rd_size,566EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_DESC_SIZE);567568writel(((rd_fetch_cnt *569(rd_size_rnd << priv->hwconfig.hwdataw)) << 16) |570(rd_fetch_cnt * (priv->config.rd_offset / sizeof(u32))),571EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_CFG);572573/* Configure DMA tx control */574val = EIP197_HIA_xDR_CFG_WR_CACHE(WR_CACHE_3BITS);575val |= EIP197_HIA_xDR_CFG_RD_CACHE(RD_CACHE_3BITS);576val |= EIP197_HIA_xDR_WR_RES_BUF | EIP197_HIA_xDR_WR_CTRL_BUF;577writel(val,578EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_DMA_CFG);579580/* clear any pending interrupt */581writel(GENMASK(7, 0),582EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_STAT);583584/* enable ring interrupt */585val = readl(EIP197_HIA_AIC_R(priv) + EIP197_HIA_AIC_R_ENABLE_CTRL(i));586val |= EIP197_RDR_IRQ(i);587writel(val, EIP197_HIA_AIC_R(priv) + EIP197_HIA_AIC_R_ENABLE_CTRL(i));588}589590return 0;591}592593static int safexcel_hw_init(struct safexcel_crypto_priv *priv)594{595u32 val;596int i, ret, pe, opbuflo, opbufhi;597598dev_dbg(priv->dev, "HW init: using %d pipe(s) and %d ring(s)\n",599priv->config.pes, priv->config.rings);600601/*602* For EIP197's only set maximum number of TX commands to 2^5 = 32603* Skip for the EIP97 as it does not have this field.604*/605if (priv->flags & SAFEXCEL_HW_EIP197) {606val = readl(EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL);607val |= EIP197_MST_CTRL_TX_MAX_CMD(5);608writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL);609}610611/* Configure wr/rd cache values */612writel(EIP197_MST_CTRL_RD_CACHE(RD_CACHE_4BITS) |613EIP197_MST_CTRL_WD_CACHE(WR_CACHE_4BITS),614EIP197_HIA_GEN_CFG(priv) + EIP197_MST_CTRL);615616/* Interrupts reset */617618/* Disable all global interrupts */619writel(0, EIP197_HIA_AIC_G(priv) + EIP197_HIA_AIC_G_ENABLE_CTRL);620621/* Clear any pending interrupt */622writel(GENMASK(31, 0), EIP197_HIA_AIC_G(priv) + EIP197_HIA_AIC_G_ACK);623624/* Processing Engine configuration */625for (pe = 0; pe < priv->config.pes; pe++) {626/* Data Fetch Engine configuration */627628/* Reset all DFE threads */629writel(EIP197_DxE_THR_CTRL_RESET_PE,630EIP197_HIA_DFE_THR(priv) + EIP197_HIA_DFE_THR_CTRL(pe));631632if (priv->flags & EIP197_PE_ARB)633/* Reset HIA input interface arbiter (if present) */634writel(EIP197_HIA_RA_PE_CTRL_RESET,635EIP197_HIA_AIC(priv) + EIP197_HIA_RA_PE_CTRL(pe));636637/* DMA transfer size to use */638val = EIP197_HIA_DFE_CFG_DIS_DEBUG;639val |= EIP197_HIA_DxE_CFG_MIN_DATA_SIZE(6) |640EIP197_HIA_DxE_CFG_MAX_DATA_SIZE(9);641val |= EIP197_HIA_DxE_CFG_MIN_CTRL_SIZE(6) |642EIP197_HIA_DxE_CFG_MAX_CTRL_SIZE(7);643val |= EIP197_HIA_DxE_CFG_DATA_CACHE_CTRL(RD_CACHE_3BITS);644val |= EIP197_HIA_DxE_CFG_CTRL_CACHE_CTRL(RD_CACHE_3BITS);645writel(val, EIP197_HIA_DFE(priv) + EIP197_HIA_DFE_CFG(pe));646647/* Leave the DFE threads reset state */648writel(0, EIP197_HIA_DFE_THR(priv) + EIP197_HIA_DFE_THR_CTRL(pe));649650/* Configure the processing engine thresholds */651writel(EIP197_PE_IN_xBUF_THRES_MIN(6) |652EIP197_PE_IN_xBUF_THRES_MAX(9),653EIP197_PE(priv) + EIP197_PE_IN_DBUF_THRES(pe));654writel(EIP197_PE_IN_xBUF_THRES_MIN(6) |655EIP197_PE_IN_xBUF_THRES_MAX(7),656EIP197_PE(priv) + EIP197_PE_IN_TBUF_THRES(pe));657658if (priv->flags & SAFEXCEL_HW_EIP197)659/* enable HIA input interface arbiter and rings */660writel(EIP197_HIA_RA_PE_CTRL_EN |661GENMASK(priv->config.rings - 1, 0),662EIP197_HIA_AIC(priv) + EIP197_HIA_RA_PE_CTRL(pe));663664/* Data Store Engine configuration */665666/* Reset all DSE threads */667writel(EIP197_DxE_THR_CTRL_RESET_PE,668EIP197_HIA_DSE_THR(priv) + EIP197_HIA_DSE_THR_CTRL(pe));669670/* Wait for all DSE threads to complete */671while ((readl(EIP197_HIA_DSE_THR(priv) + EIP197_HIA_DSE_THR_STAT(pe)) &672GENMASK(15, 12)) != GENMASK(15, 12))673;674675/* DMA transfer size to use */676if (priv->hwconfig.hwnumpes > 4) {677opbuflo = 9;678opbufhi = 10;679} else {680opbuflo = 7;681opbufhi = 8;682}683val = EIP197_HIA_DSE_CFG_DIS_DEBUG;684val |= EIP197_HIA_DxE_CFG_MIN_DATA_SIZE(opbuflo) |685EIP197_HIA_DxE_CFG_MAX_DATA_SIZE(opbufhi);686val |= EIP197_HIA_DxE_CFG_DATA_CACHE_CTRL(WR_CACHE_3BITS);687val |= EIP197_HIA_DSE_CFG_ALWAYS_BUFFERABLE;688/* FIXME: instability issues can occur for EIP97 but disabling689* it impacts performance.690*/691if (priv->flags & SAFEXCEL_HW_EIP197)692val |= EIP197_HIA_DSE_CFG_EN_SINGLE_WR;693writel(val, EIP197_HIA_DSE(priv) + EIP197_HIA_DSE_CFG(pe));694695/* Leave the DSE threads reset state */696writel(0, EIP197_HIA_DSE_THR(priv) + EIP197_HIA_DSE_THR_CTRL(pe));697698/* Configure the processing engine thresholds */699writel(EIP197_PE_OUT_DBUF_THRES_MIN(opbuflo) |700EIP197_PE_OUT_DBUF_THRES_MAX(opbufhi),701EIP197_PE(priv) + EIP197_PE_OUT_DBUF_THRES(pe));702703/* Processing Engine configuration */704705/* Token & context configuration */706val = EIP197_PE_EIP96_TOKEN_CTRL_CTX_UPDATES |707EIP197_PE_EIP96_TOKEN_CTRL_NO_TOKEN_WAIT |708EIP197_PE_EIP96_TOKEN_CTRL_ENABLE_TIMEOUT;709writel(val, EIP197_PE(priv) + EIP197_PE_EIP96_TOKEN_CTRL(pe));710711/* H/W capabilities selection: just enable everything */712writel(EIP197_FUNCTION_ALL,713EIP197_PE(priv) + EIP197_PE_EIP96_FUNCTION_EN(pe));714writel(EIP197_FUNCTION_ALL,715EIP197_PE(priv) + EIP197_PE_EIP96_FUNCTION2_EN(pe));716}717718/* Command Descriptor Rings prepare */719for (i = 0; i < priv->config.rings; i++) {720/* Clear interrupts for this ring */721writel(GENMASK(31, 0),722EIP197_HIA_AIC_R(priv) + EIP197_HIA_AIC_R_ENABLE_CLR(i));723724/* Disable external triggering */725writel(0, EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_CFG);726727/* Clear the pending prepared counter */728writel(EIP197_xDR_PREP_CLR_COUNT,729EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_PREP_COUNT);730731/* Clear the pending processed counter */732writel(EIP197_xDR_PROC_CLR_COUNT,733EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_PROC_COUNT);734735writel(0,736EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_PREP_PNTR);737writel(0,738EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_PROC_PNTR);739740writel((EIP197_DEFAULT_RING_SIZE * priv->config.cd_offset),741EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_RING_SIZE);742}743744/* Result Descriptor Ring prepare */745for (i = 0; i < priv->config.rings; i++) {746/* Disable external triggering*/747writel(0, EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_CFG);748749/* Clear the pending prepared counter */750writel(EIP197_xDR_PREP_CLR_COUNT,751EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_PREP_COUNT);752753/* Clear the pending processed counter */754writel(EIP197_xDR_PROC_CLR_COUNT,755EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_PROC_COUNT);756757writel(0,758EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_PREP_PNTR);759writel(0,760EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_PROC_PNTR);761762/* Ring size */763writel((EIP197_DEFAULT_RING_SIZE * priv->config.rd_offset),764EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_RING_SIZE);765}766767for (pe = 0; pe < priv->config.pes; pe++) {768/* Enable command descriptor rings */769writel(EIP197_DxE_THR_CTRL_EN | GENMASK(priv->config.rings - 1, 0),770EIP197_HIA_DFE_THR(priv) + EIP197_HIA_DFE_THR_CTRL(pe));771772/* Enable result descriptor rings */773writel(EIP197_DxE_THR_CTRL_EN | GENMASK(priv->config.rings - 1, 0),774EIP197_HIA_DSE_THR(priv) + EIP197_HIA_DSE_THR_CTRL(pe));775}776777/* Clear any HIA interrupt */778writel(GENMASK(30, 20), EIP197_HIA_AIC_G(priv) + EIP197_HIA_AIC_G_ACK);779780if (priv->flags & EIP197_SIMPLE_TRC) {781writel(EIP197_STRC_CONFIG_INIT |782EIP197_STRC_CONFIG_LARGE_REC(EIP197_CS_TRC_REC_WC) |783EIP197_STRC_CONFIG_SMALL_REC(EIP197_CS_TRC_REC_WC),784priv->base + EIP197_STRC_CONFIG);785writel(EIP197_PE_EIP96_TOKEN_CTRL2_CTX_DONE,786EIP197_PE(priv) + EIP197_PE_EIP96_TOKEN_CTRL2(0));787} else if (priv->flags & SAFEXCEL_HW_EIP197) {788ret = eip197_trc_cache_init(priv);789if (ret)790return ret;791}792793if (priv->flags & EIP197_ICE) {794ret = eip197_load_firmwares(priv);795if (ret)796return ret;797}798799return safexcel_hw_setup_cdesc_rings(priv) ?:800safexcel_hw_setup_rdesc_rings(priv) ?:8010;802}803804/* Called with ring's lock taken */805static void safexcel_try_push_requests(struct safexcel_crypto_priv *priv,806int ring)807{808int coal = min_t(int, priv->ring[ring].requests, EIP197_MAX_BATCH_SZ);809810if (!coal)811return;812813/* Configure when we want an interrupt */814writel(EIP197_HIA_RDR_THRESH_PKT_MODE |815EIP197_HIA_RDR_THRESH_PROC_PKT(coal),816EIP197_HIA_RDR(priv, ring) + EIP197_HIA_xDR_THRESH);817}818819void safexcel_dequeue(struct safexcel_crypto_priv *priv, int ring)820{821struct crypto_async_request *req, *backlog;822struct safexcel_context *ctx;823int ret, nreq = 0, cdesc = 0, rdesc = 0, commands, results;824825/* If a request wasn't properly dequeued because of a lack of resources,826* proceeded it first,827*/828req = priv->ring[ring].req;829backlog = priv->ring[ring].backlog;830if (req)831goto handle_req;832833while (true) {834spin_lock_bh(&priv->ring[ring].queue_lock);835backlog = crypto_get_backlog(&priv->ring[ring].queue);836req = crypto_dequeue_request(&priv->ring[ring].queue);837spin_unlock_bh(&priv->ring[ring].queue_lock);838839if (!req) {840priv->ring[ring].req = NULL;841priv->ring[ring].backlog = NULL;842goto finalize;843}844845handle_req:846ctx = crypto_tfm_ctx(req->tfm);847ret = ctx->send(req, ring, &commands, &results);848if (ret)849goto request_failed;850851if (backlog)852crypto_request_complete(backlog, -EINPROGRESS);853854/* In case the send() helper did not issue any command to push855* to the engine because the input data was cached, continue to856* dequeue other requests as this is valid and not an error.857*/858if (!commands && !results)859continue;860861cdesc += commands;862rdesc += results;863nreq++;864}865866request_failed:867/* Not enough resources to handle all the requests. Bail out and save868* the request and the backlog for the next dequeue call (per-ring).869*/870priv->ring[ring].req = req;871priv->ring[ring].backlog = backlog;872873finalize:874if (!nreq)875return;876877spin_lock_bh(&priv->ring[ring].lock);878879priv->ring[ring].requests += nreq;880881if (!priv->ring[ring].busy) {882safexcel_try_push_requests(priv, ring);883priv->ring[ring].busy = true;884}885886spin_unlock_bh(&priv->ring[ring].lock);887888/* let the RDR know we have pending descriptors */889writel((rdesc * priv->config.rd_offset),890EIP197_HIA_RDR(priv, ring) + EIP197_HIA_xDR_PREP_COUNT);891892/* let the CDR know we have pending descriptors */893writel((cdesc * priv->config.cd_offset),894EIP197_HIA_CDR(priv, ring) + EIP197_HIA_xDR_PREP_COUNT);895}896897inline int safexcel_rdesc_check_errors(struct safexcel_crypto_priv *priv,898void *rdp)899{900struct safexcel_result_desc *rdesc = rdp;901struct result_data_desc *result_data = rdp + priv->config.res_offset;902903if (likely((!rdesc->last_seg) || /* Rest only valid if last seg! */904((!rdesc->descriptor_overflow) &&905(!rdesc->buffer_overflow) &&906(!result_data->error_code))))907return 0;908909if (rdesc->descriptor_overflow)910dev_err(priv->dev, "Descriptor overflow detected");911912if (rdesc->buffer_overflow)913dev_err(priv->dev, "Buffer overflow detected");914915if (result_data->error_code & 0x4066) {916/* Fatal error (bits 1,2,5,6 & 14) */917dev_err(priv->dev,918"result descriptor error (%x)",919result_data->error_code);920921return -EIO;922} else if (result_data->error_code &923(BIT(7) | BIT(4) | BIT(3) | BIT(0))) {924/*925* Give priority over authentication fails:926* Blocksize, length & overflow errors,927* something wrong with the input!928*/929return -EINVAL;930} else if (result_data->error_code & BIT(9)) {931/* Authentication failed */932return -EBADMSG;933}934935/* All other non-fatal errors */936return -EINVAL;937}938939inline void safexcel_rdr_req_set(struct safexcel_crypto_priv *priv,940int ring,941struct safexcel_result_desc *rdesc,942struct crypto_async_request *req)943{944int i = safexcel_ring_rdr_rdesc_index(priv, ring, rdesc);945946priv->ring[ring].rdr_req[i] = req;947}948949inline struct crypto_async_request *950safexcel_rdr_req_get(struct safexcel_crypto_priv *priv, int ring)951{952int i = safexcel_ring_first_rdr_index(priv, ring);953954return priv->ring[ring].rdr_req[i];955}956957void safexcel_complete(struct safexcel_crypto_priv *priv, int ring)958{959struct safexcel_command_desc *cdesc;960961/* Acknowledge the command descriptors */962do {963cdesc = safexcel_ring_next_rptr(priv, &priv->ring[ring].cdr);964if (IS_ERR(cdesc)) {965dev_err(priv->dev,966"Could not retrieve the command descriptor\n");967return;968}969} while (!cdesc->last_seg);970}971972int safexcel_invalidate_cache(struct crypto_async_request *async,973struct safexcel_crypto_priv *priv,974dma_addr_t ctxr_dma, int ring)975{976struct safexcel_command_desc *cdesc;977struct safexcel_result_desc *rdesc;978struct safexcel_token *dmmy;979int ret = 0;980981/* Prepare command descriptor */982cdesc = safexcel_add_cdesc(priv, ring, true, true, 0, 0, 0, ctxr_dma,983&dmmy);984if (IS_ERR(cdesc))985return PTR_ERR(cdesc);986987cdesc->control_data.type = EIP197_TYPE_EXTENDED;988cdesc->control_data.options = 0;989cdesc->control_data.context_lo &= ~EIP197_CONTEXT_SIZE_MASK;990cdesc->control_data.control0 = CONTEXT_CONTROL_INV_TR;991992/* Prepare result descriptor */993rdesc = safexcel_add_rdesc(priv, ring, true, true, 0, 0);994995if (IS_ERR(rdesc)) {996ret = PTR_ERR(rdesc);997goto cdesc_rollback;998}9991000safexcel_rdr_req_set(priv, ring, rdesc, async);10011002return ret;10031004cdesc_rollback:1005safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr);10061007return ret;1008}10091010static inline void safexcel_handle_result_descriptor(struct safexcel_crypto_priv *priv,1011int ring)1012{1013struct crypto_async_request *req;1014struct safexcel_context *ctx;1015int ret, i, nreq, ndesc, tot_descs, handled = 0;1016bool should_complete;10171018handle_results:1019tot_descs = 0;10201021nreq = readl(EIP197_HIA_RDR(priv, ring) + EIP197_HIA_xDR_PROC_COUNT);1022nreq >>= EIP197_xDR_PROC_xD_PKT_OFFSET;1023nreq &= EIP197_xDR_PROC_xD_PKT_MASK;1024if (!nreq)1025goto requests_left;10261027for (i = 0; i < nreq; i++) {1028req = safexcel_rdr_req_get(priv, ring);10291030ctx = crypto_tfm_ctx(req->tfm);1031ndesc = ctx->handle_result(priv, ring, req,1032&should_complete, &ret);1033if (ndesc < 0) {1034dev_err(priv->dev, "failed to handle result (%d)\n",1035ndesc);1036goto acknowledge;1037}10381039if (should_complete) {1040local_bh_disable();1041crypto_request_complete(req, ret);1042local_bh_enable();1043}10441045tot_descs += ndesc;1046handled++;1047}10481049acknowledge:1050if (i)1051writel(EIP197_xDR_PROC_xD_PKT(i) |1052(tot_descs * priv->config.rd_offset),1053EIP197_HIA_RDR(priv, ring) + EIP197_HIA_xDR_PROC_COUNT);10541055/* If the number of requests overflowed the counter, try to proceed more1056* requests.1057*/1058if (nreq == EIP197_xDR_PROC_xD_PKT_MASK)1059goto handle_results;10601061requests_left:1062spin_lock_bh(&priv->ring[ring].lock);10631064priv->ring[ring].requests -= handled;1065safexcel_try_push_requests(priv, ring);10661067if (!priv->ring[ring].requests)1068priv->ring[ring].busy = false;10691070spin_unlock_bh(&priv->ring[ring].lock);1071}10721073static void safexcel_dequeue_work(struct work_struct *work)1074{1075struct safexcel_work_data *data =1076container_of(work, struct safexcel_work_data, work);10771078safexcel_dequeue(data->priv, data->ring);1079}10801081struct safexcel_ring_irq_data {1082struct safexcel_crypto_priv *priv;1083int ring;1084};10851086static irqreturn_t safexcel_irq_ring(int irq, void *data)1087{1088struct safexcel_ring_irq_data *irq_data = data;1089struct safexcel_crypto_priv *priv = irq_data->priv;1090int ring = irq_data->ring, rc = IRQ_NONE;1091u32 status, stat;10921093status = readl(EIP197_HIA_AIC_R(priv) + EIP197_HIA_AIC_R_ENABLED_STAT(ring));1094if (!status)1095return rc;10961097/* RDR interrupts */1098if (status & EIP197_RDR_IRQ(ring)) {1099stat = readl(EIP197_HIA_RDR(priv, ring) + EIP197_HIA_xDR_STAT);11001101if (unlikely(stat & EIP197_xDR_ERR)) {1102/*1103* Fatal error, the RDR is unusable and must be1104* reinitialized. This should not happen under1105* normal circumstances.1106*/1107dev_err(priv->dev, "RDR: fatal error.\n");1108} else if (likely(stat & EIP197_xDR_THRESH)) {1109rc = IRQ_WAKE_THREAD;1110}11111112/* ACK the interrupts */1113writel(stat & 0xff,1114EIP197_HIA_RDR(priv, ring) + EIP197_HIA_xDR_STAT);1115}11161117/* ACK the interrupts */1118writel(status, EIP197_HIA_AIC_R(priv) + EIP197_HIA_AIC_R_ACK(ring));11191120return rc;1121}11221123static irqreturn_t safexcel_irq_ring_thread(int irq, void *data)1124{1125struct safexcel_ring_irq_data *irq_data = data;1126struct safexcel_crypto_priv *priv = irq_data->priv;1127int ring = irq_data->ring;11281129safexcel_handle_result_descriptor(priv, ring);11301131queue_work(priv->ring[ring].workqueue,1132&priv->ring[ring].work_data.work);11331134return IRQ_HANDLED;1135}11361137static int safexcel_request_ring_irq(void *pdev, int irqid,1138int is_pci_dev,1139int ring_id,1140irq_handler_t handler,1141irq_handler_t threaded_handler,1142struct safexcel_ring_irq_data *ring_irq_priv)1143{1144int ret, irq, cpu;1145struct device *dev;11461147if (IS_ENABLED(CONFIG_PCI) && is_pci_dev) {1148struct pci_dev *pci_pdev = pdev;11491150dev = &pci_pdev->dev;1151irq = pci_irq_vector(pci_pdev, irqid);1152if (irq < 0) {1153dev_err(dev, "unable to get device MSI IRQ %d (err %d)\n",1154irqid, irq);1155return irq;1156}1157} else if (IS_ENABLED(CONFIG_OF)) {1158struct platform_device *plf_pdev = pdev;1159char irq_name[6] = {0}; /* "ringX\0" */11601161snprintf(irq_name, 6, "ring%d", irqid);1162dev = &plf_pdev->dev;1163irq = platform_get_irq_byname(plf_pdev, irq_name);11641165if (irq < 0)1166return irq;1167} else {1168return -ENXIO;1169}11701171ret = devm_request_threaded_irq(dev, irq, handler,1172threaded_handler, IRQF_ONESHOT,1173dev_name(dev), ring_irq_priv);1174if (ret) {1175dev_err(dev, "unable to request IRQ %d\n", irq);1176return ret;1177}11781179/* Set affinity */1180cpu = cpumask_local_spread(ring_id, NUMA_NO_NODE);1181irq_set_affinity_hint(irq, get_cpu_mask(cpu));11821183return irq;1184}11851186static struct safexcel_alg_template *safexcel_algs[] = {1187&safexcel_alg_ecb_des,1188&safexcel_alg_cbc_des,1189&safexcel_alg_ecb_des3_ede,1190&safexcel_alg_cbc_des3_ede,1191&safexcel_alg_ecb_aes,1192&safexcel_alg_cbc_aes,1193&safexcel_alg_ctr_aes,1194&safexcel_alg_md5,1195&safexcel_alg_sha1,1196&safexcel_alg_sha224,1197&safexcel_alg_sha256,1198&safexcel_alg_sha384,1199&safexcel_alg_sha512,1200&safexcel_alg_hmac_md5,1201&safexcel_alg_hmac_sha1,1202&safexcel_alg_hmac_sha224,1203&safexcel_alg_hmac_sha256,1204&safexcel_alg_hmac_sha384,1205&safexcel_alg_hmac_sha512,1206&safexcel_alg_authenc_hmac_sha1_cbc_aes,1207&safexcel_alg_authenc_hmac_sha224_cbc_aes,1208&safexcel_alg_authenc_hmac_sha256_cbc_aes,1209&safexcel_alg_authenc_hmac_sha384_cbc_aes,1210&safexcel_alg_authenc_hmac_sha512_cbc_aes,1211&safexcel_alg_authenc_hmac_sha1_cbc_des3_ede,1212&safexcel_alg_authenc_hmac_sha1_ctr_aes,1213&safexcel_alg_authenc_hmac_sha224_ctr_aes,1214&safexcel_alg_authenc_hmac_sha256_ctr_aes,1215&safexcel_alg_authenc_hmac_sha384_ctr_aes,1216&safexcel_alg_authenc_hmac_sha512_ctr_aes,1217&safexcel_alg_xts_aes,1218&safexcel_alg_gcm,1219&safexcel_alg_ccm,1220&safexcel_alg_cbcmac,1221&safexcel_alg_xcbcmac,1222&safexcel_alg_cmac,1223&safexcel_alg_chacha20,1224&safexcel_alg_chachapoly,1225&safexcel_alg_chachapoly_esp,1226&safexcel_alg_sm3,1227&safexcel_alg_hmac_sm3,1228&safexcel_alg_ecb_sm4,1229&safexcel_alg_cbc_sm4,1230&safexcel_alg_ctr_sm4,1231&safexcel_alg_authenc_hmac_sha1_cbc_sm4,1232&safexcel_alg_authenc_hmac_sm3_cbc_sm4,1233&safexcel_alg_authenc_hmac_sha1_ctr_sm4,1234&safexcel_alg_authenc_hmac_sm3_ctr_sm4,1235&safexcel_alg_sha3_224,1236&safexcel_alg_sha3_256,1237&safexcel_alg_sha3_384,1238&safexcel_alg_sha3_512,1239&safexcel_alg_hmac_sha3_224,1240&safexcel_alg_hmac_sha3_256,1241&safexcel_alg_hmac_sha3_384,1242&safexcel_alg_hmac_sha3_512,1243&safexcel_alg_authenc_hmac_sha1_cbc_des,1244&safexcel_alg_authenc_hmac_sha256_cbc_des3_ede,1245&safexcel_alg_authenc_hmac_sha224_cbc_des3_ede,1246&safexcel_alg_authenc_hmac_sha512_cbc_des3_ede,1247&safexcel_alg_authenc_hmac_sha384_cbc_des3_ede,1248&safexcel_alg_authenc_hmac_sha256_cbc_des,1249&safexcel_alg_authenc_hmac_sha224_cbc_des,1250&safexcel_alg_authenc_hmac_sha512_cbc_des,1251&safexcel_alg_authenc_hmac_sha384_cbc_des,1252&safexcel_alg_rfc4106_gcm,1253&safexcel_alg_rfc4543_gcm,1254&safexcel_alg_rfc4309_ccm,1255};12561257static int safexcel_register_algorithms(struct safexcel_crypto_priv *priv)1258{1259int i, j, ret = 0;12601261for (i = 0; i < ARRAY_SIZE(safexcel_algs); i++) {1262safexcel_algs[i]->priv = priv;12631264/* Do we have all required base algorithms available? */1265if ((safexcel_algs[i]->algo_mask & priv->hwconfig.algo_flags) !=1266safexcel_algs[i]->algo_mask)1267/* No, so don't register this ciphersuite */1268continue;12691270if (safexcel_algs[i]->type == SAFEXCEL_ALG_TYPE_SKCIPHER)1271ret = crypto_register_skcipher(&safexcel_algs[i]->alg.skcipher);1272else if (safexcel_algs[i]->type == SAFEXCEL_ALG_TYPE_AEAD)1273ret = crypto_register_aead(&safexcel_algs[i]->alg.aead);1274else1275ret = crypto_register_ahash(&safexcel_algs[i]->alg.ahash);12761277if (ret)1278goto fail;1279}12801281return 0;12821283fail:1284for (j = 0; j < i; j++) {1285/* Do we have all required base algorithms available? */1286if ((safexcel_algs[j]->algo_mask & priv->hwconfig.algo_flags) !=1287safexcel_algs[j]->algo_mask)1288/* No, so don't unregister this ciphersuite */1289continue;12901291if (safexcel_algs[j]->type == SAFEXCEL_ALG_TYPE_SKCIPHER)1292crypto_unregister_skcipher(&safexcel_algs[j]->alg.skcipher);1293else if (safexcel_algs[j]->type == SAFEXCEL_ALG_TYPE_AEAD)1294crypto_unregister_aead(&safexcel_algs[j]->alg.aead);1295else1296crypto_unregister_ahash(&safexcel_algs[j]->alg.ahash);1297}12981299return ret;1300}13011302static void safexcel_unregister_algorithms(struct safexcel_crypto_priv *priv)1303{1304int i;13051306for (i = 0; i < ARRAY_SIZE(safexcel_algs); i++) {1307/* Do we have all required base algorithms available? */1308if ((safexcel_algs[i]->algo_mask & priv->hwconfig.algo_flags) !=1309safexcel_algs[i]->algo_mask)1310/* No, so don't unregister this ciphersuite */1311continue;13121313if (safexcel_algs[i]->type == SAFEXCEL_ALG_TYPE_SKCIPHER)1314crypto_unregister_skcipher(&safexcel_algs[i]->alg.skcipher);1315else if (safexcel_algs[i]->type == SAFEXCEL_ALG_TYPE_AEAD)1316crypto_unregister_aead(&safexcel_algs[i]->alg.aead);1317else1318crypto_unregister_ahash(&safexcel_algs[i]->alg.ahash);1319}1320}13211322static void safexcel_configure(struct safexcel_crypto_priv *priv)1323{1324u32 mask = BIT(priv->hwconfig.hwdataw) - 1;13251326priv->config.pes = priv->hwconfig.hwnumpes;1327priv->config.rings = min_t(u32, priv->hwconfig.hwnumrings, max_rings);1328/* Cannot currently support more rings than we have ring AICs! */1329priv->config.rings = min_t(u32, priv->config.rings,1330priv->hwconfig.hwnumraic);13311332priv->config.cd_size = EIP197_CD64_FETCH_SIZE;1333priv->config.cd_offset = (priv->config.cd_size + mask) & ~mask;1334priv->config.cdsh_offset = (EIP197_MAX_TOKENS + mask) & ~mask;13351336/* res token is behind the descr, but ofs must be rounded to buswdth */1337priv->config.res_offset = (EIP197_RD64_FETCH_SIZE + mask) & ~mask;1338/* now the size of the descr is this 1st part plus the result struct */1339priv->config.rd_size = priv->config.res_offset +1340EIP197_RD64_RESULT_SIZE;1341priv->config.rd_offset = (priv->config.rd_size + mask) & ~mask;13421343/* convert dwords to bytes */1344priv->config.cd_offset *= sizeof(u32);1345priv->config.cdsh_offset *= sizeof(u32);1346priv->config.rd_offset *= sizeof(u32);1347priv->config.res_offset *= sizeof(u32);1348}13491350static void safexcel_init_register_offsets(struct safexcel_crypto_priv *priv)1351{1352struct safexcel_register_offsets *offsets = &priv->offsets;13531354if (priv->flags & SAFEXCEL_HW_EIP197) {1355offsets->hia_aic = EIP197_HIA_AIC_BASE;1356offsets->hia_aic_g = EIP197_HIA_AIC_G_BASE;1357offsets->hia_aic_r = EIP197_HIA_AIC_R_BASE;1358offsets->hia_aic_xdr = EIP197_HIA_AIC_xDR_BASE;1359offsets->hia_dfe = EIP197_HIA_DFE_BASE;1360offsets->hia_dfe_thr = EIP197_HIA_DFE_THR_BASE;1361offsets->hia_dse = EIP197_HIA_DSE_BASE;1362offsets->hia_dse_thr = EIP197_HIA_DSE_THR_BASE;1363offsets->hia_gen_cfg = EIP197_HIA_GEN_CFG_BASE;1364offsets->pe = EIP197_PE_BASE;1365offsets->global = EIP197_GLOBAL_BASE;1366} else {1367offsets->hia_aic = EIP97_HIA_AIC_BASE;1368offsets->hia_aic_g = EIP97_HIA_AIC_G_BASE;1369offsets->hia_aic_r = EIP97_HIA_AIC_R_BASE;1370offsets->hia_aic_xdr = EIP97_HIA_AIC_xDR_BASE;1371offsets->hia_dfe = EIP97_HIA_DFE_BASE;1372offsets->hia_dfe_thr = EIP97_HIA_DFE_THR_BASE;1373offsets->hia_dse = EIP97_HIA_DSE_BASE;1374offsets->hia_dse_thr = EIP97_HIA_DSE_THR_BASE;1375offsets->hia_gen_cfg = EIP97_HIA_GEN_CFG_BASE;1376offsets->pe = EIP97_PE_BASE;1377offsets->global = EIP97_GLOBAL_BASE;1378}1379}13801381/*1382* Generic part of probe routine, shared by platform and PCI driver1383*1384* Assumes IO resources have been mapped, private data mem has been allocated,1385* clocks have been enabled, device pointer has been assigned etc.1386*1387*/1388static int safexcel_probe_generic(void *pdev,1389struct safexcel_crypto_priv *priv,1390int is_pci_dev)1391{1392struct device *dev = priv->dev;1393u32 peid, version, mask, val, hiaopt, hwopt, peopt;1394int i, ret, hwctg;13951396priv->context_pool = dmam_pool_create("safexcel-context", dev,1397sizeof(struct safexcel_context_record),13981, 0);1399if (!priv->context_pool)1400return -ENOMEM;14011402/*1403* First try the EIP97 HIA version regs1404* For the EIP197, this is guaranteed to NOT return any of the test1405* values1406*/1407version = readl(priv->base + EIP97_HIA_AIC_BASE + EIP197_HIA_VERSION);14081409mask = 0; /* do not swap */1410if (EIP197_REG_LO16(version) == EIP197_HIA_VERSION_LE) {1411priv->hwconfig.hiaver = EIP197_VERSION_MASK(version);1412} else if (EIP197_REG_HI16(version) == EIP197_HIA_VERSION_BE) {1413/* read back byte-swapped, so complement byte swap bits */1414mask = EIP197_MST_CTRL_BYTE_SWAP_BITS;1415priv->hwconfig.hiaver = EIP197_VERSION_SWAP(version);1416} else {1417/* So it wasn't an EIP97 ... maybe it's an EIP197? */1418version = readl(priv->base + EIP197_HIA_AIC_BASE +1419EIP197_HIA_VERSION);1420if (EIP197_REG_LO16(version) == EIP197_HIA_VERSION_LE) {1421priv->hwconfig.hiaver = EIP197_VERSION_MASK(version);1422priv->flags |= SAFEXCEL_HW_EIP197;1423} else if (EIP197_REG_HI16(version) ==1424EIP197_HIA_VERSION_BE) {1425/* read back byte-swapped, so complement swap bits */1426mask = EIP197_MST_CTRL_BYTE_SWAP_BITS;1427priv->hwconfig.hiaver = EIP197_VERSION_SWAP(version);1428priv->flags |= SAFEXCEL_HW_EIP197;1429} else {1430return -ENODEV;1431}1432}14331434/* Now initialize the reg offsets based on the probing info so far */1435safexcel_init_register_offsets(priv);14361437/*1438* If the version was read byte-swapped, we need to flip the device1439* swapping Keep in mind here, though, that what we write will also be1440* byte-swapped ...1441*/1442if (mask) {1443val = readl(EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL);1444val = val ^ (mask >> 24); /* toggle byte swap bits */1445writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL);1446}14471448/*1449* We're not done probing yet! We may fall through to here if no HIA1450* was found at all. So, with the endianness presumably correct now and1451* the offsets setup, *really* probe for the EIP97/EIP197.1452*/1453version = readl(EIP197_GLOBAL(priv) + EIP197_VERSION);1454if (((priv->flags & SAFEXCEL_HW_EIP197) &&1455(EIP197_REG_LO16(version) != EIP197_VERSION_LE) &&1456(EIP197_REG_LO16(version) != EIP196_VERSION_LE)) ||1457((!(priv->flags & SAFEXCEL_HW_EIP197) &&1458(EIP197_REG_LO16(version) != EIP97_VERSION_LE)))) {1459/*1460* We did not find the device that matched our initial probing1461* (or our initial probing failed) Report appropriate error.1462*/1463dev_err(priv->dev, "Probing for EIP97/EIP19x failed - no such device (read %08x)\n",1464version);1465return -ENODEV;1466}14671468priv->hwconfig.hwver = EIP197_VERSION_MASK(version);1469hwctg = version >> 28;1470peid = version & 255;14711472/* Detect EIP206 processing pipe */1473version = readl(EIP197_PE(priv) + + EIP197_PE_VERSION(0));1474if (EIP197_REG_LO16(version) != EIP206_VERSION_LE) {1475dev_err(priv->dev, "EIP%d: EIP206 not detected\n", peid);1476return -ENODEV;1477}1478priv->hwconfig.ppver = EIP197_VERSION_MASK(version);14791480/* Detect EIP96 packet engine and version */1481version = readl(EIP197_PE(priv) + EIP197_PE_EIP96_VERSION(0));1482if (EIP197_REG_LO16(version) != EIP96_VERSION_LE) {1483dev_err(dev, "EIP%d: EIP96 not detected.\n", peid);1484return -ENODEV;1485}1486priv->hwconfig.pever = EIP197_VERSION_MASK(version);14871488hwopt = readl(EIP197_GLOBAL(priv) + EIP197_OPTIONS);1489hiaopt = readl(EIP197_HIA_AIC(priv) + EIP197_HIA_OPTIONS);14901491priv->hwconfig.icever = 0;1492priv->hwconfig.ocever = 0;1493priv->hwconfig.psever = 0;1494if (priv->flags & SAFEXCEL_HW_EIP197) {1495/* EIP197 */1496peopt = readl(EIP197_PE(priv) + EIP197_PE_OPTIONS(0));14971498priv->hwconfig.hwdataw = (hiaopt >> EIP197_HWDATAW_OFFSET) &1499EIP197_HWDATAW_MASK;1500priv->hwconfig.hwcfsize = ((hiaopt >> EIP197_CFSIZE_OFFSET) &1501EIP197_CFSIZE_MASK) +1502EIP197_CFSIZE_ADJUST;1503priv->hwconfig.hwrfsize = ((hiaopt >> EIP197_RFSIZE_OFFSET) &1504EIP197_RFSIZE_MASK) +1505EIP197_RFSIZE_ADJUST;1506priv->hwconfig.hwnumpes = (hiaopt >> EIP197_N_PES_OFFSET) &1507EIP197_N_PES_MASK;1508priv->hwconfig.hwnumrings = (hiaopt >> EIP197_N_RINGS_OFFSET) &1509EIP197_N_RINGS_MASK;1510if (hiaopt & EIP197_HIA_OPT_HAS_PE_ARB)1511priv->flags |= EIP197_PE_ARB;1512if (EIP206_OPT_ICE_TYPE(peopt) == 1) {1513priv->flags |= EIP197_ICE;1514/* Detect ICE EIP207 class. engine and version */1515version = readl(EIP197_PE(priv) +1516EIP197_PE_ICE_VERSION(0));1517if (EIP197_REG_LO16(version) != EIP207_VERSION_LE) {1518dev_err(dev, "EIP%d: ICE EIP207 not detected.\n",1519peid);1520return -ENODEV;1521}1522priv->hwconfig.icever = EIP197_VERSION_MASK(version);1523}1524if (EIP206_OPT_OCE_TYPE(peopt) == 1) {1525priv->flags |= EIP197_OCE;1526/* Detect EIP96PP packet stream editor and version */1527version = readl(EIP197_PE(priv) + EIP197_PE_PSE_VERSION(0));1528if (EIP197_REG_LO16(version) != EIP96_VERSION_LE) {1529dev_err(dev, "EIP%d: EIP96PP not detected.\n", peid);1530return -ENODEV;1531}1532priv->hwconfig.psever = EIP197_VERSION_MASK(version);1533/* Detect OCE EIP207 class. engine and version */1534version = readl(EIP197_PE(priv) +1535EIP197_PE_ICE_VERSION(0));1536if (EIP197_REG_LO16(version) != EIP207_VERSION_LE) {1537dev_err(dev, "EIP%d: OCE EIP207 not detected.\n",1538peid);1539return -ENODEV;1540}1541priv->hwconfig.ocever = EIP197_VERSION_MASK(version);1542}1543/* If not a full TRC, then assume simple TRC */1544if (!(hwopt & EIP197_OPT_HAS_TRC))1545priv->flags |= EIP197_SIMPLE_TRC;1546/* EIP197 always has SOME form of TRC */1547priv->flags |= EIP197_TRC_CACHE;1548} else {1549/* EIP97 */1550priv->hwconfig.hwdataw = (hiaopt >> EIP197_HWDATAW_OFFSET) &1551EIP97_HWDATAW_MASK;1552priv->hwconfig.hwcfsize = (hiaopt >> EIP97_CFSIZE_OFFSET) &1553EIP97_CFSIZE_MASK;1554priv->hwconfig.hwrfsize = (hiaopt >> EIP97_RFSIZE_OFFSET) &1555EIP97_RFSIZE_MASK;1556priv->hwconfig.hwnumpes = 1; /* by definition */1557priv->hwconfig.hwnumrings = (hiaopt >> EIP197_N_RINGS_OFFSET) &1558EIP197_N_RINGS_MASK;1559}15601561/* Scan for ring AIC's */1562for (i = 0; i < EIP197_MAX_RING_AIC; i++) {1563version = readl(EIP197_HIA_AIC_R(priv) +1564EIP197_HIA_AIC_R_VERSION(i));1565if (EIP197_REG_LO16(version) != EIP201_VERSION_LE)1566break;1567}1568priv->hwconfig.hwnumraic = i;1569/* Low-end EIP196 may not have any ring AIC's ... */1570if (!priv->hwconfig.hwnumraic) {1571dev_err(priv->dev, "No ring interrupt controller present!\n");1572return -ENODEV;1573}15741575/* Get supported algorithms from EIP96 transform engine */1576priv->hwconfig.algo_flags = readl(EIP197_PE(priv) +1577EIP197_PE_EIP96_OPTIONS(0));15781579/* Print single info line describing what we just detected */1580dev_info(priv->dev, "EIP%d:%x(%d,%d,%d,%d)-HIA:%x(%d,%d,%d),PE:%x/%x(alg:%08x)/%x/%x/%x\n",1581peid, priv->hwconfig.hwver, hwctg, priv->hwconfig.hwnumpes,1582priv->hwconfig.hwnumrings, priv->hwconfig.hwnumraic,1583priv->hwconfig.hiaver, priv->hwconfig.hwdataw,1584priv->hwconfig.hwcfsize, priv->hwconfig.hwrfsize,1585priv->hwconfig.ppver, priv->hwconfig.pever,1586priv->hwconfig.algo_flags, priv->hwconfig.icever,1587priv->hwconfig.ocever, priv->hwconfig.psever);15881589safexcel_configure(priv);15901591if (IS_ENABLED(CONFIG_PCI) && priv->data->version == EIP197_DEVBRD) {1592/*1593* Request MSI vectors for global + 1 per ring -1594* or just 1 for older dev images1595*/1596struct pci_dev *pci_pdev = pdev;15971598ret = pci_alloc_irq_vectors(pci_pdev,1599priv->config.rings + 1,1600priv->config.rings + 1,1601PCI_IRQ_MSI | PCI_IRQ_MSIX);1602if (ret < 0) {1603dev_err(dev, "Failed to allocate PCI MSI interrupts\n");1604return ret;1605}1606}16071608/* Register the ring IRQ handlers and configure the rings */1609priv->ring = devm_kcalloc(dev, priv->config.rings,1610sizeof(*priv->ring),1611GFP_KERNEL);1612if (!priv->ring)1613return -ENOMEM;16141615for (i = 0; i < priv->config.rings; i++) {1616char wq_name[9] = {0};1617int irq;1618struct safexcel_ring_irq_data *ring_irq;16191620ret = safexcel_init_ring_descriptors(priv,1621&priv->ring[i].cdr,1622&priv->ring[i].rdr);1623if (ret) {1624dev_err(dev, "Failed to initialize rings\n");1625goto err_cleanup_rings;1626}16271628priv->ring[i].rdr_req = devm_kcalloc(dev,1629EIP197_DEFAULT_RING_SIZE,1630sizeof(*priv->ring[i].rdr_req),1631GFP_KERNEL);1632if (!priv->ring[i].rdr_req) {1633ret = -ENOMEM;1634goto err_cleanup_rings;1635}16361637ring_irq = devm_kzalloc(dev, sizeof(*ring_irq), GFP_KERNEL);1638if (!ring_irq) {1639ret = -ENOMEM;1640goto err_cleanup_rings;1641}16421643ring_irq->priv = priv;1644ring_irq->ring = i;16451646irq = safexcel_request_ring_irq(pdev,1647EIP197_IRQ_NUMBER(i, is_pci_dev),1648is_pci_dev,1649i,1650safexcel_irq_ring,1651safexcel_irq_ring_thread,1652ring_irq);1653if (irq < 0) {1654dev_err(dev, "Failed to get IRQ ID for ring %d\n", i);1655ret = irq;1656goto err_cleanup_rings;1657}16581659priv->ring[i].irq = irq;1660priv->ring[i].work_data.priv = priv;1661priv->ring[i].work_data.ring = i;1662INIT_WORK(&priv->ring[i].work_data.work,1663safexcel_dequeue_work);16641665snprintf(wq_name, 9, "wq_ring%d", i);1666priv->ring[i].workqueue =1667create_singlethread_workqueue(wq_name);1668if (!priv->ring[i].workqueue) {1669ret = -ENOMEM;1670goto err_cleanup_rings;1671}16721673priv->ring[i].requests = 0;1674priv->ring[i].busy = false;16751676crypto_init_queue(&priv->ring[i].queue,1677EIP197_DEFAULT_RING_SIZE);16781679spin_lock_init(&priv->ring[i].lock);1680spin_lock_init(&priv->ring[i].queue_lock);1681}16821683atomic_set(&priv->ring_used, 0);16841685ret = safexcel_hw_init(priv);1686if (ret) {1687dev_err(dev, "HW init failed (%d)\n", ret);1688goto err_cleanup_rings;1689}16901691ret = safexcel_register_algorithms(priv);1692if (ret) {1693dev_err(dev, "Failed to register algorithms (%d)\n", ret);1694goto err_cleanup_rings;1695}16961697return 0;16981699err_cleanup_rings:1700for (i = 0; i < priv->config.rings; i++) {1701if (priv->ring[i].irq)1702irq_set_affinity_hint(priv->ring[i].irq, NULL);1703if (priv->ring[i].workqueue)1704destroy_workqueue(priv->ring[i].workqueue);1705}17061707return ret;1708}17091710static void safexcel_hw_reset_rings(struct safexcel_crypto_priv *priv)1711{1712int i;17131714for (i = 0; i < priv->config.rings; i++) {1715/* clear any pending interrupt */1716writel(GENMASK(5, 0), EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_STAT);1717writel(GENMASK(7, 0), EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_STAT);17181719/* Reset the CDR base address */1720writel(0, EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_RING_BASE_ADDR_LO);1721writel(0, EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_RING_BASE_ADDR_HI);17221723/* Reset the RDR base address */1724writel(0, EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_RING_BASE_ADDR_LO);1725writel(0, EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_RING_BASE_ADDR_HI);1726}1727}17281729/* for Device Tree platform driver */17301731static int safexcel_probe(struct platform_device *pdev)1732{1733struct device *dev = &pdev->dev;1734struct safexcel_crypto_priv *priv;1735int ret;17361737priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);1738if (!priv)1739return -ENOMEM;17401741priv->dev = dev;1742priv->data = (struct safexcel_priv_data *)of_device_get_match_data(dev);17431744platform_set_drvdata(pdev, priv);17451746priv->base = devm_platform_ioremap_resource(pdev, 0);1747if (IS_ERR(priv->base)) {1748dev_err(dev, "failed to get resource\n");1749return PTR_ERR(priv->base);1750}17511752priv->clk = devm_clk_get(&pdev->dev, NULL);1753ret = PTR_ERR_OR_ZERO(priv->clk);1754/* The clock isn't mandatory */1755if (ret != -ENOENT) {1756if (ret)1757return ret;17581759ret = clk_prepare_enable(priv->clk);1760if (ret) {1761dev_err(dev, "unable to enable clk (%d)\n", ret);1762return ret;1763}1764}17651766priv->reg_clk = devm_clk_get(&pdev->dev, "reg");1767ret = PTR_ERR_OR_ZERO(priv->reg_clk);1768/* The clock isn't mandatory */1769if (ret != -ENOENT) {1770if (ret)1771goto err_core_clk;17721773ret = clk_prepare_enable(priv->reg_clk);1774if (ret) {1775dev_err(dev, "unable to enable reg clk (%d)\n", ret);1776goto err_core_clk;1777}1778}17791780ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));1781if (ret)1782goto err_reg_clk;17831784/* Generic EIP97/EIP197 device probing */1785ret = safexcel_probe_generic(pdev, priv, 0);1786if (ret)1787goto err_reg_clk;17881789return 0;17901791err_reg_clk:1792clk_disable_unprepare(priv->reg_clk);1793err_core_clk:1794clk_disable_unprepare(priv->clk);1795return ret;1796}17971798static void safexcel_remove(struct platform_device *pdev)1799{1800struct safexcel_crypto_priv *priv = platform_get_drvdata(pdev);1801int i;18021803safexcel_unregister_algorithms(priv);1804safexcel_hw_reset_rings(priv);18051806clk_disable_unprepare(priv->reg_clk);1807clk_disable_unprepare(priv->clk);18081809for (i = 0; i < priv->config.rings; i++) {1810irq_set_affinity_hint(priv->ring[i].irq, NULL);1811destroy_workqueue(priv->ring[i].workqueue);1812}1813}18141815static const struct safexcel_priv_data eip97ies_mrvl_data = {1816.version = EIP97IES_MRVL,1817};18181819static const struct safexcel_priv_data eip197b_mrvl_data = {1820.version = EIP197B_MRVL,1821};18221823static const struct safexcel_priv_data eip197d_mrvl_data = {1824.version = EIP197D_MRVL,1825};18261827static const struct safexcel_priv_data eip197_devbrd_data = {1828.version = EIP197_DEVBRD,1829};18301831static const struct safexcel_priv_data eip197c_mxl_data = {1832.version = EIP197C_MXL,1833.fw_little_endian = true,1834};18351836static const struct of_device_id safexcel_of_match_table[] = {1837{1838.compatible = "inside-secure,safexcel-eip97ies",1839.data = &eip97ies_mrvl_data,1840},1841{1842.compatible = "inside-secure,safexcel-eip197b",1843.data = &eip197b_mrvl_data,1844},1845{1846.compatible = "inside-secure,safexcel-eip197d",1847.data = &eip197d_mrvl_data,1848},1849{1850.compatible = "inside-secure,safexcel-eip197c-mxl",1851.data = &eip197c_mxl_data,1852},1853/* For backward compatibility and intended for generic use */1854{1855.compatible = "inside-secure,safexcel-eip97",1856.data = &eip97ies_mrvl_data,1857},1858{1859.compatible = "inside-secure,safexcel-eip197",1860.data = &eip197b_mrvl_data,1861},1862{},1863};18641865MODULE_DEVICE_TABLE(of, safexcel_of_match_table);18661867static struct platform_driver crypto_safexcel = {1868.probe = safexcel_probe,1869.remove = safexcel_remove,1870.driver = {1871.name = "crypto-safexcel",1872.of_match_table = safexcel_of_match_table,1873},1874};18751876/* PCIE devices - i.e. Inside Secure development boards */18771878static int safexcel_pci_probe(struct pci_dev *pdev,1879const struct pci_device_id *ent)1880{1881struct device *dev = &pdev->dev;1882struct safexcel_crypto_priv *priv;1883void __iomem *pciebase;1884int rc;1885u32 val;18861887dev_dbg(dev, "Probing PCIE device: vendor %04x, device %04x, subv %04x, subdev %04x, ctxt %lx\n",1888ent->vendor, ent->device, ent->subvendor,1889ent->subdevice, ent->driver_data);18901891priv = kzalloc(sizeof(*priv), GFP_KERNEL);1892if (!priv)1893return -ENOMEM;18941895priv->dev = dev;1896priv->data = (struct safexcel_priv_data *)ent->driver_data;18971898pci_set_drvdata(pdev, priv);18991900/* enable the device */1901rc = pcim_enable_device(pdev);1902if (rc) {1903dev_err(dev, "Failed to enable PCI device\n");1904return rc;1905}19061907/* take ownership of PCI BAR0 */1908rc = pcim_iomap_regions(pdev, 1, "crypto_safexcel");1909if (rc) {1910dev_err(dev, "Failed to map IO region for BAR0\n");1911return rc;1912}1913priv->base = pcim_iomap_table(pdev)[0];19141915if (priv->data->version == EIP197_DEVBRD) {1916dev_dbg(dev, "Device identified as FPGA based development board - applying HW reset\n");19171918rc = pcim_iomap_regions(pdev, 4, "crypto_safexcel");1919if (rc) {1920dev_err(dev, "Failed to map IO region for BAR4\n");1921return rc;1922}19231924pciebase = pcim_iomap_table(pdev)[2];1925val = readl(pciebase + EIP197_XLX_IRQ_BLOCK_ID_ADDR);1926if ((val >> 16) == EIP197_XLX_IRQ_BLOCK_ID_VALUE) {1927dev_dbg(dev, "Detected Xilinx PCIE IRQ block version %d, multiple MSI support enabled\n",1928(val & 0xff));19291930/* Setup MSI identity map mapping */1931writel(EIP197_XLX_USER_VECT_LUT0_IDENT,1932pciebase + EIP197_XLX_USER_VECT_LUT0_ADDR);1933writel(EIP197_XLX_USER_VECT_LUT1_IDENT,1934pciebase + EIP197_XLX_USER_VECT_LUT1_ADDR);1935writel(EIP197_XLX_USER_VECT_LUT2_IDENT,1936pciebase + EIP197_XLX_USER_VECT_LUT2_ADDR);1937writel(EIP197_XLX_USER_VECT_LUT3_IDENT,1938pciebase + EIP197_XLX_USER_VECT_LUT3_ADDR);19391940/* Enable all device interrupts */1941writel(GENMASK(31, 0),1942pciebase + EIP197_XLX_USER_INT_ENB_MSK);1943} else {1944dev_err(dev, "Unrecognised IRQ block identifier %x\n",1945val);1946return -ENODEV;1947}19481949/* HW reset FPGA dev board */1950/* assert reset */1951writel(1, priv->base + EIP197_XLX_GPIO_BASE);1952wmb(); /* maintain strict ordering for accesses here */1953/* deassert reset */1954writel(0, priv->base + EIP197_XLX_GPIO_BASE);1955wmb(); /* maintain strict ordering for accesses here */1956}19571958/* enable bus mastering */1959pci_set_master(pdev);19601961/* Generic EIP97/EIP197 device probing */1962rc = safexcel_probe_generic(pdev, priv, 1);1963return rc;1964}19651966static void safexcel_pci_remove(struct pci_dev *pdev)1967{1968struct safexcel_crypto_priv *priv = pci_get_drvdata(pdev);1969int i;19701971safexcel_unregister_algorithms(priv);19721973for (i = 0; i < priv->config.rings; i++)1974destroy_workqueue(priv->ring[i].workqueue);19751976safexcel_hw_reset_rings(priv);1977}19781979static const struct pci_device_id safexcel_pci_ids[] = {1980{1981PCI_DEVICE_SUB(PCI_VENDOR_ID_XILINX, 0x9038,19820x16ae, 0xc522),1983.driver_data = (kernel_ulong_t)&eip197_devbrd_data,1984},1985{},1986};19871988MODULE_DEVICE_TABLE(pci, safexcel_pci_ids);19891990static struct pci_driver safexcel_pci_driver = {1991.name = "crypto-safexcel",1992.id_table = safexcel_pci_ids,1993.probe = safexcel_pci_probe,1994.remove = safexcel_pci_remove,1995};19961997static int __init safexcel_init(void)1998{1999int ret;20002001/* Register PCI driver */2002ret = pci_register_driver(&safexcel_pci_driver);20032004/* Register platform driver */2005if (IS_ENABLED(CONFIG_OF) && !ret) {2006ret = platform_driver_register(&crypto_safexcel);2007if (ret)2008pci_unregister_driver(&safexcel_pci_driver);2009}20102011return ret;2012}20132014static void __exit safexcel_exit(void)2015{2016/* Unregister platform driver */2017if (IS_ENABLED(CONFIG_OF))2018platform_driver_unregister(&crypto_safexcel);20192020/* Unregister PCI driver if successfully registered before */2021pci_unregister_driver(&safexcel_pci_driver);2022}20232024module_init(safexcel_init);2025module_exit(safexcel_exit);20262027MODULE_AUTHOR("Antoine Tenart <[email protected]>");2028MODULE_AUTHOR("Ofer Heifetz <[email protected]>");2029MODULE_AUTHOR("Igal Liberman <[email protected]>");2030MODULE_DESCRIPTION("Support for SafeXcel cryptographic engines: EIP97 & EIP197");2031MODULE_LICENSE("GPL v2");2032MODULE_IMPORT_NS("CRYPTO_INTERNAL");20332034MODULE_FIRMWARE("ifpp.bin");2035MODULE_FIRMWARE("ipue.bin");2036MODULE_FIRMWARE("inside-secure/eip197b/ifpp.bin");2037MODULE_FIRMWARE("inside-secure/eip197b/ipue.bin");2038MODULE_FIRMWARE("inside-secure/eip197d/ifpp.bin");2039MODULE_FIRMWARE("inside-secure/eip197d/ipue.bin");2040MODULE_FIRMWARE("inside-secure/eip197_minifw/ifpp.bin");2041MODULE_FIRMWARE("inside-secure/eip197_minifw/ipue.bin");204220432044