845 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Marvell MVEBU pinctrl core driver4 *5 * Authors: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>6 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>7 */8 9#include <linux/err.h>10#include <linux/gpio/driver.h>11#include <linux/io.h>12#include <linux/mfd/syscon.h>13#include <linux/of.h>14#include <linux/platform_device.h>15#include <linux/regmap.h>16#include <linux/seq_file.h>17#include <linux/slab.h>18 19#include <linux/pinctrl/machine.h>20#include <linux/pinctrl/pinconf.h>21#include <linux/pinctrl/pinctrl.h>22#include <linux/pinctrl/pinmux.h>23 24#include "pinctrl-mvebu.h"25 26#define MPPS_PER_REG 827#define MPP_BITS 428#define MPP_MASK 0xf29 30struct mvebu_pinctrl_function {31 const char *name;32 const char **groups;33 unsigned num_groups;34};35 36struct mvebu_pinctrl_group {37 const char *name;38 const struct mvebu_mpp_ctrl *ctrl;39 struct mvebu_mpp_ctrl_data *data;40 struct mvebu_mpp_ctrl_setting *settings;41 unsigned num_settings;42 unsigned gid;43 unsigned *pins;44 unsigned npins;45};46 47struct mvebu_pinctrl {48 struct device *dev;49 struct pinctrl_dev *pctldev;50 struct pinctrl_desc desc;51 struct mvebu_pinctrl_group *groups;52 unsigned num_groups;53 struct mvebu_pinctrl_function *functions;54 unsigned num_functions;55 u8 variant;56};57 58int mvebu_mmio_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,59 unsigned int pid, unsigned long *config)60{61 unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;62 unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;63 64 *config = (readl(data->base + off) >> shift) & MVEBU_MPP_MASK;65 66 return 0;67}68 69int mvebu_mmio_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,70 unsigned int pid, unsigned long config)71{72 unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;73 unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;74 unsigned long reg;75 76 reg = readl(data->base + off) & ~(MVEBU_MPP_MASK << shift);77 writel(reg | (config << shift), data->base + off);78 79 return 0;80}81 82static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_pid(83 struct mvebu_pinctrl *pctl, unsigned pid)84{85 unsigned n;86 for (n = 0; n < pctl->num_groups; n++) {87 if (pid >= pctl->groups[n].pins[0] &&88 pid < pctl->groups[n].pins[0] +89 pctl->groups[n].npins)90 return &pctl->groups[n];91 }92 return NULL;93}94 95static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_name(96 struct mvebu_pinctrl *pctl, const char *name)97{98 unsigned n;99 100 for (n = 0; n < pctl->num_groups; n++) {101 if (strcmp(name, pctl->groups[n].name) == 0)102 return &pctl->groups[n];103 }104 105 return NULL;106}107 108static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_val(109 struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp,110 unsigned long config)111{112 unsigned n;113 114 for (n = 0; n < grp->num_settings; n++) {115 if (config == grp->settings[n].val) {116 if (!pctl->variant || (pctl->variant &117 grp->settings[n].variant))118 return &grp->settings[n];119 }120 }121 122 return NULL;123}124 125static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_name(126 struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp,127 const char *name)128{129 unsigned n;130 131 for (n = 0; n < grp->num_settings; n++) {132 if (strcmp(name, grp->settings[n].name) == 0) {133 if (!pctl->variant || (pctl->variant &134 grp->settings[n].variant))135 return &grp->settings[n];136 }137 }138 139 return NULL;140}141 142static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_gpio_setting(143 struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp)144{145 unsigned n;146 147 for (n = 0; n < grp->num_settings; n++) {148 if (grp->settings[n].flags &149 (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {150 if (!pctl->variant || (pctl->variant &151 grp->settings[n].variant))152 return &grp->settings[n];153 }154 }155 156 return NULL;157}158 159static struct mvebu_pinctrl_function *mvebu_pinctrl_find_function_by_name(160 struct mvebu_pinctrl *pctl, const char *name)161{162 unsigned n;163 164 for (n = 0; n < pctl->num_functions; n++) {165 if (strcmp(name, pctl->functions[n].name) == 0)166 return &pctl->functions[n];167 }168 169 return NULL;170}171 172static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev,173 unsigned gid, unsigned long *config)174{175 struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);176 struct mvebu_pinctrl_group *grp = &pctl->groups[gid];177 178 if (!grp->ctrl)179 return -EINVAL;180 181 return grp->ctrl->mpp_get(grp->data, grp->pins[0], config);182}183 184static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev,185 unsigned gid, unsigned long *configs,186 unsigned num_configs)187{188 struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);189 struct mvebu_pinctrl_group *grp = &pctl->groups[gid];190 int i, ret;191 192 if (!grp->ctrl)193 return -EINVAL;194 195 for (i = 0; i < num_configs; i++) {196 ret = grp->ctrl->mpp_set(grp->data, grp->pins[0], configs[i]);197 if (ret)198 return ret;199 } /* for each config */200 201 return 0;202}203 204static void mvebu_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,205 struct seq_file *s, unsigned gid)206{207 struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);208 struct mvebu_pinctrl_group *grp = &pctl->groups[gid];209 struct mvebu_mpp_ctrl_setting *curr;210 unsigned long config;211 unsigned n;212 213 if (mvebu_pinconf_group_get(pctldev, gid, &config))214 return;215 216 curr = mvebu_pinctrl_find_setting_by_val(pctl, grp, config);217 218 if (curr) {219 seq_printf(s, "current: %s", curr->name);220 if (curr->subname)221 seq_printf(s, "(%s)", curr->subname);222 if (curr->flags & (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {223 seq_putc(s, '(');224 if (curr->flags & MVEBU_SETTING_GPI)225 seq_putc(s, 'i');226 if (curr->flags & MVEBU_SETTING_GPO)227 seq_putc(s, 'o');228 seq_putc(s, ')');229 }230 } else {231 seq_puts(s, "current: UNKNOWN");232 }233 234 if (grp->num_settings > 1) {235 seq_puts(s, ", available = [");236 for (n = 0; n < grp->num_settings; n++) {237 if (curr == &grp->settings[n])238 continue;239 240 /* skip unsupported settings for this variant */241 if (pctl->variant &&242 !(pctl->variant & grp->settings[n].variant))243 continue;244 245 seq_printf(s, " %s", grp->settings[n].name);246 if (grp->settings[n].subname)247 seq_printf(s, "(%s)", grp->settings[n].subname);248 if (grp->settings[n].flags &249 (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {250 seq_putc(s, '(');251 if (grp->settings[n].flags & MVEBU_SETTING_GPI)252 seq_putc(s, 'i');253 if (grp->settings[n].flags & MVEBU_SETTING_GPO)254 seq_putc(s, 'o');255 seq_putc(s, ')');256 }257 }258 seq_puts(s, " ]");259 }260}261 262static const struct pinconf_ops mvebu_pinconf_ops = {263 .pin_config_group_get = mvebu_pinconf_group_get,264 .pin_config_group_set = mvebu_pinconf_group_set,265 .pin_config_group_dbg_show = mvebu_pinconf_group_dbg_show,266};267 268static int mvebu_pinmux_get_funcs_count(struct pinctrl_dev *pctldev)269{270 struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);271 272 return pctl->num_functions;273}274 275static const char *mvebu_pinmux_get_func_name(struct pinctrl_dev *pctldev,276 unsigned fid)277{278 struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);279 280 return pctl->functions[fid].name;281}282 283static int mvebu_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned fid,284 const char * const **groups,285 unsigned * const num_groups)286{287 struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);288 289 *groups = pctl->functions[fid].groups;290 *num_groups = pctl->functions[fid].num_groups;291 return 0;292}293 294static int mvebu_pinmux_set(struct pinctrl_dev *pctldev, unsigned fid,295 unsigned gid)296{297 struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);298 struct mvebu_pinctrl_function *func = &pctl->functions[fid];299 struct mvebu_pinctrl_group *grp = &pctl->groups[gid];300 struct mvebu_mpp_ctrl_setting *setting;301 int ret;302 unsigned long config;303 304 setting = mvebu_pinctrl_find_setting_by_name(pctl, grp,305 func->name);306 if (!setting) {307 dev_err(pctl->dev,308 "unable to find setting %s in group %s\n",309 func->name, func->groups[gid]);310 return -EINVAL;311 }312 313 config = setting->val;314 ret = mvebu_pinconf_group_set(pctldev, grp->gid, &config, 1);315 if (ret) {316 dev_err(pctl->dev, "cannot set group %s to %s\n",317 func->groups[gid], func->name);318 return ret;319 }320 321 return 0;322}323 324static int mvebu_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,325 struct pinctrl_gpio_range *range, unsigned offset)326{327 struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);328 struct mvebu_pinctrl_group *grp;329 struct mvebu_mpp_ctrl_setting *setting;330 unsigned long config;331 332 grp = mvebu_pinctrl_find_group_by_pid(pctl, offset);333 if (!grp)334 return -EINVAL;335 336 if (grp->ctrl->mpp_gpio_req)337 return grp->ctrl->mpp_gpio_req(grp->data, offset);338 339 setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);340 if (!setting)341 return -ENOTSUPP;342 343 config = setting->val;344 345 return mvebu_pinconf_group_set(pctldev, grp->gid, &config, 1);346}347 348static int mvebu_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,349 struct pinctrl_gpio_range *range, unsigned offset, bool input)350{351 struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);352 struct mvebu_pinctrl_group *grp;353 struct mvebu_mpp_ctrl_setting *setting;354 355 grp = mvebu_pinctrl_find_group_by_pid(pctl, offset);356 if (!grp)357 return -EINVAL;358 359 if (grp->ctrl->mpp_gpio_dir)360 return grp->ctrl->mpp_gpio_dir(grp->data, offset, input);361 362 setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);363 if (!setting)364 return -ENOTSUPP;365 366 if ((input && (setting->flags & MVEBU_SETTING_GPI)) ||367 (!input && (setting->flags & MVEBU_SETTING_GPO)))368 return 0;369 370 return -ENOTSUPP;371}372 373static const struct pinmux_ops mvebu_pinmux_ops = {374 .get_functions_count = mvebu_pinmux_get_funcs_count,375 .get_function_name = mvebu_pinmux_get_func_name,376 .get_function_groups = mvebu_pinmux_get_groups,377 .gpio_request_enable = mvebu_pinmux_gpio_request_enable,378 .gpio_set_direction = mvebu_pinmux_gpio_set_direction,379 .set_mux = mvebu_pinmux_set,380};381 382static int mvebu_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)383{384 struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);385 return pctl->num_groups;386}387 388static const char *mvebu_pinctrl_get_group_name(struct pinctrl_dev *pctldev,389 unsigned gid)390{391 struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);392 return pctl->groups[gid].name;393}394 395static int mvebu_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,396 unsigned gid, const unsigned **pins,397 unsigned *num_pins)398{399 struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);400 *pins = pctl->groups[gid].pins;401 *num_pins = pctl->groups[gid].npins;402 return 0;403}404 405static int mvebu_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,406 struct device_node *np,407 struct pinctrl_map **map,408 unsigned *num_maps)409{410 struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);411 struct property *prop;412 const char *function;413 const char *group;414 int ret, nmaps, n;415 416 *map = NULL;417 *num_maps = 0;418 419 ret = of_property_read_string(np, "marvell,function", &function);420 if (ret) {421 dev_err(pctl->dev,422 "missing marvell,function in node %pOFn\n", np);423 return 0;424 }425 426 nmaps = of_property_count_strings(np, "marvell,pins");427 if (nmaps < 0) {428 dev_err(pctl->dev,429 "missing marvell,pins in node %pOFn\n", np);430 return 0;431 }432 433 *map = kmalloc_array(nmaps, sizeof(**map), GFP_KERNEL);434 if (!*map)435 return -ENOMEM;436 437 n = 0;438 of_property_for_each_string(np, "marvell,pins", prop, group) {439 struct mvebu_pinctrl_group *grp =440 mvebu_pinctrl_find_group_by_name(pctl, group);441 442 if (!grp) {443 dev_err(pctl->dev, "unknown pin %s", group);444 continue;445 }446 447 if (!mvebu_pinctrl_find_setting_by_name(pctl, grp, function)) {448 dev_err(pctl->dev, "unsupported function %s on pin %s",449 function, group);450 continue;451 }452 453 (*map)[n].type = PIN_MAP_TYPE_MUX_GROUP;454 (*map)[n].data.mux.group = group;455 (*map)[n].data.mux.function = function;456 n++;457 }458 459 *num_maps = nmaps;460 461 return 0;462}463 464static void mvebu_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,465 struct pinctrl_map *map, unsigned num_maps)466{467 kfree(map);468}469 470static const struct pinctrl_ops mvebu_pinctrl_ops = {471 .get_groups_count = mvebu_pinctrl_get_groups_count,472 .get_group_name = mvebu_pinctrl_get_group_name,473 .get_group_pins = mvebu_pinctrl_get_group_pins,474 .dt_node_to_map = mvebu_pinctrl_dt_node_to_map,475 .dt_free_map = mvebu_pinctrl_dt_free_map,476};477 478static int _add_function(struct mvebu_pinctrl_function *funcs, int *funcsize,479 const char *name)480{481 if (*funcsize <= 0)482 return -EOVERFLOW;483 484 while (funcs->num_groups) {485 /* function already there */486 if (strcmp(funcs->name, name) == 0) {487 funcs->num_groups++;488 return -EEXIST;489 }490 funcs++;491 }492 493 /* append new unique function */494 funcs->name = name;495 funcs->num_groups = 1;496 (*funcsize)--;497 498 return 0;499}500 501static int mvebu_pinctrl_build_functions(struct platform_device *pdev,502 struct mvebu_pinctrl *pctl)503{504 struct mvebu_pinctrl_function *funcs;505 int num = 0, funcsize = pctl->desc.npins;506 int n, s;507 508 /* we allocate functions for number of pins and hope509 * there are fewer unique functions than pins available */510 funcs = devm_kcalloc(&pdev->dev,511 funcsize, sizeof(struct mvebu_pinctrl_function),512 GFP_KERNEL);513 if (!funcs)514 return -ENOMEM;515 516 for (n = 0; n < pctl->num_groups; n++) {517 struct mvebu_pinctrl_group *grp = &pctl->groups[n];518 for (s = 0; s < grp->num_settings; s++) {519 int ret;520 521 /* skip unsupported settings on this variant */522 if (pctl->variant &&523 !(pctl->variant & grp->settings[s].variant))524 continue;525 526 /* check for unique functions and count groups */527 ret = _add_function(funcs, &funcsize,528 grp->settings[s].name);529 if (ret == -EOVERFLOW)530 dev_err(&pdev->dev,531 "More functions than pins(%d)\n",532 pctl->desc.npins);533 if (ret < 0)534 continue;535 536 num++;537 }538 }539 540 pctl->num_functions = num;541 pctl->functions = funcs;542 543 for (n = 0; n < pctl->num_groups; n++) {544 struct mvebu_pinctrl_group *grp = &pctl->groups[n];545 for (s = 0; s < grp->num_settings; s++) {546 struct mvebu_pinctrl_function *f;547 const char **groups;548 549 /* skip unsupported settings on this variant */550 if (pctl->variant &&551 !(pctl->variant & grp->settings[s].variant))552 continue;553 554 f = mvebu_pinctrl_find_function_by_name(pctl,555 grp->settings[s].name);556 557 /* allocate group name array if not done already */558 if (!f->groups) {559 f->groups = devm_kcalloc(&pdev->dev,560 f->num_groups,561 sizeof(char *),562 GFP_KERNEL);563 if (!f->groups)564 return -ENOMEM;565 }566 567 /* find next free group name and assign current name */568 groups = f->groups;569 while (*groups)570 groups++;571 *groups = grp->name;572 }573 }574 575 return 0;576}577 578int mvebu_pinctrl_probe(struct platform_device *pdev)579{580 struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev);581 struct mvebu_pinctrl *pctl;582 struct pinctrl_pin_desc *pdesc;583 unsigned gid, n, k;584 unsigned size, noname = 0;585 char *noname_buf;586 void *p;587 int ret;588 589 if (!soc || !soc->controls || !soc->modes) {590 dev_err(&pdev->dev, "wrong pinctrl soc info\n");591 return -EINVAL;592 }593 594 pctl = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pinctrl),595 GFP_KERNEL);596 if (!pctl)597 return -ENOMEM;598 599 pctl->desc.name = dev_name(&pdev->dev);600 pctl->desc.owner = THIS_MODULE;601 pctl->desc.pctlops = &mvebu_pinctrl_ops;602 pctl->desc.pmxops = &mvebu_pinmux_ops;603 pctl->desc.confops = &mvebu_pinconf_ops;604 pctl->variant = soc->variant;605 pctl->dev = &pdev->dev;606 platform_set_drvdata(pdev, pctl);607 608 /* count controls and create names for mvebu generic609 register controls; also does sanity checks */610 pctl->num_groups = 0;611 pctl->desc.npins = 0;612 for (n = 0; n < soc->ncontrols; n++) {613 const struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];614 615 pctl->desc.npins += ctrl->npins;616 /* initialize control's pins[] array */617 for (k = 0; k < ctrl->npins; k++)618 ctrl->pins[k] = ctrl->pid + k;619 620 /*621 * We allow to pass controls with NULL name that we treat622 * as a range of one-pin groups with generic mvebu register623 * controls.624 */625 if (!ctrl->name) {626 pctl->num_groups += ctrl->npins;627 noname += ctrl->npins;628 } else {629 pctl->num_groups += 1;630 }631 }632 633 pdesc = devm_kcalloc(&pdev->dev,634 pctl->desc.npins,635 sizeof(struct pinctrl_pin_desc),636 GFP_KERNEL);637 if (!pdesc)638 return -ENOMEM;639 640 for (n = 0; n < pctl->desc.npins; n++)641 pdesc[n].number = n;642 pctl->desc.pins = pdesc;643 644 /*645 * allocate groups and name buffers for unnamed groups.646 */647 size = pctl->num_groups * sizeof(*pctl->groups) + noname * 8;648 p = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);649 if (!p)650 return -ENOMEM;651 652 pctl->groups = p;653 noname_buf = p + pctl->num_groups * sizeof(*pctl->groups);654 655 /* assign mpp controls to groups */656 gid = 0;657 for (n = 0; n < soc->ncontrols; n++) {658 const struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];659 struct mvebu_mpp_ctrl_data *data = soc->control_data ?660 &soc->control_data[n] : NULL;661 662 pctl->groups[gid].gid = gid;663 pctl->groups[gid].ctrl = ctrl;664 pctl->groups[gid].data = data;665 pctl->groups[gid].name = ctrl->name;666 pctl->groups[gid].pins = ctrl->pins;667 pctl->groups[gid].npins = ctrl->npins;668 669 /*670 * We treat unnamed controls as a range of one-pin groups671 * with generic mvebu register controls. Use one group for672 * each in this range and assign a default group name.673 */674 if (!ctrl->name) {675 pctl->groups[gid].name = noname_buf;676 pctl->groups[gid].npins = 1;677 sprintf(noname_buf, "mpp%d", ctrl->pid+0);678 noname_buf += 8;679 680 for (k = 1; k < ctrl->npins; k++) {681 gid++;682 pctl->groups[gid].gid = gid;683 pctl->groups[gid].ctrl = ctrl;684 pctl->groups[gid].data = data;685 pctl->groups[gid].name = noname_buf;686 pctl->groups[gid].pins = &ctrl->pins[k];687 pctl->groups[gid].npins = 1;688 sprintf(noname_buf, "mpp%d", ctrl->pid+k);689 noname_buf += 8;690 }691 }692 gid++;693 }694 695 /* assign mpp modes to groups */696 for (n = 0; n < soc->nmodes; n++) {697 struct mvebu_mpp_mode *mode = &soc->modes[n];698 struct mvebu_mpp_ctrl_setting *set = &mode->settings[0];699 struct mvebu_pinctrl_group *grp;700 unsigned num_settings;701 unsigned supp_settings;702 703 for (num_settings = 0, supp_settings = 0; ; set++) {704 if (!set->name)705 break;706 707 num_settings++;708 709 /* skip unsupported settings for this variant */710 if (pctl->variant && !(pctl->variant & set->variant))711 continue;712 713 supp_settings++;714 715 /* find gpio/gpo/gpi settings */716 if (strcmp(set->name, "gpio") == 0)717 set->flags = MVEBU_SETTING_GPI |718 MVEBU_SETTING_GPO;719 else if (strcmp(set->name, "gpo") == 0)720 set->flags = MVEBU_SETTING_GPO;721 else if (strcmp(set->name, "gpi") == 0)722 set->flags = MVEBU_SETTING_GPI;723 }724 725 /* skip modes with no settings for this variant */726 if (!supp_settings)727 continue;728 729 grp = mvebu_pinctrl_find_group_by_pid(pctl, mode->pid);730 if (!grp) {731 dev_warn(&pdev->dev, "unknown pinctrl group %d\n",732 mode->pid);733 continue;734 }735 736 grp->settings = mode->settings;737 grp->num_settings = num_settings;738 }739 740 ret = mvebu_pinctrl_build_functions(pdev, pctl);741 if (ret) {742 dev_err(&pdev->dev, "unable to build functions\n");743 return ret;744 }745 746 pctl->pctldev = devm_pinctrl_register(&pdev->dev, &pctl->desc, pctl);747 if (IS_ERR(pctl->pctldev)) {748 dev_err(&pdev->dev, "unable to register pinctrl driver\n");749 return PTR_ERR(pctl->pctldev);750 }751 752 dev_info(&pdev->dev, "registered pinctrl driver\n");753 754 /* register gpio ranges */755 for (n = 0; n < soc->ngpioranges; n++)756 pinctrl_add_gpio_range(pctl->pctldev, &soc->gpioranges[n]);757 758 return 0;759}760 761/*762 * mvebu_pinctrl_simple_mmio_probe - probe a simple mmio pinctrl763 * @pdev: platform device (with platform data already attached)764 *765 * Initialise a simple (single base address) mmio pinctrl driver,766 * assigning the MMIO base address to all mvebu mpp ctrl instances.767 */768int mvebu_pinctrl_simple_mmio_probe(struct platform_device *pdev)769{770 struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev);771 struct mvebu_mpp_ctrl_data *mpp_data;772 void __iomem *base;773 int i;774 775 base = devm_platform_ioremap_resource(pdev, 0);776 if (IS_ERR(base))777 return PTR_ERR(base);778 779 mpp_data = devm_kcalloc(&pdev->dev, soc->ncontrols, sizeof(*mpp_data),780 GFP_KERNEL);781 if (!mpp_data)782 return -ENOMEM;783 784 for (i = 0; i < soc->ncontrols; i++)785 mpp_data[i].base = base;786 787 soc->control_data = mpp_data;788 789 return mvebu_pinctrl_probe(pdev);790}791 792int mvebu_regmap_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,793 unsigned int pid, unsigned long *config)794{795 unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;796 unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;797 unsigned int val;798 int err;799 800 err = regmap_read(data->regmap.map, data->regmap.offset + off, &val);801 if (err)802 return err;803 804 *config = (val >> shift) & MVEBU_MPP_MASK;805 806 return 0;807}808 809int mvebu_regmap_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,810 unsigned int pid, unsigned long config)811{812 unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;813 unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;814 815 return regmap_update_bits(data->regmap.map, data->regmap.offset + off,816 MVEBU_MPP_MASK << shift, config << shift);817}818 819int mvebu_pinctrl_simple_regmap_probe(struct platform_device *pdev,820 struct device *syscon_dev, u32 offset)821{822 struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev);823 struct mvebu_mpp_ctrl_data *mpp_data;824 struct regmap *regmap;825 int i;826 827 regmap = syscon_node_to_regmap(syscon_dev->of_node);828 if (IS_ERR(regmap))829 return PTR_ERR(regmap);830 831 mpp_data = devm_kcalloc(&pdev->dev, soc->ncontrols, sizeof(*mpp_data),832 GFP_KERNEL);833 if (!mpp_data)834 return -ENOMEM;835 836 for (i = 0; i < soc->ncontrols; i++) {837 mpp_data[i].regmap.map = regmap;838 mpp_data[i].regmap.offset = offset;839 }840 841 soc->control_data = mpp_data;842 843 return mvebu_pinctrl_probe(pdev);844}845