diff options
-rw-r--r-- | drivers/char/tpm/tpm_crb.c | 47 |
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 | |
394 | out: | ||
395 | crb_go_idle(dev, priv); | ||
396 | |||
397 | return ret; | ||
375 | } | 398 | } |
376 | 399 | ||
377 | static int crb_acpi_add(struct acpi_device *device) | 400 | static 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 | ||
421 | static int crb_acpi_remove(struct acpi_device *device) | 452 | static int crb_acpi_remove(struct acpi_device *device) |