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