TPM2.0 is implemented in Loongson security engine. This is the driver for it. Co-developed-by: Yinggang Gu <guyinggang@xxxxxxxxxxx> Signed-off-by: Yinggang Gu <guyinggang@xxxxxxxxxxx> Signed-off-by: Qunqin Zhao <zhaoqunqin@xxxxxxxxxxx> --- 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 <zhaoqunqin@xxxxxxxxxxxx> L: linux-crypto@xxxxxxxxxxxxxxx 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 <linux/device.h> +#include <linux/mfd/ls6000se.h> +#include <linux/platform_device.h> +#include <linux/wait.h> + +#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 <guyinggang@xxxxxxxxxxx>"); +MODULE_AUTHOR("Qunqin Zhao <zhaoqunqin@xxxxxxxxxxx>"); +MODULE_DESCRIPTION("Loongson TPM driver"); -- 2.43.0