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