Commit daacdfa6e7d6e57c5d1b8e72b1c863feb53d8a82

Authored by Kylene Jo Hall
Committed by Linus Torvalds
1 parent b2b1866006

[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>

Showing 3 changed files with 53 additions and 70 deletions Side-by-side Diff

drivers/char/tpm/tpm.h
... ... @@ -31,8 +31,8 @@
31 31  
32 32 /* TPM addresses */
33 33 enum tpm_addr {
  34 + TPM_SUPERIO_ADDR = 0x2E,
34 35 TPM_ADDR = 0x4E,
35   - TPM_DATA = 0x4F
36 36 };
37 37  
38 38 extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr,
39 39  
40 40  
41 41  
... ... @@ -79,16 +79,16 @@
79 79 struct list_head list;
80 80 };
81 81  
82   -static inline int tpm_read_index(int index)
  82 +static inline int tpm_read_index(int base, int index)
83 83 {
84   - outb(index, TPM_ADDR);
85   - return inb(TPM_DATA) & 0xFF;
  84 + outb(index, base);
  85 + return inb(base+1) & 0xFF;
86 86 }
87 87  
88   -static inline void tpm_write_index(int index, int value)
  88 +static inline void tpm_write_index(int base, int index, int value)
89 89 {
90   - outb(index, TPM_ADDR);
91   - outb(value & 0xFF, TPM_DATA);
  90 + outb(index, base);
  91 + outb(value & 0xFF, base+1);
92 92 }
93 93  
94 94 extern int tpm_register_hardware(struct pci_dev *,
drivers/char/tpm/tpm_atmel.c
... ... @@ -163,24 +163,24 @@
163 163 if (pci_enable_device(pci_dev))
164 164 return -EIO;
165 165  
166   - lo = tpm_read_index( TPM_ATMEL_BASE_ADDR_LO );
167   - hi = tpm_read_index( TPM_ATMEL_BASE_ADDR_HI );
  166 + lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
  167 + hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
168 168  
169 169 tpm_atmel.base = (hi<<8)|lo;
170 170 dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base);
171 171  
172 172 /* verify that it is an Atmel part */
173   - if (tpm_read_index(4) != 'A' || tpm_read_index(5) != 'T'
174   - || tpm_read_index(6) != 'M' || tpm_read_index(7) != 'L') {
  173 + if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T'
  174 + || tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') {
175 175 rc = -ENODEV;
176 176 goto out_err;
177 177 }
178 178  
179 179 /* query chip for its version number */
180   - if ((version[0] = tpm_read_index(0x00)) != 0xFF) {
181   - version[1] = tpm_read_index(0x01);
182   - version[2] = tpm_read_index(0x02);
183   - version[3] = tpm_read_index(0x03);
  180 + if ((version[0] = tpm_read_index(TPM_ADDR, 0x00)) != 0xFF) {
  181 + version[1] = tpm_read_index(TPM_ADDR, 0x01);
  182 + version[2] = tpm_read_index(TPM_ADDR, 0x02);
  183 + version[3] = tpm_read_index(TPM_ADDR, 0x03);
184 184 } else {
185 185 dev_info(&pci_dev->dev, "version query failed\n");
186 186 rc = -ENODEV;
drivers/char/tpm/tpm_nsc.c
... ... @@ -23,7 +23,6 @@
23 23  
24 24 /* National definitions */
25 25 enum tpm_nsc_addr{
26   - TPM_NSC_BASE = 0x360,
27 26 TPM_NSC_IRQ = 0x07,
28 27 TPM_NSC_BASE0_HI = 0x60,
29 28 TPM_NSC_BASE0_LO = 0x61,
... ... @@ -56,6 +55,7 @@
56 55 NSC_STATUS_RDY = 0x10, /* ready to receive command */
57 56 NSC_STATUS_IBR = 0x20 /* ready to receive data */
58 57 };
  58 +
59 59 /* command bits */
60 60 enum tpm_nsc_cmd_mode {
61 61 NSC_COMMAND_NORMAL = 0x01, /* normal mode */
... ... @@ -150,7 +150,8 @@
150 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 155 dev_err(&chip->pci_dev->dev, "F0 not set\n");
155 156 return -EIO;
156 157 }
157 158  
158 159  
159 160  
160 161  
161 162  
162 163  
163 164  
164 165  
165 166  
166 167  
167 168  
168 169  
169 170  
170 171  
171 172  
172 173  
... ... @@ -259,85 +260,64 @@
259 260 {
260 261 int rc = 0;
261 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 265  
266   - tpm_nsc.base = (hi<<8) | lo;
267   -
268 266 if (pci_enable_device(pci_dev))
269 267 return -EIO;
270 268  
  269 + /* select PM channel 1 */
  270 + tpm_write_index(nscAddrBase,NSC_LDN_INDEX, 0x12);
  271 +
271 272 /* verify that it is a National part (SID) */
272   - if (tpm_read_index(NSC_SID_INDEX) != 0xEF) {
273   - rc = -ENODEV;
274   - goto out_err;
  273 + if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
  274 + nscAddrBase = (tpm_read_index(TPM_SUPERIO_ADDR, 0x2C)<<8)|
  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 286 dev_dbg(&pci_dev->dev, "NSC TPM detected\n");
278 287 dev_dbg(&pci_dev->dev,
279 288 "NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n",
280   - tpm_read_index(0x07), tpm_read_index(0x20),
281   - tpm_read_index(0x27));
  289 + tpm_read_index(nscAddrBase,0x07), tpm_read_index(nscAddrBase,0x20),
  290 + tpm_read_index(nscAddrBase,0x27));
282 291 dev_dbg(&pci_dev->dev,
283 292 "NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n",
284   - tpm_read_index(0x21), tpm_read_index(0x25),
285   - tpm_read_index(0x26), tpm_read_index(0x28));
  293 + tpm_read_index(nscAddrBase,0x21), tpm_read_index(nscAddrBase,0x25),
  294 + tpm_read_index(nscAddrBase,0x26), tpm_read_index(nscAddrBase,0x28));
286 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 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 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 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 303 dev_dbg(&pci_dev->dev,
295 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 306 dev_dbg(&pci_dev->dev,
298 307 "NSC Config "
299 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),
301   - tpm_read_index(0xF2), tpm_read_index(0xF3),
302   - tpm_read_index(0xF4), tpm_read_index(0xF5),
303   - tpm_read_index(0xF6), tpm_read_index(0xF7),
304   - tpm_read_index(0xF8), tpm_read_index(0xF9));
  309 + tpm_read_index(nscAddrBase,0xF0), tpm_read_index(nscAddrBase,0xF1),
  310 + tpm_read_index(nscAddrBase,0xF2), tpm_read_index(nscAddrBase,0xF3),
  311 + tpm_read_index(nscAddrBase,0xF4), tpm_read_index(nscAddrBase,0xF5),
  312 + tpm_read_index(nscAddrBase,0xF6), tpm_read_index(nscAddrBase,0xF7),
  313 + tpm_read_index(nscAddrBase,0xF8), tpm_read_index(nscAddrBase,0xF9));
305 314  
306 315 dev_info(&pci_dev->dev,
307   - "NSC PC21100 TPM revision %d\n",
308   - tpm_read_index(0x27) & 0x1F);
  316 + "NSC TPM revision %d\n",
  317 + tpm_read_index(nscAddrBase, 0x27) & 0x1F);
309 318  
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   -
338 319 /* enable the DPM module */
339   - tpm_write_index(NSC_LDC_INDEX, 0x01);
340   - tpm_read_index(NSC_LDC_INDEX);
  320 + tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
341 321  
342 322 if ((rc = tpm_register_hardware(pci_dev, &tpm_nsc)) < 0)
343 323 goto out_err;
... ... @@ -355,6 +335,9 @@
355 335 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
356 336 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
357 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 341 {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
359 342 {0,}
360 343 };