diff --git a/cpu/stm32l1/include/periph_cpu.h b/cpu/stm32l1/include/periph_cpu.h
index 35068642c374f9502e56d99895668175a735bfa7..18399b038c39104f2bc4faccfc363e0a73fd3114 100644
--- a/cpu/stm32l1/include/periph_cpu.h
+++ b/cpu/stm32l1/include/periph_cpu.h
@@ -45,6 +45,31 @@ typedef uint32_t gpio_t;
  */
 #define GPIO_PIN(x, y)      ((GPIOA_BASE + (x << 10)) | y)
 
+/**
+ * @brief   Generate GPIO mode bitfields
+ *
+ * We use 5 bit to encode the mode:
+ * - bit 0+1: pin mode (input / output)
+ * - bit 2+3: pull resistor configuration
+ * - bit   4: output type (0: push-pull, 1: open-drain)
+ */
+#define GPIO_MODE(io, pr, ot)   ((io << 0) | (pr << 2) | (ot << 4))
+
+/**
+ * @brief   Override GPIO mode options
+ * @{
+ */
+#define HAVE_GPIO_MODE_T
+typedef enum {
+    GPIO_IN    = GPIO_MODE(0, 0, 0),    /**< input w/o pull R */
+    GPIO_IN_PD = GPIO_MODE(0, 2, 0),    /**< input with pull-down */
+    GPIO_IN_PU = GPIO_MODE(0, 1, 0),    /**< input with pull-up */
+    GPIO_OUT   = GPIO_MODE(1, 0, 0),    /**< push-pull output */
+    GPIO_OD    = GPIO_MODE(1, 0, 1),    /**< open-drain w/o pull R */
+    GPIO_OD_PU = GPIO_MODE(1, 1, 1)     /**< open-drain with pull-up */
+} gpio_mode_t;
+/** @} */
+
 /**
  * @brief   Available ports on the STM32L1 family
  */
@@ -106,6 +131,7 @@ typedef struct {
     I2C_TypeDef *dev;       /**< i2c device */
     gpio_t scl;             /**< scl pin number */
     gpio_t sda;             /**< sda pin number */
+    gpio_mode_t pin_mode;   /**< with or without pull resistor */
     gpio_af_t af;           /**< I2C alternate function value */
     uint8_t er_irqn;        /**< error IRQ */
     uint8_t ev_irqn;        /**< event IRQ */
diff --git a/cpu/stm32l1/periph/gpio.c b/cpu/stm32l1/periph/gpio.c
index bb80559f9f54e2ee3d9c3a7c3e28c70a0c0246e0..9de5baea76e8a41363e9e0383097d91fdd099c87 100644
--- a/cpu/stm32l1/periph/gpio.c
+++ b/cpu/stm32l1/periph/gpio.c
@@ -63,32 +63,31 @@ static inline int _pin_num(gpio_t pin)
     return (pin & 0x0f);
 }
 
-int gpio_init(gpio_t pin, gpio_dir_t dir, gpio_pp_t pullup)
+int gpio_init(gpio_t pin, gpio_mode_t mode)
 {
     GPIO_TypeDef *port = _port(pin);
     int pin_num = _pin_num(pin);
 
     /* enable clock */
     RCC->AHBENR |= (RCC_AHBENR_GPIOAEN << _port_num(pin));
-    /* configure pull register */
-    port->PUPDR &= ~(3 << (2 * pin_num));
-    port->PUPDR |= (pullup << (2 * pin_num));
-    /* set direction */
-    if (dir == GPIO_DIR_OUT) {
-        port->MODER &= ~(3 << (2 * pin_num));   /* set pin to output mode */
-        port->MODER |= (1 << (2 * pin_num));
-        port->OTYPER &= ~(1 << pin_num);        /* set to push-pull */
-        port->OSPEEDR |= (3 << (2 * pin_num));  /* set to high speed */
-        port->ODR &= ~(1 << pin_num);           /* set pin to low signal */
-    }
-    else {
-        port->MODER &= ~(3 << (2 * pin_num));   /* configure pin as input */
-    }
+
+    /* set mode */
+    port->MODER &= ~(0x3 << (2 * pin_num));
+    port->MODER |=  ((mode & 0x3) << (2 * pin_num));
+    /* set pull resistor configuration */
+    port->PUPDR &= ~(0x3 << (2 * pin_num));
+    port->PUPDR |=  (((mode >> 2) & 0x3) << (2 * pin_num));
+    /* set output mode */
+    port->OTYPER &= ~(1 << pin_num);
+    port->OTYPER |=  (((mode >> 4) & 0x1) << pin_num);
+    /* finally set pin speed to maximum and reset output */
+    port->OSPEEDR |= (3 << (2 * pin_num));
+    port->BRR = (1 << pin_num);
+
     return 0;
 }
 
-int gpio_init_int(gpio_t pin,
-                   gpio_pp_t pullup, gpio_flank_t flank,
+int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
                    gpio_cb_t cb, void *arg)
 {
     int pin_num = _pin_num(pin);
@@ -100,7 +99,7 @@ int gpio_init_int(gpio_t pin,
     /* enable the SYSCFG clock */
     RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
     /* initialize pin as input */
-    gpio_init(pin, GPIO_DIR_IN, pullup);
+    gpio_init(pin, mode);
     /* enable global pin interrupt */
     if (pin_num < 5) {
         NVIC_EnableIRQ(EXTI0_IRQn + pin_num);
diff --git a/cpu/stm32l1/periph/i2c.c b/cpu/stm32l1/periph/i2c.c
index 3fad897d94f84a2e527ea2974f3dc54257894ea7..5d2d4f6d819733eefc18a5bdf2004f5b609c87c2 100644
--- a/cpu/stm32l1/periph/i2c.c
+++ b/cpu/stm32l1/periph/i2c.c
@@ -97,9 +97,9 @@ int i2c_init_master(i2c_t dev, i2c_speed_t speed)
     NVIC_EnableIRQ(i2c_config[dev].er_irqn);
 
     /* configure pins */
-    gpio_init(i2c_config[dev].scl, GPIO_DIR_OUT, GPIO_PULLUP);
+    gpio_init(i2c_config[dev].scl, i2c_config[dev].pin_mode);
     gpio_init_af(i2c_config[dev].scl, i2c_config[dev].af);
-    gpio_init(i2c_config[dev].sda, GPIO_DIR_OUT, GPIO_PULLUP);
+    gpio_init(i2c_config[dev].sda, i2c_config[dev].pin_mode);
     gpio_init_af(i2c_config[dev].sda, i2c_config[dev].af);
 
     /* configure device */
diff --git a/cpu/stm32l1/periph/uart.c b/cpu/stm32l1/periph/uart.c
index 22da881ef7a7a75e744781cbbad130dc50548092..056f261d8f45c5ed360600f1d7063bacff8400aa 100644
--- a/cpu/stm32l1/periph/uart.c
+++ b/cpu/stm32l1/periph/uart.c
@@ -114,9 +114,9 @@ static int init_base(uart_t uart, uint32_t baudrate)
     }
 
     /* uart_configure RX and TX pins, set pin to use alternative function mode */
-    gpio_init(tx_pin, GPIO_DIR_OUT, GPIO_NOPULL);
+    gpio_init(tx_pin, GPIO_OUT);
     gpio_init_af(tx_pin, af);
-    gpio_init(rx_pin, GPIO_DIR_IN, GPIO_NOPULL);
+    gpio_init(rx_pin, GPIO_IN);
     gpio_init_af(rx_pin, af);
 
     /* uart_configure UART to mode 8N1 with given baudrate */