예제 #1
0
void __hw_clock_source_set(uint32_t ts)
{
	/* Convert microseconds to ticks. */
	uint32_t ticks;

	/* Disable the timer. */
	ROTOR_MCU_TMR_TNCR(0) &= ~1;
#ifdef BOARD_REI
	/* ticks = (ts / SECOND) * clock_get_freq(); */
	ticks = (clock_get_freq() / SECOND) * ts;
	/* Set the load count. */
	/* ROTOR_MCU_TMR_TNLC(0) = reload_val - ticks; */
	ROTOR_MCU_TMR_TNLC(0) = 0xFFFFFFFF - ticks;

	/* Re-enable the timer block. */
	ROTOR_MCU_TMR_TNCR(0) |= 1;

	/*
	 * Restore the behaviour of counting down from the reload value after
	 * the next reload.
	 */
	/* ROTOR_MCU_TMR_TNLC(0) = reload_val; */
#else
	/* Determine the rollover count and set the load count */
	rollover_cnt = ts / ((0xFFFFFFFF / clock_get_freq()) * SECOND);
	ticks = (ts % (0xFFFFFFFF / clock_get_freq()) * SECOND);
	ROTOR_MCU_TMR_TNLC(0) = 0xFFFFFFFF - ticks;

	/* Re-enable the timer block. */
	ROTOR_MCU_TMR_TNCR(0) |= 1;
#endif /* defined(BOARD_REI) */
}
예제 #2
0
/* Hooks */
static void i2c_freq_changed(void)
{
	int freq, i;

	for (i = 0; i < i2c_ports_used; i++) {
		int bus_freq = i2c_ports[i].kbps;
		int ctrl = i2c_port_to_controller(i2c_ports[i].port);
		int scl_time;

		/* SMB0/1 use core clock & SMB2/3 use apb2 clock */
		if (ctrl < 2)
			freq = clock_get_freq();
		else
			freq = clock_get_apb2_freq();

		/* use Fast Mode */
		SET_BIT(NPCX_SMBCTL3(ctrl)  , NPCX_SMBCTL3_400K);

		/*
		 * Set SCLLT/SCLHT:
		 * tSCLL = 2 * SCLLT7-0 * tCLK
		 * tSCLH = 2 * SCLHT7-0 * tCLK
		 * (tSCLL+tSCLH) = 4 * SCLH(L)T * tCLK if tSCLL == tSCLH
		 * SCLH(L)T = T(SCL)/4/T(CLK) = FREQ(CLK)/4/FREQ(SCL)
		 */
		scl_time = (freq/1000) / (bus_freq * 4);   /* bus_freq is KHz */

		/* set SCL High/Low time */
		NPCX_SMBSCLLT(ctrl) = scl_time;
		NPCX_SMBSCLHT(ctrl) = scl_time;
	}
}
예제 #3
0
static void adc_interval_read(int ain_id, int interval_ms)
{
	adc_configure(ain_id);

	/* EXTEN=01 -> hardware trigger detection on rising edge */
	STM32_ADC_CFGR1 = (STM32_ADC_CFGR1 & ~0xc00) | (1 << 10);

	/* EXTSEL=TRG3 -> Trigger on TIM3_TRGO */
	STM32_ADC_CFGR1 = (STM32_ADC_CFGR1 & ~0x1c0) | (3 << 6);

	__hw_timer_enable_clock(TIM_ADC, 1);

	/* Upcounter, counter disabled, update event only on underflow */
	STM32_TIM_CR1(TIM_ADC) = 0x0004;

	/* TRGO on update event */
	STM32_TIM_CR2(TIM_ADC) = 0x0020;
	STM32_TIM_SMCR(TIM_ADC) = 0x0000;

	/* Auto-reload value */
	STM32_TIM_ARR(TIM_ADC) = interval_ms & 0xffff;

	/* Set prescaler to tick per millisecond */
	STM32_TIM_PSC(TIM_ADC) = (clock_get_freq() / MSEC) - 1;

	/* Start counting */
	STM32_TIM_CR1(TIM_ADC) |= 1;

	/* Start ADC conversion */
	STM32_ADC_CR |= 1 << 2; /* ADSTART */
}
예제 #4
0
uint32_t __hw_clock_source_read(void)
{
#ifdef BOARD_REI
	/* uint32_t ticks = reload_val - ROTOR_MCU_TMR_TNCV(0); */
	uint32_t ticks = 0xFFFFFFFF - ROTOR_MCU_TMR_TNCV(0);
	/* Convert the ticks into microseconds. */
	/* return ticks * (SECOND / clock_get_freq()); */

	return (ticks * (clock_get_freq() / SECOND));
#else
	/* Convert ticks to microseconds and account for the rollovers. */
	uint32_t ticks = 0xFFFFFFFF - ROTOR_MCU_TMR_TNCV(0);
	uint32_t us = (0xFFFFFFFF / clock_get_freq()) * rollover_cnt * SECOND;
	return us + ((ticks * SECOND) / clock_get_freq());
#endif /* defined(BOARD_REI) */
}
예제 #5
0
uint32_t __hw_clock_event_get(void)
{
	uint32_t ticks;
	/* Get the time of the next programmed deadline. */
	ticks = ROTOR_MCU_TMR_TNCV(1);
	return __hw_clock_source_read() + ((ticks * SECOND) / clock_get_freq());
}
예제 #6
0
/* Triggered when Timer 0 reaches 0. */
void __hw_clock_source_irq(void)
{
	/* Make sure that the interrupt actually fired. */
	if (!(ROTOR_MCU_TMR_TNIS(0) & (1 << 0)))
		return;
	/*
	 * Clear the interrupt by reading the TNEOI register.  Reading from this
	 * register returns all zeroes.
	 */
	if (ROTOR_MCU_TMR_TNEOI(0))
		;

#ifdef BOARD_REI
	/* Process timers indicating the overflow event. */
	process_timers(1);
#else
	rollover_cnt++;
	if (rollover_cnt >= (clock_get_freq() / 1000000)) {
		/* Process timers indicating the overflow event. */
		process_timers(1);
		rollover_cnt = 0;
	} else {
		process_timers(0);
	}
#endif /* defined(BOARD_REI) */
}
예제 #7
0
static void freq_change(void)
{
	size_t	i;

	for (i = 0; i < ARRAY_SIZE(configs); ++i)
		if (configs[i])
			usart_set_baud_f0_l(configs[i], clock_get_freq());
}
예제 #8
0
파일: timer.c 프로젝트: tlauda/sof
/* get timestamp for DAI stream DMA position */
void platform_dai_timestamp(struct comp_dev *dai,
			    struct sof_ipc_stream_posn *posn)
{
	int err;

