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