diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2015-12-15 14:52:16 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2015-12-15 14:52:16 -0300 |
commit | 8d91c1e411f55d7ea91b1183a2e9f8088fb4d5be (patch) | |
tree | e9891aa6c295060d065adffd610c4f49ecf884f3 /drivers/pinctrl/sh-pfc/pinctrl.c | |
parent | a71852147516bc1cb5b0b3cbd13639bfd4022dc8 (diff) |
Linux-libre 4.3.2-gnu
Diffstat (limited to 'drivers/pinctrl/sh-pfc/pinctrl.c')
-rw-r--r-- | drivers/pinctrl/sh-pfc/pinctrl.c | 86 |
1 files changed, 76 insertions, 10 deletions
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c index ff6789660..863c3e30c 100644 --- a/drivers/pinctrl/sh-pfc/pinctrl.c +++ b/drivers/pinctrl/sh-pfc/pinctrl.c @@ -40,6 +40,10 @@ struct sh_pfc_pinctrl { struct pinctrl_pin_desc *pins; struct sh_pfc_pin_config *configs; + + const char *func_prop_name; + const char *groups_prop_name; + const char *pins_prop_name; }; static int sh_pfc_get_groups_count(struct pinctrl_dev *pctldev) @@ -96,10 +100,13 @@ static int sh_pfc_map_add_config(struct pinctrl_map *map, return 0; } -static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np, +static int sh_pfc_dt_subnode_to_map(struct pinctrl_dev *pctldev, + struct device_node *np, struct pinctrl_map **map, unsigned int *num_maps, unsigned int *index) { + struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); + struct device *dev = pmx->pfc->dev; struct pinctrl_map *maps = *map; unsigned int nmaps = *num_maps; unsigned int idx = *index; @@ -113,10 +120,27 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np, const char *pin; int ret; + /* Support both the old Renesas-specific properties and the new standard + * properties. Mixing old and new properties isn't allowed, neither + * inside a subnode nor across subnodes. + */ + if (!pmx->func_prop_name) { + if (of_find_property(np, "groups", NULL) || + of_find_property(np, "pins", NULL)) { + pmx->func_prop_name = "function"; + pmx->groups_prop_name = "groups"; + pmx->pins_prop_name = "pins"; + } else { + pmx->func_prop_name = "renesas,function"; + pmx->groups_prop_name = "renesas,groups"; + pmx->pins_prop_name = "renesas,pins"; + } + } + /* Parse the function and configuration properties. At least a function * or one configuration must be specified. */ - ret = of_property_read_string(np, "renesas,function", &function); + ret = of_property_read_string(np, pmx->func_prop_name, &function); if (ret < 0 && ret != -EINVAL) { dev_err(dev, "Invalid function in DT\n"); return ret; @@ -129,11 +153,12 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np, if (!function && num_configs == 0) { dev_err(dev, "DT node must contain at least a function or config\n"); + ret = -ENODEV; goto done; } /* Count the number of pins and groups and reallocate mappings. */ - ret = of_property_count_strings(np, "renesas,pins"); + ret = of_property_count_strings(np, pmx->pins_prop_name); if (ret == -EINVAL) { num_pins = 0; } else if (ret < 0) { @@ -143,7 +168,7 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np, num_pins = ret; } - ret = of_property_count_strings(np, "renesas,groups"); + ret = of_property_count_strings(np, pmx->groups_prop_name); if (ret == -EINVAL) { num_groups = 0; } else if (ret < 0) { @@ -174,7 +199,7 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np, *num_maps = nmaps; /* Iterate over pins and groups and create the mappings. */ - of_property_for_each_string(np, "renesas,groups", prop, group) { + of_property_for_each_string(np, pmx->groups_prop_name, prop, group) { if (function) { maps[idx].type = PIN_MAP_TYPE_MUX_GROUP; maps[idx].data.mux.group = group; @@ -198,7 +223,7 @@ static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np, goto done; } - of_property_for_each_string(np, "renesas,pins", prop, pin) { + of_property_for_each_string(np, pmx->pins_prop_name, prop, pin) { ret = sh_pfc_map_add_config(&maps[idx], pin, PIN_MAP_TYPE_CONFIGS_PIN, configs, num_configs); @@ -246,7 +271,7 @@ static int sh_pfc_dt_node_to_map(struct pinctrl_dev *pctldev, index = 0; for_each_child_of_node(np, child) { - ret = sh_pfc_dt_subnode_to_map(dev, child, map, num_maps, + ret = sh_pfc_dt_subnode_to_map(pctldev, child, map, num_maps, &index); if (ret < 0) goto done; @@ -254,7 +279,8 @@ static int sh_pfc_dt_node_to_map(struct pinctrl_dev *pctldev, /* If no mapping has been found in child nodes try the config node. */ if (*num_maps == 0) { - ret = sh_pfc_dt_subnode_to_map(dev, np, map, num_maps, &index); + ret = sh_pfc_dt_subnode_to_map(pctldev, np, map, num_maps, + &index); if (ret < 0) goto done; } @@ -465,6 +491,9 @@ static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin, case PIN_CONFIG_BIAS_PULL_DOWN: return pin->configs & SH_PFC_PIN_CFG_PULL_DOWN; + case PIN_CONFIG_POWER_SOURCE: + return pin->configs & SH_PFC_PIN_CFG_IO_VOLTAGE; + default: return false; } @@ -477,7 +506,6 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin, struct sh_pfc *pfc = pmx->pfc; enum pin_config_param param = pinconf_to_config_param(*config); unsigned long flags; - unsigned int bias; if (!sh_pfc_pinconf_validate(pfc, _pin, param)) return -ENOTSUPP; @@ -485,7 +513,9 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin, switch (param) { case PIN_CONFIG_BIAS_DISABLE: case PIN_CONFIG_BIAS_PULL_UP: - case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_DOWN: { + unsigned int bias; + if (!pfc->info->ops || !pfc->info->ops->get_bias) return -ENOTSUPP; @@ -498,6 +528,24 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin, *config = 0; break; + } + + case PIN_CONFIG_POWER_SOURCE: { + int ret; + + if (!pfc->info->ops || !pfc->info->ops->get_io_voltage) + return -ENOTSUPP; + + spin_lock_irqsave(&pfc->lock, flags); + ret = pfc->info->ops->get_io_voltage(pfc, _pin); + spin_unlock_irqrestore(&pfc->lock, flags); + + if (ret < 0) + return ret; + + *config = ret; + break; + } default: return -ENOTSUPP; @@ -534,6 +582,24 @@ static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin, break; + case PIN_CONFIG_POWER_SOURCE: { + unsigned int arg = + pinconf_to_config_argument(configs[i]); + int ret; + + if (!pfc->info->ops || !pfc->info->ops->set_io_voltage) + return -ENOTSUPP; + + spin_lock_irqsave(&pfc->lock, flags); + ret = pfc->info->ops->set_io_voltage(pfc, _pin, arg); + spin_unlock_irqrestore(&pfc->lock, flags); + + if (ret) + return ret; + + break; + } + default: return -ENOTSUPP; } |