[PATCH 04/14] OF: pinctrl: MIPS: lantiq: implement lantiq/xway pinctrl support

Linus Walleij linus.walleij at linaro.org
Tue May 8 23:21:33 EST 2012


On Fri, May 4, 2012 at 2:18 PM, John Crispin <blogic at openwrt.org> wrote:

> Implement support for pinctrl on lantiq/xway socs. The IO core found on these
> socs has the registers for pinctrl, pinconf and gpio mixed up in the same
> register range. As the gpio_chip handling is only a few lines, the driver also
> implements the gpio functionality. This obseletes the old gpio driver that was
> located in the arch/ folder.
>
> Signed-off-by: John Crispin <blogic at openwrt.org>
> Cc: devicetree-discuss at lists.ozlabs.org
> Cc: Linus Walleij <linus.walleij at linaro.org>
> Cc: Stephen Warren <swarren at wwwdotorg.org>

Overall this is looking very good and a positive development for these SoCs.

Nitpicking below.

> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -216,6 +216,7 @@ config MACH_JZ4740
>  config LANTIQ
>        bool "Lantiq based platforms"
>        select DMA_NONCOHERENT
> +       select PINCTRL

Shouldn't this be:
select PINCTRL
select PINCTRL_LANTIQ

?

> diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
> index 9485fe5..b86d942 100644
> --- a/arch/mips/lantiq/Kconfig
> +++ b/arch/mips/lantiq/Kconfig
> @@ -2,6 +2,7 @@ if LANTIQ
>
>  config SOC_TYPE_XWAY
>        bool
> +       select PINCTRL_XWAY
>        default n

OK...

> -obj-y := prom.o pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o dma.o
> +obj-y := prom.o pmu.o ebu.o reset.o gpio_stp.o gpio_ebu.o dma.o

Yeah good riddance :-)

> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> index f73a5ea..a19bac96 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -30,6 +30,11 @@ config PINCTRL_PXA3xx
>        bool
>        select PINMUX
>
> +config PINCTRL_LANTIQ
> +       bool
> +       select PINMUX
> +       select PINCONF

depends on LANTIQ

?

I don't think anyone else is going to want to compile
this.

> +
>  config PINCTRL_MMP2
>        bool "MMP2 pin controller driver"
>        depends on ARCH_MMP
> @@ -83,6 +88,10 @@ config PINCTRL_COH901
>          COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
>          ports of 8 GPIO pins each.
>
> +config PINCTRL_XWAY
> +       bool
> +       select PINCTRL_LANTIQ

Shouldn't this be:

depends on SOC_TYPE_XWAY
depends on PINCTRL_LANTIQ

?

So LANTIQ selects it's pinctrl driver, the the xway SoC
selects its driver and they both are dependent on their
respective system.

> diff --git a/drivers/pinctrl/pinctrl-lantiq.h b/drivers/pinctrl/pinctrl-lantiq.h

> +#define ARRAY_AND_SIZE(x)      (x), ARRAY_SIZE(x)

Hm if we redefine this I start to wonder if this
should go into <linux/kernel.h>

No big deal, we can alsway refactor later.

> +#define LTQ_PINCONF_PACK(_param_, _arg_)       ((_param_) << 16 | (_arg_))
> +#define LTQ_PINCONF_UNPACK_PARAM(_conf_)       ((_conf_) >> 16)
> +#define LTQ_PINCONF_UNPACK_ARG(_conf_)         ((_conf_) & 0xffff)

No need to add _underscores_ around the macro parameters?
I've not seen any coding convention requiring this.

> +struct ltq_pinmux_info {
> +       struct device *dev;
> +       struct pinctrl_dev *pctrl;
> +
> +       /* we need to manage up to 5 padcontrolers */

controllers

> +       void __iomem *membase[5];
> +
> +       /* the handler for the subsystem */
> +       struct pinctrl_desc *desc;

It's a descriptor not a handler.

> +       /* we expose our pads to the subsystem */
> +       struct pinctrl_pin_desc *pads;
> +
> +       /* the number of pads. this varies between socs */
> +       unsigned int num_gpio;

Why not call it num_pads, atleast use the same name for
the array and the count.

> +       /* these are our multifunction pins */
> +       const struct ltq_mfp_pin *mfp;
> +       unsigned int num_mfp;
> +
> +       /* a number of multifunction pins can be grouped together */
> +       const struct ltq_pin_group *grps;
> +       unsigned int num_grps;
> +
> +       /* a mapping between function string and id */
> +       const struct ltq_pmx_func *funcs;
> +       unsigned int num_funcs;
> +
> +       /* the pinconf options that we are able to read from the DT */
> +       const struct ltq_cfg_param *params;
> +       unsigned int num_params;
> +
> +       /* soc specific callback used to apply muxing */
> +       int (*apply_mux)(struct pinctrl_dev *pctrldev, int pin, int mux);
> +};
>
> +enum ltq_pin_list {
> +       GPIO0 = 0,
> +       GPIO1,

Wait, this enum is called something ending with _list but it's not
a list, it's a pin. The enum is like a type, so should define the basic
unit we're dealing with, not a collection of such units, so rename it
"ltq_pin" simply.

You could also consider using:
#define GPIO0 0
#define GPIO1 1

etc like some other drivers do. (Your pick.)

> diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c

> +/* macros to help us access the registers */
> +#define gpio_getbit(m, r, p)   (!!(ltq_r32(m + r) & (1 << p)))
> +#define gpio_setbit(m, r, p)   ltq_w32_mask(0, (1 << p), m + r)
> +#define gpio_clearbit(m, r, p) ltq_w32_mask((1 << p), 0, m + r)

So what makes this arch so fantastic that it needs its own read/write functions?
(Just curious...)

You could replace (1 << p) with BIT(p) by using <linux/bitops.h>

> +       {"pci",         ARRAY_AND_SIZE(xrx_pci_grps)},
> +       {"ebu",         ARRAY_AND_SIZE(xrx_ebu_grps)},
> +};
> +
> +
> +
> +
> +
> +

