1 /*
2 * Copyright (c) 2021 Carlo Caione <ccaione@baylibre.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @ingroup syscon_interface
10 * @brief Main header file for SYSCON (System Control) driver API.
11 */
12
13 #ifndef ZEPHYR_INCLUDE_DRIVERS_SYSCON_H_
14 #define ZEPHYR_INCLUDE_DRIVERS_SYSCON_H_
15
16 /**
17 * @brief Interfaces for system control registers.
18 * @defgroup syscon_interface System control (SYSCON)
19 * @ingroup io_interfaces
20 * @{
21 */
22
23 #include <errno.h>
24
25 #include <zephyr/types.h>
26 #include <zephyr/device.h>
27
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31
32 /**
33 * API template to get the base address of the syscon region.
34 *
35 * @see syscon_get_base
36 */
37 typedef int (*syscon_api_get_base)(const struct device *dev, uintptr_t *addr);
38
39 /**
40 * API template to read a single register.
41 *
42 * @see syscon_read_reg
43 */
44 typedef int (*syscon_api_read_reg)(const struct device *dev, uint16_t reg, uint32_t *val);
45
46 /**
47 * API template to write a single register.
48 *
49 * @see syscon_write_reg
50 */
51 typedef int (*syscon_api_write_reg)(const struct device *dev, uint16_t reg, uint32_t val);
52
53 /**
54 * API template to get the size of the syscon register.
55 *
56 * @see syscon_get_size
57 */
58 typedef int (*syscon_api_get_size)(const struct device *dev, size_t *size);
59
60 /**
61 * @brief System Control (syscon) register driver API
62 */
63 __subsystem struct syscon_driver_api {
64 syscon_api_read_reg read;
65 syscon_api_write_reg write;
66 syscon_api_get_base get_base;
67 syscon_api_get_size get_size;
68 };
69
70 /**
71 * @brief Get the syscon base address
72 *
73 * @param dev The device to get the register size for.
74 * @param addr Where to write the base address.
75 *
76 * @retval 0 When @a addr was written to.
77 * @retval -ENOSYS If the API or function isn't implemented.
78 */
79 __syscall int syscon_get_base(const struct device *dev, uintptr_t *addr);
80
z_impl_syscon_get_base(const struct device * dev,uintptr_t * addr)81 static inline int z_impl_syscon_get_base(const struct device *dev, uintptr_t *addr)
82 {
83 const struct syscon_driver_api *api = (const struct syscon_driver_api *)dev->api;
84
85 if ((api == NULL) || (api->get_base == NULL)) {
86 return -ENOSYS;
87 }
88
89 return api->get_base(dev, addr);
90 }
91
92
93 /**
94 * @brief Read from syscon register
95 *
96 * This function reads from a specific register in the syscon area
97 *
98 * @param dev The device to get the register size for.
99 * @param reg The register offset
100 * @param val The returned value read from the syscon register
101 *
102 * @retval 0 on success.
103 * @retval -ENOSYS If the API or function isn't implemented.
104 */
105 __syscall int syscon_read_reg(const struct device *dev, uint16_t reg, uint32_t *val);
106
z_impl_syscon_read_reg(const struct device * dev,uint16_t reg,uint32_t * val)107 static inline int z_impl_syscon_read_reg(const struct device *dev, uint16_t reg, uint32_t *val)
108 {
109 const struct syscon_driver_api *api = (const struct syscon_driver_api *)dev->api;
110
111 if ((api == NULL) || (api->read == NULL)) {
112 return -ENOSYS;
113 }
114
115 return api->read(dev, reg, val);
116 }
117
118
119 /**
120 * @brief Write to syscon register
121 *
122 * This function writes to a specific register in the syscon area
123 *
124 * @param dev The device to get the register size for.
125 * @param reg The register offset
126 * @param val The value to be written in the register
127 *
128 * @retval 0 on success.
129 * @retval -ENOSYS If the API or function isn't implemented.
130 */
131 __syscall int syscon_write_reg(const struct device *dev, uint16_t reg, uint32_t val);
132
z_impl_syscon_write_reg(const struct device * dev,uint16_t reg,uint32_t val)133 static inline int z_impl_syscon_write_reg(const struct device *dev, uint16_t reg, uint32_t val)
134 {
135 const struct syscon_driver_api *api = (const struct syscon_driver_api *)dev->api;
136
137 if ((api == NULL) || (api->write == NULL)) {
138 return -ENOSYS;
139 }
140
141 return api->write(dev, reg, val);
142 }
143
144 /**
145 * Get the size of the syscon register in bytes.
146 *
147 * @param dev The device to get the register size for.
148 * @param size Pointer to write the size to.
149 *
150 * @retval 0 on success.
151 * @retval -ENOSYS If the API or function isn't implemented.
152 */
153 __syscall int syscon_get_size(const struct device *dev, size_t *size);
154
z_impl_syscon_get_size(const struct device * dev,size_t * size)155 static inline int z_impl_syscon_get_size(const struct device *dev, size_t *size)
156 {
157 const struct syscon_driver_api *api = (const struct syscon_driver_api *)dev->api;
158
159 if ((api == NULL) || (api->get_size == NULL)) {
160 return -ENOSYS;
161 }
162
163 return api->get_size(dev, size);
164 }
165
166 /**
167 * @}
168 */
169
170 #ifdef __cplusplus
171 }
172 #endif
173
174 #include <zephyr/syscalls/syscon.h>
175
176 #endif /* ZEPHYR_INCLUDE_DRIVERS_SYSCON_H_ */
177