summaryrefslogtreecommitdiff
path: root/drivers/char/tpm/tpm_nsc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/tpm/tpm_nsc.c')
-rw-r--r--drivers/char/tpm/tpm_nsc.c60
1 files changed, 41 insertions, 19 deletions
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index 766370bed60c..07163a429fdf 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -64,6 +64,16 @@ enum tpm_nsc_cmd_mode {
NSC_COMMAND_EOC = 0x03,
NSC_COMMAND_CANCEL = 0x22
};
+
+struct tpm_nsc_priv {
+ unsigned long base;
+};
+
+static inline struct tpm_nsc_priv *nsc_get_priv(struct tpm_chip *chip)
+{
+ return chip->vendor.priv;
+}
+
/*
* Wait for a certain status to appear
*/
@@ -72,7 +82,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
unsigned long stop;
/* status immediately available check */
- *data = inb(chip->vendor.base + NSC_STATUS);
+ *data = inb(nsc_get_priv(chip)->base + NSC_STATUS);
if ((*data & mask) == val)
return 0;
@@ -80,7 +90,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(nsc_get_priv(chip)->base + 1);
if ((*data & mask) == val)
return 0;
}
@@ -95,9 +105,9 @@ static int nsc_wait_for_ready(struct tpm_chip *chip)
unsigned long stop;
/* status immediately available check */
- status = inb(chip->vendor.base + NSC_STATUS);
+ status = inb(nsc_get_priv(chip)->base + NSC_STATUS);
if (status & NSC_STATUS_OBF)
- status = inb(chip->vendor.base + NSC_DATA);
+ status = inb(nsc_get_priv(chip)->base + NSC_DATA);
if (status & NSC_STATUS_RDY)
return 0;
@@ -105,9 +115,9 @@ 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(nsc_get_priv(chip)->base + NSC_STATUS);
if (status & NSC_STATUS_OBF)
- status = inb(chip->vendor.base + NSC_DATA);
+ status = inb(nsc_get_priv(chip)->base + NSC_DATA);
if (status & NSC_STATUS_RDY)
return 0;
}
@@ -132,8 +142,9 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
dev_err(&chip->dev, "F0 timeout\n");
return -EIO;
}
- if ((data =
- inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
+
+ data = inb(nsc_get_priv(chip)->base + NSC_DATA);
+ if (data != NSC_COMMAND_NORMAL) {
dev_err(&chip->dev, "not in normal mode (0x%x)\n",
data);
return -EIO;
@@ -149,7 +160,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
}
if (data & NSC_STATUS_F0)
break;
- *p = inb(chip->vendor.base + NSC_DATA);
+ *p = inb(nsc_get_priv(chip)->base + NSC_DATA);
}
if ((data & NSC_STATUS_F0) == 0 &&
@@ -157,7 +168,9 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
dev_err(&chip->dev, "F0 not set\n");
return -EIO;
}
- if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) {
+
+ data = inb(nsc_get_priv(chip)->base + NSC_DATA);
+ if (data != NSC_COMMAND_EOC) {
dev_err(&chip->dev,
"expected end of command(0x%x)\n", data);
return -EIO;
@@ -183,7 +196,7 @@ 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, nsc_get_priv(chip)->base + NSC_COMMAND);
if (nsc_wait_for_ready(chip) != 0)
return -EIO;
@@ -193,7 +206,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
return -EIO;
}
- outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND);
+ outb(NSC_COMMAND_NORMAL, nsc_get_priv(chip)->base + NSC_COMMAND);
if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
dev_err(&chip->dev, "IBR timeout\n");
return -EIO;
@@ -205,26 +218,26 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
"IBF timeout (while writing data)\n");
return -EIO;
}
- outb(buf[i], chip->vendor.base + NSC_DATA);
+ outb(buf[i], nsc_get_priv(chip)->base + NSC_DATA);
}
if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
dev_err(&chip->dev, "IBF timeout\n");
return -EIO;
}
- outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND);
+ outb(NSC_COMMAND_EOC, nsc_get_priv(chip)->base + NSC_COMMAND);
return count;
}
static void tpm_nsc_cancel(struct tpm_chip *chip)
{
- outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
+ outb(NSC_COMMAND_CANCEL, nsc_get_priv(chip)->base + NSC_COMMAND);
}
static u8 tpm_nsc_status(struct tpm_chip *chip)
{
- return inb(chip->vendor.base + NSC_STATUS);
+ return inb(nsc_get_priv(chip)->base + NSC_STATUS);
}
static bool tpm_nsc_req_canceled(struct tpm_chip *chip, u8 status)
@@ -249,7 +262,7 @@ static void tpm_nsc_remove(struct device *dev)
struct tpm_chip *chip = dev_get_drvdata(dev);
tpm_chip_unregister(chip);
- release_region(chip->vendor.base, 2);
+ release_region(nsc_get_priv(chip)->base, 2);
}
static SIMPLE_DEV_PM_OPS(tpm_nsc_pm, tpm_pm_suspend, tpm_pm_resume);
@@ -268,6 +281,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 +315,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 +334,8 @@ static int __init init_nsc(void)
goto err_rel_reg;
}
+ chip->vendor.priv = priv;
+
rc = tpm_chip_register(chip);
if (rc)
goto err_rel_reg;
@@ -349,8 +373,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: