示例#1
0
static enum switch_state get_switch_state(void)
{
	struct stopwatch sw;
	int sampled_value;
	uint8_t rec_sw;
	static enum switch_state saved_state = not_probed;

	if (saved_state != not_probed)
		return saved_state;

	rec_sw = get_rec_sw_gpio_pin();
	sampled_value = read_gpio(rec_sw) ^ !REC_POL;

	if (!sampled_value) {
		saved_state = no_req;
		display_pattern(WWR_NORMAL_BOOT);
		return saved_state;
	}

	display_pattern(WWR_RECOVERY_PUSHED);
	printk(BIOS_INFO, "recovery button pressed\n");

	stopwatch_init_msecs_expire(&sw, WIPEOUT_MODE_DELAY_MS);

	do {
		sampled_value = read_gpio(rec_sw) ^ !REC_POL;
		if (!sampled_value)
			break;
	} while (!stopwatch_expired(&sw));

	if (sampled_value) {
		display_pattern(WWR_WIPEOUT_REQUEST);
		printk(BIOS_INFO, "wipeout requested, checking recovery\n");
		stopwatch_init_msecs_expire(&sw, RECOVERY_MODE_EXTRA_DELAY_MS);
		do {
			sampled_value = read_gpio(rec_sw) ^ !REC_POL;
			if (!sampled_value)
				break;
		} while (!stopwatch_expired(&sw));

		if (sampled_value) {
			saved_state = recovery_req;
			display_pattern(WWR_RECOVERY_REQUEST);
			printk(BIOS_INFO, "recovery requested\n");
		} else {
			saved_state = wipeout_req;
		}
	} else {
		saved_state = no_req;
		display_pattern(WWR_NORMAL_BOOT);
	}

	return saved_state;
}
示例#2
0
文件: ec_spi.c 项目: siro20/coreboot
static int crosec_spi_io(size_t req_size, size_t resp_size, void *context)
{
	struct spi_slave *slave = (struct spi_slave *)context;
	int ret = 0;

	while (!stopwatch_expired(&cs_cooldown_sw))
		/* Wait minimum delay between CS assertions. */;
	spi_claim_bus(slave);

	 /* Allow EC to ramp up clock after being awaken.
	  * See chrome-os-partner:32223 for more details. */
	udelay(CONFIG_EC_GOOGLE_CHROMEEC_SPI_WAKEUP_DELAY_US);

	if (spi_xfer(slave, req_buf, req_size, NULL, 0)) {
		printk(BIOS_ERR, "%s: Failed to send request.\n", __func__);
		ret = -1;
		goto out;
	}

	uint8_t byte;
	struct stopwatch sw;
	// Wait 1s for a framing byte.
	stopwatch_init_usecs_expire(&sw, USECS_PER_SEC);
	while (1) {
		if (spi_xfer(slave, NULL, 0, &byte, sizeof(byte))) {
			printk(BIOS_ERR, "%s: Failed to receive byte.\n",
			       __func__);
			ret = -1;
			goto out;
		}
		if (byte == EcFramingByte)
			break;

		if (stopwatch_expired(&sw)) {
			printk(BIOS_ERR,
			       "%s: Timeout waiting for framing byte.\n",
			       __func__);
			ret = -1;
			goto out;
		}
	}

	if (spi_xfer(slave, NULL, 0, resp_buf, resp_size)) {
		printk(BIOS_ERR, "%s: Failed to receive response.\n", __func__);
		ret = -1;
	}

out:
	spi_release_bus(slave);
	stopwatch_init_usecs_expire(&cs_cooldown_sw, cs_cooldown_us);
	return ret;
}
示例#3
0
文件: reset.c 项目: Oxyoptia/coreboot
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));
}
示例#4
0
文件: usb.c 项目: AdriDlu/coreboot
static int check_ip_clk_status(void)
{
	int u3_port_num;
	u32 check_bits;
	u32 sts1, sts2;
	struct stopwatch sw;

	u3_port_num = CAP_U3_PORT_NUM(read32(&ippc_regs->ip_xhci_cap));

	check_bits = STS1_SYSPLL_STABLE | STS1_REF_RST | STS1_SYS125_RST;
	check_bits = (u3_port_num ? STS1_U3_MAC_RST : 0);

	stopwatch_init_usecs_expire(&sw, 50000);

	do {
		if (stopwatch_expired(&sw)) {
			u3p_err("usb clocks are not stable!!!\n");
			return -1;
		}

		sts1 = read32(&ippc_regs->ip_pw_sts1) & check_bits;
		sts2 = read32(&ippc_regs->ip_pw_sts2) & STS2_U2_MAC_RST;
	} while ((sts1 != check_bits) || !sts2);

	return 0;
}
示例#5
0
/* cr50 uses bytes 3:2 of status register for burst count and
 * all 4 bytes must be read */
