diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep
index 12ff91b964e76669a7fc1fe30231e0a01a544449..a3c70435384ad222065a6f0747ee03b0d01413ca 100644
--- a/drivers/Makefile.dep
+++ b/drivers/Makefile.dep
@@ -446,6 +446,11 @@ ifneq (,$(filter tsl2561,$(USEMODULE)))
   USEMODULE += xtimer
 endif
 
+ifneq (,$(filter tsl4531x,$(USEMODULE)))
+  FEATURES_REQUIRED += periph_i2c
+  USEMODULE += xtimer
+endif
+
 ifneq (,$(filter uart_half_duplex,$(USEMODULE)))
   FEATURES_REQUIRED += periph_gpio
   FEATURES_REQUIRED += periph_uart
@@ -475,7 +480,3 @@ ifneq (,$(filter xbee,$(USEMODULE)))
   USEMODULE += xtimer
   USEMODULE += netif
 endif
-
-ifneq (,$(filter tsl4531x,$(USEMODULE)))
-  FEATURES_REQUIRED += periph_i2c
-endif
diff --git a/drivers/Makefile.include b/drivers/Makefile.include
index 19bb780f39d6d8294f5aded1df906dd3f33bf8f3..1c2c0e61b289034854448584f815a7856dfe6676 100644
--- a/drivers/Makefile.include
+++ b/drivers/Makefile.include
@@ -242,6 +242,10 @@ ifneq (,$(filter tsl2561,$(USEMODULE)))
   USEMODULE_INCLUDES += $(RIOTBASE)/drivers/tsl2561/include
 endif
 
+ifneq (,$(filter tsl4531x,$(USEMODULE)))
+  USEMODULE_INCLUDES += $(RIOTBASE)/drivers/tsl4531x/include
+endif
+
 ifneq (,$(filter uart_half_duplex,$(USEMODULE)))
   USEMODULE_INCLUDES += $(RIOTBASE)/drivers/uart_half_duplex/include
 endif
