1
2 /*
3 * Copyright (c) 2015 Intel Corporation.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #ifndef _DEVICE_H_
9 #define _DEVICE_H_
10
11 //#include <kernel.h>
12
13 /**
14 * @brief Device Driver APIs
15 * @defgroup io_interfaces Device Driver APIs
16 * @{
17 * @}
18 */
19 /**
20 * @brief Device Model APIs
21 * @defgroup device_model Device Model APIs
22 * @{
23 */
24
25 #include <ble_types/types.h>
26 // #include <common.h>
27
28
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32
33 #define CONFIG_CLOCK_CONTROL_NRF5_K32SRC_DRV_NAME "nrf5k32srcclockcontrol"
34
35 #define CONFIG_CLOCK_CONTROL_NRF5_M16SRC_DRV_NAME "nrf5m16srcclockcontrol"
36
37
38 static const int _INIT_LEVEL_PRE_KERNEL_1 = 1;
39 static const int _INIT_LEVEL_PRE_KERNEL_2 = 1;
40 static const int _INIT_LEVEL_POST_KERNEL = 1;
41 static const int _INIT_LEVEL_APPLICATION = 1;
42
43
44 /**
45 * @brief Runtime device structure (In memory) Per driver instance
46 * @param device_config Build time config information
47 * @param driver_api pointer to structure containing the API functions for
48 * the device type. This pointer is filled in by the driver at init time.
49 * @param driver_data driver instance data. For driver use only
50 */
51 struct device {
52 struct device_config *config;
53 const void *driver_api;
54 void *driver_data;
55 };
56
57
58 /**
59 * @brief Static device information (In ROM) Per driver instance
60 *
61 * @param name name of the device
62 * @param init init function for the driver
63 * @param config_info address of driver instance config information
64 */
65 struct device_config {
66 char *name;
67 int (*init)(struct device *device);
68 #ifdef CONFIG_DEVICE_POWER_MANAGEMENT
69 int (*device_pm_control)(struct device *device, bt_u32_t command,
70 void *context);
71 #endif
72 const void *config_info;
73 };
74
75
76 /**
77 * @def DEVICE_INIT
78 *
79 * @brief Create device object and set it up for boot time initialization.
80 *
81 * @details This macro defines a device object that is automatically
82 * configured by the kernel during system initialization.
83 *
84 * @param dev_name Device name.
85 *
86 * @param drv_name The name this instance of the driver exposes to
87 * the system.
88 *
89 * @param init_fn Address to the init function of the driver.
90 *
91 * @param data Pointer to the device's configuration data.
92 *
93 * @param cfg_info The address to the structure containing the
94 * configuration information for this instance of the driver.
95 *
96 * @param level The initialization level at which configuration occurs.
97 * Must be one of the following symbols, which are listed in the order
98 * they are performed by the kernel:
99 * \n
100 * \li PRE_KERNEL_1: Used for devices that have no dependencies, such as those
101 * that rely solely on hardware present in the processor/SOC. These devices
102 * cannot use any kernel services during configuration, since they are not
103 * yet available.
104 * \n
105 * \li PRE_KERNEL_2: Used for devices that rely on the initialization of devices
106 * initialized as part of the PRIMARY level. These devices cannot use any
107 * kernel services during configuration, since they are not yet available.
108 * \n
109 * \li POST_KERNEL: Used for devices that require kernel services during
110 * configuration.
111 * \n
112 * \li APPLICATION: Used for application components (i.e. non-kernel components)
113 * that need automatic configuration. These devices can use all services
114 * provided by the kernel during configuration.
115 *
116 * @param prio The initialization priority of the device, relative to
117 * other devices of the same initialization level. Specified as an integer
118 * value in the range 0 to 99; lower values indicate earlier initialization.
119 * Must be a decimal integer literal without leading zeroes or sign (e.g. 32),
120 * or an equivalent symbolic name (e.g. \#define MY_INIT_PRIO 32); symbolic
121 * expressions are *not* permitted
122 * (e.g. CONFIG_KERNEL_INIT_PRIORITY_DEFAULT + 5).
123 */
124
125 /**
126 * @def DEVICE_AND_API_INIT
127 *
128 * @brief Create device object and set it up for boot time initialization,
129 * with the option to set driver_api.
130 *
131 * @copydetails DEVICE_INIT
132 * @param api Provides an initial pointer to the API function struct
133 * used by the driver. Can be NULL.
134 * @details The driver api is also set here, eliminating the need to do that
135 * during initialization.
136 */
137
138 #define _DO_CONCAT(x, y) x ## y
139 #define _CONCAT(x, y) _DO_CONCAT(x, y)
140
141 #define _STRINGIFY(x) #x
142 #define STRINGIFY(s) _STRINGIFY(s)
143
144
145
146 #ifndef CONFIG_DEVICE_POWER_MANAGEMENT
147 #define DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, data, cfg_info, \
148 level, prio, api) \
149 \
150 static struct device_config _CONCAT(__config_, dev_name) __used \
151 __attribute__((__section__(".devconfig.init"))) = { \
152 .name = drv_name, .init = (init_fn), \
153 .config_info = (cfg_info) \
154 }; \
155 static struct device _CONCAT(__device_, dev_name) __used \
156 __attribute__((__section__(".init_" #level STRINGIFY(prio)))) = { \
157 .config = &_CONCAT(__config_, dev_name), \
158 .driver_api = api, \
159 .driver_data = data \
160 }
161
162
163 #define DEVICE_DEFINE(dev_name, drv_name, init_fn, pm_control_fn, \
164 data, cfg_info, level, prio, api) \
165 DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, data, cfg_info, \
166 level, prio, api)
167 #else
168
169 /**
170 * @def DEVICE_DEFINE
171 *
172 * @brief Create device object and set it up for boot time initialization,
173 * with the option to device_pm_control.
174 *
175 * @copydetails DEVICE_AND_API_INIT
176 * @param pm_control_fn Pointer to device_pm_control function.
177 * Can be empty function (device_pm_control_nop) if not implemented.
178 */
179 #define DEVICE_DEFINE(dev_name, drv_name, init_fn, pm_control_fn, \
180 data, cfg_info, level, prio, api) \
181 \
182 static struct device_config _CONCAT(__config_, dev_name) __used \
183 __attribute__((__section__(".devconfig.init"))) = { \
184 .name = drv_name, .init = (init_fn), \
185 .device_pm_control = (pm_control_fn), \
186 .config_info = (cfg_info) \
187 }; \
188 static struct device _CONCAT(__device_, dev_name) __used \
189 __attribute__((__section__(".init_" #level STRINGIFY(prio)))) = { \
190 .config = &_CONCAT(__config_, dev_name), \
191 .driver_api = api, \
192 .driver_data = data \
193 }
194 /*
195 * Use the default device_pm_control for devices that do not call the
196 * DEVICE_DEFINE macro so that caller of hook functions
197 * need not check device_pm_control != NULL.
198 */
199 #define DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, data, cfg_info, \
200 level, prio, api) \
201 DEVICE_DEFINE(dev_name, drv_name, init_fn, \
202 device_pm_control_nop, data, cfg_info, level, \
203 prio, api)
204 #endif
205
206 #define DEVICE_INIT(dev_name, drv_name, init_fn, data, cfg_info, level, prio) \
207 DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, data, cfg_info, \
208 level, prio, NULL)
209
210 /**
211 * @def DEVICE_NAME_GET
212 *
213 * @brief Expands to the full name of a global device object
214 *
215 * @details Return the full name of a device object symbol created by
216 * DEVICE_INIT(), using the dev_name provided to DEVICE_INIT().
217 *
218 * It is meant to be used for declaring extern symbols pointing on device
219 * objects before using the DEVICE_GET macro to get the device object.
220 *
221 * @param name The same as dev_name provided to DEVICE_INIT()
222 *
223 * @return The expanded name of the device object created by DEVICE_INIT()
224 */
225 #define DEVICE_NAME_GET(name) (_CONCAT(__device_, name))
226
227 /**
228 * @def DEVICE_GET
229 *
230 * @brief Obtain a pointer to a device object by name
231 *
232 * @details Return the address of a device object created by
233 * DEVICE_INIT(), using the dev_name provided to DEVICE_INIT().
234 *
235 * @param name The same as dev_name provided to DEVICE_INIT()
236 *
237 * @return A pointer to the device object created by DEVICE_INIT()
238 */
239 #define DEVICE_GET(name) (&DEVICE_NAME_GET(name))
240
241 /** @def DEVICE_DECLARE
242 *
243 * @brief Declare a static device object
244 *
245 * This macro can be used at the top-level to declare a device, such
246 * that DEVICE_GET() may be used before the full declaration in
247 * DEVICE_INIT().
248 *
249 * This is often useful when configuring interrupts statically in a
250 * device's init or per-instance config function, as the init function
251 * itself is required by DEVICE_INIT() and use of DEVICE_GET()
252 * inside it creates a circular dependency.
253 *
254 * @param name Device name
255 */
256 #define DEVICE_DECLARE(name) static struct device DEVICE_NAME_GET(name)
257
258 struct device;
259
260 #ifdef CONFIG_DEVICE_POWER_MANAGEMENT
261 /**
262 * @brief Device Power Management APIs
263 * @defgroup device_power_management_api Device Power Management APIs
264 * @ingroup power_management_api
265 * @{
266 */
267
268 /**
269 * @}
270 */
271
272 /** @def DEVICE_PM_ACTIVE_STATE
273 *
274 * @brief device is in ACTIVE power state
275 *
276 * @details Normal operation of the device. All device context is retained.
277 */
278 #define DEVICE_PM_ACTIVE_STATE 1
279
280 /** @def DEVICE_PM_LOW_POWER_STATE
281 *
282 * @brief device is in LOW power state
283 *
284 * @details Device context is preserved by the HW and need not be
285 * restored by the driver.
286 */
287 #define DEVICE_PM_LOW_POWER_STATE 2
288
289 /** @def DEVICE_PM_SUSPEND_STATE
290 *
291 * @brief device is in SUSPEND power state
292 *
293 * @details Most device context is lost by the hardware.
294 * Device drivers must save and restore or reinitialize any context
295 * lost by the hardware
296 */
297 #define DEVICE_PM_SUSPEND_STATE 3
298
299 /** @def DEVICE_PM_OFF_STATE
300 *
301 * @brief device is in OFF power state
302 *
303 * @details - Power has been fully removed from the device.
304 * The device context is lost when this state is entered, so the OS
305 * software will reinitialize the device when powering it back on
306 */
307 #define DEVICE_PM_OFF_STATE 4
308
309 /* Constants defining support device power commands */
310 #define DEVICE_PM_SET_POWER_STATE 1
311 #define DEVICE_PM_GET_POWER_STATE 2
312 #endif
313
314
315 void _sys_device_do_config_level(int level);
316
317 /**
318 * @brief Retrieve the device structure for a driver by name
319 *
320 * @details Device objects are created via the DEVICE_INIT() macro and
321 * placed in memory by the linker. If a driver needs to bind to another driver
322 * it can use this function to retrieve the device structure of the lower level
323 * driver by the name the driver exposes to the system.
324 *
325 * @param name device name to search for.
326 *
327 * @return pointer to device structure; NULL if not found or cannot be used.
328 */
329 struct device *device_get_binding(const char *name);
330
331 /**
332 * @brief Device Power Management APIs
333 * @defgroup device_power_management_api Device Power Management APIs
334 * @ingroup power_management_api
335 * @{
336 */
337
338 /**
339 * @brief Indicate that the device is in the middle of a transaction
340 *
341 * Called by a device driver to indicate that it is in the middle of a
342 * transaction.
343 *
344 * @param busy_dev Pointer to device structure of the driver instance.
345 */
346 void device_busy_set(struct device *busy_dev);
347
348 /**
349 * @brief Indicate that the device has completed its transaction
350 *
351 * Called by a device driver to indicate the end of a transaction.
352 *
353 * @param busy_dev Pointer to device structure of the driver instance.
354 */
355 void device_busy_clear(struct device *busy_dev);
356
357 #ifdef CONFIG_DEVICE_POWER_MANAGEMENT
358 /*
359 * Device PM functions
360 */
361
362 /**
363 * @brief No-op function to initialize unimplemented hook
364 *
365 * This function should be used to initialize device hook
366 * for which a device has no PM operations.
367 *
368 * @param unused_device Unused
369 * @param unused_ctrl_command Unused
370 * @param unused_context Unused
371 *
372 * @retval 0 Always returns 0
373 */
374 int device_pm_control_nop(struct device *unused_device,
375 bt_u32_t unused_ctrl_command, void *unused_context);
376 /**
377 * @brief Call the set power state function of a device
378 *
379 * Called by the application or power management service to let the device do
380 * required operations when moving to the required power state
381 * Note that devices may support just some of the device power states
382 * @param device Pointer to device structure of the driver instance.
383 * @param device_power_state Device power state to be set
384 *
385 * @retval 0 If successful.
386 * @retval Errno Negative errno code if failure.
387 */
device_set_power_state(struct device * device,bt_u32_t device_power_state)388 static inline int device_set_power_state(struct device *device,
389 bt_u32_t device_power_state)
390 {
391 return device->config->device_pm_control(device,
392 DEVICE_PM_SET_POWER_STATE, &device_power_state);
393 }
394
395 /**
396 * @brief Call the get power state function of a device
397 *
398 * This function lets the caller know the current device
399 * power state at any time. This state will be one of the defined
400 * power states allowed for the devices in that system
401 *
402 * @param device pointer to device structure of the driver instance.
403 * @param device_power_state Device power state to be filled by the device
404 *
405 * @retval 0 If successful.
406 * @retval Errno Negative errno code if failure.
407 */
device_get_power_state(struct device * device,bt_u32_t * device_power_state)408 static inline int device_get_power_state(struct device *device,
409 bt_u32_t *device_power_state)
410 {
411 return device->config->device_pm_control(device,
412 DEVICE_PM_GET_POWER_STATE, device_power_state);
413 }
414
415 /**
416 * @brief Gets the device structure list array and device count
417 *
418 * Called by the Power Manager application to get the list of
419 * device structures associated with the devices in the system.
420 * The PM app would use this list to create its own sorted list
421 * based on the order it wishes to suspend or resume the devices.
422 *
423 * @param device_list Pointer to receive the device list array
424 * @param device_count Pointer to receive the device count
425 */
426 void device_list_get(struct device **device_list, int *device_count);
427
428 /**
429 * @brief Check if any device is in the middle of a transaction
430 *
431 * Called by an application to see if any device is in the middle
432 * of a critical transaction that cannot be interrupted.
433 *
434 * @retval 0 if no device is busy
435 * @retval -EBUSY if any device is busy
436 */
437 int device_any_busy_check(void);
438
439 /**
440 * @brief Check if a specific device is in the middle of a transaction
441 *
442 * Called by an application to see if a particular device is in the
443 * middle of a critical transaction that cannot be interrupted.
444 *
445 * @param chk_dev Pointer to device structure of the specific device driver
446 * the caller is interested in.
447 * @retval 0 if the device is not busy
448 * @retval -EBUSY if the device is busy
449 */
450 int device_busy_check(struct device *chk_dev);
451
452 #endif
453
454 /**
455 * @}
456 */
457
458 #ifdef __cplusplus
459 }
460 #endif
461 /**
462 * @}
463 */
464 #endif /* _DEVICE_H_ */
465