Commit 45df8963 authored by Sadik Ozer's avatar Sadik Ozer Committed by Henrik Brix Andersen
Browse files

drivers: Add MAX32690 clock control driver



Clock control for MAX32690

Co-authored-by: default avatarOkan Sahin <okan.sahin@analog.com>
Signed-off-by: default avatarSadik Ozer <sadik.ozer@analog.com>
parent e0528e38
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -76,3 +76,4 @@ if(CONFIG_CLOCK_CONTROL_RCAR_CPG_MSSR)
endif()

zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_AST10X0 clock_control_ast10x0.c)
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_MAX32 clock_control_max32.c)
+2 −0
Original line number Diff line number Diff line
@@ -82,6 +82,8 @@ source "drivers/clock_control/Kconfig.agilex5"

source "drivers/clock_control/Kconfig.renesas_ra"

source "drivers/clock_control/Kconfig.max32"

source "drivers/clock_control/Kconfig.ambiq"

source "drivers/clock_control/Kconfig.pwm"
+9 −0
Original line number Diff line number Diff line
# Copyright (c) 2023-2024 Analog Devices, Inc.
# SPDX-License-Identifier: Apache-2.0

config CLOCK_CONTROL_MAX32
	bool "MAX32 Clock Control Driver"
	default y
	depends on DT_HAS_ADI_MAX32_GCR_ENABLED
	help
	  Enable clock control support for Analog Devices MAX32xxx/MAX78xxx SoC series.
+158 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2023-2024 Analog Devices, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/adi_max32_clock_control.h>

#include <wrap_max32_sys.h>

#define DT_DRV_COMPAT adi_max32_gcr

static inline int api_on(const struct device *dev, clock_control_subsys_t clkcfg)
{
	ARG_UNUSED(dev);
	struct max32_perclk *perclk = (struct max32_perclk *)(clkcfg);

	switch (perclk->bus) {
	case ADI_MAX32_CLOCK_BUS0:
		MXC_SYS_ClockEnable((mxc_sys_periph_clock_t)perclk->bit);
		break;
	case ADI_MAX32_CLOCK_BUS1:
		MXC_SYS_ClockEnable((mxc_sys_periph_clock_t)(perclk->bit + 32));
		break;
	case ADI_MAX32_CLOCK_BUS2:
		MXC_SYS_ClockEnable((mxc_sys_periph_clock_t)(perclk->bit + 64));
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static inline int api_off(const struct device *dev, clock_control_subsys_t clkcfg)
{
	ARG_UNUSED(dev);
	struct max32_perclk *perclk = (struct max32_perclk *)(clkcfg);

	switch (perclk->bus) {
	case ADI_MAX32_CLOCK_BUS0:
		MXC_SYS_ClockDisable((mxc_sys_periph_clock_t)perclk->bit);
		break;
	case ADI_MAX32_CLOCK_BUS1:
		MXC_SYS_ClockDisable((mxc_sys_periph_clock_t)(perclk->bit + 32));
		break;
	case ADI_MAX32_CLOCK_BUS2:
		MXC_SYS_ClockDisable((mxc_sys_periph_clock_t)(perclk->bit + 64));
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int api_get_rate(const struct device *dev, clock_control_subsys_t clkcfg, uint32_t *rate)
{
	ARG_UNUSED(dev);
	struct max32_perclk *perclk = (struct max32_perclk *)(clkcfg);

	switch (perclk->clk_src) {
	case ADI_MAX32_PRPH_CLK_SRC_PCLK:
		*rate = ADI_MAX32_PCLK_FREQ;
		break;
	case ADI_MAX32_PRPH_CLK_SRC_EXTCLK:
		*rate = ADI_MAX32_CLK_EXTCLK_FREQ;
		break;
	case ADI_MAX32_PRPH_CLK_SRC_IBRO:
		*rate = ADI_MAX32_CLK_IBRO_FREQ;
		break;
	case ADI_MAX32_PRPH_CLK_SRC_ERFO:
		*rate = ADI_MAX32_CLK_ERFO_FREQ;
		break;
	case ADI_MAX32_PRPH_CLK_SRC_ERTCO:
		*rate = ADI_MAX32_CLK_ERTCO_FREQ;
		break;
	case ADI_MAX32_PRPH_CLK_SRC_INRO:
		*rate = ADI_MAX32_CLK_INRO_FREQ;
		break;
	case ADI_MAX32_PRPH_CLK_SRC_ISO:
		*rate = ADI_MAX32_CLK_ISO_FREQ;
		break;
	case ADI_MAX32_PRPH_CLK_SRC_IBRO_DIV8:
		*rate = ADI_MAX32_CLK_IBRO_FREQ / 8;
		break;
	default:
		*rate = 0U;
		/* Invalid parameters */
		return -EINVAL;
	}

	return 0;
}

static const struct clock_control_driver_api max32_clkctrl_api = {
	.on = api_on,
	.off = api_off,
	.get_rate = api_get_rate,
};

static void setup_fixed_clocks(void)
{
#if DT_NODE_HAS_COMPAT(DT_NODELABEL(clk_extclk), fixed_clock)
	MXC_SYS_ClockSourceDisable(ADI_MAX32_CLK_EXTCLK);
#endif

#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_ipo), okay)
	MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_IPO);
#endif

#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_erfo), okay)
	MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_ERFO);
#endif

#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_ibro), okay)
	MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_IBRO);
#endif

#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_iso), okay)
	MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_ISO);
#endif

#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_inro), okay)
	MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_INRO);
#endif

#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_ertco), okay)
	MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_ERTCO);
#endif

/* Some device does not support external clock */
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_extclk), fixed_clock, okay)
	MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_EXTCLK);
#endif
}

static int max32_clkctrl_init(const struct device *dev)
{
	ARG_UNUSED(dev);

	/* Setup fixed clocks if enabled */
	setup_fixed_clocks();

	/* Setup device clock source */
	MXC_SYS_Clock_Select(ADI_MAX32_SYSCLK_SRC);

#if DT_NODE_HAS_PROP(DT_NODELABEL(gcr), sysclk_prescaler)
	/* Setup divider */
	Wrap_MXC_SYS_SetClockDiv(sysclk_prescaler(ADI_MAX32_SYSCLK_PRESCALER));
#endif

	return 0;
}

DEVICE_DT_INST_DEFINE(0, max32_clkctrl_init, NULL, NULL, NULL, PRE_KERNEL_1,
		      CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &max32_clkctrl_api);
+36 −0
Original line number Diff line number Diff line
# Copyright (c) 2023-2024 Analog Devices, Inc.
# SPDX-License-Identifier: Apache-2.0

description: MAX32 Global Control

compatible: "adi,max32-gcr"

include: [clock-controller.yaml, base.yaml]

properties:
  reg:
    required: true

  "#clock-cells":
    const: 2

  sysclk-prescaler:
    type: int
    enum:
      - 1
      - 2
      - 4
      - 8
      - 16
      - 32
      - 64
      - 128

    description: |
        SYSCLK prescaler. Defines actual core clock frequency SYSCLK
        based on system frequency input. Some MAX32xxx devices does not
        support this feature, check your device user guide before using it.

clock-cells:
  - offset
  - bit
Loading