diff --git a/drivers/leds/leds-tps68470.c b/drivers/leds/leds-tps68470.c
index 44df175d25de..abcd3494b1a8 100644
--- a/drivers/leds/leds-tps68470.c
+++ b/drivers/leds/leds-tps68470.c
@@ -8,6 +8,7 @@
  *	Kate Hsuan <hpa@redhat.com>
  */
 
+#include <linux/clk.h>
 #include <linux/leds.h>
 #include <linux/mfd/tps68470.h>
 #include <linux/module.h>
@@ -15,7 +16,10 @@
 #include <linux/platform_device.h>
 #include <linux/property.h>
 #include <linux/regmap.h>
+#include <linux/workqueue.h>
 
+#define work_to_led(work) \
+	container_of(work, struct tps68470_led, keepalive_work)
 
 #define lcdev_to_led(led_cdev) \
 	container_of(led_cdev, struct tps68470_led, lcdev)
@@ -26,20 +30,25 @@
 enum tps68470_led_ids {
 	TPS68470_ILED_A,
 	TPS68470_ILED_B,
+	TPS68470_WLED,
 	TPS68470_NUM_LEDS
 };
 
 static const char *tps68470_led_names[] = {
 	[TPS68470_ILED_A] = "tps68470-iled_a",
 	[TPS68470_ILED_B] = "tps68470-iled_b",
+	[TPS68470_WLED] = "tps68470-wled",
 };
 
 struct tps68470_led {
 	unsigned int led_id;
 	struct led_classdev lcdev;
+	enum led_brightness state;
+	struct work_struct keepalive_work;
 };
 
 struct tps68470_device {
+	struct clk *clk;
 	struct device *dev;
 	struct regmap *regmap;
 	struct tps68470_led leds[TPS68470_NUM_LEDS];
@@ -52,11 +61,33 @@ enum ctrlb_current {
 	CTRLB_16MA	= 3,
 };
 
+/*
+ * The WLED can operate in different modes, including a Flash and Torch mode. In
+ * each mode there's a timeout which ranges from a matter of milliseconds to up
+ * to 13 seconds. We don't want that timeout to apply though because the LED
+ * should be lit until we say that it should no longer be lit, re-trigger the
+ * LED periodically to keep it alive.
+ */
+static void tps68470_wled_keepalive_work(struct work_struct *work)
+{
+	struct tps68470_device *tps68470;
+	struct tps68470_led *led;
+
+	led = work_to_led(work);
+	tps68470 = led_to_tps68470(led, led->led_id);
+
+	regmap_update_bits_async(tps68470->regmap, TPS68470_REG_WLEDCTL,
+				 TPS68470_WLED_CTL_MASK, TPS68470_WLED_CTL_MASK);
+	schedule_work(&led->keepalive_work);
+}
+
 static int tps68470_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness)
 {
 	struct tps68470_led *led = lcdev_to_led(led_cdev);
 	struct tps68470_device *tps68470 = led_to_tps68470(led, led->led_id);
 	struct regmap *regmap = tps68470->regmap;
+	const char *errmsg;
+	int ret;
 
 	switch (led->led_id) {
 	case TPS68470_ILED_A:
@@ -65,8 +96,59 @@ static int tps68470_brightness_set(struct led_classdev *led_cdev, enum led_brigh
 	case TPS68470_ILED_B:
 		return regmap_update_bits(regmap, TPS68470_REG_ILEDCTL, TPS68470_ILEDCTL_ENB,
 					  brightness ? TPS68470_ILEDCTL_ENB : 0);
+	case TPS68470_WLED:
+		/*
+		 * LED core does not prevent re-setting brightness to its current
+		 * value; we need to do so here to avoid unbalanced calls to clk
+		 * enable/disable.
+		 */
+		if (led->state == brightness)
+			return 0;
+
+		if (brightness) {
+			schedule_work(&led->keepalive_work);
+
+			ret = clk_prepare_enable(tps68470->clk);
+			if (ret) {
+				errmsg = "failed to start clock\n";
+				goto err_cancel_work;
+			}
+		} else {
+			cancel_work_sync(&led->keepalive_work);
+			clk_disable_unprepare(tps68470->clk);
+		}
+
+		ret = regmap_update_bits(tps68470->regmap, TPS68470_REG_WLEDCTL,
+					 TPS68470_WLED_EN_MASK,
+					 brightness ? TPS68470_WLED_EN_MASK :
+						      ~TPS68470_WLED_EN_MASK);
+		if (ret) {
+			errmsg = "failed to set WLED EN\n";
+			goto err_disable_clk;
+		}
+
+		ret = regmap_update_bits(tps68470->regmap, TPS68470_REG_WLEDCTL,
+					 TPS68470_WLED_CTL_MASK,
+					 brightness ? TPS68470_WLED_CTL_MASK :
+						      ~TPS68470_WLED_CTL_MASK);
+		if (ret) {
+			errmsg = "failed to set WLED START\n";
+			goto err_disable_clk;
+		}
+
+		led->state = brightness;
+		break;
+	default:
+		return dev_err_probe(led_cdev->dev, -EINVAL, "invalid LED ID\n");
 	}
-	return -EINVAL;
+
+	return ret;
+
+err_disable_clk:
+	clk_disable_unprepare(tps68470->clk);
+err_cancel_work:
+	cancel_work_sync(&led->keepalive_work);
+	return dev_err_probe(tps68470->dev, ret, errmsg);
 }
 
 static enum led_brightness tps68470_brightness_get(struct led_classdev *led_cdev)
@@ -88,6 +170,14 @@ static enum led_brightness tps68470_brightness_get(struct led_classdev *led_cdev
 		value &= led->led_id == TPS68470_ILED_A ? TPS68470_ILEDCTL_ENA :
 					TPS68470_ILEDCTL_ENB;
 		break;
+	case TPS68470_WLED:
+		ret = regmap_read(regmap, TPS68470_REG_WLEDCTL, &value);
+		if (ret)
+			return dev_err_probe(led_cdev->dev, ret,
+					     "failed to read LED status\n");
+
+		value &= TPS68470_WLED_CTL_MASK;
+		break;
 	default:
 		return dev_err_probe(led_cdev->dev, -EINVAL, "invalid LED ID\n");
 	}
@@ -177,6 +267,11 @@ static int tps68470_leds_probe(struct platform_device *pdev)
 	tps68470->dev = &pdev->dev;
 	tps68470->regmap = dev_get_drvdata(pdev->dev.parent);
 
+	tps68470->clk = devm_clk_get(tps68470->dev, NULL);
+	if (IS_ERR(tps68470->clk))
+		return dev_err_probe(tps68470->dev, PTR_ERR(tps68470->clk),
+				     "failed to get clock\n");
+
 	for (i = 0; i < TPS68470_NUM_LEDS; i++) {
 		led = &tps68470->leds[i];
 		lcdev = &led->lcdev;
@@ -206,6 +301,11 @@ static int tps68470_leds_probe(struct platform_device *pdev)
 			if (ret)
 				goto err_exit;
 		}
+
+		if (led->led_id == TPS68470_WLED) {
+			INIT_WORK(&led->keepalive_work,
+				  tps68470_wled_keepalive_work);
+		}
 	}
 
 	ret = tps68470_leds_init(tps68470);
