From 3642f9d6a3d423f1de0edc38f068d73c936443f4 Mon Sep 17 00:00:00 2001 From: Maciek Borzecki Date: Sun, 6 Mar 2016 13:50:48 +0100 Subject: [PATCH] soc/stm32f1/gpio: implement GPIO support Add functions required for integration with common STM32 GPIO driver. Change-Id: Ic6637e991f5c0cf659f3b927ed47ef482b13b64f Origin: Original Signed-off-by: Maciej Borzecki --- arch/arm/soc/st_stm32/stm32f1/Kbuild | 2 + .../arm/soc/st_stm32/stm32f1/gpio_registers.h | 42 +++++ arch/arm/soc/st_stm32/stm32f1/soc.h | 12 ++ arch/arm/soc/st_stm32/stm32f1/soc_gpio.c | 173 ++++++++++++++++++ arch/arm/soc/st_stm32/stm32f1/soc_registers.h | 1 + 5 files changed, 230 insertions(+) create mode 100644 arch/arm/soc/st_stm32/stm32f1/gpio_registers.h create mode 100644 arch/arm/soc/st_stm32/stm32f1/soc_gpio.c diff --git a/arch/arm/soc/st_stm32/stm32f1/Kbuild b/arch/arm/soc/st_stm32/stm32f1/Kbuild index 52341f86c0b..ada8aa63b65 100644 --- a/arch/arm/soc/st_stm32/stm32f1/Kbuild +++ b/arch/arm/soc/st_stm32/stm32f1/Kbuild @@ -1 +1,3 @@ obj-y += soc.o + +obj-$(CONFIG_GPIO) += soc_gpio.o diff --git a/arch/arm/soc/st_stm32/stm32f1/gpio_registers.h b/arch/arm/soc/st_stm32/stm32f1/gpio_registers.h new file mode 100644 index 00000000000..17720fabdfc --- /dev/null +++ b/arch/arm/soc/st_stm32/stm32f1/gpio_registers.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016 Open-RnD Sp. z o.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _STM32F10X_GPIO_REGISTERS_H_ +#define _STM32F10X_GPIO_REGISTERS_H_ + +/** + * @brief + * + * Based on reference manual: + * STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx and STM32F107xx + * advanced ARM ® -based 32-bit MCUs + * + * Chapter 9: General-purpose and alternate-function I/Os + * (GPIOs and AFIOs) + */ + +/* 9.2 GPIO registers - each GPIO port controls 16 pins */ +struct stm32f10x_gpio { + uint32_t crl; + uint32_t crh; + uint32_t idr; + uint32_t odr; + uint32_t bsrr; + uint32_t brr; + uint32_t lckr; +}; + +#endif /* _STM32F10X_GPIO_REGISTERS_H_ */ diff --git a/arch/arm/soc/st_stm32/stm32f1/soc.h b/arch/arm/soc/st_stm32/stm32f1/soc.h index b2957314f56..bb5ea52a8db 100644 --- a/arch/arm/soc/st_stm32/stm32f1/soc.h +++ b/arch/arm/soc/st_stm32/stm32f1/soc.h @@ -61,6 +61,18 @@ #include #include +/* IO pin functions */ +enum stm32f10x_pin_config_mode { + STM32F10X_PIN_CONFIG_BIAS_HIGH_IMPEDANCE, + STM32F10X_PIN_CONFIG_BIAS_PULL_UP, + STM32F10X_PIN_CONFIG_BIAS_PULL_DOWN, + STM32F10X_PIN_CONFIG_ANALOG, + STM32F10X_PIN_CONFIG_DRIVE_OPEN_DRAIN, + STM32F10X_PIN_CONFIG_DRIVE_PUSH_PULL, + STM32F10X_PIN_CONFIG_AF_PUSH_PULL, + STM32F10X_PIN_CONFIG_AF_OPEN_DRAIN, +}; + #endif /* !_ASMLANGUAGE */ #endif /* _STM32F1_SOC_H_ */ diff --git a/arch/arm/soc/st_stm32/stm32f1/soc_gpio.c b/arch/arm/soc/st_stm32/stm32f1/soc_gpio.c new file mode 100644 index 00000000000..fd2edf856b1 --- /dev/null +++ b/arch/arm/soc/st_stm32/stm32f1/soc_gpio.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2016 Open-RnD Sp. z o.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @brief + * + * Based on reference manual: + * STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx and STM32F107xx + * advanced ARM ® -based 32-bit MCUs + * + * Chapter 9: General-purpose and alternate-function I/Os + * (GPIOs and AFIOs) + */ + +#include +#include "soc.h" +#include "soc_registers.h" +#include +#include + +/** + * @brief map pin function to MODE register value + */ +static uint32_t __func_to_mode(int func) +{ + switch (func) { + case STM32F10X_PIN_CONFIG_ANALOG: + case STM32F10X_PIN_CONFIG_BIAS_HIGH_IMPEDANCE: + case STM32F10X_PIN_CONFIG_BIAS_PULL_UP: + case STM32F10X_PIN_CONFIG_BIAS_PULL_DOWN: + return 0; + case STM32F10X_PIN_CONFIG_DRIVE_OPEN_DRAIN: + case STM32F10X_PIN_CONFIG_DRIVE_PUSH_PULL: + case STM32F10X_PIN_CONFIG_AF_PUSH_PULL: + case STM32F10X_PIN_CONFIG_AF_OPEN_DRAIN: + return 0x1; + } + return 0; +} + +/** + * @brief map pin function to CNF register value + */ +static uint32_t __func_to_cnf(int func) +{ + switch (func) { + case STM32F10X_PIN_CONFIG_ANALOG: + return 0x0; + case STM32F10X_PIN_CONFIG_BIAS_HIGH_IMPEDANCE: + return 0x1; + case STM32F10X_PIN_CONFIG_BIAS_PULL_UP: + case STM32F10X_PIN_CONFIG_BIAS_PULL_DOWN: + return 0x2; + case STM32F10X_PIN_CONFIG_DRIVE_PUSH_PULL: + return 0x0; + case STM32F10X_PIN_CONFIG_DRIVE_OPEN_DRAIN: + return 0x1; + case STM32F10X_PIN_CONFIG_AF_PUSH_PULL: + return 0x2; + case STM32F10X_PIN_CONFIG_AF_OPEN_DRAIN: + return 0x3; + } + return 0; +} + +int stm32_gpio_flags_to_conf(int flags, int *pincfg) +{ + int direction = flags & GPIO_DIR_MASK; + + if (!pincfg) { + return -EINVAL; + } + + if (direction == GPIO_DIR_OUT) { + *pincfg = STM32F10X_PIN_CONFIG_DRIVE_PUSH_PULL; + } else if (direction == GPIO_DIR_IN) { + int pud = flags & GPIO_PUD_MASK; + + /* pull-{up,down} maybe? */ + if (pud == GPIO_PUD_PULL_UP) { + *pincfg = STM32F10X_PIN_CONFIG_BIAS_PULL_UP; + } else if (pud == GPIO_PUD_PULL_DOWN) { + *pincfg = STM32F10X_PIN_CONFIG_BIAS_PULL_DOWN; + } else { + /* floating */ + *pincfg = STM32F10X_PIN_CONFIG_BIAS_HIGH_IMPEDANCE; + } + } else { + return -ENOTSUP; + } + + return 0; +} + +int stm32_gpio_configure(uint32_t *base_addr, int pin, int conf) +{ + volatile struct stm32f10x_gpio *gpio = + (struct stm32f10x_gpio *)(base_addr); + int cnf, mode; + int crpin = pin; + + /* pins are configured in CRL (0-7) and CRH (8-15) + * registers + */ + volatile uint32_t *reg = &gpio->crl; + + if (crpin > 7) { + reg = &gpio->crh; + crpin -= 8; + } + + /* each port is configured by 2 registers: + * CNFy[1:0]: Port x configuration bits + * MODEy[1:0]: Port x mode bits + * + * memory layout is repeated for every port: + * | CNF | MODE | + * | [0:1] | [0:1] | + */ + cnf = __func_to_cnf(conf); + mode = __func_to_mode(conf); + + /* clear bits */ + *reg &= ~(0xf << (crpin * 4)); + /* set bits */ + *reg |= (cnf << (crpin * 4 + 2) | mode << (crpin * 4)); + + /* input mode - 0x1 */ + if (conf == STM32F10X_PIN_CONFIG_BIAS_PULL_UP) { + /* enable pull up */ + gpio->odr |= 1 << pin; + } else if (conf == STM32F10X_PIN_CONFIG_BIAS_PULL_DOWN) { + /* or pull down */ + gpio->odr &= ~(1 << pin); + } + + return 0; +} + +int stm32_gpio_set(uint32_t *base, int pin, int value) +{ + struct stm32f10x_gpio *gpio = (struct stm32f10x_gpio *)base; + + int pval = 1 << (pin & 0xf); + + if (value) { + gpio->odr |= pval; + } else { + gpio->odr &= ~pval; + } + + return 0; +} + +int stm32_gpio_get(uint32_t *base, int pin) +{ + struct stm32f10x_gpio *gpio = (struct stm32f10x_gpio *)base; + + return (gpio->idr >> pin) & 0x1; +} diff --git a/arch/arm/soc/st_stm32/stm32f1/soc_registers.h b/arch/arm/soc/st_stm32/stm32f1/soc_registers.h index 4f76a08d1f9..7c747e80610 100644 --- a/arch/arm/soc/st_stm32/stm32f1/soc_registers.h +++ b/arch/arm/soc/st_stm32/stm32f1/soc_registers.h @@ -19,5 +19,6 @@ /* include register mapping headers */ #include "rcc_registers.h" +#include "gpio_registers.h" #endif /* _STM32F10X_SOC_REGISTERS_H_ */