All of lore.kernel.org
 help / color / mirror / Atom feed
From: linus.walleij@linaro.org (Linus Walleij)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 3/7] pinctrl: imx1 core driver
Date: Wed, 7 Aug 2013 21:25:35 +0200	[thread overview]
Message-ID: <CACRpkdabJnjo5i-NGS-sTb3dqQQ9xQa_CdUY=+a1rpaAfF7rhQ@mail.gmail.com> (raw)
In-Reply-To: <1375439907-10462-4-git-send-email-mpa@pengutronix.de>

On Fri, Aug 2, 2013 at 12:38 PM, Markus Pargmann <mpa@pengutronix.de> wrote:

> Signed-off-by: Markus Pargmann <mpa@pengutronix.de>

I think you need a bit of patch description here. Zero lines of
commit message is not acceptable for an entire new driver.
Elaborate a bit on the imx27 hardware and so on.

> +/*
> + * Calculates the register offset from a pin_id
> + */
> +static void __iomem *imx1_mem(struct imx1_pinctrl *ipctl, unsigned int pin_id)
> +{
> +       unsigned int port = pin_id / 32;
> +       return ipctl->base + port * 0x100;

Use this:
#define IMX1_PORT_STRIDE 0x100

> +/*
> + * Write to a register with 2 bits per pin. The function will automatically
> + * use the next register if the pin is managed in the second register.
> + */
> +static void imx1_write_2bit(struct imx1_pinctrl *ipctl, unsigned int pin_id,
> +               u32 value, u32 reg_offset)
> +{
> +       void __iomem *reg = imx1_mem(ipctl, pin_id) + reg_offset;
> +       int shift = (pin_id % 16) * 2;
> +       int mask = ~(0x3 << shift);

I think I understand this, but insert a comment on what this is
anyway.

> +       u32 old_value;
> +
> +       dev_dbg(ipctl->dev, "write: register 0x%p shift %d value 0x%x\n",
> +                       reg, shift, value);
> +
> +       if (pin_id % 32 >= 16)
> +               reg += 0x04;

Comment on what is happening here.

> +
> +       value = (value & 0x11) << shift;

What is this? 0x11? Shall this be #defined or
what does it mean? The "value" argument really needs
some documentation I think.

You're modifying the argument "value" which is confusing.
Try to avoid this.

> +       old_value = readl(reg) & mask;
> +       writel(value | old_value, reg);

This is a bit over-complicating things. Write out
the sequence and let the compiler do the optimization.

val = readl(reg);
val &= mask;
val |= value;
writel(val, reg);


> +static void imx1_write_bit(struct imx1_pinctrl *ipctl, unsigned int pin_id,
> +               u32 value, u32 reg_offset)
> +{
> +       void __iomem *reg = imx1_mem(ipctl, pin_id) + reg_offset;
> +       int shift = pin_id % 32;
> +       int mask = ~(0x1 << shift);
> +       u32 old_value;
> +
> +       dev_dbg(ipctl->dev, "write: register 0x%p shift %d value 0x%x\n",
> +                       reg, shift, value);
> +
> +       value = (value & 0x1) << shift;
> +       old_value = readl(reg) & mask;
> +       writel(value | old_value, reg);

Same comments here.

> +static int imx1_read_bit(struct imx1_pinctrl *ipctl, unsigned int pin_id,
> +               u32 reg_offset)
> +{
> +       void __iomem *reg = imx1_mem(ipctl, pin_id) + reg_offset;
> +       int shift = pin_id % 32;
> +
> +       return (readl(reg) >> shift) & 0x1;

Hard to read. Can't you just do this?

#include <linux/bitops.h>

u32 offset = pin_id % 32;

return !!(readl(reg) & BIT(offset));

> +static void imx1_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
> +                  unsigned offset)
> +{
> +       seq_printf(s, "%s", dev_name(pctldev->dev));
> +}

Don't you want to print some other more interesting things about
each pin?

This template is really just an example. The debugfs file is
intended to be helpful.

> +static int imx1_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
> +                          unsigned group)
> +{
> +       struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
> +       const struct imx_pinctrl_soc_info *info = ipctl->info;
> +       const unsigned *pins, *mux;
> +       unsigned int npins;
> +       int i;
> +
> +       /*
> +        * Configure the mux mode for each pin in the group for a specific
> +        * function.
> +        */
> +       pins = info->groups[group].pins;
> +       npins = info->groups[group].npins;
> +       mux = info->groups[group].mux_mode;
> +
> +       WARN_ON(!pins || !npins || !mux);
> +
> +       dev_dbg(ipctl->dev, "enable function %s group %s\n",
> +               info->functions[selector].name, info->groups[group].name);
> +
> +       for (i = 0; i < npins; i++) {
> +               unsigned int pin_id = pins[i];
> +               unsigned int afunction = 0x001 & mux[i];
> +               unsigned int gpio_in_use = (0x002 & mux[i]) >> 1;
> +               unsigned int direction = (0x004 & mux[i]) >> 2;
> +               unsigned int gpio_oconf = (0x030 & mux[i]) >> 4;
> +               unsigned int gpio_iconfa = (0x300 & mux[i]) >> 8;
> +               unsigned int gpio_iconfb = (0xc00 & mux[i]) >> 10;

If you use <linux/bitops.h> this can be made more understandable,
BIT(0), BIT(1), BIT(2) etc.

The shift offsets should be #defined.

> +static void imx1_pinconf_dbg_show(struct pinctrl_dev *pctldev,
> +                                  struct seq_file *s, unsigned pin_id)
> +{
> +       struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
> +       const struct imx_pinctrl_soc_info *info = ipctl->info;
> +       const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
> +       unsigned long config;
> +
> +       if (!pin_reg || !pin_reg->conf_reg) {
> +               seq_puts(s, "N/A");
> +               return;
> +       }
> +
> +       config = readl(ipctl->base + pin_reg->conf_reg);
> +       seq_printf(s, "0x%lx", config);
> +}

That's pretty helpful, nice!

> +static int imx1_pinctrl_parse_gpio(struct platform_device *pdev,
> +               struct imx1_pinctrl *pctl, struct device_node *np, int i,
> +               u32 base)
> +{
> +       int ret;
> +       u32 memoffset;
> +
> +       ret = of_property_read_u32(np, "reg", &memoffset);
> +       if (ret)
> +               return ret;
> +
> +       memoffset -= base;
> +       pctl->gpio_pdata[i].base = pctl->base + memoffset;
> +
> +       pctl->gpio_dev[i] = of_device_alloc(np, NULL, &pdev->dev);
> +       pctl->gpio_dev[i]->dev.platform_data = &pctl->gpio_pdata[i];
> +       pctl->gpio_dev[i]->dev.bus = &platform_bus_type;
> +
> +       ret = of_device_add(pctl->gpio_dev[i]);
> +       if (ret) {
> +               dev_err(&pdev->dev,
> +                               "Failed to add child gpio device\n");
> +               return ret;
> +       }
> +       return 0;
> +}

As mentioned for the other patch I think this is the wrong approach.
Try to make the GPIO driver wholly independent.

Yours,
Linus Walleij

  parent reply	other threads:[~2013-08-07 19:25 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-02 10:38 [PATCH 0/7] ARM: imx27 pinctrl Markus Pargmann
2013-08-02 10:38 ` [PATCH 1/7] gpio: mxc: Support initialization as subdevice Markus Pargmann
2013-08-07 19:03   ` Linus Walleij
2013-08-09 17:56     ` Markus Pargmann
2013-08-02 10:38 ` [PATCH 2/7] pinctrl: imx header, conditional probe functions Markus Pargmann
2013-08-05  5:43   ` Shawn Guo
2013-08-09 13:31     ` Markus Pargmann
2013-08-02 10:38 ` [PATCH 3/7] pinctrl: imx1 core driver Markus Pargmann
2013-08-02 10:51   ` Alexander Shiyan
2013-08-02 10:54     ` Markus Pargmann
2013-08-05  9:29   ` Sascha Hauer
2013-08-09 18:16     ` Markus Pargmann
2013-08-07 19:25   ` Linus Walleij [this message]
2013-08-09 19:33     ` Markus Pargmann
2013-08-02 10:38 ` [PATCH 4/7] pinctrl: imx27: imx27 pincontrol driver Markus Pargmann
2013-08-05  6:12   ` Shawn Guo
2013-08-09 13:46     ` Markus Pargmann
2013-08-02 10:38 ` [PATCH 5/7] ARM: dts: imx27 pin functions Markus Pargmann
2013-08-05  6:14   ` Shawn Guo
2013-08-02 10:38 ` [PATCH 6/7] ARM: dts: imx27 pinctrl Markus Pargmann
2013-08-05  6:18   ` Shawn Guo
2013-08-09 13:54     ` Markus Pargmann
2013-08-02 10:38 ` [PATCH 7/7] ARM: imx27: enable pinctrl Markus Pargmann

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='CACRpkdabJnjo5i-NGS-sTb3dqQQ9xQa_CdUY=+a1rpaAfF7rhQ@mail.gmail.com' \
    --to=linus.walleij@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.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.