/* * request_locality request the TPM locality * @param: chip, the chip description * @return: the active locality or EACCESS. */ static int request_locality(struct tpm_chip *chip) { unsigned long stop; long rc; struct i2c_client *client; u8 data; client = (struct i2c_client *)TPM_VPRIV(chip); if (check_locality(chip) == chip->vendor.locality) return chip->vendor.locality; data = TPM_ACCESS_REQUEST_USE; rc = I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1); if (rc < 0) goto end; if (chip->vendor.irq) { rc = wait_for_serirq_timeout(chip, (check_locality (chip) >= 0), chip->vendor.timeout_a); if (rc > 0) return chip->vendor.locality; } else { stop = jiffies + chip->vendor.timeout_a; do { if (check_locality(chip) >= 0) return chip->vendor.locality; msleep(TPM_TIMEOUT); } while (time_before(jiffies, stop)); } rc = -EACCES; end: return rc; } /* request_locality() */
static void tpm_tis_irq_handler(evtchn_port_t port, struct pt_regs *regs, void* data) { struct tpm_chip* tpm = data; uint32_t interrupt; int i; interrupt = ioread32(TPM_INT_STATUS(tpm, tpm->locality)); if(interrupt == 0) { return; } if(interrupt & TPM_INTF_DATA_AVAIL_INT) { wake_up(&tpm->read_queue); } if(interrupt & TPM_INTF_LOCALITY_CHANGE_INT) { for(i = 0; i < 5; ++i) { if(check_locality(tpm, i) >= 0) { break; } } } if(interrupt & (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT | TPM_INTF_CMD_READY_INT)) { wake_up(&tpm->int_queue); } /* Clear interrupts handled with TPM_EOI */ iowrite32(TPM_INT_STATUS(tpm, tpm->locality), interrupt); ioread32(TPM_INT_STATUS(tpm, tpm->locality)); return; }
static int request_locality(struct tpm_chip *chip, int loc) { unsigned long stop; u8 buf = TPM_ACCESS_REQUEST_USE; if (check_locality(chip, loc) >= 0) return loc; iic_tpm_write(TPM_ACCESS(loc), &buf, 1); /* wait for burstcount */ stop = jiffies + chip->vendor.timeout_a; do { if (check_locality(chip, loc) >= 0) return loc; usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI); } while (time_before(jiffies, stop)); return -ETIME; }