static int cr50_i2c_wait_burststs(struct tpm_chip *chip, uint8_t mask,
				  size_t *burst, int *status)
{
	uint8_t buf[4];
	struct stopwatch sw;

	stopwatch_init_msecs_expire(&sw, CR50_TIMEOUT_LONG_MS);

	while (!stopwatch_expired(&sw)) {
		if (cr50_i2c_read(chip, TPM_STS(chip->vendor.locality),
				  buf, sizeof(buf)) != 0) {
			mdelay(CR50_TIMEOUT_SHORT_MS);
			continue;
		}

		*status = buf[0];
		*burst = read_le16(&buf[1]);

		/* Check if mask matches and burst is valid */
		if ((*status & mask) == mask &&
		    *burst > 0 && *burst <= CR50_MAX_BUFSIZE)
			return 0;

		mdelay(CR50_TIMEOUT_SHORT_MS);
	}

	printk(BIOS_ERR, "%s: Timeout reading burst and status\n", __func__);
	return -1;
}
示例#6
0
static int dma_read(u32 addr, u8 *buf, u32 len, uintptr_t dma_buf,
		    size_t dma_buf_len)
{
	struct stopwatch sw;

	assert(IS_ALIGNED((uintptr_t)buf, SFLASH_DMA_ALIGN) &&
	       IS_ALIGNED(len, SFLASH_DMA_ALIGN) &&
	       len <= dma_buf_len);

	/* do dma reset */
	write32(&mt8173_nor->fdma_ctl, SFLASH_DMA_SW_RESET);
	write32(&mt8173_nor->fdma_ctl, SFLASH_DMA_WDLE_EN);
	/* flash source address and dram dest address */
	write32(&mt8173_nor->fdma_fadr, addr);
	write32(&mt8173_nor->fdma_dadr, dma_buf);
	write32(&mt8173_nor->fdma_end_dadr, (dma_buf + len));
	/* start dma */
	write32(&mt8173_nor->fdma_ctl, SFLASH_DMA_TRIGGER | SFLASH_DMA_WDLE_EN);

	stopwatch_init_usecs_expire(&sw, SFLASH_POLLINGREG_US);
	while ((read32(&mt8173_nor->fdma_ctl) & SFLASH_DMA_TRIGGER) != 0) {
		if (stopwatch_expired(&sw)) {
			printk(BIOS_WARNING, "dma read timeout!\n");
			return -1;
		}
	}

	memcpy(buf, (const void *)dma_buf, len);
	return 0;
}
示例#7
0
static int rk_edp_hw_link_training(struct rk_edp *edp)
{
	u32 val;
	struct stopwatch sw;

	/* Set link rate and count as you want to establish*/
	write32(&edp->regs->link_bw_set, edp->link_train.link_rate);
	write32(&edp->regs->lane_count_set, edp->link_train.lane_count);

	if (rk_edp_link_train_cr(edp))
		return -1;
	if (rk_edp_link_train_ce(edp))
		return -1;

	write32(&edp->regs->dp_hw_link_training, HW_LT_EN);
	stopwatch_init_msecs_expire(&sw, 10);
	do {
		val = read32(&edp->regs->dp_hw_link_training);
		if (!(val & HW_LT_EN))
			break;
	} while (!stopwatch_expired(&sw));
	if (val & HW_LT_ERR_CODE_MASK) {
		printk(BIOS_ERR, "edp hw link training error: %d\n",
		val >> HW_LT_ERR_CODE_SHIFT);
		return -1;
	}
示例#8
0
static int tegra_spi_pio_finish(struct tegra_spi_channel *spi)
{
	u8 *p = spi->in_buf;
	struct stopwatch sw;

	clrbits_le32(&spi->regs->command1, SPI_CMD1_RX_EN | SPI_CMD1_TX_EN);

	/*
	 * Allow some time in case the Rx FIFO does not yet have
	 * all packets pushed into it. See chrome-os-partner:24215.
	 */
	stopwatch_init_usecs_expire(&sw, SPI_FIFO_XFER_TIMEOUT_US);
	do {
		if (rx_fifo_count(spi) == spi_byte_count(spi))
			break;
	} while (!stopwatch_expired(&sw));

	while (!(read32(&spi->regs->fifo_status) &
				SPI_FIFO_STATUS_RX_FIFO_EMPTY)) {
		*p = read8(&spi->regs->rx_fifo);
		p++;
	}

	if (fifo_error(spi)) {
		printk(BIOS_ERR, "%s: ERROR:\n", __func__);
		dump_spi_regs(spi);
		dump_fifo_status(spi);
		return -1;
	}

	return 0;
}
示例#9
0
/*
 * Punit Initialization code. This all isn't documented, but
 * this is the recipe.
 */
static bool punit_init(void)
{
	uint32_t reg;
	uint32_t data;
	struct stopwatch sw;

	/* Thermal throttle activation offset */
	configure_thermal_target();

	/*
	 * Software Core Disable Mask (P_CR_CORE_DISABLE_MASK_0_0_0_MCHBAR).
	 * Enable all cores here.
	 */
	MCHBAR32(CORE_DISABLE_MASK) = 0x0;

	/* P-Unit bring up */
	reg = MCHBAR32(BIOS_RESET_CPL);
	if (reg == 0xffffffff) {
		/* P-unit not found */
		printk(BIOS_DEBUG, "Punit MMIO not available\n");
		return false;
	}
	/* Set Punit interrupt pin IPIN offset 3D */
	pci_write_config8(SA_DEV_PUNIT, PCI_INTERRUPT_PIN, 0x2);

	/* Set PUINT IRQ to 24 and INTPIN LOCK */
	MCHBAR32(PUNIT_THERMAL_DEVICE_IRQ) =
			PUINT_THERMAL_DEVICE_IRQ_VEC_NUMBER |
			PUINT_THERMAL_DEVICE_IRQ_LOCK;

	if (!CONFIG(SOC_INTEL_GLK)) {
		data = MCHBAR32(0x7818);
		data &= 0xFFFFE01F;
		data |= 0x20 | 0x200;
		MCHBAR32(0x7818) = data;
	}

	/* Stage0 BIOS Reset Complete (RST_CPL) */
	enable_bios_reset_cpl();

	/*
	 * Poll for bit 8 to check if PCODE has completed its action
	 * in reponse to BIOS Reset complete.
	 * We wait here till 1 ms for the bit to get set.
	 */
	stopwatch_init_msecs_expire(&sw, 1);
	while (!(MCHBAR32(BIOS_RESET_CPL) & PCODE_INIT_DONE)) {
		if (stopwatch_expired(&sw)) {
			printk(BIOS_DEBUG, "PCODE Init Done Failure\n");
			return false;
		}
		udelay(100);
	}

	return true;
}
示例#10
0
/*
 * Wait for the bit at the shift position to be set in reg
 * If the bit is not set in SPI_TIMEOUT_VALUE_US return with error
 */
static int wait_status(u32 reg, u32 shift)
{
	struct stopwatch sw;

	stopwatch_init_usecs_expire(&sw, SPI_TIMEOUT_VALUE_US);
	while (!(read32_x(reg) & (1 << shift))) {
		if (stopwatch_expired(&sw))
			return -SPIM_TIMEOUT;
	}
	return SPIM_OK;
}
示例#11
0
/*
 * Punit Initialization code. This all isn't documented, but
 * this is the recipe.
 */
static bool punit_init(void)
{
	uint32_t reg;
	uint32_t data;
	struct stopwatch sw;

	/*
	 * Software Core Disable Mask (P_CR_CORE_DISABLE_MASK_0_0_0_MCHBAR).
	 * Enable all cores here.
	 */
	write32((void *)(MCH_BASE_ADDR + P_CR_CORE_DISABLE_MASK_0_0_0_MCHBAR),
		0x0);

	void *bios_rest_cpl = (void *)(MCH_BASE_ADDR +
				       P_CR_BIOS_RESET_CPL_0_0_0_MCHBAR);
	/* P-Unit bring up */
	reg = read32(bios_rest_cpl);
	if (reg == 0xffffffff) {
		/* P-unit not found */
		printk(BIOS_DEBUG, "Punit MMIO not available \n");
		return false;
	} else {
		/* Set Punit interrupt pin IPIN offset 3D */
		pci_write_config8(PUNIT_DEVFN, PCI_INTERRUPT_PIN, 0x2);

		/* Set PUINT IRQ to 24 and INTPIN LOCK */
		write32((void *)(MCH_BASE_ADDR + PUNIT_THERMAL_DEVICE_IRQ),
			PUINT_THERMAL_DEVICE_IRQ_VEC_NUMBER |
			PUINT_THERMAL_DEVICE_IRQ_LOCK);

		data = read32((void *)(MCH_BASE_ADDR + 0x7818));
		data &= 0xFFFFE01F;
		data |= 0x20 | 0x200;
		write32((void *)(MCH_BASE_ADDR + 0x7818), data);

		/* Stage0 BIOS Reset Complete (RST_CPL) */
		write32(bios_rest_cpl, 0x1);

		/*
		 * Poll for bit 8 in same reg (RST_CPL).
		 * We wait here till 1 ms for the bit to get set.
		 */
		stopwatch_init_msecs_expire(&sw, 1);
		while (!(read32(bios_rest_cpl) & 0x100)) {
			if (stopwatch_expired(&sw)) {
				printk(BIOS_DEBUG,
				       "Failed to set RST_CPL bit\n");
				return false;
			}
			udelay(100);
		}
	}
	return true;
}
示例#12
0
文件: fb.c 项目: tidatida/coreboot
/*
 * Configure DP in slave mode and wait for video stream.
 *
 * param dp		pointer to main s5p-dp structure
 * param video_info	pointer to main video_info structure.
 * return		status
 */
static int s5p_dp_config_video(struct s5p_dp_device *dp,
			       struct video_info *video_info)
{
	int timeout = 0;
	struct exynos5_dp *base = dp->base;
	struct stopwatch sw;
	s5p_dp_config_video_slave_mode(dp, video_info);

	s5p_dp_set_video_color_format(dp, video_info->color_depth,
				      video_info->color_space,
				      video_info->dynamic_range,
				      video_info->ycbcr_coeff);

	if (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
		printk(BIOS_DEBUG, "PLL is not locked yet.\n");
		return -ERR_PLL_NOT_UNLOCKED;
	}

	stopwatch_init_msecs_expire(&sw, STREAM_ON_TIMEOUT);
	do {
		if (s5p_dp_is_slave_video_stream_clock_on(dp) == 0) {
			timeout++;
			break;
		}
	} while (!stopwatch_expired(&sw));

	if (!timeout) {
		printk(BIOS_ERR, "Video Clock Not ok after %ldus.\n",
				stopwatch_duration_usecs(&sw));
		return -ERR_VIDEO_CLOCK_BAD;
	}

	/* Set to use the register calculated M/N video */
	s5p_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);

	clrbits_le32(&base->video_ctl_10, FORMAT_SEL);

	/* Disable video mute */
	clrbits_le32(&base->video_ctl_1, HDCP_VIDEO_MUTE);

	/* Configure video slave mode */
	s5p_dp_enable_video_master(dp);

	/* Enable video */
	setbits_le32(&base->video_ctl_1, VIDEO_EN);
	timeout = s5p_dp_is_video_stream_on(dp);

	if (timeout) {
		printk(BIOS_DEBUG, "Video Stream Not on\n");
		return -ERR_VIDEO_STREAM_BAD;
	}

	return 0;
}
示例#13
0
/* Wait for interrupt to indicate the TPM is ready */
static int cr50_i2c_wait_tpm_ready(struct tpm_chip *chip)
{
	struct stopwatch sw;

	stopwatch_init_msecs_expire(&sw, CR50_TIMEOUT_IRQ_MS);

	while (!tis_plat_irq_status())
		if (stopwatch_expired(&sw))
			return -1;

	return 0;
}
示例#14
0
/*
 * TPM may trigger a IRQ after finish processing previous transfer.
 * Waiting for this IRQ to sync TPM status.
 *
 * Returns 1 on success, 0 on failure (timeout).
 */
