All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bjorn Andersson <bjorn.andersson@sonymobile.com>
To: "Ivan T. Ivanov" <iivanov@mm-sol.com>
Cc: Linus Walleij <linus.walleij@linaro.org>,
	Grant Likely <grant.likely@linaro.org>,
	Rob Herring <robh+dt@kernel.org>,
	David Collins <collinsd@codeaurora.org>,
	Wu Fenglin <fenglinw@qti.qualcomm.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
	"linux-arm-msm@vger.kernel.org" <linux-arm-msm@vger.kernel.org>
Subject: Re: [PATCH v4 3/4] pinctrl: Qualcomm SPMI PMIC GPIO pin controller driver
Date: Tue, 23 Sep 2014 21:18:53 -0700	[thread overview]
Message-ID: <20140924041852.GO10179@sonymobile.com> (raw)
In-Reply-To: <1410792254-24126-4-git-send-email-iivanov@mm-sol.com>

On Mon 15 Sep 07:44 PDT 2014, Ivan T. Ivanov wrote:

> This is the pinctrl, pinmux, pinconf and gpiolib driver for the
> Qualcomm GPIO sub-function blocks found in the PMIC chips.
> 
> Signed-off-by: Ivan T. Ivanov <iivanov@mm-sol.com>

I think this looks pretty good, just some minor comments. Mostly on the future
compatibility of the Kconfig and compatible.

It's much in line with what I hacked up for pm8xxx, I was just hoping to get
something from Thomas regarding irq_read_line() before pushing it again...

> ---
>  drivers/pinctrl/qcom/Kconfig                  |  12 +
>  drivers/pinctrl/qcom/Makefile                 |   1 +
>  drivers/pinctrl/qcom/pinctrl-spmi-pmic-gpio.c | 942 ++++++++++++++++++++++++++
>  3 files changed, 955 insertions(+)
>  create mode 100644 drivers/pinctrl/qcom/pinctrl-spmi-pmic-gpio.c
> 
> diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
> index d160a71..123248f 100644
> --- a/drivers/pinctrl/qcom/Kconfig
> +++ b/drivers/pinctrl/qcom/Kconfig
> @@ -39,4 +39,16 @@ config PINCTRL_MSM8X74
>           This is the pinctrl, pinmux, pinconf and gpiolib driver for the
>           Qualcomm TLMM block found in the Qualcomm 8974 platform.
> 
> +config PINCTRL_SPMI_PMIC

As SPMI is a MIPI specification for doing power management I think it's safe to
assume that this is not going to be the only "spmi pmic" pinctrl driver.
So please make this a little bit more specific by throwing in a QCOM here.

> +       tristate "Qualcomm SPMI PMIC pin controller driver"
> +       depends on GPIOLIB && OF
> +       select PINMUX
> +       select PINCONF
> +       select GENERIC_PINCONF
> +       help
> +         This is the pinctrl, pinmux, pinconf and gpiolib driver for the
> +         Qualcomm GPIO and MPP blocks found in the Qualcomm PMIC's chips,
> +         which are using SPMI for communication with SoC. Example PMIC's
> +         devices are pm8841, pm8941 and pma8084.
> +
>  endif
> diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
> index 2a02602..396130c 100644
> --- a/drivers/pinctrl/qcom/Makefile
> +++ b/drivers/pinctrl/qcom/Makefile
> @@ -4,3 +4,4 @@ obj-$(CONFIG_PINCTRL_APQ8064)   += pinctrl-apq8064.o
>  obj-$(CONFIG_PINCTRL_IPQ8064)  += pinctrl-ipq8064.o
>  obj-$(CONFIG_PINCTRL_MSM8960)  += pinctrl-msm8960.o
>  obj-$(CONFIG_PINCTRL_MSM8X74)  += pinctrl-msm8x74.o
> +obj-$(CONFIG_PINCTRL_SPMI_PMIC)        += pinctrl-spmi-pmic-gpio.o
> diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-pmic-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-pmic-gpio.c
> new file mode 100644
> index 0000000..493f0d3
> --- /dev/null
> +++ b/drivers/pinctrl/qcom/pinctrl-spmi-pmic-gpio.c

This is fine, no need to change as we have qcom in the path...

