1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright 2019 Microchip. 4 */ 5 #include <assert.h> 6 #include <drivers/clk.h> 7 #include <drivers/clk_dt.h> 8 #include <drivers/pinctrl.h> 9 #include <initcall.h> 10 #include <io.h> 11 #include <kernel/dt.h> 12 #include <libfdt.h> 13 #include <malloc.h> 14 #include <matrix.h> 15 #include <platform_config.h> 16 #include <trace.h> 17 #include <util.h> 18 19 #define PIO_GROUP_COUNT 4 20 #define PIO_GROUP_OFFSET 0x40 21 #define PIO_REG(reg, group) ((reg) + ((group) * PIO_GROUP_OFFSET)) 22 /* Mask register */ 23 #define PIO_MSKR(group) PIO_REG(0x0, (group)) 24 /* Configuration register */ 25 #define PIO_CFGR(group) PIO_REG(0x4, (group)) 26 #define PIO_CFGR_FUNC GENMASK(2, 0) 27 #define PIO_CFGR_PUEN BIT(9) 28 #define PIO_CFGR_PDEN BIT(10) 29 30 /* Non-Secure configuration register */ 31 #define PIO_SIONR(group) PIO_REG(0x30, (group)) 32 /* Secure configuration register */ 33 #define PIO_SIOSR(group) PIO_REG(0x34, (group)) 34 35 #define DT_GET_PIN_NO(val) ((val) & 0xFF) 36 #define DT_GET_FUNC(val) (((val) >> 16) & 0xF) 37 38 struct atmel_pio { 39 vaddr_t base; 40 }; 41 42 struct atmel_pio_pin_conf { 43 uint32_t pin_mask; 44 uint32_t pin_cfg; 45 uint8_t pio_group; 46 struct atmel_pio *pio; 47 }; 48 49 static void pio_write(struct atmel_pio *pio, unsigned int offset, uint32_t val) 50 { 51 io_write32(pio->base + offset, val); 52 } 53 54 static TEE_Result pio_conf_apply(struct pinconf *conf) 55 { 56 struct atmel_pio_pin_conf *pio_conf = conf->priv; 57 struct atmel_pio *pio = pio_conf->pio; 58 59 DMSG("Apply cfg %#" PRIx32 " on group %" PRIu8 ", pins %#" PRIx32, 60 pio_conf->pin_cfg, pio_conf->pio_group, pio_conf->pin_mask); 61 62 pio_write(pio, PIO_SIOSR(pio_conf->pio_group), pio_conf->pin_mask); 63 pio_write(pio, PIO_MSKR(pio_conf->pio_group), pio_conf->pin_mask); 64 pio_write(pio, PIO_CFGR(pio_conf->pio_group), pio_conf->pin_cfg); 65 66 return TEE_SUCCESS; 67 } 68 69 static void pio_conf_free(struct pinconf *conf) 70 { 71 free(conf); 72 } 73 74 static const struct pinctrl_ops pio_pinctrl_ops = { 75 .conf_apply = pio_conf_apply, 76 .conf_free = pio_conf_free, 77 }; 78 79 static struct pinconf *pio_pinctrl_dt_get(struct dt_driver_phandle_args *a, 80 void *data, TEE_Result *res) 81 { 82 int i = 0; 83 int func = 0; 84 int group = 0; 85 int pin_no = 0; 86 uint32_t cfg = 0; 87 int prop_count = 0; 88 int pio_group = -1; 89 uint32_t pinmux = 0; 90 uint32_t pin_mask = 0; 91 bitstr_t *cfg_modes = NULL; 92 const uint32_t *prop = NULL; 93 struct pinconf *pinconf = NULL; 94 struct atmel_pio *atmel_pio = data; 95 struct atmel_pio_pin_conf *pio_conf = NULL; 96 97 prop = fdt_getprop(a->fdt, a->phandle_node, "pinmux", &prop_count); 98 if (!prop) { 99 *res = TEE_ERROR_ITEM_NOT_FOUND; 100 return NULL; 101 } 102 103 prop_count /= sizeof(uint32_t); 104 for (i = 0; i < prop_count; i++) { 105 pinmux = fdt32_to_cpu(prop[i]); 106 107 pin_no = DT_GET_PIN_NO(pinmux); 108 func = DT_GET_FUNC(pinmux); 109 110 group = pin_no / 32; 111 if (pio_group == -1) { 112 pio_group = group; 113 } else { 114 if (group != pio_group) { 115 EMSG("Unexpected group %d vs %d", group, 116 pio_group); 117 *res = TEE_ERROR_GENERIC; 118 return NULL; 119 } 120 } 121 122 pin_mask |= BIT(pin_no % 32); 123 } 124 125 cfg = func; 126 127 *res = pinctrl_parse_dt_pin_modes(a->fdt, a->phandle_node, &cfg_modes); 128 if (*res) 129 return NULL; 130 131 for (i = 0; i < PINCTRL_DT_PROP_MAX; i++) { 132 if (!bit_test(cfg_modes, i)) 133 continue; 134 135 switch (i) { 136 case PINCTRL_DT_PROP_BIAS_PULL_UP: 137 cfg |= PIO_CFGR_PUEN; 138 cfg &= ~PIO_CFGR_PDEN; 139 break; 140 case PINCTRL_DT_PROP_BIAS_PULL_DOWN: 141 cfg |= PIO_CFGR_PDEN; 142 cfg &= ~PIO_CFGR_PUEN; 143 break; 144 case PINCTRL_DT_PROP_BIAS_DISABLE: 145 break; 146 default: 147 EMSG("Unhandled config %u", i); 148 break; 149 } 150 } 151 152 free(cfg_modes); 153 154 pinconf = calloc(1, sizeof(*pinconf) + sizeof(*pio_conf)); 155 if (!pinconf) { 156 *res = TEE_ERROR_OUT_OF_MEMORY; 157 return NULL; 158 } 159 160 pio_conf = (struct atmel_pio_pin_conf *)(pinconf + 1); 161 162 pio_conf->pin_mask = pin_mask; 163 pio_conf->pin_cfg = cfg; 164 pio_conf->pio = atmel_pio; 165 pio_conf->pio_group = pio_group; 166 pinconf->priv = pio_conf; 167 pinconf->ops = &pio_pinctrl_ops; 168 169 *res = TEE_SUCCESS; 170 171 return pinconf; 172 } 173 174 static void pio_init_hw(struct atmel_pio *pio) 175 { 176 int i = 0; 177 178 /* Set all IOs as non-secure */ 179 for (i = 0; i < PIO_GROUP_COUNT; i++) 180 pio_write(pio, PIO_SIONR(PIO_GROUP_COUNT), GENMASK_32(31, 0)); 181 } 182 183 static TEE_Result pio_node_probe(const void *fdt, int node, 184 const void *compat_data __unused) 185 { 186 size_t size = 0; 187 struct clk *clk = NULL; 188 struct atmel_pio *pio = NULL; 189 TEE_Result res = TEE_ERROR_GENERIC; 190 191 if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) 192 return TEE_ERROR_BAD_STATE; 193 194 pio = calloc(1, sizeof(*pio)); 195 if (!pio) 196 return TEE_ERROR_OUT_OF_MEMORY; 197 198 res = clk_dt_get_by_index(fdt, node, 0, &clk); 199 if (res) 200 goto free_pio; 201 202 if (dt_map_dev(fdt, node, &pio->base, &size, DT_MAP_AUTO) < 0) 203 goto free_pio; 204 205 res = clk_enable(clk); 206 if (res) 207 goto free_pio; 208 209 matrix_configure_periph_secure(AT91C_ID_PIOA); 210 matrix_configure_periph_secure(AT91C_ID_PIOB); 211 matrix_configure_periph_secure(AT91C_ID_PIOC); 212 matrix_configure_periph_secure(AT91C_ID_PIOD); 213 214 pio_init_hw(pio); 215 216 res = pinctrl_register_provider(fdt, node, pio_pinctrl_dt_get, pio); 217 if (res) 218 goto disable_clock; 219 220 return TEE_SUCCESS; 221 222 disable_clock: 223 clk_disable(clk); 224 free_pio: 225 free(pio); 226 227 return res; 228 } 229 230 static const struct dt_device_match atmel_pio_match_table[] = { 231 { .compatible = "atmel,sama5d2-pinctrl" }, 232 { } 233 }; 234 235 DEFINE_DT_DRIVER(atmel_pio_dt_driver) = { 236 .name = "atmel_pio", 237 .type = DT_DRIVER_PINCTRL, 238 .match_table = atmel_pio_match_table, 239 .probe = pio_node_probe, 240 }; 241