soc: xtensa: imx8: Enable clock control on i.MX8QM/QXP

This commit enables clock control on the i.MX8QM and QXP boards.
This is achieved through the following changes:
	1) The "reg" property is no longer marked as required
	for the "nxp,imx-ccm" binding. This is necessary because
	in the case of i.MX8QM and i.MX8QXP the clock management
	is done through the SCFW, hence there's no need to access
	CCM's MMIO space (not that you could anyways).

	2) The DTS now contains a scu_mu node. This node refers
	to the MU instance used by the DSP to communicate with
	the SCFW.

	3) The CCM driver needs to support the LPUART clocks
	(which will be the only IP that's supported for now)
	and needs to perform an initialization so that the
	NXP HAL driver knows which MU to use to communicate
	with the SCFW.

Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
This commit is contained in:
Laurentiu Mihalcea 2023-09-22 11:19:57 +03:00 committed by Carles Cufí
parent eb12bae048
commit ea99578b76
5 changed files with 112 additions and 5 deletions

View file

@ -12,3 +12,6 @@ CONFIG_LOG=y
# TODO: maybe move this to SOF?
CONFIG_DYNAMIC_INTERRUPTS=y
CONFIG_BUILD_OUTPUT_BIN=n
# clock-related configurations
CONFIG_CLOCK_CONTROL=y

View file

@ -12,3 +12,6 @@ CONFIG_LOG=y
# TODO: maybe move this to SOF?
CONFIG_DYNAMIC_INTERRUPTS=y
CONFIG_BUILD_OUTPUT_BIN=n
# clock-related configurations
CONFIG_CLOCK_CONTROL=y

View file

@ -12,6 +12,10 @@
#include <zephyr/dt-bindings/clock/imx_ccm.h>
#include <fsl_clock.h>
#if defined(CONFIG_SOC_MIMX8QM_ADSP) || defined(CONFIG_SOC_MIMX8QXP_ADSP)
#include <main/ipc.h>
#endif
#define LOG_LEVEL CONFIG_CLOCK_CONTROL_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(clock_control);
@ -52,6 +56,34 @@ static const clock_root_t lpuart_clk_root[] = {
};
#endif
#ifdef CONFIG_UART_MCUX_LPUART
#ifdef CONFIG_SOC_MIMX8QM_ADSP
static const clock_ip_name_t lpuart_clocks[] = {
kCLOCK_DMA_Lpuart0,
kCLOCK_DMA_Lpuart1,
kCLOCK_DMA_Lpuart2,
kCLOCK_DMA_Lpuart3,
kCLOCK_DMA_Lpuart4,
};
static const uint32_t lpuart_rate = MHZ(80);
#endif /* CONFIG_SOC_MIMX8QM_ADSP */
#ifdef CONFIG_SOC_MIMX8QXP_ADSP
static const clock_ip_name_t lpuart_clocks[] = {
kCLOCK_DMA_Lpuart0,
kCLOCK_DMA_Lpuart1,
kCLOCK_DMA_Lpuart2,
kCLOCK_DMA_Lpuart3,
};
static const uint32_t lpuart_rate = MHZ(80);
#endif /* CONFIG_SOC_MIMX8QXP_ADSP */
#endif /* CONFIG_UART_MCUX_LPUART */
static int mcux_ccm_on(const struct device *dev,
clock_control_subsys_t sub_system)
{
@ -67,6 +99,25 @@ static int mcux_ccm_on(const struct device *dev,
CLOCK_EnableClock(uart_clocks[instance]);
return 0;
#endif
#if defined(CONFIG_UART_MCUX_LPUART) && defined(CONFIG_SOC_MIMX8QM_ADSP)
case IMX_CCM_LPUART1_CLK:
case IMX_CCM_LPUART2_CLK:
case IMX_CCM_LPUART3_CLK:
case IMX_CCM_LPUART4_CLK:
case IMX_CCM_LPUART5_CLK:
CLOCK_EnableClock(lpuart_clocks[instance]);
return 0;
#endif
#if defined(CONFIG_UART_MCUX_LPUART) && defined(CONFIG_SOC_MIMX8QXP_ADSP)
case IMX_CCM_LPUART1_CLK:
case IMX_CCM_LPUART2_CLK:
case IMX_CCM_LPUART3_CLK:
case IMX_CCM_LPUART4_CLK:
CLOCK_EnableClock(lpuart_clocks[instance]);
return 0;
#endif
default:
(void)instance;
return 0;
@ -128,7 +179,31 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev,
#endif
#ifdef CONFIG_UART_MCUX_LPUART
#ifdef CONFIG_SOC_MIMX93_A55
#if defined(CONFIG_SOC_MIMX8QM_ADSP)
case IMX_CCM_LPUART1_CLK:
case IMX_CCM_LPUART2_CLK:
case IMX_CCM_LPUART3_CLK:
case IMX_CCM_LPUART4_CLK:
case IMX_CCM_LPUART5_CLK:
uint32_t instance = clock_name & IMX_CCM_INSTANCE_MASK;
CLOCK_SetIpFreq(lpuart_clocks[instance], lpuart_rate);
*rate = CLOCK_GetIpFreq(lpuart_clocks[instance]);
break;
#elif defined(CONFIG_SOC_MIMX8QXP_ADSP)
case IMX_CCM_LPUART1_CLK:
case IMX_CCM_LPUART2_CLK:
case IMX_CCM_LPUART3_CLK:
case IMX_CCM_LPUART4_CLK:
uint32_t instance = clock_name & IMX_CCM_INSTANCE_MASK;
CLOCK_SetIpFreq(lpuart_clocks[instance], lpuart_rate);
*rate = CLOCK_GetIpFreq(lpuart_clocks[instance]);
break;
#elif defined(CONFIG_SOC_MIMX93_A55)
case IMX_CCM_LPUART1_CLK:
case IMX_CCM_LPUART2_CLK:
case IMX_CCM_LPUART3_CLK:
@ -270,6 +345,22 @@ static const struct clock_control_driver_api mcux_ccm_driver_api = {
.get_rate = mcux_ccm_get_subsys_rate,
};
DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL,
static int mcux_ccm_init(const struct device *dev)
{
#if defined(CONFIG_SOC_MIMX8QM_ADSP) || defined(CONFIG_SOC_MIMX8QXP_ADSP)
sc_ipc_t ipc_handle;
int ret;
ret = sc_ipc_open(&ipc_handle, DT_REG_ADDR(DT_NODELABEL(scu_mu)));
if (ret != SC_ERR_NONE) {
return -ENODEV;
}
CLOCK_Init(ipc_handle);
#endif
return 0;
}
DEVICE_DT_INST_DEFINE(0, mcux_ccm_init, NULL, NULL, NULL,
PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
&mcux_ccm_driver_api);

View file

@ -8,9 +8,6 @@ compatible: "nxp,imx-ccm"
include: [clock-controller.yaml, base.yaml]
properties:
reg:
required: true
"#clock-cells":
const: 3

View file

@ -6,6 +6,7 @@
#include <xtensa/xtensa.dtsi>
#include <mem.h>
#include <zephyr/dt-bindings/clock/imx_ccm.h>
/ {
cpus {
@ -30,4 +31,16 @@
compatible = "mmio-sram";
reg = <0x92c00000 DT_SIZE_K(512)>;
};
/* LSIO MU2, used to interact with the SCFW */
scu_mu: mailbox@5d1d0000 {
reg = <0x5d1d0000 DT_SIZE_K(64)>;
};
scu: system-controller {
ccm: clock-controller {
compatible = "nxp,imx-ccm";
#clock-cells = <3>;
};
};
};