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_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 **out_rstctrl) 162 { 163 TEE_Result res = TEE_ERROR_GENERIC; 164 void *rstctrl = NULL; 165 166 res = dt_driver_device_from_node_idx_prop("resets", fdt, nodeoffset, 167 index, DT_DRIVER_RSTCTRL, 168 &rstctrl); 169 if (!res) 170 *out_rstctrl = rstctrl; 171 172 return res; 173 } 174 #else 175 static inline TEE_Result rstctrl_dt_get_by_index(const void *fdt __unused, 176 int nodeoffset __unused, 177 unsigned int index __unused, 178 struct rstctrl **ctrl __unused) 179 { 180 return TEE_ERROR_NOT_SUPPORTED; 181 } 182 #endif /*CFG_DT*/ 183 184 /** 185 * rstctrl_dt_get_by_name() - Get a reset controller matching a name in the 186 * 'reset-names' property 187 * 188 * @fdt: Device tree to work on 189 * @nodeoffset: Node offset of the subnode containing a 'resets' property 190 * @name: Reset controller name to get 191 * @rstctrl: Output reset controller reference upon success 192 * 193 * Return TEE_SUCCESS in case of success 194 * Return TEE_ERROR_DEFER_DRIVER_INIT if reset controller is not initialized 195 * Return TEE_ERROR_ITEM_NOT_FOUND if the reset-names property does not exist 196 * Return a TEE_Result compliant code in case of error 197 */ 198 TEE_Result rstctrl_dt_get_by_name(const void *fdt, int nodeoffset, 199 const char *name, struct rstctrl **rstctrl); 200 201 /** 202 * rstctrl_dt_get_func - Typedef of function to get reset controller from 203 * devicetree properties 204 * 205 * @args: Pointer to devicetree description of the reset controller to parse 206 * @data: Pointer to data given at rstctrl_register_provider() call 207 * @rstctrl: Output reset controller reference upon success 208 */ 209 typedef TEE_Result (*rstctrl_dt_get_func)(struct dt_pargs *args, void *data, 210 struct rstctrl **out_rstctrl); 211 212 /** 213 * rstctrl_register_provider() - Register a reset controller provider 214 * 215 * @fdt: Device tree to work on 216 * @nodeoffset: Node offset of the reset controller 217 * @func: Callback to match the reset controller with a struct rstctrl 218 * @data: Data which will be passed to the get_dt_rstctrl callback 219 * Returns TEE_Result value 220 */ 221 static inline TEE_Result rstctrl_register_provider(const void *fdt, 222 int nodeoffset, 223 rstctrl_dt_get_func func, 224 void *data) 225 { 226 return dt_driver_register_provider(fdt, nodeoffset, 227 (get_of_device_func)func, data, 228 DT_DRIVER_RSTCTRL); 229 } 230 #endif /* __DRIVERS_RSTCTRL_H */ 231