From patchwork Tue Jan 14 09:55:25 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qunqin Zhao X-Patchwork-Id: 13938564 X-Patchwork-Delegate: herbert@gondor.apana.org.au Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B84A81ADC6B; Tue, 14 Jan 2025 09:56:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736848574; cv=none; b=UBfn9JscmUG1MjmWtMlfzYscjY+4wlrL2nu2AoZKvLcZaLP8Lg/oeXPMdarsYVwtpfVvtz3lrB1JlrdQRwJfMWPg74bjhfXfBVaEJuwQseTzdW+WhcMzKdozJG0+kej7XxcWs9gNtkjmdMH2cY+yyV8KPkXM60rVNHsIMTcZuJQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736848574; c=relaxed/simple; bh=xJ+hHUA+ITRYxUhudy2FojjqJHoJNSeJZoxF1hvTXek=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=F5ppCFmUhK+CF5B5qIk6heOXafv/Rac5F2P0xh6witsgaXhF20sQDfOOaSXPt9gANnzqyABbnrImgUQ9zagKQegy/8L9+BNjK0FLHXbjVHLaGcNDg171XWWBsD+ePeMwagJKoyv74QZlwhDdIRDXLQ6BGpyBn1xIu+NSpqQ4sJE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [10.40.54.90]) by gateway (Coremail) with SMTP id _____8CxCeG5NIZn5x9jAA--.63318S3; Tue, 14 Jan 2025 17:56:09 +0800 (CST) Received: from localhost.localdomain (unknown [10.40.54.90]) by front1 (Coremail) with SMTP id qMiowMBxReSoNIZnct0hAA--.2343S3; Tue, 14 Jan 2025 17:56:02 +0800 (CST) From: Qunqin Zhao To: lee@kernel.org, herbert@gondor.apana.org.au, gregkh@linuxfoundation.org Cc: linux-kernel@vger.kernel.org, loongarch@lists.linux.dev, davem@davemloft.net, linux-crypto@vger.kernel.org, arnd@arndb.de, derek.kiernan@amd.com, dragan.cvetic@amd.com, Qunqin Zhao , Yinggang Gu Subject: [PATCH v1 1/3] mfd: Add support for Loongson Security Module Date: Tue, 14 Jan 2025 17:55:25 +0800 Message-Id: <20250114095527.23722-2-zhaoqunqin@loongson.cn> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20250114095527.23722-1-zhaoqunqin@loongson.cn> References: <20250114095527.23722-1-zhaoqunqin@loongson.cn> Precedence: bulk X-Mailing-List: linux-crypto@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMBxReSoNIZnct0hAA--.2343S3 X-CM-SenderInfo: 52kd01pxqtx0o6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj9fXoW3Zr17JF1DAw1fGF1xtw1xXrc_yoW8GrWrXo WxZFsxZw18Jrn2yrW09r4rtrWfZr9Y9a4Yyw45Z39ru3WUtFn8KFW8Ww43Wr13ZF4Fyry5 u34aqr48uF43Crn5l-sFpf9Il3svdjkaLaAFLSUrUUUUeb8apTn2vfkv8UJUUUU8wcxFpf 9Il3svdxBIdaVrn0xqx4xG64xvF2IEw4CE5I8CrVC2j2Jv73VFW2AGmfu7bjvjm3AaLaJ3 UjIYCTnIWjp_UUUYG7kC6x804xWl14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI 8IcIk0rVWrJVCq3wAFIxvE14AKwVWUXVWUAwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xG Y2AK021l84ACjcxK6xIIjxv20xvE14v26ryj6F1UM28EF7xvwVC0I7IYx2IY6xkF7I0E14 v26r4j6F4UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6rxl6s0DM2kKe7AKxVWUAVWUtwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07AIYI kI8VC2zVCFFI0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWUtVWr XwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7VAKI4 8JMxkF7I0En4kS14v26r126r1DMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j 6r4UMxCIbckI1I0E14v26r126r1DMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwV AFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUtVW8ZwCIc40Y0x0EwIxGrwCI42IY6xIIjxv2 0xvE14v26r4j6ryUMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwCI42IY6xAIw20EY4 v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AK xVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7IU8_gA5UUUUU== This driver supports Loongson Security Module, which provides the control for it's hardware encryption acceleration child devices. Co-developed-by: Yinggang Gu Signed-off-by: Yinggang Gu Signed-off-by: Qunqin Zhao --- MAINTAINERS | 7 + drivers/mfd/Kconfig | 9 + drivers/mfd/Makefile | 2 + drivers/mfd/ls6000se.c | 373 +++++++++++++++++++++++++++++++++++ include/linux/mfd/ls6000se.h | 75 +++++++ 5 files changed, 466 insertions(+) create mode 100644 drivers/mfd/ls6000se.c create mode 100644 include/linux/mfd/ls6000se.h diff --git a/MAINTAINERS b/MAINTAINERS index 219b6709b6..3c8a9d6198 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13494,6 +13494,13 @@ S: Maintained F: Documentation/devicetree/bindings/i2c/loongson,ls2x-i2c.yaml F: drivers/i2c/busses/i2c-ls2x.c +LOONGSON SECURITY MODULE DRIVER +M: Qunqin Zhao +L: loongarch@lists.linux.dev +S: Maintained +F: drivers/mfd/ls6000se.c +F: include/linux/mfd/ls6000se.h + LOONGSON-2 SOC SERIES CLOCK DRIVER M: Yinbo Zhu L: linux-clk@vger.kernel.org diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 6b0682af6e..a17554d64e 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -2438,6 +2438,15 @@ config MFD_UPBOARD_FPGA To compile this driver as a module, choose M here: the module will be called upboard-fpga. +config MFD_LS6000SE + tristate "Loongson Security Module Interface" + depends on LOONGARCH && ACPI + select MFD_CORE + help + The Loongson security module provides the control for hardware + encryption acceleration devices. Each device uses at least one + channel to interact with security module, and each channel may + have its own buffer provided by security module. endmenu endif diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 9220eaf7cf..9556de7715 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -294,3 +294,5 @@ obj-$(CONFIG_MFD_RSMU_I2C) += rsmu_i2c.o rsmu_core.o obj-$(CONFIG_MFD_RSMU_SPI) += rsmu_spi.o rsmu_core.o obj-$(CONFIG_MFD_UPBOARD_FPGA) += upboard-fpga.o + +obj-$(CONFIG_MFD_LS6000SE) += ls6000se.o diff --git a/drivers/mfd/ls6000se.c b/drivers/mfd/ls6000se.c new file mode 100644 index 0000000000..42ff7f6285 --- /dev/null +++ b/drivers/mfd/ls6000se.c @@ -0,0 +1,373 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (C) 2025 Loongson Technology Corporation Limited */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * The Loongson Security Module provides the control for hardware + * encryption acceleration child devices. The SE framework is + * shown as follows: + * + * +------------+ + * | CPU | + * +------------+ + * ^ ^ + * DMA | | IRQ + * v v + * +-----------------------------------+ + * | Loongson Security Module | + * +-----------------------------------+ + * ^ ^ + * channel1 | channel2 | + * v v + * +-----------+ +----------+ + * | sub-dev1 | | sub-dev2 | ..... Max sub-dev31 + * +-----------+ +----------+ + * + * The CPU cannot directly communicate with SE's sub devices, + * but sends commands to SE, which processes the commands and + * sends them to the corresponding sub devices. + */ + +struct loongson_se { + void __iomem *base; + u32 version; + spinlock_t dev_lock; + struct completion cmd_completion; + + /* dma memory */ + void *mem_base; + int mem_map_pages; + unsigned long *mem_map; + + /* channel */ + struct mutex ch_init_lock; + struct lsse_ch chs[SE_CH_MAX]; +}; + +union se_request { + u32 info[8]; + struct se_cmd { + u32 cmd; + u32 info[7]; + } req; + struct se_res { + u32 cmd; + u32 cmd_ret; + u32 info[6]; + } res; +}; + +static inline u32 se_readl(struct loongson_se *se, u32 off) +{ + return readl(se->base + off); +} + +static inline void se_writel(struct loongson_se *se, u32 val, u32 off) +{ + writel(val, se->base + off); +} + +static void se_enable_int_locked(struct loongson_se *se, u32 int_bit) +{ + u32 tmp; + + tmp = se_readl(se, SE_S2LINT_EN); + tmp |= int_bit; + se_writel(se, tmp, SE_S2LINT_EN); +} + +static void se_disable_int(struct loongson_se *se, u32 int_bit) +{ + unsigned long flag; + u32 tmp; + + spin_lock_irqsave(&se->dev_lock, flag); + + tmp = se_readl(se, SE_S2LINT_EN); + tmp &= ~(int_bit); + se_writel(se, tmp, SE_S2LINT_EN); + + spin_unlock_irqrestore(&se->dev_lock, flag); +} + +static int se_poll(struct loongson_se *se, u32 int_bit) +{ + u32 status; + int err; + + spin_lock_irq(&se->dev_lock); + + se_enable_int_locked(se, int_bit); + se_writel(se, int_bit, SE_L2SINT_SET); + err = readl_relaxed_poll_timeout_atomic(se->base + SE_L2SINT_STAT, status, + !(status & int_bit), 1, 10000); + + spin_unlock_irq(&se->dev_lock); + + return err; +} + +static int se_send_requeset(struct loongson_se *se, union se_request *req) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(req->info); i++) + se_writel(se, req->info[i], SE_DATA_S + i * 4); + + return se_poll(se, SE_INT_SETUP); +} + +/* + * Called by SE's child device driver. + * Send a request to the corresponding device. + */ +int se_send_ch_requeset(struct lsse_ch *ch) +{ + return se_poll(ch->se, ch->int_bit); +} +EXPORT_SYMBOL_GPL(se_send_ch_requeset); + +static int se_get_res(struct loongson_se *se, u32 cmd, union se_request *res) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(res->info); i++) + res->info[i] = se_readl(se, SE_DATA_L + i * 4); + + if (res->res.cmd != cmd) + return -EFAULT; + + return 0; +} + +static int se_send_genl_cmd(struct loongson_se *se, union se_request *req) +{ + int err; + + err = se_send_requeset(se, req); + if (err) + return err; + + if (!wait_for_completion_timeout(&se->cmd_completion, HZ)) + return -ETIME; + + return se_get_res(se, req->req.cmd, req); +} + +static int se_set_msg(struct lsse_ch *ch) +{ + struct loongson_se *se = ch->se; + union se_request req; + + req.req.cmd = SE_CMD_SETMSG; + req.req.info[0] = ch->id; + req.req.info[1] = ch->smsg - se->mem_base; + req.req.info[2] = ch->msg_size; + + return se_send_genl_cmd(se, &req); +} + +static irqreturn_t se_irq(int irq, void *dev_id) +{ + struct loongson_se *se = (struct loongson_se *)dev_id; + struct lsse_ch *ch; + u32 int_status; + int id; + + int_status = se_readl(se, SE_S2LINT_STAT); + se_disable_int(se, int_status); + if (int_status & SE_INT_SETUP) { + complete(&se->cmd_completion); + int_status &= ~SE_INT_SETUP; + se_writel(se, SE_INT_SETUP, SE_S2LINT_CL); + } + + while (int_status) { + id = __ffs(int_status); + + ch = &se->chs[id]; + if (ch->complete) + ch->complete(ch); + int_status &= ~BIT(id); + se_writel(se, BIT(id), SE_S2LINT_CL); + } + + return IRQ_HANDLED; +} + +static int se_init_hw(struct loongson_se *se, dma_addr_t addr, int size) +{ + union se_request req; + int err; + + /* Start engine */ + req.req.cmd = SE_CMD_START; + err = se_send_genl_cmd(se, &req); + if (err) + return err; + + /* Get Version */ + req.req.cmd = SE_CMD_GETVER; + err = se_send_genl_cmd(se, &req); + if (err) + return err; + se->version = req.res.info[0]; + + /* Setup dma memory */ + req.req.cmd = SE_CMD_SETBUF; + req.req.info[0] = addr & 0xffffffff; + req.req.info[1] = addr >> 32; + + return se_send_genl_cmd(se, &req); +} + +/* + * se_init_ch() - Init the channel used by child device. + * + * Allocate dma memory as agreed upon with SE on SE probe, + * and register the callback function when the data processing + * in this channel is completed. + */ +struct lsse_ch *se_init_ch(struct device *dev, int id, int data_size, int msg_size, + void *priv, void (*complete)(struct lsse_ch *se_ch)) +{ + struct loongson_se *se = dev_get_drvdata(dev); + struct lsse_ch *ch; + int data_first, data_nr; + int msg_first, msg_nr; + + mutex_lock(&se->ch_init_lock); + + ch = &se->chs[id]; + ch->se = se; + ch->id = id; + ch->int_bit = BIT(id); + + data_nr = round_up(data_size, PAGE_SIZE) / PAGE_SIZE; + data_first = bitmap_find_next_zero_area(se->mem_map, se->mem_map_pages, + 0, data_nr, 0); + if (data_first >= se->mem_map_pages) { + ch = NULL; + goto out_unlock; + } + + bitmap_set(se->mem_map, data_first, data_nr); + ch->off = data_first * PAGE_SIZE; + ch->data_buffer = se->mem_base + ch->off; + ch->data_size = data_size; + + msg_nr = round_up(msg_size, PAGE_SIZE) / PAGE_SIZE; + msg_first = bitmap_find_next_zero_area(se->mem_map, se->mem_map_pages, + 0, msg_nr, 0); + if (msg_first >= se->mem_map_pages) { + ch = NULL; + goto out_unlock; + } + + bitmap_set(se->mem_map, msg_first, msg_nr); + ch->smsg = se->mem_base + msg_first * PAGE_SIZE; + ch->rmsg = ch->smsg + msg_size / 2; + ch->msg_size = msg_size; + ch->complete = complete; + ch->priv = priv; + ch->version = se->version; + + if (se_set_msg(ch)) + ch = NULL; + +out_unlock: + mutex_unlock(&se->ch_init_lock); + + return ch; +} +EXPORT_SYMBOL_GPL(se_init_ch); + +static const struct mfd_cell se_devs[] = { + { .name = "ls6000se-sdf" }, + { .name = "ls6000se-rng" }, +}; + +static int loongson_se_probe(struct platform_device *pdev) +{ + struct loongson_se *se; + struct device *dev = &pdev->dev; + int nr_irq, irq, err, size; + dma_addr_t paddr; + + se = devm_kmalloc(dev, sizeof(*se), GFP_KERNEL); + if (!se) + return -ENOMEM; + dev_set_drvdata(dev, se); + init_completion(&se->cmd_completion); + spin_lock_init(&se->dev_lock); + mutex_init(&se->ch_init_lock); + dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); + if (device_property_read_u32(dev, "dmam_size", &size)) + return -ENODEV; + size = roundup_pow_of_two(size); + se->mem_base = dmam_alloc_coherent(dev, size, &paddr, GFP_KERNEL); + if (!se->mem_base) + return -ENOMEM; + se->mem_map_pages = size / PAGE_SIZE; + se->mem_map = devm_bitmap_zalloc(dev, se->mem_map_pages, GFP_KERNEL); + if (!se->mem_map) + return -ENOMEM; + + se->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(se->base)) + return PTR_ERR(se->base); + + nr_irq = platform_irq_count(pdev); + if (nr_irq <= 0) + return -ENODEV; + while (nr_irq) { + irq = platform_get_irq(pdev, --nr_irq); + /* Use the same interrupt handler address. + * Determine which irq it is accroding + * SE_S2LINT_STAT register. + */ + err = devm_request_irq(dev, irq, se_irq, 0, "ls6000se", se); + if (err) + dev_err(dev, "failed to request irq: %d\n", irq); + } + + err = se_init_hw(se, paddr, size); + if (err) + return err; + + return devm_mfd_add_devices(dev, 0, se_devs, ARRAY_SIZE(se_devs), + NULL, 0, NULL); +} + +static const struct acpi_device_id loongson_se_acpi_match[] = { + {"LOON0011", 0}, + {} +}; +MODULE_DEVICE_TABLE(acpi, loongson_se_acpi_match); + +static struct platform_driver loongson_se_driver = { + .probe = loongson_se_probe, + .driver = { + .name = "ls6000se", + .acpi_match_table = loongson_se_acpi_match, + }, +}; +module_platform_driver(loongson_se_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Yinggang Gu "); +MODULE_AUTHOR("Qunqin Zhao "); +MODULE_DESCRIPTION("Loongson Security Module driver"); diff --git a/include/linux/mfd/ls6000se.h b/include/linux/mfd/ls6000se.h new file mode 100644 index 0000000000..f70e9f196a --- /dev/null +++ b/include/linux/mfd/ls6000se.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (C) 2025 Loongson Technology Corporation Limited */ + +#ifndef __LOONGSON_SE_H__ +#define __LOONGSON_SE_H__ + +#define SE_DATA_S 0x0 +#define SE_DATA_L 0x20 +#define SE_S2LINT_STAT 0x88 +#define SE_S2LINT_EN 0x8c +#define SE_S2LINT_SET 0x90 +#define SE_S2LINT_CL 0x94 +#define SE_L2SINT_STAT 0x98 +#define SE_L2SINT_EN 0x9c +#define SE_L2SINT_SET 0xa0 +#define SE_L2SINT_CL 0xa4 + +/* INT bit definition */ +#define SE_INT_SETUP BIT(0) +#define SE_INT_TPM BIT(5) + +#define SE_CMD_START 0x0 +#define SE_CMD_STOP 0x1 +#define SE_CMD_GETVER 0x2 +#define SE_CMD_SETBUF 0x3 +#define SE_CMD_SETMSG 0x4 + +#define SE_CMD_RNG 0x100 +#define SE_CMD_SM2_SIGN 0x200 +#define SE_CMD_SM2_VSIGN 0x201 +#define SE_CMD_SM3_DIGEST 0x300 +#define SE_CMD_SM3_UPDATE 0x301 +#define SE_CMD_SM3_FINISH 0x302 +#define SE_CMD_SM4_ECB_ENCRY 0x400 +#define SE_CMD_SM4_ECB_DECRY 0x401 +#define SE_CMD_SM4_CBC_ENCRY 0x402 +#define SE_CMD_SM4_CBC_DECRY 0x403 +#define SE_CMD_SM4_CTR 0x404 +#define SE_CMD_TPM 0x500 +#define SE_CMD_ZUC_INIT_READ 0x600 +#define SE_CMD_ZUC_READ 0x601 +#define SE_CMD_SDF 0x700 + +#define SE_CH_MAX 32 +#define SE_CH_RNG 1 +#define SE_CH_SM2 2 +#define SE_CH_SM3 3 +#define SE_CH_SM4 4 +#define SE_CH_TPM 5 +#define SE_CH_ZUC 6 +#define SE_CH_SDF 7 + +struct lsse_ch { + struct loongson_se *se; + void *priv; + u32 version; + u32 id; + u32 int_bit; + + void *smsg; + void *rmsg; + int msg_size; + + void *data_buffer; + int data_size; + u32 off; + + void (*complete)(struct lsse_ch *se_ch); +}; + +struct lsse_ch *se_init_ch(struct device *dev, int id, int data_size, int msg_size, + void *priv, void (*complete)(struct lsse_ch *se_ch)); +int se_send_ch_requeset(struct lsse_ch *ch); + +#endif From patchwork Tue Jan 14 09:55:26 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qunqin Zhao X-Patchwork-Id: 13938565 X-Patchwork-Delegate: herbert@gondor.apana.org.au Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id CBBE51ADC8C; Tue, 14 Jan 2025 09:56:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736848593; cv=none; b=WkMn3pA+ji6aOujweVc5FTT+x9zWNwr4z36sgxKhXMqPRA1UAXxHiElxyOKvo1bBlBGhTT/dO56GSEdn6fkhumbpygzyricsjBe2gLlLGTFx0iilgHRcJCxF2ftIlmPI44fqrhTQMECMOCDZlcfms6irzksOK726SNCdUkQZtd4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736848593; c=relaxed/simple; bh=jTuh1Ev5IZPcdkNdsy2IZdo8ZZhkoLL3jWd/jM68nnw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=FaH3mjWoebyHkdc4UMBLX9Cfte6VeU7gSZwYwtcfuy2H/fGzXmSrOPRpv+BGacbAMwRd9OVnCw7nnqL7DW+wmMWws5xE5KZkcb2xjpdv96JqGiqgGqH1g10znCyrfbKPm3woDiSCNvgeUYfCz18Dpvt4hpbk2LT/pJJoq/U2qHw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [10.40.54.90]) by gateway (Coremail) with SMTP id _____8CxieDJNIZn_h9jAA--.62592S3; Tue, 14 Jan 2025 17:56:25 +0800 (CST) Received: from localhost.localdomain (unknown [10.40.54.90]) by front1 (Coremail) with SMTP id qMiowMBxReSoNIZnct0hAA--.2343S4; Tue, 14 Jan 2025 17:56:10 +0800 (CST) From: Qunqin Zhao To: lee@kernel.org, herbert@gondor.apana.org.au, gregkh@linuxfoundation.org Cc: linux-kernel@vger.kernel.org, loongarch@lists.linux.dev, davem@davemloft.net, linux-crypto@vger.kernel.org, arnd@arndb.de, derek.kiernan@amd.com, dragan.cvetic@amd.com, Qunqin Zhao , Yinggang Gu Subject: [PATCH v1 2/3] crypto: loongson - add Loongson RNG driver support Date: Tue, 14 Jan 2025 17:55:26 +0800 Message-Id: <20250114095527.23722-3-zhaoqunqin@loongson.cn> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20250114095527.23722-1-zhaoqunqin@loongson.cn> References: <20250114095527.23722-1-zhaoqunqin@loongson.cn> Precedence: bulk X-Mailing-List: linux-crypto@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMBxReSoNIZnct0hAA--.2343S4 X-CM-SenderInfo: 52kd01pxqtx0o6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj93XoW3Jr15CFWktF1kZFWxCFyfGrX_yoW3JF1rpF 4Fk3y8CrWUGFsrKFZ5JrWrCFW3Z3sa9a4agFW7Gwn09r92yFyDXayfAFyUAFWDAFWxWrWa gFZa9F4UKa1UJ3gCm3ZEXasCq-sJn29KB7ZKAUJUUUUf529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUB0b4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Ar0_tr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr0_Cr1l84ACjcxK6I8E87Iv67AKxVW0oVCq3wA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_ GcCE3s1ln4kS14v26r126r1DM2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6xkI12xvs2 x26I8E6xACxx1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r1q6rW5 McIj6I8E87Iv67AKxVW8JVWxJwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr4 1lc7CjxVAaw2AFwI0_JF0_Jw1l42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_ Gr1l4IxYO2xFxVAFwI0_JF0_Jw1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67 AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8I cVAFwI0_Xr0_Ar1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4j6F4UMIIF0xvE42xK8VAvwI 8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v2 6r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjxU4Xo7DUUUU Loongson's Random Number Generator is found inside Loongson 6000SE. Co-developed-by: Yinggang Gu Signed-off-by: Yinggang Gu Signed-off-by: Qunqin Zhao --- MAINTAINERS | 6 + drivers/crypto/Kconfig | 1 + drivers/crypto/Makefile | 1 + drivers/crypto/loongson/Kconfig | 6 + drivers/crypto/loongson/Makefile | 2 + drivers/crypto/loongson/ls6000se-rng.c | 190 +++++++++++++++++++++++++ 6 files changed, 206 insertions(+) create mode 100644 drivers/crypto/loongson/Kconfig create mode 100644 drivers/crypto/loongson/Makefile create mode 100644 drivers/crypto/loongson/ls6000se-rng.c diff --git a/MAINTAINERS b/MAINTAINERS index 3c8a9d6198..e65a7f4ea4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13480,6 +13480,12 @@ S: Maintained F: Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml F: drivers/gpio/gpio-loongson-64bit.c +LOONGSON CRYPTO DRIVER +M: Qunqin Zhao +L: linux-crypto@vger.kernel.org +S: Maintained +F: drivers/crypto/loongson/ + LOONGSON-2 APB DMA DRIVER M: Binbin Zhou L: dmaengine@vger.kernel.org diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 0a9cdd31cb..80caf6158e 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -872,5 +872,6 @@ config CRYPTO_DEV_SA2UL source "drivers/crypto/aspeed/Kconfig" source "drivers/crypto/starfive/Kconfig" +source "drivers/crypto/loongson/Kconfig" endif # CRYPTO_HW diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index ad4ccef67d..a80e2586f7 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -52,3 +52,4 @@ obj-y += hisilicon/ obj-$(CONFIG_CRYPTO_DEV_AMLOGIC_GXL) += amlogic/ obj-y += intel/ obj-y += starfive/ +obj-y += loongson/ diff --git a/drivers/crypto/loongson/Kconfig b/drivers/crypto/loongson/Kconfig new file mode 100644 index 0000000000..2b0b8b3241 --- /dev/null +++ b/drivers/crypto/loongson/Kconfig @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +config CRYPTO_DEV_LS6000SE_RNG + tristate "Support for Loongson 6000SE RNG Driver" + depends on MFD_LS6000SE + help + Support for Loongson 6000SE RNG Driver. diff --git a/drivers/crypto/loongson/Makefile b/drivers/crypto/loongson/Makefile new file mode 100644 index 0000000000..17b0fa89e9 --- /dev/null +++ b/drivers/crypto/loongson/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_CRYPTO_DEV_LS6000SE_RNG) += ls6000se-rng.o diff --git a/drivers/crypto/loongson/ls6000se-rng.c b/drivers/crypto/loongson/ls6000se-rng.c new file mode 100644 index 0000000000..b366475782 --- /dev/null +++ b/drivers/crypto/loongson/ls6000se-rng.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019 HiSilicon Limited. */ +/* Copyright (c) 2025 Loongson Technology Corporation Limited. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct lsrng_list { + struct mutex lock; + struct list_head list; + int is_init; +}; + +struct lsrng { + bool is_used; + struct lsse_ch *se_ch; + struct list_head list; + struct completion rng_completion; +}; + +struct lsrng_ctx { + struct lsrng *rng; +}; + +struct rng_msg { + u32 cmd; + union { + u32 len; + u32 ret; + } u; + u32 resved; + u32 out_off; + u32 pad[4]; +}; + +static atomic_t rng_active_devs; +static struct lsrng_list rng_devices; + +static void lsrng_complete(struct lsse_ch *ch) +{ + struct lsrng *rng = (struct lsrng *)ch->priv; + + complete(&rng->rng_completion); +} + +static int lsrng_generate(struct crypto_rng *tfm, const u8 *src, + unsigned int slen, u8 *dstn, unsigned int dlen) +{ + struct lsrng_ctx *ctx = crypto_rng_ctx(tfm); + struct lsrng *rng = ctx->rng; + struct rng_msg *msg; + int err, len; + + do { + len = min(dlen, PAGE_SIZE); + msg = rng->se_ch->smsg; + msg->u.len = len; + err = se_send_ch_requeset(rng->se_ch); + if (err) + return err; + + wait_for_completion_interruptible(&rng->rng_completion); + + msg = rng->se_ch->rmsg; + if (msg->u.ret) + return -EFAULT; + + memcpy(dstn, rng->se_ch->data_buffer, len); + dlen -= len; + dstn += len; + } while (dlen > 0); + + return 0; +} + +static int lsrng_init(struct crypto_tfm *tfm) +{ + struct lsrng_ctx *ctx = crypto_tfm_ctx(tfm); + struct lsrng *rng; + int ret = -EBUSY; + + mutex_lock(&rng_devices.lock); + list_for_each_entry(rng, &rng_devices.list, list) { + if (!rng->is_used) { + rng->is_used = true; + ctx->rng = rng; + ret = 0; + break; + } + } + mutex_unlock(&rng_devices.lock); + + return ret; +} + +static void lsrng_exit(struct crypto_tfm *tfm) +{ + struct lsrng_ctx *ctx = crypto_tfm_ctx(tfm); + + mutex_lock(&rng_devices.lock); + ctx->rng->is_used = false; + mutex_unlock(&rng_devices.lock); +} + +static int no_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen) +{ + return 0; +} + +static struct rng_alg lsrng_alg = { + .generate = lsrng_generate, + .seed = no_seed, + .base = { + .cra_name = "stdrng", + .cra_driver_name = "loongson_stdrng", + .cra_priority = 300, + .cra_ctxsize = sizeof(struct lsrng_ctx), + .cra_module = THIS_MODULE, + .cra_init = lsrng_init, + .cra_exit = lsrng_exit, + }, +}; + +static void lsrng_add_to_list(struct lsrng *rng) +{ + mutex_lock(&rng_devices.lock); + list_add_tail(&rng->list, &rng_devices.list); + mutex_unlock(&rng_devices.lock); +} + +static int lsrng_probe(struct platform_device *pdev) +{ + struct rng_msg *msg; + struct lsrng *rng; + int ret; + + rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); + if (!rng) + return -ENOMEM; + + init_completion(&rng->rng_completion); + rng->se_ch = se_init_ch(pdev->dev.parent, SE_CH_RNG, PAGE_SIZE, + sizeof(struct rng_msg) * 2, rng, lsrng_complete); + if (!rng->se_ch) + return -ENODEV; + msg = rng->se_ch->smsg; + msg->cmd = SE_CMD_RNG; + msg->out_off = rng->se_ch->off; + + if (!rng_devices.is_init) { + ret = crypto_register_rng(&lsrng_alg); + if (ret) { + dev_err(&pdev->dev, "failed to register crypto(%d)\n", ret); + return ret; + } + INIT_LIST_HEAD(&rng_devices.list); + mutex_init(&rng_devices.lock); + rng_devices.is_init = true; + } + + lsrng_add_to_list(rng); + atomic_inc(&rng_active_devs); + + return 0; +} + +static struct platform_driver lsrng_driver = { + .probe = lsrng_probe, + .driver = { + .name = "ls6000se-rng", + }, +}; +module_platform_driver(lsrng_driver); + +MODULE_ALIAS("platform:ls6000se-rng"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Yinggang Gu "); +MODULE_AUTHOR("Qunqin Zhao "); +MODULE_DESCRIPTION("Loongson random number generator driver"); From patchwork Tue Jan 14 09:55:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qunqin Zhao X-Patchwork-Id: 13938566 X-Patchwork-Delegate: herbert@gondor.apana.org.au Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 48A331ADC6A; Tue, 14 Jan 2025 09:56:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736848605; cv=none; b=cMih/mql87LU5A5wQbFrV2FmB15JO70cQfpKPcZxFRp0m1laJTOHTK0n6HPOZ1jH+WSosMiMyxu8m85VKM+3bdeQ5/bvI9jHXf+bLfHH/0VVxxrkTmpH1W4/x0d7Pnn5z4l0zeHoCN3TigaoO8/rKxjwFRCCLA2zfeLS9wQh+qI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736848605; c=relaxed/simple; bh=6/f8KFQddy2s34NVUfLM8qvh2q9HJtui40udrWnrUec=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=N6CvcMFWKKlamOqkClXV89iFjMOWd9L0D3OG/Ijq7HbVNOBk84doYll7FJHzOg8P8A6MvskmZffLynzN9SZQUokdz7h+HT0nCDLwe8LeE+g7+nhHu1laP2hPQ4Vl0oailFN6Tst/U8EO0F40n8orEPGJy6TfpmScekPuUcMKi4M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [10.40.54.90]) by gateway (Coremail) with SMTP id _____8Axjq_UNIZnHiBjAA--.39493S3; Tue, 14 Jan 2025 17:56:36 +0800 (CST) Received: from localhost.localdomain (unknown [10.40.54.90]) by front1 (Coremail) with SMTP id qMiowMBxReSoNIZnct0hAA--.2343S5; Tue, 14 Jan 2025 17:56:21 +0800 (CST) From: Qunqin Zhao To: lee@kernel.org, herbert@gondor.apana.org.au, gregkh@linuxfoundation.org Cc: linux-kernel@vger.kernel.org, loongarch@lists.linux.dev, davem@davemloft.net, linux-crypto@vger.kernel.org, arnd@arndb.de, derek.kiernan@amd.com, dragan.cvetic@amd.com, Qunqin Zhao , Yinggang Gu Subject: [PATCH v1 3/3] misc: ls6000se-sdf: Add driver for Loongson 6000SE SDF Date: Tue, 14 Jan 2025 17:55:27 +0800 Message-Id: <20250114095527.23722-4-zhaoqunqin@loongson.cn> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20250114095527.23722-1-zhaoqunqin@loongson.cn> References: <20250114095527.23722-1-zhaoqunqin@loongson.cn> Precedence: bulk X-Mailing-List: linux-crypto@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMBxReSoNIZnct0hAA--.2343S5 X-CM-SenderInfo: 52kd01pxqtx0o6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj93XoW3Jr15Cw18urWkAry7Wr4DAwc_yoW7Cw48pF s5Ca45Cr4UWF47Kr43Jr4Uuay3Jas2gry2gry2kw1F93sIyFWkGryrta4DtFsxXrWDGrya qa45KrW5uF4DA3gCm3ZEXasCq-sJn29KB7ZKAUJUUUUf529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUBYb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Ar0_tr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Cr0_Gr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6rxl6s0DM2kKe7AKxVWUAVWUtwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07AIYI kI8VC2zVCFFI0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWUtVWr XwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7VAKI4 8JMxkF7I0En4kS14v26r126r1DMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j 6r4UMxCIbckI1I0E14v26r126r1DMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwV AFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUtVW8ZwCIc40Y0x0EwIxGrwCI42IY6xIIjxv2 0xvE14v26ryj6F1UMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwCI42IY6xAIw20EY4 v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AK xVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7IU8_gA5UUUUU== Loongson Secure Device Function device supports the functions specified in "GB/T 36322-2018". This driver is only responsible for sending user data to SDF devices or returning SDF device data to users. Co-developed-by: Yinggang Gu Signed-off-by: Yinggang Gu Signed-off-by: Qunqin Zhao --- MAINTAINERS | 1 + drivers/misc/Kconfig | 9 +++ drivers/misc/Makefile | 1 + drivers/misc/ls6000se-sdf.c | 123 ++++++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 drivers/misc/ls6000se-sdf.c diff --git a/MAINTAINERS b/MAINTAINERS index e65a7f4ea4..e313e0daf8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13485,6 +13485,7 @@ M: Qunqin Zhao L: linux-crypto@vger.kernel.org S: Maintained F: drivers/crypto/loongson/ +F: drivers/misc/ls6000se-sdf.c LOONGSON-2 APB DMA DRIVER M: Binbin Zhou diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 09cbe3f0ab..10a3ea59a1 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -634,6 +634,15 @@ config MCHP_LAN966X_PCI - lan966x-miim (MDIO_MSCC_MIIM) - lan966x-switch (LAN966X_SWITCH) +config LS6000SE_SDF + tristate "Loongson Secure Device Function driver" + depends on MFD_LS6000SE + help + Loongson Secure Device Function device is the child device of Loongson + Security Module device, it supports the functions specified in + GB/T 36322-2018. This driver will use the interface of Loongson Security + Module driver. + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 40bf953185..b273ec7802 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -74,3 +74,4 @@ lan966x-pci-objs := lan966x_pci.o lan966x-pci-objs += lan966x_pci.dtbo.o obj-$(CONFIG_MCHP_LAN966X_PCI) += lan966x-pci.o obj-y += keba/ +obj-$(CONFIG_LS6000SE_SDF) += ls6000se-sdf.o diff --git a/drivers/misc/ls6000se-sdf.c b/drivers/misc/ls6000se-sdf.c new file mode 100644 index 0000000000..646d54b6e4 --- /dev/null +++ b/drivers/misc/ls6000se-sdf.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (C) 2025 Loongson Technology Corporation Limited */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SE_SDF_BUFSIZE (PAGE_SIZE * 2) + +struct sdf_dev { + struct miscdevice miscdev; + struct lsse_ch *se_ch; + struct completion sdf_completion; +}; + +struct sdf_msg { + u32 cmd; + u32 data_off; + u32 data_len; + u32 pad[5]; +}; + +static void sdf_complete(struct lsse_ch *ch) +{ + struct sdf_dev *sdf = ch->priv; + + complete(&sdf->sdf_completion); +} + +static int send_sdf_cmd(struct sdf_dev *sdf, int len) +{ + struct sdf_msg *smsg = sdf->se_ch->smsg; + + smsg->data_len = len; + + return se_send_ch_requeset(sdf->se_ch); +} + +static ssize_t sdf_read(struct file *file, char __user *buf, + size_t cnt, loff_t *offt) +{ + struct sdf_dev *sdf = container_of(file->private_data, + struct sdf_dev, miscdev); + struct sdf_msg *rmsg; + + if (!wait_for_completion_timeout(&sdf->sdf_completion, HZ*5)) + return -ETIME; + + rmsg = (struct sdf_msg *)sdf->se_ch->rmsg; + if (copy_to_user(buf, + sdf->se_ch->data_buffer + rmsg->data_off, rmsg->data_len)) + return -EFAULT; + + return rmsg->data_len; +} + +static ssize_t sdf_write(struct file *file, const char __user *buf, + size_t cnt, loff_t *offt) +{ + struct sdf_dev *sdf = container_of(file->private_data, + struct sdf_dev, miscdev); + int ret; + + if (copy_from_user(sdf->se_ch->data_buffer, buf, cnt)) + return -EFAULT; + + ret = send_sdf_cmd(sdf, cnt); + + return ret ? -EFAULT : cnt; +} + +static const struct file_operations sdf_fops = { + .owner = THIS_MODULE, + .write = sdf_write, + .read = sdf_read, +}; + +static int sdf_probe(struct platform_device *pdev) +{ + struct sdf_msg *smsg; + struct sdf_dev *sdf; + static int idx; + + sdf = devm_kzalloc(&pdev->dev, sizeof(*sdf), GFP_KERNEL); + if (!sdf) + return -ENOMEM; + init_completion(&sdf->sdf_completion); + + sdf->se_ch = se_init_ch(pdev->dev.parent, SE_CH_SDF, SE_SDF_BUFSIZE, + sizeof(struct sdf_msg) * 2, sdf, sdf_complete); + smsg = sdf->se_ch->smsg; + smsg->cmd = SE_CMD_SDF; + smsg->data_off = sdf->se_ch->off; + sdf->miscdev.minor = MISC_DYNAMIC_MINOR; + sdf->miscdev.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "lsse_sdf%d", idx++); + sdf->miscdev.fops = &sdf_fops; + + return misc_register(&sdf->miscdev); +} + +static struct platform_driver loongson_sdf_driver = { + .probe = sdf_probe, + .driver = { + .name = "ls6000se-sdf", + }, +}; +module_platform_driver(loongson_sdf_driver); + +MODULE_ALIAS("platform:ls6000se-sdf"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Yinggang Gu "); +MODULE_AUTHOR("Qunqin Zhao "); +MODULE_DESCRIPTION("Loongson Secure Device Function driver");