[U-Boot] [PATCH v3 4/6] gpio: stm32: add stm32f1 support

Matt Porter mporter at konsulko.com
Tue May 5 21:00:25 CEST 2015


Add support for the STM32F1 family to the STM32 gpio driver.

Signed-off-by: Matt Porter <mporter at konsulko.com>
---
v3:
	- Update copyright notice
v2:
	- Explicitly check for F4/F1 family and error if not
	  set to a supported STM32 family.

 drivers/gpio/stm32_gpio.c | 110 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 109 insertions(+), 1 deletion(-)

diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c
index d3497e9..86bb19e 100644
--- a/drivers/gpio/stm32_gpio.c
+++ b/drivers/gpio/stm32_gpio.c
@@ -5,6 +5,9 @@
  * (C) Copyright 2015
  * Kamil Lulko, <rev13 at wp.pl>
  *
+ * Copyright 2015 ATS Advanced Telematics Systems GmbH
+ * Copyright 2015 Konsulko Group, Matt Porter <mporter at konsulko.com>
+ *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
@@ -16,6 +19,7 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#if defined(CONFIG_STM32F4)
 #define STM32_GPIOA_BASE	(STM32_AHB1PERIPH_BASE + 0x0000)
 #define STM32_GPIOB_BASE	(STM32_AHB1PERIPH_BASE + 0x0400)
 #define STM32_GPIOC_BASE	(STM32_AHB1PERIPH_BASE + 0x0800)
@@ -90,6 +94,92 @@ int stm32_gpio_config(const struct stm32_gpio_dsc *dsc,
 out:
 	return rv;
 }
