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