aboutsummaryrefslogtreecommitdiffstats
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.c120
1 files changed, 68 insertions, 52 deletions
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index 9cce833a0923..1a45e7dfc13b 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -22,43 +22,52 @@
22#include "tpm.h" 22#include "tpm.h"
23 23
24/* National definitions */ 24/* National definitions */
25#define TPM_NSC_BASE 0x360 25enum tpm_nsc_addr{
26#define TPM_NSC_IRQ 0x07 26 TPM_NSC_BASE = 0x360,
27 TPM_NSC_IRQ = 0x07,
28 TPM_NSC_BASE0_HI = 0x60,
29 TPM_NSC_BASE0_LO = 0x61,
30 TPM_NSC_BASE1_HI = 0x62,
31 TPM_NSC_BASE1_LO = 0x63
32};
27 33
28#define NSC_LDN_INDEX 0x07 34enum tpm_nsc_index {
29#define NSC_SID_INDEX 0x20 35 NSC_LDN_INDEX = 0x07,
30#define NSC_LDC_INDEX 0x30 36 NSC_SID_INDEX = 0x20,
31#define NSC_DIO_INDEX 0x60 37 NSC_LDC_INDEX = 0x30,
32#define NSC_CIO_INDEX 0x62 38 NSC_DIO_INDEX = 0x60,
33#define NSC_IRQ_INDEX 0x70 39 NSC_CIO_INDEX = 0x62,
34#define NSC_ITS_INDEX 0x71 40 NSC_IRQ_INDEX = 0x70,
41 NSC_ITS_INDEX = 0x71
42};
35 43
36#define NSC_STATUS 0x01 44enum tpm_nsc_status_loc {
37#define NSC_COMMAND 0x01 45 NSC_STATUS = 0x01,
38#define NSC_DATA 0x00 46 NSC_COMMAND = 0x01,
47 NSC_DATA = 0x00
48};
39 49
40/* status bits */ 50/* status bits */
41#define NSC_STATUS_OBF 0x01 /* output buffer full */ 51enum tpm_nsc_status {
42#define NSC_STATUS_IBF 0x02 /* input buffer full */ 52 NSC_STATUS_OBF = 0x01, /* output buffer full */
43#define NSC_STATUS_F0 0x04 /* F0 */ 53 NSC_STATUS_IBF = 0x02, /* input buffer full */
44#define NSC_STATUS_A2 0x08 /* A2 */ 54 NSC_STATUS_F0 = 0x04, /* F0 */
45#define NSC_STATUS_RDY 0x10 /* ready to receive command */ 55 NSC_STATUS_A2 = 0x08, /* A2 */
46#define NSC_STATUS_IBR 0x20 /* ready to receive data */ 56 NSC_STATUS_RDY = 0x10, /* ready to receive command */
47 57 NSC_STATUS_IBR = 0x20 /* ready to receive data */
58};
48/* command bits */ 59/* command bits */
49#define NSC_COMMAND_NORMAL 0x01 /* normal mode */ 60enum tpm_nsc_cmd_mode {
50#define NSC_COMMAND_EOC 0x03 61 NSC_COMMAND_NORMAL = 0x01, /* normal mode */
51#define NSC_COMMAND_CANCEL 0x22 62 NSC_COMMAND_EOC = 0x03,
52 63 NSC_COMMAND_CANCEL = 0x22
64};
53/* 65/*
54 * Wait for a certain status to appear 66 * Wait for a certain status to appear
55 */ 67 */
56static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) 68static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
57{ 69{
58 int expired = 0; 70 unsigned long stop;
59 struct timer_list status_timer =
60 TIMER_INITIALIZER(tpm_time_expired, jiffies + 10 * HZ,
61 (unsigned long) &expired);
62 71
63 /* status immediately available check */ 72 /* status immediately available check */
64 *data = inb(chip->vendor->base + NSC_STATUS); 73 *data = inb(chip->vendor->base + NSC_STATUS);
@@ -66,17 +75,14 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
66 return 0; 75 return 0;
67 76
68 /* wait for status */ 77 /* wait for status */
69 add_timer(&status_timer); 78 stop = jiffies + 10 * HZ;
70 do { 79 do {
71 set_current_state(TASK_UNINTERRUPTIBLE); 80 msleep(TPM_TIMEOUT);
72 schedule_timeout(TPM_TIMEOUT);
73 *data = inb(chip->vendor->base + 1); 81 *data = inb(chip->vendor->base + 1);
74 if ((*data & mask) == val) { 82 if ((*data & mask) == val)
75 del_singleshot_timer_sync(&status_timer);
76 return 0; 83 return 0;
77 }
78 } 84 }
79 while (!expired); 85 while (time_before(jiffies, stop));
80 86
81 return -EBUSY; 87 return -EBUSY;
82} 88}
@@ -84,10 +90,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
84static int nsc_wait_for_ready(struct tpm_chip *chip) 90static int nsc_wait_for_ready(struct tpm_chip *chip)
85{ 91{
86 int status; 92 int status;
87 int expired = 0; 93 unsigned long stop;
88 struct timer_list status_timer =
89 TIMER_INITIALIZER(tpm_time_expired, jiffies + 100,
90 (unsigned long) &expired);
91 94
92 /* status immediately available check */ 95 /* status immediately available check */
93 status = inb(chip->vendor->base + NSC_STATUS); 96 status = inb(chip->vendor->base + NSC_STATUS);
@@ -97,19 +100,16 @@ static int nsc_wait_for_ready(struct tpm_chip *chip)
97 return 0; 100 return 0;
98 101
99 /* wait for status */ 102 /* wait for status */
100 add_timer(&status_timer); 103 stop = jiffies + 100;
101 do { 104 do {
102 set_current_state(TASK_UNINTERRUPTIBLE); 105 msleep(TPM_TIMEOUT);
103 schedule_timeout(TPM_TIMEOUT);
104 status = inb(chip->vendor->base + NSC_STATUS); 106 status = inb(chip->vendor->base + NSC_STATUS);
105 if (status & NSC_STATUS_OBF) 107 if (status & NSC_STATUS_OBF)
106 status = inb(chip->vendor->base + NSC_DATA); 108 status = inb(chip->vendor->base + NSC_DATA);
107 if (status & NSC_STATUS_RDY) { 109 if (status & NSC_STATUS_RDY)
108 del_singleshot_timer_sync(&status_timer);
109 return 0; 110 return 0;
110 }
111 } 111 }
112 while (!expired); 112 while (time_before(jiffies, stop));
113 113
114 dev_info(&chip->pci_dev->dev, "wait for ready failed\n"); 114 dev_info(&chip->pci_dev->dev, "wait for ready failed\n");
115 return -EBUSY; 115 return -EBUSY;
@@ -228,30 +228,46 @@ static struct file_operations nsc_ops = {
228 .release = tpm_release, 228 .release = tpm_release,
229}; 229};
230 230
231static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
232static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
233static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
234static DEVICE_ATTR(cancel, S_IWUSR|S_IWGRP, NULL, tpm_store_cancel);
235
236static struct attribute * nsc_attrs[] = {
237 &dev_attr_pubek.attr,
238 &dev_attr_pcrs.attr,
239 &dev_attr_caps.attr,
240 &dev_attr_cancel.attr,
241 0,
242};
243
244static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
245
231static struct tpm_vendor_specific tpm_nsc = { 246static struct tpm_vendor_specific tpm_nsc = {
232 .recv = tpm_nsc_recv, 247 .recv = tpm_nsc_recv,
233 .send = tpm_nsc_send, 248 .send = tpm_nsc_send,
234 .cancel = tpm_nsc_cancel, 249 .cancel = tpm_nsc_cancel,
235 .req_complete_mask = NSC_STATUS_OBF, 250 .req_complete_mask = NSC_STATUS_OBF,
236 .req_complete_val = NSC_STATUS_OBF, 251 .req_complete_val = NSC_STATUS_OBF,
237 .base = TPM_NSC_BASE, 252 .req_canceled = NSC_STATUS_RDY,
253 .attr_group = &nsc_attr_grp,
238 .miscdev = { .fops = &nsc_ops, }, 254 .miscdev = { .fops = &nsc_ops, },
239
240}; 255};
241 256
242static int __devinit tpm_nsc_init(struct pci_dev *pci_dev, 257static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
243 const struct pci_device_id *pci_id) 258 const struct pci_device_id *pci_id)
244{ 259{
245 int rc = 0; 260 int rc = 0;
261 int lo, hi;
262
263 hi = tpm_read_index(TPM_NSC_BASE0_HI);
264 lo = tpm_read_index(TPM_NSC_BASE0_LO);
265
266 tpm_nsc.base = (hi<<8) | lo;
246 267
247 if (pci_enable_device(pci_dev)) 268 if (pci_enable_device(pci_dev))
248 return -EIO; 269 return -EIO;
249 270
250 if (tpm_lpc_bus_init(pci_dev, TPM_NSC_BASE)) {
251 rc = -ENODEV;
252 goto out_err;
253 }
254
255 /* verify that it is a National part (SID) */ 271 /* verify that it is a National part (SID) */
256 if (tpm_read_index(NSC_SID_INDEX) != 0xEF) { 272 if (tpm_read_index(NSC_SID_INDEX) != 0xEF) {
257 rc = -ENODEV; 273 rc = -ENODEV;