1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Sophgo SoCs pinctrl common ops. 4 * 5 * Copyright (C) 2024 Inochi Amaoto <inochiama@outlook.com> 6 * 7 */ 8 9 #include <linux/bsearch.h> 10 #include <linux/cleanup.h> 11 #include <linux/export.h> 12 #include <linux/io.h> 13 #include <linux/of.h> 14 #include <linux/module.h> 15 #include <linux/platform_device.h> 16 #include <linux/seq_file.h> 17 #include <linux/spinlock.h> 18 19 #include <linux/pinctrl/pinconf-generic.h> 20 #include <linux/pinctrl/pinctrl.h> 21 22 #include "../pinctrl-utils.h" 23 #include "../pinconf.h" 24 #include "../pinmux.h" 25 26 #include "pinctrl-sophgo.h" 27 28 static u16 sophgo_dt_get_pin(u32 value) 29 { 30 return value; 31 } 32 33 static int sophgo_cmp_pin(const void *key, const void *pivot) 34 { 35 const struct sophgo_pin *pin = pivot; 36 int pin_id = (long)key; 37 int pivid = pin->id; 38 39 return pin_id - pivid; 40 } 41 42 const struct sophgo_pin *sophgo_get_pin(struct sophgo_pinctrl *pctrl, 43 unsigned long pin_id) 44 { 45 return bsearch((void *)pin_id, pctrl->data->pindata, pctrl->data->npins, 46 pctrl->data->pinsize, sophgo_cmp_pin); 47 } 48 49 static int sophgo_verify_pinmux_config(struct sophgo_pinctrl *pctrl, 50 const struct sophgo_pin_mux_config *config) 51 { 52 if (pctrl->data->cfg_ops->verify_pinmux_config) 53 return pctrl->data->cfg_ops->verify_pinmux_config(config); 54 return 0; 55 } 56 57 static int sophgo_verify_pin_group(struct sophgo_pinctrl *pctrl, 58 const struct sophgo_pin_mux_config *config, 59 unsigned int npins) 60 { 61 if (pctrl->data->cfg_ops->verify_pin_group) 62 return pctrl->data->cfg_ops->verify_pin_group(config, npins); 63 return 0; 64 } 65 66 static int sophgo_dt_node_to_map_post(struct device_node *cur, 67 struct sophgo_pinctrl *pctrl, 68 struct sophgo_pin_mux_config *config, 69 unsigned int npins) 70 { 71 if (pctrl->data->cfg_ops->dt_node_to_map_post) 72 return pctrl->data->cfg_ops->dt_node_to_map_post(cur, pctrl, 73 config, npins); 74 return 0; 75 } 76 77 int sophgo_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node *np, 78 struct pinctrl_map **maps, unsigned int *num_maps) 79 { 80 struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 81 struct device *dev = pctrl->dev; 82 struct device_node *child; 83 struct pinctrl_map *map; 84 const char **grpnames; 85 const char *grpname; 86 int ngroups = 0; 87 int nmaps = 0; 88 int ret; 89 90 for_each_available_child_of_node(np, child) 91 ngroups += 1; 92 93 grpnames = devm_kcalloc(dev, ngroups, sizeof(*grpnames), GFP_KERNEL); 94 if (!grpnames) 95 return -ENOMEM; 96 97 map = kcalloc(ngroups * 2, sizeof(*map), GFP_KERNEL); 98 if (!map) 99 return -ENOMEM; 100 101 ngroups = 0; 102 guard(mutex)(&pctrl->mutex); 103 for_each_available_child_of_node(np, child) { 104 int npins = of_property_count_u32_elems(child, "pinmux"); 105 unsigned int *pins; 106 struct sophgo_pin_mux_config *pinmuxs; 107 u32 config; 108 int i; 109 110 if (npins < 1) { 111 dev_err(dev, "invalid pinctrl group %pOFn.%pOFn\n", 112 np, child); 113 ret = -EINVAL; 114 goto dt_failed; 115 } 116 117 grpname = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn", 118 np, child); 119 if (!grpname) { 120 ret = -ENOMEM; 121 goto dt_failed; 122 } 123 124 grpnames[ngroups++] = grpname; 125 126 pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL); 127 if (!pins) { 128 ret = -ENOMEM; 129 goto dt_failed; 130 } 131 132 pinmuxs = devm_kcalloc(dev, npins, sizeof(*pinmuxs), GFP_KERNEL); 133 if (!pinmuxs) { 134 ret = -ENOMEM; 135 goto dt_failed; 136 } 137 138 for (i = 0; i < npins; i++) { 139 ret = of_property_read_u32_index(child, "pinmux", 140 i, &config); 141 if (ret) 142 goto dt_failed; 143 144 pins[i] = sophgo_dt_get_pin(config); 145 pinmuxs[i].config = config; 146 pinmuxs[i].pin = sophgo_get_pin(pctrl, pins[i]); 147 148 if (!pinmuxs[i].pin) { 149 dev_err(dev, "failed to get pin %d\n", pins[i]); 150 ret = -ENODEV; 151 goto dt_failed; 152 } 153 154 ret = sophgo_verify_pinmux_config(pctrl, &pinmuxs[i]); 155 if (ret) { 156 dev_err(dev, "group %s pin %d is invalid\n", 157 grpname, i); 158 goto dt_failed; 159 } 160 } 161 162 ret = sophgo_verify_pin_group(pctrl, pinmuxs, npins); 163 if (ret) { 164 dev_err(dev, "group %s is invalid\n", grpname); 165 goto dt_failed; 166 } 167 168 ret = sophgo_dt_node_to_map_post(child, pctrl, pinmuxs, npins); 169 if (ret) 170 goto dt_failed; 171 172 map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP; 173 map[nmaps].data.mux.function = np->name; 174 map[nmaps].data.mux.group = grpname; 175 nmaps += 1; 176 177 ret = pinconf_generic_parse_dt_config(child, pctldev, 178 &map[nmaps].data.configs.configs, 179 &map[nmaps].data.configs.num_configs); 180 if (ret) { 181 dev_err(dev, "failed to parse pin config of group %s: %d\n", 182 grpname, ret); 183 goto dt_failed; 184 } 185 186 ret = pinctrl_generic_add_group(pctldev, grpname, 187 pins, npins, pinmuxs); 188 if (ret < 0) { 189 dev_err(dev, "failed to add group %s: %d\n", grpname, ret); 190 goto dt_failed; 191 } 192 193 /* don't create a map if there are no pinconf settings */ 194 if (map[nmaps].data.configs.num_configs == 0) 195 continue; 196 197 map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP; 198 map[nmaps].data.configs.group_or_pin = grpname; 199 nmaps += 1; 200 } 201 202 ret = pinmux_generic_add_function(pctldev, np->name, 203 grpnames, ngroups, NULL); 204 if (ret < 0) { 205 dev_err(dev, "error adding function %s: %d\n", np->name, ret); 206 goto function_failed; 207 } 208 209 *maps = map; 210 *num_maps = nmaps; 211 212 return 0; 213 214 dt_failed: 215 of_node_put(child); 216 function_failed: 217 pinctrl_utils_free_map(pctldev, map, nmaps); 218 return ret; 219 } 220 221 int sophgo_pmx_set_mux(struct pinctrl_dev *pctldev, 222 unsigned int fsel, unsigned int gsel) 223 { 224 struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 225 const struct group_desc *group; 226 const struct sophgo_pin_mux_config *configs; 227 unsigned int i; 228 229 group = pinctrl_generic_get_group(pctldev, gsel); 230 if (!group) 231 return -EINVAL; 232 233 configs = group->data; 234 235 for (i = 0; i < group->grp.npins; i++) { 236 const struct sophgo_pin *pin = configs[i].pin; 237 u32 value = configs[i].config; 238 239 guard(raw_spinlock_irqsave)(&pctrl->lock); 240 241 pctrl->data->cfg_ops->set_pinmux_config(pctrl, pin, value); 242 } 243 244 return 0; 245 } 246 247 static int sophgo_pin_set_config(struct sophgo_pinctrl *pctrl, 248 unsigned int pin_id, 249 u32 value, u32 mask) 250 { 251 const struct sophgo_pin *pin = sophgo_get_pin(pctrl, pin_id); 252 253 if (!pin) 254 return -EINVAL; 255 256 guard(raw_spinlock_irqsave)(&pctrl->lock); 257 258 return pctrl->data->cfg_ops->set_pinconf_config(pctrl, pin, value, mask); 259 } 260 261 int sophgo_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin_id, 262 unsigned long *configs, unsigned int num_configs) 263 { 264 struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 265 const struct sophgo_pin *pin = sophgo_get_pin(pctrl, pin_id); 266 u32 value, mask; 267 268 if (!pin) 269 return -ENODEV; 270 271 if (pctrl->data->cfg_ops->compute_pinconf_config(pctrl, pin, 272 configs, num_configs, 273 &value, &mask)) 274 return -ENOTSUPP; 275 276 return sophgo_pin_set_config(pctrl, pin_id, value, mask); 277 } 278 279 int sophgo_pconf_group_set(struct pinctrl_dev *pctldev, unsigned int gsel, 280 unsigned long *configs, unsigned int num_configs) 281 { 282 struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 283 const struct group_desc *group; 284 const struct sophgo_pin_mux_config *pinmuxs; 285 u32 value, mask; 286 int i; 287 288 group = pinctrl_generic_get_group(pctldev, gsel); 289 if (!group) 290 return -EINVAL; 291 292 pinmuxs = group->data; 293 294 if (pctrl->data->cfg_ops->compute_pinconf_config(pctrl, pinmuxs[0].pin, 295 configs, num_configs, 296 &value, &mask)) 297 return -ENOTSUPP; 298 299 for (i = 0; i < group->grp.npins; i++) 300 sophgo_pin_set_config(pctrl, group->grp.pins[i], value, mask); 301 302 return 0; 303 } 304 305 u32 sophgo_pinctrl_typical_pull_down(struct sophgo_pinctrl *pctrl, 306 const struct sophgo_pin *pin, 307 const u32 *power_cfg) 308 { 309 return pctrl->data->vddio_ops->get_pull_down(pin, power_cfg); 310 } 311 312 u32 sophgo_pinctrl_typical_pull_up(struct sophgo_pinctrl *pctrl, 313 const struct sophgo_pin *pin, 314 const u32 *power_cfg) 315 { 316 return pctrl->data->vddio_ops->get_pull_up(pin, power_cfg); 317 } 318 319 int sophgo_pinctrl_oc2reg(struct sophgo_pinctrl *pctrl, 320 const struct sophgo_pin *pin, 321 const u32 *power_cfg, u32 target) 322 { 323 const u32 *map; 324 int i, len; 325 326 if (!pctrl->data->vddio_ops->get_oc_map) 327 return -ENOTSUPP; 328 329 len = pctrl->data->vddio_ops->get_oc_map(pin, power_cfg, &map); 330 if (len < 0) 331 return len; 332 333 for (i = 0; i < len; i++) { 334 if (map[i] >= target) 335 return i; 336 } 337 338 return -EINVAL; 339 } 340 341 int sophgo_pinctrl_reg2oc(struct sophgo_pinctrl *pctrl, 342 const struct sophgo_pin *pin, 343 const u32 *power_cfg, u32 reg) 344 { 345 const u32 *map; 346 int len; 347 348 if (!pctrl->data->vddio_ops->get_oc_map) 349 return -ENOTSUPP; 350 351 len = pctrl->data->vddio_ops->get_oc_map(pin, power_cfg, &map); 352 if (len < 0) 353 return len; 354 355 if (reg >= len) 356 return -EINVAL; 357 358 return map[reg]; 359 } 360 361 int sophgo_pinctrl_schmitt2reg(struct sophgo_pinctrl *pctrl, 362 const struct sophgo_pin *pin, 363 const u32 *power_cfg, u32 target) 364 { 365 const u32 *map; 366 int i, len; 367 368 if (!pctrl->data->vddio_ops->get_schmitt_map) 369 return -ENOTSUPP; 370 371 len = pctrl->data->vddio_ops->get_schmitt_map(pin, power_cfg, &map); 372 if (len < 0) 373 return len; 374 375 for (i = 0; i < len; i++) { 376 if (map[i] == target) 377 return i; 378 } 379 380 return -EINVAL; 381 } 382 383 int sophgo_pinctrl_reg2schmitt(struct sophgo_pinctrl *pctrl, 384 const struct sophgo_pin *pin, 385 const u32 *power_cfg, u32 reg) 386 { 387 const u32 *map; 388 int len; 389 390 if (!pctrl->data->vddio_ops->get_schmitt_map) 391 return -ENOTSUPP; 392 393 len = pctrl->data->vddio_ops->get_schmitt_map(pin, power_cfg, &map); 394 if (len < 0) 395 return len; 396 397 if (reg >= len) 398 return -EINVAL; 399 400 return map[reg]; 401 } 402 403 int sophgo_pinctrl_probe(struct platform_device *pdev) 404 { 405 struct device *dev = &pdev->dev; 406 struct sophgo_pinctrl *pctrl; 407 const struct sophgo_pinctrl_data *pctrl_data; 408 int ret; 409 410 pctrl_data = device_get_match_data(dev); 411 if (!pctrl_data) 412 return -ENODEV; 413 414 if (pctrl_data->npins == 0) 415 return dev_err_probe(dev, -EINVAL, "invalid pin data\n"); 416 417 pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL); 418 if (!pctrl) 419 return -ENOMEM; 420 421 pctrl->pdesc.name = dev_name(dev); 422 pctrl->pdesc.pins = pctrl_data->pins; 423 pctrl->pdesc.npins = pctrl_data->npins; 424 pctrl->pdesc.pctlops = pctrl_data->pctl_ops; 425 pctrl->pdesc.pmxops = pctrl_data->pmx_ops; 426 pctrl->pdesc.confops = pctrl_data->pconf_ops; 427 pctrl->pdesc.owner = THIS_MODULE; 428 429 pctrl->data = pctrl_data; 430 pctrl->dev = dev; 431 raw_spin_lock_init(&pctrl->lock); 432 mutex_init(&pctrl->mutex); 433 434 ret = pctrl->data->cfg_ops->pctrl_init(pdev, pctrl); 435 if (ret) 436 return ret; 437 438 platform_set_drvdata(pdev, pctrl); 439 440 ret = devm_pinctrl_register_and_init(dev, &pctrl->pdesc, 441 pctrl, &pctrl->pctrl_dev); 442 if (ret) 443 return dev_err_probe(dev, ret, 444 "fail to register pinctrl driver\n"); 445 446 return pinctrl_enable(pctrl->pctrl_dev); 447 } 448 EXPORT_SYMBOL_GPL(sophgo_pinctrl_probe); 449 450 MODULE_DESCRIPTION("Common pinctrl helper function for the Sophgo SoC"); 451 MODULE_LICENSE("GPL"); 452