From 6df41298dc6daf80b59fc174c9644d0ab730ea73 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Jirman?= <megi@xff.cz>
Date: Mon, 30 Sep 2019 11:49:54 +0200
Subject: [PATCH] mtd: spi-nor: Add regulator support

Signed-off-by: Ondrej Jirman <megi@xff.cz>
---
 drivers/mtd/spi-nor/core.c  | 37 +++++++++++++++++++++++++++++++------
 include/linux/mtd/spi-nor.h |  3 +++
 2 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 5dbf52aa0..39241ed62 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -3103,6 +3103,22 @@ static int spi_nor_probe(struct spi_mem *spimem)
 	if (!nor)
 		return -ENOMEM;
 
+	nor->reg_vdd = devm_regulator_get(&spi->dev, "vdd");
+	if (IS_ERR(nor->reg_vdd)) {
+		ret = PTR_ERR(nor->reg_vdd);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&spi->dev, "unable to get regulator: %d\n", ret);
+		return ret;
+	}
+
+	ret = regulator_enable(nor->reg_vdd);
+	if (ret) {
+		dev_err(&spi->dev, "unable to enable regulator: %d\n", ret);
+		return ret;
+	}
+
+	msleep(5);
+
 	nor->spimem = spimem;
 	nor->dev = &spi->dev;
 	spi_nor_set_flash_node(nor, spi->dev.of_node);
@@ -3130,7 +3146,7 @@ static int spi_nor_probe(struct spi_mem *spimem)
 
 	ret = spi_nor_scan(nor, flash_name, &hwcaps);
 	if (ret)
-		return ret;
+		goto err_reg_disable;
 
 	spi_nor_debugfs_register(nor);
 
@@ -3145,20 +3161,28 @@ static int spi_nor_probe(struct spi_mem *spimem)
 		nor->bouncebuf = devm_kmalloc(nor->dev,
 					      nor->bouncebuf_size,
 					      GFP_KERNEL);
-		if (!nor->bouncebuf)
-			return -ENOMEM;
+		if (!nor->bouncebuf) {
+			ret = -ENOMEM;
+			goto err_reg_disable;
+		}
 	}
 
 	ret = spi_nor_create_read_dirmap(nor);
 	if (ret)
-		return ret;
+		goto err_reg_disable;
 
 	ret = spi_nor_create_write_dirmap(nor);
 	if (ret)
-		return ret;
+		goto err_reg_disable;
 
-	return mtd_device_register(&nor->mtd, data ? data->parts : NULL,
+	ret = mtd_device_register(&nor->mtd, data ? data->parts : NULL,
 				   data ? data->nr_parts : 0);
+	if (!ret)
+		return 0;
+
+err_reg_disable:
+	regulator_disable(nor->reg_vdd);
+	return ret;
 }
 
 static int spi_nor_remove(struct spi_mem *spimem)
@@ -3166,6 +3190,7 @@ static int spi_nor_remove(struct spi_mem *spimem)
 	struct spi_nor *nor = spi_mem_get_drvdata(spimem);
 
 	spi_nor_restore(nor);
+	regulator_disable(nor->reg_vdd);
 
 	/* Clean up MTD stuff. */
 	return mtd_device_unregister(&nor->mtd);
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index f92bf7f7a..193aceba8 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -9,6 +9,7 @@
 #include <linux/bitops.h>
 #include <linux/mtd/mtd.h>
 #include <linux/spi/spi-mem.h>
+#include <linux/regulator/consumer.h>
 
 /*
  * Note on opcode nomenclature: some opcodes have a format like
@@ -403,6 +404,8 @@ struct spi_nor {
 		struct spi_mem_dirmap_desc *wdesc;
 	} dirmap;
 
+	struct regulator* reg_vdd;
+
 	void *priv;
 };
 
-- 
2.35.3

