From patchwork Wed Feb 12 03:31:11 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qunqin Zhao X-Patchwork-Id: 13971177 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id BF4BB27183A; Wed, 12 Feb 2025 03:31: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=1739331105; cv=none; b=lkYcQ7tvKehGeKIqfIDWNVaYdouDV0WHtz8lCyN0YPTS5zsgJz0LpyjiOysnli60l0qWryY26QN5/k8jNw949WZa8tRCWXjdE3klptg7SM55sFxRjfoHPmjfzCGgzYJs2ottR2eEIEzuhvDvkjEP7R8AWJwzQjOahiSKS9kS+A0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739331105; c=relaxed/simple; bh=ue8ygS291cmQBNFbpfuyV8UgJK2KKd8EKnoSuxEjwFA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=O6y3TAkqNsDJUjZTLd0C4suGzw09kO8L97M5eIyFaim/kX7vwrlWtBF+oYHmFNb3x1shLfKqWDMpnVRtvqNmthHx2Nt9x7kCuZ0hCADKXNgpRq1z/SA4TzvwKZW+CazZmvaPJmxJc25N/5k48Tbenli9Lpyq0T16wiXw/Y1AiWM= 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 _____8BxXWscFqxnX8pyAA--.3251S3; Wed, 12 Feb 2025 11:31:40 +0800 (CST) Received: from localhost.localdomain (unknown [10.40.54.90]) by front1 (Coremail) with SMTP id qMiowMCx_cYUFqxnxxENAA--.51918S3; Wed, 12 Feb 2025 11:31:33 +0800 (CST) From: Qunqin Zhao To: lee@kernel.org, herbert@gondor.apana.org.au, davem@davemloft.net, peterhuewe@gmx.de, jarkko@kernel.org Cc: linux-kernel@vger.kernel.org, loongarch@lists.linux.dev, linux-crypto@vger.kernel.org, jgg@ziepe.ca, linux-integrity@vger.kernel.org, Qunqin Zhao , Yinggang Gu Subject: [PATCH v2 1/3] mfd: Add support for Loongson Security Module Date: Wed, 12 Feb 2025 11:31:11 +0800 Message-Id: <20250212033113.15137-2-zhaoqunqin@loongson.cn> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20250212033113.15137-1-zhaoqunqin@loongson.cn> References: <20250212033113.15137-1-zhaoqunqin@loongson.cn> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMCx_cYUFqxnxxENAA--.51918S3 X-CM-SenderInfo: 52kd01pxqtx0o6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj9fXoW3Zr17JF1DAw1fGF1xtw1xXrc_yoW8GF1xZo WxZFs3Zw18Jrn2yrW8ur4rtrWfZr9Y9a45Aw4Yv39rC3WUtFn8KFW0gw43Ww13ZF4Fyry5 u34aqr48uF43Crn5l-sFpf9Il3svdjkaLaAFLSUrUUUU0b8apTn2vfkv8UJUUUU8wcxFpf 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 --- v2: Removed "ls6000se-sdf" device, added "ls6000se-tpm" device. Passed size to SE firmware in se_init_hw() function. MAINTAINERS | 7 + drivers/mfd/Kconfig | 9 + drivers/mfd/Makefile | 2 + drivers/mfd/ls6000se.c | 374 +++++++++++++++++++++++++++++++++++ include/linux/mfd/ls6000se.h | 75 +++++++ 5 files changed, 467 insertions(+) create mode 100644 drivers/mfd/ls6000se.c create mode 100644 include/linux/mfd/ls6000se.h diff --git a/MAINTAINERS b/MAINTAINERS index 5583df569c..cd6c029398 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..24d76c2ffc --- /dev/null +++ b/drivers/mfd/ls6000se.c @@ -0,0 +1,374 @@ +// 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; + req.req.info[2] = size; + + 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-tpm" }, +}; + +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 Wed Feb 12 03:31:12 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qunqin Zhao X-Patchwork-Id: 13971178 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 3BD111DC19E; Wed, 12 Feb 2025 03:31:54 +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=1739331118; cv=none; b=sfpHB+SAGY8C0e4S/DDWVKEB5HroSFl0YtlMvhIij4XoHMmvgGnTb5dp78r/YA9TsS1ejera5LI8F4mIz/4HlaG3LMXm6bZi+FvH5r4G07oxsgdwaEw47z8PBatTL5YGqN7ex8E8+veDYm3KsHRVGvyQdnVjtOeYWW03Z6tOVck= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739331118; c=relaxed/simple; bh=fAjXhqUBPCyLO1dLIbk1ZZhjdtzlMNensvH/h2QwlDY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=c0gtRzTVtL5PN0U0gY5XIGxThYoPzWHsN8pTt/NUkCHuOlvgRdXCOJSv6rUQw3GxU+Ma510ztuKyb0vF0OCOdoC4vgKCx7wSbyTtgq6L16DShb4vGE7+YPV6IOcOqkgkmj+sb0k34i7C+IzswQ2/IvzPHtkAixH26mYt7ATb+28= 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 _____8Bx32slFqxnecpyAA--.3089S3; Wed, 12 Feb 2025 11:31:49 +0800 (CST) Received: from localhost.localdomain (unknown [10.40.54.90]) by front1 (Coremail) with SMTP id qMiowMCx_cYUFqxnxxENAA--.51918S4; Wed, 12 Feb 2025 11:31:39 +0800 (CST) From: Qunqin Zhao To: lee@kernel.org, herbert@gondor.apana.org.au, davem@davemloft.net, peterhuewe@gmx.de, jarkko@kernel.org Cc: linux-kernel@vger.kernel.org, loongarch@lists.linux.dev, linux-crypto@vger.kernel.org, jgg@ziepe.ca, linux-integrity@vger.kernel.org, Qunqin Zhao , Yinggang Gu Subject: [PATCH v2 2/3] crypto: loongson - add Loongson RNG driver support Date: Wed, 12 Feb 2025 11:31:12 +0800 Message-Id: <20250212033113.15137-3-zhaoqunqin@loongson.cn> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20250212033113.15137-1-zhaoqunqin@loongson.cn> References: <20250212033113.15137-1-zhaoqunqin@loongson.cn> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMCx_cYUFqxnxxENAA--.51918S4 X-CM-SenderInfo: 52kd01pxqtx0o6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj93XoW3Jr15CFWktF1kZFWxCFyfGrX_yoW3JF4UpF 4Fk3y8CrWUGFsrKFZ5JrWrCFW3X3sa9a4agFW7Gwn09r92yFyDXayfAFyUAFWDAFWxWrWa gFZa9F4UKa1UJ3gCm3ZEXasCq-sJn29KB7ZKAUJUUUUx529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUBYb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Ar0_tr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Cr0_Gr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6rxl6s0DM2kKe7AKxVWUAVWUtwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07AIYI kI8VC2zVCFFI0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWUtVWr XwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7VAKI4 8JMxkF7I0En4kS14v26r126r1DMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j 6r4UMxCIbckI1I0E14v26r126r1DMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwV AFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUtVW8ZwCIc40Y0x0EwIxGrwCI42IY6xIIjxv2 0xvE14v26r4j6ryUMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwCI42IY6xAIw20EY4 v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AK xVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7IU8_gA5UUUUU== 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 --- v2: None 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 cd6c029398..6493d58436 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 Wed Feb 12 03:31:13 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qunqin Zhao X-Patchwork-Id: 13971179 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8671E1DEFDD; Wed, 12 Feb 2025 03:32:00 +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=1739331123; cv=none; b=ASprwd7WUmf33vDKb3M2ZVDfLbn0YfQWRQZPJzq24YQ8Ug+03r5cwE9TnuCb6foI3rI+2m0E/AbIxs4jZ/won2oe+NS6kkD9VVETzcpGKrolwgW/Ceaeg3E3yJhEPLZVdYVfWRWXFjA+xqWZ3OfOZdHRanijVLe5ztj1ZeM8hd0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739331123; c=relaxed/simple; bh=EHw7z8g8mtLD0aY8DUDoR5M7dB45HIaBPKlgoUDASC4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=rxeU6UFJBHbUVOeVRr22oLY4uAmCBlr06UpPsFQ9iwpckNppZs6/om54g5NAjDa7jJ4vmbnajyrlVNLn7IKrmFnMo2qaGAOSgJ6X/S34hSbSFq5By2i9YfBimmhS7B8FTok25opiv/I009z/hZ98u89in93MMWZ+FB9JW5f1jkU= 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 _____8BxjawrFqxng8pyAA--.36169S3; Wed, 12 Feb 2025 11:31:55 +0800 (CST) Received: from localhost.localdomain (unknown [10.40.54.90]) by front1 (Coremail) with SMTP id qMiowMCx_cYUFqxnxxENAA--.51918S5; Wed, 12 Feb 2025 11:31:46 +0800 (CST) From: Qunqin Zhao To: lee@kernel.org, herbert@gondor.apana.org.au, davem@davemloft.net, peterhuewe@gmx.de, jarkko@kernel.org Cc: linux-kernel@vger.kernel.org, loongarch@lists.linux.dev, linux-crypto@vger.kernel.org, jgg@ziepe.ca, linux-integrity@vger.kernel.org, Qunqin Zhao , Yinggang Gu Subject: [PATCH v2 3/3] tpm: Add a driver for Loongson TPM device Date: Wed, 12 Feb 2025 11:31:13 +0800 Message-Id: <20250212033113.15137-4-zhaoqunqin@loongson.cn> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20250212033113.15137-1-zhaoqunqin@loongson.cn> References: <20250212033113.15137-1-zhaoqunqin@loongson.cn> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: qMiowMCx_cYUFqxnxxENAA--.51918S5 X-CM-SenderInfo: 52kd01pxqtx0o6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj93XoWxCr4fGF4kGryruw47tw43Arc_yoWrKFy8pF 4rCa43CrW5GF47t39xJr4DuFsxX3s2qFW7KrWxJasxZr90yas8uF4ktFy5JFsxXr97GFWa qa9a9F4a9F4jywcCm3ZEXasCq-sJn29KB7ZKAUJUUUUx529EdanIXcx71UUUUU7KY7ZEXa 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== TPM2.0 is implemented in Loongson security engine. This is the driver for it. Co-developed-by: Yinggang Gu Signed-off-by: Yinggang Gu Signed-off-by: Qunqin Zhao --- MAINTAINERS | 1 + drivers/char/tpm/Kconfig | 9 ++++ drivers/char/tpm/Makefile | 1 + drivers/char/tpm/tpm_lsse.c | 104 ++++++++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+) create mode 100644 drivers/char/tpm/tpm_lsse.c diff --git a/MAINTAINERS b/MAINTAINERS index 6493d58436..6aad0f08ad 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13484,6 +13484,7 @@ LOONGSON CRYPTO DRIVER M: Qunqin Zhao L: linux-crypto@vger.kernel.org S: Maintained +F: drivers/char/tpm/tpm_lsse.c F: drivers/crypto/loongson/ LOONGSON-2 APB DMA DRIVER diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 0fc9a510e0..56d0417065 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -225,5 +225,14 @@ config TCG_FTPM_TEE help This driver proxies for firmware TPM running in TEE. +config TCG_LSSE + tristate "Loongson TPM Interface" + depends on MFD_LS6000SE + help + If you want to make Loongson TPM support available, say Yes and + it will be accessible from within Linux. To compile this + driver as a module, choose M here; the module will be called + tpm_lsse. + source "drivers/char/tpm/st33zp24/Kconfig" endif # TCG_TPM diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 9bb142c752..bf2280352d 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile @@ -44,3 +44,4 @@ obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o obj-$(CONFIG_TCG_CRB) += tpm_crb.o obj-$(CONFIG_TCG_VTPM_PROXY) += tpm_vtpm_proxy.o obj-$(CONFIG_TCG_FTPM_TEE) += tpm_ftpm_tee.o +obj-$(CONFIG_TCG_LSSE) += tpm_lsse.o diff --git a/drivers/char/tpm/tpm_lsse.c b/drivers/char/tpm/tpm_lsse.c new file mode 100644 index 0000000000..3fd2d9bac8 --- /dev/null +++ b/drivers/char/tpm/tpm_lsse.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2025 Loongson Technology Corporation Limited. */ + +#include +#include +#include +#include + +#include "tpm.h" + +struct tpm_msg { + u32 cmd; + u32 data_off; + u32 data_len; + u32 info[5]; +}; + +struct tpm_dev { + struct lsse_ch *se_ch; + struct completion tpm_completion; +}; + +static void tpm_complete(struct lsse_ch *ch) +{ + struct tpm_dev *td = ch->priv; + + complete(&td->tpm_completion); +} + +static int tpm_ls_recv(struct tpm_chip *chip, u8 *buf, size_t count) +{ + struct tpm_dev *td = dev_get_drvdata(&chip->dev); + struct tpm_msg *rmsg; + int sig; + + sig = wait_for_completion_interruptible(&td->tpm_completion); + if (sig) + return sig; + + rmsg = td->se_ch->rmsg; + memcpy(buf, td->se_ch->data_buffer, rmsg->data_len); + + return rmsg->data_len; +} + +static int tpm_ls_send(struct tpm_chip *chip, u8 *buf, size_t count) +{ + struct tpm_dev *td = dev_get_drvdata(&chip->dev); + struct tpm_msg *smsg = td->se_ch->smsg; + + memcpy(td->se_ch->data_buffer, buf, count); + smsg->data_len = count; + + return se_send_ch_requeset(td->se_ch); +} + +static const struct tpm_class_ops lsse_tpm_ops = { + .flags = TPM_OPS_AUTO_STARTUP, + .recv = tpm_ls_recv, + .send = tpm_ls_send, +}; + +static int lsse_tpm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tpm_chip *chip; + struct tpm_msg *smsg; + struct tpm_dev *td; + + td = devm_kzalloc(dev, sizeof(struct tpm_dev), GFP_KERNEL); + if (!td) + return -ENOMEM; + + init_completion(&td->tpm_completion); + td->se_ch = se_init_ch(dev->parent, SE_CH_TPM, PAGE_SIZE, + 2 * sizeof(struct tpm_msg), td, tpm_complete); + if (!td->se_ch) + return -ENODEV; + smsg = td->se_ch->smsg; + smsg->cmd = SE_CMD_TPM; + smsg->data_off = td->se_ch->off; + + chip = tpmm_chip_alloc(dev, &lsse_tpm_ops); + if (IS_ERR(chip)) + return PTR_ERR(chip); + chip->flags = TPM_CHIP_FLAG_TPM2 | TPM_CHIP_FLAG_IRQ; + dev_set_drvdata(&chip->dev, td); + + return tpm_chip_register(chip); +} + +static struct platform_driver lsse_tpm_driver = { + .probe = lsse_tpm_probe, + .driver = { + .name = "ls6000se-tpm", + }, +}; +module_platform_driver(lsse_tpm_driver); + +MODULE_ALIAS("platform:ls6000se-tpm"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Yinggang Gu "); +MODULE_AUTHOR("Qunqin Zhao "); +MODULE_DESCRIPTION("Loongson TPM driver");