1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * Copyright (c) 2021, Linaro Limited 4 */ 5 6 #ifndef __DRIVERS_RSTCTRL_H 7 #define __DRIVERS_RSTCTRL_H 8 9 #include <kernel/dt.h> 10 #include <kernel/dt_driver.h> 11 #include <stdint.h> 12 #include <tee_api_types.h> 13 14 struct rstctrl; 15 16 struct rstctrl_ops { 17 /* 18 * Operators on reset control(s) exposed by a reset controller 19 * 20 * @assert_level: Assert reset level on control with a timeout hint 21 * @deassert_level: Deassert reset level on control with a timeout hint 22 * @get_name: Get a string name for the controller, or NULL is none 23 * 24 * Operator functions @assert_level and @deassert_level use arguments: 25 * @rstctrl: Reset controller 26 * @id: Identifier for the reset level control in the reset controller 27 * @to_ms: Timeout in microseconds or RSTCTRL_NO_TIMEOUT, may be ignored 28 * by reset controller. 29 * Return a TEE_Result compliant code. 30 */ 31 TEE_Result (*assert_level)(struct rstctrl *rstctrl, unsigned int to_us); 32 TEE_Result (*deassert_level)(struct rstctrl *rstctrl, 33 unsigned int to_us); 34 const char *(*get_name)(struct rstctrl *rstctrl); 35 }; 36 37 /* 38 * struct rstctrl - Instance of a control exposed by a reset controller 39 * @ops: Operators of the reset controller 40 * @exclusive: Set when a consumer has exclusive control on the reset level 41 */ 42 struct rstctrl { 43 const struct rstctrl_ops *ops; 44 bool exclusive; 45 }; 46 47 /** 48 * RSTCTRL_DECLARE - Declare a reset controller driver with a single 49 * device tree compatible string. 50 * 51 * @__name: Reset controller driver name 52 * @__compat: Compatible string 53 * @__probe: Reset controller probe function 54 */ 55 #define RSTCTRL_DT_DECLARE(__name, __compat, __probe) \ 56 static const struct dt_device_match __name ## _match_table[] = { \ 57 { .compatible = __compat }, \ 58 { } \ 59 }; \ 60 DEFINE_DT_DRIVER(__name ## _dt_driver) = { \ 61 .name = # __name, \ 62 .type = DT_DRIVER_RSTCTRL, \ 63 .match_table = __name ## _match_table, \ 64 .probe = __probe, \ 65 } 66 67 /* 68 * Platform driver may ignore the timeout hint according to their 69 * capabilities. RSTCTRL_NO_TIMEOUT specifies no timeout hint. 70 */ 71 #define RSTCTRL_NO_TIMEOUT 0 72 73 /* 74 * rstctrl_assert_to - Assert reset control possibly with timeout 75 * rstctrl_assert - Assert reset control 76 * rstctrl_deassert_to - Deassert reset control possibly with timeout 77 * rstctrl_deassert - Deassert reset control 78 * 79 * @rstctrl: Reset controller 80 * @to_us: Timeout in microseconds 81 * Return a TEE_Result compliant code 82 */ 83 static inline TEE_Result rstctrl_assert_to(struct rstctrl *rstctrl, 84 unsigned int to_us) 85 { 86 return rstctrl->ops->assert_level(rstctrl, to_us); 87 } 88 89 static inline TEE_Result rstctrl_assert(struct rstctrl *rstctrl) 90 { 91 return rstctrl_assert_to(rstctrl, RSTCTRL_NO_TIMEOUT); 92 } 93 94 static inline TEE_Result rstctrl_deassert_to(struct rstctrl *rstctrl, 95 unsigned int to_us) 96 { 97 return rstctrl->ops->deassert_level(rstctrl, to_us); 98 } 99 100 static inline TEE_Result rstctrl_deassert(struct rstctrl *rstctrl) 101 { 102 return rstctrl_deassert_to(rstctrl, RSTCTRL_NO_TIMEOUT); 103 } 104 105 /* 106 * rstctrl_name - Get a name for the reset level control or NULL 107 * 108 * @rstctrl: Reset controller 109 * Return a pointer to controller name or NULL 110 */ 111 static inline const char *rstctrl_name(struct rstctrl *rstctrl) 112 { 113 if (rstctrl->ops->get_name) 114 return rstctrl->ops->get_name(rstctrl); 115 116 return NULL; 117 } 118 119 /** 120 * rstctrl_dt_get_exclusive - Get exclusive access to reset controller 121 * 122 * @rstctrl: Reset controller 123 * Return a TEE_Result compliant value 124 */ 125 TEE_Result rstctrl_get_exclusive(struct rstctrl *rstctrl); 126 127 /** 128 * rstctrl_put_exclusive - Release exclusive access to target 129 * 130 * @rstctrl: Reset controller 131 */ 132 void rstctrl_put_exclusive(struct rstctrl *rstctrl); 133 134 /** 135 * rstctrl_ops_is_valid - Check reset controller ops is valid 136 * 137 * @ops: Reference to reset controller operator instance 138 */ 139 static inline bool rstctrl_ops_is_valid(const struct rstctrl_ops *ops) 140 { 141 return ops && ops->assert_level && ops->deassert_level; 142 } 143 144 #ifdef CFG_DT 145 /** 146 * rstctrl_dt_get_by_index - Get a reset controller at a specific index in 147 * 'resets' property 148 * 149 * @fdt: Device tree to work on 150 * @nodeoffset: Node offset of the subnode containing a 'resets' property 151 * @index: Reset controller index in 'resets' property 152 * @rstctrl: Output reset controller reference upon success 153 * 154 * Return TEE_SUCCESS in case of success 155 * Return TEE_ERROR_DEFER_DRIVER_INIT if reset controller is not initialized 156 * Return TEE_ERROR_ITEM_NOT_FOUND if the resets property does not exist 157 * Return a TEE_Result compliant code in case of error 158 */ 159 static inline TEE_Result rstctrl_dt_get_by_index(const void *fdt, 160 int nodeoffset, 161 unsigned int index, 162 struct rstctrl **rstctrl) 163 { 164 TEE_Result res = TEE_ERROR_GENERIC; 165 166 *rstctrl = dt_driver_device_from_node_idx_prop("resets", fdt, 167 nodeoffset, index, 168 DT_DRIVER_RSTCTRL, &res); 169 return res; 170 } 171 #else 172 static inline TEE_Result rstctrl_dt_get_by_index(const void *fdt __unused, 173 int nodeoffset __unused, 174 unsigned int index __unused, 175 struct rstctrl **rstctrl) 176 { 177 *rstctrl = NULL; 178 return TEE_ERROR_NOT_SUPPORTED; 179 } 180 #endif /*CFG_DT*/ 181 182 /** 183 * rstctrl_dt_get_by_name - Get a reset controller matching a name in the 184 * 'reset-names' property 185 * 186 * @fdt: Device tree to work on 187 * @nodeoffset: Node offset of the subnode containing a 'resets' property 188 * @name: Reset controller name to get 189 * @rstctrl: Output reset controller reference upon success 190 * 191 * Return TEE_SUCCESS in case of success 192 * Return TEE_ERROR_DEFER_DRIVER_INIT if reset controller is not initialized 193 * Return TEE_ERROR_ITEM_NOT_FOUND if the reset-names property does not exist 194 * Return a TEE_Result compliant code in case of error 195 */ 196 TEE_Result rstctrl_dt_get_by_name(const void *fdt, int nodeoffset, 197 const char *name, struct rstctrl **rstctrl); 198 199 /** 200 * rstctrl_dt_get_func - Typedef of function to get reset controller from 201 * devicetree properties 202 * 203 * @a: Pointer to devicetree description of the reset controller to parse 204 * @data: Pointer to data given at rstctrl_dt_register_provider() call 205 * @res: Output result code of the operation: 206 * TEE_SUCCESS in case of success 207 * TEE_ERROR_DEFER_DRIVER_INIT if reset controller is not initialized 208 * Any TEE_Result compliant code in case of error. 209 * 210 * Returns a struct rstctrl pointer pointing to a reset controller matching 211 * the devicetree description or NULL if invalid description in which case 212 * @res provides the error code. 213 */ 214 typedef struct rstctrl *(*rstctrl_dt_get_func)(struct dt_driver_phandle_args *a, 215 void *data, TEE_Result *res); 216 217 /** 218 * rstctrl_dt_register_provider - Register a reset controller provider 219 * 220 * @fdt: Device tree to work on 221 * @nodeoffset: Node offset of the reset controller 222 * @get_dt_rstctrl: Callback to match the reset controller with a struct rstctrl 223 * @data: Data which will be passed to the get_dt_rstctrl callback 224 * Returns TEE_Result value 225 */ 226 static inline 227 TEE_Result rstctrl_register_provider(const void *fdt, int nodeoffset, 228 rstctrl_dt_get_func get_dt_rstctrl, 229 void *data) 230 { 231 return dt_driver_register_provider(fdt, nodeoffset, 232 (get_of_device_func)get_dt_rstctrl, 233 data, DT_DRIVER_RSTCTRL); 234 } 235 #endif /* __DRIVERS_RSTCTRL_H */ 236 237