diff options
Diffstat (limited to 'drivers/char/tpm/tpm_nsc.c')
-rw-r--r-- | drivers/char/tpm/tpm_nsc.c | 84 |
1 files changed, 55 insertions, 29 deletions
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index 289389ecef84..9ff0e072c476 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c @@ -64,15 +64,21 @@ enum tpm_nsc_cmd_mode { NSC_COMMAND_EOC = 0x03, NSC_COMMAND_CANCEL = 0x22 }; + +struct tpm_nsc_priv { + unsigned long base; +}; + /* * Wait for a certain status to appear */ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) { + struct tpm_nsc_priv *priv = dev_get_drvdata(&chip->dev); unsigned long stop; /* status immediately available check */ - *data = inb(chip->vendor.base + NSC_STATUS); + *data = inb(priv->base + NSC_STATUS); if ((*data & mask) == val) return 0; @@ -80,7 +86,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) stop = jiffies + 10 * HZ; do { msleep(TPM_TIMEOUT); - *data = inb(chip->vendor.base + 1); + *data = inb(priv->base + 1); if ((*data & mask) == val) return 0; } @@ -91,13 +97,14 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) static int nsc_wait_for_ready(struct tpm_chip *chip) { + struct tpm_nsc_priv *priv = dev_get_drvdata(&chip->dev); int status; unsigned long stop; /* status immediately available check */ - status = inb(chip->vendor.base + NSC_STATUS); + status = inb(priv->base + NSC_STATUS); if (status & NSC_STATUS_OBF) - status = inb(chip->vendor.base + NSC_DATA); + status = inb(priv->base + NSC_DATA); if (status & NSC_STATUS_RDY) return 0; @@ -105,21 +112,22 @@ static int nsc_wait_for_ready(struct tpm_chip *chip) stop = jiffies + 100; do { msleep(TPM_TIMEOUT); - status = inb(chip->vendor.base + NSC_STATUS); + status = inb(priv->base + NSC_STATUS); if (status & NSC_STATUS_OBF) - status = inb(chip->vendor.base + NSC_DATA); + status = inb(priv->base + NSC_DATA); if (status & NSC_STATUS_RDY) return 0; } while (time_before(jiffies, stop)); - dev_info(chip->pdev, "wait for ready failed\n"); + dev_info(&chip->dev, "wait for ready failed\n"); return -EBUSY; } static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) { + struct tpm_nsc_priv *priv = dev_get_drvdata(&chip->dev); u8 *buffer = buf; u8 data, *p; u32 size; @@ -129,12 +137,13 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) return -EIO; if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) { - dev_err(chip->pdev, "F0 timeout\n"); + dev_err(&chip->dev, "F0 timeout\n"); return -EIO; } - if ((data = - inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) { - dev_err(chip->pdev, "not in normal mode (0x%x)\n", + + data = inb(priv->base + NSC_DATA); + if (data != NSC_COMMAND_NORMAL) { + dev_err(&chip->dev, "not in normal mode (0x%x)\n", data); return -EIO; } @@ -143,22 +152,24 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) for (p = buffer; p < &buffer[count]; p++) { if (wait_for_stat (chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) { - dev_err(chip->pdev, + dev_err(&chip->dev, "OBF timeout (while reading data)\n"); return -EIO; } if (data & NSC_STATUS_F0) break; - *p = inb(chip->vendor.base + NSC_DATA); + *p = inb(priv->base + NSC_DATA); } if ((data & NSC_STATUS_F0) == 0 && (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) { - dev_err(chip->pdev, "F0 not set\n"); + dev_err(&chip->dev, "F0 not set\n"); return -EIO; } - if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) { - dev_err(chip->pdev, + + data = inb(priv->base + NSC_DATA); + if (data != NSC_COMMAND_EOC) { + dev_err(&chip->dev, "expected end of command(0x%x)\n", data); return -EIO; } @@ -174,6 +185,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) { + struct tpm_nsc_priv *priv = dev_get_drvdata(&chip->dev); u8 data; int i; @@ -183,48 +195,52 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) * fix it. Not sure why this is needed, we followed the flow * chart in the manual to the letter. */ - outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND); + outb(NSC_COMMAND_CANCEL, priv->base + NSC_COMMAND); if (nsc_wait_for_ready(chip) != 0) return -EIO; if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { - dev_err(chip->pdev, "IBF timeout\n"); + dev_err(&chip->dev, "IBF timeout\n"); return -EIO; } - outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND); + outb(NSC_COMMAND_NORMAL, priv->base + NSC_COMMAND); if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) { - dev_err(chip->pdev, "IBR timeout\n"); + dev_err(&chip->dev, "IBR timeout\n"); return -EIO; } for (i = 0; i < count; i++) { if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { - dev_err(chip->pdev, + dev_err(&chip->dev, "IBF timeout (while writing data)\n"); return -EIO; } - outb(buf[i], chip->vendor.base + NSC_DATA); + outb(buf[i], priv->base + NSC_DATA); } if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { - dev_err(chip->pdev, "IBF timeout\n"); + dev_err(&chip->dev, "IBF timeout\n"); return -EIO; } - outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND); + outb(NSC_COMMAND_EOC, priv->base + NSC_COMMAND); return count; } static void tpm_nsc_cancel(struct tpm_chip *chip) { - outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND); + struct tpm_nsc_priv *priv = dev_get_drvdata(&chip->dev); + + outb(NSC_COMMAND_CANCEL, priv->base + NSC_COMMAND); } static u8 tpm_nsc_status(struct tpm_chip *chip) { - return inb(chip->vendor.base + NSC_STATUS); + struct tpm_nsc_priv *priv = dev_get_drvdata(&chip->dev); + + return inb(priv->base + NSC_STATUS); } static bool tpm_nsc_req_canceled(struct tpm_chip *chip, u8 status) @@ -247,9 +263,10 @@ static struct platform_device *pdev = NULL; static void tpm_nsc_remove(struct device *dev) { struct tpm_chip *chip = dev_get_drvdata(dev); + struct tpm_nsc_priv *priv = dev_get_drvdata(&chip->dev); tpm_chip_unregister(chip); - release_region(chip->vendor.base, 2); + release_region(priv->base, 2); } static SIMPLE_DEV_PM_OPS(tpm_nsc_pm, tpm_pm_suspend, tpm_pm_resume); @@ -268,6 +285,7 @@ static int __init init_nsc(void) int nscAddrBase = TPM_ADDR; struct tpm_chip *chip; unsigned long base; + struct tpm_nsc_priv *priv; /* verify that it is a National part (SID) */ if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) { @@ -301,6 +319,14 @@ static int __init init_nsc(void) if ((rc = platform_device_add(pdev)) < 0) goto err_put_dev; + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) { + rc = -ENOMEM; + goto err_del_dev; + } + + priv->base = base; + if (request_region(base, 2, "tpm_nsc0") == NULL ) { rc = -EBUSY; goto err_del_dev; @@ -312,6 +338,8 @@ static int __init init_nsc(void) goto err_rel_reg; } + dev_set_drvdata(&chip->dev, priv); + rc = tpm_chip_register(chip); if (rc) goto err_rel_reg; @@ -349,8 +377,6 @@ static int __init init_nsc(void) "NSC TPM revision %d\n", tpm_read_index(nscAddrBase, 0x27) & 0x1F); - chip->vendor.base = base; - return 0; err_rel_reg: |