[PATCH v2 6/9] pinctrl-tz1090: add TZ1090 pinctrl driver
Linus Walleij
linus.walleij at linaro.org
Tue May 28 16:48:57 EST 2013
Hi James, I want to route this patch by Laurent Pinchart, as he's also
adding device tree support for a SoC using generic pinconf.
Creating new bindings for every pin controller defining the same thing
and implementing the same OF parsers is not sane.
We need to:
- Define generic pinconf bindings
- Implement a common parser for these in drivers/pinctrl/pinconf-generic.c
I'll merge your patches to <linux/pinctrl/pinctrl-generic.h> as a
baseline.
On Fri, May 24, 2013 at 6:21 PM, James Hogan <james.hogan at imgtec.com> wrote:
(...)
> +Optional subnode-properties:
> +- function: A string containing the name of the function to mux to the pin or
> + group. Valid values for function names are listed below, including which
> + pingroups can be muxed to them.
> +- tristate: Flag, put pin into high impedance state.
> +- pull-up: Flag, pull pin high.
> +- pull-down: Flag, pull pin low.
> +- bus-hold: Flag, weak latch last value on tristate bus.
> +- schmitt: Integer, enable or disable Schmitt trigger mode for the pins.
> + 0: no hysteresis
> + 1: schmitt trigger
> +- slew-rate: Integer, control slew rate of pins.
> + 0: slow (half frequency)
> + 1: fast
> +- drive-strength: Integer, control drive strength of pins in mA.
> + 2: 2mA
> + 4: 4mA
> + 8: 8mA
> + 12: 12mA
So if you want to use these names they shall be made generic.
Else you have to prefix everything with "tz1090,<property>"
> +/* Describes pinconf properties/flags available from device tree */
> +static const struct cfg_param {
> + const char *property;
> + enum pin_config_param param;
> + bool flag;
> +} cfg_params[] = {
> + {"tristate", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, true},
> + {"pull-up", PIN_CONFIG_BIAS_PULL_UP, true},
> + {"pull-down", PIN_CONFIG_BIAS_PULL_DOWN, true},
> + {"bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, true},
> + {"schmitt", PIN_CONFIG_INPUT_SCHMITT_ENABLE, true},
> + {"slew-rate", PIN_CONFIG_SLEW_RATE, false},
> + {"drive-strength", PIN_CONFIG_DRIVE_STRENGTH, false},
> +};
> +
> +int tz1090_pinctrl_dt_subnode_to_map(struct device *dev,
> + struct device_node *np,
> + struct pinctrl_map **map,
> + unsigned *reserved_maps,
> + unsigned *num_maps)
> +{
> + int ret, i;
> + const char *function;
> + u32 val;
> + unsigned long config;
> + unsigned long *configs = NULL;
> + unsigned num_configs = 0;
> + unsigned reserve;
> + struct property *prop;
> + const char *group;
> +
> + ret = of_property_read_string(np, "function", &function);
> + if (ret < 0) {
> + /* EINVAL=missing, which is fine since it's optional */
> + if (ret != -EINVAL)
> + dev_err(dev, "could not parse property function\n");
> + function = NULL;
> + }
> +
> + for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
> + ret = of_property_read_u32(np, cfg_params[i].property, &val);
> + /* flags don't have to have a value */
> + if (ret == -EOVERFLOW && cfg_params[i].flag) {
> + val = 1;
> + ret = 0;
> + }
> + if (!ret) {
> + config = pinconf_to_config_packed(cfg_params[i].param,
> + val);
> + ret = add_config(dev, &configs, &num_configs, config);
> + if (ret < 0)
> + goto exit;
> + /* EINVAL=missing, which is fine since it's optional */
> + } else if (ret != -EINVAL) {
> + dev_err(dev, "could not parse property %s (%d)\n",
> + cfg_params[i].property, ret);
> + }
> + }
> +
> + reserve = 0;
> + if (function != NULL)
> + reserve++;
> + if (num_configs)
> + reserve++;
> + ret = of_property_count_strings(np, "pins");
> + if (ret < 0) {
> + dev_err(dev, "could not parse property pins\n");
> + goto exit;
> + }
> + reserve *= ret;
> +
> + ret = reserve_map(dev, map, reserved_maps, num_maps, reserve);
> + if (ret < 0)
> + goto exit;
> +
> + of_property_for_each_string(np, "pins", prop, group) {
> + if (function) {
> + ret = add_map_mux(map, reserved_maps, num_maps,
> + group, function);
> + if (ret < 0)
> + goto exit;
> + }
> +
> + if (num_configs) {
> + ret = add_map_configs(dev, map, reserved_maps,
> + num_maps, group, configs,
> + num_configs);
> + if (ret < 0)
> + goto exit;
> + }
> + }
> +
> + ret = 0;
> +
> +exit:
> + kfree(configs);
> + return ret;
> +}
This is looking good. Can you split out the pin config mapping in
some way and put that into pinconf-generic.c?
Yours,
Linus Walleij
More information about the devicetree-discuss
mailing list