Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1364921 > unrolled thread

[PATCH 0/3] regulator: twl: Fix regulator mode support

Started byIvaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
First post2016-03-26 09:30 +0100
Last post2016-03-29 09:50 +0200
Articles 5 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH 0/3] regulator: twl: Fix regulator mode support Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com> - 2016-03-26 09:30 +0100
    [PATCH 1/3] regulator: twl: Make sure we have access to powerbus before trying to write to it Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com> - 2016-03-26 09:30 +0100
    [PATCH 3/3] regulator: twl: Regulator mode should not depend on regulator enabled state Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com> - 2016-03-26 09:40 +0100
    [PATCH 2/3] regulator: twl: Provide of_map_mode for twl4030 Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com> - 2016-03-26 09:40 +0100
      Re: [PATCH 2/3] regulator: twl: Provide of_map_mode for twl4030 Mark Brown <broonie@kernel.org> - 2016-03-29 09:50 +0200

#1364921 — [PATCH 0/3] regulator: twl: Fix regulator mode support

FromIvaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
Date2016-03-26 09:30 +0100
Subject[PATCH 0/3] regulator: twl: Fix regulator mode support
Message-ID<rgRLz-6Ae-3@gated-at.bofh.it>
On Nokia N900 regulators are left in the mode last set by the bootloader
or by the stock kernel, depends on whether it is power-on or reboot from
stock kernel to mainline. That leads to problem with devices connected
to vmmc2 regulator - when the device is rebooted from stock kernel vmmc2
is left in "sleep" mode (REGULATOR_STATUS_STANDBY in terms of regulator
framework) and as noone in mainline kernel switches vmmc2 regulator to
normal (REGULATOR_STATUS_NORMAL) mode, devices supplied by it does not
get enough power to operate normally.

Fix that by providing the correct functionality for initial mode setting
from the board DTS. Fix i2c access to powerbus while at it.

I will send a follow-up patch for N900 board DTS that sets initial
regulators mode once the $subject series is assumed to be ok.

Ivaylo Dimitrov (3):
  regulator: twl: Make sure we have access to powerbus before trying to
    write to it
  regulator: twl: Provide of_map_mode for twl4030
  regulator: twl: Regulator mode should not depend on regulator enabled
    state

 drivers/regulator/twl-regulator.c | 100 +++++++++++++++++++++++++++++++-------
 1 file changed, 82 insertions(+), 18 deletions(-)

-- 
1.9.1

[toc] | [next] | [standalone]


#1364922 — [PATCH 1/3] regulator: twl: Make sure we have access to powerbus before trying to write to it

FromIvaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
Date2016-03-26 09:30 +0100
Subject[PATCH 1/3] regulator: twl: Make sure we have access to powerbus before trying to write to it
Message-ID<rgRLA-6Ae-5@gated-at.bofh.it>
In reply to#1364921
According to the TRM, we need to enable i2c access to powerbus before
writing to it. Also, a new write to powerbus should not be attempted if
there is a pending transfer. The current code does not implement that
functionality and while there are no known problems caused by that, it is
better to follow what TRM says.

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
---
 drivers/regulator/twl-regulator.c | 78 +++++++++++++++++++++++++++++++++++----
 1 file changed, 70 insertions(+), 8 deletions(-)

diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 955a6fb..aad748b0 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -21,7 +21,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/i2c/twl.h>
-
+#include <linux/delay.h>
 
 /*
  * The TWL4030/TW5030/TPS659x0/TWL6030 family chips include power management, a
@@ -188,6 +188,74 @@ static int twl6030reg_is_enabled(struct regulator_dev *rdev)
 	return grp && (val == TWL6030_CFG_STATE_ON);
 }
 
+#define PB_I2C_BUSY	BIT(0)
+#define PB_I2C_BWEN	BIT(1)
+
+/* Wait until buffer empty/ready to send a word on power bus. */
+static int twl4030_wait_pb_ready(void)
+{
+
+	int	ret;
+	int	timeout = 10;
+	u8	val;
+
+	do {
+		ret = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val,
+				      TWL4030_PM_MASTER_PB_CFG);
+		if (ret < 0)
+			return ret;
+
+		if (!(val & PB_I2C_BUSY))
+			return 0;
+
+		mdelay(1);
+		timeout--;
+	} while (timeout);
+
+	return -ETIMEDOUT;
+}
+
+/* Send a word over the powerbus */
+static int twl4030_send_pb_msg(unsigned msg)
+{
+	u8	val;
+	int	ret;
+
+	/* save powerbus configuration */
+	ret = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val,
+			      TWL4030_PM_MASTER_PB_CFG);
+	if (ret < 0)
+		return ret;
+
+	/* Enable i2c access to powerbus */
+	ret = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val | PB_I2C_BWEN,
+			       TWL4030_PM_MASTER_PB_CFG);
+	if (ret < 0)
+		return ret;
+
+	ret = twl4030_wait_pb_ready();
+	if (ret < 0)
+		return ret;
+
+	ret = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, msg >> 8,
+			       TWL4030_PM_MASTER_PB_WORD_MSB);
+	if (ret < 0)
+		return ret;
+
+	ret = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, msg & 0xff,
+			       TWL4030_PM_MASTER_PB_WORD_LSB);
+	if (ret < 0)
+		return ret;
+
+	ret = twl4030_wait_pb_ready();
+	if (ret < 0)
+		return ret;
+
+	/* Restore powerbus configuration */
+	return twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val,
+				TWL_MODULE_PM_MASTER);
+}
+
 static int twl4030reg_enable(struct regulator_dev *rdev)
 {
 	struct twlreg_info	*info = rdev_get_drvdata(rdev);
@@ -324,13 +392,7 @@ static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
 	if (!(status & (P3_GRP_4030 | P2_GRP_4030 | P1_GRP_4030)))
 		return -EACCES;
 
-	status = twl_i2c_write_u8(TWL_MODULE_PM_MASTER,
-			message >> 8, TWL4030_PM_MASTER_PB_WORD_MSB);
-	if (status < 0)
-		return status;
-
-	return twl_i2c_write_u8(TWL_MODULE_PM_MASTER,
-			message & 0xff, TWL4030_PM_MASTER_PB_WORD_LSB);
+	return twl4030_send_pb_msg(message);
 }
 
 static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1364924 — [PATCH 3/3] regulator: twl: Regulator mode should not depend on regulator enabled state

FromIvaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
Date2016-03-26 09:40 +0100
Subject[PATCH 3/3] regulator: twl: Regulator mode should not depend on regulator enabled state
Message-ID<rgRVg-6G7-5@gated-at.bofh.it>
In reply to#1364921
When machine constraints are applied, regulator framework first sets
initial mode (if any) and then enables the regulator if needed. The current
code in twl4030reg_set_mode always checks if the regulator is enabled
before applying the mode. That results in -EACCES error returned for
"always-on" regulators which have "initial-mode" set in the board DTS. Fix
that by removing the unneeded check.

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
---
 drivers/regulator/twl-regulator.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index be8d05e..d8f6ad6 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -371,7 +371,6 @@ static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
 {
 	struct twlreg_info	*info = rdev_get_drvdata(rdev);
 	unsigned		message;
-	int			status;
 
 	/* We can only set the mode through state machine commands... */
 	switch (mode) {
@@ -385,13 +384,6 @@ static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
 		return -EINVAL;
 	}
 
-	/* Ensure the resource is associated with some group */
-	status = twlreg_grp(rdev);
-	if (status < 0)
-		return status;
-	if (!(status & (P3_GRP_4030 | P2_GRP_4030 | P1_GRP_4030)))
-		return -EACCES;
-
 	return twl4030_send_pb_msg(message);
 }
 
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1364925 — [PATCH 2/3] regulator: twl: Provide of_map_mode for twl4030

FromIvaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
Date2016-03-26 09:40 +0100
Subject[PATCH 2/3] regulator: twl: Provide of_map_mode for twl4030
Message-ID<rgRVg-6G7-9@gated-at.bofh.it>
In reply to#1364921
of_map_mode is needed so to be possible to set initial regulators mode from
the board DTS. Otherwise, for DT boot, regulators are left in their default
state after reset/reboot.

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
---
 drivers/regulator/twl-regulator.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index aad748b0..be8d05e 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -395,6 +395,12 @@ static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
 	return twl4030_send_pb_msg(message);
 }
 
+static inline unsigned int twl4030reg_map_mode(unsigned int mode)
+{
+	return mode == RES_STATE_ACTIVE ?
+				REGULATOR_MODE_NORMAL : REGULATOR_MODE_STANDBY;
+}
+
 static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
 {
 	struct twlreg_info	*info = rdev_get_drvdata(rdev);
@@ -897,10 +903,11 @@ static struct regulator_ops twlsmps_ops = {
 #define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
 			remap_conf) \
 		TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
-			remap_conf, TWL4030, twl4030fixed_ops)
+			remap_conf, TWL4030, twl4030fixed_ops, \
+			twl4030reg_map_mode)
 #define TWL6030_FIXED_LDO(label, offset, mVolts, turnon_delay) \
 		TWL_FIXED_LDO(label, offset, mVolts, 0x0, turnon_delay, \
-			0x0, TWL6030, twl6030fixed_ops)
+			0x0, TWL6030, twl6030fixed_ops, 0x0)
 
 #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) \
 static const struct twlreg_info TWL4030_INFO_##label = { \
@@ -917,6 +924,7 @@ static const struct twlreg_info TWL4030_INFO_##label = { \
 		.type = REGULATOR_VOLTAGE, \
 		.owner = THIS_MODULE, \
 		.enable_time = turnon_delay, \
+		.of_map_mode = twl4030reg_map_mode, \
 		}, \
 	}
 
@@ -932,6 +940,7 @@ static const struct twlreg_info TWL4030_INFO_##label = { \
 		.type = REGULATOR_VOLTAGE, \
 		.owner = THIS_MODULE, \
 		.enable_time = turnon_delay, \
+		.of_map_mode = twl4030reg_map_mode, \
 		}, \
 	}
 
@@ -977,7 +986,7 @@ static const struct twlreg_info TWL6032_INFO_##label = { \
 	}
 
 #define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \
-		family, operations) \
+		family, operations, map_mode) \
 static const struct twlreg_info TWLFIXED_INFO_##label = { \
 	.base = offset, \
 	.id = num, \
@@ -992,6 +1001,7 @@ static const struct twlreg_info TWLFIXED_INFO_##label = { \
 		.owner = THIS_MODULE, \
 		.min_uV = mVolts * 1000, \
 		.enable_time = turnon_delay, \
+		.of_map_mode = map_mode, \
 		}, \
 	}
 
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1365959 — Re: [PATCH 2/3] regulator: twl: Provide of_map_mode for twl4030

FromMark Brown <broonie@kernel.org>
Date2016-03-29 09:50 +0200
SubjectRe: [PATCH 2/3] regulator: twl: Provide of_map_mode for twl4030
Message-ID<rhWzw-2QS-23@gated-at.bofh.it>
In reply to#1364925

[Multipart message — attachments visible in raw view] — view raw

On Sat, Mar 26, 2016 at 10:28:14AM +0200, Ivaylo Dimitrov wrote:
> of_map_mode is needed so to be possible to set initial regulators mode from
> the board DTS. Otherwise, for DT boot, regulators are left in their default
> state after reset/reboot.

This should also update the DT binding document for the device to
specify what the valid modes for the device are.

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web