[..]
> +
> +/**
> + * struct pmic_gpio_pad - keep current GPIO settings

Some indentation in this table would be nice.
Content look sane though.

> + * @base: Address base in SPMI device.
> + * @irq: IRQ number which this GPIO generate.
> + * @is_enabled: Set to false when GPIO should be put in high Z state.
> + * @out_value: Cached pin output value
> + * @have_buffer: Set to true if GPIO output could be configured in push-pull,
> + *     open-drain or open-source mode.
> + * @output_enabled: Set to true if GPIO output logic is enabled.
> + * @input_enabled: Set to true if GPIO input buffer logic is enabled.
> + * @num_sources: Number of power-sources supported by this GPIO.
> + * @power_source: Current power-source used.
> + * @buffer_type: Push-pull, open-drain or open-source.
> + * @pullup: Constant current which flow trough GPIO output buffer.
> + * @strength: No, Low, Medium, High
> + * @function: See pmic_gpio_functions[]
> + */
> +struct pmic_gpio_pad {
> +       u16 base;
> +       int irq;
> +       bool is_enabled;
> +       bool out_value;
> +       bool have_buffer;
> +       bool output_enabled;
> +       bool input_enabled;
> +       unsigned int num_sources;
> +       unsigned int power_source;
> +       unsigned int buffer_type;
> +       unsigned int pullup;
> +       unsigned int strength;
> +       unsigned int function;
> +};
> +
[..]
> +
> +static int pmic_gpio_parse_dt_config(struct device_node *np,
> +                                    struct pinctrl_dev *pctldev,
> +                                    unsigned long **configs,
> +                                    unsigned int *nconfs)
> +{
> +       struct pmic_gpio_bindings *par;
> +       unsigned long cfg;
> +       int ret, i;
> +       u32 val;
> +
> +       for (i = 0; i < ARRAY_SIZE(pmic_gpio_bindings); i++) {
> +

Empty line

> +               par = &pmic_gpio_bindings[i];
> +               ret = of_property_read_u32(np, par->property, &val);
> +
> +               /* property not found */
> +               if (ret == -EINVAL)
> +                       continue;
> +
> +               /* use zero as default value */
> +               if (ret)
> +                       val = 0;
> +
> +               dev_dbg(pctldev->dev, "found %s with value %u\n",
> +                       par->property, val);
> +
> +               cfg = pinconf_to_config_packed(par->param, val);
> +
> +               ret = pinctrl_utils_add_config(pctldev, configs, nconfs, cfg);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       return 0;
> +}
> +
[..]
> +
> +static int pmic_gpio_dt_node_to_map(struct pinctrl_dev *pctldev,
> +                                   struct device_node *np_config,
> +                                   struct pinctrl_map **map, unsigned *nmaps)
> +{
> +       enum pinctrl_map_type type;
> +       struct device_node *np;
> +       unsigned reserv;
> +       int ret;
> +
> +       ret = 0;
> +       *map = NULL;
> +       *nmaps = 0;
> +       reserv = 0;
> +       type = PIN_MAP_TYPE_CONFIGS_GROUP;
> +
> +       for_each_child_of_node(np_config, np) {
> +

Empty line

> +               ret = pinconf_generic_dt_subnode_to_map(pctldev, np, map,
> +                                                       &reserv, nmaps, type);
> +               if (ret)
> +                       break;
> +
> +               ret = pmic_gpio_dt_subnode_to_map(pctldev, np, map, &reserv,
> +                                                 nmaps, type);
> +               if (ret)
> +                       break;
> +       }
> +
> +       if (ret < 0)
> +               pinctrl_utils_dt_free_map(pctldev, *map, *nmaps);
> +
> +       return ret;
> +}
> +
[..]
> +
> +static int pmic_gpio_config_get(struct pinctrl_dev *pctldev,
> +                               unsigned int pin, unsigned long *config)
> +{
> +       unsigned param = pinconf_to_config_param(*config);
> +       struct pmic_gpio_pad *pad;
> +       unsigned arg;
> +
> +       pad = pctldev->desc->pins[pin].drv_data;
> +
> +       switch (param) {
> +       case PIN_CONFIG_DRIVE_PUSH_PULL:
> +               arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_CMOS;
> +               break;
> +       case PIN_CONFIG_DRIVE_OPEN_DRAIN:
> +               arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS;
> +               break;
> +       case PIN_CONFIG_DRIVE_OPEN_SOURCE:
> +               arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS;
> +               break;
> +       case PIN_CONFIG_BIAS_PULL_DOWN:
> +               arg = pad->pullup == PMIC_GPIO_PULL_DOWN;
> +               break;
> +       case PIN_CONFIG_BIAS_DISABLE:
> +               arg = pad->pullup = PMIC_GPIO_PULL_DISABLE;
> +               break;
> +       case PIN_CONFIG_BIAS_PULL_UP:
> +               arg = pad->pullup == PMIC_GPIO_PULL_UP_30;
> +               break;

Extra break;

> +               break;
> +       case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
> +               arg = !pad->is_enabled;
> +               break;
> +       case PIN_CONFIG_POWER_SOURCE:
> +               arg = pad->power_source;
> +               break;
> +       case PIN_CONFIG_INPUT_ENABLE:
> +               arg = pad->input_enabled;
> +               break;
> +       case PIN_CONFIG_OUTPUT:
> +               arg = pad->out_value;
> +               break;
> +       case PMIC_GPIO_CONF_PULL_UP:
> +               arg = pad->pullup;
> +               break;
> +       case PMIC_GPIO_CONF_STRENGTH:
> +               arg = pad->strength;
> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +
> +       *config = pinconf_to_config_packed(param, arg);
> +       return 0;
> +}
> +
[..]
> +static int pmic_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
> +{
> +       struct pmic_gpio_state *state;
> +       unsigned long config;
> +
> +       state = container_of(chip, struct pmic_gpio_state, chip);

You use this container_of plenty of times, consider breaking it out to a
to_gpio_state() helper function and you can fit it on the declaration line.

> +       config = pinconf_to_config_packed(PIN_CONFIG_INPUT_ENABLE, 1);
> +
> +       return pmic_gpio_config_set(state->ctrl, pin, &config, 1);
> +}
> +
[..]
> +
> +static int pmic_gpio_of_xlate(struct gpio_chip *chip,
> +                             const struct of_phandle_args *gpio_desc,
> +                             u32 *flags)
> +{
> +       if (chip->of_gpio_n_cells < 2)
> +               return -EINVAL;
> +
> +       if (flags)
> +               *flags = gpio_desc->args[1];
> +
> +       return gpio_desc->args[0] - PMIC_GPIO_PHYSICAL_OFFSET;
> +}

If you change:
 gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins);
to:
 gpiochip_add_pin_range(&state->chip, dev_name(dev), 1, 0, npins);

And you treat the gpio functions as taking the gpio number instead of pinctrl
number (i.e. subtract 1 in those), then gpiolib will provide this function for
you.

[..]
> +
> +static const struct of_device_id pmic_gpio_of_match[] = {
> +       { .compatible = "qcom,spmi-pmic-gpio" },

I think this should be more specific, because hopefully the spmi specification
will outlive the current pmic gpio block.

So I think you need to list the pmic blocks here (e.g. "qcom,pm8941-gpio").

> +       { },
> +};
> +
> +MODULE_DEVICE_TABLE(of, pmic_gpio_of_match);
> +
> +static struct platform_driver pmic_gpio_driver = {
> +       .driver = {
> +                  .name = "spmi-pmic-gpio",

The name should include "qcom" as well, to make it less prone to collisions.

> +                  .owner = THIS_MODULE,

owner filled in for you by module_platform_driver()

> +                  .of_match_table = pmic_gpio_of_match,
> +       },
> +       .probe  = pmic_gpio_probe,
> +       .remove = pmic_gpio_remove,
> +};
> +
> +module_platform_driver(pmic_gpio_driver);
> +

Regards,
Bjorn

  reply	other threads:[~2014-09-24  4:18 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-15 14:44 [PATCH v4 0/4] Qualcomm SPMI PMIC pin controller drivers Ivan T. Ivanov
2014-09-15 14:44 ` [PATCH v4 1/4] pinctrl: Device tree bindings for Qualcomm PMIC GPIO block Ivan T. Ivanov
2014-09-15 14:44 ` [PATCH v4 2/4] pinctrl: Device tree bindings for Qualcomm PMIC MPP block Ivan T. Ivanov
2014-09-15 14:44 ` [PATCH v4 3/4] pinctrl: Qualcomm SPMI PMIC GPIO pin controller driver Ivan T. Ivanov
2014-09-24  4:18   ` Bjorn Andersson [this message]
2014-09-24  8:14     ` Ivan T. Ivanov
2014-09-24 13:09     ` Ivan T. Ivanov
2014-09-30 17:02       ` Bjorn Andersson
2014-10-07 14:14         ` Linus Walleij
2014-09-15 14:44 ` [PATCH v4 4/4] pinctrl: Qualcomm SPMI PMIC MPP " Ivan T. Ivanov
2014-09-23 15:16 ` [PATCH v4 0/4] Qualcomm SPMI PMIC pin controller drivers Linus Walleij

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140924041852.GO10179@sonymobile.com \
    --to=bjorn.andersson@sonymobile.com \
    --cc=collinsd@codeaurora.org \
    --cc=devicetree@vger.kernel.org \
    --cc=fenglinw@qti.qualcomm.com \
    --cc=grant.likely@linaro.org \
    --cc=iivanov@mm-sol.com \
    --cc=linus.walleij@linaro.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=robh+dt@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.