Path: blob/master/drivers/crypto/hisilicon/zip/dae_main.c
29524 views
// SPDX-License-Identifier: GPL-2.01/* Copyright (c) 2024 HiSilicon Limited. */23#include <linux/bitops.h>4#include <linux/io.h>5#include <linux/uacce.h>6#include "zip.h"78/* memory */9#define DAE_MEM_START_OFFSET 0x33104010#define DAE_MEM_DONE_OFFSET 0x33104411#define DAE_MEM_START_MASK 0x112#define DAE_MEM_DONE_MASK 0x113#define DAE_REG_RD_INTVRL_US 1014#define DAE_REG_RD_TMOUT_US USEC_PER_SEC1516#define DAE_ALG_NAME "hashagg"17#define DAE_V5_ALG_NAME "hashagg\nudma\nhashjoin\ngather"1819/* error */20#define DAE_AXI_CFG_OFFSET 0x33100021#define DAE_AXI_SHUTDOWN_MASK (BIT(0) | BIT(5))22#define DAE_ERR_SOURCE_OFFSET 0x331C8423#define DAE_ERR_STATUS_OFFSET 0x331C8824#define DAE_ERR_CE_OFFSET 0x331CA025#define DAE_ERR_CE_MASK BIT(3)26#define DAE_ERR_NFE_OFFSET 0x331CA427#define DAE_ERR_NFE_MASK 0x1728#define DAE_ERR_FE_OFFSET 0x331CA829#define DAE_ERR_FE_MASK 030#define DAE_ECC_MBIT_MASK BIT(2)31#define DAE_ECC_INFO_OFFSET 0x33400C32#define DAE_ERR_SHUTDOWN_OFFSET 0x331CAC33#define DAE_ERR_SHUTDOWN_MASK 0x1734#define DAE_ERR_ENABLE_OFFSET 0x331C8035#define DAE_ERR_ENABLE_MASK (DAE_ERR_FE_MASK | DAE_ERR_NFE_MASK | DAE_ERR_CE_MASK)36#define DAE_AM_CTRL_GLOBAL_OFFSET 0x33000037#define DAE_AM_RETURN_OFFSET 0x33015038#define DAE_AM_RETURN_MASK 0x339#define DAE_AXI_CFG_OFFSET 0x33100040#define DAE_AXI_SHUTDOWN_EN_MASK (BIT(0) | BIT(5))4142struct hisi_dae_hw_error {43u32 int_msk;44const char *msg;45};4647static const struct hisi_dae_hw_error dae_hw_error[] = {48{ .int_msk = BIT(0), .msg = "dae_axi_bus_err" },49{ .int_msk = BIT(1), .msg = "dae_axi_poison_err" },50{ .int_msk = BIT(2), .msg = "dae_ecc_2bit_err" },51{ .int_msk = BIT(3), .msg = "dae_ecc_1bit_err" },52{ .int_msk = BIT(4), .msg = "dae_fsm_hbeat_err" },53};5455static inline bool dae_is_support(struct hisi_qm *qm)56{57if (test_bit(QM_SUPPORT_DAE, &qm->caps))58return true;5960return false;61}6263int hisi_dae_set_user_domain(struct hisi_qm *qm)64{65u32 val;66int ret;6768if (!dae_is_support(qm))69return 0;7071val = readl(qm->io_base + DAE_MEM_START_OFFSET);72val |= DAE_MEM_START_MASK;73writel(val, qm->io_base + DAE_MEM_START_OFFSET);74ret = readl_relaxed_poll_timeout(qm->io_base + DAE_MEM_DONE_OFFSET, val,75val & DAE_MEM_DONE_MASK,76DAE_REG_RD_INTVRL_US, DAE_REG_RD_TMOUT_US);77if (ret)78pci_err(qm->pdev, "failed to init dae memory!\n");7980return ret;81}8283int hisi_dae_set_alg(struct hisi_qm *qm)84{85const char *alg_name;86size_t len;8788if (!dae_is_support(qm))89return 0;9091if (!qm->uacce)92return 0;9394if (qm->ver >= QM_HW_V5)95alg_name = DAE_V5_ALG_NAME;96else97alg_name = DAE_ALG_NAME;9899len = strlen(qm->uacce->algs);100/* A line break may be required */101if (len + strlen(alg_name) + 1 >= QM_DEV_ALG_MAX_LEN) {102pci_err(qm->pdev, "algorithm name is too long!\n");103return -EINVAL;104}105106if (len)107strcat((char *)qm->uacce->algs, "\n");108109strcat((char *)qm->uacce->algs, alg_name);110111return 0;112}113114static void hisi_dae_master_ooo_ctrl(struct hisi_qm *qm, bool enable)115{116u32 axi_val, err_val;117118axi_val = readl(qm->io_base + DAE_AXI_CFG_OFFSET);119if (enable) {120axi_val |= DAE_AXI_SHUTDOWN_MASK;121err_val = DAE_ERR_SHUTDOWN_MASK;122} else {123axi_val &= ~DAE_AXI_SHUTDOWN_MASK;124err_val = 0;125}126127writel(axi_val, qm->io_base + DAE_AXI_CFG_OFFSET);128writel(err_val, qm->io_base + DAE_ERR_SHUTDOWN_OFFSET);129}130131void hisi_dae_hw_error_enable(struct hisi_qm *qm)132{133if (!dae_is_support(qm))134return;135136/* clear dae hw error source if having */137writel(DAE_ERR_ENABLE_MASK, qm->io_base + DAE_ERR_SOURCE_OFFSET);138139/* configure error type */140writel(DAE_ERR_CE_MASK, qm->io_base + DAE_ERR_CE_OFFSET);141writel(DAE_ERR_NFE_MASK, qm->io_base + DAE_ERR_NFE_OFFSET);142writel(DAE_ERR_FE_MASK, qm->io_base + DAE_ERR_FE_OFFSET);143144hisi_dae_master_ooo_ctrl(qm, true);145146/* enable dae hw error interrupts */147writel(DAE_ERR_ENABLE_MASK, qm->io_base + DAE_ERR_ENABLE_OFFSET);148}149150void hisi_dae_hw_error_disable(struct hisi_qm *qm)151{152if (!dae_is_support(qm))153return;154155writel(0, qm->io_base + DAE_ERR_ENABLE_OFFSET);156hisi_dae_master_ooo_ctrl(qm, false);157}158159static u32 hisi_dae_get_hw_err_status(struct hisi_qm *qm)160{161return readl(qm->io_base + DAE_ERR_STATUS_OFFSET);162}163164static void hisi_dae_clear_hw_err_status(struct hisi_qm *qm, u32 err_sts)165{166if (!dae_is_support(qm))167return;168169writel(err_sts, qm->io_base + DAE_ERR_SOURCE_OFFSET);170}171172static void hisi_dae_disable_error_report(struct hisi_qm *qm, u32 err_type)173{174writel(DAE_ERR_NFE_MASK & (~err_type), qm->io_base + DAE_ERR_NFE_OFFSET);175}176177static void hisi_dae_enable_error_report(struct hisi_qm *qm)178{179writel(DAE_ERR_CE_MASK, qm->io_base + DAE_ERR_CE_OFFSET);180writel(DAE_ERR_NFE_MASK, qm->io_base + DAE_ERR_NFE_OFFSET);181}182183static void hisi_dae_log_hw_error(struct hisi_qm *qm, u32 err_type)184{185const struct hisi_dae_hw_error *err = dae_hw_error;186struct device *dev = &qm->pdev->dev;187u32 ecc_info;188size_t i;189190for (i = 0; i < ARRAY_SIZE(dae_hw_error); i++) {191err = &dae_hw_error[i];192if (!(err->int_msk & err_type))193continue;194195dev_err(dev, "%s [error status=0x%x] found\n",196err->msg, err->int_msk);197198if (err->int_msk & DAE_ECC_MBIT_MASK) {199ecc_info = readl(qm->io_base + DAE_ECC_INFO_OFFSET);200dev_err(dev, "dae multi ecc sram info 0x%x\n", ecc_info);201}202}203}204205enum acc_err_result hisi_dae_get_err_result(struct hisi_qm *qm)206{207u32 err_status;208209if (!dae_is_support(qm))210return ACC_ERR_NONE;211212err_status = hisi_dae_get_hw_err_status(qm);213if (!err_status)214return ACC_ERR_NONE;215216hisi_dae_log_hw_error(qm, err_status);217218if (err_status & DAE_ERR_NFE_MASK) {219/* Disable the same error reporting until device is recovered. */220hisi_dae_disable_error_report(qm, err_status);221return ACC_ERR_NEED_RESET;222}223hisi_dae_clear_hw_err_status(qm, err_status);224/* Avoid firmware disable error report, re-enable. */225hisi_dae_enable_error_report(qm);226227return ACC_ERR_RECOVERED;228}229230bool hisi_dae_dev_is_abnormal(struct hisi_qm *qm)231{232u32 err_status;233234if (!dae_is_support(qm))235return false;236237err_status = hisi_dae_get_hw_err_status(qm);238if (err_status & DAE_ERR_NFE_MASK)239return true;240241return false;242}243244int hisi_dae_close_axi_master_ooo(struct hisi_qm *qm)245{246u32 val;247int ret;248249if (!dae_is_support(qm))250return 0;251252val = readl(qm->io_base + DAE_AM_CTRL_GLOBAL_OFFSET);253val |= BIT(0);254writel(val, qm->io_base + DAE_AM_CTRL_GLOBAL_OFFSET);255256ret = readl_relaxed_poll_timeout(qm->io_base + DAE_AM_RETURN_OFFSET,257val, (val == DAE_AM_RETURN_MASK),258DAE_REG_RD_INTVRL_US, DAE_REG_RD_TMOUT_US);259if (ret)260dev_err(&qm->pdev->dev, "failed to close dae axi ooo!\n");261262return ret;263}264265void hisi_dae_open_axi_master_ooo(struct hisi_qm *qm)266{267u32 val;268269if (!dae_is_support(qm))270return;271272val = readl(qm->io_base + DAE_AXI_CFG_OFFSET);273274writel(val & ~DAE_AXI_SHUTDOWN_EN_MASK, qm->io_base + DAE_AXI_CFG_OFFSET);275writel(val | DAE_AXI_SHUTDOWN_EN_MASK, qm->io_base + DAE_AXI_CFG_OFFSET);276}277278279