diff options
-rw-r--r-- | drivers/char/tpm/tpm_crb.c | 59 |
1 files changed, 29 insertions, 30 deletions
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 8f0a98dea327..7b3c2a8aa9de 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c | |||
@@ -92,14 +92,9 @@ enum crb_status { | |||
92 | CRB_DRV_STS_COMPLETE = BIT(0), | 92 | CRB_DRV_STS_COMPLETE = BIT(0), |
93 | }; | 93 | }; |
94 | 94 | ||
95 | enum crb_flags { | ||
96 | CRB_FL_ACPI_START = BIT(0), | ||
97 | CRB_FL_CRB_START = BIT(1), | ||
98 | CRB_FL_CRB_SMC_START = BIT(2), | ||
99 | }; | ||
100 | |||
101 | struct crb_priv { | 95 | struct crb_priv { |
102 | unsigned int flags; | 96 | u32 sm; |
97 | const char *hid; | ||
103 | void __iomem *iobase; | 98 | void __iomem *iobase; |
104 | struct crb_regs_head __iomem *regs_h; | 99 | struct crb_regs_head __iomem *regs_h; |
105 | struct crb_regs_tail __iomem *regs_t; | 100 | struct crb_regs_tail __iomem *regs_t; |
@@ -128,14 +123,16 @@ struct tpm2_crb_smc { | |||
128 | * Anyhow, we do not wait here as a consequent CMD_READY request | 123 | * Anyhow, we do not wait here as a consequent CMD_READY request |
129 | * will be handled correctly even if idle was not completed. | 124 | * will be handled correctly even if idle was not completed. |
130 | * | 125 | * |
131 | * The function does nothing for devices with ACPI-start method. | 126 | * The function does nothing for devices with ACPI-start method |
127 | * or SMC-start method. | ||
132 | * | 128 | * |
133 | * Return: 0 always | 129 | * Return: 0 always |
134 | */ | 130 | */ |
135 | static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) | 131 | static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) |
136 | { | 132 | { |
137 | if ((priv->flags & CRB_FL_ACPI_START) || | 133 | if ((priv->sm == ACPI_TPM2_START_METHOD) || |
138 | (priv->flags & CRB_FL_CRB_SMC_START)) | 134 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || |
135 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC)) | ||
139 | return 0; | 136 | return 0; |
140 | 137 | ||
141 | iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); | 138 | iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); |
@@ -174,14 +171,16 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, | |||
174 | * The device should respond within TIMEOUT_C. | 171 | * The device should respond within TIMEOUT_C. |
175 | * | 172 | * |
176 | * The function does nothing for devices with ACPI-start method | 173 | * The function does nothing for devices with ACPI-start method |
174 | * or SMC-start method. | ||
177 | * | 175 | * |
178 | * Return: 0 on success -ETIME on timeout; | 176 | * Return: 0 on success -ETIME on timeout; |
179 | */ | 177 | */ |
180 | static int __maybe_unused crb_cmd_ready(struct device *dev, | 178 | static int __maybe_unused crb_cmd_ready(struct device *dev, |
181 | struct crb_priv *priv) | 179 | struct crb_priv *priv) |
182 | { | 180 | { |
183 | if ((priv->flags & CRB_FL_ACPI_START) || | 181 | if ((priv->sm == ACPI_TPM2_START_METHOD) || |
184 | (priv->flags & CRB_FL_CRB_SMC_START)) | 182 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || |
183 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC)) | ||
185 | return 0; | 184 | return 0; |
186 | 185 | ||
187 | iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req); | 186 | iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req); |
@@ -325,13 +324,20 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
325 | /* Make sure that cmd is populated before issuing start. */ | 324 | /* Make sure that cmd is populated before issuing start. */ |
326 | wmb(); | 325 | wmb(); |
327 | 326 | ||
328 | if (priv->flags & CRB_FL_CRB_START) | 327 | /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs |
328 | * report only ACPI start but in practice seems to require both | ||
329 | * CRB start, hence invoking CRB start method if hid == MSFT0101. | ||
330 | */ | ||
331 | if ((priv->sm == ACPI_TPM2_COMMAND_BUFFER) || | ||
332 | (priv->sm == ACPI_TPM2_MEMORY_MAPPED) || | ||
333 | (!strcmp(priv->hid, "MSFT0101"))) | ||
329 | iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start); | 334 | iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start); |
330 | 335 | ||
331 | if (priv->flags & CRB_FL_ACPI_START) | 336 | if ((priv->sm == ACPI_TPM2_START_METHOD) || |
337 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD)) | ||
332 | rc = crb_do_acpi_start(chip); | 338 | rc = crb_do_acpi_start(chip); |
333 | 339 | ||
334 | if (priv->flags & CRB_FL_CRB_SMC_START) { | 340 | if (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC) { |
335 | iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start); | 341 | iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start); |
336 | rc = tpm_crb_smc_start(&chip->dev, priv->smc_func_id); | 342 | rc = tpm_crb_smc_start(&chip->dev, priv->smc_func_id); |
337 | } | 343 | } |
@@ -345,7 +351,9 @@ static void crb_cancel(struct tpm_chip *chip) | |||
345 | 351 | ||
346 | iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel); | 352 | iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel); |
347 | 353 | ||
348 | if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip)) | 354 | if (((priv->sm == ACPI_TPM2_START_METHOD) || |
355 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD)) && | ||
356 | crb_do_acpi_start(chip)) | ||
349 | dev_err(&chip->dev, "ACPI Start failed\n"); | 357 | dev_err(&chip->dev, "ACPI Start failed\n"); |
350 | } | 358 | } |
351 | 359 | ||
@@ -458,7 +466,8 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, | |||
458 | * the control area, as one nice sane region except for some older | 466 | * the control area, as one nice sane region except for some older |
459 | * stuff that puts the control area outside the ACPI IO region. | 467 | * stuff that puts the control area outside the ACPI IO region. |
460 | */ | 468 | */ |
461 | if (!(priv->flags & CRB_FL_ACPI_START)) { | 469 | if ((priv->sm == ACPI_TPM2_COMMAND_BUFFER) || |
470 | (priv->sm == ACPI_TPM2_MEMORY_MAPPED)) { | ||
462 | if (buf->control_address == io_res.start + | 471 | if (buf->control_address == io_res.start + |
463 | sizeof(*priv->regs_h)) | 472 | sizeof(*priv->regs_h)) |
464 | priv->regs_h = priv->iobase; | 473 | priv->regs_h = priv->iobase; |
@@ -552,18 +561,6 @@ static int crb_acpi_add(struct acpi_device *device) | |||
552 | if (!priv) | 561 | if (!priv) |
553 | return -ENOMEM; | 562 | return -ENOMEM; |
554 | 563 | ||
555 | /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs | ||
556 | * report only ACPI start but in practice seems to require both | ||
557 | * ACPI start and CRB start. | ||
558 | */ | ||
559 | if (sm == ACPI_TPM2_COMMAND_BUFFER || sm == ACPI_TPM2_MEMORY_MAPPED || | ||
560 | !strcmp(acpi_device_hid(device), "MSFT0101")) | ||
561 | priv->flags |= CRB_FL_CRB_START; | ||
562 | |||
563 | if (sm == ACPI_TPM2_START_METHOD || | ||
564 | sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) | ||
565 | priv->flags |= CRB_FL_ACPI_START; | ||
566 | |||
567 | if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC) { | 564 | if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC) { |
568 | if (buf->header.length < (sizeof(*buf) + sizeof(*crb_smc))) { | 565 | if (buf->header.length < (sizeof(*buf) + sizeof(*crb_smc))) { |
569 | dev_err(dev, | 566 | dev_err(dev, |
@@ -574,9 +571,11 @@ static int crb_acpi_add(struct acpi_device *device) | |||
574 | } | 571 | } |
575 | crb_smc = ACPI_ADD_PTR(struct tpm2_crb_smc, buf, sizeof(*buf)); | 572 | crb_smc = ACPI_ADD_PTR(struct tpm2_crb_smc, buf, sizeof(*buf)); |
576 | priv->smc_func_id = crb_smc->smc_func_id; | 573 | priv->smc_func_id = crb_smc->smc_func_id; |
577 | priv->flags |= CRB_FL_CRB_SMC_START; | ||
578 | } | 574 | } |
579 | 575 | ||
576 | priv->sm = sm; | ||
577 | priv->hid = acpi_device_hid(device); | ||
578 | |||
580 | rc = crb_map_io(device, priv, buf); | 579 | rc = crb_map_io(device, priv, buf); |
581 | if (rc) | 580 | if (rc) |
582 | return rc; | 581 | return rc; |