blob: 49354aaed4b5c9f419fbbf0e419a66f4f85ab658 [file] [log] [blame]
Tomasz Bursztyka714dd972015-11-21 21:16:01 -05001/* clock_control.h - public clock controller driver API */
2
3/*
4 * Copyright (c) 2015 Intel Corporation
5 *
David B. Kinderac74d8b2017-01-18 17:01:01 -08006 * SPDX-License-Identifier: Apache-2.0
Tomasz Bursztyka714dd972015-11-21 21:16:01 -05007 */
8
Flavio Ceolin67ca1762018-09-14 10:43:44 -07009#ifndef ZEPHYR_INCLUDE_CLOCK_CONTROL_H_
10#define ZEPHYR_INCLUDE_CLOCK_CONTROL_H_
Tomasz Bursztyka714dd972015-11-21 21:16:01 -050011
Kumar Gala78908162017-04-19 10:32:08 -050012#include <zephyr/types.h>
Tomasz Bursztyka714dd972015-11-21 21:16:01 -050013#include <stddef.h>
14#include <device.h>
Maciek Borzecki14482f02016-03-05 15:08:51 +010015#include <misc/__assert.h>
Krzysztof Chruscinskie0943cf2019-06-07 11:14:52 +020016#include <misc/slist.h>
Tomasz Bursztyka714dd972015-11-21 21:16:01 -050017
18#ifdef __cplusplus
19extern "C" {
20#endif
21
22/* Clock control API */
23
24/* Used to select all subsystem of a clock controller */
25#define CLOCK_CONTROL_SUBSYS_ALL NULL
26
27/**
Krzysztof Chruscinskie0943cf2019-06-07 11:14:52 +020028 * @brief Current clock status.
29 */
30enum clock_control_status {
31 CLOCK_CONTROL_STATUS_STARTING,
32 CLOCK_CONTROL_STATUS_OFF,
33 CLOCK_CONTROL_STATUS_ON,
34 CLOCK_CONTROL_STATUS_UNKNOWN
35};
36
37typedef void (*clock_control_cb_t)(struct device *dev, void *user_data);
38
39/**
40 * @cond INTERNAL_HIDDEN
41 */
42#define Z_CLOCK_CONTROL_ASYNC_DATA_INITIALIZER(_cb, _user_data) \
43 { \
44 .cb = cb, \
45 .user_data = _user_data \
46 }
47/**
48 * INTERNAL_HIDDEN @endcond
49 */
50
51/**
52 * Define and initialize clock_control async data.
53 *
54 * @param name Name of the data.
55 * @param cb Callback.
56 * @param user_data User data
57 */
58#define CLOCK_CONTROL_ASYNC_DATA_DEFINE(name, cb, user_data) \
59 struct clock_control_async_data name = \
60 Z_CLOCK_CONTROL_ASYNC_DATA_INITIALIZER(cb, user_data)
61
62/**
63 * @brief Clock control data used for asynchronous clock enabling.
64 *
65 * @param node Used internally for linking asynchronous requests.
66 * @param cb Callback called when clock is started.
67 * @param user_data User data passed as an argument in the callback.
68 */
69struct clock_control_async_data {
70 sys_snode_t node;
71 clock_control_cb_t cb;
72 void *user_data;
73};
74
75/**
Tomasz Bursztyka714dd972015-11-21 21:16:01 -050076 * clock_control_subsys_t is a type to identify a clock controller sub-system.
77 * Such data pointed is opaque and relevant only to the clock controller
78 * driver instance being used.
79 */
80typedef void *clock_control_subsys_t;
81
82typedef int (*clock_control)(struct device *dev, clock_control_subsys_t sys);
83
Maciek Borzecki14482f02016-03-05 15:08:51 +010084typedef int (*clock_control_get)(struct device *dev,
85 clock_control_subsys_t sys,
Kumar Galacc334c72017-04-21 10:55:34 -050086 u32_t *rate);
Maciek Borzecki14482f02016-03-05 15:08:51 +010087
Krzysztof Chruscinskie0943cf2019-06-07 11:14:52 +020088typedef int (*clock_control_async_on_fn)(struct device *dev,
89 clock_control_subsys_t sys,
90 struct clock_control_async_data *data);
91
92typedef enum clock_control_status (*clock_control_get_status_fn)(
93 struct device *dev,
94 clock_control_subsys_t sys);
95
Tomasz Bursztyka714dd972015-11-21 21:16:01 -050096struct clock_control_driver_api {
Krzysztof Chruscinskie0943cf2019-06-07 11:14:52 +020097 clock_control on;
98 clock_control off;
99 clock_control_async_on_fn async_on;
100 clock_control_get get_rate;
101 clock_control_get_status_fn get_status;
Tomasz Bursztyka714dd972015-11-21 21:16:01 -0500102};
103
104/**
105 * @brief Enable the clock of a sub-system controlled by the device
106 * @param dev Pointer to the device structure for the clock controller driver
107 * instance
108 * @param sys A pointer to an opaque data representing the sub-system
109 */
110static inline int clock_control_on(struct device *dev,
111 clock_control_subsys_t sys)
112{
Benoit Leforestier9915b4e2019-04-25 14:46:55 +0200113 const struct clock_control_driver_api *api =
114 (const struct clock_control_driver_api *)dev->driver_api;
Tomasz Bursztyka714dd972015-11-21 21:16:01 -0500115
Tomasz Bursztyka714dd972015-11-21 21:16:01 -0500116 return api->on(dev, sys);
117}
118
119/**
120 * @brief Disable the clock of a sub-system controlled by the device
121 * @param dev Pointer to the device structure for the clock controller driver
122 * instance
123 * @param sys A pointer to an opaque data representing the sub-system
124 */
125static inline int clock_control_off(struct device *dev,
126 clock_control_subsys_t sys)
127{
Benoit Leforestier9915b4e2019-04-25 14:46:55 +0200128 const struct clock_control_driver_api *api =
129 (const struct clock_control_driver_api *)dev->driver_api;
Tomasz Bursztyka714dd972015-11-21 21:16:01 -0500130
Tomasz Bursztyka714dd972015-11-21 21:16:01 -0500131 return api->off(dev, sys);
132}
133
Maciek Borzecki14482f02016-03-05 15:08:51 +0100134/**
Krzysztof Chruscinskie0943cf2019-06-07 11:14:52 +0200135 * @brief Request clock to start with notification when clock has been started.
136 *
137 * User can request delayed start by providing exact information when clock
138 * should be ready. Driver ensures that clock is ready before requested time.
139 * It is the driver responsibility to take into account clock startup time.
140 * When clock is already running user callback will be called from the context
141 * of the function call else it is called from other context (e.g. clock
142 * interrupt).
143 *
144 * @param dev Device.
145 * @param sys A pointer to an opaque data representing the sub-system.
146 * @param data Data structure containing a callback that is called when
147 * action is performed. Structure content must be valid until
148 * clock is started and user callback is called. Can be NULL.
149 *
150 * @retval 0 if clock is started or already running.
151 * @retval -EBUSY if same request already scheduled and not yet completed.
152 * @retval -ENOTSUP if not supported.
153 */
154static inline int clock_control_async_on(struct device *dev,
155 clock_control_subsys_t sys,
156 struct clock_control_async_data *data)
157{
158 const struct clock_control_driver_api *api =
159 (const struct clock_control_driver_api *)dev->driver_api;
160
161 if (!api->async_on) {
162 return -ENOTSUP;
163 }
164
165 return api->async_on(dev, sys, data);
166}
167
168/**
169 * @brief Get clock status.
170 *
171 * @param dev Device.
172 * @param sys A pointer to an opaque data representing the sub-system.
173 *
174 * @return Status.
175 */
176static inline enum clock_control_status clock_control_get_status(
177 struct device *dev,
178 clock_control_subsys_t sys)
179{
180 const struct clock_control_driver_api *api =
181 (const struct clock_control_driver_api *)dev->driver_api;
182
183 if (!api->get_status) {
184 return CLOCK_CONTROL_STATUS_UNKNOWN;
185 }
186
187 return api->get_status(dev, sys);
188}
189
190/**
Maciek Borzecki14482f02016-03-05 15:08:51 +0100191 * @brief Obtain the clock rate of given sub-system
192 * @param dev Pointer to the device structure for the clock controller driver
193 * instance
194 * @param sys A pointer to an opaque data representing the sub-system
195 * @param[out] rate Subsystem clock rate
196 */
197static inline int clock_control_get_rate(struct device *dev,
198 clock_control_subsys_t sys,
Kumar Galacc334c72017-04-21 10:55:34 -0500199 u32_t *rate)
Maciek Borzecki14482f02016-03-05 15:08:51 +0100200{
Benoit Leforestier9915b4e2019-04-25 14:46:55 +0200201 const struct clock_control_driver_api *api =
202 (const struct clock_control_driver_api *)dev->driver_api;
Maciek Borzecki14482f02016-03-05 15:08:51 +0100203
Flavio Ceolind8837c62018-09-18 12:40:54 -0700204 __ASSERT(api->get_rate != NULL, "%s not implemented for device %s",
Maciek Borzecki14482f02016-03-05 15:08:51 +0100205 __func__, dev->config->name);
206
207 return api->get_rate(dev, sys, rate);
208}
209
Tomasz Bursztyka714dd972015-11-21 21:16:01 -0500210#ifdef __cplusplus
211}
212#endif
213
Flavio Ceolin67ca1762018-09-14 10:43:44 -0700214#endif /* ZEPHYR_INCLUDE_CLOCK_CONTROL_H_ */