1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2023, Microchip 4 */ 5 6 #include <assert.h> 7 #include <drivers/pinctrl.h> 8 #include <libfdt.h> 9 #include <stdio.h> 10 #include <tee_api_defines.h> 11 #include <tee_api_defines_extensions.h> 12 #include <tee_api_types.h> 13 #include <util.h> 14 15 static const char * const pin_modes[PINCTRL_DT_PROP_MAX] = { 16 [PINCTRL_DT_PROP_BIAS_DISABLE] = "bias-disable", 17 [PINCTRL_DT_PROP_BIAS_PULL_UP] = "bias-pull-up", 18 [PINCTRL_DT_PROP_BIAS_PULL_DOWN] = "bias-pull-down", 19 }; 20 21 TEE_Result pinctrl_parse_dt_pin_modes(const void *fdt, int node, 22 bitstr_t **modes) 23 { 24 unsigned int i = 0; 25 bitstr_t *modes_ptr = NULL; 26 27 modes_ptr = bit_alloc(PINCTRL_DT_PROP_MAX); 28 if (!modes_ptr) 29 return TEE_ERROR_OUT_OF_MEMORY; 30 31 for (i = 0; i < ARRAY_SIZE(pin_modes); i++) 32 if (fdt_getprop(fdt, node, pin_modes[i], NULL)) 33 bit_set(modes_ptr, i); 34 35 *modes = modes_ptr; 36 37 return TEE_SUCCESS; 38 } 39 40 TEE_Result pinctrl_apply_state(struct pinctrl_state *state) 41 { 42 unsigned int i = 0; 43 struct pinconf *conf = NULL; 44 TEE_Result res = TEE_ERROR_GENERIC; 45 46 for (i = 0; i < state->conf_count; i++) { 47 conf = state->confs[i]; 48 49 res = conf->ops->conf_apply(conf); 50 if (res) { 51 EMSG("Failed to apply pin conf"); 52 return res; 53 } 54 } 55 56 return TEE_SUCCESS; 57 } 58 59 void pinctrl_free_state(struct pinctrl_state *state) 60 { 61 unsigned int i = 0; 62 63 for (i = 0; i < state->conf_count; i++) 64 state->confs[i]->ops->conf_free(state->confs[i]); 65 66 free(state); 67 } 68 69 TEE_Result pinctrl_get_state_by_idx(const void *fdt, int nodeoffset, 70 unsigned int pinctrl_index, 71 struct pinctrl_state **state_ret) 72 { 73 int bw = 0; 74 unsigned int conf_id = 0; 75 const uint32_t *prop = NULL; 76 unsigned int conf_count = 0; 77 /* Enough char to hold "pinctrl-<max_int>" */ 78 char prop_name[8 + 20 + 1] = { }; 79 struct pinctrl_state *state = NULL; 80 TEE_Result res = TEE_ERROR_GENERIC; 81 82 bw = snprintf(prop_name, sizeof(prop_name), "pinctrl-%d", 83 pinctrl_index); 84 if (bw >= (int)sizeof(prop_name)) 85 return TEE_ERROR_OVERFLOW; 86 87 prop = fdt_getprop(fdt, nodeoffset, prop_name, (int *)&conf_count); 88 if (!prop) 89 return TEE_ERROR_ITEM_NOT_FOUND; 90 91 conf_count /= sizeof(uint32_t); 92 state = calloc(1, sizeof(struct pinctrl_state) + 93 conf_count * sizeof(struct pinconf *)); 94 if (!state) 95 return TEE_ERROR_OUT_OF_MEMORY; 96 97 state->conf_count = conf_count; 98 for (conf_id = 0; conf_id < conf_count; conf_id++) { 99 void *pinconf = NULL; 100 101 res = dt_driver_device_from_node_idx_prop(prop_name, fdt, 102 nodeoffset, conf_id, 103 DT_DRIVER_PINCTRL, 104 &pinconf); 105 if (res) { 106 free(state); 107 return res; 108 } 109 110 state->confs[conf_id] = pinconf; 111 } 112 113 *state_ret = state; 114 115 return TEE_SUCCESS; 116 } 117 118 TEE_Result pinctrl_get_state_by_name(const void *fdt, int nodeoffset, 119 const char *name, 120 struct pinctrl_state **state) 121 { 122 int pinctrl_index = 0; 123 124 if (!name) 125 name = "default"; 126 127 pinctrl_index = fdt_stringlist_search(fdt, nodeoffset, "pinctrl-names", 128 name); 129 if (pinctrl_index < 0) { 130 *state = NULL; 131 if (pinctrl_index == -FDT_ERR_NOTFOUND) 132 return TEE_ERROR_ITEM_NOT_FOUND; 133 else 134 return TEE_ERROR_GENERIC; 135 } 136 137 return pinctrl_get_state_by_idx(fdt, nodeoffset, pinctrl_index, state); 138 } 139