Skip to content

Commit 9afb9ea

Browse files
stuyod01jarkkojs
authored andcommitted
tpm_crb: Add support for the ARM FF-A start method
The TCG ACPI spec v1.4 defines a start method for the TPMs implemented with the ARM CRB over FF-A ABI. Add support for the FF-A start method, and use interfaces provided by the ffa_crb driver to interact with the FF-A based TPM. [jarkko: Fine-tuned the commit message.] Reviewed-by: Jarkko Sakkinen <[email protected]> Signed-off-by: Stuart Yoder <[email protected]> Signed-off-by: Jarkko Sakkinen <[email protected]>
1 parent 6a45754 commit 9afb9ea

File tree

1 file changed

+66
-5
lines changed

1 file changed

+66
-5
lines changed

drivers/char/tpm/tpm_crb.c

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#ifdef CONFIG_ARM64
2020
#include <linux/arm-smccc.h>
2121
#endif
22+
#include "tpm_crb_ffa.h"
2223
#include "tpm.h"
2324

2425
#define ACPI_SIG_TPM2 "TPM2"
@@ -100,6 +101,8 @@ struct crb_priv {
100101
u32 smc_func_id;
101102
u32 __iomem *pluton_start_addr;
102103
u32 __iomem *pluton_reply_addr;
104+
u8 ffa_flags;
105+
u8 ffa_attributes;
103106
};
104107

105108
struct tpm2_crb_smc {
@@ -110,6 +113,14 @@ struct tpm2_crb_smc {
110113
u32 smc_func_id;
111114
};
112115

116+
/* CRB over FFA start method parameters in TCG2 ACPI table */
117+
struct tpm2_crb_ffa {
118+
u8 flags;
119+
u8 attributes;
120+
u16 partition_id;
121+
u8 reserved[8];
122+
};
123+
113124
struct tpm2_crb_pluton {
114125
u64 start_addr;
115126
u64 reply_addr;
@@ -122,7 +133,8 @@ static inline bool tpm_crb_has_idle(u32 start_method)
122133
{
123134
return !(start_method == ACPI_TPM2_START_METHOD ||
124135
start_method == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD ||
125-
start_method == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC);
136+
start_method == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC ||
137+
start_method == ACPI_TPM2_CRB_WITH_ARM_FFA);
126138
}
127139

128140
static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
@@ -261,13 +273,20 @@ static int crb_cmd_ready(struct tpm_chip *chip)
261273
static int __crb_request_locality(struct device *dev,
262274
struct crb_priv *priv, int loc)
263275
{
264-
u32 value = CRB_LOC_STATE_LOC_ASSIGNED |
265-
CRB_LOC_STATE_TPM_REG_VALID_STS;
276+
u32 value = CRB_LOC_STATE_LOC_ASSIGNED | CRB_LOC_STATE_TPM_REG_VALID_STS;
277+
int rc;
266278

267279
if (!priv->regs_h)
268280
return 0;
269281

270282
iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h->loc_ctrl);
283+
284+
if (priv->sm == ACPI_TPM2_CRB_WITH_ARM_FFA) {
285+
rc = tpm_crb_ffa_start(CRB_FFA_START_TYPE_LOCALITY_REQUEST, loc);
286+
if (rc)
287+
return rc;
288+
}
289+
271290
if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, value, value,
272291
TPM2_TIMEOUT_C)) {
273292
dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n");
@@ -287,14 +306,21 @@ static int crb_request_locality(struct tpm_chip *chip, int loc)
287306
static int __crb_relinquish_locality(struct device *dev,
288307
struct crb_priv *priv, int loc)
289308
{
290-
u32 mask = CRB_LOC_STATE_LOC_ASSIGNED |
291-
CRB_LOC_STATE_TPM_REG_VALID_STS;
309+
u32 mask = CRB_LOC_STATE_LOC_ASSIGNED | CRB_LOC_STATE_TPM_REG_VALID_STS;
292310
u32 value = CRB_LOC_STATE_TPM_REG_VALID_STS;
311+
int rc;
293312

294313
if (!priv->regs_h)
295314
return 0;
296315

297316
iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl);
317+
318+
if (priv->sm == ACPI_TPM2_CRB_WITH_ARM_FFA) {
319+
rc = tpm_crb_ffa_start(CRB_FFA_START_TYPE_LOCALITY_REQUEST, loc);
320+
if (rc)
321+
return rc;
322+
}
323+
298324
if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, mask, value,
299325
TPM2_TIMEOUT_C)) {
300326
dev_warn(dev, "TPM_LOC_STATE_x.Relinquish timed out\n");
@@ -443,6 +469,11 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
443469
rc = tpm_crb_smc_start(&chip->dev, priv->smc_func_id);
444470
}
445471

