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_pargs *pargs, 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(pargs->fdt, pargs->phandle_node, "pinmux", 98 &prop_count); 99 if (!prop) { 100 *res = TEE_ERROR_ITEM_NOT_FOUND; 101 return NULL; 102 } 103 104 prop_count /= sizeof(uint32_t); 105 for (i = 0; i < prop_count; i++) { 106 pinmux = fdt32_to_cpu(prop[i]); 107 108 pin_no = DT_GET_PIN_NO(pinmux); 109 func = DT_GET_FUNC(pinmux); 110 111 group = pin_no / 32; 112 if (pio_group == -1) { 113 pio_group = group; 114 } else { 115 if (group != pio_group) { 116 EMSG("Unexpected group %d vs %d", group, 117 pio_group); 118 *res = TEE_ERROR_GENERIC; 119 return NULL; 120 } 121 } 122 123 pin_mask |= BIT(pin_no % 32); 124 } 125 126 cfg = func; 127 128 *res = pinctrl_parse_dt_pin_modes(pargs->fdt, pargs->phandle_node, 129 &cfg_modes); 130 if (*res) 131 return NULL; 132 133 for (i = 0; i < PINCTRL_DT_PROP_MAX; i++) { 134 if (!bit_test(cfg_modes, i)) 135 continue; 136 137 switch (i) { 138 case PINCTRL_DT_PROP_BIAS_PULL_UP: 139 cfg |= PIO_CFGR_PUEN; 140 cfg &= ~PIO_CFGR_PDEN; 141 break; 142 case PINCTRL_DT_PROP_BIAS_PULL_DOWN: 143 cfg |= PIO_CFGR_PDEN; 144 cfg &= ~PIO_CFGR_PUEN; 145 break; 146 case PINCTRL_DT_PROP_BIAS_DISABLE: 147 break; 148 default: 149 EMSG("Unhandled config %u", i); 150 break; 151 } 152 } 153 154 free(cfg_modes); 155 156 pinconf = calloc(1, sizeof(*pinconf) + sizeof(*pio_conf)); 157 if (!pinconf) { 158 *res = TEE_ERROR_OUT_OF_MEMORY; 159 return NULL; 160 } 161 162 pio_conf = (struct atmel_pio_pin_conf *)(pinconf + 1); 163 164 pio_conf->pin_mask = pin_mask; 165 pio_conf->pin_cfg = cfg; 166 pio_conf->pio = atmel_pio; 167 pio_conf->pio_group = pio_group; 168 pinconf->priv = pio_conf; 169 pinconf->ops = &pio_pinctrl_ops; 170 171 *res = TEE_SUCCESS; 172 173 return pinconf; 174 } 175 176 static void pio_init_hw(struct atmel_pio *pio) 177 { 178 int i = 0; 179 180 /* Set all IOs as non-secure */ 181 for (i = 0; i < PIO_GROUP_COUNT; i++) 182 pio_write(pio, PIO_SIONR(PIO_GROUP_COUNT), GENMASK_32(31, 0)); 183 } 184 185 static TEE_Result pio_node_probe(const void *fdt, int node, 186 const void *compat_data __unused) 187 { 188 size_t size = 0; 189 struct clk *clk = NULL; 190 struct atmel_pio *pio = NULL; 191 TEE_Result res = TEE_ERROR_GENERIC; 192 193 if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) 194 return TEE_ERROR_BAD_STATE; 195 196 pio = calloc(1, sizeof(*pio)); 197 if (!pio) 198 return TEE_ERROR_OUT_OF_MEMORY; 199 200 res = clk_dt_get_by_index(fdt, node, 0, &clk); 201 if (res) 202 goto free_pio; 203 204 if (dt_map_dev(fdt, node, &pio->base, &size, DT_MAP_AUTO) < 0) 205 goto free_pio; 206 207 res = clk_enable(clk); 208 if (res) 209 goto free_pio; 210 211 matrix_configure_periph_secure(AT91C_ID_PIOA); 212 matrix_configure_periph_secure(AT91C_ID_PIOB); 213 matrix_configure_periph_secure(AT91C_ID_PIOC); 214 matrix_configure_periph_secure(AT91C_ID_PIOD); 215 216 pio_init_hw(pio); 217 218 res = pinctrl_register_provider(fdt, node, pio_pinctrl_dt_get, pio); 219 if (res) 220 goto disable_clock; 221 222 return TEE_SUCCESS; 223 224 disable_clock: 225 clk_disable(clk); 226 free_pio: 227 free(pio); 228 229 return res; 230 } 231 232 static const struct dt_device_match atmel_pio_match_table[] = { 233 { .compatible = "atmel,sama5d2-pinctrl" }, 234 { } 235 }; 236 237 DEFINE_DT_DRIVER(atmel_pio_dt_driver) = { 238 .name = "atmel_pio", 239 .type = DT_DRIVER_PINCTRL, 240 .match_table = atmel_pio_match_table, 241 .probe = pio_node_probe, 242 }; 243