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 <guyinggang@xxxxxxxxxxx> Signed-off-by: Yinggang Gu <guyinggang@xxxxxxxxxxx> Signed-off-by: Qunqin Zhao <zhaoqunqin@xxxxxxxxxxx> --- 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 <zhaoqunqin@xxxxxxxxxxxx> L: linux-crypto@xxxxxxxxxxxxxxx S: Maintained F: drivers/crypto/loongson/ +F: drivers/misc/ls6000se-sdf.c LOONGSON-2 APB DMA DRIVER M: Binbin Zhou <zhoubinbin@xxxxxxxxxxx> 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 <linux/init.h> +#include <linux/iopoll.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/mfd/ls6000se.h> +#include <linux/miscdevice.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/uaccess.h> +#include <linux/wait.h> + +#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 <guyinggang@xxxxxxxxxxx>"); +MODULE_AUTHOR("Qunqin Zhao <zhaoqunqin@xxxxxxxxxxx>"); +MODULE_DESCRIPTION("Loongson Secure Device Function driver"); -- 2.43.0