From 6722544f1e36ea749f28b7b616ff7ce9395782f9 Mon Sep 17 00:00:00 2001 From: Aaron Ye Date: Sat, 4 Nov 2023 08:26:51 +0800 Subject: [PATCH] drivers: clock_control: Add Ambiq clock_control driver. This commit adds Ambiq clock_control driver support. Signed-off-by: Aaron Ye --- drivers/clock_control/CMakeLists.txt | 1 + drivers/clock_control/Kconfig | 2 + drivers/clock_control/Kconfig.ambiq | 14 ++ drivers/clock_control/clock_control_ambiq.c | 138 ++++++++++++++++++ dts/bindings/clock/ambiq,clkctrl.yaml | 23 +++ .../clock_control/clock_control_ambiq.h | 37 +++++ 6 files changed, 215 insertions(+) create mode 100644 drivers/clock_control/Kconfig.ambiq create mode 100644 drivers/clock_control/clock_control_ambiq.c create mode 100644 dts/bindings/clock/ambiq,clkctrl.yaml create mode 100644 include/zephyr/drivers/clock_control/clock_control_ambiq.h diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index 8b246b55e38..0f7a1c4dd4a 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -27,6 +27,7 @@ zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_SMARTBOND clock_cont zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NUMAKER_SCC clock_control_numaker_scc.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NXP_S32 clock_control_nxp_s32.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_RA clock_control_ra.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_AMBIQ clock_control_ambiq.c) if(CONFIG_CLOCK_CONTROL_STM32_CUBE) diff --git a/drivers/clock_control/Kconfig b/drivers/clock_control/Kconfig index 3ff554e684a..a380b9a9c12 100644 --- a/drivers/clock_control/Kconfig +++ b/drivers/clock_control/Kconfig @@ -82,4 +82,6 @@ source "drivers/clock_control/Kconfig.agilex5" source "drivers/clock_control/Kconfig.ra" +source "drivers/clock_control/Kconfig.ambiq" + endif # CLOCK_CONTROL diff --git a/drivers/clock_control/Kconfig.ambiq b/drivers/clock_control/Kconfig.ambiq new file mode 100644 index 00000000000..ca0a4c1bce5 --- /dev/null +++ b/drivers/clock_control/Kconfig.ambiq @@ -0,0 +1,14 @@ +# Ambiq Clock Control Driver configuration options +# +# Copyright (c) 2023 Ambiq Micro Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +config CLOCK_CONTROL_AMBIQ + bool "AMBIQ clock control driver" + default y + depends on DT_HAS_AMBIQ_CLKCTRL_ENABLED + select AMBIQ_HAL + help + Enable driver for Ambiq clock control. diff --git a/drivers/clock_control/clock_control_ambiq.c b/drivers/clock_control/clock_control_ambiq.c new file mode 100644 index 00000000000..a64030c2a2d --- /dev/null +++ b/drivers/clock_control/clock_control_ambiq.c @@ -0,0 +1,138 @@ +/* + * Copyright 2023 Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ambiq_clkctrl + +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(clock_control_ambiq, CONFIG_CLOCK_CONTROL_LOG_LEVEL); + +struct ambiq_clock_config { + uint32_t clock_freq; + const struct pinctrl_dev_config *pcfg; +}; + +static int ambiq_clock_on(const struct device *dev, clock_control_subsys_t sub_system) +{ + ARG_UNUSED(dev); + + int ret; + uint32_t clock_name = (uint32_t)sub_system; + am_hal_mcuctrl_control_arg_t arg = { + .b_arg_hfxtal_in_use = true, + .b_arg_apply_ext_source = false, + .b_arg_force_update = false, + }; + + if (clock_name >= CLOCK_CONTROL_AMBIQ_TYPE_MAX) { + return -EINVAL; + } + + switch (clock_name) { + case CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_BLE: + arg.ui32_arg_hfxtal_user_mask = BIT(AM_HAL_HFXTAL_BLE_CONTROLLER_EN); + arg.b_arg_enable_HfXtalClockout = true; + ret = am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_EXTCLK32M_KICK_START, &arg); + break; + case CLOCK_CONTROL_AMBIQ_TYPE_LFXTAL: + ret = am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_EXTCLK32K_ENABLE, 0); + default: + ret = -ENOTSUP; + break; + } + + return ret; +} + +static int ambiq_clock_off(const struct device *dev, clock_control_subsys_t sub_system) +{ + ARG_UNUSED(dev); + + int ret; + uint32_t clock_name = (uint32_t)sub_system; + am_hal_mcuctrl_control_arg_t arg = { + .b_arg_hfxtal_in_use = true, + .b_arg_apply_ext_source = false, + .b_arg_force_update = false, + }; + + if (clock_name >= CLOCK_CONTROL_AMBIQ_TYPE_MAX) { + return -EINVAL; + } + + switch (clock_name) { + case CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_BLE: + arg.ui32_arg_hfxtal_user_mask = BIT(AM_HAL_HFXTAL_BLE_CONTROLLER_EN); + arg.b_arg_enable_HfXtalClockout = true; + ret = am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_EXTCLK32M_DISABLE, &arg); + break; + case CLOCK_CONTROL_AMBIQ_TYPE_LFXTAL: + ret = am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_EXTCLK32K_DISABLE, 0); + break; + default: + ret = -ENOTSUP; + break; + } + + return ret; +} + +static inline int ambiq_clock_get_rate(const struct device *dev, clock_control_subsys_t sub_system, + uint32_t *rate) +{ + ARG_UNUSED(sub_system); + + const struct ambiq_clock_config *cfg = dev->config; + *rate = cfg->clock_freq; + + return 0; +} + +static inline int ambiq_clock_configure(const struct device *dev, clock_control_subsys_t sub_system, + void *data) +{ + ARG_UNUSED(sub_system); + ARG_UNUSED(data); + + const struct ambiq_clock_config *cfg = dev->config; + int ret; + + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + + return ret; +} + +static int ambiq_clock_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* Nothing to do.*/ + return 0; +} + +static const struct clock_control_driver_api ambiq_clock_driver_api = { + .on = ambiq_clock_on, + .off = ambiq_clock_off, + .get_rate = ambiq_clock_get_rate, + .configure = ambiq_clock_configure, +}; + +#define AMBIQ_CLOCK_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static const struct ambiq_clock_config ambiq_clock_config##n = { \ + .clock_freq = DT_INST_PROP(n, clock_frequency), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n)}; \ + DEVICE_DT_INST_DEFINE(n, ambiq_clock_init, NULL, NULL, &ambiq_clock_config##n, \ + POST_KERNEL, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, \ + &ambiq_clock_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(AMBIQ_CLOCK_INIT) diff --git a/dts/bindings/clock/ambiq,clkctrl.yaml b/dts/bindings/clock/ambiq,clkctrl.yaml new file mode 100644 index 00000000000..e1b3f9534b3 --- /dev/null +++ b/dts/bindings/clock/ambiq,clkctrl.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2023 Ambiq Micro Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: Ambiq Apollo Series SoC Clock Controller + +compatible: "ambiq,clkctrl" + +include: [clock-controller.yaml, pinctrl-device.yaml, base.yaml] + +properties: + clock-frequency: + type: int + description: output clock frequency (Hz) + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true + + "#clock-cells": + const: 1 diff --git a/include/zephyr/drivers/clock_control/clock_control_ambiq.h b/include/zephyr/drivers/clock_control/clock_control_ambiq.h new file mode 100644 index 00000000000..02ca16b54db --- /dev/null +++ b/include/zephyr/drivers/clock_control/clock_control_ambiq.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_CLOCK_CONTROL_AMBIQ_H_ +#define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_CLOCK_CONTROL_AMBIQ_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Clocks handled by the CLOCK peripheral. + * + * Enum shall be used as a sys argument in clock_control API. + */ +enum clock_control_ambiq_type { + CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_BLE, + CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_USB, + CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_ADC, + CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_AUADC, + CLOCK_CONTROL_AMBIQ_TYPE_HCXTAL_DBGCTRL, + CLOCK_CONTROL_AMBIQ_TYPE_HCXTAL_CLKGEN_MISC, + CLOCK_CONTROL_AMBIQ_TYPE_HCXTAL_CLKGEN_CLKOUT, + CLOCK_CONTROL_AMBIQ_TYPE_HCXTAL_PDM, + CLOCK_CONTROL_AMBIQ_TYPE_HCXTAL_IIS, + CLOCK_CONTROL_AMBIQ_TYPE_HCXTAL_IOM, + CLOCK_CONTROL_AMBIQ_TYPE_LFXTAL, + CLOCK_CONTROL_AMBIQ_TYPE_MAX +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_CLOCK_CONTROL_AMBIQ_H_ */