You can never get enough whitespace :-)

Please trim it down...

> +/* ---------  pinconf related code --------- */
> +static int xway_pinconf_group_get(struct pinctrl_dev *pctldev,
> +                               unsigned group,
> +                               unsigned long *config)
> +{
> +       return -ENOTSUPP;
> +}
> +
> +static int xway_pinconf_group_set(struct pinctrl_dev *pctldev,
> +                               unsigned group,
> +                               unsigned long config)
> +{
> +       return -ENOTSUPP;
> +}

Just don't define these function pointers and leave callbacks as NULL.
The pinctrl core should handle this and if it doesn't, patch the core
in pinconf.c.

> +static void xway_pinconf_dbg_show(struct pinctrl_dev *pctldev,
> +                                       struct seq_file *s, unsigned offset)
> +{
> +}
> +
> +static void xway_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
> +                                       struct seq_file *s, unsigned selector)
> +{
> +}

Just don't define them if you don't use them, leave pointers as NULL.

These are however good for verbose pretty-printing the pins/groups
hardware state.

> +static inline int xway_mux_apply(struct pinctrl_dev *pctrldev,
> +                               int pin, int mux)
> +{
> +       struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
> +       int port = PORT(pin);
> +
> +       if (mux & 0x1)
> +               gpio_setbit(info->membase[0], GPIO_ALT0(pin), PORT_PIN(pin));
> +       else
> +               gpio_clearbit(info->membase[0], GPIO_ALT0(pin), PORT_PIN(pin));
> +
> +       if ((port == 3) && (mux & 0x2))
> +               gpio_setbit(info->membase[0], GPIO3_ALT1, PORT_PIN(pin));
> +       else if (mux & 0x2)
> +               gpio_setbit(info->membase[0], GPIO_ALT1(pin), PORT_PIN(pin));
> +       else if (port == 3)
> +               gpio_clearbit(info->membase[0], GPIO3_ALT1, PORT_PIN(pin));
> +       else
> +               gpio_clearbit(info->membase[0], GPIO_ALT1(pin), PORT_PIN(pin));
> +
> +       return 0;
> +}

Please introduce some #defines for the magic numbers used above:

0x1, 3, 0x2, 3, etc so we can easily figure out what's going on.

> +static struct ltq_pinmux_info xway_info = {
> +       .mfp            = xway_mfp,
> +       .desc           = &xway_pctrl_desc,
> +       .apply_mux      = xway_mux_apply,
> +       .params         = xway_cfg_params,
> +       .num_params     = ARRAY_SIZE(xway_cfg_params),
> +};
> +
> +
> +
> +

Whitespacey...

> +/* ---------  gpio_chip related code --------- */
> +
> +int gpio_to_irq(unsigned int gpio)
> +{
> +       return -EINVAL;
> +}
> +EXPORT_SYMBOL(gpio_to_irq);
> +
> +int irq_to_gpio(unsigned int gpio)
> +{
> +       return -EINVAL;
> +}
> +EXPORT_SYMBOL(irq_to_gpio);

Can't you just leave them undefined?

> +static struct gpio_chip xway_chip = {
> +       .label = "gpio-xway",
> +       .direction_input = xway_gpio_dir_in,
> +       .direction_output = xway_gpio_dir_out,
> +       .get = xway_gpio_get,
> +       .set = xway_gpio_set,
> +       .request = xway_gpio_req,
> +       .free = xway_gpio_free,
> +       .base = 0,
> +};
> +
> +
> +
> +

Whitespace.

Yours,
Linus Walleij


More information about the devicetree-discuss mailing list