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