1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2025 Loongson Technology Corporation Limited. */ 3 4 #include <linux/device.h> 5 #include <linux/mfd/loongson-se.h> 6 #include <linux/platform_device.h> 7 #include <linux/wait.h> 8 9 #include "tpm.h" 10 11 struct tpm_loongson_cmd { 12 u32 cmd_id; 13 u32 data_off; 14 u32 data_len; 15 u32 pad[5]; 16 }; 17 18 static int tpm_loongson_recv(struct tpm_chip *chip, u8 *buf, size_t count) 19 { 20 struct loongson_se_engine *tpm_engine = dev_get_drvdata(&chip->dev); 21 struct tpm_loongson_cmd *cmd_ret = tpm_engine->command_ret; 22 23 if (cmd_ret->data_len > count) 24 return -EIO; 25 26 memcpy(buf, tpm_engine->data_buffer, cmd_ret->data_len); 27 28 return cmd_ret->data_len; 29 } 30 31 static int tpm_loongson_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, size_t count) 32 { 33 struct loongson_se_engine *tpm_engine = dev_get_drvdata(&chip->dev); 34 struct tpm_loongson_cmd *cmd = tpm_engine->command; 35 36 if (count > tpm_engine->buffer_size) 37 return -E2BIG; 38 39 cmd->data_len = count; 40 memcpy(tpm_engine->data_buffer, buf, count); 41 42 return loongson_se_send_engine_cmd(tpm_engine); 43 } 44 45 static const struct tpm_class_ops tpm_loongson_ops = { 46 .flags = TPM_OPS_AUTO_STARTUP, 47 .recv = tpm_loongson_recv, 48 .send = tpm_loongson_send, 49 }; 50 51 static int tpm_loongson_probe(struct platform_device *pdev) 52 { 53 struct loongson_se_engine *tpm_engine; 54 struct device *dev = &pdev->dev; 55 struct tpm_loongson_cmd *cmd; 56 struct tpm_chip *chip; 57 58 tpm_engine = loongson_se_init_engine(dev->parent, SE_ENGINE_TPM); 59 if (!tpm_engine) 60 return -ENODEV; 61 cmd = tpm_engine->command; 62 cmd->cmd_id = SE_CMD_TPM; 63 cmd->data_off = tpm_engine->buffer_off; 64 65 chip = tpmm_chip_alloc(dev, &tpm_loongson_ops); 66 if (IS_ERR(chip)) 67 return PTR_ERR(chip); 68 chip->flags = TPM_CHIP_FLAG_TPM2 | TPM_CHIP_FLAG_IRQ; 69 dev_set_drvdata(&chip->dev, tpm_engine); 70 71 return tpm_chip_register(chip); 72 } 73 74 static struct platform_driver tpm_loongson = { 75 .probe = tpm_loongson_probe, 76 .driver = { 77 .name = "tpm_loongson", 78 }, 79 }; 80 module_platform_driver(tpm_loongson); 81 82 MODULE_ALIAS("platform:tpm_loongson"); 83 MODULE_LICENSE("GPL"); 84 MODULE_DESCRIPTION("Loongson TPM driver"); 85