static int tpm_sync(void)
{
	struct stopwatch sw;

	stopwatch_init_msecs_expire(&sw, 10);
	while (!tis_plat_irq_status()) {
		if (stopwatch_expired(&sw)) {
			printk(BIOS_ERR, "Timeout wait for TPM IRQ!\n");
			return 0;
		}
	}
	return 1;
}
示例#15
0
static int pcr_wait_for_completion(device_t dev)
{
	struct stopwatch sw;

	stopwatch_init_msecs_expire(&sw, PCR_SBI_CMD_TIMEOUT);
	do {
		if ((pci_read_config16(dev, P2SB_CR_SBI_STATUS) &
			P2SB_CR_SBI_STATUS_BUSY) == 0)
			return 0;
	} while (!stopwatch_expired(&sw));

	return -1;
}
示例#16
0
static int polling_cmd(u32 val)
{
	struct stopwatch sw;

	stopwatch_init_usecs_expire(&sw, SFLASH_POLLINGREG_US);

	while ((read32(&mt8173_nor->cmd) & val) != 0) {
		if (stopwatch_expired(&sw))
			return -1;
	}

	return 0;
}
示例#17
0
static int rk_edp_aux_enable(struct rk_edp *edp)
{
	struct stopwatch sw;

	setbits_le32(&edp->regs->aux_ch_ctl_2, AUX_EN);
	stopwatch_init_msecs_expire(&sw, 20);
	do {
		if (!(read32(&edp->regs->aux_ch_ctl_2) & AUX_EN))
			return 0;
	} while (!stopwatch_expired(&sw));

	return -1;

}
示例#18
0
static int rk_edp_is_aux_reply(struct rk_edp *edp)
{
	struct stopwatch sw;

	stopwatch_init_msecs_expire(&sw, 10);

	while (!(read32(&edp->regs->dp_int_sta) & RPLY_RECEIV)) {
		if (stopwatch_expired(&sw))
			return -1;
	}

	write32(&edp->regs->dp_int_sta, RPLY_RECEIV);

	return 0;
}
示例#19
0
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;
}
示例#20
0
static int wait_for_write_done(void)
{
	struct stopwatch sw;
	u8 reg;

	stopwatch_init_usecs_expire(&sw, SFLASH_POLLINGREG_US);

	while (sflashhw_read_flash_status(&reg) == 0) {
		if (!(reg & SFLASH_WRITE_IN_PROGRESS))
			return 0;
		if (stopwatch_expired(&sw))
			return -1;
	}

	return -1;
}
示例#21
0
static bool wilco_ec_response_timed_out(void)
{
	uint8_t mask = EC_CMDR_PENDING | EC_CMDR_BUSY;
	struct stopwatch sw;

	stopwatch_init_msecs_expire(&sw, EC_MAILBOX_TIMEOUT_MS);

	while (inb(CONFIG_EC_BASE_HOST_COMMAND) & mask) {
		if (stopwatch_expired(&sw)) {
			printk(BIOS_ERR, "%s: Command timeout\n", __func__);
			return true; /* Timed out */
		}
		mdelay(1);
	}

	return false; /* Did not time out */
}
示例#22
0
/*
 * 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;
}
示例#23
0
void udelay(unsigned int usec)
{
	struct stopwatch sw;

	/*
	 * As the timer granularity is in microseconds pad the
	 * requested delay by one to get at least >= requested usec delay.
	 */
	usec += 1;

	if (!thread_yield_microseconds(usec))
		return;

	stopwatch_init_usecs_expire(&sw, usec);

	while (!stopwatch_expired(&sw))
		;
}
示例#24
0
static int wait_for_status(uint32_t status_mask, uint32_t status_expected)
{
	uint32_t status;
	struct stopwatch sw;

	stopwatch_init_usecs_expire(&sw, MAX_STATUS_TIMEOUT * 1000 * 1000);
	do {
		udelay(1000);
		if (stopwatch_expired(&sw)) {
			printk(BIOS_ERR, "failed to get expected status %x\n",
			       status_expected);
			return false;
		}
		read_tpm_sts(&status);
	} while ((status & status_mask) != status_expected);

	return 1;
}
示例#25
0
/**
 * 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;
}
示例#26
0
int ps8640_init(uint8_t bus, uint8_t chip)
{
	u8 set_vdo_done;
	struct stopwatch sw;

	stopwatch_init_msecs_expire(&sw, 350);

	do {
		i2c_readb(bus, chip + 2, PAGE2_GPIO_H, &set_vdo_done);
		if (stopwatch_expired(&sw)) {
			printk(BIOS_INFO, "Failed to init ps8640.\n");
			return -1;
		}
	} while ((set_vdo_done & PS_GPIO9) != PS_GPIO9);

	i2c_writeb(bus, chip + 3, PAGE3_SET_ADD, VDO_CTL_ADD);
	i2c_writeb(bus, chip + 3, PAGE3_SET_VAL, VDO_DIS);
	i2c_writeb(bus, chip + 3, PAGE3_SET_ADD, VDO_CTL_ADD);
	i2c_writeb(bus, chip + 3, PAGE3_SET_VAL, VDO_EN);

	return 0;
}
示例#27
0
static void rk_edp_init_analog_func(struct rk_edp *edp)
{
	struct stopwatch sw;

	write32(&edp->regs->dp_pd, 0x00);

	write32(&edp->regs->common_int_sta_1, PLL_LOCK_CHG);

	clrbits_le32(&edp->regs->dp_debug_ctl, F_PLL_LOCK | PLL_LOCK_CTRL);

	stopwatch_init_msecs_expire(&sw, PLL_LOCK_TIMEOUT);

	while (rk_edp_get_pll_lock_status(edp) == DP_PLL_UNLOCKED) {
		if (stopwatch_expired(&sw)) {
			printk(BIOS_ERR, "%s: PLL is not locked\n", __func__);
			return;
		}
	}

	/* Enable Serdes FIFO function and Link symbol clock domain module */
	clrbits_le32(&edp->regs->func_en_2, SERDES_FIFO_FUNC_EN_N |
				       LS_CLK_DOMAIN_FUNC_EN_N | AUX_FUNC_EN_N |
				       SSC_FUNC_EN_N);
}
示例#28
0
文件: ccplex.c 项目: AdriDlu/coreboot
static int ccplex_start(void)
{
	struct stopwatch sw;
	const long timeout_ms = 1500;
	const uint32_t handshake_mask = 1;
	const uint32_t cxreset1_mask = 1 << 21;
	uint32_t reg;
	struct tegra_pmc_regs * const pmc = PMC_REGS;

	/* Set the handshake bit to be knocked down. */
	write32(&pmc->scratch118, handshake_mask);

	/* Assert nCXRSET[1] */
	reg = read32(CLK_RST_REG(rst_cpu_cmplx_set));
	reg |= cxreset1_mask;
	write32(CLK_RST_REG(rst_cpu_cmplx_set), reg);

	stopwatch_init_msecs_expire(&sw, timeout_ms);
	while (1) {
		reg = read32(&pmc->scratch118);

		/* Wait for the bit to be knocked down. */
		if ((reg & handshake_mask) != handshake_mask)
			break;

		if (stopwatch_expired(&sw)) {
			printk(BIOS_DEBUG, "MTS handshake timeout.\n");
			return -1;
		}
	}

	printk(BIOS_DEBUG, "MTS handshake took %ld usecs.\n",
		stopwatch_duration_usecs(&sw));

	return 0;
}
示例#29
0
void arch_initialize_cpus(device_t cluster, struct cpu_control_ops *cntrl_ops)
{
	size_t max_cpus;
	size_t i;
	struct cpu_info *ci;
	void (*entry)(void);
	struct bus *bus;

	if (cluster->path.type != DEVICE_PATH_CPU_CLUSTER) {
		printk(BIOS_ERR,
			"CPU init failed. Device is not a CPU_CLUSTER: %s\n",
			dev_path(cluster));
		return;
	}

	bus = cluster->link_list;

	/* Check if no children under this device. */
	if (bus == NULL)
		return;

	/*
	 * el3_init must be performed prior to prepare_secondary_cpu_startup.
	 * This is important since el3_init initializes SCR values on BSP CPU
	 * and then prepare_secondary_cpu_startup reads the initialized SCR
	 * value and saves it for use by non-BSP CPUs.
	 */
	el3_init();
	/* Mark current cpu online. */
	cpu_mark_online(cpu_info());
	entry = prepare_secondary_cpu_startup();

	/* Initialize the cpu_info structures. */
	init_cpu_info(bus);
	max_cpus = cntrl_ops->total_cpus();

	if (max_cpus > CONFIG_MAX_CPUS) {
		printk(BIOS_WARNING,
			"max_cpus (%zu) exceeds CONFIG_MAX_CPUS (%zu).\n",
			max_cpus, (size_t)CONFIG_MAX_CPUS);
		max_cpus = CONFIG_MAX_CPUS;
	}

	for (i = 0; i < max_cpus; i++) {
		device_t dev;
		struct cpu_action action;
		struct stopwatch sw;

		ci = cpu_info_for_cpu(i);
		dev = ci->cpu;

		/* Disregard CPUs not in device tree. */
		if (dev == NULL)
			continue;

		/* Skip disabled CPUs. */
		if (!dev->enabled)
			continue;

		if (!cpu_online(ci)) {
			/* Start the CPU. */
			printk(BIOS_DEBUG, "Starting CPU%x\n", ci->id);

			if (cntrl_ops->start_cpu(ci->id, entry)) {
				printk(BIOS_ERR,
					"Failed to start CPU%x\n", ci->id);
				continue;
			}
			stopwatch_init_msecs_expire(&sw, 1000);
			/* Wait for CPU to come online. */
			while (!stopwatch_expired(&sw)) {
				if (!cpu_online(ci))
					continue;
				printk(BIOS_DEBUG,
					"CPU%x online in %ld usecs.\n",
					ci->id, stopwatch_duration_usecs(&sw));
				break;
			}
		}

		if (!cpu_online(ci)) {
			printk(BIOS_DEBUG,
				"CPU%x failed to come online in %ld usecs.\n",
				ci->id, stopwatch_duration_usecs(&sw));
			continue;
		}

		/* Send it the init action. */
		action.run = init_this_cpu;
		action.arg = ci;
		arch_run_on_cpu(ci->id, &action);
	}
}
示例#30
0
文件: fb.c 项目: tidatida/coreboot
/*
 * DP H/w Link Training. Set DPCD link rate and bandwidth.
 * param dp		pointer to main s5p-dp structure
 * param max_lane	No of lanes
 * param max_rate	bandwidth
 * return status
 */
