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