diff --git a/include/linux/mfd/tps68470.h b/include/linux/mfd/tps68470.h
index 2d2abb25b944..103ff730e028 100644
--- a/include/linux/mfd/tps68470.h
+++ b/include/linux/mfd/tps68470.h
@@ -35,6 +35,11 @@
 #define TPS68470_REG_GPDI		0x26
 #define TPS68470_REG_GPDO		0x27
 #define TPS68470_REG_ILEDCTL		0x28
+#define TPS68470_REG_WLEDMAXF		0x2F
+#define TPS68470_REG_WLEDTO		0x30
+#define TPS68470_REG_WLEDC1		0x34
+#define TPS68470_REG_WLEDC2		0x35
+#define TPS68470_REG_WLEDCTL		0x36
 #define TPS68470_REG_VCMVAL		0x3C
 #define TPS68470_REG_VAUX1VAL		0x3D
 #define TPS68470_REG_VAUX2VAL		0x3E
@@ -98,5 +103,12 @@
 #define TPS68470_ILEDCTL_ENA		BIT(2)
 #define TPS68470_ILEDCTL_ENB		BIT(6)
 #define TPS68470_ILEDCTL_CTRLB		GENMASK(5, 4)
+#define TPS68470_WLEDMAXF_MAX_CUR_MASK	GENMASK(4, 0)
+#define TPS68470_WLEDC_ILED_MASK	GENMASK(4, 0)
+#define TPS68470_WLED_MODE_MASK		GENMASK(1, 0)
+#define TPS68470_WLED_EN_MASK		BIT(2)
+#define TPS68470_WLED_DISLED1		BIT(3)
+#define TPS68470_WLED_DISLED2		BIT(4)
+#define TPS68470_WLED_CTL_MASK		BIT(5)
 
 #endif /* __LINUX_MFD_TPS68470_H */
