blob: 77fdcbad6bda157bc168b6f5d1e55a903cdcc416 [file] [log] [blame]
Aaron Ye67225442023-11-04 08:26:51 +08001/*
2 * Copyright 2023 Ambiq Micro Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#define DT_DRV_COMPAT ambiq_clkctrl
8
9#include <errno.h>
10#include <zephyr/init.h>
11#include <zephyr/drivers/clock_control.h>
12#include <zephyr/drivers/pinctrl.h>
13#include <zephyr/drivers/clock_control/clock_control_ambiq.h>
14#include <am_mcu_apollo.h>
15
16#include <zephyr/logging/log.h>
17LOG_MODULE_REGISTER(clock_control_ambiq, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
18
19struct ambiq_clock_config {
20 uint32_t clock_freq;
21 const struct pinctrl_dev_config *pcfg;
22};
23
24static int ambiq_clock_on(const struct device *dev, clock_control_subsys_t sub_system)
25{
26 ARG_UNUSED(dev);
27
28 int ret;
29 uint32_t clock_name = (uint32_t)sub_system;
30 am_hal_mcuctrl_control_arg_t arg = {
31 .b_arg_hfxtal_in_use = true,
32 .b_arg_apply_ext_source = false,
33 .b_arg_force_update = false,
34 };
35
36 if (clock_name >= CLOCK_CONTROL_AMBIQ_TYPE_MAX) {
37 return -EINVAL;
38 }
39
40 switch (clock_name) {
41 case CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_BLE:
42 arg.ui32_arg_hfxtal_user_mask = BIT(AM_HAL_HFXTAL_BLE_CONTROLLER_EN);
43 arg.b_arg_enable_HfXtalClockout = true;
44 ret = am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_EXTCLK32M_KICK_START, &arg);
45 break;
46 case CLOCK_CONTROL_AMBIQ_TYPE_LFXTAL:
47 ret = am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_EXTCLK32K_ENABLE, 0);
48 default:
49 ret = -ENOTSUP;
50 break;
51 }
52
53 return ret;
54}
55
56static int ambiq_clock_off(const struct device *dev, clock_control_subsys_t sub_system)
57{
58 ARG_UNUSED(dev);
59
60 int ret;
61 uint32_t clock_name = (uint32_t)sub_system;
62 am_hal_mcuctrl_control_arg_t arg = {
63 .b_arg_hfxtal_in_use = true,
64 .b_arg_apply_ext_source = false,
65 .b_arg_force_update = false,
66 };
67
68 if (clock_name >= CLOCK_CONTROL_AMBIQ_TYPE_MAX) {
69 return -EINVAL;
70 }
71
72 switch (clock_name) {
73 case CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_BLE:
74 arg.ui32_arg_hfxtal_user_mask = BIT(AM_HAL_HFXTAL_BLE_CONTROLLER_EN);
75 arg.b_arg_enable_HfXtalClockout = true;
76 ret = am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_EXTCLK32M_DISABLE, &arg);
77 break;
78 case CLOCK_CONTROL_AMBIQ_TYPE_LFXTAL:
79 ret = am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_EXTCLK32K_DISABLE, 0);
80 break;
81 default:
82 ret = -ENOTSUP;
83 break;
84 }
85
86 return ret;
87}
88
89static inline int ambiq_clock_get_rate(const struct device *dev, clock_control_subsys_t sub_system,
90 uint32_t *rate)
91{
92 ARG_UNUSED(sub_system);
93
94 const struct ambiq_clock_config *cfg = dev->config;
95 *rate = cfg->clock_freq;
96
97 return 0;
98}
99
100static inline int ambiq_clock_configure(const struct device *dev, clock_control_subsys_t sub_system,
101 void *data)
102{
103 ARG_UNUSED(sub_system);
104 ARG_UNUSED(data);
105
106 const struct ambiq_clock_config *cfg = dev->config;
107 int ret;
108
109 ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
110
111 return ret;
112}
113
114static int ambiq_clock_init(const struct device *dev)
115{
116 ARG_UNUSED(dev);
117
118 /* Nothing to do.*/
119 return 0;
120}
121
Pieter De Gendtc25e3152024-11-27 17:20:44 +0100122static DEVICE_API(clock_control, ambiq_clock_driver_api) = {
Aaron Ye67225442023-11-04 08:26:51 +0800123 .on = ambiq_clock_on,
124 .off = ambiq_clock_off,
125 .get_rate = ambiq_clock_get_rate,
126 .configure = ambiq_clock_configure,
127};
128
129#define AMBIQ_CLOCK_INIT(n) \
130 PINCTRL_DT_INST_DEFINE(n); \
131 static const struct ambiq_clock_config ambiq_clock_config##n = { \
132 .clock_freq = DT_INST_PROP(n, clock_frequency), \
133 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n)}; \
134 DEVICE_DT_INST_DEFINE(n, ambiq_clock_init, NULL, NULL, &ambiq_clock_config##n, \
135 POST_KERNEL, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, \
136 &ambiq_clock_driver_api);
137
138DT_INST_FOREACH_STATUS_OKAY(AMBIQ_CLOCK_INIT)