tpm_crb: Add idle support for the Arm FF-A start method

According to the CRB over FF-A specification [1], a TPM that implements
the ABI must comply with the TCG PTP specification. This requires support
for the Idle and Ready states.

This patch implements CRB control area requests for goIdle and
cmdReady on FF-A based TPMs.

The FF-A message used to notify the TPM of CRB updates includes a
locality parameter, which provides a hint to the TPM about which
locality modified the CRB. This patch adds a locality parameter
to __crb_go_idle() and __crb_cmd_ready() to support this.

[1] https://developer.arm.com/documentation/den0138/latest/

Signed-off-by: Stuart Yoder <stuart.yoder@arm.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>

authored by Stuart Yoder and committed by Jarkko Sakkinen dbfdaeb3 f406055c

+20 -9
+20 -9
drivers/char/tpm/tpm_crb.c
··· 133 { 134 return !(start_method == ACPI_TPM2_START_METHOD || 135 start_method == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD || 136 - start_method == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC || 137 - start_method == ACPI_TPM2_CRB_WITH_ARM_FFA); 138 } 139 140 static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, ··· 190 * 191 * Return: 0 always 192 */ 193 - static int __crb_go_idle(struct device *dev, struct crb_priv *priv) 194 { 195 int rc; 196 ··· 198 return 0; 199 200 iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); 201 202 rc = crb_try_pluton_doorbell(priv, true); 203 if (rc) ··· 225 struct device *dev = &chip->dev; 226 struct crb_priv *priv = dev_get_drvdata(dev); 227 228 - return __crb_go_idle(dev, priv); 229 } 230 231 /** ··· 243 * 244 * Return: 0 on success -ETIME on timeout; 245 */ 246 - static int __crb_cmd_ready(struct device *dev, struct crb_priv *priv) 247 { 248 int rc; 249 ··· 251 return 0; 252 253 iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req); 254 255 rc = crb_try_pluton_doorbell(priv, true); 256 if (rc) ··· 278 struct device *dev = &chip->dev; 279 struct crb_priv *priv = dev_get_drvdata(dev); 280 281 - return __crb_cmd_ready(dev, priv); 282 } 283 284 static int __crb_request_locality(struct device *dev, ··· 455 456 /* Seems to be necessary for every command */ 457 if (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) 458 - __crb_cmd_ready(&chip->dev, priv); 459 460 memcpy_toio(priv->cmd, buf, len); 461 ··· 683 * PTT HW bug w/a: wake up the device to access 684 * possibly not retained registers. 685 */ 686 - ret = __crb_cmd_ready(dev, priv); 687 if (ret) 688 goto out_relinquish_locality; 689 ··· 755 if (!ret) 756 priv->cmd_size = cmd_size; 757 758 - __crb_go_idle(dev, priv); 759 760 out_relinquish_locality: 761
··· 133 { 134 return !(start_method == ACPI_TPM2_START_METHOD || 135 start_method == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD || 136 + start_method == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC); 137 } 138 139 static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, ··· 191 * 192 * Return: 0 always 193 */ 194 + static int __crb_go_idle(struct device *dev, struct crb_priv *priv, int loc) 195 { 196 int rc; 197 ··· 199 return 0; 200 201 iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); 202 + 203 + if (priv->sm == ACPI_TPM2_CRB_WITH_ARM_FFA) { 204 + rc = tpm_crb_ffa_start(CRB_FFA_START_TYPE_COMMAND, loc); 205 + if (rc) 206 + return rc; 207 + } 208 209 rc = crb_try_pluton_doorbell(priv, true); 210 if (rc) ··· 220 struct device *dev = &chip->dev; 221 struct crb_priv *priv = dev_get_drvdata(dev); 222 223 + return __crb_go_idle(dev, priv, chip->locality); 224 } 225 226 /** ··· 238 * 239 * Return: 0 on success -ETIME on timeout; 240 */ 241 + static int __crb_cmd_ready(struct device *dev, struct crb_priv *priv, int loc) 242 { 243 int rc; 244 ··· 246 return 0; 247 248 iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req); 249 + 250 + if (priv->sm == ACPI_TPM2_CRB_WITH_ARM_FFA) { 251 + rc = tpm_crb_ffa_start(CRB_FFA_START_TYPE_COMMAND, loc); 252 + if (rc) 253 + return rc; 254 + } 255 256 rc = crb_try_pluton_doorbell(priv, true); 257 if (rc) ··· 267 struct device *dev = &chip->dev; 268 struct crb_priv *priv = dev_get_drvdata(dev); 269 270 + return __crb_cmd_ready(dev, priv, chip->locality); 271 } 272 273 static int __crb_request_locality(struct device *dev, ··· 444 445 /* Seems to be necessary for every command */ 446 if (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) 447 + __crb_cmd_ready(&chip->dev, priv, chip->locality); 448 449 memcpy_toio(priv->cmd, buf, len); 450 ··· 672 * PTT HW bug w/a: wake up the device to access 673 * possibly not retained registers. 674 */ 675 + ret = __crb_cmd_ready(dev, priv, 0); 676 if (ret) 677 goto out_relinquish_locality; 678 ··· 744 if (!ret) 745 priv->cmd_size = cmd_size; 746 747 + __crb_go_idle(dev, priv, 0); 748 749 out_relinquish_locality: 750