/* * Locality could be already claimed (if this is a later coreboot stage and * the RO did not release it), or not yet claimed, if this is verstage or the * older RO did release it. */ static int claim_locality(struct tpm_chip *chip) { uint8_t access; const uint8_t mask = TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY; if (cr50_i2c_read(chip, TPM_ACCESS(0), &access, sizeof(access))) return -1; if ((access & mask) == mask) { printk(BIOS_INFO, "Locality already claimed\n"); return 0; } access = TPM_ACCESS_REQUEST_USE; if (cr50_i2c_write(chip, TPM_ACCESS(0), &access, sizeof(access))) return -1; if (cr50_i2c_read(chip, TPM_ACCESS(0), &access, sizeof(access))) return -1; if ((access & mask) != mask) { printk(BIOS_INFO, "Failed to claim locality.\n"); return -1; } return 0; }
void release_locality(struct tpm_chip* tpm, int l, int force) { if (locality_enabled(tpm, l) && (force || (ioread8(TPM_ACCESS(tpm, l)) & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))) { iowrite8(TPM_ACCESS(tpm, l), TPM_ACCESS_RELINQUISH_LOCALITY); } }
/* implementation similar to tpm_tis */ static void release_locality(struct tpm_chip *chip, int loc, int force) { u8 buf; if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0) return; if (force || (buf & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) { buf = TPM_ACCESS_ACTIVE_LOCALITY; iic_tpm_write(TPM_ACCESS(loc), &buf, 1); } }
static void tpm_tis_i2c_release_locality(struct udevice *dev, int loc, int force) { const u8 mask = TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID; u8 buf; if (tpm_tis_i2c_read(dev, TPM_ACCESS(loc), &buf, 1) < 0) return; if (force || (buf & mask) == mask) { buf = TPM_ACCESS_ACTIVE_LOCALITY; tpm_tis_i2c_write(dev, TPM_ACCESS(loc), &buf, 1); } }
int tpm_tis_request_locality(struct tpm_chip* tpm, int l) { s_time_t stop; /*Make sure locality is valid */ if(!locality_enabled(tpm, l)) { printk("tpm_tis_change_locality() Tried to change to locality %d, but it is disabled or invalid!\n", l); return -1; } /* Check if we already have the current locality */ if(check_locality(tpm, l) >= 0) { return tpm->locality = l; } /* Set the new locality*/ iowrite8(TPM_ACCESS(tpm, l), TPM_ACCESS_REQUEST_USE); if(tpm->irq) { /* Wait for interrupt */ wait_event_deadline(tpm->int_queue, (check_locality(tpm, l) >= 0), NOW() + tpm->timeout_a); /* FIXME: Handle timeout event, should return error in that case */ return l; } else { /* Wait for burstcount */ stop = NOW() + tpm->timeout_a; do { if(check_locality(tpm, l) >= 0) { return tpm->locality = l; } msleep(TPM_TIMEOUT); } while(NOW() < stop); } printk("REQ LOCALITY FAILURE\n"); return -1; }
static int check_locality(struct tpm_chip* tpm, int l) { if(locality_enabled(tpm, l) && (ioread8(TPM_ACCESS(tpm, l)) & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { return l; } return -1; }
static int check_locality(struct tpm_chip *chip, int loc) { u8 buf; int rc; rc = iic_tpm_read(TPM_ACCESS(loc), &buf, 1); if (rc < 0) return rc; if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { chip->vendor.locality = loc; return loc; } return -EIO; }
/* * Cr50 processes reset requests asynchronously and consceivably could be busy * executing a long command and not reacting to the reset pulse for a while. * * This function will make sure that the AP does not proceed with boot until * TPM finished reset processing. */ static int process_reset(struct tpm_chip *chip) { struct stopwatch sw; int rv = 0; uint8_t access; /* * Locality is released by TPM reset. * * If locality is taken at this point, this could be due to the fact * that the TPM is performing a long operation and has not processed * reset request yet. We'll wait up to CR50_TIMEOUT_INIT_MS and see if * it releases locality when reset is processed. */ stopwatch_init_msecs_expire(&sw, CR50_TIMEOUT_INIT_MS); do { const uint8_t mask = TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY; rv = cr50_i2c_read(chip, TPM_ACCESS(0), &access, sizeof(access)); if (rv || ((access & mask) == mask)) { /* * Don't bombard the chip with traffic, let it keep * processing the command. */ mdelay(2); continue; } printk(BIOS_INFO, "TPM ready after %ld ms\n", stopwatch_duration_msecs(&sw)); return 0; } while (!stopwatch_expired(&sw)); if (rv) printk(BIOS_ERR, "Failed to read TPM\n"); else printk(BIOS_ERR, "TPM failed to reset after %ld ms, status: %#x\n", stopwatch_duration_msecs(&sw), access); return -1; }
static int tpm_tis_i2c_check_locality(struct udevice *dev, int loc) { const u8 mask = TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID; struct tpm_chip *chip = dev_get_priv(dev); u8 buf; int rc; rc = tpm_tis_i2c_read(dev, TPM_ACCESS(loc), &buf, 1); if (rc < 0) return rc; if ((buf & mask) == mask) { chip->locality = loc; return loc; } return -ENOENT; }
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; }
static int tpm_tis_i2c_request_locality(struct udevice *dev, int loc) { struct tpm_chip *chip = dev_get_priv(dev); unsigned long start, stop; u8 buf = TPM_ACCESS_REQUEST_USE; int rc; rc = tpm_tis_i2c_check_locality(dev, loc); if (rc >= 0) { debug("%s: Already have locality\n", __func__); return loc; /* We already have the locality */ } else if (rc != -ENOENT) { debug("%s: Failed to get locality: %d\n", __func__, rc); return rc; } rc = tpm_tis_i2c_write(dev, TPM_ACCESS(loc), &buf, 1); if (rc) { debug("%s: Failed to write to TPM: %d\n", __func__, rc); return rc; } /* Wait for burstcount */ start = get_timer(0); stop = chip->timeout_a; do { rc = tpm_tis_i2c_check_locality(dev, loc); if (rc >= 0) { debug("%s: Have locality\n", __func__); return loc; } else if (rc != -ENOENT) { debug("%s: Failed to get locality: %d\n", __func__, rc); return rc; } mdelay(TPM_TIMEOUT_MS); } while (get_timer(start) < stop); debug("%s: Timeout getting locality: %d\n", __func__, rc); return rc; }