[PATCH V3 3/4] regulator: pv88080: Update Regulator driver for MFD support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Eric Jeong <eric.jeong.opensource@xxxxxxxxxxx>

This change convert from using struct i2c_clinet 
to using struct platform_device for MFD structure.
And, the declaration of of_device_id and regmap_config
are also move to MFD driver.

The configuration for MASK registers is moved 
to MFD core.

Kconfig is updated to reflect support for PV88080 regulator.

Signed-off-by: Eric Jeong <eric.jeong.opensource@xxxxxxxxxxx>

---
This patch applies against linux-next and next-20161117

Hi,

The existing PV88080 regulstor driver is updated to support
MFD structure by adding GPIO function.
Most of changes are related with MFD structure support.

Change since PATCH V2
 - Fix regression in config and driver
 - Change IRQ name.

Change since PATCH V1
 - Patch separated from PATCH V1

Regards,
Eric Jeong, Dialog Semiconductor Ltd.


 drivers/regulator/Kconfig             |    9 +-
 drivers/regulator/pv88080-regulator.c |  185 +++++++++++----------------------
 drivers/regulator/pv88080-regulator.h |  118 ---------------------
 3 files changed, 66 insertions(+), 246 deletions(-)
 delete mode 100644 drivers/regulator/pv88080-regulator.h

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 936f7cc..ea89653 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -577,10 +577,13 @@ config REGULATOR_PV88060
 
 config REGULATOR_PV88080
 	tristate "Powerventure Semiconductor PV88080 regulator"
-	depends on I2C
-	select REGMAP_I2C
+	depends on MFD_PV88080
 	help
-	  Say y here to support the buck convertors on PV88080
+	  Say y here to support the BUCKs regulators found on
+	  PV88080 PMICs.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called pv88080-regulator.
 
 config REGULATOR_PV88090
 	tristate "Powerventure Semiconductor PV88090 regulator"
diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c
index 954a20e..eb9024d 100644
--- a/drivers/regulator/pv88080-regulator.c
+++ b/drivers/regulator/pv88080-regulator.c
@@ -14,8 +14,8 @@
  */
 
 #include <linux/err.h>
-#include <linux/i2c.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -25,9 +25,8 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/regulator/of_regulator.h>
-#include "pv88080-regulator.h"
 
