drivers: Add MAX32690 clock control driver
Clock control for MAX32690 Co-authored-by: Okan Sahin <okan.sahin@analog.com> Signed-off-by: Sadik Ozer <sadik.ozer@analog.com>
This commit is contained in:
parent
e0528e3852
commit
45df8963f1
7 changed files with 329 additions and 0 deletions
|
@ -76,3 +76,4 @@ if(CONFIG_CLOCK_CONTROL_RCAR_CPG_MSSR)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_AST10X0 clock_control_ast10x0.c)
|
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_AST10X0 clock_control_ast10x0.c)
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_MAX32 clock_control_max32.c)
|
||||||
|
|
|
@ -82,6 +82,8 @@ source "drivers/clock_control/Kconfig.agilex5"
|
||||||
|
|
||||||
source "drivers/clock_control/Kconfig.renesas_ra"
|
source "drivers/clock_control/Kconfig.renesas_ra"
|
||||||
|
|
||||||
|
source "drivers/clock_control/Kconfig.max32"
|
||||||
|
|
||||||
source "drivers/clock_control/Kconfig.ambiq"
|
source "drivers/clock_control/Kconfig.ambiq"
|
||||||
|
|
||||||
source "drivers/clock_control/Kconfig.pwm"
|
source "drivers/clock_control/Kconfig.pwm"
|
||||||
|
|
9
drivers/clock_control/Kconfig.max32
Normal file
9
drivers/clock_control/Kconfig.max32
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# 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
drivers/clock_control/clock_control_max32.c
Normal file
158
drivers/clock_control/clock_control_max32.c
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* 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
dts/bindings/clock/adi,max32-gcr.yaml
Normal file
36
dts/bindings/clock/adi,max32-gcr.yaml
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
# 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
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2024 Analog Devices, Inc.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ADI_MAX32_CLOCK_CONTROL_H_
|
||||||
|
#define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ADI_MAX32_CLOCK_CONTROL_H_
|
||||||
|
|
||||||
|
#include <zephyr/drivers/clock_control.h>
|
||||||
|
|
||||||
|
#include <zephyr/dt-bindings/clock/adi_max32_clock.h>
|
||||||
|
|
||||||
|
#include <wrap_max32_sys.h>
|
||||||
|
|
||||||
|
/** Driver structure definition */
|
||||||
|
|
||||||
|
struct max32_perclk {
|
||||||
|
uint32_t bus;
|
||||||
|
uint32_t bit;
|
||||||
|
|
||||||
|
/* Peripheral clock source:
|
||||||
|
* Can be (see: adi_max32_clock.h file):
|
||||||
|
*
|
||||||
|
* ADI_MAX32_PRPH_CLK_SRC_PCLK
|
||||||
|
* ADI_MAX32_PRPH_CLK_SRC_EXTCLK
|
||||||
|
* ADI_MAX32_PRPH_CLK_SRC_IBRO
|
||||||
|
* ADI_MAX32_PRPH_CLK_SRC_ERFO
|
||||||
|
* ADI_MAX32_PRPH_CLK_SRC_ERTCO
|
||||||
|
* ADI_MAX32_PRPH_CLK_SRC_INRO
|
||||||
|
* ADI_MAX32_PRPH_CLK_SRC_ISO
|
||||||
|
* ADI_MAX32_PRPH_CLK_SRC_IBRO_DIV8
|
||||||
|
*/
|
||||||
|
uint32_t clk_src;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Get prescaler value if it defined */
|
||||||
|
#define ADI_MAX32_SYSCLK_PRESCALER DT_PROP_OR(DT_NODELABEL(gcr), sysclk_prescaler, 1)
|
||||||
|
|
||||||
|
#define ADI_MAX32_CLK_IPO_FREQ DT_PROP(DT_NODELABEL(clk_ipo), clock_frequency)
|
||||||
|
#define ADI_MAX32_CLK_ERFO_FREQ DT_PROP(DT_NODELABEL(clk_erfo), clock_frequency)
|
||||||
|
#define ADI_MAX32_CLK_IBRO_FREQ DT_PROP(DT_NODELABEL(clk_ibro), clock_frequency)
|
||||||
|
#define ADI_MAX32_CLK_ISO_FREQ DT_PROP_OR(DT_NODELABEL(clk_iso), clock_frequency, 0)
|
||||||
|
#define ADI_MAX32_CLK_INRO_FREQ DT_PROP(DT_NODELABEL(clk_inro), clock_frequency)
|
||||||
|
#define ADI_MAX32_CLK_ERTCO_FREQ DT_PROP(DT_NODELABEL(clk_ertco), clock_frequency)
|
||||||
|
/* External clock may not be defined so _OR is used */
|
||||||
|
#define ADI_MAX32_CLK_EXTCLK_FREQ DT_PROP_OR(DT_NODELABEL(clk_extclk), clock_frequency, 0)
|
||||||
|
|
||||||
|
#define DT_GCR_CLOCKS_CTRL DT_CLOCKS_CTLR(DT_NODELABEL(gcr))
|
||||||
|
|
||||||
|
#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_ipo))
|
||||||
|
#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_IPO
|
||||||
|
#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_IPO_FREQ / ADI_MAX32_SYSCLK_PRESCALER)
|
||||||
|
#endif
|
||||||
|
#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_erfo))
|
||||||
|
#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_ERFO
|
||||||
|
#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_ERFO_FREQ / ADI_MAX32_SYSCLK_PRESCALER)
|
||||||
|
#endif
|
||||||
|
#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_ibro))
|
||||||
|
#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_IBRO
|
||||||
|
#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_IBRO_FREQ / ADI_MAX32_SYSCLK_PRESCALER)
|
||||||
|
#endif
|
||||||
|
#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_iso))
|
||||||
|
#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_ISO
|
||||||
|
#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_ISO_FREQ / ADI_MAX32_SYSCLK_PRESCALER)
|
||||||
|
#endif
|
||||||
|
#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_inro))
|
||||||
|
#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_INRO
|
||||||
|
#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_INRO_FREQ / ADI_MAX32_SYSCLK_PRESCALER)
|
||||||
|
#endif
|
||||||
|
#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_ertco))
|
||||||
|
#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_ERTCO
|
||||||
|
#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_ERTCO_FREQ / ADI_MAX32_SYSCLK_PRESCALER)
|
||||||
|
#endif
|
||||||
|
#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_extclk))
|
||||||
|
#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_EXTCLK
|
||||||
|
#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_EXTCLK_FREQ / ADI_MAX32_SYSCLK_PRESCALER)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ADI_MAX32_SYSCLK_SRC
|
||||||
|
#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_IPO
|
||||||
|
#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_IPO_FREQ / ADI_MAX32_SYSCLK_PRESCALER)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ADI_MAX32_PCLK_FREQ (ADI_MAX32_SYSCLK_FREQ / 2)
|
||||||
|
|
||||||
|
#define ADI_MAX32_GET_PRPH_CLK_FREQ(clk_src) \
|
||||||
|
((clk_src) == ADI_MAX32_PRPH_CLK_SRC_PCLK ? ADI_MAX32_PCLK_FREQ \
|
||||||
|
: (clk_src) == ADI_MAX32_PRPH_CLK_SRC_IBRO ? ADI_MAX32_CLK_IBRO_FREQ \
|
||||||
|
: (clk_src) == ADI_MAX32_PRPH_CLK_SRC_ERFO ? ADI_MAX32_CLK_ERFO_FREQ \
|
||||||
|
: (clk_src) == ADI_MAX32_PRPH_CLK_SRC_ERTCO ? ADI_MAX32_CLK_ERTCO_FREQ \
|
||||||
|
: (clk_src) == ADI_MAX32_PRPH_CLK_SRC_INRO ? ADI_MAX32_CLK_INRO_FREQ \
|
||||||
|
: (clk_src) == ADI_MAX32_PRPH_CLK_SRC_ISO ? ADI_MAX32_CLK_ISO_FREQ \
|
||||||
|
: (clk_src) == ADI_MAX32_PRPH_CLK_SRC_IBRO_DIV8 ? (ADI_MAX32_CLK_IBRO_FREQ / 8) \
|
||||||
|
: (clk_src) == ADI_MAX32_PRPH_CLK_SRC_EXTCLK ? ADI_MAX32_CLK_EXTCLK_FREQ \
|
||||||
|
: 0)
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ADI_MAX32_CLOCK_CONTROL_H_ */
|
25
include/zephyr/dt-bindings/clock/adi_max32_clock.h
Normal file
25
include/zephyr/dt-bindings/clock/adi_max32_clock.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023-2024 Analog Devices, Inc.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ADI_MAX32_CLOCK_H_
|
||||||
|
#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ADI_MAX32_CLOCK_H_
|
||||||
|
|
||||||
|
/** Peripheral clock register */
|
||||||
|
#define ADI_MAX32_CLOCK_BUS0 0
|
||||||
|
#define ADI_MAX32_CLOCK_BUS1 1
|
||||||
|
#define ADI_MAX32_CLOCK_BUS2 2
|
||||||
|
|
||||||
|
/** Clock source for peripheral interfaces like UART, WDT... */
|
||||||
|
#define ADI_MAX32_PRPH_CLK_SRC_PCLK 0 /* Peripheral clock */
|
||||||
|
#define ADI_MAX32_PRPH_CLK_SRC_EXTCLK 1 /* External clock */
|
||||||
|
#define ADI_MAX32_PRPH_CLK_SRC_IBRO 2 /* Internal Baud Rate Oscillator*/
|
||||||
|
#define ADI_MAX32_PRPH_CLK_SRC_ERFO 3 /* External RF Oscillator */
|
||||||
|
#define ADI_MAX32_PRPH_CLK_SRC_ERTCO 4 /* External RTC Oscillator */
|
||||||
|
#define ADI_MAX32_PRPH_CLK_SRC_INRO 5 /* Internal Nano Ring Oscillator */
|
||||||
|
#define ADI_MAX32_PRPH_CLK_SRC_ISO 6 /* Internal Secondary Oscillator */
|
||||||
|
#define ADI_MAX32_PRPH_CLK_SRC_IBRO_DIV8 7 /* IBRO/8 */
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ADI_MAX32_CLOCK_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue