Zephyr's current ADC API only supports 32 logical channels, which is inadequate for SAR ADCs on certain SoCs. For instance, the ADC on the MCXE31B has 64 hardware channels. The previous implementation used a one-to-one mapping between logical and hardware channels. In the new SAR ADC driver version, we bind hardware channels to logical channels via the zephyr,input-positive property, enabling us to access any channel. Currently, only imx93 uses this ADC. To maintain the bisectability of Zephyr commits, in this commit we will also modify the imx93-related files, inlcuding: 1. Update the clock_control_mcux_ccm_rev2.c to use the new Kconfig option 'CONFIG_ADC_NXP_SAR_ADC'. 2. Add properties to the imx93_evk_mimx9352_m33.overlay of the adc_api testcase. Now the sar adc is native driver, so, remove CONFIG_MCUX_COMPONENT_driver.sar_adc from the glue cmake. Signed-off-by: Zhaoxiang Jin <Zhaoxiang.Jin_1@nxp.com>
480 lines
11 KiB
C
480 lines
11 KiB
C
/*
|
|
* Copyright 2021,2024-2025 NXP
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#define DT_DRV_COMPAT nxp_imx_ccm_rev2
|
|
#include <errno.h>
|
|
#include <zephyr/drivers/clock_control.h>
|
|
#include <zephyr/dt-bindings/clock/imx_ccm_rev2.h>
|
|
#include <fsl_clock.h>
|
|
#if defined(CONFIG_SOC_MIMX9352)
|
|
#include <soc.h>
|
|
#endif
|
|
|
|
#define LOG_LEVEL CONFIG_CLOCK_CONTROL_LOG_LEVEL
|
|
#include <zephyr/logging/log.h>
|
|
LOG_MODULE_REGISTER(clock_control);
|
|
|
|
static int mcux_ccm_on(const struct device *dev,
|
|
clock_control_subsys_t sub_system)
|
|
{
|
|
uint32_t clock_name = (uintptr_t)sub_system;
|
|
uint32_t peripheral, instance;
|
|
|
|
peripheral = (clock_name & IMX_CCM_PERIPHERAL_MASK);
|
|
instance = (clock_name & IMX_CCM_INSTANCE_MASK);
|
|
switch (peripheral) {
|
|
#ifdef CONFIG_ETH_NXP_ENET
|
|
|
|
#if defined(CONFIG_SOC_MIMX9352) || defined(CONFIG_SOC_MIMX9131)
|
|
#define ENET1G_CLOCK kCLOCK_Enet1
|
|
#else
|
|
#define ENET_CLOCK kCLOCK_Enet
|
|
#define ENET1G_CLOCK kCLOCK_Enet_1g
|
|
#endif
|
|
#ifdef ENET_CLOCK
|
|
case IMX_CCM_ENET_CLK:
|
|
CLOCK_EnableClock(ENET_CLOCK);
|
|
return 0;
|
|
#endif
|
|
case IMX_CCM_ENET1G_CLK:
|
|
CLOCK_EnableClock(ENET1G_CLOCK);
|
|
return 0;
|
|
#endif
|
|
#ifdef CONFIG_I2S_MCUX_SAI
|
|
#if defined(CONFIG_SOC_MIMX9352) || defined(CONFIG_SOC_MIMX9131) || defined(CONFIG_SOC_MIMX9111)
|
|
case IMX_CCM_SAI1_CLK:
|
|
CLOCK_EnableClock(kCLOCK_Sai1 + instance);
|
|
return 0;
|
|
#endif
|
|
#endif
|
|
default:
|
|
(void)instance;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static int mcux_ccm_off(const struct device *dev,
|
|
clock_control_subsys_t sub_system)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int mcux_ccm_get_subsys_rate(const struct device *dev,
|
|
clock_control_subsys_t sub_system,
|
|
uint32_t *rate)
|
|
{
|
|
uint32_t clock_name = (size_t) sub_system;
|
|
uint32_t clock_root, peripheral, instance;
|
|
|
|
peripheral = (clock_name & IMX_CCM_PERIPHERAL_MASK);
|
|
instance = (clock_name & IMX_CCM_INSTANCE_MASK);
|
|
switch (peripheral) {
|
|
#ifdef CONFIG_I2C_MCUX_LPI2C
|
|
#if defined(CONFIG_SOC_SERIES_IMXRT118X)
|
|
case IMX_CCM_LPI2C0102_CLK:
|
|
clock_root = kCLOCK_Root_Lpi2c0102 + instance;
|
|
break;
|
|
#else
|
|
case IMX_CCM_LPI2C1_CLK:
|
|
clock_root = kCLOCK_Root_Lpi2c1 + instance;
|
|
break;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef CONFIG_I3C_MCUX
|
|
case IMX_CCM_I3C1_CLK:
|
|
case IMX_CCM_I3C2_CLK:
|
|
clock_root = kCLOCK_Root_I3c1 + instance;
|
|
break;
|
|
#endif
|
|
|
|
#ifdef CONFIG_SPI_NXP_LPSPI
|
|
#if defined(CONFIG_SOC_SERIES_IMXRT118X)
|
|
case IMX_CCM_LPSPI0102_CLK:
|
|
clock_root = kCLOCK_Root_Lpspi0102 + instance;
|
|
break;
|
|
#else
|
|
case IMX_CCM_LPSPI1_CLK:
|
|
clock_root = kCLOCK_Root_Lpspi1 + instance;
|
|
break;
|
|
#endif /* CONFIG_SOC_SERIES_IMXRT118X */
|
|
#endif /* CONFIG_SPI_NXP_LPSPI */
|
|
|
|
#ifdef CONFIG_UART_MCUX_LPUART
|
|
#if defined(CONFIG_SOC_SERIES_IMXRT118X)
|
|
case IMX_CCM_LPUART0102_CLK:
|
|
case IMX_CCM_LPUART0304_CLK:
|
|
clock_root = kCLOCK_Root_Lpuart0102 + instance;
|
|
break;
|
|
#else
|
|
case IMX_CCM_LPUART1_CLK:
|
|
case IMX_CCM_LPUART2_CLK:
|
|
clock_root = kCLOCK_Root_Lpuart1 + instance;
|
|
break;
|
|
#endif
|
|
#endif
|
|
|
|
#if CONFIG_IMX_USDHC
|
|
case IMX_CCM_USDHC1_CLK:
|
|
case IMX_CCM_USDHC2_CLK:
|
|
clock_root = kCLOCK_Root_Usdhc1 + instance;
|
|
break;
|
|
#endif
|
|
|
|
#ifdef CONFIG_DMA_MCUX_EDMA
|
|
case IMX_CCM_EDMA_CLK:
|
|
clock_root = kCLOCK_Root_Bus;
|
|
break;
|
|
case IMX_CCM_EDMA_LPSR_CLK:
|
|
clock_root = kCLOCK_Root_Bus_Lpsr;
|
|
break;
|
|
#endif
|
|
|
|
#ifdef CONFIG_DMA_MCUX_EDMA_V4
|
|
#if !defined(CONFIG_SOC_MIMX9352) && !defined(CONFIG_SOC_MIMX9131) && !defined(CONFIG_SOC_MIMX9111)
|
|
case IMX_CCM_EDMA3_CLK:
|
|
clock_root = kCLOCK_Root_M33;
|
|
break;
|
|
case IMX_CCM_EDMA4_CLK:
|
|
clock_root = kCLOCK_Root_Wakeup_Axi;
|
|
break;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef CONFIG_PWM_MCUX
|
|
#if defined(CONFIG_SOC_SERIES_IMXRT118X)
|
|
case IMX_CCM_PWM_CLK:
|
|
clock_root = kCLOCK_Root_Bus_Aon;
|
|
break;
|
|
#else
|
|
case IMX_CCM_PWM_CLK:
|
|
clock_root = kCLOCK_Root_Bus;
|
|
break;
|
|
#endif /* CONFIG_SOC_SERIES_IMXRT118X */
|
|
#endif /* CONFIG_PWM_MCUX */
|
|
|
|
#ifdef CONFIG_CAN_MCUX_FLEXCAN
|
|
case IMX_CCM_CAN1_CLK:
|
|
clock_root = kCLOCK_Root_Can1 + instance;
|
|
break;
|
|
#endif
|
|
|
|
#ifdef CONFIG_COUNTER_MCUX_GPT
|
|
case IMX_CCM_GPT_CLK:
|
|
clock_root = kCLOCK_Root_Gpt1 + instance;
|
|
break;
|
|
#endif
|
|
|
|
#ifdef CONFIG_I2S_MCUX_SAI
|
|
#if (defined(CONFIG_SOC_MIMX9352) || defined(CONFIG_SOC_MIMX9131) || defined(CONFIG_SOC_MIMX9111))
|
|
case IMX_CCM_SAI1_CLK:
|
|
clock_root = kCLOCK_Root_Sai1 + instance;
|
|
break;
|
|
#else
|
|
case IMX_CCM_SAI1_CLK:
|
|
clock_root = kCLOCK_Root_Sai1;
|
|
break;
|
|
case IMX_CCM_SAI2_CLK:
|
|
clock_root = kCLOCK_Root_Sai2;
|
|
break;
|
|
case IMX_CCM_SAI3_CLK:
|
|
clock_root = kCLOCK_Root_Sai3;
|
|
break;
|
|
case IMX_CCM_SAI4_CLK:
|
|
clock_root = kCLOCK_Root_Sai4;
|
|
break;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef CONFIG_ETH_NXP_ENET
|
|
case IMX_CCM_ENET_CLK:
|
|
case IMX_CCM_ENET1G_CLK:
|
|
#if defined(CONFIG_SOC_MIMX9352) || defined(CONFIG_SOC_MIMX9131)
|
|
clock_root = kCLOCK_Root_WakeupAxi;
|
|
#else
|
|
clock_root = kCLOCK_Root_Bus;
|
|
#endif
|
|
break;
|
|
#endif
|
|
|
|
#if defined(CONFIG_SOC_MIMX9352)
|
|
case IMX_CCM_MEDIA_AXI_CLK:
|
|
clock_root = kCLOCK_Root_MediaAxi;
|
|
break;
|
|
case IMX_CCM_MEDIA_APB_CLK:
|
|
clock_root = kCLOCK_Root_MediaApb;
|
|
break;
|
|
case IMX_CCM_MEDIA_DISP_PIX_CLK:
|
|
clock_root = kCLOCK_Root_MediaDispPix;
|
|
break;
|
|
case IMX_CCM_MEDIA_LDB_CLK:
|
|
clock_root = kCLOCK_Root_MediaLdb;
|
|
break;
|
|
case IMX_CCM_MIPI_PHY_CFG_CLK:
|
|
clock_root = kCLOCK_Root_MipiPhyCfg;
|
|
break;
|
|
case IMX_CCM_CAM_PIX_CLK:
|
|
clock_root = kCLOCK_Root_CamPix;
|
|
break;
|
|
#endif
|
|
|
|
#if defined(CONFIG_SOC_MIMX9352) && defined(CONFIG_DAI_NXP_SAI)
|
|
case IMX_CCM_SAI1_CLK:
|
|
case IMX_CCM_SAI2_CLK:
|
|
case IMX_CCM_SAI3_CLK:
|
|
clock_root = kCLOCK_Root_Sai1 + instance;
|
|
uint32_t mux = CLOCK_GetRootClockMux(clock_root);
|
|
uint32_t divider = CLOCK_GetRootClockDiv(clock_root);
|
|
|
|
/* assumption: SAI's SRC is AUDIO_PLL */
|
|
if (mux != 1) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* assumption: AUDIO_PLL's frequency is 393216000 Hz */
|
|
*rate = 393216000 / divider;
|
|
|
|
return 0;
|
|
#endif
|
|
#if defined(CONFIG_COUNTER_MCUX_TPM) || defined(CONFIG_PWM_MCUX_TPM)
|
|
#if defined(CONFIG_SOC_SERIES_IMXRT118X)
|
|
case IMX_CCM_TPM_CLK:
|
|
switch (instance) {
|
|
case 0:
|
|
clock_root = kCLOCK_Root_Bus_Aon;
|
|
break;
|
|
case 1:
|
|
clock_root = kCLOCK_Root_Tpm2;
|
|
break;
|
|
case 2:
|
|
clock_root = kCLOCK_Root_Bus_Wakeup;
|
|
break;
|
|
default:
|
|
clock_root = (kCLOCK_Root_Tpm4 + instance - 3);
|
|
}
|
|
break;
|
|
#elif defined(CONFIG_SOC_MIMX9352_A55) || defined(CONFIG_SOC_MIMX9352_M33)
|
|
case IMX_CCM_TPM_CLK:
|
|
switch (instance) {
|
|
case 2:
|
|
clock_root = kCLOCK_Root_BusWakeup;
|
|
break;
|
|
default:
|
|
clock_root = kCLOCK_Root_Tpm1 + instance;
|
|
}
|
|
break;
|
|
#else
|
|
case IMX_CCM_TPM_CLK:
|
|
clock_root = kCLOCK_Root_Tpm1 + instance;
|
|
break;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef CONFIG_MCUX_FLEXIO
|
|
case IMX_CCM_FLEXIO_CLK:
|
|
clock_root = kCLOCK_Root_Flexio1 + instance;
|
|
break;
|
|
#endif
|
|
|
|
#if defined(CONFIG_PWM_MCUX_QTMR) || defined(CONFIG_COUNTER_MCUX_QTMR)
|
|
#if defined(CONFIG_SOC_SERIES_IMXRT118X)
|
|
case IMX_CCM_QTMR_CLK:
|
|
clock_root = kCLOCK_Root_Bus_Aon;
|
|
break;
|
|
#else
|
|
case IMX_CCM_QTMR1_CLK:
|
|
case IMX_CCM_QTMR2_CLK:
|
|
case IMX_CCM_QTMR3_CLK:
|
|
case IMX_CCM_QTMR4_CLK:
|
|
clock_root = kCLOCK_Root_Bus;
|
|
break;
|
|
#endif /* CONFIG_SOC_SERIES_IMXRT118X */
|
|
#endif /* CONFIG_PWM_MCUX_QTMR || CONFIG_COUNTER_MCUX_QTMR */
|
|
|
|
#ifdef CONFIG_MEMC_MCUX_FLEXSPI
|
|
case IMX_CCM_FLEXSPI_CLK:
|
|
case IMX_CCM_FLEXSPI2_CLK:
|
|
clock_root = kCLOCK_Root_Flexspi1 + instance;
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_COUNTER_NXP_PIT
|
|
case IMX_CCM_PIT_CLK:
|
|
clock_root = kCLOCK_Root_Bus + instance;
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_COUNTER_MCUX_LPIT
|
|
#if defined(CONFIG_SOC_SERIES_IMXRT118X)
|
|
case IMX_CCM_LPIT_CLK:
|
|
switch (instance) {
|
|
case 0:
|
|
clock_root = kCLOCK_Root_Bus_Aon;
|
|
break;
|
|
case 1:
|
|
clock_root = kCLOCK_Root_Bus_Wakeup;
|
|
break;
|
|
case 2:
|
|
clock_root = kCLOCK_Root_Lpit3;
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
break;
|
|
#endif
|
|
#endif
|
|
#ifdef CONFIG_ADC_MCUX_LPADC
|
|
case IMX_CCM_LPADC1_CLK:
|
|
clock_root = kCLOCK_Root_Adc1 + instance;
|
|
break;
|
|
#endif
|
|
|
|
#ifdef CONFIG_ADC_NXP_SAR_ADC
|
|
case IMX_CCM_SAR_ADC1_CLK:
|
|
clock_root = kCLOCK_Root_Adc + instance;
|
|
break;
|
|
#endif
|
|
|
|
#if defined(CONFIG_ETH_NXP_IMX_NETC)
|
|
case IMX_CCM_NETC_CLK:
|
|
clock_root = kCLOCK_Root_Netc;
|
|
break;
|
|
#endif
|
|
|
|
#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX)
|
|
case IMX_CCM_MIPI_CSI2RX_ROOT_CLK:
|
|
clock_root = kCLOCK_Root_Csi2;
|
|
break;
|
|
case IMX_CCM_MIPI_CSI2RX_ESC_CLK:
|
|
clock_root = kCLOCK_Root_Csi2_Esc;
|
|
break;
|
|
case IMX_CCM_MIPI_CSI2RX_UI_CLK:
|
|
clock_root = kCLOCK_Root_Csi2_Ui;
|
|
break;
|
|
#endif
|
|
|
|
#ifdef CONFIG_INPUT_MCUX_KPP
|
|
case IMX_CCM_KPP_CLK:
|
|
clock_root = kCLOCK_CpuClk;
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
#if defined(CONFIG_SOC_MIMX9352) || defined(CONFIG_SOC_MIMX9131) \
|
|
|| defined(CONFIG_SOC_MIMX9111)
|
|
*rate = CLOCK_GetIpFreq(clock_root);
|
|
#else
|
|
*rate = CLOCK_GetRootClockFreq(clock_root);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Since this function is used to reclock the FlexSPI when running in
|
|
* XIP, it must be located in RAM when MEMC driver is enabled.
|
|
*/
|
|
#ifdef CONFIG_MEMC_MCUX_FLEXSPI
|
|
#define CCM_SET_FUNC_ATTR __ramfunc
|
|
#else
|
|
#define CCM_SET_FUNC_ATTR
|
|
#endif
|
|
|
|
static int CCM_SET_FUNC_ATTR mcux_ccm_set_subsys_rate(const struct device *dev,
|
|
clock_control_subsys_t subsys,
|
|
clock_control_subsys_rate_t rate)
|
|
{
|
|
uint32_t clock_name = (uintptr_t)subsys;
|
|
uint32_t clock_rate = (uintptr_t)rate;
|
|
|
|
switch (clock_name) {
|
|
case IMX_CCM_FLEXSPI_CLK:
|
|
__fallthrough;
|
|
case IMX_CCM_FLEXSPI2_CLK:
|
|
#if (defined(CONFIG_SOC_SERIES_IMXRT11XX) || defined(CONFIG_SOC_SERIES_IMXRT118X)) \
|
|
&& defined(CONFIG_MEMC_MCUX_FLEXSPI)
|
|
/* The SOC is using the FlexSPI for XIP. Therefore,
|
|
* the FlexSPI itself must be managed within the function,
|
|
* which is SOC specific.
|
|
*/
|
|
return flexspi_clock_set_freq(clock_name, clock_rate);
|
|
#endif
|
|
|
|
#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX)
|
|
case IMX_CCM_MIPI_CSI2RX_ROOT_CLK:
|
|
return mipi_csi2rx_clock_set_freq(kCLOCK_Root_Csi2, clock_rate);
|
|
case IMX_CCM_MIPI_CSI2RX_UI_CLK:
|
|
return mipi_csi2rx_clock_set_freq(kCLOCK_Root_Csi2_Ui, clock_rate);
|
|
case IMX_CCM_MIPI_CSI2RX_ESC_CLK:
|
|
return mipi_csi2rx_clock_set_freq(kCLOCK_Root_Csi2_Esc, clock_rate);
|
|
#endif
|
|
|
|
#if defined(CONFIG_SOC_MIMX9352)
|
|
case IMX_CCM_MEDIA_AXI_CLK:
|
|
case IMX_CCM_MEDIA_APB_CLK:
|
|
case IMX_CCM_MEDIA_DISP_PIX_CLK:
|
|
case IMX_CCM_MEDIA_LDB_CLK:
|
|
case IMX_CCM_MIPI_PHY_CFG_CLK:
|
|
case IMX_CCM_CAM_PIX_CLK:
|
|
return common_clock_set_freq(clock_name, (uint32_t)clock_rate);
|
|
#endif
|
|
|
|
#if (defined(CONFIG_SOC_MIMX9352) || defined(CONFIG_SOC_MIMX9131) || \
|
|
defined(CONFIG_SOC_MIMX9111)) && defined(CONFIG_I2S_MCUX_SAI)
|
|
case IMX_CCM_SAI1_CLK:
|
|
case IMX_CCM_SAI2_CLK:
|
|
case IMX_CCM_SAI3_CLK:
|
|
uint32_t clock_root, instance;
|
|
clock_root_config_t saiClkCfg;
|
|
fracn_pll_init_t g_audioPllCfg;
|
|
|
|
instance = (clock_name & IMX_CCM_INSTANCE_MASK);
|
|
clock_root = kCLOCK_Root_Sai1 + instance;
|
|
|
|
/* Fixed AUDIO_PLL's frequency at 393216000 Hz */
|
|
#define AUDIO_PLL_CLK_FREQ 393216000
|
|
g_clockSourceFreq[kCLOCK_AudioPll1Out] = AUDIO_PLL_CLK_FREQ;
|
|
g_clockSourceFreq[kCLOCK_AudioPll1] = AUDIO_PLL_CLK_FREQ;
|
|
g_audioPllCfg.rdiv = 1;
|
|
g_audioPllCfg.mfi = 163;
|
|
g_audioPllCfg.mfn = 84;
|
|
g_audioPllCfg.mfd = 100;
|
|
g_audioPllCfg.odiv = 10;
|
|
|
|
CLOCK_PllInit(AUDIOPLL, &g_audioPllCfg);
|
|
|
|
saiClkCfg.clockOff = false;
|
|
saiClkCfg.mux = 1;
|
|
saiClkCfg.div = (AUDIO_PLL_CLK_FREQ + (clock_rate - 1)) / clock_rate;
|
|
|
|
CLOCK_SetRootClock(clock_root, &saiClkCfg);
|
|
|
|
return 0;
|
|
#endif
|
|
|
|
#if defined(CONFIG_UDC_NXP_EHCI) && defined(CONFIG_SOC_MIMX9352_A55)
|
|
case IMX_CCM_USB_CLK:
|
|
case IMX_CCM_USB_PHY_CLK:
|
|
return common_clock_set_freq(clock_name, (uint32_t)clock_rate);
|
|
#endif
|
|
|
|
default:
|
|
/* Silence unused variable warning */
|
|
ARG_UNUSED(clock_rate);
|
|
return -ENOTSUP;
|
|
}
|
|
}
|
|
|
|
static DEVICE_API(clock_control, mcux_ccm_driver_api) = {
|
|
.on = mcux_ccm_on,
|
|
.off = mcux_ccm_off,
|
|
.get_rate = mcux_ccm_get_subsys_rate,
|
|
.set_rate = mcux_ccm_set_subsys_rate,
|
|
};
|
|
|
|
DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, PRE_KERNEL_1,
|
|
CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
|
|
&mcux_ccm_driver_api);
|