summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorAdam Podogrocki <adam.podogrocki@rndity.com>2016-12-21 08:56:20 +0000
committerKumar Gala <kumar.gala@linaro.org>2017-01-23 15:15:52 -0600
commitf23492a05939ee720a3991df36d5829d4a47abc7 (patch)
tree2121dabf6d338a409bf1d60b9a456be09cbbd9a3 /arch
parent61cc74c425d02af0e43020ca4cb75f539cada82f (diff)
gpio/stm32: provide GPIO driver implementation for STM32F3X family
Implementation includes adding some defines in the pinmux, adjusting gpio driver to specific defines for STM32F3X family, adding specific functionality in the F3X SoC definition. Change-Id: I465c66eb93e7afb43166c4585c852e284b0d6e67 Signed-off-by: Adam Podogrocki <adam.podogrocki@rndity.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/soc/st_stm32/stm32f3/Makefile3
-rw-r--r--arch/arm/soc/st_stm32/stm32f3/gpio_registers.h112
-rw-r--r--arch/arm/soc/st_stm32/stm32f3/rcc_registers.h4
-rw-r--r--arch/arm/soc/st_stm32/stm32f3/soc_config.c28
-rw-r--r--arch/arm/soc/st_stm32/stm32f3/soc_gpio.c219
-rw-r--r--arch/arm/soc/st_stm32/stm32f3/soc_registers.h1
6 files changed, 361 insertions, 6 deletions
diff --git a/arch/arm/soc/st_stm32/stm32f3/Makefile b/arch/arm/soc/st_stm32/stm32f3/Makefile
index baf5eb307..00e22c015 100644
--- a/arch/arm/soc/st_stm32/stm32f3/Makefile
+++ b/arch/arm/soc/st_stm32/stm32f3/Makefile
@@ -17,4 +17,5 @@
obj-y += soc.o
-obj-$(CONFIG_PINMUX) += soc_config.o \ No newline at end of file
+obj-$(CONFIG_PINMUX) += soc_config.o
+obj-$(CONFIG_GPIO) += soc_gpio.o \ No newline at end of file
diff --git a/arch/arm/soc/st_stm32/stm32f3/gpio_registers.h b/arch/arm/soc/st_stm32/stm32f3/gpio_registers.h
new file mode 100644
index 000000000..dfeaf41ea
--- /dev/null
+++ b/arch/arm/soc/st_stm32/stm32f3/gpio_registers.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2016 RnDity 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 _STM32F3X_GPIO_REGISTERS_H_
+#define _STM32F3X_GPIO_REGISTERS_H_
+
+/**
+ * @brief
+ *
+ * Based on reference manual:
+ * STM32F303xB/C/D/E, STM32F303x6/8, STM32F328x8, STM32F358xC,
+ * STM32F398xE advanced ARM ® -based MCUs
+ *
+ * Chapter 11: General-purpose I/Os
+ */
+
+struct stm32f3x_gpio {
+ uint32_t moder;
+ uint32_t otyper;
+ uint32_t ospeedr;
+ uint32_t pupdr;
+ uint32_t idr;
+ uint32_t odr;
+ uint32_t bsrr;
+ uint32_t lckr;
+ uint32_t afrl;
+ uint32_t afrh;
+ uint32_t brr;
+};
+
+union syscfg_cfgr1 {
+ uint32_t val;
+ struct {
+ uint32_t mem_mode :2 __packed;
+ uint32_t rsvd__2_5 :4 __packed;
+ uint32_t tim1_itr3_rmo :1 __packed;
+ uint32_t dac_trig_rmp :1 __packed;
+ uint32_t rsvd__8_10 :3 __packed;
+ uint32_t tim16_dma_rmp :1 __packed;
+ uint32_t tim17_dma_rmp :1 __packed;
+ uint32_t tim16_dac1_dma_rmp :1 __packed;
+ uint32_t tim17_dac2_dma_rmp :1 __packed;
+ uint32_t dac2_ch1_dma_rmp :1 __packed;
+ uint32_t i2c_pb6_fmp :1 __packed;
+ uint32_t i2c_pb7_fmp :1 __packed;
+ uint32_t i2c_pb8_fmp :1 __packed;
+ uint32_t i2c_pb9_fmp :1 __packed;
+ uint32_t i2c1_fmp :1 __packed;
+ uint32_t rsvd__21 :1 __packed;
+ uint32_t encoder_mode :2 __packed;
+ uint32_t rsvd__24_25 :2 __packed;
+ uint32_t fpu_ie :6 __packed;
+ } bit;
+};
+
+union syscfg_rcr {
+ uint32_t val;
+ struct {
+ uint32_t page0_wp :1 __packed;
+ uint32_t page1_wp :1 __packed;
+ uint32_t page2_wp :1 __packed;
+ uint32_t page3_wp :1 __packed;
+ uint32_t rsvd__4_31 :28 __packed;
+ } bit;
+};
+
+union syscfg__exticr {
+ uint32_t val;
+ struct {
+ uint16_t exti;
+ uint16_t rsvd__16_31;
+ } bit;
+};
+
+struct stm32f3x_syscfg {
+ union syscfg_cfgr1 cfgr1;
+ union syscfg_rcr rcr;
+ union syscfg__exticr exticr1;
+ union syscfg__exticr exticr2;
+ union syscfg__exticr exticr3;
+ union syscfg__exticr exticr4;
+ uint32_t cfgr2;
+ uint32_t rsvd_0x1C;
+ uint32_t rsvd_0x20;
+ uint32_t rsvd_0x24;
+ uint32_t rsvd_0x28;
+ uint32_t rsvd_0x2C;
+ uint32_t rsvd_0x30;
+ uint32_t rsvd_0x34;
+ uint32_t rsvd_0x38;
+ uint32_t rsvd_0x3C;
+ uint32_t rsvd_0x40;
+ uint32_t rsvd_0x44;
+ uint32_t rsvd_0x48;
+ uint32_t rsvd_0x4C;
+ uint32_t cfgr3;
+};
+
+#endif /* _STM32F3X_GPIO_REGISTERS_H_ */
diff --git a/arch/arm/soc/st_stm32/stm32f3/rcc_registers.h b/arch/arm/soc/st_stm32/stm32f3/rcc_registers.h
index dfe11fd9e..808a724ab 100644
--- a/arch/arm/soc/st_stm32/stm32f3/rcc_registers.h
+++ b/arch/arm/soc/st_stm32/stm32f3/rcc_registers.h
@@ -29,8 +29,8 @@
*/
/**
- * @brief Reset and Clock Control
- */
+ * @brief Reset and Clock Control
+ */
union __rcc_cr {
uint32_t val;
diff --git a/arch/arm/soc/st_stm32/stm32f3/soc_config.c b/arch/arm/soc/st_stm32/stm32f3/soc_config.c
index c4f25ec25..d22b3f9fd 100644
--- a/arch/arm/soc/st_stm32/stm32f3/soc_config.c
+++ b/arch/arm/soc/st_stm32/stm32f3/soc_config.c
@@ -18,7 +18,7 @@
#include <errno.h>
#include <device.h>
#include <pinmux/stm32/pinmux_stm32.h>
-#include <gpio/gpio_stm32.h>
+#include <drivers/clock_control/stm32_clock_control.h>
int stm32_get_pin_config(int pin, int func)
{
@@ -36,6 +36,28 @@ int stm32_get_pin_config(int pin, int func)
return -EINVAL;
}
- /* ToDo: encode and return the 'real' alternate function number */
- return -EINVAL;
+ /* encode and return the 'real' alternate function number */
+ return STM32_PINFUNC(func, STM32F3X_PIN_CONFIG_AF);
+}
+
+clock_control_subsys_t stm32_get_port_clock(int port)
+{
+ const clock_control_subsys_t ports_to_clock[STM32_PORTS_MAX] = {
+ UINT_TO_POINTER(STM32F3X_CLOCK_SUBSYS_IOPA),
+ UINT_TO_POINTER(STM32F3X_CLOCK_SUBSYS_IOPB),
+ UINT_TO_POINTER(STM32F3X_CLOCK_SUBSYS_IOPC),
+ UINT_TO_POINTER(STM32F3X_CLOCK_SUBSYS_IOPD),
+#ifdef CONFIG_SOC_STM32F334X8
+ UINT_TO_POINTER(0),
+#else
+ UINT_TO_POINTER(STM32F3X_CLOCK_SUBSYS_IOPE),
+#endif
+ UINT_TO_POINTER(STM32F3X_CLOCK_SUBSYS_IOPF),
+ };
+
+ if (port > STM32_PORTF) {
+ return NULL;
+ }
+
+ return ports_to_clock[port];
}
diff --git a/arch/arm/soc/st_stm32/stm32f3/soc_gpio.c b/arch/arm/soc/st_stm32/stm32f3/soc_gpio.c
new file mode 100644
index 000000000..3d57542c3
--- /dev/null
+++ b/arch/arm/soc/st_stm32/stm32f3/soc_gpio.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2016 RnDity 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:
+ * STM32F303xB/C/D/E, STM32F303x6/8, STM32F328x8, STM32F358xC,
+ * STM32F398xE advanced ARM ® -based MCUs
+ *
+ * Chapter 11: General-purpose I/Os (GPIO)
+ */
+
+#include <errno.h>
+
+#include <device.h>
+#include "soc.h"
+#include "soc_registers.h"
+#include <gpio.h>
+#include <gpio/gpio_stm32.h>
+
+/**
+ * @brief map pin function to MODE register value
+ */
+static uint32_t func_to_mode(int func)
+{
+ switch (func) {
+ case STM32F3X_PIN_CONFIG_ANALOG:
+ return 0x3;
+ case STM32F3X_PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
+ case STM32F3X_PIN_CONFIG_BIAS_PULL_UP:
+ case STM32F3X_PIN_CONFIG_BIAS_PULL_DOWN:
+ return 0x0;
+ case STM32F3X_PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ case STM32F3X_PIN_CONFIG_DRIVE_PUSH_PULL:
+ case STM32F3X_PIN_CONFIG_DRIVE_PUSH_PULL_PU:
+ case STM32F3X_PIN_CONFIG_DRIVE_PUSH_PULL_PD:
+ case STM32F3X_PIN_CONFIG_DRIVE_OPEN_DRAIN_PU:
+ case STM32F3X_PIN_CONFIG_DRIVE_OPEN_DRAIN_PD:
+ return 0x1;
+ case STM32F3X_PIN_CONFIG_AF:
+ return 0x2;
+ }
+ return 0;
+}
+
+int stm32_gpio_flags_to_conf(int flags, int *pincfg)
+{
+ int direction = flags & GPIO_DIR_MASK;
+
+ if (!pincfg) {
+ return -EINVAL;
+ }
+
+ int pud = flags & GPIO_PUD_MASK;
+
+ if (direction == GPIO_DIR_OUT) {
+ int type = flags & GPIO_PP_OD_MASK;
+
+ if (type == GPIO_PUSH_PULL) {
+ *pincfg = STM32F3X_PIN_CONFIG_DRIVE_PUSH_PULL;
+ if (pud == GPIO_PUD_PULL_UP) {
+ *pincfg = STM32F3X_PIN_CONFIG_DRIVE_PUSH_PULL_PU;
+ } else if (pud == GPIO_PUD_PULL_DOWN) {
+ *pincfg = STM32F3X_PIN_CONFIG_DRIVE_PUSH_PULL_PD;
+ }
+ } else if (type == GPIO_OPEN_DRAIN) {
+ *pincfg = STM32F3X_PIN_CONFIG_DRIVE_OPEN_DRAIN;
+ if (pud == GPIO_PUD_PULL_UP) {
+ *pincfg = STM32F3X_PIN_CONFIG_DRIVE_OPEN_DRAIN_PU;
+ } else if (pud == GPIO_PUD_PULL_DOWN) {
+ *pincfg = STM32F3X_PIN_CONFIG_DRIVE_OPEN_DRAIN_PD;
+ }
+ }
+ } else if (direction == GPIO_DIR_IN) {
+ if (pud == GPIO_PUD_PULL_UP) {
+ *pincfg = STM32F3X_PIN_CONFIG_BIAS_PULL_UP;
+ } else if (pud == GPIO_PUD_PULL_DOWN) {
+ *pincfg = STM32F3X_PIN_CONFIG_BIAS_PULL_DOWN;
+ } else {
+ /* floating */
+ *pincfg = STM32F3X_PIN_CONFIG_BIAS_HIGH_IMPEDANCE;
+ }
+ } else {
+ return -ENOTSUP;
+ }
+
+ return 0;
+}
+
+int stm32_gpio_configure(uint32_t *base_addr, int pin, int conf, int altf)
+{
+ volatile struct stm32f3x_gpio *gpio =
+ (struct stm32f3x_gpio *)(base_addr);
+ int mode, cmode;
+
+ cmode = STM32_MODE(conf);
+ mode = func_to_mode(cmode);
+
+ /* clear bits */
+ gpio->moder &= ~(0x3 << (pin * 2));
+ /* set bits */
+ gpio->moder |= (mode << (pin * 2));
+
+ if (cmode == STM32F3X_PIN_CONFIG_AF) {
+ /* alternate function setup */
+ int af = STM32_AF(conf);
+ volatile uint32_t *afr = &gpio->afrl;
+ int crpin = pin;
+
+ if (crpin > 7) {
+ afr = &gpio->afrh;
+ crpin -= 7;
+ }
+
+ /* clear AF bits */
+ *afr &= ~(0xf << (crpin * 4));
+ /* set AF */
+ *afr |= (af << (crpin * 4));
+ } else if (cmode == STM32F3X_PIN_CONFIG_ANALOG) {
+ gpio->pupdr &= ~(0x3 << (pin * 2));
+ } else {
+ /* clear typer */
+ gpio->otyper &= ~(1 << pin);
+
+ if (cmode == STM32F3X_PIN_CONFIG_DRIVE_OPEN_DRAIN ||
+ cmode == STM32F3X_PIN_CONFIG_DRIVE_OPEN_DRAIN_PU ||
+ cmode == STM32F3X_PIN_CONFIG_DRIVE_OPEN_DRAIN_PD) {
+ /* configure pin as output open-drain */
+ gpio->otyper |= 1 << pin;
+ }
+
+ /* configure pin as floating by clearing pupd flags */
+ gpio->pupdr &= ~(0x3 << (pin * 2));
+
+ if (cmode == STM32F3X_PIN_CONFIG_BIAS_PULL_UP ||
+ cmode == STM32F3X_PIN_CONFIG_DRIVE_PUSH_PULL_PU ||
+ cmode == STM32F3X_PIN_CONFIG_DRIVE_OPEN_DRAIN_PU) {
+ /* enable pull up */
+ gpio->pupdr |= (1 << (pin * 2));
+ } else if (cmode == STM32F3X_PIN_CONFIG_BIAS_PULL_DOWN ||
+ cmode == STM32F3X_PIN_CONFIG_DRIVE_PUSH_PULL_PD ||
+ cmode == STM32F3X_PIN_CONFIG_DRIVE_OPEN_DRAIN_PD) {
+ /* or pull down */
+ gpio->pupdr |= (2 << (pin * 2));
+ }
+ }
+
+ return 0;
+}
+
+int stm32_gpio_set(uint32_t *base, int pin, int value)
+{
+ struct stm32f3x_gpio *gpio = (struct stm32f3x_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 stm32f3x_gpio *gpio = (struct stm32f3x_gpio *)base;
+
+ return (gpio->idr >> pin) & 0x1;
+}
+
+int stm32_gpio_enable_int(int port, int pin)
+{
+ volatile struct stm32f3x_syscfg *syscfg =
+ (struct stm32f3x_syscfg *)SYSCFG_BASE;
+ volatile union syscfg__exticr *exticr;
+
+ /* Enable System Configuration Controller clock. */
+ struct device *clk =
+ device_get_binding(STM32_CLOCK_CONTROL_NAME);
+
+ clock_control_on(clk, UINT_TO_POINTER(STM32F3X_CLOCK_SUBSYS_SYSCFG));
+
+ int shift = 0;
+
+ if (pin <= 3) {
+ exticr = &syscfg->exticr1;
+ } else if (pin <= 7) {
+ exticr = &syscfg->exticr2;
+ } else if (pin <= 11) {
+ exticr = &syscfg->exticr3;
+ } else if (pin <= 15) {
+ exticr = &syscfg->exticr4;
+ } else {
+ return -EINVAL;
+ }
+
+ shift = 4 * (pin % 4);
+
+ exticr->val &= ~(0xf << shift);
+ exticr->val |= port << shift;
+
+ return 0;
+}
diff --git a/arch/arm/soc/st_stm32/stm32f3/soc_registers.h b/arch/arm/soc/st_stm32/stm32f3/soc_registers.h
index 3819ebf5c..55ba8b21f 100644
--- a/arch/arm/soc/st_stm32/stm32f3/soc_registers.h
+++ b/arch/arm/soc/st_stm32/stm32f3/soc_registers.h
@@ -20,5 +20,6 @@
/* include register mapping headers */
#include "rcc_registers.h"
#include "flash_registers.h"
+#include "gpio_registers.h"
#endif /* _STM32F3X_SOC_REGISTERS_H_ */