static int tpm2_claim_locality(void) { uint8_t access; struct stopwatch sw; /* * 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 { access = tpm2_read_access_reg(); if (access & TPM_ACCESS_ACTIVE_LOCALITY) { /* * Don't bombard the chip with traffic, let it keep * processing the command. */ mdelay(2); continue; } /* * Ok, the locality is free, TPM must be reset, let's claim * it. */ tpm2_write_access_reg(TPM_ACCESS_REQUEST_USE); access = tpm2_read_access_reg(); if (access != (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) { break; } printk(BIOS_INFO, "TPM ready after %ld ms\n", stopwatch_duration_msecs(&sw)); return 1; } while (!stopwatch_expired(&sw)); printk(BIOS_ERR, "Failed to claim locality 0 after %ld ms, status: %#x\n", stopwatch_duration_msecs(&sw), access); return 0; }
void reset_prepare(void) { struct stopwatch sw; /* * If CSE state is something else than 'normal', it is probably in some * recovery state. In this case there is no point in waiting for it to * get ready so we cross fingers and reset. */ if (!heci_cse_normal()) { printk(BIOS_DEBUG, "CSE is not in normal state, resetting\n"); return; } /* Reset if CSE is ready */ if (heci_cse_done()) return; printk(BIOS_SPEW, "CSE is not yet ready, waiting\n"); stopwatch_init_msecs_expire(&sw, CSE_WAIT_MAX_MS); while (!heci_cse_done()) { if (stopwatch_expired(&sw)) { printk(BIOS_SPEW, "CSE timed out. Resetting\n"); return; } mdelay(1); } printk(BIOS_SPEW, "CSE took %lu ms\n", stopwatch_duration_msecs(&sw)); }
/* * 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; }
/** * Wait for DisplayPort to be ready * * @param timeout Wait aborts after <timeout> ms. * @return 1: Success or 0: Timeout. */ int google_chromeec_wait_for_displayport(long timeout) { struct stopwatch sw; printk(BIOS_INFO, "Waiting for DisplayPort\n"); stopwatch_init_msecs_expire(&sw, timeout); while (google_chromeec_pd_get_amode(USB_SID_DISPLAYPORT) != 1) { if (stopwatch_expired(&sw)) { printk(BIOS_WARNING, "DisplayPort not ready after %ldms. Abort.\n", timeout); return 0; } mdelay(200); } printk(BIOS_INFO, "DisplayPort ready after %lu ms\n", stopwatch_duration_msecs(&sw)); return 1; }