Linux preempt-rt

Check our new training course

Real-Time Linux with PREEMPT_RT

Check our new training course
with Creative Commons CC-BY-SA
lecture and lab materials

Bootlin logo

Elixir Cross Referencer

/*
 * Copyright (c) 2020, NXP
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT nxp_lpc_syscon
#include <errno.h>
#include <soc.h>
#include <drivers/clock_control.h>
#include <dt-bindings/clock/mcux_lpc_syscon_clock.h>
#include <fsl_clock.h>

#define LOG_LEVEL CONFIG_CLOCK_CONTROL_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(clock_control);

static int mcux_lpc_syscon_clock_control_on(const struct device *dev,
			      clock_control_subsys_t sub_system)
{
	return 0;
}

static int mcux_lpc_syscon_clock_control_off(const struct device *dev,
			       clock_control_subsys_t sub_system)
{
	return 0;
}

static int mcux_lpc_syscon_clock_control_get_subsys_rate(
					const struct device *dev,
				    clock_control_subsys_t sub_system,
				    uint32_t *rate)
{
#if defined(CONFIG_I2C_MCUX_FLEXCOMM) || \
		defined(CONFIG_SPI_MCUX_FLEXCOMM) || \
		defined(CONFIG_UART_MCUX_FLEXCOMM) || \
		defined(CONFIG_COUNTER_MCUX_CTIMER)

	uint32_t clock_name = (uint32_t) sub_system;

	switch (clock_name) {
	case MCUX_FLEXCOMM0_CLK:
		*rate = CLOCK_GetFlexCommClkFreq(0);
		break;
	case MCUX_FLEXCOMM1_CLK:
		*rate = CLOCK_GetFlexCommClkFreq(1);
		break;
	case MCUX_FLEXCOMM2_CLK:
		*rate = CLOCK_GetFlexCommClkFreq(2);
		break;
	case MCUX_FLEXCOMM3_CLK:
		*rate = CLOCK_GetFlexCommClkFreq(3);
		break;
	case MCUX_FLEXCOMM4_CLK:
		*rate = CLOCK_GetFlexCommClkFreq(4);
		break;
	case MCUX_FLEXCOMM5_CLK:
		*rate = CLOCK_GetFlexCommClkFreq(5);
		break;
	case MCUX_FLEXCOMM6_CLK:
		*rate = CLOCK_GetFlexCommClkFreq(6);
		break;
	case MCUX_FLEXCOMM7_CLK:
		*rate = CLOCK_GetFlexCommClkFreq(7);
		break;
	case MCUX_HS_SPI_CLK:
#if defined(FSL_FEATURE_FLEXCOMM8_SPI_INDEX)
		*rate = CLOCK_GetHsLspiClkFreq();
#elif defined(FSL_FEATURE_FLEXCOMM14_SPI_INDEX)
		*rate = CLOCK_GetFlexCommClkFreq(14);
#else
		LOG_ERR("Missing feature define for HS_SPI clock!");
#endif
		break;
#if (defined(FSL_FEATURE_SOC_USDHC_COUNT) && FSL_FEATURE_SOC_USDHC_COUNT)
	case MCUX_USDHC1_CLK:
		*rate = CLOCK_GetSdioClkFreq(0);
		break;
	case MCUX_USDHC2_CLK:
		*rate = CLOCK_GetSdioClkFreq(1);
		break;
#endif
#if defined(CONFIG_COUNTER_MCUX_CTIMER)
	case (MCUX_CTIMER0_CLK + MCUX_CTIMER_CLK_OFFSET):
		*rate = CLOCK_GetCTimerClkFreq(0);
		break;
	case (MCUX_CTIMER1_CLK + MCUX_CTIMER_CLK_OFFSET):
		*rate = CLOCK_GetCTimerClkFreq(1);
		break;
	case (MCUX_CTIMER2_CLK + MCUX_CTIMER_CLK_OFFSET):
		*rate = CLOCK_GetCTimerClkFreq(2);
		break;
	case (MCUX_CTIMER3_CLK + MCUX_CTIMER_CLK_OFFSET):
		*rate = CLOCK_GetCTimerClkFreq(3);
		break;
	case (MCUX_CTIMER4_CLK + MCUX_CTIMER_CLK_OFFSET):
		*rate = CLOCK_GetCTimerClkFreq(4);
		break;
#endif
	}
#endif

	return 0;
}

static int mcux_lpc_syscon_clock_control_init(const struct device *dev)
{
	return 0;
}

static const struct clock_control_driver_api mcux_lpc_syscon_api = {
	.on = mcux_lpc_syscon_clock_control_on,
	.off = mcux_lpc_syscon_clock_control_off,
	.get_rate = mcux_lpc_syscon_clock_control_get_subsys_rate,
};

#define LPC_CLOCK_INIT(n) \
	\
DEVICE_DT_INST_DEFINE(n, \
		    &mcux_lpc_syscon_clock_control_init, \
		    NULL, \
		    NULL, NULL, \
		    PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
		    &mcux_lpc_syscon_api);

DT_INST_FOREACH_STATUS_OKAY(LPC_CLOCK_INIT)