-#define PV88080_MAX_REGULATORS	4
+#include <linux/mfd/pv88080.h>
 
 /* PV88080 REGULATOR IDs */
 enum {
@@ -38,11 +37,6 @@ enum {
 	PV88080_ID_HVBUCK,
 };
 
-enum pv88080_types {
-	TYPE_PV88080_AA,
-	TYPE_PV88080_BA,
-};
-
 struct pv88080_regulator {
 	struct regulator_desc desc;
 	/* Current limiting */
@@ -55,14 +49,6 @@ struct pv88080_regulator {
 	unsigned int conf5;
 };
 
-struct pv88080 {
-	struct device *dev;
-	struct regmap *regmap;
-	struct regulator_dev *rdev[PV88080_MAX_REGULATORS];
-	unsigned long type;
-	const struct pv88080_compatible_regmap *regmap_config;
-};
-
 struct pv88080_buck_voltage {
 	int min_uV;
 	int max_uV;
@@ -93,9 +79,11 @@ struct pv88080_compatible_regmap {
 	int hvbuck_vsel_mask;
 };
 
-static const struct regmap_config pv88080_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
+struct pv88080_regulators {
+	int	virq;
+	struct pv88080 *pv88080;
+	struct regulator_dev *rdev[PV88080_MAX_REGULATORS];
+	const struct pv88080_compatible_regmap *regmap_config;
 };
 
 /* Current limits array (in uA) for BUCK1, BUCK2, BUCK3.
@@ -211,16 +199,6 @@ struct pv88080_compatible_regmap {
 	.hvbuck_vsel_mask		  = PV88080_VHVBUCK_MASK,
 };
 
-#ifdef CONFIG_OF
-static const struct of_device_id pv88080_dt_ids[] = {
-	{ .compatible = "pvs,pv88080",    .data = (void *)TYPE_PV88080_AA },
-	{ .compatible = "pvs,pv88080-aa", .data = (void *)TYPE_PV88080_AA },
-	{ .compatible = "pvs,pv88080-ba", .data = (void *)TYPE_PV88080_BA },
-	{},
-};
-MODULE_DEVICE_TABLE(of, pv88080_dt_ids);
-#endif
-
 static unsigned int pv88080_buck_get_mode(struct regulator_dev *rdev)
 {
 	struct pv88080_regulator *info = rdev_get_drvdata(rdev);
@@ -372,9 +350,10 @@ static int pv88080_get_current_limit(struct regulator_dev *rdev)
 	PV88080_HVBUCK(PV88080, HVBUCK, 0, 5000, 1275000),
 };
 
-static irqreturn_t pv88080_irq_handler(int irq, void *data)
+static irqreturn_t pv88080_vdd_overtemp_event(int irq, void *data)
 {
-	struct pv88080 *chip = data;
+	struct pv88080_regulators *regulators = data;
+	struct pv88080 *chip = regulators->pv88080;
 	int i, reg_val, err, ret = IRQ_NONE;
 
 	err = regmap_read(chip->regmap, PV88080_REG_EVENT_A, &reg_val);
@@ -383,8 +362,9 @@ static irqreturn_t pv88080_irq_handler(int irq, void *data)
 
 	if (reg_val & PV88080_E_VDD_FLT) {
 		for (i = 0; i < PV88080_MAX_REGULATORS; i++) {
-			if (chip->rdev[i] != NULL) {
-				regulator_notifier_call_chain(chip->rdev[i],
+			if (regulators->rdev[i] != NULL) {
+				regulator_notifier_call_chain(
+					regulators->rdev[i],
 					REGULATOR_EVENT_UNDER_VOLTAGE,
 					NULL);
 			}
@@ -400,8 +380,9 @@ static irqreturn_t pv88080_irq_handler(int irq, void *data)
 
 	if (reg_val & PV88080_E_OVER_TEMP) {
 		for (i = 0; i < PV88080_MAX_REGULATORS; i++) {
-			if (chip->rdev[i] != NULL) {
-				regulator_notifier_call_chain(chip->rdev[i],
+			if (regulators->rdev[i] != NULL) {
+				regulator_notifier_call_chain(
+					regulators->rdev[i],
 					REGULATOR_EVENT_OVER_TEMP,
 					NULL);
 			}
@@ -425,94 +406,61 @@ static irqreturn_t pv88080_irq_handler(int irq, void *data)
 /*
  * I2C driver interface functions
  */
-static int pv88080_i2c_probe(struct i2c_client *i2c,
-		const struct i2c_device_id *id)
+static int pv88080_regulator_probe(struct platform_device *pdev)
 {
-	struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev);
-	struct pv88080 *chip;
+	struct regulator_init_data *init_data = dev_get_platdata(&pdev->dev);
+	struct pv88080 *chip = dev_get_drvdata(pdev->dev.parent);
+	struct pv88080_regulators *regulators;
 	const struct pv88080_compatible_regmap *regmap_config;
-	const struct of_device_id *match;
 	struct regulator_config config = { };
-	int i, error, ret;
+	int i, ret, irq;
 	unsigned int conf2, conf5;
 
-	chip = devm_kzalloc(&i2c->dev, sizeof(struct pv88080), GFP_KERNEL);
-	if (!chip)
+	regulators = devm_kzalloc(&pdev->dev,
+			sizeof(struct pv88080_regulators), GFP_KERNEL);
+	if (!regulators)
 		return -ENOMEM;
 
-	chip->dev = &i2c->dev;
-	chip->regmap = devm_regmap_init_i2c(i2c, &pv88080_regmap_config);
-	if (IS_ERR(chip->regmap)) {
-		error = PTR_ERR(chip->regmap);
-		dev_err(chip->dev, "Failed to allocate register map: %d\n",
-			error);
-		return error;
-	}
+	platform_set_drvdata(pdev, regulators);
 
-	if (i2c->dev.of_node) {
-		match = of_match_node(pv88080_dt_ids, i2c->dev.of_node);
-		if (!match) {
-			dev_err(chip->dev, "Failed to get of_match_node\n");
-			return -EINVAL;
-		}
-		chip->type = (unsigned long)match->data;
-	} else {
-		chip->type = id->driver_data;
+	irq = platform_get_irq_byname(pdev, "VDD_TEMP_FAULT");
+	if (irq < 0) {
+		dev_err(&pdev->dev, "Failed to get IRQ.\n");
+		return irq;
 	}
 
-	i2c_set_clientdata(i2c, chip);
-
-	if (i2c->irq != 0) {
-		ret = regmap_write(chip->regmap, PV88080_REG_MASK_A, 0xFF);
-		if (ret < 0) {
-			dev_err(chip->dev,
-				"Failed to mask A reg: %d\n", ret);
-			return ret;
-		}
-		ret = regmap_write(chip->regmap, PV88080_REG_MASK_B, 0xFF);
-		if (ret < 0) {
-			dev_err(chip->dev,
-				"Failed to mask B reg: %d\n", ret);
-			return ret;
-		}
-		ret = regmap_write(chip->regmap, PV88080_REG_MASK_C, 0xFF);
-		if (ret < 0) {
-			dev_err(chip->dev,
-				"Failed to mask C reg: %d\n", ret);
-			return ret;
-		}
-
-		ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
-					pv88080_irq_handler,
-					IRQF_TRIGGER_LOW|IRQF_ONESHOT,
-					"pv88080", chip);
-		if (ret != 0) {
-			dev_err(chip->dev, "Failed to request IRQ: %d\n",
-				i2c->irq);
+	regulators->virq = regmap_irq_get_virq(chip->irq_data, irq);
+	if (regulators->virq >= 0) {
+		ret = devm_request_threaded_irq(&pdev->dev,
+				regulators->virq, NULL,
+				pv88080_vdd_overtemp_event,
+				IRQF_TRIGGER_LOW|IRQF_ONESHOT,
+				"VDD_TEMP_FAULT", regulators);
+		if (ret) {
+			dev_err(chip->dev, "Failed to request IRQ: %d\n", irq);
 			return ret;
 		}
+	}
 
-		ret = regmap_update_bits(chip->regmap, PV88080_REG_MASK_A,
-			PV88080_M_VDD_FLT | PV88080_M_OVER_TEMP, 0);
-		if (ret < 0) {
-			dev_err(chip->dev,
-				"Failed to update mask reg: %d\n", ret);
-			return ret;
-		}
-	} else {
-		dev_warn(chip->dev, "No IRQ configured\n");
+	ret = regmap_update_bits(chip->regmap, PV88080_REG_MASK_A,
+		PV88080_M_VDD_FLT | PV88080_M_OVER_TEMP, 0);
+	if (ret < 0) {
+		dev_err(chip->dev,
+			"Failed to update mask reg: %d\n", ret);
+		return ret;
 	}
 
 	switch (chip->type) {
 	case TYPE_PV88080_AA:
-		chip->regmap_config = &pv88080_aa_regs;
+		regulators->regmap_config = &pv88080_aa_regs;
 		break;
 	case TYPE_PV88080_BA:
-		chip->regmap_config = &pv88080_ba_regs;
+		regulators->regmap_config = &pv88080_ba_regs;
 		break;
 	}
 
-	regmap_config = chip->regmap_config;
+	regulators->pv88080 = chip;
+	regmap_config = regulators->regmap_config;
 	config.dev = chip->dev;
 	config.regmap = chip->regmap;
 
@@ -564,12 +512,12 @@ static int pv88080_i2c_probe(struct i2c_client *i2c,
 			/(pv88080_regulator_info[i].desc.uV_step) + 1;
 
 		config.driver_data = (void *)&pv88080_regulator_info[i];
-		chip->rdev[i] = devm_regulator_register(chip->dev,
+		regulators->rdev[i] = devm_regulator_register(chip->dev,
 			&pv88080_regulator_info[i].desc, &config);
-		if (IS_ERR(chip->rdev[i])) {
+		if (IS_ERR(regulators->rdev[i])) {
 			dev_err(chip->dev,
 				"Failed to register PV88080 regulator\n");
-			return PTR_ERR(chip->rdev[i]);
+			return PTR_ERR(regulators->rdev[i]);
 		}
 	}
 
@@ -582,40 +530,27 @@ static int pv88080_i2c_probe(struct i2c_client *i2c,
 	pv88080_regulator_info[PV88080_ID_HVBUCK].desc.vsel_mask
 		= regmap_config->hvbuck_vsel_mask;
 
-	/* Registeration for HVBUCK */
 	if (init_data)
 		config.init_data = &init_data[PV88080_ID_HVBUCK];
 
 	config.driver_data = (void *)&pv88080_regulator_info[PV88080_ID_HVBUCK];
-	chip->rdev[PV88080_ID_HVBUCK] = devm_regulator_register(chip->dev,
+	regulators->rdev[PV88080_ID_HVBUCK] = devm_regulator_register(chip->dev,
 		&pv88080_regulator_info[PV88080_ID_HVBUCK].desc, &config);
-	if (IS_ERR(chip->rdev[PV88080_ID_HVBUCK])) {
+	if (IS_ERR(regulators->rdev[PV88080_ID_HVBUCK])) {
 		dev_err(chip->dev, "Failed to register PV88080 regulator\n");
-		return PTR_ERR(chip->rdev[PV88080_ID_HVBUCK]);
+		return PTR_ERR(regulators->rdev[PV88080_ID_HVBUCK]);
 	}
 
 	return 0;
 }
-
-static const struct i2c_device_id pv88080_i2c_id[] = {
-	{ "pv88080",    TYPE_PV88080_AA },
-	{ "pv88080-aa", TYPE_PV88080_AA },
-	{ "pv88080-ba", TYPE_PV88080_BA },
-	{},
-};
-MODULE_DEVICE_TABLE(i2c, pv88080_i2c_id);
-
-static struct i2c_driver pv88080_regulator_driver = {
+static struct platform_driver pv88080_regulator_driver = {
 	.driver = {
-		.name = "pv88080",
-		.of_match_table = of_match_ptr(pv88080_dt_ids),
+		.name = "pv88080-regulator",
 	},
-	.probe = pv88080_i2c_probe,
-	.id_table = pv88080_i2c_id,
+	.probe = pv88080_regulator_probe,
 };
+module_platform_driver(pv88080_regulator_driver);
 
-module_i2c_driver(pv88080_regulator_driver);
-
-MODULE_AUTHOR("James Ban <James.Ban.opensource@xxxxxxxxxxx>");
+MODULE_AUTHOR("Eric Jeong <eric.jeong.opensource@xxxxxxxxxxx>");
 MODULE_DESCRIPTION("Regulator device driver for Powerventure PV88080");
 MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/pv88080-regulator.h b/drivers/regulator/pv88080-regulator.h
deleted file mode 100644
index ae25ff3..0000000
--- a/drivers/regulator/pv88080-regulator.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * pv88080-regulator.h - Regulator definitions for PV88080
- * Copyright (C) 2016 Powerventure Semiconductor Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __PV88080_REGISTERS_H__
-#define __PV88080_REGISTERS_H__
-
-/* System Control and Event Registers */
-#define	PV88080_REG_EVENT_A				0x04
-#define	PV88080_REG_MASK_A				0x09
-#define	PV88080_REG_MASK_B				0x0A
-#define	PV88080_REG_MASK_C				0x0B
-
-/* Regulator Registers - rev. AA */
-#define PV88080AA_REG_HVBUCK_CONF1		0x2D
-#define PV88080AA_REG_HVBUCK_CONF2		0x2E
-#define	PV88080AA_REG_BUCK1_CONF0		0x27
-#define	PV88080AA_REG_BUCK1_CONF1		0x28
-#define	PV88080AA_REG_BUCK1_CONF2		0x59
-#define	PV88080AA_REG_BUCK1_CONF5		0x5C
-#define	PV88080AA_REG_BUCK2_CONF0		0x29
-#define	PV88080AA_REG_BUCK2_CONF1		0x2A
-#define	PV88080AA_REG_BUCK2_CONF2		0x61
-#define	PV88080AA_REG_BUCK2_CONF5		0x64
-#define	PV88080AA_REG_BUCK3_CONF0		0x2B
-#define	PV88080AA_REG_BUCK3_CONF1		0x2C
-#define	PV88080AA_REG_BUCK3_CONF2		0x69
-#define	PV88080AA_REG_BUCK3_CONF5		0x6C
-
-/* Regulator Registers - rev. BA */
-#define	PV88080BA_REG_HVBUCK_CONF1		0x33
-#define	PV88080BA_REG_HVBUCK_CONF2		0x34
-#define	PV88080BA_REG_BUCK1_CONF0		0x2A
-#define	PV88080BA_REG_BUCK1_CONF1		0x2C
-#define	PV88080BA_REG_BUCK1_CONF2		0x5A
-#define	PV88080BA_REG_BUCK1_CONF5		0x5D
-#define	PV88080BA_REG_BUCK2_CONF0		0x2D
-#define	PV88080BA_REG_BUCK2_CONF1		0x2F
-#define	PV88080BA_REG_BUCK2_CONF2		0x63
-#define	PV88080BA_REG_BUCK2_CONF5		0x66
-#define	PV88080BA_REG_BUCK3_CONF0		0x30
-#define	PV88080BA_REG_BUCK3_CONF1		0x32
-#define	PV88080BA_REG_BUCK3_CONF2		0x6C
-#define	PV88080BA_REG_BUCK3_CONF5		0x6F
-
-/* PV88080_REG_EVENT_A (addr=0x04) */
-#define	PV88080_E_VDD_FLT				0x01
-#define	PV88080_E_OVER_TEMP				0x02
-
-/* PV88080_REG_MASK_A (addr=0x09) */
-#define	PV88080_M_VDD_FLT				0x01
-#define	PV88080_M_OVER_TEMP				0x02
-
-/* PV88080_REG_BUCK1_CONF0 (addr=0x27|0x2A) */
-#define	PV88080_BUCK1_EN				0x80
-#define PV88080_VBUCK1_MASK				0x7F
-
-/* PV88080_REG_BUCK2_CONF0 (addr=0x29|0x2D) */
-#define	PV88080_BUCK2_EN				0x80
-#define PV88080_VBUCK2_MASK				0x7F
-
-/* PV88080_REG_BUCK3_CONF0 (addr=0x2B|0x30) */
-#define	PV88080_BUCK3_EN				0x80
-#define PV88080_VBUCK3_MASK				0x7F
-
-/* PV88080_REG_BUCK1_CONF1 (addr=0x28|0x2C) */
-#define PV88080_BUCK1_ILIM_SHIFT		2
-#define PV88080_BUCK1_ILIM_MASK			0x0C
-#define PV88080_BUCK1_MODE_MASK			0x03
-
-/* PV88080_REG_BUCK2_CONF1 (addr=0x2A|0x2F) */
-#define PV88080_BUCK2_ILIM_SHIFT		2
-#define PV88080_BUCK2_ILIM_MASK			0x0C
-#define PV88080_BUCK2_MODE_MASK			0x03
-
-/* PV88080_REG_BUCK3_CONF1 (addr=0x2C|0x32) */
-#define PV88080_BUCK3_ILIM_SHIFT		2
-#define PV88080_BUCK3_ILIM_MASK			0x0C
-#define PV88080_BUCK3_MODE_MASK			0x03
-
-#define	PV88080_BUCK_MODE_SLEEP			0x00
-#define	PV88080_BUCK_MODE_AUTO			0x01
-#define	PV88080_BUCK_MODE_SYNC			0x02
-
-/* PV88080_REG_HVBUCK_CONF1 (addr=0x2D|0x33) */
-#define PV88080_VHVBUCK_MASK			0xFF
-
-/* PV88080_REG_HVBUCK_CONF1 (addr=0x2E|0x34) */
-#define PV88080_HVBUCK_EN				0x01
-
-/* PV88080_REG_BUCK2_CONF2 (addr=0x61|0x63) */
-/* PV88080_REG_BUCK3_CONF2 (addr=0x69|0x6C) */
-#define PV88080_BUCK_VDAC_RANGE_SHIFT	7
-#define PV88080_BUCK_VDAC_RANGE_MASK	0x01
-
-#define PV88080_BUCK_VDAC_RANGE_1		0x00
-#define PV88080_BUCK_VDAC_RANGE_2		0x01
-
-/* PV88080_REG_BUCK2_CONF5 (addr=0x64|0x66) */
-/* PV88080_REG_BUCK3_CONF5 (addr=0x6C|0x6F) */
-#define PV88080_BUCK_VRANGE_GAIN_SHIFT	0
-#define PV88080_BUCK_VRANGE_GAIN_MASK	0x01
-
-#define PV88080_BUCK_VRANGE_GAIN_1		0x00
-#define PV88080_BUCK_VRANGE_GAIN_2		0x01
-
-#endif	/* __PV88080_REGISTERS_H__ */
-- 
end-of-patch for PATCH V3

--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux