aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tpm
diff options
context:
space:
mode:
authorKylene Jo Hall <kjhall@us.ibm.com>2005-06-25 17:55:39 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-25 19:24:38 -0400
commitdaacdfa6e7d6e57c5d1b8e72b1c863feb53d8a82 (patch)
treedc68ef70c69f34a9c394ec0eca73d0beb2c2d88a /drivers/char/tpm
parentb2b18660066997420b716c1881a6be8b82700d97 (diff)
[PATCH] tpm: Support new National TPMs
This patch is work to support new National TPMs that problems were reported with on Thinkpad T43 and Thinkcentre S51. Thanks to Jens and Gang for their debugging work on these issues. Signed-off-by: Kylene Hall <kjhall@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char/tpm')
-rw-r--r--drivers/char/tpm/tpm.h14
-rw-r--r--drivers/char/tpm/tpm_atmel.c16
-rw-r--r--drivers/char/tpm/tpm_nsc.c93
3 files changed, 53 insertions, 70 deletions
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 10cb450191a6..373b41f6b460 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -31,8 +31,8 @@ enum tpm_timeout {
31 31
32/* TPM addresses */ 32/* TPM addresses */
33enum tpm_addr { 33enum tpm_addr {
34 TPM_SUPERIO_ADDR = 0x2E,
34 TPM_ADDR = 0x4E, 35 TPM_ADDR = 0x4E,
35 TPM_DATA = 0x4F
36}; 36};
37 37
38extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, 38extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr,
@@ -79,16 +79,16 @@ struct tpm_chip {
79 struct list_head list; 79 struct list_head list;
80}; 80};
81 81
82static inline int tpm_read_index(int index) 82static inline int tpm_read_index(int base, int index)
83{ 83{
84 outb(index, TPM_ADDR); 84 outb(index, base);
85 return inb(TPM_DATA) & 0xFF; 85 return inb(base+1) & 0xFF;
86} 86}
87 87
88static inline void tpm_write_index(int index, int value) 88static inline void tpm_write_index(int base, int index, int value)
89{ 89{
90 outb(index, TPM_ADDR); 90 outb(index, base);
91 outb(value & 0xFF, TPM_DATA); 91 outb(value & 0xFF, base+1);
92} 92}
93 93
94extern int tpm_register_hardware(struct pci_dev *, 94extern int tpm_register_hardware(struct pci_dev *,
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index 61fe14a77124..cc2cc77fd174 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -163,24 +163,24 @@ static int __devinit tpm_atml_init(struct pci_dev *pci_dev,
163 if (pci_enable_device(pci_dev)) 163 if (pci_enable_device(pci_dev))
164 return -EIO; 164 return -EIO;
165 165
166 lo = tpm_read_index( TPM_ATMEL_BASE_ADDR_LO ); 166 lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
167 hi = tpm_read_index( TPM_ATMEL_BASE_ADDR_HI ); 167 hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
168 168
169 tpm_atmel.base = (hi<<8)|lo; 169 tpm_atmel.base = (hi<<8)|lo;
170 dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base); 170 dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base);
171 171
172 /* verify that it is an Atmel part */ 172 /* verify that it is an Atmel part */
173 if (tpm_read_index(4) != 'A' || tpm_read_index(5) != 'T' 173 if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T'
174 || tpm_read_index(6) != 'M' || tpm_read_index(7) != 'L') { 174 || tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') {
175 rc = -ENODEV; 175 rc = -ENODEV;
176 goto out_err; 176 goto out_err;
177 } 177 }
178 178
179 /* query chip for its version number */ 179 /* query chip for its version number */
180 if ((version[0] = tpm_read_index(0x00)) != 0xFF) { 180 if ((version[0] = tpm_read_index(TPM_ADDR, 0x00)) != 0xFF) {
181 version[1] = tpm_read_index(0x01); 181 version[1] = tpm_read_index(TPM_ADDR, 0x01);
182 version[2] = tpm_read_index(0x02); 182 version[2] = tpm_read_index(TPM_ADDR, 0x02);
183 version[3] = tpm_read_index(0x03); 183 version[3] = tpm_read_index(TPM_ADDR, 0x03);
184 } else { 184 } else {
185 dev_info(&pci_dev->dev, "version query failed\n"); 185 dev_info(&pci_dev->dev, "version query failed\n");
186 rc = -ENODEV; 186 rc = -ENODEV;
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index 1a45e7dfc13b..b4127348c063 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -23,7 +23,6 @@
23 23
24/* National definitions */ 24/* National definitions */
25enum tpm_nsc_addr{ 25enum tpm_nsc_addr{
26 TPM_NSC_BASE = 0x360,
27 TPM_NSC_IRQ = 0x07, 26 TPM_NSC_IRQ = 0x07,
28 TPM_NSC_BASE0_HI = 0x60, 27 TPM_NSC_BASE0_HI = 0x60,
29 TPM_NSC_BASE0_LO = 0x61, 28 TPM_NSC_BASE0_LO = 0x61,
@@ -56,6 +55,7 @@ enum tpm_nsc_status {
56 NSC_STATUS_RDY = 0x10, /* ready to receive command */ 55 NSC_STATUS_RDY = 0x10, /* ready to receive command */
57 NSC_STATUS_IBR = 0x20 /* ready to receive data */ 56 NSC_STATUS_IBR = 0x20 /* ready to receive data */
58}; 57};
58
59/* command bits */ 59/* command bits */
60enum tpm_nsc_cmd_mode { 60enum tpm_nsc_cmd_mode {
61 NSC_COMMAND_NORMAL = 0x01, /* normal mode */ 61 NSC_COMMAND_NORMAL = 0x01, /* normal mode */
@@ -150,7 +150,8 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
150 *p = inb(chip->vendor->base + NSC_DATA); 150 *p = inb(chip->vendor->base + NSC_DATA);
151 } 151 }
152 152
153 if ((data & NSC_STATUS_F0) == 0) { 153 if ((data & NSC_STATUS_F0) == 0 &&
154 (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) {
154 dev_err(&chip->pci_dev->dev, "F0 not set\n"); 155 dev_err(&chip->pci_dev->dev, "F0 not set\n");
155 return -EIO; 156 return -EIO;
156 } 157 }
@@ -259,85 +260,64 @@ static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
259{ 260{
260 int rc = 0; 261 int rc = 0;
261 int lo, hi; 262 int lo, hi;
263 int nscAddrBase = TPM_ADDR;
262 264
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;
267 265
268 if (pci_enable_device(pci_dev)) 266 if (pci_enable_device(pci_dev))
269 return -EIO; 267 return -EIO;
270 268
269 /* select PM channel 1 */
270 tpm_write_index(nscAddrBase,NSC_LDN_INDEX, 0x12);
271
271 /* verify that it is a National part (SID) */ 272 /* verify that it is a National part (SID) */
272 if (tpm_read_index(NSC_SID_INDEX) != 0xEF) { 273 if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
273 rc = -ENODEV; 274 nscAddrBase = (tpm_read_index(TPM_SUPERIO_ADDR, 0x2C)<<8)|
274 goto out_err; 275 (tpm_read_index(TPM_SUPERIO_ADDR, 0x2B)&0xFE);
276 if (tpm_read_index(nscAddrBase, NSC_SID_INDEX) != 0xF6) {
277 rc = -ENODEV;
278 goto out_err;
279 }
275 } 280 }
276 281
282 hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
283 lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
284 tpm_nsc.base = (hi<<8) | lo;
285
277 dev_dbg(&pci_dev->dev, "NSC TPM detected\n"); 286 dev_dbg(&pci_dev->dev, "NSC TPM detected\n");
278 dev_dbg(&pci_dev->dev, 287 dev_dbg(&pci_dev->dev,
279 "NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n", 288 "NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n",
280 tpm_read_index(0x07), tpm_read_index(0x20), 289 tpm_read_index(nscAddrBase,0x07), tpm_read_index(nscAddrBase,0x20),
281 tpm_read_index(0x27)); 290 tpm_read_index(nscAddrBase,0x27));
282 dev_dbg(&pci_dev->dev, 291 dev_dbg(&pci_dev->dev,
283 "NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n", 292 "NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n",
284 tpm_read_index(0x21), tpm_read_index(0x25), 293 tpm_read_index(nscAddrBase,0x21), tpm_read_index(nscAddrBase,0x25),
285 tpm_read_index(0x26), tpm_read_index(0x28)); 294 tpm_read_index(nscAddrBase,0x26), tpm_read_index(nscAddrBase,0x28));
286 dev_dbg(&pci_dev->dev, "NSC IO Base0 0x%x\n", 295 dev_dbg(&pci_dev->dev, "NSC IO Base0 0x%x\n",
287 (tpm_read_index(0x60) << 8) | tpm_read_index(0x61)); 296 (tpm_read_index(nscAddrBase,0x60) << 8) | tpm_read_index(nscAddrBase,0x61));
288 dev_dbg(&pci_dev->dev, "NSC IO Base1 0x%x\n", 297 dev_dbg(&pci_dev->dev, "NSC IO Base1 0x%x\n",
289 (tpm_read_index(0x62) << 8) | tpm_read_index(0x63)); 298 (tpm_read_index(nscAddrBase,0x62) << 8) | tpm_read_index(nscAddrBase,0x63));
290 dev_dbg(&pci_dev->dev, "NSC Interrupt number and wakeup 0x%x\n", 299 dev_dbg(&pci_dev->dev, "NSC Interrupt number and wakeup 0x%x\n",
291 tpm_read_index(0x70)); 300 tpm_read_index(nscAddrBase,0x70));
292 dev_dbg(&pci_dev->dev, "NSC IRQ type select 0x%x\n", 301 dev_dbg(&pci_dev->dev, "NSC IRQ type select 0x%x\n",
293 tpm_read_index(0x71)); 302 tpm_read_index(nscAddrBase,0x71));
294 dev_dbg(&pci_dev->dev, 303 dev_dbg(&pci_dev->dev,
295 "NSC DMA channel select0 0x%x, select1 0x%x\n", 304 "NSC DMA channel select0 0x%x, select1 0x%x\n",
296 tpm_read_index(0x74), tpm_read_index(0x75)); 305 tpm_read_index(nscAddrBase,0x74), tpm_read_index(nscAddrBase,0x75));
297 dev_dbg(&pci_dev->dev, 306 dev_dbg(&pci_dev->dev,
298 "NSC Config " 307 "NSC Config "
299 "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", 308 "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
300 tpm_read_index(0xF0), tpm_read_index(0xF1), 309 tpm_read_index(nscAddrBase,0xF0), tpm_read_index(nscAddrBase,0xF1),
301 tpm_read_index(0xF2), tpm_read_index(0xF3), 310 tpm_read_index(nscAddrBase,0xF2), tpm_read_index(nscAddrBase,0xF3),
302 tpm_read_index(0xF4), tpm_read_index(0xF5), 311 tpm_read_index(nscAddrBase,0xF4), tpm_read_index(nscAddrBase,0xF5),
303 tpm_read_index(0xF6), tpm_read_index(0xF7), 312 tpm_read_index(nscAddrBase,0xF6), tpm_read_index(nscAddrBase,0xF7),
304 tpm_read_index(0xF8), tpm_read_index(0xF9)); 313 tpm_read_index(nscAddrBase,0xF8), tpm_read_index(nscAddrBase,0xF9));
305 314
306 dev_info(&pci_dev->dev, 315 dev_info(&pci_dev->dev,
307 "NSC PC21100 TPM revision %d\n", 316 "NSC TPM revision %d\n",
308 tpm_read_index(0x27) & 0x1F); 317 tpm_read_index(nscAddrBase, 0x27) & 0x1F);
309
310 if (tpm_read_index(NSC_LDC_INDEX) == 0)
311 dev_info(&pci_dev->dev, ": NSC TPM not active\n");
312
313 /* select PM channel 1 */
314 tpm_write_index(NSC_LDN_INDEX, 0x12);
315 tpm_read_index(NSC_LDN_INDEX);
316
317 /* disable the DPM module */
318 tpm_write_index(NSC_LDC_INDEX, 0);
319 tpm_read_index(NSC_LDC_INDEX);
320
321 /* set the data register base addresses */
322 tpm_write_index(NSC_DIO_INDEX, TPM_NSC_BASE >> 8);
323 tpm_write_index(NSC_DIO_INDEX + 1, TPM_NSC_BASE);
324 tpm_read_index(NSC_DIO_INDEX);
325 tpm_read_index(NSC_DIO_INDEX + 1);
326
327 /* set the command register base addresses */
328 tpm_write_index(NSC_CIO_INDEX, (TPM_NSC_BASE + 1) >> 8);
329 tpm_write_index(NSC_CIO_INDEX + 1, (TPM_NSC_BASE + 1));
330 tpm_read_index(NSC_DIO_INDEX);
331 tpm_read_index(NSC_DIO_INDEX + 1);
332
333 /* set the interrupt number to be used for the host interface */
334 tpm_write_index(NSC_IRQ_INDEX, TPM_NSC_IRQ);
335 tpm_write_index(NSC_ITS_INDEX, 0x00);
336 tpm_read_index(NSC_IRQ_INDEX);
337 318
338 /* enable the DPM module */ 319 /* enable the DPM module */
339 tpm_write_index(NSC_LDC_INDEX, 0x01); 320 tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
340 tpm_read_index(NSC_LDC_INDEX);
341 321
342 if ((rc = tpm_register_hardware(pci_dev, &tpm_nsc)) < 0) 322 if ((rc = tpm_register_hardware(pci_dev, &tpm_nsc)) < 0)
343 goto out_err; 323 goto out_err;
@@ -355,6 +335,9 @@ static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
355 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)}, 335 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
356 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)}, 336 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
357 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)}, 337 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
338 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
339 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
340 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)},
358 {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)}, 341 {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
359 {0,} 342 {0,}
360}; 343};