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) */ }
/* 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; } }
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 */ }
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) */ }
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()); }
/* 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) */ }
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()); }
/* 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; }
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); }
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; }
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); }
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; }