diff --git a/drivers/include/tsl4531x.h b/drivers/include/tsl4531x.h
index 2bcd4b6a4290504cd6a3a49b387b421125f6ff03..cc799734675e283fe7bc13165bafa46f980b8ec3 100644
--- a/drivers/include/tsl4531x.h
+++ b/drivers/include/tsl4531x.h
@@ -12,49 +12,184 @@
  * @brief       Device driver for the AMS TSL4531 sensor
  * @{
  *
+ * # Power modes
+ *
+ * This driver has two power modes: high and low. Its startup mode is configured
+ * in the initialization parameters, and it can also be changed during runtime.
+ *
+ * In high power mode, the user application can read from the device using the
+ * tsl4531x_simple_read function, and it will return immediately.
+ *
+ * In low power mode, the user application can interact with the driver in a
+ * synchronous or asynchronous manner. For synchronous operation, the application
+ * can call tsl4531x_simple_read, and the driver will block for the integration
+ * time defined in the initialization parameters (plus a small margin, to encompass
+ * the max times indicated in the datasheet). For asyncronous operation, the
+ * application needs to use the functions tsl4531x_start_sample,
+ * tsl4531x_time_until_sample_ready and tsl4531x_get_sample, as described in those
+ * functions' descriptions.
+ *
+ * Both modes will work through SAUL, with the low-power mode being synchronous.
+ *
  * @file
  * @brief       Device driver for the AMS TSL4531 sensor
  *
  * @author      Juan I Carrano <j.carrano@fu-berlin.de>
+ * @author      Daniel Petry <daniel.petry@fu-berlin.de>
  */
 
-#ifndef TSL4531x_H
-#define TSL4531x_H
+#ifndef TSL4531X_H
+#define TSL4531X_H
 
 #include <stdint.h>
 
 #include "periph/i2c.h"
 
-static const uint16_t TSL4531x_INTEGRATE_400ms = 0; /* 0b00 */
-static const uint16_t TSL4531x_INTEGRATE_200ms = 1; /* 0b01 */
-static const uint16_t TSL4531x_INTEGRATE_100ms = 2; /* 0b10 */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Integration times
+ */
+typedef enum {
+    TSL4531X_INTEGRATE_400MS = 0,       /* 0b00 */
+    TSL4531X_INTEGRATE_200MS = 1,       /* 0b01 */
+    TSL4531X_INTEGRATE_100MS = 2,       /* 0b10 */
+}tsl4531x_intgn_time_t;
+
+/**
+ * @name  Fixed values for different members of the TSL4531x series
+ * @{
+ *
+ * @brief Part numbers
+ */
+#define TSL45311_PARTNO                  (0x8)
+#define TSL45313_PARTNO                  (0x9)
+#define TSL45315_PARTNO                  (0xA)
+#define TSL45317_PARTNO                  (0xB)
+
+/**
+ * @brief TSL4531x I2C addresses
+ */
+#define TSL45311_ADDR                    (0x39)
+#define TSL45313_ADDR                    (0x39)
+#define TSL45315_ADDR                    (0x29)
+#define TSL45317_ADDR                    (0x29)
+/** @} */
 
 /**
- * @brief   Represents a single TSL4531x device.
+ * @brief Device initialization parameters
  */
-typedef struct tsl4531x {
-    i2c_t i2c_dev;
-    uint8_t integration_time;
+typedef struct {
+    i2c_t i2c_dev;                              /**< I2C device which is used */
+    i2c_t i2c_addr;                             /**< I2C address of sensor */
+    tsl4531x_intgn_time_t integration_time;     /**< integration time */
+    uint8_t low_power_mode : 1;                 /**< low power mode */
+    uint8_t part_number;                        /**< part number, according to variant */
+} tsl4531x_params_t;
+
+/**
+ * @brief Device descriptor
+ */
+typedef struct {
+    i2c_t i2c_dev;                              /**< I2C device which is used */
+    i2c_t i2c_addr;                             /**< I2C address of sensor */
+    tsl4531x_intgn_time_t integration_time;     /**< integration time */
+    uint8_t low_power_mode : 1;                 /**< low power mode */
+    uint8_t high_power_mode_started_up : 1;     /**< high power mode started up flag */
+    uint32_t sample_start_time;                 /**< sample start time */
 } tsl4531x_t;
 
 /**
- * Initialize TSL4513 device.
+ * Initialize the TSL4531x device.
+ *
+ * @param[out] dev        Initialized device descriptor
+ * @param[in]  params     Device initialization parameters
+ *
+ * @return     Zero on success
+ * @return     -ENODEV if I2C bus can't be acquired
+ * @return     -ENXIO if device can't be read or configured
+ * @return     -ENOTSUP if ID, once read, is wrong
+ */
+int tsl4531x_init(tsl4531x_t *dev, const tsl4531x_params_t *params);
+
+/**
+ * Set the low power mode of the driver on or off.
+ *
+ * @param      dev           Initialized device descriptor
+ * @param      low_power_on  Bool indicating whether low power mode is on or off
+ *
+ * @return     Zero
+ */
+int tsl4531x_set_low_power_mode(tsl4531x_t *dev, uint8_t low_power_on);
+
+/**
+ * Start collecting sample in low power mode. This provides asynchronous operation
+ * along with tsl4531x_time_until_sample_ready and tsl4531x_get_sample. It does
+ * nothing in high power mode.
+ *
+ * @param      dev           Initialized device descriptor
+ *
+ * @return     Zero
+ */
+int tsl4531x_start_sample(tsl4531x_t *dev);
+
+/**
+ * Deliver time in microseconds until sample is ready, or zero if it is ready.
+ * In low power mode, this counts down from the point at which tsl4531x_start_sample
+ * is called, and along with that function and tsl4531x_get_sample, provides
+ * asynchronous operation. In high power mode, this counts down from the point
+ * at which the driver is switched into high power mode or started up, and
+ * indicates whether enough time has passed for a full sample to be collected.
+ *
+ * Note that for low power mode this rolls over and repeats its behaviour every
+ * 1.2 hours. The sample should have been collected well before this, however.
+ *
+ * The countdown time equals the integration time, which can be set in the
+ * device initialisation parameters, plus 5% margin to encompass the max times
+ * indicated in the datasheet.
  *
- * @param   dev     Device object.
- * @param   i2c_dev I2C interface to use.
- * @param   integration_time  one of TSL4531x_INTEGRATE_400ms,
- *                              TSL4531x_INTEGRATE_200ms, TSL4531x_INTEGRATE_100ms.
+ * @param      dev           Initialized device descriptor
  *
- * @return  Zero on success, negative on error.
+ * @return    Time in microseconds until sample is ready
  */
-int tsl4531x_init(tsl4531x_t *dev, i2c_t i2c_dev, uint8_t integration_time);
+uint32_t  tsl4531x_time_until_sample_ready(tsl4531x_t *dev);
 
 /**
- * Get the last measurements of illuminance, in lux.
+ * Reads the sample from the device immediately. In high power mode, this does
+ * the same as tsl4531x_simple_read once the device has performed one
+ * integration cycle. In low power mode, this provides asynchronous operation
+ * along with tsl4531x_start_sample and tsl4531x_time_until_sample_ready which
+ * determine whether the device has performed an integration cycle.
  *
- * @return  0 on sucess, negative on error. If there is an error, the value of
- *           `*result_lux` is undefined.
+ * Note that this function will always return the value stored in the device's
+ * internal register, and this value will be sensible physically, representing
+ * the last time an integration cycle has been performed. However, in order for
+ * it to be accurate, the start_sample and time_until_sample_ready functions
+ * need to also be used, or alternatively the simple_read function can be used.
+ *
+ * @param      dev           Initialized device descriptor
+ *
+ * @return     The sample value in Lux
  */
-int tsl4531x_read(const tsl4531x_t *dev, uint16_t *result_lux);
+int tsl4531x_get_sample(const tsl4531x_t *dev);
+
+/**
+ * Reads the sample from the device. In low power mode, or in high power mode
+ * just after startup, this starts collecting the sample, blocks until the
+ * sample is ready (400/200/100ms depending on the integration time set in the
+ * initialization parameters), and then reads and returns the sample.
+ *
+ * @param      dev           Initialized device descriptor
+ *
+ * @return     The sample value in Lux
+ */
+int tsl4531x_simple_read(tsl4531x_t *dev);
+
+#ifdef __cplusplus
+}
+#endif
 
-#endif /* TSL4531x_H */
+#endif /* TSL4531X_H */
+/** @} */
diff --git a/drivers/include/tsl4531x_saul.h b/drivers/include/tsl4531x_saul.h
deleted file mode 100644
index 7783b1f469d812e7f96e1a02b976ce9b7c22466e..0000000000000000000000000000000000000000
--- a/drivers/include/tsl4531x_saul.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2018 Freie Universität Berlin
- *
- * This file is subject to the terms and conditions of the GNU Lesser
- * General Public License v2.1. See the file LICENSE in the top level
- * directory for more details.
- */
-
-/**
- * @ingroup     drivers_tsl4531x
- * @{
- *
- * @file
- * @brief       SAUL interface for TSL4531 Luminosity sensor.
- *
- * @author      Juan I Carrano <j.carrano@fu-berlin.de>
- *
- * @}
- */
-
-#ifndef TSL4531x_SAUL_H
-#define TSL4531x_SAUL_H
-
-#include "saul.h"
-
-/** SAUL-compatible structure for illuminance sensor
- */
-const saul_driver_t tsl4531x_saul_driver;
-
-#endif /* TSL4531x_SAUL_H */
-
diff --git a/drivers/tsl4531x/include/tsl4531x_internals.h b/drivers/tsl4531x/include/tsl4531x_internals.h
new file mode 100644
index 0000000000000000000000000000000000000000..514f8209887aff35b5a045bc437e205ba3edad1c
--- /dev/null
+++ b/drivers/tsl4531x/include/tsl4531x_internals.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2017 Inria
+ * Copyright (C) 2018 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     drivers_tsl4531x
+ * @brief       Internal addresses, registers, constants for the TSL4531x sensor.
+ * @{
+ *
+ * @file
+ * @brief       Internal addresses, registers, constants for the TSL4531x sensor.
+ *
+ * @author      Alexandre Abadie <alexandre.abadie@inria.fr>
+ * @author      Daniel Petry <danielpetry@cantab.net>
+ * @author      Juan I Carrano <j.carrano@fu-berlin.de>
+ *
+ * Derived from the internals.h file for the tsl2561 driver.
+ */
+
+#ifndef TSL4531X_INTERNALS_H
+#define TSL4531X_INTERNALS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @name TSL4531x internal registers
+ * @{
+ */
+#define TSL4531X_CONTROL_REG             (0x0)      /**< sets power mode */
+#define TSL4531X_CONFIGURATION_REG       (0x01)     /**< sets power mode */
+#define TSL4531X_ALSDATA1_REG            (0x04)     /**< contains DATALOW */
+#define TSL4531X_ALSDATA2_REG            (0x05)     /**< contains DATAHIGH */
+#define TSL4531X_ID_REG                  (0x0A)     /**< contains part no above*/
+/** @} */
+
+/**
+ * @name TSL4531x power modes
+ * @{
+ */
+#define TSL4531X_MODE_POWER_DOWN         (0x00)
+#define TSL4531X_MODE_RESERVED           (0x01)
+#define TSL4531X_MODE_SINGLE_ADC_CYCLE   (0x02)     /**< Runs a single ADC cycle then
+                                                       returns to power down. */
+#define TSL4531X_MODE_NORMAL             (0x03)
+
+/* PowerSave saves some power in full power mode. PowerSave skip turns this off.
+ * Currently PowerSave skip is hard-coded to be on for simplicity, as it's just
+ * an intermediate between normal mode and low-power mode. */
+#define TSL4531X_PSAVESKIP_OFF           (0)
+#define TSL4531X_PSAVESKIP_ON            (1)
+/** @} */
+
+/**
+ * @name TSL4531x macros
+ * @{
+ */
+/* Assemble the Command register */
+#define TSL4531X_COMMAND(addr)   ((1 << 7) | (addr))
+
+/* Assemble the Configuration register */
+#define TSL4531X_CONFIG(psaveskip, tcntrl)  (((!!(psaveskip)) << 3) | (tcntrl))
+
+/* Assemble the Control register */
+#define TSL4531X_CONTROL(mode)  (mode)
+
+#define TSL4531X_GET_PARTNO(id_reg)  ((id_reg) >> 4)
+
+/* Data multiplier according to integration time.
+ *
+ * From the manual:
+ *      MULTIPLIER = 1 for TCNTRL = 00 (Tint = 400 ms)
+ *      MULTIPLIER = 2 for TCNTRL = 01 (Tint = 200 ms)
+ *      MULTIPLIER = 4 for TCNTRL = 10 (Tint = 100 ms)
+ */
+#define MULTIPLY_DATA(data_raw, integration_time) ((data_raw) << (integration_time))
+
+/* This allows either full power mode or power down mode. */
+#define TSL4531X_POWER_MODE(mode) ((!mode) * (0x03))
+
+/* The full integration time is a sum of:
+ * 1. A worst-case time for each of the integration times, which according to
+ *    the datasheet is 5% more than the nominal time
+ * 2. 60, 30 or 15 ms, according to the integration time, if PowerSave is on;
+ *    which is the power down period in between integration cycles in this mode.
+ *    Note that in the current implementation, the "PowerSave skip" option is
+ *    hard-coded to be on, as PowerSave only gives slightly less power
+ *    consumption than normal mode.
+ */
+#define TSL4531X_GET_INTEGRATION_TIME_USEC(int_time_setting, psaveskip) \
+    (uint32_t)1000 * (((0x04 >> int_time_setting) * 105) + ((!psaveskip) * (60 >> int_time_setting)))
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TSL4531X_INTERNALS_H */
+/** @} */
diff --git a/drivers/tsl4531x/include/tsl4531x_params.h b/drivers/tsl4531x/include/tsl4531x_params.h
new file mode 100644
index 0000000000000000000000000000000000000000..c6b548b7dd26200e773ca86a92cd9a281c8d5743
--- /dev/null
+++ b/drivers/tsl4531x/include/tsl4531x_params.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 Inria
+ * Copyright (C) 2018 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     drivers_tsl4531x
+ *
+ * @{
+ * @file
+ * @brief       Default configuration for tsl4531x light sensor.
+ *
+ * @author      Alexandre Abadie <alexandre.abadie@inria.fr>
+ * @author      Daniel Petry <danielpetry@cantab.net>
+ *
+ * Derived from the default configuration for the tsl2561 driver.
+ */
+
+#ifndef TSL4531X_PARAMS_H
+#define TSL4531X_PARAMS_H
+
+#include "board.h"
+#include "saul_reg.h"
+#include "tsl4531x.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @name    Set default configuration parameters for the TSL4531x
+ * @{
+ */
+#ifndef TSL4531X_PARAM_I2C_DEV
+#define TSL4531X_PARAM_I2C_DEV         I2C_DEV(0)
+#endif
+#ifndef TSL4531X_PARAM_I2C_ADDR
+#define TSL4531X_PARAM_I2C_ADDR        TSL45315_ADDR
+#endif
+#ifndef TSL4531X_PARAM_INTEGRATION
+#define TSL4531X_PARAM_INTEGRATION     TSL4531X_INTEGRATE_400MS
+#endif
+#ifndef TSL4531X_LOW_POWER_MODE
+#define TSL4531X_LOW_POWER_MODE        (false)
+#endif
+#ifndef TSL4531X_PARAM_PARTNO
+#define TSL4531X_PARAM_PARTNO          TSL45315_PARTNO
+#endif
+#ifndef TSL4531X_PARAMS
+#define TSL4531X_PARAMS                { .i2c_dev     = TSL4531X_PARAM_I2C_DEV, \
+                                         .i2c_addr    = TSL4531X_PARAM_I2C_ADDR, \
+                                         .integration_time = TSL4531X_PARAM_INTEGRATION, \
+                                         .low_power_mode = TSL4531X_LOW_POWER_MODE, \
+                                         .part_number = TSL4531X_PARAM_PARTNO }
+#endif
+
+#ifndef TSL4531X_SAUL_INFO
+#define TSL4531X_SAUL_INFO             { .name = "tsl4531x" }
+#endif
+/**@}*/
+
+/**
+ * @brief   Configure TSL4531x
+ */
+static const tsl4531x_params_t tsl4531x_params[] =
+{
+    TSL4531X_PARAMS
+};
+
+/**
+ * @brief   Allocate and configure entries to the SAUL registry
+ */
+saul_reg_info_t tsl4531x_saul_info[] =
+{
+    TSL4531X_SAUL_INFO
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TSL4531X_PARAMS_H */
+/** @} */
diff --git a/drivers/tsl4531x/tsl4531x.c b/drivers/tsl4531x/tsl4531x.c
index 703982ad77ef989ddfcd1865f40bae73f17f072f..13bdaf1f75000600cb63d163117c7dae050e30a8 100644
--- a/drivers/tsl4531x/tsl4531x.c
+++ b/drivers/tsl4531x/tsl4531x.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2016 Inria
  * Copyright (C) 2018 Freie Universität Berlin
  *
  * This file is subject to the terms and conditions of the GNU Lesser
@@ -11,15 +12,13 @@
  * @{
  *
  * @file
- * @brief       Device driver for the TSL4531 Luminosity sensor.
+ * @brief       Device driver for the TSL4531x Luminosity sensor.
  *
+ * @author      Daniel Petry <daniel.petry@fu-berlin.de>
  * @author      Juan I Carrano <j.carrano@fu-berlin.de>
+ * @author      Alexandre Abadie <alexandre.abadie@inria.fr>
  *
- * This driver was derived from the one for TSL2561.
- *
- * @todo    The i2c address is hardcoded
- * @todo    The only operating mode is "Normal Operation"
- * @todo    PowerSave is not supported
+ * This driver was derived from the TSL2561 driver.
  *
  * @}
  */
@@ -28,113 +27,202 @@
 
 #include "log.h"
 #include "tsl4531x.h"
+#include "tsl4531x_internals.h"
+#include "xtimer.h"
 
 #define ENABLE_DEBUG        (0)
 #include "debug.h"
 
-static const uint16_t TSL4531_Addr = 0x29;
-static const uint16_t TSL4531_PARTNO = 0xA; /* 0b1010 */
+#define _DATALOW 0
+#define _DATAHIGH 1
 
-static const uint16_t Control_Reg = 0x0;
-static const uint16_t Configuration_Reg = 0x01;
-static const uint16_t ALSData1_Reg = 0x04;  /* contains DATALOW */
-static const uint16_t ALSData2_Reg = 0x05;  /* contains DATAHIGH */
-static const uint16_t ID_Reg = 0x0A;
+int tsl4531x_init(tsl4531x_t *dev, const tsl4531x_params_t *params)
+{
+    int r;
+    uint8_t id;
 
-static const uint16_t TSL4531x_MODE_Normal = 0x03; /* 0b11 */
+    /* Initialise I2C bus */
+    if ((r = i2c_acquire(params->i2c_dev)) < 0) {
+        DEBUG("I2C_dev is: %d.", params->i2c_dev);
+        DEBUG("[Error] Cannot acquire device. I2C error: %d\n", r);
+        return -ENODEV;
+    }
 
-/* Assemble the Command register */
-#define TSL4531_COMMAND(addr)   ((1<<7)|(addr))
+    /* Test for connectivity - verify ID and compare against stored value */
+    if ((r = i2c_read_reg(params->i2c_dev,
+                          params->i2c_addr,
+                          TSL4531X_COMMAND(TSL4531X_ID_REG),
+                          &id, 0)) < 0) {
+        DEBUG("[Error] Cannot read ID register. I2C error: %d\n", r);
+        i2c_release(params->i2c_dev);
+        return -ENXIO;
+    }
 
-/* Assemble the Configuration register */
-#define TSL4531_CONFIG(psaveskip, tcntrl)  (((!!(psaveskip)) << 3) | (tcntrl))
+    DEBUG("[Info] tsl4531x sensor ID ? %d\n", id);
 
-/* Assemble the Control register */
-#define TSL4531_CONTROL(mode)  (mode)
+    if (TSL4531X_GET_PARTNO(id) != params->part_number) {
+        DEBUG("[Error] not a TSL4531 sensor.\n");
+        i2c_release(params->i2c_dev);
+        return -ENOTSUP;
+    }
 
-#define TSL4531_GET_PARTNO(id_reg)  ((id_reg) >> 4)
+    /* Configure device. In low power mode, we initially power the sensor down. */
+    if (((r = i2c_write_reg(params->i2c_dev,
+                            params->i2c_addr,
+                            TSL4531X_COMMAND(TSL4531X_CONTROL_REG),
+                            TSL4531X_CONTROL(TSL4531X_POWER_MODE(params->low_power_mode)),
+                            0)) < 0)
+        ||
+        ((r = i2c_write_reg(params->i2c_dev,
+                            params->i2c_addr,
+                            TSL4531X_COMMAND(TSL4531X_CONFIGURATION_REG),
+                            TSL4531X_CONFIG(TSL4531X_PSAVESKIP_ON, params->integration_time),
+                            0)) < 0)) {
+
+        DEBUG("[Error] Cannot configure device. I2C error: %d\n", r);
+        i2c_release(params->i2c_dev);
+        return -ENXIO;
+    }
 
-/* Apply the multiplier corresponding to the active integration time */
-/* From the manual:
- *      MULTIPLIER = 1 for TCNTRL = 00 (Tint = 400 ms),
- *      MULTIPLIER = 2 for TCNTRL = 01 (Tint = 200 ms), and
- *      MULTIPLIER = 4 for TCNTRL = 10 (Tint = 100 ms), and
- */
-#define MULTIPLY_DATA(data_raw, integration_time) ((data_raw) << (integration_time))
+    /* If device was configured correctly, initialise the device descriptor */
+    dev->i2c_dev = params->i2c_dev;
+    dev->i2c_addr = params->i2c_addr;
+    dev->integration_time = params->integration_time;
+    dev->low_power_mode = params->low_power_mode;
+    dev->high_power_mode_started_up = false;
+    dev->sample_start_time = 0; /* Device assumed to start up at same time as
+                                   microcontroller - i.e. when it hits this line */
 
-int tsl4531x_init(tsl4531x_t *dev, i2c_t i2c_dev, uint8_t integration_time)
+    i2c_release(params->i2c_dev);
+
+    return 0;
+}
+
+int tsl4531x_set_low_power_mode(tsl4531x_t *dev, uint8_t low_power_mode)
 {
+    assert(dev);
+
     int r;
-    uint8_t id;
 
-    dev->i2c_dev = i2c_dev;
-    dev->integration_time = integration_time;
+    dev->low_power_mode = low_power_mode;
 
     if ((r = i2c_acquire(dev->i2c_dev)) < 0) {
-        DEBUG("[Error] Cannot acquire device: %d\n", r);
-        goto acquire_error;
+        DEBUG("[Error] Cannot acquire device. I2C error: %d\n", r);
+        return -ENODEV;
     }
 
-    /* Verify sensor ID */
-    if ((r = i2c_read_reg(dev->i2c_dev, TSL4531_Addr, TSL4531_COMMAND(ID_Reg),
-                          &id, 0)) < 0) {
-        DEBUG("[Error] Cannot read ID register: %d\n", r);
-        goto init_error;
-    }
-    DEBUG("[Info] ID ? %d\n", id);
-    if (TSL4531_GET_PARTNO(id) != TSL4531_PARTNO) {
-        DEBUG("[Error] not a TSL4531 sensor\n");
-        r = -ENOTSUP;
-        goto init_error;
+    if ((r = i2c_write_reg(dev->i2c_dev,
+                           dev->i2c_addr,
+                           TSL4531X_COMMAND(TSL4531X_CONTROL_REG),
+                           TSL4531X_CONTROL(TSL4531X_POWER_MODE(low_power_mode)),
+                           0)) < 0) {
+        DEBUG("[Error] Cannot write power mode. I2C error: %d\n", r);
+        i2c_release(dev->i2c_dev);
+        return -ENXIO;
     }
 
-    /* configure device */
-    if (((r = i2c_write_reg(dev->i2c_dev , TSL4531_Addr, TSL4531_COMMAND(Control_Reg),
-                  TSL4531_CONTROL(TSL4531x_MODE_Normal), 0)) < 0)
-         ||
-         ((r = i2c_write_reg(dev->i2c_dev , TSL4531_Addr, TSL4531_COMMAND(Configuration_Reg),
-                  TSL4531_CONFIG(1, integration_time), 0)) < 0)) {
-        DEBUG("[Error] Cannot configure device %d\n", r);
-        goto init_error;
+    i2c_release(dev->i2c_dev);
+
+    /* In high power mode only, we restart the sample ready timer, because only
+       in this mode it's used to indicate readiness after startup. */
+    if (!dev->low_power_mode) {
+        dev->sample_start_time = xtimer_now_usec();
     }
 
-init_error:
-    /* ignore errors on device release */
-    i2c_release(dev->i2c_dev);
+    return 0;
+}
 
-acquire_error:
+int tsl4531x_start_sample(tsl4531x_t *dev)
+{
+    assert(dev);
+
+    /* Don't change the mode to one-shot if the device is in high power mode. */
+    if (dev->low_power_mode) {
+
+        int r;
+
+        if ((r = i2c_acquire(dev->i2c_dev)) < 0) {
+            DEBUG("[Error] Cannot acquire device. I2C error: %d\n", r);
+            return -ENODEV;
+        }
+
+        if ((r = i2c_write_reg(dev->i2c_dev,
+                               dev->i2c_addr,
+                               TSL4531X_COMMAND(TSL4531X_CONTROL_REG),
+                               TSL4531X_CONTROL(TSL4531X_MODE_SINGLE_ADC_CYCLE),
+                               0)) < 0) {
+            DEBUG("[Error] Cannot write power mode. I2C error: %d\n", r);
+            i2c_release(dev->i2c_dev);
+            return -ENXIO;
+        }
+
+        i2c_release(dev->i2c_dev);
 
-    return r;
+        dev->sample_start_time = xtimer_now_usec();
+    }
+
+    return 0;
 }
 
-#define _DATALOW 0
-#define _DATAHIGH 1
+uint32_t tsl4531x_time_until_sample_ready(tsl4531x_t *dev)
+{
+    assert(dev);
+
+    uint32_t t = TSL4531X_GET_INTEGRATION_TIME_USEC(dev->integration_time, TSL4531X_PSAVESKIP_ON) -
+                 (xtimer_now_usec() - dev->sample_start_time);
+
+    /* Clamp t at zero */
+    t = (t <= TSL4531X_GET_INTEGRATION_TIME_USEC(dev->integration_time, TSL4531X_PSAVESKIP_ON) ?
+         t : 0);
+
+    if (!dev->low_power_mode) {
+        if (t == 0) {
+            dev->high_power_mode_started_up = true;
+        }
+        if (dev->high_power_mode_started_up) {
+            return 0;
+        }
+    }
+
+    return t;
+}
 
-int tsl4531x_read(const tsl4531x_t *dev, uint16_t *result_lux)
+int tsl4531x_get_sample(const tsl4531x_t *dev)
 {
+    assert(dev);
+
     int r;
     uint8_t als_data[2]; /* = {[DATALOW], [DATAHIGH]} */
 
     if ((r = i2c_acquire(dev->i2c_dev)) < 0) {
-        DEBUG("[Error] Cannot acquire device: %d\n", r);
-        goto read_acquire_error;
+        DEBUG("[Error] Cannot acquire device. I2C error: %d\n", r);
+        return -ENODEV;
     }
 
-    if ((r = i2c_read_regs(dev->i2c_dev, TSL4531_Addr, TSL4531_COMMAND(ALSData1_Reg),
-                  als_data, 2, 0)) < 0) {
-        (void)ALSData2_Reg; /* suppress warning */
-        DEBUG("[Error] Cannot read device: %d\n", r);
-        goto read_error;
+    if ((r = i2c_read_regs(dev->i2c_dev,
+                           dev->i2c_addr,
+                           TSL4531X_COMMAND(TSL4531X_ALSDATA1_REG),
+                           als_data, 2, 0)) < 0) {
+        DEBUG("[Error] Cannot read data register. I2C error: %d\n", r);
+        i2c_release(dev->i2c_dev);
+        return -ENXIO;
     }
 
-    *result_lux = MULTIPLY_DATA((((uint16_t)als_data[_DATAHIGH]) << 8)
-                            + als_data[_DATALOW], dev->integration_time);
-
-read_error:
-    /* ignore errors on device release */
     i2c_release(dev->i2c_dev);
 
-read_acquire_error:
-    return r;
+    return MULTIPLY_DATA((((uint16_t)als_data[_DATAHIGH]) << 8)
+                         + als_data[_DATALOW], dev->integration_time);
 }
 
+int tsl4531x_simple_read(tsl4531x_t *dev)
+{
+    assert(dev);
+
+    if (dev->low_power_mode) {
+        tsl4531x_start_sample(dev);
+    }
+
+    xtimer_usleep(tsl4531x_time_until_sample_ready(dev));
+
+    return tsl4531x_get_sample(dev);
+}
diff --git a/drivers/tsl4531x/tsl4531x_saul.c b/drivers/tsl4531x/tsl4531x_saul.c
index 010c146111e410962668f434cb1ec5f73015f063..ee719ac230e8097541afa99671140e305eb786ad 100644
--- a/drivers/tsl4531x/tsl4531x_saul.c
+++ b/drivers/tsl4531x/tsl4531x_saul.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2016 Inria
  * Copyright (C) 2018 Freie Universität Berlin
  *
  * This file is subject to the terms and conditions of the GNU Lesser
@@ -11,27 +12,25 @@
  * @{
  *
  * @file
- * @brief       SAUL interface for TSL4531 Luminosity sensor.
+ * @brief       SAUL interface for TSL4531x Luminosity sensor.
  *
  * @author      Juan I Carrano <j.carrano@fu-berlin.de>
+ * @author      Daniel Petry <daniel.petry@fu-berlin.de>
  *
  * @}
  */
 
+#include <string.h>
 #include "saul.h"
 #include "tsl4531x.h"
 
-static int _read(const void *dev, phydat_t *res)
+static int _read(const void *dev, phydat_t *data)
 {
-    int nvals;
-    uint16_t lux;
-
-    nvals = (tsl4531x_read(dev, &lux) >= 0)? 1 : 0;
-
-    res->val[0] = lux;
-    res->unit = UNIT_LUX;
-    res->scale = 0;
-    return nvals;
+    memset(data, 0, sizeof(phydat_t));
+    data->val[0] = tsl4531x_simple_read((const tsl4531x_t *)dev);
+    data->unit = UNIT_LUX;
+    data->scale = 0;
+    return 1;
 }
 
 const saul_driver_t tsl4531x_saul_driver = {