	/* get DAI position */
	err = comp_position(dai, posn);
	if (err == 0)
		posn->flags |= SOF_TIME_DAI_VALID;

	/* get SSP wallclock - DAI sets this to stream start value */
	posn->wallclock = platform_timer_get(platform_timer) - posn->wallclock;
	posn->wallclock_hz = clock_get_freq(PLATFORM_DEFAULT_CLOCK);
	posn->flags |= SOF_TIME_WALL_VALID | SOF_TIME_WALL_64;
}
예제 #9
0
static void usart_variant_enable(struct usart_config const *config)
{
	/* Use single-bit sampling */
	STM32_USART_CR3(config->hw->base) |= STM32_USART_CR3_ONEBIT;

	/*
	 * Make sure we register this config before enabling the HW.
	 * If we did it the other way around the FREQ_CHANGE hook could be
	 * called before we update the configs array and we would miss the
	 * clock frequency change event, leaving our baud rate divisor wrong.
	 */
	configs[config->hw->index] = config;

	usart_set_baud_f0_l(config, clock_get_freq());

	task_enable_irq(config->hw->irq);
}
예제 #10
0
static void i2c_set_freq_port(const struct i2c_port_t *p)
{
	int port = p->port;
	int freq = clock_get_freq();

	/* Force peripheral reset and disable port */
	STM32_I2C_CR1(port) = STM32_I2C_CR1_SWRST;
	STM32_I2C_CR1(port) = 0;

	/* Set clock frequency */
	STM32_I2C_CCR(port) = freq / (2 * MSEC * p->kbps);
	STM32_I2C_CR2(port) = freq / SECOND;
	STM32_I2C_TRISE(port) = freq / SECOND + 1;

	/* Enable port */
	STM32_I2C_CR1(port) |= STM32_I2C_CR1_PE;
}
예제 #11
0
void __hw_clock_event_set(uint32_t deadline)
{
	uint32_t ticks;
	uint32_t delta;

	__hw_clock_event_clear();

	delta = deadline - __hw_clock_source_read();

	/* Convert the delta to ticks. */
	ticks = delta * (clock_get_freq() / SECOND);

	/* Set the timer load count to the deadline. */
	ROTOR_MCU_TMR_TNLC(1) = ticks;

	/* Enable the timer. */
	ROTOR_MCU_TMR_TNCR(1) |= (1 << 0);
}
예제 #12
0
파일: peci.c 프로젝트: coreboot/chrome-ec
static void peci_freq_changed(void)
{
	int freq = clock_get_freq();
	int baud;

	/* Disable polling while reconfiguring */
	LM4_PECI_CTL = 0;

	/*
	 * Calculate baud setting from desired rate, compensating for internal
	 * and external delays.
	 */
	baud = freq / (4 * PECI_BAUD_RATE) - 2;
	baud -= (freq / 1000000) * (PECI_TD_FET_NS + PECI_TD_INT_NS) / 1000;

	/* Set baud rate and polling rate */
	LM4_PECI_DIV = (baud << 16) |
		(PECI_POLL_INTERVAL_MS * (freq / 1000 / 4096));

	/* Set up temperature monitoring to report in degrees K */
	LM4_PECI_CTL = ((CONFIG_PECI_TJMAX + 273) << 22) | 0x0001 |
		       (PECI_RETRY_COUNT << 12) |
		       (PECI_ERROR_BYPASS << 11);
}
int flash_physical_write(int offset, int size, const char *data)
{
	uint32_t *data32 = (uint32_t *)data;
	uint32_t *address = (uint32_t *)(CONFIG_PROGRAM_MEMORY_BASE + offset);
	int res = EC_SUCCESS;
	int word_mode = 0;
	int i;

	/* Fail if offset, size, and data aren't at least word-aligned */
	if ((offset | size | (uint32_t)(uintptr_t)data) & 3)
		return EC_ERROR_INVAL;

	/* Unlock program area */
	res = unlock(STM32_FLASH_PECR_PRG_LOCK);
	if (res)
		goto exit_wr;

	/* Clear previous error status */
	STM32_FLASH_SR = 0xf00;

	/*
	 * If offset and size aren't on word boundaries, do word writes.  This
	 * is slower, but since we claim to the outside world that writes must
	 * be half-page size, the only code which hits this path is writing
	 * pstate (which is just writing one word).
	 */
	if ((offset | size) & (CONFIG_FLASH_WRITE_SIZE - 1))
		word_mode = 1;

	/* Update flash timeout based on current clock speed */
	flash_timeout_loop = FLASH_TIMEOUT_MS * (clock_get_freq() / MSEC) /
		CYCLE_PER_FLASH_LOOP;

	while (size > 0) {
		/*
		 * Reload the watchdog timer to avoid watchdog reset when doing
		 * long writing with interrupt disabled.
		 */
		watchdog_reload();

		if (word_mode) {
			/* Word write */
			*address++ = *data32++;

			/* Wait for writes to complete */
			for (i = 0; ((STM32_FLASH_SR & 9) != 8) &&
				     (i < flash_timeout_loop); i++)
				;

			size -= sizeof(uint32_t);
		} else {
			/* Half page write */
			interrupt_disable();
			iram_flash_write(address, data32);
			interrupt_enable();
			address += CONFIG_FLASH_WRITE_SIZE / sizeof(uint32_t);
			data32 += CONFIG_FLASH_WRITE_SIZE / sizeof(uint32_t);
			size -= CONFIG_FLASH_WRITE_SIZE;
		}

		if (STM32_FLASH_SR & 1) {
			res = EC_ERROR_TIMEOUT;
			goto exit_wr;
		}

		/*
		 * Check for error conditions: erase failed, voltage error,
		 * protection error
		 */
		if (STM32_FLASH_SR & 0xf00) {
			res = EC_ERROR_UNKNOWN;
			goto exit_wr;
		}
	}

exit_wr:
	/* Relock program lock */
	lock();

	return res;
}