uboot/drivers/pinctrl/pinctrl_stm32.c
<<
>>
Prefs
   1#include <common.h>
   2#include <dm.h>
   3#include <dm/pinctrl.h>
   4#include <asm/arch/gpio.h>
   5#include <asm/gpio.h>
   6#include <asm/io.h>
   7
   8DECLARE_GLOBAL_DATA_PTR;
   9
  10#define MAX_PINS_ONE_IP                 70
  11#define MODE_BITS_MASK                  3
  12#define OSPEED_MASK                     3
  13#define PUPD_MASK                       3
  14#define OTYPE_MSK                       1
  15#define AFR_MASK                        0xF
  16
  17static int stm32_gpio_config(struct gpio_desc *desc,
  18                             const struct stm32_gpio_ctl *ctl)
  19{
  20        struct stm32_gpio_priv *priv = dev_get_priv(desc->dev);
  21        struct stm32_gpio_regs *regs = priv->regs;
  22        u32 index;
  23
  24        if (!ctl || ctl->af > 15 || ctl->mode > 3 || ctl->otype > 1 ||
  25            ctl->pupd > 2 || ctl->speed > 3)
  26                return -EINVAL;
  27
  28        index = (desc->offset & 0x07) * 4;
  29        clrsetbits_le32(&regs->afr[desc->offset >> 3], AFR_MASK << index,
  30                        ctl->af << index);
  31
  32        index = desc->offset * 2;
  33        clrsetbits_le32(&regs->moder, MODE_BITS_MASK << index,
  34                        ctl->mode << index);
  35        clrsetbits_le32(&regs->ospeedr, OSPEED_MASK << index,
  36                        ctl->speed << index);
  37        clrsetbits_le32(&regs->pupdr, PUPD_MASK << index, ctl->pupd << index);
  38
  39        index = desc->offset;
  40        clrsetbits_le32(&regs->otyper, OTYPE_MSK << index, ctl->otype << index);
  41
  42        return 0;
  43}
  44static int prep_gpio_dsc(struct stm32_gpio_dsc *gpio_dsc, u32 port_pin)
  45{
  46        gpio_dsc->port = (port_pin & 0xF000) >> 12;
  47        gpio_dsc->pin = (port_pin & 0x0F00) >> 8;
  48        debug("%s: GPIO:port= %d, pin= %d\n", __func__, gpio_dsc->port,
  49              gpio_dsc->pin);
  50
  51        return 0;
  52}
  53
  54static int prep_gpio_ctl(struct stm32_gpio_ctl *gpio_ctl, u32 gpio_fn, int node)
  55{
  56        gpio_fn &= 0x00FF;
  57        gpio_ctl->af = 0;
  58
  59        switch (gpio_fn) {
  60        case 0:
  61                gpio_ctl->mode = STM32_GPIO_MODE_IN;
  62                break;
  63        case 1 ... 16:
  64                gpio_ctl->mode = STM32_GPIO_MODE_AF;
  65                gpio_ctl->af = gpio_fn - 1;
  66                break;
  67        case 17:
  68                gpio_ctl->mode = STM32_GPIO_MODE_AN;
  69                break;
  70        default:
  71                gpio_ctl->mode = STM32_GPIO_MODE_OUT;
  72                break;
  73        }
  74
  75        gpio_ctl->speed = fdtdec_get_int(gd->fdt_blob, node, "slew-rate", 0);
  76
  77        if (fdtdec_get_bool(gd->fdt_blob, node, "drive-open-drain"))
  78                gpio_ctl->otype = STM32_GPIO_OTYPE_OD;
  79        else
  80                gpio_ctl->otype = STM32_GPIO_OTYPE_PP;
  81
  82        if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-up"))
  83                gpio_ctl->pupd = STM32_GPIO_PUPD_UP;
  84        else if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-down"))
  85                gpio_ctl->pupd = STM32_GPIO_PUPD_DOWN;
  86        else
  87                gpio_ctl->pupd = STM32_GPIO_PUPD_NO;
  88
  89        debug("%s: gpio fn= %d, slew-rate= %x, op type= %x, pull-upd is = %x\n",
  90              __func__,  gpio_fn, gpio_ctl->speed, gpio_ctl->otype,
  91             gpio_ctl->pupd);
  92
  93        return 0;
  94}
  95
  96static int stm32_pinctrl_set_state_simple(struct udevice *dev,
  97                                          struct udevice *periph)
  98{
  99        u32 pin_mux[MAX_PINS_ONE_IP];
 100        struct fdtdec_phandle_args args;
 101        int rv, len;
 102
 103        /* Get node pinctrl-0 */
 104        rv = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(periph),
 105                                           "pinctrl-0", 0, 0, 0, &args);
 106        if (rv)
 107                return rv;
 108        /*
 109         * check for "pinmux" property in each subnode (e.g. pins1 and pins2 for
 110         * usart1) of pin controller phandle "pinctrl-0"
 111         * */
 112        fdt_for_each_subnode(args.node, gd->fdt_blob, args.node) {
 113                struct stm32_gpio_dsc gpio_dsc;
 114                struct stm32_gpio_ctl gpio_ctl;
 115                int i;
 116
 117                len = fdtdec_get_int_array_count(gd->fdt_blob, args.node,
 118                                                 "pinmux", pin_mux,
 119                                                 ARRAY_SIZE(pin_mux));
 120                debug("%s: periph->name = %s, no of pinmux entries= %d\n",
 121                      __func__, periph->name, len);
 122                if (len < 0)
 123                        return -EINVAL;
 124                for (i = 0; i < len; i++) {
 125                        struct gpio_desc desc;
 126                        debug("%s: pinmux = %x\n", __func__, *(pin_mux + i));
 127                        prep_gpio_dsc(&gpio_dsc, *(pin_mux + i));
 128                        prep_gpio_ctl(&gpio_ctl, *(pin_mux + i), args.node);
 129                        rv = uclass_get_device_by_seq(UCLASS_GPIO,
 130                                                      gpio_dsc.port, &desc.dev);
 131                        if (rv)
 132                                return rv;
 133                        desc.offset = gpio_dsc.pin;
 134                        rv = stm32_gpio_config(&desc, &gpio_ctl);
 135                        debug("%s: rv = %d\n\n", __func__, rv);
 136                        if (rv)
 137                                return rv;
 138                }
 139        }
 140
 141        return 0;
 142}
 143
 144static struct pinctrl_ops stm32_pinctrl_ops = {
 145        .set_state_simple       = stm32_pinctrl_set_state_simple,
 146};
 147
 148static const struct udevice_id stm32_pinctrl_ids[] = {
 149        { .compatible = "st,stm32f746-pinctrl" },
 150        { }
 151};
 152
 153U_BOOT_DRIVER(pinctrl_stm32) = {
 154        .name           = "pinctrl_stm32",
 155        .id             = UCLASS_PINCTRL,
 156        .of_match       = stm32_pinctrl_ids,
 157        .ops            = &stm32_pinctrl_ops,
 158        .bind           = dm_scan_fdt_dev,
 159};
 160