nxp: imx: Implement iuart clock gating

Add clock control support for UART controllers found in i.MX SoC family.
This change moves clock gating out of respective `soc.c` files and into
clock controller's `clock_control_on`/`_off` methods, allowing for
dynamic clock state control, and setup via Device Tree bindings.

This is especially important on SoCs, where Zephyr is sharing the bus
with cores running other OSes, such as might be the case for i.MX 8MM.

Unfortunately, Zephyr doesn't possess an ability to represent clock
hierarchy (e.g. via DT's `assigned-clocks` property), so clock source
and frequency still need to be hardcoded in aforementioned `soc.c`
files.

Signed-off-by: Artur Rojek <artur@conclusive.pl>
This commit is contained in:
Artur Rojek 2022-12-08 14:55:46 +01:00 committed by Carles Cufí
commit 14912d241c
2 changed files with 41 additions and 2 deletions

View file

@ -30,6 +30,13 @@ static const clock_root_control_t uart_clk_root[] = {
kCLOCK_RootUart3,
kCLOCK_RootUart4,
};
static const clock_ip_name_t uart_clocks[] = {
kCLOCK_Uart1,
kCLOCK_Uart2,
kCLOCK_Uart3,
kCLOCK_Uart4,
};
#endif
#if defined(CONFIG_UART_MCUX_LPUART) && defined(CONFIG_SOC_MIMX93_A55)
static const clock_root_t lpuart_clk_root[] = {
@ -47,13 +54,43 @@ static const clock_root_t lpuart_clk_root[] = {
static int mcux_ccm_on(const struct device *dev,
clock_control_subsys_t sub_system)
{
return 0;
uint32_t clock_name = (uintptr_t)sub_system;
uint32_t instance = clock_name & IMX_CCM_INSTANCE_MASK;
switch (clock_name) {
#ifdef CONFIG_UART_MCUX_IUART
case IMX_CCM_UART1_CLK:
case IMX_CCM_UART2_CLK:
case IMX_CCM_UART3_CLK:
case IMX_CCM_UART4_CLK:
CLOCK_EnableClock(uart_clocks[instance]);
return 0;
#endif
default:
(void)instance;
return 0;
}
}
static int mcux_ccm_off(const struct device *dev,
clock_control_subsys_t sub_system)
{
return 0;
uint32_t clock_name = (uintptr_t)sub_system;
uint32_t instance = clock_name & IMX_CCM_INSTANCE_MASK;
switch (clock_name) {
#ifdef CONFIG_UART_MCUX_IUART
case IMX_CCM_UART1_CLK:
case IMX_CCM_UART2_CLK:
case IMX_CCM_UART3_CLK:
case IMX_CCM_UART4_CLK:
CLOCK_DisableClock(uart_clocks[instance]);
return 0;
#endif
default:
(void)instance;
return 0;
}
}
static int mcux_ccm_get_subsys_rate(const struct device *dev,

View file

@ -241,10 +241,12 @@ static int mcux_iuart_init(const struct device *dev)
uart_config.enableRx = true;
uart_config.baudRate_Bps = config->baud_rate;
clock_control_on(config->clock_dev, config->clock_subsys);
UART_Init(config->base, &uart_config, clock_freq);
err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
if (err) {
clock_control_off(config->clock_dev, config->clock_subsys);
return err;
}