uboot/drivers/gpio/stm32_gpio.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2011
   3 * Yuri Tikhonov, Emcraft Systems, yur@emcraft.com
   4 *
   5 * (C) Copyright 2015
   6 * Kamil Lulko, <kamil.lulko@gmail.com>
   7 *
   8 * Copyright 2015 ATS Advanced Telematics Systems GmbH
   9 * Copyright 2015 Konsulko Group, Matt Porter <mporter@konsulko.com>
  10 *
  11 * SPDX-License-Identifier:     GPL-2.0+
  12 */
  13
  14#include <common.h>
  15#include <asm/io.h>
  16#include <linux/errno.h>
  17#include <asm/arch/stm32.h>
  18#include <asm/arch/gpio.h>
  19
  20DECLARE_GLOBAL_DATA_PTR;
  21
  22#if defined(CONFIG_STM32F4) || defined(CONFIG_STM32F7)
  23static const unsigned long io_base[] = {
  24        STM32_GPIOA_BASE, STM32_GPIOB_BASE, STM32_GPIOC_BASE,
  25        STM32_GPIOD_BASE, STM32_GPIOE_BASE, STM32_GPIOF_BASE,
  26        STM32_GPIOG_BASE, STM32_GPIOH_BASE, STM32_GPIOI_BASE
  27};
  28
  29struct stm32_gpio_regs {
  30        u32 moder;      /* GPIO port mode */
  31        u32 otyper;     /* GPIO port output type */
  32        u32 ospeedr;    /* GPIO port output speed */
  33        u32 pupdr;      /* GPIO port pull-up/pull-down */
  34        u32 idr;        /* GPIO port input data */
  35        u32 odr;        /* GPIO port output data */
  36        u32 bsrr;       /* GPIO port bit set/reset */
  37        u32 lckr;       /* GPIO port configuration lock */
  38        u32 afr[2];     /* GPIO alternate function */
  39};
  40
  41#define CHECK_DSC(x)    (!x || x->port > 8 || x->pin > 15)
  42#define CHECK_CTL(x)    (!x || x->af > 15 || x->mode > 3 || x->otype > 1 || \
  43                        x->pupd > 2 || x->speed > 3)
  44
  45int stm32_gpio_config(const struct stm32_gpio_dsc *dsc,
  46                const struct stm32_gpio_ctl *ctl)
  47{
  48        struct stm32_gpio_regs *gpio_regs;
  49        u32 i;
  50        int rv;
  51
  52        if (CHECK_DSC(dsc)) {
  53                rv = -EINVAL;
  54                goto out;
  55        }
  56        if (CHECK_CTL(ctl)) {
  57                rv = -EINVAL;
  58                goto out;
  59        }
  60
  61        gpio_regs = (struct stm32_gpio_regs *)io_base[dsc->port];
  62
  63        i = (dsc->pin & 0x07) * 4;
  64        clrsetbits_le32(&gpio_regs->afr[dsc->pin >> 3], 0xF << i, ctl->af << i);
  65
  66        i = dsc->pin * 2;
  67
  68        clrsetbits_le32(&gpio_regs->moder, 0x3 << i, ctl->mode << i);
  69        clrsetbits_le32(&gpio_regs->otyper, 0x3 << i, ctl->otype << i);
  70        clrsetbits_le32(&gpio_regs->ospeedr, 0x3 << i, ctl->speed << i);
  71        clrsetbits_le32(&gpio_regs->pupdr, 0x3 << i, ctl->pupd << i);
  72
  73        rv = 0;
  74out:
  75        return rv;
  76}
  77#elif defined(CONFIG_STM32F1)
  78static const unsigned long io_base[] = {
  79        STM32_GPIOA_BASE, STM32_GPIOB_BASE, STM32_GPIOC_BASE,
  80        STM32_GPIOD_BASE, STM32_GPIOE_BASE, STM32_GPIOF_BASE,
  81        STM32_GPIOG_BASE
  82};
  83
  84#define STM32_GPIO_CR_MODE_MASK         0x3
  85#define STM32_GPIO_CR_MODE_SHIFT(p)     (p * 4)
  86#define STM32_GPIO_CR_CNF_MASK          0x3
  87#define STM32_GPIO_CR_CNF_SHIFT(p)      (p * 4 + 2)
  88
  89struct stm32_gpio_regs {
  90        u32 crl;        /* GPIO port configuration low */
  91        u32 crh;        /* GPIO port configuration high */
  92        u32 idr;        /* GPIO port input data */
  93        u32 odr;        /* GPIO port output data */
  94        u32 bsrr;       /* GPIO port bit set/reset */
  95        u32 brr;        /* GPIO port bit reset */
  96        u32 lckr;       /* GPIO port configuration lock */
  97};
  98
  99#define CHECK_DSC(x)    (!x || x->port > 6 || x->pin > 15)
 100#define CHECK_CTL(x)    (!x || x->mode > 3 || x->icnf > 3 || x->ocnf > 3 || \
 101                         x->pupd > 1)
 102
 103int stm32_gpio_config(const struct stm32_gpio_dsc *dsc,
 104                const struct stm32_gpio_ctl *ctl)
 105{
 106        struct stm32_gpio_regs *gpio_regs;
 107        u32 *cr;
 108        int p, crp;
 109        int rv;
 110
 111        if (CHECK_DSC(dsc)) {
 112                rv = -EINVAL;
 113                goto out;
 114        }
 115        if (CHECK_CTL(ctl)) {
 116                rv = -EINVAL;
 117                goto out;
 118        }
 119
 120        p = dsc->pin;
 121
 122        gpio_regs = (struct stm32_gpio_regs *)io_base[dsc->port];
 123
 124        if (p < 8) {
 125                cr = &gpio_regs->crl;
 126                crp = p;
 127        } else {
 128                cr = &gpio_regs->crh;
 129                crp = p - 8;
 130        }
 131
 132        clrbits_le32(cr, 0x3 << STM32_GPIO_CR_MODE_SHIFT(crp));
 133        setbits_le32(cr, ctl->mode << STM32_GPIO_CR_MODE_SHIFT(crp));
 134
 135        clrbits_le32(cr, 0x3 << STM32_GPIO_CR_CNF_SHIFT(crp));
 136        /* Inputs set the optional pull up / pull down */
 137        if (ctl->mode == STM32_GPIO_MODE_IN) {
 138                setbits_le32(cr, ctl->icnf << STM32_GPIO_CR_CNF_SHIFT(crp));
 139                clrbits_le32(&gpio_regs->odr, 0x1 << p);
 140                setbits_le32(&gpio_regs->odr, ctl->pupd << p);
 141        } else {
 142                setbits_le32(cr, ctl->ocnf << STM32_GPIO_CR_CNF_SHIFT(crp));
 143        }
 144
 145        rv = 0;
 146out:
 147        return rv;
 148}
 149#else
 150#error STM32 family not supported
 151#endif
 152
 153int stm32_gpout_set(const struct stm32_gpio_dsc *dsc, int state)
 154{
 155        struct stm32_gpio_regs  *gpio_regs;
 156        int rv;
 157
 158        if (CHECK_DSC(dsc)) {
 159                rv = -EINVAL;
 160                goto out;
 161        }
 162
 163        gpio_regs = (struct stm32_gpio_regs *)io_base[dsc->port];
 164
 165        if (state)
 166                writel(1 << dsc->pin, &gpio_regs->bsrr);
 167        else
 168                writel(1 << (dsc->pin + 16), &gpio_regs->bsrr);
 169
 170        rv = 0;
 171out:
 172        return rv;
 173}
 174
 175int stm32_gpin_get(const struct stm32_gpio_dsc *dsc)
 176{
 177        struct stm32_gpio_regs  *gpio_regs;
 178        int rv;
 179
 180        if (CHECK_DSC(dsc)) {
 181                rv = -EINVAL;
 182                goto out;
 183        }
 184
 185        gpio_regs = (struct stm32_gpio_regs *)io_base[dsc->port];
 186        rv = readl(&gpio_regs->idr) & (1 << dsc->pin);
 187out:
 188        return rv;
 189}
 190
 191/* Common GPIO API */
 192
 193int gpio_request(unsigned gpio, const char *label)
 194{
 195        return 0;
 196}
 197
 198int gpio_free(unsigned gpio)
 199{
 200        return 0;
 201}
 202
 203int gpio_direction_input(unsigned gpio)
 204{
 205        struct stm32_gpio_dsc dsc;
 206        struct stm32_gpio_ctl ctl;
 207
 208        dsc.port = stm32_gpio_to_port(gpio);
 209        dsc.pin = stm32_gpio_to_pin(gpio);
 210#if defined(CONFIG_STM32F4) || defined(CONFIG_STM32F7)
 211        ctl.af = STM32_GPIO_AF0;
 212        ctl.mode = STM32_GPIO_MODE_IN;
 213        ctl.otype = STM32_GPIO_OTYPE_PP;
 214        ctl.pupd = STM32_GPIO_PUPD_NO;
 215        ctl.speed = STM32_GPIO_SPEED_50M;
 216#elif defined(CONFIG_STM32F1)
 217        ctl.mode = STM32_GPIO_MODE_IN;
 218        ctl.icnf = STM32_GPIO_ICNF_IN_FLT;
 219        ctl.ocnf = STM32_GPIO_OCNF_GP_PP;       /* ignored for input */
 220        ctl.pupd = STM32_GPIO_PUPD_UP;          /* ignored for floating */
 221#else
 222#error STM32 family not supported
 223#endif
 224
 225        return stm32_gpio_config(&dsc, &ctl);
 226}
 227
 228int gpio_direction_output(unsigned gpio, int value)
 229{
 230        struct stm32_gpio_dsc dsc;
 231        struct stm32_gpio_ctl ctl;
 232        int res;
 233
 234        dsc.port = stm32_gpio_to_port(gpio);
 235        dsc.pin = stm32_gpio_to_pin(gpio);
 236#if defined(CONFIG_STM32F4) || defined(CONFIG_STM32F7)
 237        ctl.af = STM32_GPIO_AF0;
 238        ctl.mode = STM32_GPIO_MODE_OUT;
 239        ctl.pupd = STM32_GPIO_PUPD_NO;
 240        ctl.speed = STM32_GPIO_SPEED_50M;
 241#elif defined(CONFIG_STM32F1)
 242        ctl.mode = STM32_GPIO_MODE_OUT_50M;
 243        ctl.ocnf = STM32_GPIO_OCNF_GP_PP;
 244        ctl.icnf = STM32_GPIO_ICNF_IN_FLT;      /* ignored for output */
 245        ctl.pupd = STM32_GPIO_PUPD_UP;          /* ignored for output */
 246#else
 247#error STM32 family not supported
 248#endif
 249
 250        res = stm32_gpio_config(&dsc, &ctl);
 251        if (res < 0)
 252                goto out;
 253        res = stm32_gpout_set(&dsc, value);
 254out:
 255        return res;
 256}
 257
 258int gpio_get_value(unsigned gpio)
 259{
 260        struct stm32_gpio_dsc dsc;
 261
 262        dsc.port = stm32_gpio_to_port(gpio);
 263        dsc.pin = stm32_gpio_to_pin(gpio);
 264
 265        return stm32_gpin_get(&dsc);
 266}
 267
 268int gpio_set_value(unsigned gpio, int value)
 269{
 270        struct stm32_gpio_dsc dsc;
 271
 272        dsc.port = stm32_gpio_to_port(gpio);
 273        dsc.pin = stm32_gpio_to_pin(gpio);
 274
 275        return stm32_gpout_set(&dsc, value);
 276}
 277