[PATCH 1/2] pinctrl: at91: add pinctrl driver

Raphaël Poggi poggi.raph at gmail.com
Wed Aug 6 00:12:07 PDT 2014


Ok, let's do it like that

Best regards,
Raphaël Poggi

2014-08-06 5:48 GMT+02:00 Jean-Christophe PLAGNIOL-VILLARD
<plagnioj at jcrosoft.com>:
>
> On Aug 6, 2014, at 11:46 AM, Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com> wrote:
>
>>
>> On Aug 5, 2014, at 7:38 PM, Raphaël Poggi <raphio98 at gmail.com> wrote:
>>
>>>
>>> Ok, so I drop my patch ? Or your version is very similar of my patch
>>> and you can review mine to improve/clean it ?
>>
>> I’ve a patch series to have dt on at91, my patch for the pinctrl is not finish
>>
>
> sorry I mean my patch series is not yet fully clean
>
>> give me few days to send it and we see after
>>
>> Best Regards,
>> J.
>>>
>>> Best regards,
>>> Raphaël Poggi
>>>
>>> 2014-08-05 12:26 GMT+02:00 Jean-Christophe PLAGNIOL-VILLARD
>>> <plagnioj at jcrosoft.com>:
>>>>
>>>> On Aug 5, 2014, at 2:37 AM, Raphaël Poggi <raphio98 at gmail.com> wrote:
>>>>
>>>>>
>>>>> I have planned to add device tree support for the AT91 port.
>>>>>
>>>>> So I port the pinctrl driver from linux to barebox to be able to use
>>>>> the pinctrl in device tree, but maybe I made a mistake and there is
>>>>> another solution.
>>>>>
>>>>
>>>> I’ve a version already that I need to update and send
>>>>
>>>> Best Regards,
>>>> J.
>>>>> Best Regards,
>>>>> Raphaël
>>>>>
>>>>> 2014-08-04 20:26 GMT+02:00 Jean-Christophe PLAGNIOL-VILLARD
>>>>> <plagnioj at jcrosoft.com>:
>>>>>> why do we need it on barebox?
>>>>>>
>>>>>> this driver was design for dt-only in linux
>>>>>>
>>>>>> Best Regards,
>>>>>> J.
>>>>>> On Aug 1, 2014, at 9:24 PM, Raphaël Poggi <poggi.raph at gmail.com> wrote:
>>>>>>
>>>>>>> This driver is based on mach-at91/gpio.c and linux pinctrl driver.
>>>>>>> The driver contains the gpio and pinctrl parts (like in linux) because the two parts
>>>>>>> share some structures and logics.
>>>>>>>
>>>>>>> Signed-off-by: Raphaël Poggi <poggi.raph at gmail.com>
>>>>>>> ---
>>>>>>> drivers/pinctrl/Kconfig        |    6 +
>>>>>>> drivers/pinctrl/Makefile       |    1 +
>>>>>>> drivers/pinctrl/pinctrl-at91.c |  529 ++++++++++++++++++++++++++++++++++++++++
>>>>>>> drivers/pinctrl/pinctrl-at91.h |  148 +++++++++++
>>>>>>> 4 files changed, 684 insertions(+)
>>>>>>> create mode 100644 drivers/pinctrl/pinctrl-at91.c
>>>>>>> create mode 100644 drivers/pinctrl/pinctrl-at91.h
>>>>>>>
>>>>>>> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
>>>>>>> index dffaa4e..ce55c7b 100644
>>>>>>> --- a/drivers/pinctrl/Kconfig
>>>>>>> +++ b/drivers/pinctrl/Kconfig
>>>>>>> @@ -7,6 +7,12 @@ config PINCTRL
>>>>>>>      from the devicetree. Legacy drivers here may not need this core
>>>>>>>      support but instead provide their own SoC specific APIs
>>>>>>>
>>>>>>> +config PINCTRL_AT91
>>>>>>> +     select PINCTRL
>>>>>>> +     bool
>>>>>>> +     help
>>>>>>> +         The pinmux controller found on AT91 SoCs.
>>>>>>> +
>>>>>>> config PINCTRL_IMX_IOMUX_V1
>>>>>>>    select PINCTRL if OFDEVICE
>>>>>>>    bool
>>>>>>> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
>>>>>>> index 566ba11..3ea8649 100644
>>>>>>> --- a/drivers/pinctrl/Makefile
>>>>>>> +++ b/drivers/pinctrl/Makefile
>>>>>>> @@ -1,4 +1,5 @@
>>>>>>> obj-$(CONFIG_PINCTRL) += pinctrl.o
>>>>>>> +obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o
>>>>>>> obj-$(CONFIG_PINCTRL_IMX_IOMUX_V1) += imx-iomux-v1.o
>>>>>>> obj-$(CONFIG_PINCTRL_IMX_IOMUX_V2) += imx-iomux-v2.o
>>>>>>> obj-$(CONFIG_PINCTRL_IMX_IOMUX_V3) += imx-iomux-v3.o
>>>>>>> diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
>>>>>>> new file mode 100644
>>>>>>> index 0000000..a92a898
>>>>>>> --- /dev/null
>>>>>>> +++ b/drivers/pinctrl/pinctrl-at91.c
>>>>>>> @@ -0,0 +1,529 @@
>>>>>>> +/*
>>>>>>> + * Copyright (C) 2005 HP Labs
>>>>>>> + * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>
>>>>>>> + * Copyright (C) 2014 Raphaël Poggi
>>>>>>> + *
>>>>>>> + * See file CREDITS for list of people who contributed to this
>>>>>>> + * project.
>>>>>>> + *
>>>>>>> + * This program is free software; you can redistribute it and/or
>>>>>>> + * modify it under the terms of the GNU General Public License as
>>>>>>> + * published by the Free Software Foundation; either version 2 of
>>>>>>> + * the License, or (at your option) any later version.
>>>>>>> + *
>>>>>>> + * This program is distributed in the hope that it will be useful,
>>>>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>>>>>> + * GNU General Public License for more details.
>>>>>>> + *
>>>>>>> + */
>>>>>>> +
>>>>>>> +#include <common.h>
>>>>>>> +#include <command.h>
>>>>>>> +#include <complete.h>
>>>>>>> +#include <linux/clk.h>
>>>>>>> +#include <linux/err.h>
>>>>>>> +#include <errno.h>
>>>>>>> +#include <io.h>
>>>>>>> +#include <gpio.h>
>>>>>>> +#include <init.h>
>>>>>>> +#include <driver.h>
>>>>>>> +#include <getopt.h>
>>>>>>> +
>>>>>>> +#include <mach/at91_pio.h>
>>>>>>> +
>>>>>>> +#include <pinctrl.h>
>>>>>>> +
>>>>>>> +#include "pinctrl-at91.h"
>>>>>>> +
>>>>>>> +struct at91_pinctrl {
>>>>>>> +    struct pinctrl_device pctl;
>>>>>>> +    struct at91_pinctrl_mux_ops      *ops;
>>>>>>> +};
>>>>>>> +
>>>>>>> +struct at91_gpio_chip {
>>>>>>> +     struct gpio_chip        chip;
>>>>>>> +     void __iomem            *regbase;       /* PIO bank virtual address */
>>>>>>> +     struct at91_pinctrl_mux_ops *ops;       /* ops */
>>>>>>> +};
>>>>>>> +
>>>>>>> +enum at91_mux {
>>>>>>> +     AT91_MUX_GPIO = 0,
>>>>>>> +     AT91_MUX_PERIPH_A = 1,
>>>>>>> +     AT91_MUX_PERIPH_B = 2,
>>>>>>> +     AT91_MUX_PERIPH_C = 3,
>>>>>>> +     AT91_MUX_PERIPH_D = 4,
>>>>>>> +};
>>>>>>> +
>>>>>>> +#define MAX_GPIO_BANKS               5
>>>>>>> +#define to_at91_pinctrl(c) container_of(c, struct at91_pinctrl, pctl);
>>>>>>> +#define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip)
>>>>>>> +
>>>>>>> +#define PULL_UP         (1 << 0)
>>>>>>> +#define MULTI_DRIVE     (1 << 1)
>>>>>>> +#define DEGLITCH        (1 << 2)
>>>>>>> +#define PULL_DOWN       (1 << 3)
>>>>>>> +#define DIS_SCHMIT      (1 << 4)
>>>>>>> +#define DEBOUNCE        (1 << 16)
>>>>>>> +#define DEBOUNCE_VAL_SHIFT      17
>>>>>>> +#define DEBOUNCE_VAL    (0x3fff << DEBOUNCE_VAL_SHIFT)
>>>>>>> +
>>>>>>> +static int gpio_banks = 0;
>>>>>>> +
>>>>>>> +static struct at91_gpio_chip gpio_chip[MAX_GPIO_BANKS];
>>>>>>> +
>>>>>>> +static inline void __iomem *pin_to_controller(struct at91_pinctrl *info, unsigned pin)
>>>>>>> +{
>>>>>>> +     pin /= MAX_NB_GPIO_PER_BANK;
>>>>>>> +     if (likely(pin < gpio_banks))
>>>>>>> +             return gpio_chip[pin].regbase;
>>>>>>> +
>>>>>>> +     return NULL;
>>>>>>> +}
>>>>>>> +
>>>>>>> +/**
>>>>>>> + * struct at91_pinctrl_mux_ops - describes an At91 mux ops group
>>>>>>> + * on new IP with support for periph C and D the way to mux in
>>>>>>> + * periph A and B has changed
>>>>>>> + * So provide the right call back
>>>>>>> + * if not present means the IP does not support it
>>>>>>> + * @get_periph: return the periph mode configured
>>>>>>> + * @mux_A_periph: mux as periph A
>>>>>>> + * @mux_B_periph: mux as periph B
>>>>>>> + * @mux_C_periph: mux as periph C
>>>>>>> + * @mux_D_periph: mux as periph D
>>>>>>> + * @set_deglitch: enable/disable deglitch
>>>>>>> + * @set_debounce: enable/disable debounce
>>>>>>> + * @set_pulldown: enable/disable pulldown
>>>>>>> + * @disable_schmitt_trig: disable schmitt trigger
>>>>>>> + */
>>>>>>> +struct at91_pinctrl_mux_ops {
>>>>>>> +     enum at91_mux (*get_periph)(void __iomem *pio, unsigned mask);
>>>>>>> +     void (*mux_A_periph)(void __iomem *pio, unsigned mask);
>>>>>>> +     void (*mux_B_periph)(void __iomem *pio, unsigned mask);
>>>>>>> +     void (*mux_C_periph)(void __iomem *pio, unsigned mask);
>>>>>>> +     void (*mux_D_periph)(void __iomem *pio, unsigned mask);
>>>>>>> +     bool (*get_deglitch)(void __iomem *pio, unsigned pin);
>>>>>>> +     void (*set_deglitch)(void __iomem *pio, unsigned mask, bool in_on);
>>>>>>> +     bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
>>>>>>> +     void (*set_debounce)(void __iomem *pio, unsigned mask, bool in_on, u32 div);
>>>>>>> +     bool (*get_pulldown)(void __iomem *pio, unsigned pin);
>>>>>>> +     void (*set_pulldown)(void __iomem *pio, unsigned mask, bool in_on);
>>>>>>> +     bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
>>>>>>> +     void (*disable_schmitt_trig)(void __iomem *pio, unsigned mask);
>>>>>>> +};
>>>>>>> +
>>>>>>> +static enum at91_mux at91_mux_pio3_get_periph(void __iomem *pio, unsigned mask)
>>>>>>> +{
>>>>>>> +     unsigned select;
>>>>>>> +
>>>>>>> +     if (__raw_readl(pio + PIO_PSR) & mask)
>>>>>>> +             return AT91_MUX_GPIO;
>>>>>>> +
>>>>>>> +     select = !!(__raw_readl(pio + PIO_ABCDSR1) & mask);
>>>>>>> +     select |= (!!(__raw_readl(pio + PIO_ABCDSR2) & mask) << 1);
>>>>>>> +
>>>>>>> +     return select + 1;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static enum at91_mux at91_mux_get_periph(void __iomem *pio, unsigned mask)
>>>>>>> +{
>>>>>>> +     unsigned select;
>>>>>>> +
>>>>>>> +     if (__raw_readl(pio + PIO_PSR) & mask)
>>>>>>> +             return AT91_MUX_GPIO;
>>>>>>> +
>>>>>>> +     select = __raw_readl(pio + PIO_ABSR) & mask;
>>>>>>> +
>>>>>>> +     return select + 1;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static bool at91_mux_get_deglitch(void __iomem *pio, unsigned pin)
>>>>>>> +{
>>>>>>> +     return (__raw_readl(pio + PIO_IFSR) >> pin) & 0x1;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static bool at91_mux_pio3_get_debounce(void __iomem *pio, unsigned pin, u32 *div)
>>>>>>> +{
>>>>>>> +     *div = __raw_readl(pio + PIO_SCDR);
>>>>>>> +
>>>>>>> +     return (__raw_readl(pio + PIO_IFSCSR) >> pin) & 0x1;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static bool at91_mux_pio3_get_pulldown(void __iomem *pio, unsigned pin)
>>>>>>> +{
>>>>>>> +     return (__raw_readl(pio + PIO_PPDSR) >> pin) & 0x1;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static bool at91_mux_pio3_get_schmitt_trig(void __iomem *pio, unsigned pin)
>>>>>>> +{
>>>>>>> +     return (__raw_readl(pio + PIO_SCHMITT) >> pin) & 0x1;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static struct at91_pinctrl_mux_ops at91rm9200_ops = {
>>>>>>> +     .get_periph     = at91_mux_get_periph,
>>>>>>> +     .mux_A_periph   = at91_mux_set_A_periph,
>>>>>>> +     .mux_B_periph   = at91_mux_set_B_periph,
>>>>>>> +     .get_deglitch   = at91_mux_get_deglitch,
>>>>>>> +     .set_deglitch   = at91_mux_set_deglitch,
>>>>>>> +};
>>>>>>> +
>>>>>>> +static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
>>>>>>> +     .get_periph     = at91_mux_pio3_get_periph,
>>>>>>> +     .mux_A_periph   = at91_mux_pio3_set_A_periph,
>>>>>>> +     .mux_B_periph   = at91_mux_pio3_set_B_periph,
>>>>>>> +     .mux_C_periph   = at91_mux_pio3_set_C_periph,
>>>>>>> +     .mux_D_periph   = at91_mux_pio3_set_D_periph,
>>>>>>> +     .get_deglitch   = at91_mux_get_deglitch,
>>>>>>> +     .set_deglitch   = at91_mux_pio3_set_deglitch,
>>>>>>> +     .get_debounce   = at91_mux_pio3_get_debounce,
>>>>>>> +     .set_debounce   = at91_mux_pio3_set_debounce,
>>>>>>> +     .get_pulldown   = at91_mux_pio3_get_pulldown,
>>>>>>> +     .set_pulldown   = at91_mux_pio3_set_pulldown,
>>>>>>> +     .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
>>>>>>> +     .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
>>>>>>> +};
>>>>>>> +
>>>>>>> +static int at91_mux_pin(struct at91_pinctrl *info, unsigned pin, enum at91_mux mux, int use_pullup)
>>>>>>> +{
>>>>>>> +     void __iomem    *pio = pin_to_controller(info, pin);
>>>>>>> +     unsigned mask = pin_to_mask(pin);
>>>>>>> +
>>>>>>> +     if (!info)
>>>>>>> +             return -EINVAL;
>>>>>>> +
>>>>>>> +     if (!pio)
>>>>>>> +             return -EINVAL;
>>>>>>> +
>>>>>>> +     at91_mux_disable_interrupt(pio, mask);
>>>>>>> +
>>>>>>> +     switch(mux) {
>>>>>>> +     case AT91_MUX_GPIO:
>>>>>>> +             at91_mux_gpio_enable(pio, mask);
>>>>>>> +             break;
>>>>>>> +     case AT91_MUX_PERIPH_A:
>>>>>>> +             info->ops->mux_A_periph(pio, mask);
>>>>>>> +             break;
>>>>>>> +     case AT91_MUX_PERIPH_B:
>>>>>>> +             info->ops->mux_B_periph(pio, mask);
>>>>>>> +             break;
>>>>>>> +     case AT91_MUX_PERIPH_C:
>>>>>>> +             if (!info->ops->mux_C_periph)
>>>>>>> +                     return -EINVAL;
>>>>>>> +             info->ops->mux_C_periph(pio, mask);
>>>>>>> +             break;
>>>>>>> +     case AT91_MUX_PERIPH_D:
>>>>>>> +             if (!info->ops->mux_D_periph)
>>>>>>> +                     return -EINVAL;
>>>>>>> +             info->ops->mux_D_periph(pio, mask);
>>>>>>> +             break;
>>>>>>> +     }
>>>>>>> +     if (mux)
>>>>>>> +             at91_mux_gpio_disable(pio, mask);
>>>>>>> +
>>>>>>> +     if (use_pullup >= 0)
>>>>>>> +             at91_mux_set_pullup(pio, mask, use_pullup);
>>>>>>> +
>>>>>>> +     return 0;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static struct of_device_id at91_pinctrl_dt_ids[] = {
>>>>>>> +     {
>>>>>>> +             .compatible = "atmel,at91rm9200-pinctrl",
>>>>>>> +             .data = (unsigned long)&at91rm9200_ops,
>>>>>>> +     }, {
>>>>>>> +             .compatible = "atmel,at91sam9x5-pinctrl",
>>>>>>> +             .data = (unsigned long)&at91sam9x5_ops,
>>>>>>> +     }, {
>>>>>>> +             /* sentinel */
>>>>>>> +     }
>>>>>>> +};
>>>>>>> +
>>>>>>> +static struct at91_pinctrl_mux_ops *at91_pinctrl_get_driver_data(struct device_d *dev)
>>>>>>> +{
>>>>>>> +    struct at91_pinctrl_mux_ops *ops_data = NULL;
>>>>>>> +    int rc;
>>>>>>> +
>>>>>>> +    if (dev->device_node) {
>>>>>>> +         const struct of_device_id *match;
>>>>>>> +         match = of_match_node(at91_pinctrl_dt_ids, dev->device_node);
>>>>>>> +         if (!match)
>>>>>>> +                     ops_data = NULL;
>>>>>>> +         else
>>>>>>> +                     ops_data = (struct at91_pinctrl_mux_ops *)match->data;
>>>>>>> +    }
>>>>>>> +    else {
>>>>>>> +         rc = dev_get_drvdata(dev, (unsigned long *)&ops_data);
>>>>>>> +             if (rc)
>>>>>>> +             ops_data = NULL;
>>>>>>> +    }
>>>>>>> +
>>>>>>> +    return ops_data;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static int at91_pinctrl_set_conf(struct at91_pinctrl *info, unsigned int pin_num, unsigned int mux, unsigned int conf)
>>>>>>> +{
>>>>>>> +     unsigned int mask;
>>>>>>> +     void __iomem *pio;
>>>>>>> +
>>>>>>> +     pio = pin_to_controller(info, pin_num);
>>>>>>> +     mask = pin_to_mask(pin_num);
>>>>>>> +
>>>>>>> +     if (conf & PULL_UP && conf & PULL_DOWN)
>>>>>>> +             return -EINVAL;
>>>>>>> +
>>>>>>> +     at91_mux_set_pullup(pio, mask, conf & PULL_UP);
>>>>>>> +     at91_mux_set_multidrive(pio, mask, conf & MULTI_DRIVE);
>>>>>>> +     if (info->ops->set_deglitch)
>>>>>>> +             info->ops->set_deglitch(pio, mask, conf & DEGLITCH);
>>>>>>> +     if (info->ops->set_debounce)
>>>>>>> +             info->ops->set_debounce(pio, mask, conf & DEBOUNCE,
>>>>>>> +                     (conf & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
>>>>>>> +     if (info->ops->set_pulldown)
>>>>>>> +             info->ops->set_pulldown(pio, mask, conf & PULL_DOWN);
>>>>>>> +     if (info->ops->disable_schmitt_trig && conf & DIS_SCHMIT)
>>>>>>> +             info->ops->disable_schmitt_trig(pio, mask);
>>>>>>> +
>>>>>>> +     return 0;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static int at91_pinctrl_set_state(struct pinctrl_device *pdev, struct device_node *np)
>>>>>>> +{
>>>>>>> +     struct at91_pinctrl *info;
>>>>>>> +     const __be32 *list;
>>>>>>> +     int i, size;
>>>>>>> +     int ret = 0;
>>>>>>> +     int bank_num, pin_num, mux, conf;
>>>>>>> +
>>>>>>> +     info = to_at91_pinctrl(pdev);
>>>>>>> +
>>>>>>> +     list = of_get_property(np, "atmel,pins", &size);
>>>>>>> +     size /= sizeof(*list);
>>>>>>> +
>>>>>>> +     if (!size || size % 4) {
>>>>>>> +             dev_err(pdev->dev, "wrong pins number or pins and configs should be by 4\n");
>>>>>>> +             return -EINVAL;
>>>>>>> +     }
>>>>>>> +
>>>>>>> +     for (i = 0; i < size; i += 4) {
>>>>>>> +             bank_num = be32_to_cpu(*list++);
>>>>>>> +             pin_num = be32_to_cpu(*list++);
>>>>>>> +             mux = be32_to_cpu(*list++);
>>>>>>> +             conf = be32_to_cpu(*list++);
>>>>>>> +
>>>>>>> +             ret = at91_mux_pin(info, pin_num, mux, conf & PULL_UP);
>>>>>>> +             if (ret) {
>>>>>>> +                     dev_err(pdev->dev, "failed to mux pin %d\n", pin_num);
>>>>>>> +                     return ret;
>>>>>>> +             }
>>>>>>> +
>>>>>>> +             ret = at91_pinctrl_set_conf(info, pin_num, mux, conf);
>>>>>>> +             if (ret) {
>>>>>>> +                     dev_err(pdev->dev, "failed to set conf on pin %d\n", pin_num);
>>>>>>> +                     return ret;
>>>>>>> +             }
>>>>>>> +     }
>>>>>>> +
>>>>>>> +     return ret;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static struct pinctrl_ops at91_pinctrl_ops = {
>>>>>>> +     .set_state = at91_pinctrl_set_state,
>>>>>>> +};
>>>>>>> +
>>>>>>> +static int at91_pinctrl_probe(struct device_d *dev)
>>>>>>> +{
>>>>>>> +     struct at91_pinctrl *info;
>>>>>>> +     int ret;
>>>>>>> +
>>>>>>> +     info = xzalloc(sizeof(struct at91_pinctrl));
>>>>>>> +
>>>>>>> +     info->ops = at91_pinctrl_get_driver_data(dev);
>>>>>>> +     if (!info->ops) {
>>>>>>> +             dev_err(dev, "failed to retrieve driver data\n");
>>>>>>> +             return -ENODEV;
>>>>>>> +     }
>>>>>>> +
>>>>>>> +     info->pctl.dev = dev;
>>>>>>> +     info->pctl.ops = &at91_pinctrl_ops;
>>>>>>> +
>>>>>>> +     ret = pinctrl_register(&info->pctl);
>>>>>>> +     if (ret)
>>>>>>> +             return ret;
>>>>>>> +
>>>>>>> +     dev_info(dev, "AT91 pinctrl registred\n");
>>>>>>> +
>>>>>>> +     return 0;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static struct platform_device_id at91_pinctrl_ids[] = {
>>>>>>> +     {
>>>>>>> +             .name = "at91rm9200-pinctrl",
>>>>>>> +             .driver_data = (unsigned long)&at91rm9200_ops,
>>>>>>> +     }, {
>>>>>>> +             .name = "at91sam9x5-pinctrl",
>>>>>>> +             .driver_data = (unsigned long)&at91sam9x5_ops,
>>>>>>> +     }, {
>>>>>>> +             /* sentinel */
>>>>>>> +     },
>>>>>>> +};
>>>>>>> +
>>>>>>> +static struct driver_d at91_pinctrl_driver = {
>>>>>>> +     .name = "pinctrl-at91",
>>>>>>> +     .probe = at91_pinctrl_probe,
>>>>>>> +     .id_table = at91_pinctrl_ids,
>>>>>>> +     .of_compatible = DRV_OF_COMPAT(at91_pinctrl_dt_ids),
>>>>>>> +};
>>>>>>> +
>>>>>>> +static int at91_pinctrl_init(void)
>>>>>>> +{
>>>>>>> +     return platform_driver_register(&at91_pinctrl_driver);
>>>>>>> +}
>>>>>>> +coredevice_initcall(at91_pinctrl_init);
>>>>>>> +
>>>>>>> +static int at91_gpio_get(struct gpio_chip *chip, unsigned offset)
>>>>>>> +{
>>>>>>> +     struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
>>>>>>> +     void __iomem *pio = at91_gpio->regbase;
>>>>>>> +     unsigned mask = 1 << offset;
>>>>>>> +
>>>>>>> +     return at91_mux_gpio_get(pio, mask);
>>>>>>> +}
>>>>>>> +
>>>>>>> +static void at91_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
>>>>>>> +{
>>>>>>> +     struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
>>>>>>> +     void __iomem *pio = at91_gpio->regbase;
>>>>>>> +     unsigned mask = 1 << offset;
>>>>>>> +
>>>>>>> +     at91_mux_gpio_set(pio, mask, value);
>>>>>>> +}
>>>>>>> +
>>>>>>> +static int at91_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
>>>>>>> +             int value)
>>>>>>> +{
>>>>>>> +     struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
>>>>>>> +     void __iomem *pio = at91_gpio->regbase;
>>>>>>> +     unsigned mask = 1 << offset;
>>>>>>> +
>>>>>>> +     at91_mux_gpio_set(pio, mask, value);
>>>>>>> +     __raw_writel(mask, pio + PIO_OER);
>>>>>>> +
>>>>>>> +     return 0;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static int at91_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
>>>>>>> +{
>>>>>>> +     struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
>>>>>>> +     void __iomem *pio = at91_gpio->regbase;
>>>>>>> +     unsigned mask = 1 << offset;
>>>>>>> +
>>>>>>> +     __raw_writel(mask, pio + PIO_ODR);
>>>>>>> +
>>>>>>> +     return 0;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static int at91_gpio_request(struct gpio_chip *chip, unsigned offset)
>>>>>>> +{
>>>>>>> +     struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
>>>>>>> +     void __iomem *pio = at91_gpio->regbase;
>>>>>>> +     unsigned mask = 1 << offset;
>>>>>>> +
>>>>>>> +     dev_dbg(chip->dev, "%s:%d pio%c%d(%d)\n", __func__, __LINE__,
>>>>>>> +              'A' + pin_to_bank(chip->base), offset, chip->base + offset);
>>>>>>> +     at91_mux_gpio_enable(pio, mask);
>>>>>>> +
>>>>>>> +     return 0;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static void at91_gpio_free(struct gpio_chip *chip, unsigned offset)
>>>>>>> +{
>>>>>>> +     dev_dbg(chip->dev, "%s:%d pio%c%d(%d)\n", __func__, __LINE__,
>>>>>>> +              'A' + pin_to_bank(chip->base), offset, chip->base + offset);
>>>>>>> +}
>>>>>>> +
>>>>>>> +static struct gpio_ops at91_gpio_ops = {
>>>>>>> +     .request = at91_gpio_request,
>>>>>>> +     .free = at91_gpio_free,
>>>>>>> +     .direction_input = at91_gpio_direction_input,
>>>>>>> +     .direction_output = at91_gpio_direction_output,
>>>>>>> +     .get = at91_gpio_get,
>>>>>>> +     .set = at91_gpio_set,
>>>>>>> +};
>>>>>>> +
>>>>>>> +static struct of_device_id at91_gpio_dt_ids[] = {
>>>>>>> +     {
>>>>>>> +             .compatible = "atmel,at91rm9200-gpio",
>>>>>>> +     }, {
>>>>>>> +             .compatible = "atmel,at91sam9x5-gpio",
>>>>>>> +     }, {
>>>>>>> +             /* sentinel */
>>>>>>> +     },
>>>>>>> +};
>>>>>>> +
>>>>>>> +static int at91_gpio_probe(struct device_d *dev)
>>>>>>> +{
>>>>>>> +     struct at91_gpio_chip *at91_gpio;
>>>>>>> +     struct clk *clk;
>>>>>>> +     int ret;
>>>>>>> +     int alias_idx = of_alias_get_id(dev->device_node, "gpio");
>>>>>>> +
>>>>>>> +     BUG_ON(dev->id > MAX_GPIO_BANKS);
>>>>>>> +
>>>>>>> +     at91_gpio = &gpio_chip[alias_idx];
>>>>>>> +
>>>>>>> +     clk = clk_get(dev, NULL);
>>>>>>> +     if (IS_ERR(clk)) {
>>>>>>> +             ret = PTR_ERR(clk);
>>>>>>> +             dev_err(dev, "clock not found: %d\n", ret);
>>>>>>> +             return ret;
>>>>>>> +     }
>>>>>>> +
>>>>>>> +     ret = clk_enable(clk);
>>>>>>> +     if (ret < 0) {
>>>>>>> +             dev_err(dev, "clock failed to enable: %d\n", ret);
>>>>>>> +             clk_put(clk);
>>>>>>> +             return ret;
>>>>>>> +     }
>>>>>>> +
>>>>>>> +     gpio_banks = max(gpio_banks, alias_idx + 1);
>>>>>>> +     at91_gpio->regbase = dev_request_mem_region(dev, 0);
>>>>>>> +
>>>>>>> +     at91_gpio->chip.ops = &at91_gpio_ops;
>>>>>>> +     at91_gpio->chip.ngpio = MAX_NB_GPIO_PER_BANK;
>>>>>>> +     at91_gpio->chip.dev = dev;
>>>>>>> +     at91_gpio->chip.base = dev->id * MAX_NB_GPIO_PER_BANK;
>>>>>>> +
>>>>>>> +     ret = gpiochip_add(&at91_gpio->chip);
>>>>>>> +     if (ret) {
>>>>>>> +             dev_err(dev, "couldn't add gpiochip, ret = %d\n", ret);
>>>>>>> +             return ret;
>>>>>>> +     }
>>>>>>> +
>>>>>>> +     dev_info(dev, "AT91 gpio driver registred\n");
>>>>>>> +
>>>>>>> +     return 0;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static struct platform_device_id at91_gpio_ids[] = {
>>>>>>> +     {
>>>>>>> +             .name = "at91rm9200-gpio",
>>>>>>> +     }, {
>>>>>>> +             .name = "at91sam9x5-gpio",
>>>>>>> +     }, {
>>>>>>> +             /* sentinel */
>>>>>>> +     },
>>>>>>> +};
>>>>>>> +
>>>>>>> +static struct driver_d at91_gpio_driver = {
>>>>>>> +     .name = "gpio-at91",
>>>>>>> +     .probe = at91_gpio_probe,
>>>>>>> +     .id_table = at91_gpio_ids,
>>>>>>> +     .of_compatible  = DRV_OF_COMPAT(at91_gpio_dt_ids),
>>>>>>> +};
>>>>>>> +
>>>>>>> +static int at91_gpio_init(void)
>>>>>>> +{
>>>>>>> +     return platform_driver_register(&at91_gpio_driver);
>>>>>>> +}
>>>>>>> +coredevice_initcall(at91_gpio_init);
>>>>>>> diff --git a/drivers/pinctrl/pinctrl-at91.h b/drivers/pinctrl/pinctrl-at91.h
>>>>>>> new file mode 100644
>>>>>>> index 0000000..e719fb8
>>>>>>> --- /dev/null
>>>>>>> +++ b/drivers/pinctrl/pinctrl-at91.h
>>>>>>> @@ -0,0 +1,148 @@
>>>>>>> +/*
>>>>>>> + * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>
>>>>>>> + *
>>>>>>> + * Under GPLv2 only
>>>>>>> + */
>>>>>>> +
>>>>>>> +#ifndef __AT91_GPIO_H__
>>>>>>> +#define __AT91_GPIO_H__
>>>>>>> +
>>>>>>> +#ifndef __gpio_init
>>>>>>> +#define __gpio_init
>>>>>>> +#endif
>>>>>>> +
>>>>>>> +#define MAX_NB_GPIO_PER_BANK 32
>>>>>>> +
>>>>>>> +static inline unsigned pin_to_bank(unsigned pin)
>>>>>>> +{
>>>>>>> +     return pin / MAX_NB_GPIO_PER_BANK;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline unsigned pin_to_bank_offset(unsigned pin)
>>>>>>> +{
>>>>>>> +     return pin % MAX_NB_GPIO_PER_BANK;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline unsigned pin_to_mask(unsigned pin)
>>>>>>> +{
>>>>>>> +     return 1 << pin_to_bank_offset(pin);
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_disable_interrupt(void __iomem *pio, unsigned mask)
>>>>>>> +{
>>>>>>> +     __raw_writel(mask, pio + PIO_IDR);
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_set_pullup(void __iomem *pio, unsigned mask, bool on)
>>>>>>> +{
>>>>>>> +     __raw_writel(mask, pio + (on ? PIO_PUER : PIO_PUDR));
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_set_multidrive(void __iomem *pio, unsigned mask, bool on)
>>>>>>> +{
>>>>>>> +     __raw_writel(mask, pio + (on ? PIO_MDER : PIO_MDDR));
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_set_A_periph(void __iomem *pio, unsigned mask)
>>>>>>> +{
>>>>>>> +     __raw_writel(mask, pio + PIO_ASR);
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_set_B_periph(void __iomem *pio, unsigned mask)
>>>>>>> +{
>>>>>>> +     __raw_writel(mask, pio + PIO_BSR);
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_pio3_set_A_periph(void __iomem *pio, unsigned mask)
>>>>>>> +{
>>>>>>> +
>>>>>>> +     __raw_writel(__raw_readl(pio + PIO_ABCDSR1) & ~mask,
>>>>>>> +                                             pio + PIO_ABCDSR1);
>>>>>>> +     __raw_writel(__raw_readl(pio + PIO_ABCDSR2) & ~mask,
>>>>>>> +                                             pio + PIO_ABCDSR2);
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_pio3_set_B_periph(void __iomem *pio, unsigned mask)
>>>>>>> +{
>>>>>>> +     __raw_writel(__raw_readl(pio + PIO_ABCDSR1) | mask,
>>>>>>> +                                             pio + PIO_ABCDSR1);
>>>>>>> +     __raw_writel(__raw_readl(pio + PIO_ABCDSR2) & ~mask,
>>>>>>> +                                             pio + PIO_ABCDSR2);
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_pio3_set_C_periph(void __iomem *pio, unsigned mask)
>>>>>>> +{
>>>>>>> +     __raw_writel(__raw_readl(pio + PIO_ABCDSR1) & ~mask, pio + PIO_ABCDSR1);
>>>>>>> +     __raw_writel(__raw_readl(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2);
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_pio3_set_D_periph(void __iomem *pio, unsigned mask)
>>>>>>> +{
>>>>>>> +     __raw_writel(__raw_readl(pio + PIO_ABCDSR1) | mask, pio + PIO_ABCDSR1);
>>>>>>> +     __raw_writel(__raw_readl(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2);
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
>>>>>>> +{
>>>>>>> +     __raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR));
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_pio3_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
>>>>>>> +{
>>>>>>> +     if (is_on)
>>>>>>> +             __raw_writel(mask, pio + PIO_IFSCDR);
>>>>>>> +     at91_mux_set_deglitch(pio, mask, is_on);
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_pio3_set_debounce(void __iomem *pio, unsigned mask,
>>>>>>> +                             bool is_on, u32 div)
>>>>>>> +{
>>>>>>> +     if (is_on) {
>>>>>>> +             __raw_writel(mask, pio + PIO_IFSCER);
>>>>>>> +             __raw_writel(div & PIO_SCDR_DIV, pio + PIO_SCDR);
>>>>>>> +             __raw_writel(mask, pio + PIO_IFER);
>>>>>>> +     } else {
>>>>>>> +             __raw_writel(mask, pio + PIO_IFDR);
>>>>>>> +     }
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is_on)
>>>>>>> +{
>>>>>>> +     __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio, unsigned mask)
>>>>>>> +{
>>>>>>> +     __raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_gpio_disable(void __iomem *pio, unsigned mask)
>>>>>>> +{
>>>>>>> +     __raw_writel(mask, pio + PIO_PDR);
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_gpio_enable(void __iomem *pio, unsigned mask)
>>>>>>> +{
>>>>>>> +     __raw_writel(mask, pio + PIO_PER);
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_gpio_input(void __iomem *pio, unsigned mask, bool input)
>>>>>>> +{
>>>>>>> +     __raw_writel(mask, pio + (input ? PIO_ODR : PIO_OER));
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline void at91_mux_gpio_set(void __iomem *pio, unsigned mask,
>>>>>>> +int value)
>>>>>>> +{
>>>>>>> +     __raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
>>>>>>> +}
>>>>>>> +
>>>>>>> +static inline int at91_mux_gpio_get(void __iomem *pio, unsigned mask)
>>>>>>> +{
>>>>>>> +       u32 pdsr;
>>>>>>> +
>>>>>>> +       pdsr = __raw_readl(pio + PIO_PDSR);
>>>>>>> +       return (pdsr & mask) != 0;
>>>>>>> +}
>>>>>>> +
>>>>>>> +#endif /* __AT91_GPIO_H__ */
>>>>>>> --
>>>>>>> 1.7.9.5
>>>>>>>
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> barebox mailing list
>>>>>>> barebox at lists.infradead.org
>>>>>>> http://lists.infradead.org/mailman/listinfo/barebox
>>>>>>
>>>>>>
>>>>>> _______________________________________________
>>>>>> barebox mailing list
>>>>>> barebox at lists.infradead.org
>>>>>> http://lists.infradead.org/mailman/listinfo/barebox
>>>>
>>
>



More information about the barebox mailing list