direct-io.hg
changeset 10524:e3ad9b9c95ee
[TPM] Add an upgrade patch to bring TPM subsystem to 2.6.17-rc4.
This patch adds the updated and newer driver plugins appearing in
2.6.17-rc4 to the 2.6.16.13 kernel. The patch needs to be placed into
the patches/linux-2.6.16.13 directory and should be removed once an
upgrade is done to 2.6.17-rc4 or later version.
Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
This patch adds the updated and newer driver plugins appearing in
2.6.17-rc4 to the 2.6.16.13 kernel. The patch needs to be placed into
the patches/linux-2.6.16.13 directory and should be removed once an
upgrade is done to 2.6.17-rc4 or later version.
Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Wed Jun 28 16:21:30 2006 +0100 (2006-06-28) |
parents | da8da6e1e1d6 |
children | d85488fd2196 |
files | patches/linux-2.6.16.13/tpm_plugin_2.6.17.patch |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/patches/linux-2.6.16.13/tpm_plugin_2.6.17.patch Wed Jun 28 16:21:30 2006 +0100 1.3 @@ -0,0 +1,1546 @@ 1.4 +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.c ./drivers/char/tpm/tpm_atmel.c 1.5 +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.c 2006-06-26 18:05:03.000000000 -0400 1.6 ++++ ./drivers/char/tpm/tpm_atmel.c 2006-06-26 18:16:33.000000000 -0400 1.7 +@@ -47,12 +47,12 @@ static int tpm_atml_recv(struct tpm_chip 1.8 + return -EIO; 1.9 + 1.10 + for (i = 0; i < 6; i++) { 1.11 +- status = ioread8(chip->vendor->iobase + 1); 1.12 ++ status = ioread8(chip->vendor.iobase + 1); 1.13 + if ((status & ATML_STATUS_DATA_AVAIL) == 0) { 1.14 + dev_err(chip->dev, "error reading header\n"); 1.15 + return -EIO; 1.16 + } 1.17 +- *buf++ = ioread8(chip->vendor->iobase); 1.18 ++ *buf++ = ioread8(chip->vendor.iobase); 1.19 + } 1.20 + 1.21 + /* size of the data received */ 1.22 +@@ -63,7 +63,7 @@ static int tpm_atml_recv(struct tpm_chip 1.23 + dev_err(chip->dev, 1.24 + "Recv size(%d) less than available space\n", size); 1.25 + for (; i < size; i++) { /* clear the waiting data anyway */ 1.26 +- status = ioread8(chip->vendor->iobase + 1); 1.27 ++ status = ioread8(chip->vendor.iobase + 1); 1.28 + if ((status & ATML_STATUS_DATA_AVAIL) == 0) { 1.29 + dev_err(chip->dev, "error reading data\n"); 1.30 + return -EIO; 1.31 +@@ -74,16 +74,16 @@ static int tpm_atml_recv(struct tpm_chip 1.32 + 1.33 + /* read all the data available */ 1.34 + for (; i < size; i++) { 1.35 +- status = ioread8(chip->vendor->iobase + 1); 1.36 ++ status = ioread8(chip->vendor.iobase + 1); 1.37 + if ((status & ATML_STATUS_DATA_AVAIL) == 0) { 1.38 + dev_err(chip->dev, "error reading data\n"); 1.39 + return -EIO; 1.40 + } 1.41 +- *buf++ = ioread8(chip->vendor->iobase); 1.42 ++ *buf++ = ioread8(chip->vendor.iobase); 1.43 + } 1.44 + 1.45 + /* make sure data available is gone */ 1.46 +- status = ioread8(chip->vendor->iobase + 1); 1.47 ++ status = ioread8(chip->vendor.iobase + 1); 1.48 + 1.49 + if (status & ATML_STATUS_DATA_AVAIL) { 1.50 + dev_err(chip->dev, "data available is stuck\n"); 1.51 +@@ -100,7 +100,7 @@ static int tpm_atml_send(struct tpm_chip 1.52 + dev_dbg(chip->dev, "tpm_atml_send:\n"); 1.53 + for (i = 0; i < count; i++) { 1.54 + dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); 1.55 +- iowrite8(buf[i], chip->vendor->iobase); 1.56 ++ iowrite8(buf[i], chip->vendor.iobase); 1.57 + } 1.58 + 1.59 + return count; 1.60 +@@ -108,12 +108,12 @@ static int tpm_atml_send(struct tpm_chip 1.61 + 1.62 + static void tpm_atml_cancel(struct tpm_chip *chip) 1.63 + { 1.64 +- iowrite8(ATML_STATUS_ABORT, chip->vendor->iobase + 1); 1.65 ++ iowrite8(ATML_STATUS_ABORT, chip->vendor.iobase + 1); 1.66 + } 1.67 + 1.68 + static u8 tpm_atml_status(struct tpm_chip *chip) 1.69 + { 1.70 +- return ioread8(chip->vendor->iobase + 1); 1.71 ++ return ioread8(chip->vendor.iobase + 1); 1.72 + } 1.73 + 1.74 + static struct file_operations atmel_ops = { 1.75 +@@ -140,7 +140,7 @@ static struct attribute* atmel_attrs[] = 1.76 + 1.77 + static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs }; 1.78 + 1.79 +-static struct tpm_vendor_specific tpm_atmel = { 1.80 ++static const struct tpm_vendor_specific tpm_atmel = { 1.81 + .recv = tpm_atml_recv, 1.82 + .send = tpm_atml_send, 1.83 + .cancel = tpm_atml_cancel, 1.84 +@@ -159,10 +159,10 @@ static void atml_plat_remove(void) 1.85 + struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); 1.86 + 1.87 + if (chip) { 1.88 +- if (chip->vendor->have_region) 1.89 +- atmel_release_region(chip->vendor->base, 1.90 +- chip->vendor->region_size); 1.91 +- atmel_put_base_addr(chip->vendor); 1.92 ++ if (chip->vendor.have_region) 1.93 ++ atmel_release_region(chip->vendor.base, 1.94 ++ chip->vendor.region_size); 1.95 ++ atmel_put_base_addr(chip->vendor.iobase); 1.96 + tpm_remove_hardware(chip->dev); 1.97 + platform_device_unregister(pdev); 1.98 + } 1.99 +@@ -179,18 +179,22 @@ static struct device_driver atml_drv = { 1.100 + static int __init init_atmel(void) 1.101 + { 1.102 + int rc = 0; 1.103 ++ void __iomem *iobase = NULL; 1.104 ++ int have_region, region_size; 1.105 ++ unsigned long base; 1.106 ++ struct tpm_chip *chip; 1.107 + 1.108 + driver_register(&atml_drv); 1.109 + 1.110 +- if ((tpm_atmel.iobase = atmel_get_base_addr(&tpm_atmel)) == NULL) { 1.111 ++ if ((iobase = atmel_get_base_addr(&base, ®ion_size)) == NULL) { 1.112 + rc = -ENODEV; 1.113 + goto err_unreg_drv; 1.114 + } 1.115 + 1.116 +- tpm_atmel.have_region = 1.117 ++ have_region = 1.118 + (atmel_request_region 1.119 +- (tpm_atmel.base, tpm_atmel.region_size, 1.120 +- "tpm_atmel0") == NULL) ? 0 : 1; 1.121 ++ (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1; 1.122 ++ 1.123 + 1.124 + if (IS_ERR 1.125 + (pdev = 1.126 +@@ -199,17 +203,25 @@ static int __init init_atmel(void) 1.127 + goto err_rel_reg; 1.128 + } 1.129 + 1.130 +- if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) 1.131 ++ if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) { 1.132 ++ rc = -ENODEV; 1.133 + goto err_unreg_dev; 1.134 ++ } 1.135 ++ 1.136 ++ chip->vendor.iobase = iobase; 1.137 ++ chip->vendor.base = base; 1.138 ++ chip->vendor.have_region = have_region; 1.139 ++ chip->vendor.region_size = region_size; 1.140 ++ 1.141 + return 0; 1.142 + 1.143 + err_unreg_dev: 1.144 + platform_device_unregister(pdev); 1.145 + err_rel_reg: 1.146 +- atmel_put_base_addr(&tpm_atmel); 1.147 +- if (tpm_atmel.have_region) 1.148 +- atmel_release_region(tpm_atmel.base, 1.149 +- tpm_atmel.region_size); 1.150 ++ atmel_put_base_addr(iobase); 1.151 ++ if (have_region) 1.152 ++ atmel_release_region(base, 1.153 ++ region_size); 1.154 + err_unreg_drv: 1.155 + driver_unregister(&atml_drv); 1.156 + return rc; 1.157 +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.h ./drivers/char/tpm/tpm_atmel.h 1.158 +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.h 2006-06-26 18:05:03.000000000 -0400 1.159 ++++ ./drivers/char/tpm/tpm_atmel.h 2006-06-26 18:16:33.000000000 -0400 1.160 +@@ -28,13 +28,12 @@ 1.161 + #define atmel_request_region request_mem_region 1.162 + #define atmel_release_region release_mem_region 1.163 + 1.164 +-static inline void atmel_put_base_addr(struct tpm_vendor_specific 1.165 +- *vendor) 1.166 ++static inline void atmel_put_base_addr(void __iomem *iobase) 1.167 + { 1.168 +- iounmap(vendor->iobase); 1.169 ++ iounmap(iobase); 1.170 + } 1.171 + 1.172 +-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor) 1.173 ++static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) 1.174 + { 1.175 + struct device_node *dn; 1.176 + unsigned long address, size; 1.177 +@@ -71,9 +70,9 @@ static void __iomem * atmel_get_base_add 1.178 + else 1.179 + size = reg[naddrc]; 1.180 + 1.181 +- vendor->base = address; 1.182 +- vendor->region_size = size; 1.183 +- return ioremap(vendor->base, vendor->region_size); 1.184 ++ *base = address; 1.185 ++ *region_size = size; 1.186 ++ return ioremap(*base, *region_size); 1.187 + } 1.188 + #else 1.189 + #define atmel_getb(chip, offset) inb(chip->vendor->base + offset) 1.190 +@@ -106,14 +105,12 @@ static int atmel_verify_tpm11(void) 1.191 + return 0; 1.192 + } 1.193 + 1.194 +-static inline void atmel_put_base_addr(struct tpm_vendor_specific 1.195 +- *vendor) 1.196 ++static inline void atmel_put_base_addr(void __iomem *iobase) 1.197 + { 1.198 + } 1.199 + 1.200 + /* Determine where to talk to device */ 1.201 +-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific 1.202 +- *vendor) 1.203 ++static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) 1.204 + { 1.205 + int lo, hi; 1.206 + 1.207 +@@ -123,9 +120,9 @@ static void __iomem * atmel_get_base_add 1.208 + lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); 1.209 + hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); 1.210 + 1.211 +- vendor->base = (hi << 8) | lo; 1.212 +- vendor->region_size = 2; 1.213 ++ *base = (hi << 8) | lo; 1.214 ++ *region_size = 2; 1.215 + 1.216 +- return ioport_map(vendor->base, vendor->region_size); 1.217 ++ return ioport_map(*base, *region_size); 1.218 + } 1.219 + #endif 1.220 +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_bios.c ./drivers/char/tpm/tpm_bios.c 1.221 +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_bios.c 2006-06-26 18:05:03.000000000 -0400 1.222 ++++ ./drivers/char/tpm/tpm_bios.c 2006-06-26 18:16:33.000000000 -0400 1.223 +@@ -29,6 +29,11 @@ 1.224 + #define MAX_TEXT_EVENT 1000 /* Max event string length */ 1.225 + #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ 1.226 + 1.227 ++enum bios_platform_class { 1.228 ++ BIOS_CLIENT = 0x00, 1.229 ++ BIOS_SERVER = 0x01, 1.230 ++}; 1.231 ++ 1.232 + struct tpm_bios_log { 1.233 + void *bios_event_log; 1.234 + void *bios_event_log_end; 1.235 +@@ -36,9 +41,18 @@ struct tpm_bios_log { 1.236 + 1.237 + struct acpi_tcpa { 1.238 + struct acpi_table_header hdr; 1.239 +- u16 reserved; 1.240 +- u32 log_max_len __attribute__ ((packed)); 1.241 +- u32 log_start_addr __attribute__ ((packed)); 1.242 ++ u16 platform_class; 1.243 ++ union { 1.244 ++ struct client_hdr { 1.245 ++ u32 log_max_len __attribute__ ((packed)); 1.246 ++ u64 log_start_addr __attribute__ ((packed)); 1.247 ++ } client; 1.248 ++ struct server_hdr { 1.249 ++ u16 reserved; 1.250 ++ u64 log_max_len __attribute__ ((packed)); 1.251 ++ u64 log_start_addr __attribute__ ((packed)); 1.252 ++ } server; 1.253 ++ }; 1.254 + }; 1.255 + 1.256 + struct tcpa_event { 1.257 +@@ -91,6 +105,12 @@ static const char* tcpa_event_type_strin 1.258 + "Non-Host Info" 1.259 + }; 1.260 + 1.261 ++struct tcpa_pc_event { 1.262 ++ u32 event_id; 1.263 ++ u32 event_size; 1.264 ++ u8 event_data[0]; 1.265 ++}; 1.266 ++ 1.267 + enum tcpa_pc_event_ids { 1.268 + SMBIOS = 1, 1.269 + BIS_CERT, 1.270 +@@ -100,14 +120,15 @@ enum tcpa_pc_event_ids { 1.271 + NVRAM, 1.272 + OPTION_ROM_EXEC, 1.273 + OPTION_ROM_CONFIG, 1.274 +- OPTION_ROM_MICROCODE, 1.275 ++ OPTION_ROM_MICROCODE = 10, 1.276 + S_CRTM_VERSION, 1.277 + S_CRTM_CONTENTS, 1.278 + POST_CONTENTS, 1.279 ++ HOST_TABLE_OF_DEVICES, 1.280 + }; 1.281 + 1.282 + static const char* tcpa_pc_event_id_strings[] = { 1.283 +- "" 1.284 ++ "", 1.285 + "SMBIOS", 1.286 + "BIS Certificate", 1.287 + "POST BIOS ", 1.288 +@@ -116,10 +137,12 @@ static const char* tcpa_pc_event_id_stri 1.289 + "NVRAM", 1.290 + "Option ROM", 1.291 + "Option ROM config", 1.292 +- "Option ROM microcode", 1.293 ++ "", 1.294 ++ "Option ROM microcode ", 1.295 + "S-CRTM Version", 1.296 +- "S-CRTM Contents", 1.297 +- "S-CRTM POST Contents", 1.298 ++ "S-CRTM Contents ", 1.299 ++ "POST Contents ", 1.300 ++ "Table of Devices", 1.301 + }; 1.302 + 1.303 + /* returns pointer to start of pos. entry of tcg log */ 1.304 +@@ -191,7 +214,7 @@ static int get_event_name(char *dest, st 1.305 + const char *name = ""; 1.306 + char data[40] = ""; 1.307 + int i, n_len = 0, d_len = 0; 1.308 +- u32 event_id; 1.309 ++ struct tcpa_pc_event *pc_event; 1.310 + 1.311 + switch(event->event_type) { 1.312 + case PREBOOT: 1.313 +@@ -220,31 +243,32 @@ static int get_event_name(char *dest, st 1.314 + } 1.315 + break; 1.316 + case EVENT_TAG: 1.317 +- event_id = be32_to_cpu(*((u32 *)event_entry)); 1.318 ++ pc_event = (struct tcpa_pc_event *)event_entry; 1.319 + 1.320 + /* ToDo Row data -> Base64 */ 1.321 + 1.322 +- switch (event_id) { 1.323 ++ switch (pc_event->event_id) { 1.324 + case SMBIOS: 1.325 + case BIS_CERT: 1.326 + case CMOS: 1.327 + case NVRAM: 1.328 + case OPTION_ROM_EXEC: 1.329 + case OPTION_ROM_CONFIG: 1.330 +- case OPTION_ROM_MICROCODE: 1.331 + case S_CRTM_VERSION: 1.332 +- case S_CRTM_CONTENTS: 1.333 +- case POST_CONTENTS: 1.334 +- name = tcpa_pc_event_id_strings[event_id]; 1.335 ++ name = tcpa_pc_event_id_strings[pc_event->event_id]; 1.336 + n_len = strlen(name); 1.337 + break; 1.338 ++ /* hash data */ 1.339 + case POST_BIOS_ROM: 1.340 + case ESCD: 1.341 +- name = tcpa_pc_event_id_strings[event_id]; 1.342 ++ case OPTION_ROM_MICROCODE: 1.343 ++ case S_CRTM_CONTENTS: 1.344 ++ case POST_CONTENTS: 1.345 ++ name = tcpa_pc_event_id_strings[pc_event->event_id]; 1.346 + n_len = strlen(name); 1.347 + for (i = 0; i < 20; i++) 1.348 +- d_len += sprintf(data, "%02x", 1.349 +- event_entry[8 + i]); 1.350 ++ d_len += sprintf(&data[2*i], "%02x", 1.351 ++ pc_event->event_data[i]); 1.352 + break; 1.353 + default: 1.354 + break; 1.355 +@@ -260,52 +284,13 @@ static int get_event_name(char *dest, st 1.356 + 1.357 + static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) 1.358 + { 1.359 ++ struct tcpa_event *event = v; 1.360 ++ char *data = v; 1.361 ++ int i; 1.362 + 1.363 +- char *eventname; 1.364 +- char data[4]; 1.365 +- u32 help; 1.366 +- int i, len; 1.367 +- struct tcpa_event *event = (struct tcpa_event *) v; 1.368 +- unsigned char *event_entry = 1.369 +- (unsigned char *) (v + sizeof(struct tcpa_event)); 1.370 +- 1.371 +- eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL); 1.372 +- if (!eventname) { 1.373 +- printk(KERN_ERR "%s: ERROR - No Memory for event name\n ", 1.374 +- __func__); 1.375 +- return -ENOMEM; 1.376 +- } 1.377 +- 1.378 +- /* 1st: PCR used is in little-endian format (4 bytes) */ 1.379 +- help = le32_to_cpu(event->pcr_index); 1.380 +- memcpy(data, &help, 4); 1.381 +- for (i = 0; i < 4; i++) 1.382 +- seq_putc(m, data[i]); 1.383 +- 1.384 +- /* 2nd: SHA1 (20 bytes) */ 1.385 +- for (i = 0; i < 20; i++) 1.386 +- seq_putc(m, event->pcr_value[i]); 1.387 +- 1.388 +- /* 3rd: event type identifier (4 bytes) */ 1.389 +- help = le32_to_cpu(event->event_type); 1.390 +- memcpy(data, &help, 4); 1.391 +- for (i = 0; i < 4; i++) 1.392 ++ for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++) 1.393 + seq_putc(m, data[i]); 1.394 + 1.395 +- len = 0; 1.396 +- 1.397 +- len += get_event_name(eventname, event, event_entry); 1.398 +- 1.399 +- /* 4th: filename <= 255 + \'0' delimiter */ 1.400 +- if (len > TCG_EVENT_NAME_LEN_MAX) 1.401 +- len = TCG_EVENT_NAME_LEN_MAX; 1.402 +- 1.403 +- for (i = 0; i < len; i++) 1.404 +- seq_putc(m, eventname[i]); 1.405 +- 1.406 +- /* 5th: delimiter */ 1.407 +- seq_putc(m, '\0'); 1.408 +- 1.409 + return 0; 1.410 + } 1.411 + 1.412 +@@ -353,6 +338,7 @@ static int tpm_ascii_bios_measurements_s 1.413 + /* 4th: eventname <= max + \'0' delimiter */ 1.414 + seq_printf(m, " %s\n", eventname); 1.415 + 1.416 ++ kfree(eventname); 1.417 + return 0; 1.418 + } 1.419 + 1.420 +@@ -376,6 +362,7 @@ static int read_log(struct tpm_bios_log 1.421 + struct acpi_tcpa *buff; 1.422 + acpi_status status; 1.423 + struct acpi_table_header *virt; 1.424 ++ u64 len, start; 1.425 + 1.426 + if (log->bios_event_log != NULL) { 1.427 + printk(KERN_ERR 1.428 +@@ -396,27 +383,37 @@ static int read_log(struct tpm_bios_log 1.429 + return -EIO; 1.430 + } 1.431 + 1.432 +- if (buff->log_max_len == 0) { 1.433 ++ switch(buff->platform_class) { 1.434 ++ case BIOS_SERVER: 1.435 ++ len = buff->server.log_max_len; 1.436 ++ start = buff->server.log_start_addr; 1.437 ++ break; 1.438 ++ case BIOS_CLIENT: 1.439 ++ default: 1.440 ++ len = buff->client.log_max_len; 1.441 ++ start = buff->client.log_start_addr; 1.442 ++ break; 1.443 ++ } 1.444 ++ if (!len) { 1.445 + printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__); 1.446 + return -EIO; 1.447 + } 1.448 + 1.449 + /* malloc EventLog space */ 1.450 +- log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL); 1.451 ++ log->bios_event_log = kmalloc(len, GFP_KERNEL); 1.452 + if (!log->bios_event_log) { 1.453 +- printk 1.454 +- ("%s: ERROR - Not enough Memory for BIOS measurements\n", 1.455 +- __func__); 1.456 ++ printk("%s: ERROR - Not enough Memory for BIOS measurements\n", 1.457 ++ __func__); 1.458 + return -ENOMEM; 1.459 + } 1.460 + 1.461 +- log->bios_event_log_end = log->bios_event_log + buff->log_max_len; 1.462 ++ log->bios_event_log_end = log->bios_event_log + len; 1.463 + 1.464 +- acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt); 1.465 ++ acpi_os_map_memory(start, len, (void *) &virt); 1.466 + 1.467 +- memcpy(log->bios_event_log, virt, buff->log_max_len); 1.468 ++ memcpy(log->bios_event_log, virt, len); 1.469 + 1.470 +- acpi_os_unmap_memory(virt, buff->log_max_len); 1.471 ++ acpi_os_unmap_memory(virt, len); 1.472 + return 0; 1.473 + } 1.474 + 1.475 +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_infineon.c ./drivers/char/tpm/tpm_infineon.c 1.476 +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_infineon.c 2006-06-26 18:05:03.000000000 -0400 1.477 ++++ ./drivers/char/tpm/tpm_infineon.c 2006-06-26 18:16:33.000000000 -0400 1.478 +@@ -15,6 +15,7 @@ 1.479 + * License. 1.480 + */ 1.481 + 1.482 ++#include <linux/init.h> 1.483 + #include <linux/pnp.h> 1.484 + #include "tpm.h" 1.485 + 1.486 +@@ -104,7 +105,7 @@ static int empty_fifo(struct tpm_chip *c 1.487 + 1.488 + if (clear_wrfifo) { 1.489 + for (i = 0; i < 4096; i++) { 1.490 +- status = inb(chip->vendor->base + WRFIFO); 1.491 ++ status = inb(chip->vendor.base + WRFIFO); 1.492 + if (status == 0xff) { 1.493 + if (check == 5) 1.494 + break; 1.495 +@@ -124,8 +125,8 @@ static int empty_fifo(struct tpm_chip *c 1.496 + */ 1.497 + i = 0; 1.498 + do { 1.499 +- status = inb(chip->vendor->base + RDFIFO); 1.500 +- status = inb(chip->vendor->base + STAT); 1.501 ++ status = inb(chip->vendor.base + RDFIFO); 1.502 ++ status = inb(chip->vendor.base + STAT); 1.503 + i++; 1.504 + if (i == TPM_MAX_TRIES) 1.505 + return -EIO; 1.506 +@@ -138,7 +139,7 @@ static int wait(struct tpm_chip *chip, i 1.507 + int status; 1.508 + int i; 1.509 + for (i = 0; i < TPM_MAX_TRIES; i++) { 1.510 +- status = inb(chip->vendor->base + STAT); 1.511 ++ status = inb(chip->vendor.base + STAT); 1.512 + /* check the status-register if wait_for_bit is set */ 1.513 + if (status & 1 << wait_for_bit) 1.514 + break; 1.515 +@@ -157,7 +158,7 @@ static int wait(struct tpm_chip *chip, i 1.516 + static void wait_and_send(struct tpm_chip *chip, u8 sendbyte) 1.517 + { 1.518 + wait(chip, STAT_XFE); 1.519 +- outb(sendbyte, chip->vendor->base + WRFIFO); 1.520 ++ outb(sendbyte, chip->vendor.base + WRFIFO); 1.521 + } 1.522 + 1.523 + /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more 1.524 +@@ -204,7 +205,7 @@ recv_begin: 1.525 + ret = wait(chip, STAT_RDA); 1.526 + if (ret) 1.527 + return -EIO; 1.528 +- buf[i] = inb(chip->vendor->base + RDFIFO); 1.529 ++ buf[i] = inb(chip->vendor.base + RDFIFO); 1.530 + } 1.531 + 1.532 + if (buf[0] != TPM_VL_VER) { 1.533 +@@ -219,7 +220,7 @@ recv_begin: 1.534 + 1.535 + for (i = 0; i < size; i++) { 1.536 + wait(chip, STAT_RDA); 1.537 +- buf[i] = inb(chip->vendor->base + RDFIFO); 1.538 ++ buf[i] = inb(chip->vendor.base + RDFIFO); 1.539 + } 1.540 + 1.541 + if ((size == 0x6D00) && (buf[1] == 0x80)) { 1.542 +@@ -268,7 +269,7 @@ static int tpm_inf_send(struct tpm_chip 1.543 + u8 count_high, count_low, count_4, count_3, count_2, count_1; 1.544 + 1.545 + /* Disabling Reset, LP and IRQC */ 1.546 +- outb(RESET_LP_IRQC_DISABLE, chip->vendor->base + CMD); 1.547 ++ outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD); 1.548 + 1.549 + ret = empty_fifo(chip, 1); 1.550 + if (ret) { 1.551 +@@ -319,7 +320,7 @@ static void tpm_inf_cancel(struct tpm_ch 1.552 + 1.553 + static u8 tpm_inf_status(struct tpm_chip *chip) 1.554 + { 1.555 +- return inb(chip->vendor->base + STAT); 1.556 ++ return inb(chip->vendor.base + STAT); 1.557 + } 1.558 + 1.559 + static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); 1.560 +@@ -346,7 +347,7 @@ static struct file_operations inf_ops = 1.561 + .release = tpm_release, 1.562 + }; 1.563 + 1.564 +-static struct tpm_vendor_specific tpm_inf = { 1.565 ++static const struct tpm_vendor_specific tpm_inf = { 1.566 + .recv = tpm_inf_recv, 1.567 + .send = tpm_inf_send, 1.568 + .cancel = tpm_inf_cancel, 1.569 +@@ -375,6 +376,7 @@ static int __devinit tpm_inf_pnp_probe(s 1.570 + int version[2]; 1.571 + int productid[2]; 1.572 + char chipname[20]; 1.573 ++ struct tpm_chip *chip; 1.574 + 1.575 + /* read IO-ports through PnP */ 1.576 + if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && 1.577 +@@ -395,14 +397,13 @@ static int __devinit tpm_inf_pnp_probe(s 1.578 + goto err_last; 1.579 + } 1.580 + /* publish my base address and request region */ 1.581 +- tpm_inf.base = TPM_INF_BASE; 1.582 + if (request_region 1.583 +- (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) { 1.584 ++ (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) { 1.585 + rc = -EINVAL; 1.586 + goto err_last; 1.587 + } 1.588 +- if (request_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN, 1.589 +- "tpm_infineon0") == NULL) { 1.590 ++ if (request_region 1.591 ++ (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) { 1.592 + rc = -EINVAL; 1.593 + goto err_last; 1.594 + } 1.595 +@@ -442,9 +443,9 @@ static int __devinit tpm_inf_pnp_probe(s 1.596 + 1.597 + /* configure TPM with IO-ports */ 1.598 + outb(IOLIMH, TPM_INF_ADDR); 1.599 +- outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA); 1.600 ++ outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA); 1.601 + outb(IOLIML, TPM_INF_ADDR); 1.602 +- outb((tpm_inf.base & 0xff), TPM_INF_DATA); 1.603 ++ outb((TPM_INF_BASE & 0xff), TPM_INF_DATA); 1.604 + 1.605 + /* control if IO-ports are set correctly */ 1.606 + outb(IOLIMH, TPM_INF_ADDR); 1.607 +@@ -452,10 +453,10 @@ static int __devinit tpm_inf_pnp_probe(s 1.608 + outb(IOLIML, TPM_INF_ADDR); 1.609 + iol = inb(TPM_INF_DATA); 1.610 + 1.611 +- if ((ioh << 8 | iol) != tpm_inf.base) { 1.612 ++ if ((ioh << 8 | iol) != TPM_INF_BASE) { 1.613 + dev_err(&dev->dev, 1.614 +- "Could not set IO-ports to 0x%lx\n", 1.615 +- tpm_inf.base); 1.616 ++ "Could not set IO-ports to 0x%x\n", 1.617 ++ TPM_INF_BASE); 1.618 + rc = -EIO; 1.619 + goto err_release_region; 1.620 + } 1.621 +@@ -466,15 +467,15 @@ static int __devinit tpm_inf_pnp_probe(s 1.622 + outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); 1.623 + 1.624 + /* disable RESET, LP and IRQC */ 1.625 +- outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD); 1.626 ++ outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD); 1.627 + 1.628 + /* Finally, we're done, print some infos */ 1.629 + dev_info(&dev->dev, "TPM found: " 1.630 + "config base 0x%x, " 1.631 + "io base 0x%x, " 1.632 +- "chip version %02x%02x, " 1.633 +- "vendor id %x%x (Infineon), " 1.634 +- "product id %02x%02x" 1.635 ++ "chip version 0x%02x%02x, " 1.636 ++ "vendor id 0x%x%x (Infineon), " 1.637 ++ "product id 0x%02x%02x" 1.638 + "%s\n", 1.639 + TPM_INF_ADDR, 1.640 + TPM_INF_BASE, 1.641 +@@ -482,11 +483,10 @@ static int __devinit tpm_inf_pnp_probe(s 1.642 + vendorid[0], vendorid[1], 1.643 + productid[0], productid[1], chipname); 1.644 + 1.645 +- rc = tpm_register_hardware(&dev->dev, &tpm_inf); 1.646 +- if (rc < 0) { 1.647 +- rc = -ENODEV; 1.648 ++ if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) { 1.649 + goto err_release_region; 1.650 + } 1.651 ++ chip->vendor.base = TPM_INF_BASE; 1.652 + return 0; 1.653 + } else { 1.654 + rc = -ENODEV; 1.655 +@@ -494,7 +494,7 @@ static int __devinit tpm_inf_pnp_probe(s 1.656 + } 1.657 + 1.658 + err_release_region: 1.659 +- release_region(tpm_inf.base, TPM_INF_PORT_LEN); 1.660 ++ release_region(TPM_INF_BASE, TPM_INF_PORT_LEN); 1.661 + release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); 1.662 + 1.663 + err_last: 1.664 +@@ -506,7 +506,8 @@ static __devexit void tpm_inf_pnp_remove 1.665 + struct tpm_chip *chip = pnp_get_drvdata(dev); 1.666 + 1.667 + if (chip) { 1.668 +- release_region(chip->vendor->base, TPM_INF_PORT_LEN); 1.669 ++ release_region(TPM_INF_BASE, TPM_INF_PORT_LEN); 1.670 ++ release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); 1.671 + tpm_remove_hardware(chip->dev); 1.672 + } 1.673 + } 1.674 +@@ -520,7 +521,7 @@ static struct pnp_driver tpm_inf_pnp = { 1.675 + }, 1.676 + .id_table = tpm_pnp_tbl, 1.677 + .probe = tpm_inf_pnp_probe, 1.678 +- .remove = tpm_inf_pnp_remove, 1.679 ++ .remove = __devexit_p(tpm_inf_pnp_remove), 1.680 + }; 1.681 + 1.682 + static int __init init_inf(void) 1.683 +@@ -538,5 +539,5 @@ module_exit(cleanup_inf); 1.684 + 1.685 + MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>"); 1.686 + MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); 1.687 +-MODULE_VERSION("1.7"); 1.688 ++MODULE_VERSION("1.8"); 1.689 + MODULE_LICENSE("GPL"); 1.690 +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_nsc.c ./drivers/char/tpm/tpm_nsc.c 1.691 +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_nsc.c 2006-06-26 18:05:03.000000000 -0400 1.692 ++++ ./drivers/char/tpm/tpm_nsc.c 2006-06-26 18:16:33.000000000 -0400 1.693 +@@ -71,7 +71,7 @@ static int wait_for_stat(struct tpm_chip 1.694 + unsigned long stop; 1.695 + 1.696 + /* status immediately available check */ 1.697 +- *data = inb(chip->vendor->base + NSC_STATUS); 1.698 ++ *data = inb(chip->vendor.base + NSC_STATUS); 1.699 + if ((*data & mask) == val) 1.700 + return 0; 1.701 + 1.702 +@@ -79,7 +79,7 @@ static int wait_for_stat(struct tpm_chip 1.703 + stop = jiffies + 10 * HZ; 1.704 + do { 1.705 + msleep(TPM_TIMEOUT); 1.706 +- *data = inb(chip->vendor->base + 1); 1.707 ++ *data = inb(chip->vendor.base + 1); 1.708 + if ((*data & mask) == val) 1.709 + return 0; 1.710 + } 1.711 +@@ -94,9 +94,9 @@ static int nsc_wait_for_ready(struct tpm 1.712 + unsigned long stop; 1.713 + 1.714 + /* status immediately available check */ 1.715 +- status = inb(chip->vendor->base + NSC_STATUS); 1.716 ++ status = inb(chip->vendor.base + NSC_STATUS); 1.717 + if (status & NSC_STATUS_OBF) 1.718 +- status = inb(chip->vendor->base + NSC_DATA); 1.719 ++ status = inb(chip->vendor.base + NSC_DATA); 1.720 + if (status & NSC_STATUS_RDY) 1.721 + return 0; 1.722 + 1.723 +@@ -104,9 +104,9 @@ static int nsc_wait_for_ready(struct tpm 1.724 + stop = jiffies + 100; 1.725 + do { 1.726 + msleep(TPM_TIMEOUT); 1.727 +- status = inb(chip->vendor->base + NSC_STATUS); 1.728 ++ status = inb(chip->vendor.base + NSC_STATUS); 1.729 + if (status & NSC_STATUS_OBF) 1.730 +- status = inb(chip->vendor->base + NSC_DATA); 1.731 ++ status = inb(chip->vendor.base + NSC_DATA); 1.732 + if (status & NSC_STATUS_RDY) 1.733 + return 0; 1.734 + } 1.735 +@@ -132,7 +132,7 @@ static int tpm_nsc_recv(struct tpm_chip 1.736 + return -EIO; 1.737 + } 1.738 + if ((data = 1.739 +- inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) { 1.740 ++ inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) { 1.741 + dev_err(chip->dev, "not in normal mode (0x%x)\n", 1.742 + data); 1.743 + return -EIO; 1.744 +@@ -148,7 +148,7 @@ static int tpm_nsc_recv(struct tpm_chip 1.745 + } 1.746 + if (data & NSC_STATUS_F0) 1.747 + break; 1.748 +- *p = inb(chip->vendor->base + NSC_DATA); 1.749 ++ *p = inb(chip->vendor.base + NSC_DATA); 1.750 + } 1.751 + 1.752 + if ((data & NSC_STATUS_F0) == 0 && 1.753 +@@ -156,7 +156,7 @@ static int tpm_nsc_recv(struct tpm_chip 1.754 + dev_err(chip->dev, "F0 not set\n"); 1.755 + return -EIO; 1.756 + } 1.757 +- if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) { 1.758 ++ if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) { 1.759 + dev_err(chip->dev, 1.760 + "expected end of command(0x%x)\n", data); 1.761 + return -EIO; 1.762 +@@ -182,7 +182,7 @@ static int tpm_nsc_send(struct tpm_chip 1.763 + * fix it. Not sure why this is needed, we followed the flow 1.764 + * chart in the manual to the letter. 1.765 + */ 1.766 +- outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND); 1.767 ++ outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND); 1.768 + 1.769 + if (nsc_wait_for_ready(chip) != 0) 1.770 + return -EIO; 1.771 +@@ -192,7 +192,7 @@ static int tpm_nsc_send(struct tpm_chip 1.772 + return -EIO; 1.773 + } 1.774 + 1.775 +- outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND); 1.776 ++ outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND); 1.777 + if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) { 1.778 + dev_err(chip->dev, "IBR timeout\n"); 1.779 + return -EIO; 1.780 +@@ -204,26 +204,26 @@ static int tpm_nsc_send(struct tpm_chip 1.781 + "IBF timeout (while writing data)\n"); 1.782 + return -EIO; 1.783 + } 1.784 +- outb(buf[i], chip->vendor->base + NSC_DATA); 1.785 ++ outb(buf[i], chip->vendor.base + NSC_DATA); 1.786 + } 1.787 + 1.788 + if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { 1.789 + dev_err(chip->dev, "IBF timeout\n"); 1.790 + return -EIO; 1.791 + } 1.792 +- outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND); 1.793 ++ outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND); 1.794 + 1.795 + return count; 1.796 + } 1.797 + 1.798 + static void tpm_nsc_cancel(struct tpm_chip *chip) 1.799 + { 1.800 +- outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND); 1.801 ++ outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND); 1.802 + } 1.803 + 1.804 + static u8 tpm_nsc_status(struct tpm_chip *chip) 1.805 + { 1.806 +- return inb(chip->vendor->base + NSC_STATUS); 1.807 ++ return inb(chip->vendor.base + NSC_STATUS); 1.808 + } 1.809 + 1.810 + static struct file_operations nsc_ops = { 1.811 +@@ -250,7 +250,7 @@ static struct attribute * nsc_attrs[] = 1.812 + 1.813 + static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs }; 1.814 + 1.815 +-static struct tpm_vendor_specific tpm_nsc = { 1.816 ++static const struct tpm_vendor_specific tpm_nsc = { 1.817 + .recv = tpm_nsc_recv, 1.818 + .send = tpm_nsc_send, 1.819 + .cancel = tpm_nsc_cancel, 1.820 +@@ -268,7 +268,7 @@ static void __devexit tpm_nsc_remove(str 1.821 + { 1.822 + struct tpm_chip *chip = dev_get_drvdata(dev); 1.823 + if ( chip ) { 1.824 +- release_region(chip->vendor->base, 2); 1.825 ++ release_region(chip->vendor.base, 2); 1.826 + tpm_remove_hardware(chip->dev); 1.827 + } 1.828 + } 1.829 +@@ -286,7 +286,8 @@ static int __init init_nsc(void) 1.830 + int rc = 0; 1.831 + int lo, hi; 1.832 + int nscAddrBase = TPM_ADDR; 1.833 +- 1.834 ++ struct tpm_chip *chip; 1.835 ++ unsigned long base; 1.836 + 1.837 + /* verify that it is a National part (SID) */ 1.838 + if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) { 1.839 +@@ -300,7 +301,7 @@ static int __init init_nsc(void) 1.840 + 1.841 + hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI); 1.842 + lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO); 1.843 +- tpm_nsc.base = (hi<<8) | lo; 1.844 ++ base = (hi<<8) | lo; 1.845 + 1.846 + /* enable the DPM module */ 1.847 + tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01); 1.848 +@@ -320,13 +321,15 @@ static int __init init_nsc(void) 1.849 + if ((rc = platform_device_register(pdev)) < 0) 1.850 + goto err_free_dev; 1.851 + 1.852 +- if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) { 1.853 ++ if (request_region(base, 2, "tpm_nsc0") == NULL ) { 1.854 + rc = -EBUSY; 1.855 + goto err_unreg_dev; 1.856 + } 1.857 + 1.858 +- if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0) 1.859 ++ if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) { 1.860 ++ rc = -ENODEV; 1.861 + goto err_rel_reg; 1.862 ++ } 1.863 + 1.864 + dev_dbg(&pdev->dev, "NSC TPM detected\n"); 1.865 + dev_dbg(&pdev->dev, 1.866 +@@ -361,10 +364,12 @@ static int __init init_nsc(void) 1.867 + "NSC TPM revision %d\n", 1.868 + tpm_read_index(nscAddrBase, 0x27) & 0x1F); 1.869 + 1.870 ++ chip->vendor.base = base; 1.871 ++ 1.872 + return 0; 1.873 + 1.874 + err_rel_reg: 1.875 +- release_region(tpm_nsc.base, 2); 1.876 ++ release_region(base, 2); 1.877 + err_unreg_dev: 1.878 + platform_device_unregister(pdev); 1.879 + err_free_dev: 1.880 +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_tis.c ./drivers/char/tpm/tpm_tis.c 1.881 +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_tis.c 1969-12-31 19:00:00.000000000 -0500 1.882 ++++ ./drivers/char/tpm/tpm_tis.c 2006-06-26 18:16:33.000000000 -0400 1.883 +@@ -0,0 +1,665 @@ 1.884 ++/* 1.885 ++ * Copyright (C) 2005, 2006 IBM Corporation 1.886 ++ * 1.887 ++ * Authors: 1.888 ++ * Leendert van Doorn <leendert@watson.ibm.com> 1.889 ++ * Kylene Hall <kjhall@us.ibm.com> 1.890 ++ * 1.891 ++ * Device driver for TCG/TCPA TPM (trusted platform module). 1.892 ++ * Specifications at www.trustedcomputinggroup.org 1.893 ++ * 1.894 ++ * This device driver implements the TPM interface as defined in 1.895 ++ * the TCG TPM Interface Spec version 1.2, revision 1.0. 1.896 ++ * 1.897 ++ * This program is free software; you can redistribute it and/or 1.898 ++ * modify it under the terms of the GNU General Public License as 1.899 ++ * published by the Free Software Foundation, version 2 of the 1.900 ++ * License. 1.901 ++ */ 1.902 ++#include <linux/init.h> 1.903 ++#include <linux/module.h> 1.904 ++#include <linux/moduleparam.h> 1.905 ++#include <linux/pnp.h> 1.906 ++#include <linux/interrupt.h> 1.907 ++#include <linux/wait.h> 1.908 ++#include "tpm.h" 1.909 ++ 1.910 ++#define TPM_HEADER_SIZE 10 1.911 ++ 1.912 ++enum tis_access { 1.913 ++ TPM_ACCESS_VALID = 0x80, 1.914 ++ TPM_ACCESS_ACTIVE_LOCALITY = 0x20, 1.915 ++ TPM_ACCESS_REQUEST_PENDING = 0x04, 1.916 ++ TPM_ACCESS_REQUEST_USE = 0x02, 1.917 ++}; 1.918 ++ 1.919 ++enum tis_status { 1.920 ++ TPM_STS_VALID = 0x80, 1.921 ++ TPM_STS_COMMAND_READY = 0x40, 1.922 ++ TPM_STS_GO = 0x20, 1.923 ++ TPM_STS_DATA_AVAIL = 0x10, 1.924 ++ TPM_STS_DATA_EXPECT = 0x08, 1.925 ++}; 1.926 ++ 1.927 ++enum tis_int_flags { 1.928 ++ TPM_GLOBAL_INT_ENABLE = 0x80000000, 1.929 ++ TPM_INTF_BURST_COUNT_STATIC = 0x100, 1.930 ++ TPM_INTF_CMD_READY_INT = 0x080, 1.931 ++ TPM_INTF_INT_EDGE_FALLING = 0x040, 1.932 ++ TPM_INTF_INT_EDGE_RISING = 0x020, 1.933 ++ TPM_INTF_INT_LEVEL_LOW = 0x010, 1.934 ++ TPM_INTF_INT_LEVEL_HIGH = 0x008, 1.935 ++ TPM_INTF_LOCALITY_CHANGE_INT = 0x004, 1.936 ++ TPM_INTF_STS_VALID_INT = 0x002, 1.937 ++ TPM_INTF_DATA_AVAIL_INT = 0x001, 1.938 ++}; 1.939 ++ 1.940 ++enum tis_defaults { 1.941 ++ TIS_MEM_BASE = 0xFED40000, 1.942 ++ TIS_MEM_LEN = 0x5000, 1.943 ++ TIS_SHORT_TIMEOUT = 750, /* ms */ 1.944 ++ TIS_LONG_TIMEOUT = 2000, /* 2 sec */ 1.945 ++}; 1.946 ++ 1.947 ++#define TPM_ACCESS(l) (0x0000 | ((l) << 12)) 1.948 ++#define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12)) 1.949 ++#define TPM_INT_VECTOR(l) (0x000C | ((l) << 12)) 1.950 ++#define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) 1.951 ++#define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) 1.952 ++#define TPM_STS(l) (0x0018 | ((l) << 12)) 1.953 ++#define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) 1.954 ++ 1.955 ++#define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) 1.956 ++#define TPM_RID(l) (0x0F04 | ((l) << 12)) 1.957 ++ 1.958 ++static LIST_HEAD(tis_chips); 1.959 ++static DEFINE_SPINLOCK(tis_lock); 1.960 ++ 1.961 ++static int check_locality(struct tpm_chip *chip, int l) 1.962 ++{ 1.963 ++ if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) & 1.964 ++ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == 1.965 ++ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) 1.966 ++ return chip->vendor.locality = l; 1.967 ++ 1.968 ++ return -1; 1.969 ++} 1.970 ++ 1.971 ++static void release_locality(struct tpm_chip *chip, int l, int force) 1.972 ++{ 1.973 ++ if (force || (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) & 1.974 ++ (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == 1.975 ++ (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) 1.976 ++ iowrite8(TPM_ACCESS_ACTIVE_LOCALITY, 1.977 ++ chip->vendor.iobase + TPM_ACCESS(l)); 1.978 ++} 1.979 ++ 1.980 ++static int request_locality(struct tpm_chip *chip, int l) 1.981 ++{ 1.982 ++ unsigned long stop; 1.983 ++ long rc; 1.984 ++ 1.985 ++ if (check_locality(chip, l) >= 0) 1.986 ++ return l; 1.987 ++ 1.988 ++ iowrite8(TPM_ACCESS_REQUEST_USE, 1.989 ++ chip->vendor.iobase + TPM_ACCESS(l)); 1.990 ++ 1.991 ++ if (chip->vendor.irq) { 1.992 ++ rc = wait_event_interruptible_timeout(chip->vendor.int_queue, 1.993 ++ (check_locality 1.994 ++ (chip, l) >= 0), 1.995 ++ chip->vendor.timeout_a); 1.996 ++ if (rc > 0) 1.997 ++ return l; 1.998 ++ 1.999 ++ } else { 1.1000 ++ /* wait for burstcount */ 1.1001 ++ stop = jiffies + chip->vendor.timeout_a; 1.1002 ++ do { 1.1003 ++ if (check_locality(chip, l) >= 0) 1.1004 ++ return l; 1.1005 ++ msleep(TPM_TIMEOUT); 1.1006 ++ } 1.1007 ++ while (time_before(jiffies, stop)); 1.1008 ++ } 1.1009 ++ return -1; 1.1010 ++} 1.1011 ++ 1.1012 ++static u8 tpm_tis_status(struct tpm_chip *chip) 1.1013 ++{ 1.1014 ++ return ioread8(chip->vendor.iobase + 1.1015 ++ TPM_STS(chip->vendor.locality)); 1.1016 ++} 1.1017 ++ 1.1018 ++static void tpm_tis_ready(struct tpm_chip *chip) 1.1019 ++{ 1.1020 ++ /* this causes the current command to be aborted */ 1.1021 ++ iowrite8(TPM_STS_COMMAND_READY, 1.1022 ++ chip->vendor.iobase + TPM_STS(chip->vendor.locality)); 1.1023 ++} 1.1024 ++ 1.1025 ++static int get_burstcount(struct tpm_chip *chip) 1.1026 ++{ 1.1027 ++ unsigned long stop; 1.1028 ++ int burstcnt; 1.1029 ++ 1.1030 ++ /* wait for burstcount */ 1.1031 ++ /* which timeout value, spec has 2 answers (c & d) */ 1.1032 ++ stop = jiffies + chip->vendor.timeout_d; 1.1033 ++ do { 1.1034 ++ burstcnt = ioread8(chip->vendor.iobase + 1.1035 ++ TPM_STS(chip->vendor.locality) + 1); 1.1036 ++ burstcnt += ioread8(chip->vendor.iobase + 1.1037 ++ TPM_STS(chip->vendor.locality) + 1.1038 ++ 2) << 8; 1.1039 ++ if (burstcnt) 1.1040 ++ return burstcnt; 1.1041 ++ msleep(TPM_TIMEOUT); 1.1042 ++ } while (time_before(jiffies, stop)); 1.1043 ++ return -EBUSY; 1.1044 ++} 1.1045 ++ 1.1046 ++static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, 1.1047 ++ wait_queue_head_t *queue) 1.1048 ++{ 1.1049 ++ unsigned long stop; 1.1050 ++ long rc; 1.1051 ++ u8 status; 1.1052 ++ 1.1053 ++ /* check current status */ 1.1054 ++ status = tpm_tis_status(chip); 1.1055 ++ if ((status & mask) == mask) 1.1056 ++ return 0; 1.1057 ++ 1.1058 ++ if (chip->vendor.irq) { 1.1059 ++ rc = wait_event_interruptible_timeout(*queue, 1.1060 ++ ((tpm_tis_status 1.1061 ++ (chip) & mask) == 1.1062 ++ mask), timeout); 1.1063 ++ if (rc > 0) 1.1064 ++ return 0; 1.1065 ++ } else { 1.1066 ++ stop = jiffies + timeout; 1.1067 ++ do { 1.1068 ++ msleep(TPM_TIMEOUT); 1.1069 ++ status = tpm_tis_status(chip); 1.1070 ++ if ((status & mask) == mask) 1.1071 ++ return 0; 1.1072 ++ } while (time_before(jiffies, stop)); 1.1073 ++ } 1.1074 ++ return -ETIME; 1.1075 ++} 1.1076 ++ 1.1077 ++static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) 1.1078 ++{ 1.1079 ++ int size = 0, burstcnt; 1.1080 ++ while (size < count && 1.1081 ++ wait_for_stat(chip, 1.1082 ++ TPM_STS_DATA_AVAIL | TPM_STS_VALID, 1.1083 ++ chip->vendor.timeout_c, 1.1084 ++ &chip->vendor.read_queue) 1.1085 ++ == 0) { 1.1086 ++ burstcnt = get_burstcount(chip); 1.1087 ++ for (; burstcnt > 0 && size < count; burstcnt--) 1.1088 ++ buf[size++] = ioread8(chip->vendor.iobase + 1.1089 ++ TPM_DATA_FIFO(chip->vendor. 1.1090 ++ locality)); 1.1091 ++ } 1.1092 ++ return size; 1.1093 ++} 1.1094 ++ 1.1095 ++static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) 1.1096 ++{ 1.1097 ++ int size = 0; 1.1098 ++ int expected, status; 1.1099 ++ 1.1100 ++ if (count < TPM_HEADER_SIZE) { 1.1101 ++ size = -EIO; 1.1102 ++ goto out; 1.1103 ++ } 1.1104 ++ 1.1105 ++ /* read first 10 bytes, including tag, paramsize, and result */ 1.1106 ++ if ((size = 1.1107 ++ recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) { 1.1108 ++ dev_err(chip->dev, "Unable to read header\n"); 1.1109 ++ goto out; 1.1110 ++ } 1.1111 ++ 1.1112 ++ expected = be32_to_cpu(*(__be32 *) (buf + 2)); 1.1113 ++ if (expected > count) { 1.1114 ++ size = -EIO; 1.1115 ++ goto out; 1.1116 ++ } 1.1117 ++ 1.1118 ++ if ((size += 1.1119 ++ recv_data(chip, &buf[TPM_HEADER_SIZE], 1.1120 ++ expected - TPM_HEADER_SIZE)) < expected) { 1.1121 ++ dev_err(chip->dev, "Unable to read remainder of result\n"); 1.1122 ++ size = -ETIME; 1.1123 ++ goto out; 1.1124 ++ } 1.1125 ++ 1.1126 ++ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, 1.1127 ++ &chip->vendor.int_queue); 1.1128 ++ status = tpm_tis_status(chip); 1.1129 ++ if (status & TPM_STS_DATA_AVAIL) { /* retry? */ 1.1130 ++ dev_err(chip->dev, "Error left over data\n"); 1.1131 ++ size = -EIO; 1.1132 ++ goto out; 1.1133 ++ } 1.1134 ++ 1.1135 ++out: 1.1136 ++ tpm_tis_ready(chip); 1.1137 ++ release_locality(chip, chip->vendor.locality, 0); 1.1138 ++ return size; 1.1139 ++} 1.1140 ++ 1.1141 ++/* 1.1142 ++ * If interrupts are used (signaled by an irq set in the vendor structure) 1.1143 ++ * tpm.c can skip polling for the data to be available as the interrupt is 1.1144 ++ * waited for here 1.1145 ++ */ 1.1146 ++static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) 1.1147 ++{ 1.1148 ++ int rc, status, burstcnt; 1.1149 ++ size_t count = 0; 1.1150 ++ u32 ordinal; 1.1151 ++ 1.1152 ++ if (request_locality(chip, 0) < 0) 1.1153 ++ return -EBUSY; 1.1154 ++ 1.1155 ++ status = tpm_tis_status(chip); 1.1156 ++ if ((status & TPM_STS_COMMAND_READY) == 0) { 1.1157 ++ tpm_tis_ready(chip); 1.1158 ++ if (wait_for_stat 1.1159 ++ (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, 1.1160 ++ &chip->vendor.int_queue) < 0) { 1.1161 ++ rc = -ETIME; 1.1162 ++ goto out_err; 1.1163 ++ } 1.1164 ++ } 1.1165 ++ 1.1166 ++ while (count < len - 1) { 1.1167 ++ burstcnt = get_burstcount(chip); 1.1168 ++ for (; burstcnt > 0 && count < len - 1; burstcnt--) { 1.1169 ++ iowrite8(buf[count], chip->vendor.iobase + 1.1170 ++ TPM_DATA_FIFO(chip->vendor.locality)); 1.1171 ++ count++; 1.1172 ++ } 1.1173 ++ 1.1174 ++ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, 1.1175 ++ &chip->vendor.int_queue); 1.1176 ++ status = tpm_tis_status(chip); 1.1177 ++ if ((status & TPM_STS_DATA_EXPECT) == 0) { 1.1178 ++ rc = -EIO; 1.1179 ++ goto out_err; 1.1180 ++ } 1.1181 ++ } 1.1182 ++ 1.1183 ++ /* write last byte */ 1.1184 ++ iowrite8(buf[count], 1.1185 ++ chip->vendor.iobase + 1.1186 ++ TPM_DATA_FIFO(chip->vendor.locality)); 1.1187 ++ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, 1.1188 ++ &chip->vendor.int_queue); 1.1189 ++ status = tpm_tis_status(chip); 1.1190 ++ if ((status & TPM_STS_DATA_EXPECT) != 0) { 1.1191 ++ rc = -EIO; 1.1192 ++ goto out_err; 1.1193 ++ } 1.1194 ++ 1.1195 ++ /* go and do it */ 1.1196 ++ iowrite8(TPM_STS_GO, 1.1197 ++ chip->vendor.iobase + TPM_STS(chip->vendor.locality)); 1.1198 ++ 1.1199 ++ if (chip->vendor.irq) { 1.1200 ++ ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); 1.1201 ++ if (wait_for_stat 1.1202 ++ (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, 1.1203 ++ tpm_calc_ordinal_duration(chip, ordinal), 1.1204 ++ &chip->vendor.read_queue) < 0) { 1.1205 ++ rc = -ETIME; 1.1206 ++ goto out_err; 1.1207 ++ } 1.1208 ++ } 1.1209 ++ return len; 1.1210 ++out_err: 1.1211 ++ tpm_tis_ready(chip); 1.1212 ++ release_locality(chip, chip->vendor.locality, 0); 1.1213 ++ return rc; 1.1214 ++} 1.1215 ++ 1.1216 ++static struct file_operations tis_ops = { 1.1217 ++ .owner = THIS_MODULE, 1.1218 ++ .llseek = no_llseek, 1.1219 ++ .open = tpm_open, 1.1220 ++ .read = tpm_read, 1.1221 ++ .write = tpm_write, 1.1222 ++ .release = tpm_release, 1.1223 ++}; 1.1224 ++ 1.1225 ++static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); 1.1226 ++static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); 1.1227 ++static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL); 1.1228 ++static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL); 1.1229 ++static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL); 1.1230 ++static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, 1.1231 ++ NULL); 1.1232 ++static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); 1.1233 ++static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); 1.1234 ++ 1.1235 ++static struct attribute *tis_attrs[] = { 1.1236 ++ &dev_attr_pubek.attr, 1.1237 ++ &dev_attr_pcrs.attr, 1.1238 ++ &dev_attr_enabled.attr, 1.1239 ++ &dev_attr_active.attr, 1.1240 ++ &dev_attr_owned.attr, 1.1241 ++ &dev_attr_temp_deactivated.attr, 1.1242 ++ &dev_attr_caps.attr, 1.1243 ++ &dev_attr_cancel.attr, NULL, 1.1244 ++}; 1.1245 ++ 1.1246 ++static struct attribute_group tis_attr_grp = { 1.1247 ++ .attrs = tis_attrs 1.1248 ++}; 1.1249 ++ 1.1250 ++static struct tpm_vendor_specific tpm_tis = { 1.1251 ++ .status = tpm_tis_status, 1.1252 ++ .recv = tpm_tis_recv, 1.1253 ++ .send = tpm_tis_send, 1.1254 ++ .cancel = tpm_tis_ready, 1.1255 ++ .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, 1.1256 ++ .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, 1.1257 ++ .req_canceled = TPM_STS_COMMAND_READY, 1.1258 ++ .attr_group = &tis_attr_grp, 1.1259 ++ .miscdev = { 1.1260 ++ .fops = &tis_ops,}, 1.1261 ++}; 1.1262 ++ 1.1263 ++static irqreturn_t tis_int_probe(int irq, void *dev_id, struct pt_regs *regs) 1.1264 ++{ 1.1265 ++ struct tpm_chip *chip = (struct tpm_chip *) dev_id; 1.1266 ++ u32 interrupt; 1.1267 ++ 1.1268 ++ interrupt = ioread32(chip->vendor.iobase + 1.1269 ++ TPM_INT_STATUS(chip->vendor.locality)); 1.1270 ++ 1.1271 ++ if (interrupt == 0) 1.1272 ++ return IRQ_NONE; 1.1273 ++ 1.1274 ++ chip->vendor.irq = irq; 1.1275 ++ 1.1276 ++ /* Clear interrupts handled with TPM_EOI */ 1.1277 ++ iowrite32(interrupt, 1.1278 ++ chip->vendor.iobase + 1.1279 ++ TPM_INT_STATUS(chip->vendor.locality)); 1.1280 ++ return IRQ_HANDLED; 1.1281 ++} 1.1282 ++ 1.1283 ++static irqreturn_t tis_int_handler(int irq, void *dev_id, struct pt_regs *regs) 1.1284 ++{ 1.1285 ++ struct tpm_chip *chip = (struct tpm_chip *) dev_id; 1.1286 ++ u32 interrupt; 1.1287 ++ int i; 1.1288 ++ 1.1289 ++ interrupt = ioread32(chip->vendor.iobase + 1.1290 ++ TPM_INT_STATUS(chip->vendor.locality)); 1.1291 ++ 1.1292 ++ if (interrupt == 0) 1.1293 ++ return IRQ_NONE; 1.1294 ++ 1.1295 ++ if (interrupt & TPM_INTF_DATA_AVAIL_INT) 1.1296 ++ wake_up_interruptible(&chip->vendor.read_queue); 1.1297 ++ if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT) 1.1298 ++ for (i = 0; i < 5; i++) 1.1299 ++ if (check_locality(chip, i) >= 0) 1.1300 ++ break; 1.1301 ++ if (interrupt & 1.1302 ++ (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT | 1.1303 ++ TPM_INTF_CMD_READY_INT)) 1.1304 ++ wake_up_interruptible(&chip->vendor.int_queue); 1.1305 ++ 1.1306 ++ /* Clear interrupts handled with TPM_EOI */ 1.1307 ++ iowrite32(interrupt, 1.1308 ++ chip->vendor.iobase + 1.1309 ++ TPM_INT_STATUS(chip->vendor.locality)); 1.1310 ++ return IRQ_HANDLED; 1.1311 ++} 1.1312 ++ 1.1313 ++static int interrupts = 1; 1.1314 ++module_param(interrupts, bool, 0444); 1.1315 ++MODULE_PARM_DESC(interrupts, "Enable interrupts"); 1.1316 ++ 1.1317 ++static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, 1.1318 ++ const struct pnp_device_id *pnp_id) 1.1319 ++{ 1.1320 ++ u32 vendor, intfcaps, intmask; 1.1321 ++ int rc, i; 1.1322 ++ unsigned long start, len; 1.1323 ++ struct tpm_chip *chip; 1.1324 ++ 1.1325 ++ start = pnp_mem_start(pnp_dev, 0); 1.1326 ++ len = pnp_mem_len(pnp_dev, 0); 1.1327 ++ 1.1328 ++ if (!start) 1.1329 ++ start = TIS_MEM_BASE; 1.1330 ++ if (!len) 1.1331 ++ len = TIS_MEM_LEN; 1.1332 ++ 1.1333 ++ if (!(chip = tpm_register_hardware(&pnp_dev->dev, &tpm_tis))) 1.1334 ++ return -ENODEV; 1.1335 ++ 1.1336 ++ chip->vendor.iobase = ioremap(start, len); 1.1337 ++ if (!chip->vendor.iobase) { 1.1338 ++ rc = -EIO; 1.1339 ++ goto out_err; 1.1340 ++ } 1.1341 ++ 1.1342 ++ vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); 1.1343 ++ 1.1344 ++ /* Default timeouts */ 1.1345 ++ chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); 1.1346 ++ chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); 1.1347 ++ chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); 1.1348 ++ chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); 1.1349 ++ 1.1350 ++ dev_info(&pnp_dev->dev, 1.1351 ++ "1.2 TPM (device-id 0x%X, rev-id %d)\n", 1.1352 ++ vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); 1.1353 ++ 1.1354 ++ /* Figure out the capabilities */ 1.1355 ++ intfcaps = 1.1356 ++ ioread32(chip->vendor.iobase + 1.1357 ++ TPM_INTF_CAPS(chip->vendor.locality)); 1.1358 ++ dev_dbg(&pnp_dev->dev, "TPM interface capabilities (0x%x):\n", 1.1359 ++ intfcaps); 1.1360 ++ if (intfcaps & TPM_INTF_BURST_COUNT_STATIC) 1.1361 ++ dev_dbg(&pnp_dev->dev, "\tBurst Count Static\n"); 1.1362 ++ if (intfcaps & TPM_INTF_CMD_READY_INT) 1.1363 ++ dev_dbg(&pnp_dev->dev, "\tCommand Ready Int Support\n"); 1.1364 ++ if (intfcaps & TPM_INTF_INT_EDGE_FALLING) 1.1365 ++ dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Falling\n"); 1.1366 ++ if (intfcaps & TPM_INTF_INT_EDGE_RISING) 1.1367 ++ dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Rising\n"); 1.1368 ++ if (intfcaps & TPM_INTF_INT_LEVEL_LOW) 1.1369 ++ dev_dbg(&pnp_dev->dev, "\tInterrupt Level Low\n"); 1.1370 ++ if (intfcaps & TPM_INTF_INT_LEVEL_HIGH) 1.1371 ++ dev_dbg(&pnp_dev->dev, "\tInterrupt Level High\n"); 1.1372 ++ if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) 1.1373 ++ dev_dbg(&pnp_dev->dev, "\tLocality Change Int Support\n"); 1.1374 ++ if (intfcaps & TPM_INTF_STS_VALID_INT) 1.1375 ++ dev_dbg(&pnp_dev->dev, "\tSts Valid Int Support\n"); 1.1376 ++ if (intfcaps & TPM_INTF_DATA_AVAIL_INT) 1.1377 ++ dev_dbg(&pnp_dev->dev, "\tData Avail Int Support\n"); 1.1378 ++ 1.1379 ++ if (request_locality(chip, 0) != 0) { 1.1380 ++ rc = -ENODEV; 1.1381 ++ goto out_err; 1.1382 ++ } 1.1383 ++ 1.1384 ++ /* INTERRUPT Setup */ 1.1385 ++ init_waitqueue_head(&chip->vendor.read_queue); 1.1386 ++ init_waitqueue_head(&chip->vendor.int_queue); 1.1387 ++ 1.1388 ++ intmask = 1.1389 ++ ioread32(chip->vendor.iobase + 1.1390 ++ TPM_INT_ENABLE(chip->vendor.locality)); 1.1391 ++ 1.1392 ++ intmask |= TPM_INTF_CMD_READY_INT 1.1393 ++ | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT 1.1394 ++ | TPM_INTF_STS_VALID_INT; 1.1395 ++ 1.1396 ++ iowrite32(intmask, 1.1397 ++ chip->vendor.iobase + 1.1398 ++ TPM_INT_ENABLE(chip->vendor.locality)); 1.1399 ++ if (interrupts) { 1.1400 ++ chip->vendor.irq = 1.1401 ++ ioread8(chip->vendor.iobase + 1.1402 ++ TPM_INT_VECTOR(chip->vendor.locality)); 1.1403 ++ 1.1404 ++ for (i = 3; i < 16 && chip->vendor.irq == 0; i++) { 1.1405 ++ iowrite8(i, chip->vendor.iobase + 1.1406 ++ TPM_INT_VECTOR(chip->vendor.locality)); 1.1407 ++ if (request_irq 1.1408 ++ (i, tis_int_probe, SA_SHIRQ, 1.1409 ++ chip->vendor.miscdev.name, chip) != 0) { 1.1410 ++ dev_info(chip->dev, 1.1411 ++ "Unable to request irq: %d for probe\n", 1.1412 ++ i); 1.1413 ++ continue; 1.1414 ++ } 1.1415 ++ 1.1416 ++ /* Clear all existing */ 1.1417 ++ iowrite32(ioread32 1.1418 ++ (chip->vendor.iobase + 1.1419 ++ TPM_INT_STATUS(chip->vendor.locality)), 1.1420 ++ chip->vendor.iobase + 1.1421 ++ TPM_INT_STATUS(chip->vendor.locality)); 1.1422 ++ 1.1423 ++ /* Turn on */ 1.1424 ++ iowrite32(intmask | TPM_GLOBAL_INT_ENABLE, 1.1425 ++ chip->vendor.iobase + 1.1426 ++ TPM_INT_ENABLE(chip->vendor.locality)); 1.1427 ++ 1.1428 ++ /* Generate Interrupts */ 1.1429 ++ tpm_gen_interrupt(chip); 1.1430 ++ 1.1431 ++ /* Turn off */ 1.1432 ++ iowrite32(intmask, 1.1433 ++ chip->vendor.iobase + 1.1434 ++ TPM_INT_ENABLE(chip->vendor.locality)); 1.1435 ++ free_irq(i, chip); 1.1436 ++ } 1.1437 ++ } 1.1438 ++ if (chip->vendor.irq) { 1.1439 ++ iowrite8(chip->vendor.irq, 1.1440 ++ chip->vendor.iobase + 1.1441 ++ TPM_INT_VECTOR(chip->vendor.locality)); 1.1442 ++ if (request_irq 1.1443 ++ (chip->vendor.irq, tis_int_handler, SA_SHIRQ, 1.1444 ++ chip->vendor.miscdev.name, chip) != 0) { 1.1445 ++ dev_info(chip->dev, 1.1446 ++ "Unable to request irq: %d for use\n", 1.1447 ++ chip->vendor.irq); 1.1448 ++ chip->vendor.irq = 0; 1.1449 ++ } else { 1.1450 ++ /* Clear all existing */ 1.1451 ++ iowrite32(ioread32 1.1452 ++ (chip->vendor.iobase + 1.1453 ++ TPM_INT_STATUS(chip->vendor.locality)), 1.1454 ++ chip->vendor.iobase + 1.1455 ++ TPM_INT_STATUS(chip->vendor.locality)); 1.1456 ++ 1.1457 ++ /* Turn on */ 1.1458 ++ iowrite32(intmask | TPM_GLOBAL_INT_ENABLE, 1.1459 ++ chip->vendor.iobase + 1.1460 ++ TPM_INT_ENABLE(chip->vendor.locality)); 1.1461 ++ } 1.1462 ++ } 1.1463 ++ 1.1464 ++ INIT_LIST_HEAD(&chip->vendor.list); 1.1465 ++ spin_lock(&tis_lock); 1.1466 ++ list_add(&chip->vendor.list, &tis_chips); 1.1467 ++ spin_unlock(&tis_lock); 1.1468 ++ 1.1469 ++ tpm_get_timeouts(chip); 1.1470 ++ tpm_continue_selftest(chip); 1.1471 ++ 1.1472 ++ return 0; 1.1473 ++out_err: 1.1474 ++ if (chip->vendor.iobase) 1.1475 ++ iounmap(chip->vendor.iobase); 1.1476 ++ tpm_remove_hardware(chip->dev); 1.1477 ++ return rc; 1.1478 ++} 1.1479 ++ 1.1480 ++static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg) 1.1481 ++{ 1.1482 ++ return tpm_pm_suspend(&dev->dev, msg); 1.1483 ++} 1.1484 ++ 1.1485 ++static int tpm_tis_pnp_resume(struct pnp_dev *dev) 1.1486 ++{ 1.1487 ++ return tpm_pm_resume(&dev->dev); 1.1488 ++} 1.1489 ++ 1.1490 ++static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { 1.1491 ++ {"PNP0C31", 0}, /* TPM */ 1.1492 ++ {"ATM1200", 0}, /* Atmel */ 1.1493 ++ {"IFX0102", 0}, /* Infineon */ 1.1494 ++ {"BCM0101", 0}, /* Broadcom */ 1.1495 ++ {"NSC1200", 0}, /* National */ 1.1496 ++ /* Add new here */ 1.1497 ++ {"", 0}, /* User Specified */ 1.1498 ++ {"", 0} /* Terminator */ 1.1499 ++}; 1.1500 ++ 1.1501 ++static struct pnp_driver tis_pnp_driver = { 1.1502 ++ .name = "tpm_tis", 1.1503 ++ .id_table = tpm_pnp_tbl, 1.1504 ++ .probe = tpm_tis_pnp_init, 1.1505 ++ .suspend = tpm_tis_pnp_suspend, 1.1506 ++ .resume = tpm_tis_pnp_resume, 1.1507 ++}; 1.1508 ++ 1.1509 ++#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2 1.1510 ++module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, 1.1511 ++ sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); 1.1512 ++MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); 1.1513 ++ 1.1514 ++static int __init init_tis(void) 1.1515 ++{ 1.1516 ++ return pnp_register_driver(&tis_pnp_driver); 1.1517 ++} 1.1518 ++ 1.1519 ++static void __exit cleanup_tis(void) 1.1520 ++{ 1.1521 ++ struct tpm_vendor_specific *i, *j; 1.1522 ++ struct tpm_chip *chip; 1.1523 ++ spin_lock(&tis_lock); 1.1524 ++ list_for_each_entry_safe(i, j, &tis_chips, list) { 1.1525 ++ chip = to_tpm_chip(i); 1.1526 ++ iowrite32(~TPM_GLOBAL_INT_ENABLE & 1.1527 ++ ioread32(chip->vendor.iobase + 1.1528 ++ TPM_INT_ENABLE(chip->vendor. 1.1529 ++ locality)), 1.1530 ++ chip->vendor.iobase + 1.1531 ++ TPM_INT_ENABLE(chip->vendor.locality)); 1.1532 ++ release_locality(chip, chip->vendor.locality, 1); 1.1533 ++ if (chip->vendor.irq) 1.1534 ++ free_irq(chip->vendor.irq, chip); 1.1535 ++ iounmap(i->iobase); 1.1536 ++ list_del(&i->list); 1.1537 ++ tpm_remove_hardware(chip->dev); 1.1538 ++ } 1.1539 ++ spin_unlock(&tis_lock); 1.1540 ++ pnp_unregister_driver(&tis_pnp_driver); 1.1541 ++} 1.1542 ++ 1.1543 ++module_init(init_tis); 1.1544 ++module_exit(cleanup_tis); 1.1545 ++MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); 1.1546 ++MODULE_DESCRIPTION("TPM Driver"); 1.1547 ++MODULE_VERSION("2.0"); 1.1548 ++MODULE_LICENSE("GPL"); 1.1549 +