예제 #1
0
파일: clock-stm32f.c 프로젝트: thehobn/ec
void clock_init(void)
{
	/*
	 * The initial state :
	 *  SYSCLK from HSI (=8MHz), no divider on AHB, APB1, APB2
	 *  PLL unlocked, RTC enabled on LSE
	 */

	config_hispeed_clock();

	/* configure RTC clock */
	wait_rtc_ready();
	prepare_rtc_write();
	/* set RTC divider to /1 */
	STM32_RTC_PRLH = 0;
	STM32_RTC_PRLL = 0;
	finalize_rtc_write();
	/* setup RTC EXTINT17 to wake up us from STOP mode */
	STM32_EXTI_IMR |= (1 << 17);
	STM32_EXTI_RTSR |= (1 << 17);

	/*
	 * Our deep sleep mode is STOP mode.
	 * clear PDDS (stop mode) , set LDDS (regulator in low power mode)
	 */
	STM32_PWR_CR = (STM32_PWR_CR & ~2) | 1;

	/* Enable RTC interrupts */
	task_enable_irq(STM32_IRQ_RTC_WAKEUP);
	task_enable_irq(STM32_IRQ_RTC_ALARM);
}
예제 #2
0
파일: lpc.c 프로젝트: thehobn/ec
static void lpc_task_enable_irq(void){

	task_enable_irq(NPCX_IRQ_SHM);
	task_enable_irq(NPCX_IRQ_KBC_IBF);
	task_enable_irq(NPCX_IRQ_PM_CHAN_IBF);
	task_enable_irq(NPCX_IRQ_PORT80);
}
예제 #3
0
int __hw_clock_source_init(uint32_t start_t)
{
	/* Set the reload and current value. */
	GR_TIMEHS_BGLOAD(0, 1) = 0xffffffff;
	GR_TIMEHS_LOAD(0, 1) = 0xffffffff;

	/* HW Timer enabled, periodic, interrupt enabled, 32-bit, wrapping */
	GR_TIMEHS_CONTROL(0, 1) = 0xe2;
	/* Event timer disabled */
	__hw_clock_event_clear();

	/* Account for the clock speed. */
	update_prescaler();

	/* Clear any pending interrupts */
	GR_TIMEHS_INTCLR(0, 1) = 0x1;

	/* Force the time to whatever we're told it is */
	__hw_clock_source_set(start_t);

	/* Here we go... */
	task_enable_irq(GC_IRQNUM_TIMEHS0_TIMINT1);
	task_enable_irq(GC_IRQNUM_TIMEHS0_TIMINT2);

	/* Return the Event timer IRQ number (NOT the HW timer IRQ) */
	return GC_IRQNUM_TIMEHS0_TIMINT2;
}
예제 #4
0
파일: gpio.c 프로젝트: longsleep/ec
static void gpio_init(void)
{
	task_enable_irq(MEC1322_IRQ_GIRQ8);
	task_enable_irq(MEC1322_IRQ_GIRQ9);
	task_enable_irq(MEC1322_IRQ_GIRQ10);
	task_enable_irq(MEC1322_IRQ_GIRQ11);
	task_enable_irq(MEC1322_IRQ_GIRQ20);
}
예제 #5
0
파일: ipc.c 프로젝트: coreboot/chrome-ec
static void setup_ipc(void)
{

	task_enable_irq(ISH_IPC_HOST2ISH_IRQ);
	task_enable_irq(ISH_IPC_ISH2HOST_CLR_IRQ);

	ipc_set_pimr(IPC_PEER_HOST_ID, SET_PIMR, PIMR_SIGNAL_IN);
	ipc_set_pimr(IPC_PEER_HOST_ID, SET_PIMR, PIMR_SIGNAL_CLR);
}
예제 #6
0
파일: sps.c 프로젝트: fourier49/BZ_DEV_EC
int sps_register_rx_handler(enum sps_mode mode, rx_handler_f rx_handler)
{
	if (sps_rx_handler)
		return -1;

	sps_rx_handler = rx_handler;
	sps_configure(mode, SPI_CLOCK_MODE0);
	task_enable_irq(GC_IRQNUM_SPS0_RXFIFO_LVL_INTR);
	task_enable_irq(GC_IRQNUM_SPS0_CS_DEASSERT_INTR);

	return 0;
}
예제 #7
0
static void i2c_init(void)
{
	/*
	 * TODO(crosbug.com/p/23763): Add config options to determine which
	 * channels to init.
	 */
	i2c_init_port(I2C1);
	i2c_init_port(I2C2);

	/* Enable event and error interrupts */
	task_enable_irq(STM32_IRQ_I2C2_EV);
	task_enable_irq(STM32_IRQ_I2C2_ER);
}
예제 #8
0
static void adc_init(void)
{
	int i;

	/* Configure GPIOs */
	configure_gpio();

	/*
	 * Temporarily enable the PLL when turning on the clock to the ADC
	 * module, to work around chip errata (10.4).  No need to notify
	 * other modules; the PLL isn't enabled long enough to matter.
	 */
	clock_enable_pll(1, 0);

	/* Enable ADC0 module in run and sleep modes. */
	clock_enable_peripheral(CGC_OFFSET_ADC, 0x1,
			CGC_MODE_RUN | CGC_MODE_SLEEP);

	/*
	 * Use external voltage references (VREFA+, VREFA-) instead of
	 * VDDA and GNDA.
	 */
	LM4_ADC_ADCCTL = 0x01;

	/* Use internal oscillator */
	LM4_ADC_ADCCC = 0x1;

	/* Disable the PLL now that the ADC is using the internal oscillator */
	clock_enable_pll(0, 0);

	/* No tasks waiting yet */
	for (i = 0; i < LM4_ADC_SEQ_COUNT; i++)
		task_waiting_on_ss[i] = TASK_ID_INVALID;

	/* Enable IRQs */
	task_enable_irq(LM4_IRQ_ADC0_SS0);
	task_enable_irq(LM4_IRQ_ADC0_SS1);
	task_enable_irq(LM4_IRQ_ADC0_SS2);
	task_enable_irq(LM4_IRQ_ADC0_SS3);

	/* 2**6 = 64x oversampling */
	LM4_ADC_ADCSAC = 6;

	/* Initialize ADC sequencer */
	for (i = 0; i < ADC_CH_COUNT; ++i)
		adc_configure(adc_channels + i);

	/* Disable ADC0 module until it is needed to conserve power. */
	clock_disable_peripheral(CGC_OFFSET_ADC, 0x1,
			CGC_MODE_RUN | CGC_MODE_SLEEP);
}
예제 #9
0
int __hw_clock_source_init(uint32_t start_t)
{
	/*
	 * 1. Use ITIM16-1 as internal time reading
	 * 2. Use ITIM16-2 for event handling
	 */

	/* Enable clock for ITIM peripheral */
	clock_enable_peripheral(CGC_OFFSET_TIMER, CGC_TIMER_MASK,
			CGC_MODE_RUN | CGC_MODE_SLEEP);

	/* init tick & event timer first */
	init_hw_timer(ITIM32,  ITIM_SOURCE_CLOCK_APB2);
	init_hw_timer(ITIM_EVENT_NO, ITIM_SOURCE_CLOCK_32K);

	/* Set initial prescaler */
	update_prescaler();

	/*
	 * Override the count with the start value now that counting has
	 * started.
	 */
	hw_clock_source_set_preload(start_t, 1);

	/* Enable interrupt of ITIM */
	task_enable_irq(NPCX_IRQ_ITIM32);

	return NPCX_IRQ_ITIM32;
}
예제 #10
0
static void i2c_init(void)
{
	const struct i2c_port_t *p = i2c_ports;
	int i;

	for (i = 0; i < i2c_ports_used; i++, p++)
		i2c_init_port(p);

#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR
	STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_RXIE | STM32_I2C_CR1_ERRIE
			| STM32_I2C_CR1_ADDRIE | STM32_I2C_CR1_STOPIE
			| STM32_I2C_CR1_NACKIE;
#if defined(CONFIG_LOW_POWER_IDLE) && (I2C_PORT_EC == STM32_I2C1_PORT)
	/*
	 * If using low power idle and EC port is I2C1, then set I2C1 to wake
	 * from STOP mode on address match. Note, this only works on I2C1 and
	 * only if the clock to I2C1 is HSI 8MHz.
	 */
	STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_WUPEN;
#endif
	STM32_I2C_OAR1(I2C_PORT_EC) = 0x8000 | CONFIG_HOSTCMD_I2C_SLAVE_ADDR;
#ifdef TCPCI_I2C_SLAVE
	/*
	 * Configure TCPC address with OA2[1] masked so that we respond
	 * to CONFIG_TCPC_I2C_BASE_ADDR and CONFIG_TCPC_I2C_BASE_ADDR + 2.
	 */
	STM32_I2C_OAR2(I2C_PORT_EC) = 0x8100 | CONFIG_TCPC_I2C_BASE_ADDR;
#endif
	task_enable_irq(IRQ_SLAVE);
#endif
}
예제 #11
0
static void ext_timer_ctrl(enum ext_timer_sel ext_timer,
		enum ext_timer_clock_source ext_timer_clock,
		int start,
		int with_int,
		int32_t count)
{
	uint8_t intc_mask;

	/* rising-edge-triggered */
	intc_mask = et_ctrl_regs[ext_timer].mask;
	*et_ctrl_regs[ext_timer].mode |= intc_mask;
	*et_ctrl_regs[ext_timer].polarity &= ~intc_mask;

	/* clear interrupt status */
	task_clear_pending_irq(et_ctrl_regs[ext_timer].irq);

	/* These bits control the clock input source to the exttimer 3 - 8 */
	IT83XX_ETWD_ETXPSR(ext_timer) = ext_timer_clock;

	/* The count number of external timer n. */
	IT83XX_ETWD_ETXCNTLR(ext_timer) = count;

	ext_timer_stop(ext_timer, 0);
	if (start)
		ext_timer_start(ext_timer, 0);

	if (with_int)
		task_enable_irq(et_ctrl_regs[ext_timer].irq);
	else
		task_disable_irq(et_ctrl_regs[ext_timer].irq);
}
예제 #12
0
파일: lpc.c 프로젝트: fourier49/BIZ_EC
void lpc_keyboard_put_char(uint8_t chr, int send_irq)
{
	/* Clear programming data bit 7-4 */
	IT83XX_KBC_KBHISR &= 0x0F;

	/* keyboard */
	IT83XX_KBC_KBHISR |= 0x10;

	/*
	 * bit0 = 0, The IRQ1 is controlled by the IRQ1B bit in KBIRQR.
	 * bit1 = 0, The IRQ12 is controlled by the IRQ12B bit in KBIRQR.
	 */
	IT83XX_KBC_KBHICR &= 0xFC;

	/*
	 * Enable the interrupt to keyboard driver in the host processor
	 * via SERIRQ when the output buffer is full.
	 */
	if (send_irq)
		IT83XX_KBC_KBHICR |= 0x01;

	udelay(16);

	task_clear_pending_irq(IT83XX_IRQ_KBC_OUT);
	/* The data output to the KBC Data Output Register. */
	IT83XX_KBC_KBHIKDOR = chr;
	task_enable_irq(IT83XX_IRQ_KBC_OUT);
}
예제 #13
0
파일: i2c.c 프로젝트: coreboot/chrome-ec
static int i2c_tran_write(int p)
{
	struct i2c_port_data *pd = pdata + p;

	if (pd->flags & I2C_XFER_START) {
		/* i2c enable */
		IT83XX_SMB_HOCTL2(p) = 0x13;
		/*
		 * bit0, Direction of the host transfer.
		 * bit[1:7}, Address of the targeted slave.
		 */
		IT83XX_SMB_TRASLA(p) = pd->addr;
		/* Send first byte */
		IT83XX_SMB_HOBDB(p) = *(pd->out++);
		pd->widx++;
		/* clear start flag */
		pd->flags &= ~I2C_XFER_START;
		/*
		 * bit0, Host interrupt enable.
		 * bit[2:4}, Extend command.
		 * bit6, start.
		 */
		IT83XX_SMB_HOCTL(p) = 0x5D;
	} else {
		/* Host has completed the transmission of a byte */
		if (IT83XX_SMB_HOSTA(p) & HOSTA_BDS) {
			if (pd->widx < pd->out_size) {
				/* Send next byte */
				IT83XX_SMB_HOBDB(p) = *(pd->out++);
				pd->widx++;
				/* W/C byte done for next byte */
				IT83XX_SMB_HOSTA(p) = HOSTA_NEXT_BYTE;
				if (pd->i2ccs == I2C_CH_REPEAT_START) {
					pd->i2ccs = I2C_CH_NORMAL;
					task_enable_irq(i2c_ctrl_regs[p].irq);
				}
			} else {
				/* done */
				pd->out_size = 0;
				if (pd->in_size > 0) {
					/* write to read */
					i2c_w2r_change_direction(p);
				} else {
					if (pd->flags & I2C_XFER_STOP) {
						/* set I2C_EN = 0 */
						IT83XX_SMB_HOCTL2(p) = 0x11;
						/* W/C byte done for finish */
						IT83XX_SMB_HOSTA(p) =
							HOSTA_NEXT_BYTE;
					} else {
						pd->i2ccs = I2C_CH_REPEAT_START;
						return 0;
					}
				}
			}
		}
	}
	return 1;
}
예제 #14
0
static void gpio_init(void)
{
	int i;

	/* Enable IRQs now that pins are set up */
	for (i = 0; i < ARRAY_SIZE(gpio_irqs); i++)
		task_enable_irq(gpio_irqs[i]);
}
예제 #15
0
void keyboard_raw_enable_interrupt(int enable)
{
	if (enable) {
		task_clear_pending_irq(MEC1322_IRQ_KSC_INT);
		task_enable_irq(MEC1322_IRQ_KSC_INT);
	} else {
		task_disable_irq(MEC1322_IRQ_KSC_INT);
	}
}
예제 #16
0
int __hw_clock_source_init(uint32_t start_t)
{
#ifdef BOARD_REI
	/* reload_val = (0xFFFFFFFF / SECOND) * clock_get_freq(); */
	/* reload_val = 0xFFFFFFFF; */
#endif /* defined(BOARD_REI) */
	/*
	 * Use Timer 0 as the clock.  The clock source for the timer block
	 * cannot be prescaled down to 1MHz, therefore, we'll have to handle the
	 * rollovers.
	 *
	 * There's also no match functionality, so set up an additional timer,
	 * Timer 1, to handle events.
	 */

	/* Disable the timers. */
	ROTOR_MCU_TMR_TNCR(0) &= ~(1 << 0);
	ROTOR_MCU_TMR_TNCR(1) &= ~(1 << 0);

	/*
	 * Timer 0
	 *
	 * Unmask interrupt, set user-defined count mode, and disable PWM.
	 */
	ROTOR_MCU_TMR_TNCR(0) = (1 << 1);

	/* Use the specified start timer value and start the timer. */
	__hw_clock_source_set(start_t);

	/*
	 * Timer 1
	 *
	 * Unmask interrupt, set user-defined count mode, and disable PWM.
	 */
	ROTOR_MCU_TMR_TNCR(1) = (1 << 1);

	/* Enable interrupts. */
	task_enable_irq(ROTOR_MCU_IRQ_TIMER_0);
	task_enable_irq(ROTOR_MCU_IRQ_TIMER_1);

	/* Return event timer IRQ number. */
	return ROTOR_MCU_IRQ_TIMER_1;
}
예제 #17
0
void ext_timer_start(enum ext_timer_sel ext_timer, int en_irq)
{
	/* enable external timer n */
	IT83XX_ETWD_ETXCTRL(ext_timer) |= 0x03;

	if (en_irq) {
		task_clear_pending_irq(et_ctrl_regs[ext_timer].irq);
		task_enable_irq(et_ctrl_regs[ext_timer].irq);
	}
}
예제 #18
0
void dma_enable_tc_interrupt(enum dma_channel channel)
{
	stm32_dma_chan_t *chan = dma_get_channel(channel);

	/* Store task ID so the ISR knows which task to wake */
	id[channel] = task_get_current();

	chan->ccr |= STM32_DMA_CCR_TCIE;
	task_enable_irq(dma_get_irq(channel));
}
예제 #19
0
int gpio_enable_interrupt(enum gpio_signal signal)
{
	int irq = gpio_to_irq(gpio_list[signal].port, gpio_list[signal].mask);

	if (irq == -1)
		return EC_ERROR_UNKNOWN;
	else
		task_enable_irq(irq);

	return EC_SUCCESS;
}
예제 #20
0
void dma_enable_tc_interrupt_callback(enum dma_channel stream,
				      void (*callback)(void *),
				      void *callback_data)
{
	stm32_dma_stream_t *dma_stream = dma_get_channel(stream);

	dma_irq[stream].cb = callback;
	dma_irq[stream].cb_data = callback_data;

	dma_stream->scr |= STM32_DMA_CCR_TCIE;
	task_enable_irq(dma_get_irq(stream));
}
예제 #21
0
파일: lpc.c 프로젝트: latelee/chrome-ec
/* Put a char to host buffer and send IRQ if specified. */
void lpc_keyboard_put_char(uint8_t chr, int send_irq)
{
	NPCX_HIKDO = chr;
	CPRINTS("KB put %02x", chr);

	/* Enable OBE interrupt to detect host read data out */
	SET_BIT(NPCX_HICTRL, NPCX_HICTRL_OBECIE);
	task_enable_irq(NPCX_IRQ_KBC_OBE);
	if (send_irq) {
		keyboard_irq_assert();
	}
}
예제 #22
0
파일: hardware.c 프로젝트: gelraen/cros-ec
static void timers_init(void)
{
	/* TIM2 is a 32-bit free running counter with 1Mhz frequency */
	STM32_TIM_CR2(2) = 0x0000;
	STM32_TIM32_ARR(2) = 0xFFFFFFFF;
	STM32_TIM32_CNT(2) = 0;
	STM32_TIM_PSC(2) = CPU_CLOCK / 1000000 - 1;
	STM32_TIM_EGR(2) = 0x0001; /* Reload the pre-scaler */
	STM32_TIM_CR1(2) = 1;
	STM32_TIM_DIER(2) = 0;
	task_enable_irq(STM32_IRQ_TIM2);
}
예제 #23
0
static void gpio_init(void)
{
	/* Enable IRQs now that pins are set up */
	task_enable_irq(STM32_IRQ_EXTI0);
	task_enable_irq(STM32_IRQ_EXTI1);
	task_enable_irq(STM32_IRQ_EXTI2);
	task_enable_irq(STM32_IRQ_EXTI3);
	task_enable_irq(STM32_IRQ_EXTI4);
	task_enable_irq(STM32_IRQ_EXTI9_5);
	task_enable_irq(STM32_IRQ_EXTI15_10);
}
예제 #24
0
static void lpc_send_response_packet(struct host_packet *pkt)
{
	/* Ignore in-progress on LPC since interface is synchronous anyway */
	if (pkt->driver_result == EC_RES_IN_PROGRESS)
		return;

	/* Write result to the data byte.  This sets the TOH status bit. */
	LPC_POOL_CMD[1] = pkt->driver_result;

	/* Clear the busy bit, so the host knows the EC is done. */
	task_disable_irq(LM4_IRQ_LPC);
	LM4_LPC_ST(LPC_CH_CMD) &= ~LM4_LPC_ST_BUSY;
	task_enable_irq(LM4_IRQ_LPC);
}
예제 #25
0
파일: i2c.c 프로젝트: thehobn/ec
static void configure_port(int port, int kbps)
{
	MEC1322_I2C_CTRL(port) = CTRL_PIN;
	MEC1322_I2C_OWN_ADDR(port) = 0x0;
	configure_port_speed(port, kbps);
	MEC1322_I2C_CTRL(port) = CTRL_PIN | CTRL_ESO | CTRL_ACK | CTRL_ENI;
	MEC1322_I2C_CONFIG(port) |= 1 << 10; /* ENAB */

	/* Enable interrupt */
	MEC1322_I2C_CONFIG(port) |= 1 << 29; /* ENIDI */
	MEC1322_INT_ENABLE(12) |= (1 << port);
	MEC1322_INT_BLK_EN |= 1 << 12;
	task_enable_irq(MEC1322_IRQ_I2C_0 + port);
}
예제 #26
0
/* HWTimer event handlers */
void __hw_clock_event_set(uint32_t deadline)
{
	fp_t inv_evt_tick = FLOAT_TO_FP(INT_32K_CLOCK/(float)SECOND);
	int32_t  evt_cnt_us;
	/* Is deadline min value? */
	if (evt_expired_us != 0 && evt_expired_us < deadline)
		return;

	/* mark min event value */
	evt_expired_us = deadline;
	evt_cnt_us = deadline - __hw_clock_source_read();
#if DEBUG_TMR
	evt_cnt_us_dbg = deadline - __hw_clock_source_read();
#endif
	/* Deadline is behind current timer */
	if (evt_cnt_us < 0)
		evt_cnt_us = 1;

	/* Event module disable */
	CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN);

	/*
	 * ITIM count down : event expired : Unit: 1/32768 sec
	 * It must exceed evt_expired_us for process_timers function
	 */
	evt_cnt = FP_TO_INT((fp_inter_t)(evt_cnt_us) * inv_evt_tick);
	if (evt_cnt > TICK_EVT_MAX_CNT) {
		CPRINTS("Event overflow! 0x%08x, us is %d\r\n",
				evt_cnt, evt_cnt_us);
		evt_cnt = TICK_EVT_MAX_CNT;
	}

	/* Wait for module disable to take effect before updating count */
	while (IS_BIT_SET(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN))
		;

	NPCX_ITCNT16(ITIM_EVENT_NO) = MAX(evt_cnt, 1);

	/* Event module enable */
	SET_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN);

	/* Wait for module enable */
	while (!IS_BIT_SET(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN))
		;

	/* Enable interrupt of ITIM */
	task_enable_irq(ITIM16_INT(ITIM_EVENT_NO));
}
예제 #27
0
void __hw_clock_event_set(uint32_t deadline)
{
	uint32_t wait;
	/* bit0, disable event timer */
	IT83XX_ETWD_ETXCTRL(EVENT_EXT_TIMER) &= ~(1 << 0);
	/* w/c interrupt status */
	event_timer_clear_pending_isr();
	/* microseconds to timer counter */
	wait = deadline - __hw_clock_source_read();
	IT83XX_ETWD_ETXCNTLR(EVENT_EXT_TIMER) =
		wait < EVENT_TIMER_COUNT_TO_US(0xffffffff) ?
		EVENT_TIMER_US_TO_COUNT(wait) : 0xffffffff;
	/* enable and re-start timer */
	IT83XX_ETWD_ETXCTRL(EVENT_EXT_TIMER) |= 0x03;
	task_enable_irq(et_ctrl_regs[EVENT_EXT_TIMER].irq);
}
예제 #28
0
static void usart_variant_enable(struct usart_config const *config)
{
	configs[config->hw->index] = config;

	/*
	 * All three USARTS are clocked from the HSI(8MHz) source.  This is
	 * done because the clock sources elsewhere are setup so that the result
	 * of clock_get_freq() is not the input clock frequency to the USARTs
	 * baud rate divisors.
	 */
	STM32_RCC_CFGR3 |= 0x000f0003;

	usart_set_baud_f0_l(config, 8000000);

	task_enable_irq(config->hw->irq);
}
예제 #29
0
파일: lpc.c 프로젝트: fourier49/BIZ_EC
void lpc_keyboard_resume_irq(void)
{
	if (lpc_keyboard_has_char()) {
		/* The IRQ1 is controlled by the IRQ1B bit in KBIRQR. */
		IT83XX_KBC_KBHICR &= ~0x01;

		/*
		 * When the OBFKIE bit in KBC Host Interface Control Register
		 * (KBHICR) is 0, the bit directly controls the IRQ1 signal.
		 */
		IT83XX_KBC_KBIRQR |= 0x01;

		task_clear_pending_irq(IT83XX_IRQ_KBC_OUT);

		task_enable_irq(IT83XX_IRQ_KBC_OUT);
	}
}
예제 #30
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);
}