static int s5p_dp_hw_link_training(struct s5p_dp_device *dp,
				   unsigned int max_lane,
				   unsigned int max_rate)
{
	int pll_is_locked = 0;
	u32 data;
	int lane;
	struct stopwatch sw;
	struct exynos5_dp *base = dp->base;

	/* Stop Video */
	clrbits_le32(&base->video_ctl_1, VIDEO_EN);

	stopwatch_init_msecs_expire(&sw, PLL_LOCK_TIMEOUT);

	while ((pll_is_locked = s5p_dp_get_pll_lock_status(dp)) == PLL_UNLOCKED) {
		if (stopwatch_expired(&sw)) {
			/* Ignore this error, and try to continue */
			printk(BIOS_ERR, "PLL is not locked yet.\n");
			break;
		}
	}
	printk(BIOS_SPEW, "PLL is %slocked\n",
			pll_is_locked == PLL_LOCKED ? "": "not ");
	/* Reset Macro */
	setbits_le32(&base->dp_phy_test, MACRO_RST);

	/* 10 us is the minimum reset time. */
	udelay(10);

	clrbits_le32(&base->dp_phy_test, MACRO_RST);

	/* Set TX pre-emphasis to minimum */
	for (lane = 0; lane < max_lane; lane++)
		if (s5p_dp_set_lane_lane_pre_emphasis(dp,
					      PRE_EMPHASIS_LEVEL_0, lane)) {
			printk(BIOS_DEBUG, "Unable to set pre emphasis level\n");
			return -ERR_PRE_EMPHASIS_LEVELS;
		}

	/* All DP analog module power up */
	writel(0x00, &base->dp_phy_pd);

	/* Initialize by reading RX's DPCD */
	s5p_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
	s5p_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);

	printk(BIOS_SPEW, "%s: rate 0x%x, lane_count %d\n", __func__,
		dp->link_train.link_rate, dp->link_train.lane_count);

	if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
	    (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
		printk(BIOS_DEBUG, "Rx Max Link Rate is abnormal :%x !\n",
		      dp->link_train.link_rate);
		/* Not Retrying */
		return -ERR_LINK_RATE_ABNORMAL;
	}

	if (dp->link_train.lane_count == 0) {
		printk(BIOS_DEBUG, "Rx Max Lane count is abnormal :%x !\n",
		      dp->link_train.lane_count);
		/* Not retrying */
		return -ERR_MAX_LANE_COUNT_ABNORMAL;
	}

	/* Setup TX lane count & rate */
	if (dp->link_train.lane_count > max_lane)
		dp->link_train.lane_count = max_lane;
	if (dp->link_train.link_rate > max_rate)
		dp->link_train.link_rate = max_rate;

	/* Set link rate and count as you want to establish*/
	writel(dp->link_train.lane_count, &base->lane_count_set);
	writel(dp->link_train.link_rate, &base->link_bw_set);

	/* Set sink to D0 (Sink Not Ready) mode. */
	s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE,
				  DPCD_SET_POWER_STATE_D0);

	/* Start HW link training */
	writel(HW_TRAINING_EN, &base->dp_hw_link_training);

	/* Wait until HW link training done */
	s5p_dp_wait_hw_link_training_done(dp);

	/* Get hardware link training status */
	data = readl(&base->dp_hw_link_training);
	printk(BIOS_SPEW, "hardware link training status: 0x%08x\n", data);
	if (data != 0) {
		printk(BIOS_ERR, " H/W link training failure: 0x%x\n", data);
		return -ERR_LINK_TRAINING_FAILURE;
	}

	/* Get Link Bandwidth */
	data = readl(&base->link_bw_set);

	dp->link_train.link_rate = data;

	data = readl(&base->lane_count_set);
	dp->link_train.lane_count = data;
	printk(BIOS_SPEW, "Done training: Link bandwidth: 0x%x, lane_count: %d\n",
		dp->link_train.link_rate, data);

	return 0;
}