feat(st-gpio): allow to set a gpio in output mode

Allow to set a gpio in output mode from the device tree.

Signed-off-by: Fabien Dessenne <fabien.dessenne@foss.st.com>
Change-Id: Ic483324bc5fe916a60df05f74706bd1da4d08aa5
diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c
index 21ad3f1..527f90f 100644
--- a/drivers/st/gpio/stm32_gpio.c
+++ b/drivers/st/gpio/stm32_gpio.c
@@ -26,8 +26,8 @@
 #define DT_GPIO_MODE_MASK	GENMASK(7, 0)
 
 static void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t type,
-		     uint32_t speed, uint32_t pull, uint32_t alternate,
-		     uint8_t status);
+		     uint32_t speed, uint32_t pull, uint32_t od,
+		     uint32_t alternate, uint8_t status);
 
 /*******************************************************************************
  * This function gets GPIO bank node in DT.
@@ -104,6 +104,7 @@
 		uint32_t mode;
 		uint32_t alternate = GPIO_ALTERNATE_(0);
 		uint32_t type;
+		uint32_t od = GPIO_OD_OUTPUT_LOW;
 		int bank_node;
 		int clk;
 
@@ -138,6 +139,20 @@
 			type = GPIO_TYPE_PUSH_PULL;
 		}
 
+		if (fdt_getprop(fdt, node, "output-high", NULL) != NULL) {
+			if (mode == GPIO_MODE_INPUT) {
+				mode = GPIO_MODE_OUTPUT;
+				od = GPIO_OD_OUTPUT_HIGH;
+			}
+		}
+
+		if (fdt_getprop(fdt, node, "output-low", NULL) != NULL) {
+			if (mode == GPIO_MODE_INPUT) {
+				mode = GPIO_MODE_OUTPUT;
+				od = GPIO_OD_OUTPUT_LOW;
+			}
+		}
+
 		bank_node = ckeck_gpio_bank(fdt, bank, pinctrl_node);
 		if (bank_node == 0) {
 			ERROR("PINCTRL inconsistent in DT\n");
@@ -152,7 +167,7 @@
 		/* Platform knows the clock: assert it is okay */
 		assert((unsigned long)clk == stm32_get_gpio_bank_clock(bank));
 
-		set_gpio(bank, pin, mode, type, speed, pull, alternate, status);
+		set_gpio(bank, pin, mode, type, speed, pull, od, alternate, status);
 	}
 
 	return 0;
@@ -208,8 +223,8 @@
 }
 
 static void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t type,
-		     uint32_t speed, uint32_t pull, uint32_t alternate,
-		     uint8_t status)
+		     uint32_t speed, uint32_t pull, uint32_t od,
+		     uint32_t alternate, uint8_t status)
 {
 	uintptr_t base = stm32_get_gpio_bank_base(bank);
 	unsigned long clock = stm32_get_gpio_bank_clock(bank);
@@ -246,6 +261,10 @@
 				   alternate << shift);
 	}
 
+	mmio_clrsetbits_32(base + GPIO_OD_OFFSET,
+			   (uint32_t)GPIO_OD_MASK << pin,
+			   od << pin);
+
 	VERBOSE("GPIO %u mode set to 0x%x\n", bank,
 		mmio_read_32(base + GPIO_MODE_OFFSET));
 	VERBOSE("GPIO %u type set to 0x%x\n", bank,
@@ -258,6 +277,8 @@
 		mmio_read_32(base + GPIO_AFRL_OFFSET));
 	VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank,
 		mmio_read_32(base + GPIO_AFRH_OFFSET));
+	VERBOSE("GPIO %u output data set to 0x%x\n", bank,
+		mmio_read_32(base + GPIO_OD_OFFSET));
 
 	clk_disable(clock);
 
@@ -292,6 +313,7 @@
 void set_gpio_reset_cfg(uint32_t bank, uint32_t pin)
 {
 	set_gpio(bank, pin, GPIO_MODE_ANALOG, GPIO_TYPE_PUSH_PULL,
-		 GPIO_SPEED_LOW, GPIO_NO_PULL, GPIO_ALTERNATE_(0), DT_DISABLED);
+		 GPIO_SPEED_LOW, GPIO_NO_PULL, GPIO_OD_OUTPUT_LOW,
+		 GPIO_ALTERNATE_(0), DT_DISABLED);
 	set_gpio_secure_cfg(bank, pin, stm32_gpio_is_secure_at_reset(bank));
 }