summaryrefslogtreecommitdiff
path: root/drivers/pinctrl/pinctrl-tz1090.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/pinctrl-tz1090.c')
-rw-r--r--drivers/pinctrl/pinctrl-tz1090.c140
1 files changed, 80 insertions, 60 deletions
diff --git a/drivers/pinctrl/pinctrl-tz1090.c b/drivers/pinctrl/pinctrl-tz1090.c
index 72d955252e41..bc9cd7a7602e 100644
--- a/drivers/pinctrl/pinctrl-tz1090.c
+++ b/drivers/pinctrl/pinctrl-tz1090.c
@@ -1762,39 +1762,46 @@ static int tz1090_pinconf_get(struct pinctrl_dev *pctldev,
}
static int tz1090_pinconf_set(struct pinctrl_dev *pctldev,
- unsigned int pin, unsigned long config)
+ unsigned int pin, unsigned long *configs,
+ unsigned num_configs)
{
struct tz1090_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
- enum pin_config_param param = pinconf_to_config_param(config);
- unsigned int arg = pinconf_to_config_argument(config);
+ enum pin_config_param param;
+ unsigned int arg;
int ret;
u32 reg, width, mask, shift, val, tmp;
unsigned long flags;
+ int i;
- dev_dbg(pctldev->dev, "%s(pin=%s, config=%#lx)\n",
- __func__, tz1090_pins[pin].name, config);
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
- /* Get register information */
- ret = tz1090_pinconf_reg(pctldev, pin, param, true,
- &reg, &width, &mask, &shift, &val);
- if (ret < 0)
- return ret;
+ dev_dbg(pctldev->dev, "%s(pin=%s, config=%#lx)\n",
+ __func__, tz1090_pins[pin].name, configs[i]);
- /* Unpack argument and range check it */
- if (arg > 1) {
- dev_dbg(pctldev->dev, "%s: arg %u out of range\n",
- __func__, arg);
- return -EINVAL;
- }
+ /* Get register information */
+ ret = tz1090_pinconf_reg(pctldev, pin, param, true,
+ &reg, &width, &mask, &shift, &val);
+ if (ret < 0)
+ return ret;
- /* Write register field */
- __global_lock2(flags);
- tmp = pmx_read(pmx, reg);
- tmp &= ~mask;
- if (arg)
- tmp |= val << shift;
- pmx_write(pmx, tmp, reg);
- __global_unlock2(flags);
+ /* Unpack argument and range check it */
+ if (arg > 1) {
+ dev_dbg(pctldev->dev, "%s: arg %u out of range\n",
+ __func__, arg);
+ return -EINVAL;
+ }
+
+ /* Write register field */
+ __global_lock2(flags);
+ tmp = pmx_read(pmx, reg);
+ tmp &= ~mask;
+ if (arg)
+ tmp |= val << shift;
+ pmx_write(pmx, tmp, reg);
+ __global_unlock2(flags);
+ } /* for each config */
return 0;
}
@@ -1894,68 +1901,81 @@ static int tz1090_pinconf_group_get(struct pinctrl_dev *pctldev,
}
static int tz1090_pinconf_group_set(struct pinctrl_dev *pctldev,
- unsigned int group, unsigned long config)
+ unsigned int group, unsigned long *configs,
+ unsigned num_configs)
{
struct tz1090_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
const struct tz1090_pingroup *g;
- enum pin_config_param param = pinconf_to_config_param(config);
+ enum pin_config_param param;
unsigned int arg, pin, i;
const unsigned int *pit;
int ret;
u32 reg, width, mask, shift, val;
unsigned long flags;
const int *map;
+ int j;
if (group >= ARRAY_SIZE(tz1090_groups)) {
pin = group - ARRAY_SIZE(tz1090_groups);
- return tz1090_pinconf_set(pctldev, pin, config);
+ return tz1090_pinconf_set(pctldev, pin, configs, num_configs);
}
g = &tz1090_groups[group];
if (g->npins == 1) {
pin = g->pins[0];
- ret = tz1090_pinconf_set(pctldev, pin, config);
+ ret = tz1090_pinconf_set(pctldev, pin, configs, num_configs);
if (ret != -ENOTSUPP)
return ret;
}
- dev_dbg(pctldev->dev, "%s(group=%s, config=%#lx)\n",
- __func__, g->name, config);
+ for (j = 0; j < num_configs; j++) {
+ param = pinconf_to_config_param(configs[j]);
- /* Get register information */
- ret = tz1090_pinconf_group_reg(pctldev, g, param, true,
- &reg, &width, &mask, &shift, &map);
- if (ret < 0) {
- /*
- * Maybe we're trying to set a per-pin configuration of a group,
- * so do the pins one by one. This is mainly as a convenience.
- */
- for (i = 0, pit = g->pins; i < g->npins; ++i, ++pit) {
- ret = tz1090_pinconf_set(pctldev, *pit, config);
- if (ret)
- return ret;
- }
- return 0;
- }
+ dev_dbg(pctldev->dev, "%s(group=%s, config=%#lx)\n",
+ __func__, g->name, configs[j]);
- /* Unpack argument and map it to register value */
- arg = pinconf_to_config_argument(config);
- for (i = 0; i < BIT(width); ++i) {
- if (map[i] == arg || (map[i] == -EINVAL && !arg)) {
- /* Write register field */
- __global_lock2(flags);
- val = pmx_read(pmx, reg);
- val &= ~mask;
- val |= i << shift;
- pmx_write(pmx, val, reg);
- __global_unlock2(flags);
+ /* Get register information */
+ ret = tz1090_pinconf_group_reg(pctldev, g, param, true, &reg,
+ &width, &mask, &shift, &map);
+ if (ret < 0) {
+ /*
+ * Maybe we're trying to set a per-pin configuration
+ * of a group, so do the pins one by one. This is
+ * mainly as a convenience.
+ */
+ for (i = 0, pit = g->pins; i < g->npins; ++i, ++pit) {
+ ret = tz1090_pinconf_set(pctldev, *pit, configs,
+ num_configs);
+ if (ret)
+ return ret;
+ }
return 0;
}
- }
- dev_dbg(pctldev->dev, "%s: arg %u not supported\n",
- __func__, arg);
- return -EINVAL;
+ /* Unpack argument and map it to register value */
+ arg = pinconf_to_config_argument(configs[j]);
+ for (i = 0; i < BIT(width); ++i) {
+ if (map[i] == arg || (map[i] == -EINVAL && !arg)) {
+ /* Write register field */
+ __global_lock2(flags);
+ val = pmx_read(pmx, reg);
+ val &= ~mask;
+ val |= i << shift;
+ pmx_write(pmx, val, reg);
+ __global_unlock2(flags);
+ goto next_config;
+ }
+ }
+
+ dev_dbg(pctldev->dev, "%s: arg %u not supported\n",
+ __func__, arg);
+ return -EINVAL;
+
+next_config:
+ ;
+ } /* for each config */
+
+ return 0;
}
static struct pinconf_ops tz1090_pinconf_ops = {