Commit 43e30f23 authored by David Jander's avatar David Jander Committed by Lee Jones
Browse files

mfd: da9052: Avoid multiwrite mode due to silicon errata



DA9053 (up to revision bc) can corrupt internal registers when multi-write
mode is enabled and power is removed or during shutdown.

Signed-off-by: default avatarDavid Jander <david@protonic.nl>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
parent 61e6cfa8
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -86,7 +86,11 @@ static int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg)
	return 0;
}

static int da9052_i2c_enable_multiwrite(struct da9052 *da9052)
/*
 * According to errata item 24, multiwrite mode should be avoided
 * in order to prevent register data corruption after power-down.
 */
static int da9052_i2c_disable_multiwrite(struct da9052 *da9052)
{
	int reg_val, ret;

@@ -94,8 +98,8 @@ static int da9052_i2c_enable_multiwrite(struct da9052 *da9052)
	if (ret < 0)
		return ret;

	if (reg_val & DA9052_CONTROL_B_WRITEMODE) {
		reg_val &= ~DA9052_CONTROL_B_WRITEMODE;
	if (!(reg_val & DA9052_CONTROL_B_WRITEMODE)) {
		reg_val |= DA9052_CONTROL_B_WRITEMODE;
		ret = regmap_write(da9052->regmap, DA9052_CONTROL_B_REG,
				   reg_val);
		if (ret < 0)
@@ -154,7 +158,7 @@ static int da9052_i2c_probe(struct i2c_client *client,
		return ret;
	}

	ret = da9052_i2c_enable_multiwrite(da9052);
	ret = da9052_i2c_disable_multiwrite(da9052);
	if (ret < 0)
		return ret;

+14 −6
Original line number Diff line number Diff line
@@ -148,10 +148,15 @@ static inline int da9052_group_read(struct da9052 *da9052, unsigned char reg,
				     unsigned reg_cnt, unsigned char *val)
{
	int ret;
	unsigned int tmp;
	int i;

	ret = regmap_bulk_read(da9052->regmap, reg, val, reg_cnt);
	for (i = 0; i < reg_cnt; i++) {
		ret = regmap_read(da9052->regmap, reg + i, &tmp);
		val[i] = (unsigned char)tmp;
		if (ret < 0)
			return ret;
	}

	if (da9052->fix_io) {
		ret = da9052->fix_io(da9052, reg);
@@ -166,10 +171,13 @@ static inline int da9052_group_write(struct da9052 *da9052, unsigned char reg,
				      unsigned reg_cnt, unsigned char *val)
{
	int ret;
	int i;

	ret = regmap_raw_write(da9052->regmap, reg, val, reg_cnt);
	for (i = 0; i < reg_cnt; i++) {
		ret = regmap_write(da9052->regmap, reg + i, val[i]);
		if (ret < 0)
			return ret;
	}

	if (da9052->fix_io) {
		ret = da9052->fix_io(da9052, reg);