472+
if (priv->sm == ACPI_TPM2_CRB_WITH_ARM_FFA) {
473+
iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start);
474+
rc = tpm_crb_ffa_start(CRB_FFA_START_TYPE_COMMAND, chip->locality);
475+
}
476+
446477
if (rc)
447478
return rc;
448479

@@ -452,13 +483,20 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
452483
static void crb_cancel(struct tpm_chip *chip)
453484
{
454485
struct crb_priv *priv = dev_get_drvdata(&chip->dev);
486+
int rc;
455487

456488
iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel);
457489

458490
if ((priv->sm == ACPI_TPM2_START_METHOD ||
459491
priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) &&
460492
crb_do_acpi_start(chip))
461493
dev_err(&chip->dev, "ACPI Start failed\n");
494+
495+
if (priv->sm == ACPI_TPM2_CRB_WITH_ARM_FFA) {
496+
rc = tpm_crb_ffa_start(CRB_FFA_START_TYPE_COMMAND, chip->locality);
497+
if (rc)
498+
dev_err(&chip->dev, "FF-A Start failed\n");
499+
}
462500
}
463501

464502
static bool crb_req_canceled(struct tpm_chip *chip, u8 status)
@@ -616,6 +654,7 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
616654
* stuff that puts the control area outside the ACPI IO region.
617655
*/
618656
if (priv->sm == ACPI_TPM2_COMMAND_BUFFER ||
657+
priv->sm == ACPI_TPM2_CRB_WITH_ARM_FFA ||
619658
priv->sm == ACPI_TPM2_MEMORY_MAPPED) {
620659
if (iores &&
621660
buf->control_address == iores->start +
@@ -737,6 +776,7 @@ static int crb_acpi_add(struct acpi_device *device)
737776
struct tpm_chip *chip;
738777
struct device *dev = &device->dev;
739778
struct tpm2_crb_smc *crb_smc;
779+
struct tpm2_crb_ffa *crb_ffa;
740780
struct tpm2_crb_pluton *crb_pluton;
741781
acpi_status status;
742782
u32 sm;
@@ -775,6 +815,27 @@ static int crb_acpi_add(struct acpi_device *device)
775815
priv->smc_func_id = crb_smc->smc_func_id;
776816
}
777817

818+
if (sm == ACPI_TPM2_CRB_WITH_ARM_FFA) {
819+
if (buf->header.length < (sizeof(*buf) + sizeof(*crb_ffa))) {
820+
dev_err(dev,
821+
FW_BUG "TPM2 ACPI table has wrong size %u for start method type %d\n",
822+
buf->header.length,
823+
ACPI_TPM2_CRB_WITH_ARM_FFA);
824+
rc = -EINVAL;
825+
goto out;
826+
}
827+
crb_ffa = ACPI_ADD_PTR(struct tpm2_crb_ffa, buf, sizeof(*buf));
828+
priv->ffa_flags = crb_ffa->flags;
829+
priv->ffa_attributes = crb_ffa->attributes;
830+
rc = tpm_crb_ffa_init();
831+
if (rc) {
832+
/* If FF-A driver is not available yet, request probe retry */
833+
if (rc == -ENOENT)
834+
rc = -EPROBE_DEFER;
835+
goto out;
836+
}
837+
}
838+
778839
if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) {
779840
if (buf->header.length < (sizeof(*buf) + sizeof(*crb_pluton))) {
780841
dev_err(dev,

0 commit comments

Comments
 (0)