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 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 a TEE_Result compliant code in case of error 193 */ 194 TEE_Result rstctrl_dt_get_by_name(const void *fdt, int nodeoffset, 195 const char *name, struct rstctrl **rstctrl); 196 197 /** 198 * rstctrl_dt_get_func - Typedef of function to get reset controller from 199 * devicetree properties 200 * 201 * @a: Pointer to devicetree description of the reset controller to parse 202 * @data: Pointer to data given at rstctrl_dt_register_provider() call 203 * @res: Output result code of the operation: 204 * TEE_SUCCESS in case of success 205 * TEE_ERROR_DEFER_DRIVER_INIT if reset controller is not initialized 206 * Any TEE_Result compliant code in case of error. 207 * 208 * Returns a struct rstctrl pointer pointing to a reset controller matching 209 * the devicetree description or NULL if invalid description in which case 210 * @res provides the error code. 211 */ 212 typedef struct rstctrl *(*rstctrl_dt_get_func)(struct dt_driver_phandle_args *a, 213 void *data, TEE_Result *res); 214 215 /** 216 * rstctrl_dt_register_provider - Register a reset controller provider 217 * 218 * @fdt: Device tree to work on 219 * @nodeoffset: Node offset of the reset controller 220 * @get_dt_rstctrl: Callback to match the reset controller with a struct rstctrl 221 * @data: Data which will be passed to the get_dt_rstctrl callback 222 * Returns TEE_Result value 223 */ 224 static inline 225 TEE_Result rstctrl_register_provider(const void *fdt, int nodeoffset, 226 rstctrl_dt_get_func get_dt_rstctrl, 227 void *data) 228 { 229 return dt_driver_register_provider(fdt, nodeoffset, 230 (get_of_device_func)get_dt_rstctrl, 231 data, DT_DRIVER_RSTCTRL); 232 } 233 #endif /* __DRIVERS_RSTCTRL_H */ 234 235