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