aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWinkler, Tomas <tomas.winkler@intel.com>2016-09-12 09:04:19 -0400
committerJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>2016-09-16 08:47:45 -0400
commit9514ff1961c6f0f5983ba72d94f384bc13e0d4a1 (patch)
tree804e90f2e3481877dec47c4b483330679751d804
parente17acbbb69d30836a8c12e2c09bbefab8656693e (diff)
tmp/tpm_crb: fix Intel PTT hw bug during idle state
There is a HW bug in Skylake, and Broxton PCH Intel PTT device, where most of the registers in the control area except START, REQUEST, CANCEL, and LOC_CTRL lost retention when the device is in the idle state. Hence we need to bring the device to ready state before accessing the other registers. The fix brings device to ready state before trying to read command and response buffer addresses in order to remap the for access. Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Tested-by: Jarkko Sakkinen <jarkko.sakkinn@linux.intel.com> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinn@linux.intel.com>
-rw-r--r--drivers/char/tpm/tpm_crb.c47
1 files changed, 39 insertions, 8 deletions
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index 466d12b7fd46..2d1669c0f6c0 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -318,6 +318,7 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
318 struct list_head resources; 318 struct list_head resources;
319 struct resource io_res; 319 struct resource io_res;
320 struct device *dev = &device->dev; 320 struct device *dev = &device->dev;
321 u32 pa_high, pa_low;
321 u64 cmd_pa; 322 u64 cmd_pa;
322 u32 cmd_size; 323 u32 cmd_size;
323 u64 rsp_pa; 324 u64 rsp_pa;
@@ -345,12 +346,27 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
345 if (IS_ERR(priv->cca)) 346 if (IS_ERR(priv->cca))
346 return PTR_ERR(priv->cca); 347 return PTR_ERR(priv->cca);
347 348
348 cmd_pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) | 349 /*
349 (u64) ioread32(&priv->cca->cmd_pa_low); 350 * PTT HW bug w/a: wake up the device to access
351 * possibly not retained registers.
352 */
353 ret = crb_cmd_ready(dev, priv);
354 if (ret)
355 return ret;
356
357 pa_high = ioread32(&priv->cca->cmd_pa_high);
358 pa_low = ioread32(&priv->cca->cmd_pa_low);
359 cmd_pa = ((u64)pa_high << 32) | pa_low;
350 cmd_size = ioread32(&priv->cca->cmd_size); 360 cmd_size = ioread32(&priv->cca->cmd_size);
361
362 dev_dbg(dev, "cmd_hi = %X cmd_low = %X cmd_size %X\n",
363 pa_high, pa_low, cmd_size);
364
351 priv->cmd = crb_map_res(dev, priv, &io_res, cmd_pa, cmd_size); 365 priv->cmd = crb_map_res(dev, priv, &io_res, cmd_pa, cmd_size);
352 if (IS_ERR(priv->cmd)) 366 if (IS_ERR(priv->cmd)) {
353 return PTR_ERR(priv->cmd); 367 ret = PTR_ERR(priv->cmd);
368 goto out;
369 }
354 370
355 memcpy_fromio(&rsp_pa, &priv->cca->rsp_pa, 8); 371 memcpy_fromio(&rsp_pa, &priv->cca->rsp_pa, 8);
356 rsp_pa = le64_to_cpu(rsp_pa); 372 rsp_pa = le64_to_cpu(rsp_pa);
@@ -358,7 +374,8 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
358 374
359 if (cmd_pa != rsp_pa) { 375 if (cmd_pa != rsp_pa) {
360 priv->rsp = crb_map_res(dev, priv, &io_res, rsp_pa, rsp_size); 376 priv->rsp = crb_map_res(dev, priv, &io_res, rsp_pa, rsp_size);
361 return PTR_ERR_OR_ZERO(priv->rsp); 377 ret = PTR_ERR_OR_ZERO(priv->rsp);
378 goto out;
362 } 379 }
363 380
364 /* According to the PTP specification, overlapping command and response 381 /* According to the PTP specification, overlapping command and response
@@ -366,12 +383,18 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
366 */ 383 */
367 if (cmd_size != rsp_size) { 384 if (cmd_size != rsp_size) {
368 dev_err(dev, FW_BUG "overlapping command and response buffer sizes are not identical"); 385 dev_err(dev, FW_BUG "overlapping command and response buffer sizes are not identical");
369 return -EINVAL; 386 ret = -EINVAL;
387 goto out;
370 } 388 }
389
371 priv->cmd_size = cmd_size; 390 priv->cmd_size = cmd_size;
372 391
373 priv->rsp = priv->cmd; 392 priv->rsp = priv->cmd;
374 return 0; 393
394out:
395 crb_go_idle(dev, priv);
396
397 return ret;
375} 398}
376 399
377static int crb_acpi_add(struct acpi_device *device) 400static int crb_acpi_add(struct acpi_device *device)
@@ -415,7 +438,15 @@ static int crb_acpi_add(struct acpi_device *device)
415 if (rc) 438 if (rc)
416 return rc; 439 return rc;
417 440
418 return crb_init(device, priv); 441 rc = crb_cmd_ready(dev, priv);
442 if (rc)
443 return rc;
444
445 rc = crb_init(device, priv);
446 if (rc)
447 crb_go_idle(dev, priv);
448
449 return rc;
419} 450}
420 451
421static int crb_acpi_remove(struct acpi_device *device) 452static int crb_acpi_remove(struct acpi_device *device)