summaryrefslogtreecommitdiff
path: root/drivers/pinctrl/pinctrl_stm32.c
diff options
context:
space:
mode:
authorStefano Babic <sbabic@denx.de>2017-05-09 18:03:44 +0200
committerStefano Babic <sbabic@denx.de>2017-05-09 18:03:44 +0200
commit4f66e09bb9fbc47b73f67c3cc08ee2663e8fcdb1 (patch)
tree89bc85aa5a8ca9b60027cdd2f1a40fc83f6278c4 /drivers/pinctrl/pinctrl_stm32.c
parent809b133722eee0e7bdfa6595daabc0bb2f5aa698 (diff)
parent85ea850976daea57c8045f3569566fad5ce9fe0f (diff)
Merge branch 'master' of git://git.denx.de/u-boot
Signed-off-by: Stefano Babic <sbabic@denx.de>
Diffstat (limited to 'drivers/pinctrl/pinctrl_stm32.c')
-rw-r--r--drivers/pinctrl/pinctrl_stm32.c50
1 files changed, 46 insertions, 4 deletions
diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c
index aa2c440b14..d7b5ea3e1c 100644
--- a/drivers/pinctrl/pinctrl_stm32.c
+++ b/drivers/pinctrl/pinctrl_stm32.c
@@ -1,10 +1,46 @@
#include <common.h>
-#include <asm/arch/gpio.h>
#include <dm.h>
#include <dm/pinctrl.h>
+#include <asm/arch/gpio.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
DECLARE_GLOBAL_DATA_PTR;
+#define MAX_PINS_ONE_IP 70
+#define MODE_BITS_MASK 3
+#define OSPEED_MASK 3
+#define PUPD_MASK 3
+#define OTYPE_MSK 1
+#define AFR_MASK 0xF
+
+static int stm32_gpio_config(struct gpio_desc *desc,
+ const struct stm32_gpio_ctl *ctl)
+{
+ struct stm32_gpio_priv *priv = dev_get_priv(desc->dev);
+ struct stm32_gpio_regs *regs = priv->regs;
+ u32 index;
+
+ if (!ctl || ctl->af > 15 || ctl->mode > 3 || ctl->otype > 1 ||
+ ctl->pupd > 2 || ctl->speed > 3)
+ return -EINVAL;
+
+ index = (desc->offset & 0x07) * 4;
+ clrsetbits_le32(&regs->afr[desc->offset >> 3], AFR_MASK << index,
+ ctl->af << index);
+
+ index = desc->offset * 2;
+ clrsetbits_le32(&regs->moder, MODE_BITS_MASK << index,
+ ctl->mode << index);
+ clrsetbits_le32(&regs->ospeedr, OSPEED_MASK << index,
+ ctl->speed << index);
+ clrsetbits_le32(&regs->pupdr, PUPD_MASK << index, ctl->pupd << index);
+
+ index = desc->offset;
+ clrsetbits_le32(&regs->otyper, OTYPE_MSK << index, ctl->otype << index);
+
+ return 0;
+}
static int prep_gpio_dsc(struct stm32_gpio_dsc *gpio_dsc, u32 port_pin)
{
gpio_dsc->port = (port_pin & 0xF000) >> 12;
@@ -18,6 +54,7 @@ static int prep_gpio_dsc(struct stm32_gpio_dsc *gpio_dsc, u32 port_pin)
static int prep_gpio_ctl(struct stm32_gpio_ctl *gpio_ctl, u32 gpio_fn, int node)
{
gpio_fn &= 0x00FF;
+ gpio_ctl->af = 0;
switch (gpio_fn) {
case 0:
@@ -59,7 +96,7 @@ static int prep_gpio_ctl(struct stm32_gpio_ctl *gpio_ctl, u32 gpio_fn, int node)
static int stm32_pinctrl_set_state_simple(struct udevice *dev,
struct udevice *periph)
{
- u32 pin_mux[50];
+ u32 pin_mux[MAX_PINS_ONE_IP];
struct fdtdec_phandle_args args;
int rv, len;
@@ -85,11 +122,16 @@ static int stm32_pinctrl_set_state_simple(struct udevice *dev,
if (len < 0)
return -EINVAL;
for (i = 0; i < len; i++) {
+ struct gpio_desc desc;
debug("%s: pinmux = %x\n", __func__, *(pin_mux + i));
prep_gpio_dsc(&gpio_dsc, *(pin_mux + i));
prep_gpio_ctl(&gpio_ctl, *(pin_mux + i), args.node);
-
- rv = stm32_gpio_config(&gpio_dsc, &gpio_ctl);
+ rv = uclass_get_device_by_seq(UCLASS_GPIO,
+ gpio_dsc.port, &desc.dev);
+ if (rv)
+ return rv;
+ desc.offset = gpio_dsc.pin;
+ rv = stm32_gpio_config(&desc, &gpio_ctl);
debug("%s: rv = %d\n\n", __func__, rv);
if (rv)
return rv;