+#elif defined(CONFIG_STM32F1)
+#define STM32_GPIOA_BASE	(STM32_APB2PERIPH_BASE + 0x0800)
+#define STM32_GPIOB_BASE	(STM32_APB2PERIPH_BASE + 0x0C00)
+#define STM32_GPIOC_BASE	(STM32_APB2PERIPH_BASE + 0x1000)
+#define STM32_GPIOD_BASE	(STM32_APB2PERIPH_BASE + 0x1400)
+#define STM32_GPIOE_BASE	(STM32_APB2PERIPH_BASE + 0x1800)
+#define STM32_GPIOF_BASE	(STM32_APB2PERIPH_BASE + 0x1C00)
+#define STM32_GPIOG_BASE	(STM32_APB2PERIPH_BASE + 0x2000)
+
+static const unsigned long io_base[] = {
+	STM32_GPIOA_BASE, STM32_GPIOB_BASE, STM32_GPIOC_BASE,
+	STM32_GPIOD_BASE, STM32_GPIOE_BASE, STM32_GPIOF_BASE,
+	STM32_GPIOG_BASE
+};
+
+#define STM32_GPIO_CR_MODE_MASK		0x3
+#define STM32_GPIO_CR_MODE_SHIFT(p)	(p * 4)
+#define STM32_GPIO_CR_CNF_MASK		0x3
+#define STM32_GPIO_CR_CNF_SHIFT(p)	(p * 4 + 2)
+
+struct stm32_gpio_regs {
+	u32 crl;	/* GPIO port configuration low */
+	u32 crh;	/* GPIO port configuration high */
+	u32 idr;	/* GPIO port input data */
+	u32 odr;	/* GPIO port output data */
+	u32 bsrr;	/* GPIO port bit set/reset */
+	u32 brr;	/* GPIO port bit reset */
+	u32 lckr;	/* GPIO port configuration lock */
+};
+
+#define CHECK_DSC(x)	(!x || x->port > 6 || x->pin > 15)
+#define CHECK_CTL(x)	(!x || x->mode > 3 || x->icnf > 3 || x->ocnf > 3 || \
+			 x->pupd > 1)
+
+int stm32_gpio_config(const struct stm32_gpio_dsc *dsc,
+		const struct stm32_gpio_ctl *ctl)
+{
+	struct stm32_gpio_regs *gpio_regs;
+	u32 *cr;
+	int p, crp;
+	int rv;
+
+	if (CHECK_DSC(dsc)) {
+		rv = -EINVAL;
+		goto out;
+	}
+	if (CHECK_CTL(ctl)) {
+		rv = -EINVAL;
+		goto out;
+	}
+
+	p = dsc->pin;
+
+	gpio_regs = (struct stm32_gpio_regs *)io_base[dsc->port];
+
+	/* Enable clock for GPIO port */
+	setbits_le32(&STM32_RCC->apb2enr, 0x04 << dsc->port);
+
+	if (p < 8) {
+		cr = &gpio_regs->crl;
+		crp = p;
+	} else {
+		cr = &gpio_regs->crh;
+		crp = p - 8;
+	}
+
+	clrbits_le32(cr, 0x3 << STM32_GPIO_CR_MODE_SHIFT(crp));
+	setbits_le32(cr, ctl->mode << STM32_GPIO_CR_MODE_SHIFT(crp));
+
+	clrbits_le32(cr, 0x3 << STM32_GPIO_CR_CNF_SHIFT(crp));
+	/* Inputs set the optional pull up / pull down */
+	if (ctl->mode == STM32_GPIO_MODE_IN) {
+		setbits_le32(cr, ctl->icnf << STM32_GPIO_CR_CNF_SHIFT(crp));
+		clrbits_le32(&gpio_regs->odr, 0x1 << p);
+		setbits_le32(&gpio_regs->odr, ctl->pupd << p);
+	} else {
+		setbits_le32(cr, ctl->ocnf << STM32_GPIO_CR_CNF_SHIFT(crp));
+	}
+
+	rv = 0;
+out:
+	return rv;
+}
+#else
+#error STM32 family not supported
+#endif
 
 int stm32_gpout_set(const struct stm32_gpio_dsc *dsc, int state)
 {
@@ -148,10 +238,20 @@ int gpio_direction_input(unsigned gpio)
 
 	dsc.port = stm32_gpio_to_port(gpio);
 	dsc.pin = stm32_gpio_to_pin(gpio);
+#if defined(CONFIG_STM32F4)
 	ctl.af = STM32_GPIO_AF0;
 	ctl.mode = STM32_GPIO_MODE_IN;
+	ctl.otype = STM32_GPIO_OTYPE_PP;
 	ctl.pupd = STM32_GPIO_PUPD_NO;
 	ctl.speed = STM32_GPIO_SPEED_50M;
+#elif defined(CONFIG_STM32F1)
+	ctl.mode = STM32_GPIO_MODE_IN;
+	ctl.icnf = STM32_GPIO_ICNF_IN_FLT;
+	ctl.ocnf = STM32_GPIO_OCNF_GP_PP;	/* ignored for input */
+	ctl.pupd = STM32_GPIO_PUPD_UP;		/* ignored for floating */
+#else
+#error STM32 family not supported
+#endif
 
 	return stm32_gpio_config(&dsc, &ctl);
 }
@@ -164,11 +264,19 @@ int gpio_direction_output(unsigned gpio, int value)
 
 	dsc.port = stm32_gpio_to_port(gpio);
 	dsc.pin = stm32_gpio_to_pin(gpio);
+#if defined(CONFIG_STM32F4)
 	ctl.af = STM32_GPIO_AF0;
 	ctl.mode = STM32_GPIO_MODE_OUT;
-	ctl.otype = STM32_GPIO_OTYPE_PP;
 	ctl.pupd = STM32_GPIO_PUPD_NO;
 	ctl.speed = STM32_GPIO_SPEED_50M;
+#elif defined(CONFIG_STM32F1)
+	ctl.mode = STM32_GPIO_MODE_OUT_50M;
+	ctl.ocnf = STM32_GPIO_OCNF_GP_PP;
+	ctl.icnf = STM32_GPIO_ICNF_IN_FLT;	/* ignored for output */
+	ctl.pupd = STM32_GPIO_PUPD_UP;		/* ignored for output */
+#else
+#error STM32 family not supported
+#endif
 
 	res = stm32_gpio_config(&dsc, &ctl);
 	if (res < 0)
-- 
2.1.0



More information about the U-Boot mailing list