2015-05-11 13:07:33

by Charles Keepax

[permalink] [raw]
Subject: [RESEND PATCH v3 00/10] wm5110 Boot Fixups

Ok so I have completed the rework to the second of the two patch
chains on this and pulled them back together into one series.

Note the main difference is I have pulled a couple patches from
the second series to the start of the chain. This is because of
patch 3 which is a bug fix for 5102 I have discovered whilst
working through this better system suspend support stuff.

Changes since v2:
- Add comment for sleep in reset disable
- Split out formatting changes and functional changes in patch 4

Changes since v1:
- Just updated the return of wm5110_apply_sleep_patch to use the
ternary as per Lee's preference.

Thanks,
Charles

Charles Keepax (10):
mfd: arizona: Use devres to manage reset GPIO
mfd: arizona: Factor out hard reset into helper functions
mfd: wm5102: Ensure we always boot the device fully
mfd: arizona: Fix formating/style issues in
arizona_apply_hardware_patch
mfd: arizona: Factor out SYSCLK enable from wm5102 hardware patch
mfd: wm5110: Add register patch required for low power sleep
regulator: arizona-ldo1: Add additional supported voltage
mfd: wm5110: Set DCVDD voltage to 1.175V before entering sleep mode
mfd: arizona: Add better support for system suspend
mfd: wm5110: Add delay before releasing reset line

drivers/mfd/arizona-core.c | 344 +++++++++++++++++++++++++++++++------
drivers/regulator/arizona-ldo1.c | 15 ++
include/linux/mfd/arizona/core.h | 1 +
3 files changed, 304 insertions(+), 56 deletions(-)

--
1.7.2.5


2015-05-11 13:07:31

by Charles Keepax

[permalink] [raw]
Subject: [RESEND PATCH v3 01/10] mfd: arizona: Use devres to manage reset GPIO

This also handily fixes a leak of the GPIO in arizona_dev_exit.

Signed-off-by: Charles Keepax <[email protected]>
Acked-by: Lee Jones <[email protected]>
---
drivers/mfd/arizona-core.c | 10 ++++------
1 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index aed43a5..915cc28 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -728,9 +728,9 @@ int arizona_dev_init(struct arizona *arizona)

if (arizona->pdata.reset) {
/* Start out with /RESET low to put the chip into reset */
- ret = gpio_request_one(arizona->pdata.reset,
- GPIOF_DIR_OUT | GPIOF_INIT_LOW,
- "arizona /RESET");
+ ret = devm_gpio_request_one(arizona->dev, arizona->pdata.reset,
+ GPIOF_DIR_OUT | GPIOF_INIT_LOW,
+ "arizona /RESET");
if (ret != 0) {
dev_err(dev, "Failed to request /RESET: %d\n", ret);
goto err_dcvdd;
@@ -1046,10 +1046,8 @@ int arizona_dev_init(struct arizona *arizona)
err_irq:
arizona_irq_exit(arizona);
err_reset:
- if (arizona->pdata.reset) {
+ if (arizona->pdata.reset)
gpio_set_value_cansleep(arizona->pdata.reset, 0);
- gpio_free(arizona->pdata.reset);
- }
regulator_disable(arizona->dcvdd);
err_enable:
regulator_bulk_disable(arizona->num_core_supplies,
--
1.7.2.5

2015-05-11 13:07:35

by Charles Keepax

[permalink] [raw]
Subject: [RESEND PATCH v3 02/10] mfd: arizona: Factor out hard reset into helper functions

This patch adds functions for enabling and disabling the physical reset
line. This will be helpful in future refactoring.

Signed-off-by: Charles Keepax <[email protected]>
Acked-by: Lee Jones <[email protected]>
---
drivers/mfd/arizona-core.c | 25 +++++++++++++++++--------
1 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 915cc28..f30d925 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -250,6 +250,20 @@ static int arizona_wait_for_boot(struct arizona *arizona)
return ret;
}

+static inline void arizona_enable_reset(struct arizona *arizona)
+{
+ if (arizona->pdata.reset)
+ gpio_set_value_cansleep(arizona->pdata.reset, 0);
+}
+
+static void arizona_disable_reset(struct arizona *arizona)
+{
+ if (arizona->pdata.reset) {
+ gpio_set_value_cansleep(arizona->pdata.reset, 1);
+ msleep(1);
+ }
+}
+
static int arizona_apply_hardware_patch(struct arizona* arizona)
{
unsigned int fll, sysclk;
@@ -751,10 +765,7 @@ int arizona_dev_init(struct arizona *arizona)
goto err_enable;
}

- if (arizona->pdata.reset) {
- gpio_set_value_cansleep(arizona->pdata.reset, 1);
- msleep(1);
- }
+ arizona_disable_reset(arizona);

regcache_cache_only(arizona->regmap, false);

@@ -1046,8 +1057,7 @@ int arizona_dev_init(struct arizona *arizona)
err_irq:
arizona_irq_exit(arizona);
err_reset:
- if (arizona->pdata.reset)
- gpio_set_value_cansleep(arizona->pdata.reset, 0);
+ arizona_enable_reset(arizona);
regulator_disable(arizona->dcvdd);
err_enable:
regulator_bulk_disable(arizona->num_core_supplies,
@@ -1072,8 +1082,7 @@ int arizona_dev_exit(struct arizona *arizona)
arizona_free_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, arizona);
arizona_free_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, arizona);
arizona_irq_exit(arizona);
- if (arizona->pdata.reset)
- gpio_set_value_cansleep(arizona->pdata.reset, 0);
+ arizona_enable_reset(arizona);

regulator_bulk_disable(arizona->num_core_supplies,
arizona->core_supplies);
--
1.7.2.5

2015-05-11 13:10:02

by Charles Keepax

[permalink] [raw]
Subject: [RESEND PATCH v3 03/10] mfd: wm5102: Ensure we always boot the device fully

The wm5102 uses a custom boot sequence and the standard boot sequence is
disabled. However, the standard boot sequence must be run at least once
after a cold boot (caused by either a hard reset or removal of AVDD).
Unfortunately the register WRITE_SEQUENCER_CTRL_3 is not affected by the
hardware reset. This means if the device has been previously booted but
the AVDD supply has never been removed, arizona_dev_init will reset the
chip but the boot sequence will not run, which can cause numerous
problems. The solution is to manually clear this register and then boot
the chip again, which is what this patch does.

Signed-off-by: Charles Keepax <[email protected]>
Acked-by: Lee Jones <[email protected]>
---
drivers/mfd/arizona-core.c | 50 +++++++++++++++++++++++++++++++++++--------
1 files changed, 40 insertions(+), 10 deletions(-)

diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index f30d925..0df1299 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -344,6 +344,33 @@ err_fll:
return err;
}

+static int wm5102_clear_write_sequencer(struct arizona *arizona)
+{
+ int ret;
+
+ ret = regmap_write(arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_3,
+ 0x0);
+ if (ret) {
+ dev_err(arizona->dev,
+ "Failed to clear write sequencer state: %d\n", ret);
+ return ret;
+ }
+
+ arizona_enable_reset(arizona);
+ regulator_disable(arizona->dcvdd);
+
+ msleep(20);
+
+ ret = regulator_enable(arizona->dcvdd);
+ if (ret) {
+ dev_err(arizona->dev, "Failed to re-enable DCVDD: %d\n", ret);
+ return ret;
+ }
+ arizona_disable_reset(arizona);
+
+ return 0;
+}
+
#ifdef CONFIG_PM
static int arizona_runtime_resume(struct device *dev)
{
@@ -802,21 +829,24 @@ int arizona_dev_init(struct arizona *arizona)
case WM5102:
ret = regmap_read(arizona->regmap,
ARIZONA_WRITE_SEQUENCER_CTRL_3, &val);
- if (ret != 0)
+ if (ret) {
dev_err(dev,
"Failed to check write sequencer state: %d\n",
ret);
- else if (val & 0x01)
- break;
- /* Fall through */
- default:
- ret = arizona_wait_for_boot(arizona);
- if (ret != 0) {
- dev_err(arizona->dev,
- "Device failed initial boot: %d\n", ret);
- goto err_reset;
+ } else if (val & 0x01) {
+ ret = wm5102_clear_write_sequencer(arizona);
+ if (ret)
+ return ret;
}
break;
+ default:
+ break;
+ }
+
+ ret = arizona_wait_for_boot(arizona);
+ if (ret) {
+ dev_err(arizona->dev, "Device failed initial boot: %d\n", ret);
+ goto err_reset;
}

/* Read the device ID information & do device specific stuff */
--
1.7.2.5

2015-05-11 13:09:58

by Charles Keepax

[permalink] [raw]
Subject: [RESEND PATCH v3 04/10] mfd: arizona: Fix formating/style issues in arizona_apply_hardware_patch

In preparation for some refactoring fixup some minor style, formating
and code clarity issues.

Signed-off-by: Charles Keepax <[email protected]>
Acked-by: Lee Jones <[email protected]>
---
drivers/mfd/arizona-core.c | 37 +++++++++++++++++--------------------
1 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 0df1299..326a4af 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -264,20 +264,20 @@ static void arizona_disable_reset(struct arizona *arizona)
}
}

-static int arizona_apply_hardware_patch(struct arizona* arizona)
+static int wm5102_apply_hardware_patch(struct arizona *arizona)
{
unsigned int fll, sysclk;
int ret, err;

/* Cache existing FLL and SYSCLK settings */
ret = regmap_read(arizona->regmap, ARIZONA_FLL1_CONTROL_1, &fll);
- if (ret != 0) {
+ if (ret) {
dev_err(arizona->dev, "Failed to cache FLL settings: %d\n",
ret);
return ret;
}
ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &sysclk);
- if (ret != 0) {
+ if (ret) {
dev_err(arizona->dev, "Failed to cache SYSCLK settings: %d\n",
ret);
return ret;
@@ -286,7 +286,7 @@ static int arizona_apply_hardware_patch(struct arizona* arizona)
/* Start up SYSCLK using the FLL in free running mode */
ret = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1,
ARIZONA_FLL1_ENA | ARIZONA_FLL1_FREERUN);
- if (ret != 0) {
+ if (ret) {
dev_err(arizona->dev,
"Failed to start FLL in freerunning mode: %d\n",
ret);
@@ -295,36 +295,36 @@ static int arizona_apply_hardware_patch(struct arizona* arizona)
ret = arizona_poll_reg(arizona, 25, ARIZONA_INTERRUPT_RAW_STATUS_5,
ARIZONA_FLL1_CLOCK_OK_STS,
ARIZONA_FLL1_CLOCK_OK_STS);
- if (ret != 0) {
+ if (ret) {
ret = -ETIMEDOUT;
goto err_fll;
}

ret = regmap_write(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, 0x0144);
- if (ret != 0) {
+ if (ret) {
dev_err(arizona->dev, "Failed to start SYSCLK: %d\n", ret);
goto err_fll;
}

/* Start the write sequencer and wait for it to finish */
ret = regmap_write(arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_0,
- ARIZONA_WSEQ_ENA | ARIZONA_WSEQ_START | 160);
- if (ret != 0) {
+ ARIZONA_WSEQ_ENA | ARIZONA_WSEQ_START | 160);
+ if (ret) {
dev_err(arizona->dev, "Failed to start write sequencer: %d\n",
ret);
goto err_sysclk;
}
ret = arizona_poll_reg(arizona, 5, ARIZONA_WRITE_SEQUENCER_CTRL_1,
ARIZONA_WSEQ_BUSY, 0);
- if (ret != 0) {
+ if (ret) {
regmap_write(arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_0,
- ARIZONA_WSEQ_ABORT);
+ ARIZONA_WSEQ_ABORT);
ret = -ETIMEDOUT;
}

err_sysclk:
err = regmap_write(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, sysclk);
- if (err != 0) {
+ if (err) {
dev_err(arizona->dev,
"Failed to re-apply old SYSCLK settings: %d\n",
err);
@@ -332,16 +332,13 @@ err_sysclk:

err_fll:
err = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1, fll);
- if (err != 0) {
+ if (err) {
dev_err(arizona->dev,
"Failed to re-apply old FLL settings: %d\n",
err);
}

- if (ret != 0)
- return ret;
- else
- return err;
+ return ret ?: err;
}

static int wm5102_clear_write_sequencer(struct arizona *arizona)
@@ -407,8 +404,8 @@ static int arizona_runtime_resume(struct device *dev)
goto err;
}

- ret = arizona_apply_hardware_patch(arizona);
- if (ret != 0) {
+ ret = wm5102_apply_hardware_patch(arizona);
+ if (ret) {
dev_err(arizona->dev,
"Failed to apply hardware patch: %d\n",
ret);
@@ -924,8 +921,8 @@ int arizona_dev_init(struct arizona *arizona)

switch (arizona->type) {
case WM5102:
- ret = arizona_apply_hardware_patch(arizona);
- if (ret != 0) {
+ ret = wm5102_apply_hardware_patch(arizona);
+ if (ret) {
dev_err(arizona->dev,
"Failed to apply hardware patch: %d\n",
ret);
--
1.7.2.5

2015-05-11 13:07:43

by Charles Keepax

[permalink] [raw]
Subject: [RESEND PATCH v3 05/10] mfd: arizona: Factor out SYSCLK enable from wm5102 hardware patch

wm5102 applies a custom hardware boot sequence, for this the SYSCLK
needs to be enabled. This patch factors out the code that enables
SYSCLK for this sequence such that it can be used for other boot time
operations that require SYSCLK.

Signed-off-by: Charles Keepax <[email protected]>
Acked-by: Lee Jones <[email protected]>
---
drivers/mfd/arizona-core.c | 77 ++++++++++++++++++++++++++++++++-----------
1 files changed, 57 insertions(+), 20 deletions(-)

diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 326a4af..b5a7e0e 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -264,19 +264,25 @@ static void arizona_disable_reset(struct arizona *arizona)
}
}

-static int wm5102_apply_hardware_patch(struct arizona *arizona)
+struct arizona_sysclk_state {
+ unsigned int fll;
+ unsigned int sysclk;
+};
+
+static int arizona_enable_freerun_sysclk(struct arizona *arizona,
+ struct arizona_sysclk_state *state)
{
- unsigned int fll, sysclk;
int ret, err;

/* Cache existing FLL and SYSCLK settings */
- ret = regmap_read(arizona->regmap, ARIZONA_FLL1_CONTROL_1, &fll);
+ ret = regmap_read(arizona->regmap, ARIZONA_FLL1_CONTROL_1, &state->fll);
if (ret) {
dev_err(arizona->dev, "Failed to cache FLL settings: %d\n",
ret);
return ret;
}
- ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &sysclk);
+ ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1,
+ &state->sysclk);
if (ret) {
dev_err(arizona->dev, "Failed to cache SYSCLK settings: %d\n",
ret);
@@ -306,14 +312,58 @@ static int wm5102_apply_hardware_patch(struct arizona *arizona)
goto err_fll;
}

+ return 0;
+
+err_fll:
+ err = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1, state->fll);
+ if (err)
+ dev_err(arizona->dev,
+ "Failed to re-apply old FLL settings: %d\n", err);
+
+ return ret;
+}
+
+static int arizona_disable_freerun_sysclk(struct arizona *arizona,
+ struct arizona_sysclk_state *state)
+{
+ int ret;
+
+ ret = regmap_write(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1,
+ state->sysclk);
+ if (ret) {
+ dev_err(arizona->dev,
+ "Failed to re-apply old SYSCLK settings: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1, state->fll);
+ if (ret) {
+ dev_err(arizona->dev,
+ "Failed to re-apply old FLL settings: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int wm5102_apply_hardware_patch(struct arizona *arizona)
+{
+ struct arizona_sysclk_state state;
+ int err, ret;
+
+ ret = arizona_enable_freerun_sysclk(arizona, &state);
+ if (ret)
+ return ret;
+
/* Start the write sequencer and wait for it to finish */
ret = regmap_write(arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_0,
ARIZONA_WSEQ_ENA | ARIZONA_WSEQ_START | 160);
if (ret) {
dev_err(arizona->dev, "Failed to start write sequencer: %d\n",
ret);
- goto err_sysclk;
+ goto err;
}
+
ret = arizona_poll_reg(arizona, 5, ARIZONA_WRITE_SEQUENCER_CTRL_1,
ARIZONA_WSEQ_BUSY, 0);
if (ret) {
@@ -322,21 +372,8 @@ static int wm5102_apply_hardware_patch(struct arizona *arizona)
ret = -ETIMEDOUT;
}

-err_sysclk:
- err = regmap_write(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, sysclk);
- if (err) {
- dev_err(arizona->dev,
- "Failed to re-apply old SYSCLK settings: %d\n",
- err);
- }
-
-err_fll:
- err = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1, fll);
- if (err) {
- dev_err(arizona->dev,
- "Failed to re-apply old FLL settings: %d\n",
- err);
- }
+err:
+ err = arizona_disable_freerun_sysclk(arizona, &state);

return ret ?: err;
}
--
1.7.2.5

2015-05-11 13:07:39

by Charles Keepax

[permalink] [raw]
Subject: [RESEND PATCH v3 06/10] mfd: wm5110: Add register patch required for low power sleep

Some register settings must be applied before the first time low power
sleep mode is entered on the wm5110 to ensure optimium performance.
These settings require SYSCLK to be enabled whilst they are being
applied. This patch applies the settings using the recently factored out
boot time SYSCLK functionality.

Signed-off-by: Charles Keepax <[email protected]>
Acked-by: Lee Jones <[email protected]>
---
drivers/mfd/arizona-core.c | 39 +++++++++++++++++++++++++++++++++++++++
1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index b5a7e0e..c80ab79 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -378,6 +378,35 @@ err:
return ret ?: err;
}

+/*
+ * Register patch to some of the CODECs internal write sequences
+ * to ensure a clean exit from the low power sleep state.
+ */
+static const struct reg_default wm5110_sleep_patch[] = {
+ { 0x337A, 0xC100 },
+ { 0x337B, 0x0041 },
+ { 0x3300, 0xA210 },
+ { 0x3301, 0x050C },
+};
+
+static int wm5110_apply_sleep_patch(struct arizona *arizona)
+{
+ struct arizona_sysclk_state state;
+ int err, ret;
+
+ ret = arizona_enable_freerun_sysclk(arizona, &state);
+ if (ret)
+ return ret;
+
+ ret = regmap_multi_reg_write_bypassed(arizona->regmap,
+ wm5110_sleep_patch,
+ ARRAY_SIZE(wm5110_sleep_patch));
+
+ err = arizona_disable_freerun_sysclk(arizona, &state);
+
+ return ret ?: err;
+}
+
static int wm5102_clear_write_sequencer(struct arizona *arizona)
{
int ret;
@@ -966,6 +995,16 @@ int arizona_dev_init(struct arizona *arizona)
goto err_reset;
}
break;
+ case WM5110:
+ case WM8280:
+ ret = wm5110_apply_sleep_patch(arizona);
+ if (ret) {
+ dev_err(arizona->dev,
+ "Failed to apply sleep patch: %d\n",
+ ret);
+ goto err_reset;
+ }
+ break;
default:
break;
}
--
1.7.2.5

2015-05-11 13:09:31

by Charles Keepax

[permalink] [raw]
Subject: [RESEND PATCH v3 07/10] regulator: arizona-ldo1: Add additional supported voltage

This patch adds support for the 1.175V mode on the LDO1 regulator on the
wm5110. This is need as part of the low power sleep mode operation.

Signed-off-by: Charles Keepax <[email protected]>
Acked-by: Mark Brown <[email protected]>
---
drivers/regulator/arizona-ldo1.c | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
index a1d07d3..9094163 100644
--- a/drivers/regulator/arizona-ldo1.c
+++ b/drivers/regulator/arizona-ldo1.c
@@ -178,6 +178,16 @@ static const struct regulator_init_data arizona_ldo1_default = {
.num_consumer_supplies = 1,
};

+static const struct regulator_init_data arizona_ldo1_wm5110 = {
+ .constraints = {
+ .min_uV = 1175000,
+ .max_uV = 1200000,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS |
+ REGULATOR_CHANGE_VOLTAGE,
+ },
+ .num_consumer_supplies = 1,
+};
+
static int arizona_ldo1_of_get_pdata(struct arizona *arizona,
struct regulator_config *config,
const struct regulator_desc *desc)
@@ -243,6 +253,11 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
desc = &arizona_ldo1_hc;
ldo1->init_data = arizona_ldo1_dvfs;
break;
+ case WM5110:
+ case WM8280:
+ desc = &arizona_ldo1;
+ ldo1->init_data = arizona_ldo1_wm5110;
+ break;
default:
desc = &arizona_ldo1;
ldo1->init_data = arizona_ldo1_default;
--
1.7.2.5

2015-05-11 13:08:23

by Charles Keepax

[permalink] [raw]
Subject: [RESEND PATCH v3 08/10] mfd: wm5110: Set DCVDD voltage to 1.175V before entering sleep mode

The low power sleep mode on wm5110 requires that the LDO1 regulator be
set to 1.175V prior to entering sleep, then returned to 1.2V after
exiting sleep mode. This patch apply these regulator settings.

Signed-off-by: Charles Keepax <[email protected]>
Acked-by: Mark Brown <[email protected]>
Acked-by: Lee Jones <[email protected]>
---
drivers/mfd/arizona-core.c | 52 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 52 insertions(+), 0 deletions(-)

diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index c80ab79..93024ac 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -478,6 +478,37 @@ static int arizona_runtime_resume(struct device *dev)
goto err;
}
break;
+ case WM5110:
+ case WM8280:
+ ret = arizona_wait_for_boot(arizona);
+ if (ret)
+ goto err;
+
+ if (arizona->external_dcvdd) {
+ ret = regmap_update_bits(arizona->regmap,
+ ARIZONA_ISOLATION_CONTROL,
+ ARIZONA_ISOLATE_DCVDD1, 0);
+ if (ret) {
+ dev_err(arizona->dev,
+ "Failed to connect DCVDD: %d\n", ret);
+ goto err;
+ }
+ } else {
+ /*
+ * As this is only called for the internal regulator
+ * (where we know voltage ranges available) it is ok
+ * to request an exact range.
+ */
+ ret = regulator_set_voltage(arizona->dcvdd,
+ 1200000, 1200000);
+ if (ret < 0) {
+ dev_err(arizona->dev,
+ "Failed to set resume voltage: %d\n",
+ ret);
+ goto err;
+ }
+ }
+ break;
default:
ret = arizona_wait_for_boot(arizona);
if (ret != 0) {
@@ -528,6 +559,27 @@ static int arizona_runtime_suspend(struct device *dev)
ret);
return ret;
}
+ } else {
+ switch (arizona->type) {
+ case WM5110:
+ case WM8280:
+ /*
+ * As this is only called for the internal regulator
+ * (where we know voltage ranges available) it is ok
+ * to request an exact range.
+ */
+ ret = regulator_set_voltage(arizona->dcvdd,
+ 1175000, 1175000);
+ if (ret < 0) {
+ dev_err(arizona->dev,
+ "Failed to set suspend voltage: %d\n",
+ ret);
+ return ret;
+ }
+ break;
+ default:
+ break;
+ }
}

regcache_cache_only(arizona->regmap, true);
--
1.7.2.5

2015-05-11 13:08:22

by Charles Keepax

[permalink] [raw]
Subject: [RESEND PATCH v3 09/10] mfd: arizona: Add better support for system suspend

Allow the chip to completely power off if we enter runtime suspend and
there is no jack detection active. This is helpful for systems where
system suspend might remove the supplies to the CODEC, without informing
us. Note the powering off is done in runtime suspend rather than system
suspend, because we need to hold reset until the first time DCVDD is
powered anyway (which would be in runtime resume), and we might as well
save the extra power.

Signed-off-by: Charles Keepax <[email protected]>
Acked-by: Lee Jones <[email protected]>
---
drivers/mfd/arizona-core.c | 94 +++++++++++++++++++++++++++++++-------
include/linux/mfd/arizona/core.h | 1 +
2 files changed, 78 insertions(+), 17 deletions(-)

diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 93024ac..f1ff68a 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -442,12 +442,33 @@ static int arizona_runtime_resume(struct device *dev)

dev_dbg(arizona->dev, "Leaving AoD mode\n");

+ if (arizona->has_fully_powered_off) {
+ dev_dbg(arizona->dev, "Re-enabling core supplies\n");
+
+ ret = regulator_bulk_enable(arizona->num_core_supplies,
+ arizona->core_supplies);
+ if (ret) {
+ dev_err(dev, "Failed to enable core supplies: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
ret = regulator_enable(arizona->dcvdd);
if (ret != 0) {
dev_err(arizona->dev, "Failed to enable DCVDD: %d\n", ret);
+ if (arizona->has_fully_powered_off)
+ regulator_bulk_disable(arizona->num_core_supplies,
+ arizona->core_supplies);
return ret;
}

+ if (arizona->has_fully_powered_off) {
+ arizona_disable_reset(arizona);
+ enable_irq(arizona->irq);
+ arizona->has_fully_powered_off = false;
+ }
+
regcache_cache_only(arizona->regmap, false);

switch (arizona->type) {
@@ -508,6 +529,14 @@ static int arizona_runtime_resume(struct device *dev)
goto err;
}
}
+
+ ret = wm5110_apply_sleep_patch(arizona);
+ if (ret) {
+ dev_err(arizona->dev,
+ "Failed to re-apply sleep patch: %d\n",
+ ret);
+ goto err;
+ }
break;
default:
ret = arizona_wait_for_boot(arizona);
@@ -545,10 +574,17 @@ err:
static int arizona_runtime_suspend(struct device *dev)
{
struct arizona *arizona = dev_get_drvdata(dev);
+ unsigned int val;
int ret;

dev_dbg(arizona->dev, "Entering AoD mode\n");

+ ret = regmap_read(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, &val);
+ if (ret) {
+ dev_err(dev, "Failed to check jack det status: %d\n", ret);
+ return ret;
+ }
+
if (arizona->external_dcvdd) {
ret = regmap_update_bits(arizona->regmap,
ARIZONA_ISOLATION_CONTROL,
@@ -559,33 +595,57 @@ static int arizona_runtime_suspend(struct device *dev)
ret);
return ret;
}
- } else {
- switch (arizona->type) {
- case WM5110:
- case WM8280:
- /*
- * As this is only called for the internal regulator
- * (where we know voltage ranges available) it is ok
- * to request an exact range.
- */
- ret = regulator_set_voltage(arizona->dcvdd,
- 1175000, 1175000);
- if (ret < 0) {
+ }
+
+ switch (arizona->type) {
+ case WM5110:
+ case WM8280:
+ if (arizona->external_dcvdd)
+ break;
+
+ /*
+ * As this is only called for the internal regulator
+ * (where we know voltage ranges available) it is ok
+ * to request an exact range.
+ */
+ ret = regulator_set_voltage(arizona->dcvdd, 1175000, 1175000);
+ if (ret < 0) {
+ dev_err(arizona->dev,
+ "Failed to set suspend voltage: %d\n", ret);
+ return ret;
+ }
+ break;
+ case WM5102:
+ if (!(val & ARIZONA_JD1_ENA))
+ ret = regmap_write(arizona->regmap,
+ ARIZONA_WRITE_SEQUENCER_CTRL_3, 0x0);
+ if (ret) {
dev_err(arizona->dev,
- "Failed to set suspend voltage: %d\n",
+ "Failed to clear write sequencer: %d\n",
ret);
return ret;
}
- break;
- default:
- break;
- }
+ break;
+ default:
+ break;
}

regcache_cache_only(arizona->regmap, true);
regcache_mark_dirty(arizona->regmap);
regulator_disable(arizona->dcvdd);

+ /* Allow us to completely power down if no jack detection */
+ if (!(val & ARIZONA_JD1_ENA)) {
+ dev_dbg(arizona->dev, "Fully powering off\n");
+
+ arizona->has_fully_powered_off = true;
+
+ disable_irq(arizona->irq);
+ arizona_enable_reset(arizona);
+ regulator_bulk_disable(arizona->num_core_supplies,
+ arizona->core_supplies);
+ }
+
return 0;
}
#endif
diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h
index 16a498f..847bdaf 100644
--- a/include/linux/mfd/arizona/core.h
+++ b/include/linux/mfd/arizona/core.h
@@ -117,6 +117,7 @@ struct arizona {
int num_core_supplies;
struct regulator_bulk_data core_supplies[ARIZONA_MAX_CORE_SUPPLIES];
struct regulator *dcvdd;
+ bool has_fully_powered_off;

struct arizona_pdata pdata;

--
1.7.2.5

2015-05-11 13:08:05

by Charles Keepax

[permalink] [raw]
Subject: [RESEND PATCH v3 10/10] mfd: wm5110: Add delay before releasing reset line

On the wm5110 it is important the reset line is held for slightly longer
to ensure the device starts up well. This patch adds a 5mS delay for
this.

Signed-off-by: Charles Keepax <[email protected]>
Acked-by: Lee Jones <[email protected]>
---
drivers/mfd/arizona-core.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index f1ff68a..93e4d94 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -259,6 +259,16 @@ static inline void arizona_enable_reset(struct arizona *arizona)
static void arizona_disable_reset(struct arizona *arizona)
{
if (arizona->pdata.reset) {
+ switch (arizona->type) {
+ case WM5110:
+ case WM8280:
+ /* Meet requirements for minimum reset duration */
+ msleep(5);
+ break;
+ default:
+ break;
+ }
+
gpio_set_value_cansleep(arizona->pdata.reset, 1);
msleep(1);
}
--
1.7.2.5

2015-05-11 14:20:17

by Mark Brown

[permalink] [raw]
Subject: Re: [RESEND PATCH v3 07/10] regulator: arizona-ldo1: Add additional supported voltage

On Mon, May 11, 2015 at 01:58:07PM +0100, Charles Keepax wrote:
> This patch adds support for the 1.175V mode on the LDO1 regulator on the
> wm5110. This is need as part of the low power sleep mode operation.

Applied, thanks. Why did this not get applied along with the other
WM8280 stuff?


Attachments:
(No filename) (292.00 B)
signature.asc (473.00 B)
Digital signature
Download all attachments

2015-05-11 14:42:10

by Charles Keepax

[permalink] [raw]
Subject: Re: [RESEND PATCH v3 07/10] regulator: arizona-ldo1: Add additional supported voltage

On Mon, May 11, 2015 at 03:20:02PM +0100, Mark Brown wrote:
> On Mon, May 11, 2015 at 01:58:07PM +0100, Charles Keepax wrote:
> > This patch adds support for the 1.175V mode on the LDO1 regulator on the
> > wm5110. This is need as part of the low power sleep mode operation.
>
> Applied, thanks. Why did this not get applied along with the other
> WM8280 stuff?

The series that has already been applied basically just added the
wm8280. This series does a bunch of fixups to the boot of both
wm5110 and wm8280 and this patch is required as part of that.

Thanks,
Charles

2015-05-11 16:05:05

by Mark Brown

[permalink] [raw]
Subject: Re: [RESEND PATCH v3 07/10] regulator: arizona-ldo1: Add additional supported voltage

On Mon, May 11, 2015 at 03:41:49PM +0100, Charles Keepax wrote:
> On Mon, May 11, 2015 at 03:20:02PM +0100, Mark Brown wrote:

> > Applied, thanks. Why did this not get applied along with the other
> > WM8280 stuff?

> The series that has already been applied basically just added the
> wm8280. This series does a bunch of fixups to the boot of both
> wm5110 and wm8280 and this patch is required as part of that.

Yes, what I'm saying is that it's disappointing that this got blocked
on whatever else is causing trouble for the rest of this series given
that once the WM8280 core support went in this has no dependencies and
could already have been part of Linus' tree.


Attachments:
(No filename) (672.00 B)
signature.asc (473.00 B)
Digital signature
Download all attachments

2015-05-13 12:20:33

by Lee Jones

[permalink] [raw]
Subject: Re: [RESEND PATCH v3 01/10] mfd: arizona: Use devres to manage reset GPIO

On Mon, 11 May 2015, Charles Keepax wrote:

> This also handily fixes a leak of the GPIO in arizona_dev_exit.
>
> Signed-off-by: Charles Keepax <[email protected]>
> Acked-by: Lee Jones <[email protected]>
> ---
> drivers/mfd/arizona-core.c | 10 ++++------
> 1 files changed, 4 insertions(+), 6 deletions(-)

Applied, thanks.

> diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
> index aed43a5..915cc28 100644
> --- a/drivers/mfd/arizona-core.c
> +++ b/drivers/mfd/arizona-core.c
> @@ -728,9 +728,9 @@ int arizona_dev_init(struct arizona *arizona)
>
> if (arizona->pdata.reset) {
> /* Start out with /RESET low to put the chip into reset */
> - ret = gpio_request_one(arizona->pdata.reset,
> - GPIOF_DIR_OUT | GPIOF_INIT_LOW,
> - "arizona /RESET");
> + ret = devm_gpio_request_one(arizona->dev, arizona->pdata.reset,
> + GPIOF_DIR_OUT | GPIOF_INIT_LOW,
> + "arizona /RESET");
> if (ret != 0) {
> dev_err(dev, "Failed to request /RESET: %d\n", ret);
> goto err_dcvdd;
> @@ -1046,10 +1046,8 @@ int arizona_dev_init(struct arizona *arizona)
> err_irq:
> arizona_irq_exit(arizona);
> err_reset:
> - if (arizona->pdata.reset) {
> + if (arizona->pdata.reset)
> gpio_set_value_cansleep(arizona->pdata.reset, 0);
> - gpio_free(arizona->pdata.reset);
> - }
> regulator_disable(arizona->dcvdd);
> err_enable:
> regulator_bulk_disable(arizona->num_core_supplies,

--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

2015-05-13 12:20:50

by Lee Jones

[permalink] [raw]
Subject: Re: [RESEND PATCH v3 02/10] mfd: arizona: Factor out hard reset into helper functions

On Mon, 11 May 2015, Charles Keepax wrote:

> This patch adds functions for enabling and disabling the physical reset
> line. This will be helpful in future refactoring.
>
> Signed-off-by: Charles Keepax <[email protected]>
> Acked-by: Lee Jones <[email protected]>
> ---
> drivers/mfd/arizona-core.c | 25 +++++++++++++++++--------
> 1 files changed, 17 insertions(+), 8 deletions(-)

Applied, thanks.

> diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
> index 915cc28..f30d925 100644
> --- a/drivers/mfd/arizona-core.c
> +++ b/drivers/mfd/arizona-core.c
> @@ -250,6 +250,20 @@ static int arizona_wait_for_boot(struct arizona *arizona)
> return ret;
> }
>
> +static inline void arizona_enable_reset(struct arizona *arizona)
> +{
> + if (arizona->pdata.reset)
> + gpio_set_value_cansleep(arizona->pdata.reset, 0);
> +}
> +
> +static void arizona_disable_reset(struct arizona *arizona)
> +{
> + if (arizona->pdata.reset) {
> + gpio_set_value_cansleep(arizona->pdata.reset, 1);
> + msleep(1);
> + }
> +}
> +
> static int arizona_apply_hardware_patch(struct arizona* arizona)
> {
> unsigned int fll, sysclk;
> @@ -751,10 +765,7 @@ int arizona_dev_init(struct arizona *arizona)
> goto err_enable;
> }
>
> - if (arizona->pdata.reset) {
> - gpio_set_value_cansleep(arizona->pdata.reset, 1);
> - msleep(1);
> - }
> + arizona_disable_reset(arizona);
>
> regcache_cache_only(arizona->regmap, false);
>
> @@ -1046,8 +1057,7 @@ int arizona_dev_init(struct arizona *arizona)
> err_irq:
> arizona_irq_exit(arizona);
> err_reset:
> - if (arizona->pdata.reset)
> - gpio_set_value_cansleep(arizona->pdata.reset, 0);
> + arizona_enable_reset(arizona);
> regulator_disable(arizona->dcvdd);
> err_enable:
> regulator_bulk_disable(arizona->num_core_supplies,
> @@ -1072,8 +1082,7 @@ int arizona_dev_exit(struct arizona *arizona)
> arizona_free_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, arizona);
> arizona_free_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, arizona);
> arizona_irq_exit(arizona);
> - if (arizona->pdata.reset)
> - gpio_set_value_cansleep(arizona->pdata.reset, 0);
> + arizona_enable_reset(arizona);
>
> regulator_bulk_disable(arizona->num_core_supplies,
> arizona->core_supplies);

--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

2015-05-13 12:21:00

by Lee Jones

[permalink] [raw]
Subject: Re: [RESEND PATCH v3 03/10] mfd: wm5102: Ensure we always boot the device fully

On Mon, 11 May 2015, Charles Keepax wrote:

> The wm5102 uses a custom boot sequence and the standard boot sequence is
> disabled. However, the standard boot sequence must be run at least once
> after a cold boot (caused by either a hard reset or removal of AVDD).
> Unfortunately the register WRITE_SEQUENCER_CTRL_3 is not affected by the
> hardware reset. This means if the device has been previously booted but
> the AVDD supply has never been removed, arizona_dev_init will reset the
> chip but the boot sequence will not run, which can cause numerous
> problems. The solution is to manually clear this register and then boot
> the chip again, which is what this patch does.
>
> Signed-off-by: Charles Keepax <[email protected]>
> Acked-by: Lee Jones <[email protected]>
> ---
> drivers/mfd/arizona-core.c | 50 +++++++++++++++++++++++++++++++++++--------
> 1 files changed, 40 insertions(+), 10 deletions(-)

Applied, thanks.

> diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
> index f30d925..0df1299 100644
> --- a/drivers/mfd/arizona-core.c
> +++ b/drivers/mfd/arizona-core.c
> @@ -344,6 +344,33 @@ err_fll:
> return err;
> }
>
> +static int wm5102_clear_write_sequencer(struct arizona *arizona)
> +{
> + int ret;
> +
> + ret = regmap_write(arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_3,
> + 0x0);
> + if (ret) {
> + dev_err(arizona->dev,
> + "Failed to clear write sequencer state: %d\n", ret);
> + return ret;
> + }
> +
> + arizona_enable_reset(arizona);
> + regulator_disable(arizona->dcvdd);
> +
> + msleep(20);
> +
> + ret = regulator_enable(arizona->dcvdd);
> + if (ret) {
> + dev_err(arizona->dev, "Failed to re-enable DCVDD: %d\n", ret);
> + return ret;
> + }
> + arizona_disable_reset(arizona);
> +
> + return 0;
> +}
> +
> #ifdef CONFIG_PM
> static int arizona_runtime_resume(struct device *dev)
> {
> @@ -802,21 +829,24 @@ int arizona_dev_init(struct arizona *arizona)
> case WM5102:
> ret = regmap_read(arizona->regmap,
> ARIZONA_WRITE_SEQUENCER_CTRL_3, &val);
> - if (ret != 0)
> + if (ret) {
> dev_err(dev,
> "Failed to check write sequencer state: %d\n",
> ret);
> - else if (val & 0x01)
> - break;
> - /* Fall through */
> - default:
> - ret = arizona_wait_for_boot(arizona);
> - if (ret != 0) {
> - dev_err(arizona->dev,
> - "Device failed initial boot: %d\n", ret);
> - goto err_reset;
> + } else if (val & 0x01) {
> + ret = wm5102_clear_write_sequencer(arizona);
> + if (ret)
> + return ret;
> }
> break;
> + default:
> + break;
> + }
> +
> + ret = arizona_wait_for_boot(arizona);
> + if (ret) {
> + dev_err(arizona->dev, "Device failed initial boot: %d\n", ret);
> + goto err_reset;
> }
>
> /* Read the device ID information & do device specific stuff */

--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

2015-05-13 12:21:15

by Lee Jones

[permalink] [raw]
Subject: Re: [RESEND PATCH v3 04/10] mfd: arizona: Fix formating/style issues in arizona_apply_hardware_patch

On Mon, 11 May 2015, Charles Keepax wrote:

> In preparation for some refactoring fixup some minor style, formating
> and code clarity issues.
>
> Signed-off-by: Charles Keepax <[email protected]>
> Acked-by: Lee Jones <[email protected]>
> ---
> drivers/mfd/arizona-core.c | 37 +++++++++++++++++--------------------
> 1 files changed, 17 insertions(+), 20 deletions(-)

Applied, thanks.

> diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
> index 0df1299..326a4af 100644
> --- a/drivers/mfd/arizona-core.c
> +++ b/drivers/mfd/arizona-core.c
> @@ -264,20 +264,20 @@ static void arizona_disable_reset(struct arizona *arizona)
> }
> }
>
> -static int arizona_apply_hardware_patch(struct arizona* arizona)
> +static int wm5102_apply_hardware_patch(struct arizona *arizona)
> {
> unsigned int fll, sysclk;
> int ret, err;
>
> /* Cache existing FLL and SYSCLK settings */
> ret = regmap_read(arizona->regmap, ARIZONA_FLL1_CONTROL_1, &fll);
> - if (ret != 0) {
> + if (ret) {
> dev_err(arizona->dev, "Failed to cache FLL settings: %d\n",
> ret);
> return ret;
> }
> ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &sysclk);
> - if (ret != 0) {
> + if (ret) {
> dev_err(arizona->dev, "Failed to cache SYSCLK settings: %d\n",
> ret);
> return ret;
> @@ -286,7 +286,7 @@ static int arizona_apply_hardware_patch(struct arizona* arizona)
> /* Start up SYSCLK using the FLL in free running mode */
> ret = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1,
> ARIZONA_FLL1_ENA | ARIZONA_FLL1_FREERUN);
> - if (ret != 0) {
> + if (ret) {
> dev_err(arizona->dev,
> "Failed to start FLL in freerunning mode: %d\n",
> ret);
> @@ -295,36 +295,36 @@ static int arizona_apply_hardware_patch(struct arizona* arizona)
> ret = arizona_poll_reg(arizona, 25, ARIZONA_INTERRUPT_RAW_STATUS_5,
> ARIZONA_FLL1_CLOCK_OK_STS,
> ARIZONA_FLL1_CLOCK_OK_STS);
> - if (ret != 0) {
> + if (ret) {
> ret = -ETIMEDOUT;
> goto err_fll;
> }
>
> ret = regmap_write(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, 0x0144);
> - if (ret != 0) {
> + if (ret) {
> dev_err(arizona->dev, "Failed to start SYSCLK: %d\n", ret);
> goto err_fll;
> }
>
> /* Start the write sequencer and wait for it to finish */
> ret = regmap_write(arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_0,
> - ARIZONA_WSEQ_ENA | ARIZONA_WSEQ_START | 160);
> - if (ret != 0) {
> + ARIZONA_WSEQ_ENA | ARIZONA_WSEQ_START | 160);
> + if (ret) {
> dev_err(arizona->dev, "Failed to start write sequencer: %d\n",
> ret);
> goto err_sysclk;
> }
> ret = arizona_poll_reg(arizona, 5, ARIZONA_WRITE_SEQUENCER_CTRL_1,
> ARIZONA_WSEQ_BUSY, 0);
> - if (ret != 0) {
> + if (ret) {
> regmap_write(arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_0,
> - ARIZONA_WSEQ_ABORT);
> + ARIZONA_WSEQ_ABORT);
> ret = -ETIMEDOUT;
> }
>
> err_sysclk:
> err = regmap_write(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, sysclk);
> - if (err != 0) {
> + if (err) {
> dev_err(arizona->dev,
> "Failed to re-apply old SYSCLK settings: %d\n",
> err);
> @@ -332,16 +332,13 @@ err_sysclk:
>
> err_fll:
> err = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1, fll);
> - if (err != 0) {
> + if (err) {
> dev_err(arizona->dev,
> "Failed to re-apply old FLL settings: %d\n",
> err);
> }
>
> - if (ret != 0)
> - return ret;
> - else
> - return err;
> + return ret ?: err;
> }
>
> static int wm5102_clear_write_sequencer(struct arizona *arizona)
> @@ -407,8 +404,8 @@ static int arizona_runtime_resume(struct device *dev)
> goto err;
> }
>
> - ret = arizona_apply_hardware_patch(arizona);
> - if (ret != 0) {
> + ret = wm5102_apply_hardware_patch(arizona);
> + if (ret) {
> dev_err(arizona->dev,
> "Failed to apply hardware patch: %d\n",
> ret);
> @@ -924,8 +921,8 @@ int arizona_dev_init(struct arizona *arizona)
>
> switch (arizona->type) {
> case WM5102:
> - ret = arizona_apply_hardware_patch(arizona);
> - if (ret != 0) {
> + ret = wm5102_apply_hardware_patch(arizona);
> + if (ret) {
> dev_err(arizona->dev,
> "Failed to apply hardware patch: %d\n",
> ret);

--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

2015-05-13 12:21:27

by Lee Jones

[permalink] [raw]
Subject: Re: [RESEND PATCH v3 05/10] mfd: arizona: Factor out SYSCLK enable from wm5102 hardware patch

On Mon, 11 May 2015, Charles Keepax wrote:

> wm5102 applies a custom hardware boot sequence, for this the SYSCLK
> needs to be enabled. This patch factors out the code that enables
> SYSCLK for this sequence such that it can be used for other boot time
> operations that require SYSCLK.
>
> Signed-off-by: Charles Keepax <[email protected]>
> Acked-by: Lee Jones <[email protected]>
> ---
> drivers/mfd/arizona-core.c | 77 ++++++++++++++++++++++++++++++++-----------
> 1 files changed, 57 insertions(+), 20 deletions(-)

Applied, thanks.

> diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
> index 326a4af..b5a7e0e 100644
> --- a/drivers/mfd/arizona-core.c
> +++ b/drivers/mfd/arizona-core.c
> @@ -264,19 +264,25 @@ static void arizona_disable_reset(struct arizona *arizona)
> }
> }
>
> -static int wm5102_apply_hardware_patch(struct arizona *arizona)
> +struct arizona_sysclk_state {
> + unsigned int fll;
> + unsigned int sysclk;
> +};
> +
> +static int arizona_enable_freerun_sysclk(struct arizona *arizona,
> + struct arizona_sysclk_state *state)
> {
> - unsigned int fll, sysclk;
> int ret, err;
>
> /* Cache existing FLL and SYSCLK settings */
> - ret = regmap_read(arizona->regmap, ARIZONA_FLL1_CONTROL_1, &fll);
> + ret = regmap_read(arizona->regmap, ARIZONA_FLL1_CONTROL_1, &state->fll);
> if (ret) {
> dev_err(arizona->dev, "Failed to cache FLL settings: %d\n",
> ret);
> return ret;
> }
> - ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &sysclk);
> + ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1,
> + &state->sysclk);
> if (ret) {
> dev_err(arizona->dev, "Failed to cache SYSCLK settings: %d\n",
> ret);
> @@ -306,14 +312,58 @@ static int wm5102_apply_hardware_patch(struct arizona *arizona)
> goto err_fll;
> }
>
> + return 0;
> +
> +err_fll:
> + err = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1, state->fll);
> + if (err)
> + dev_err(arizona->dev,
> + "Failed to re-apply old FLL settings: %d\n", err);
> +
> + return ret;
> +}
> +
> +static int arizona_disable_freerun_sysclk(struct arizona *arizona,
> + struct arizona_sysclk_state *state)
> +{
> + int ret;
> +
> + ret = regmap_write(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1,
> + state->sysclk);
> + if (ret) {
> + dev_err(arizona->dev,
> + "Failed to re-apply old SYSCLK settings: %d\n", ret);
> + return ret;
> + }
> +
> + ret = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1, state->fll);
> + if (ret) {
> + dev_err(arizona->dev,
> + "Failed to re-apply old FLL settings: %d\n", ret);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int wm5102_apply_hardware_patch(struct arizona *arizona)
> +{
> + struct arizona_sysclk_state state;
> + int err, ret;
> +
> + ret = arizona_enable_freerun_sysclk(arizona, &state);
> + if (ret)
> + return ret;
> +
> /* Start the write sequencer and wait for it to finish */
> ret = regmap_write(arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_0,
> ARIZONA_WSEQ_ENA | ARIZONA_WSEQ_START | 160);
> if (ret) {
> dev_err(arizona->dev, "Failed to start write sequencer: %d\n",
> ret);
> - goto err_sysclk;
> + goto err;
> }
> +
> ret = arizona_poll_reg(arizona, 5, ARIZONA_WRITE_SEQUENCER_CTRL_1,
> ARIZONA_WSEQ_BUSY, 0);
> if (ret) {
> @@ -322,21 +372,8 @@ static int wm5102_apply_hardware_patch(struct arizona *arizona)
> ret = -ETIMEDOUT;
> }
>
> -err_sysclk:
> - err = regmap_write(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, sysclk);
> - if (err) {
> - dev_err(arizona->dev,
> - "Failed to re-apply old SYSCLK settings: %d\n",
> - err);
> - }
> -
> -err_fll:
> - err = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1, fll);
> - if (err) {
> - dev_err(arizona->dev,
> - "Failed to re-apply old FLL settings: %d\n",
> - err);
> - }
> +err:
> + err = arizona_disable_freerun_sysclk(arizona, &state);
>
> return ret ?: err;
> }

--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

2015-05-13 12:21:38

by Lee Jones

[permalink] [raw]
Subject: Re: [RESEND PATCH v3 06/10] mfd: wm5110: Add register patch required for low power sleep

On Mon, 11 May 2015, Charles Keepax wrote:

> Some register settings must be applied before the first time low power
> sleep mode is entered on the wm5110 to ensure optimium performance.
> These settings require SYSCLK to be enabled whilst they are being
> applied. This patch applies the settings using the recently factored out
> boot time SYSCLK functionality.
>
> Signed-off-by: Charles Keepax <[email protected]>
> Acked-by: Lee Jones <[email protected]>
> ---
> drivers/mfd/arizona-core.c | 39 +++++++++++++++++++++++++++++++++++++++
> 1 files changed, 39 insertions(+), 0 deletions(-)

Applied, thanks.

> diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
> index b5a7e0e..c80ab79 100644
> --- a/drivers/mfd/arizona-core.c
> +++ b/drivers/mfd/arizona-core.c
> @@ -378,6 +378,35 @@ err:
> return ret ?: err;
> }
>
> +/*
> + * Register patch to some of the CODECs internal write sequences
> + * to ensure a clean exit from the low power sleep state.
> + */
> +static const struct reg_default wm5110_sleep_patch[] = {
> + { 0x337A, 0xC100 },
> + { 0x337B, 0x0041 },
> + { 0x3300, 0xA210 },
> + { 0x3301, 0x050C },
> +};
> +
> +static int wm5110_apply_sleep_patch(struct arizona *arizona)
> +{
> + struct arizona_sysclk_state state;
> + int err, ret;
> +
> + ret = arizona_enable_freerun_sysclk(arizona, &state);
> + if (ret)
> + return ret;
> +
> + ret = regmap_multi_reg_write_bypassed(arizona->regmap,
> + wm5110_sleep_patch,
> + ARRAY_SIZE(wm5110_sleep_patch));
> +
> + err = arizona_disable_freerun_sysclk(arizona, &state);
> +
> + return ret ?: err;
> +}
> +
> static int wm5102_clear_write_sequencer(struct arizona *arizona)
> {
> int ret;
> @@ -966,6 +995,16 @@ int arizona_dev_init(struct arizona *arizona)
> goto err_reset;
> }
> break;
> + case WM5110:
> + case WM8280:
> + ret = wm5110_apply_sleep_patch(arizona);
> + if (ret) {
> + dev_err(arizona->dev,
> + "Failed to apply sleep patch: %d\n",
> + ret);
> + goto err_reset;
> + }
> + break;
> default:
> break;
> }

--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

2015-05-13 12:21:47

by Lee Jones

[permalink] [raw]
Subject: Re: [RESEND PATCH v3 08/10] mfd: wm5110: Set DCVDD voltage to 1.175V before entering sleep mode

On Mon, 11 May 2015, Charles Keepax wrote:

> The low power sleep mode on wm5110 requires that the LDO1 regulator be
> set to 1.175V prior to entering sleep, then returned to 1.2V after
> exiting sleep mode. This patch apply these regulator settings.
>
> Signed-off-by: Charles Keepax <[email protected]>
> Acked-by: Mark Brown <[email protected]>
> Acked-by: Lee Jones <[email protected]>
> ---
> drivers/mfd/arizona-core.c | 52 ++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 52 insertions(+), 0 deletions(-)

Applied, thanks.

> diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
> index c80ab79..93024ac 100644
> --- a/drivers/mfd/arizona-core.c
> +++ b/drivers/mfd/arizona-core.c
> @@ -478,6 +478,37 @@ static int arizona_runtime_resume(struct device *dev)
> goto err;
> }
> break;
> + case WM5110:
> + case WM8280:
> + ret = arizona_wait_for_boot(arizona);
> + if (ret)
> + goto err;
> +
> + if (arizona->external_dcvdd) {
> + ret = regmap_update_bits(arizona->regmap,
> + ARIZONA_ISOLATION_CONTROL,
> + ARIZONA_ISOLATE_DCVDD1, 0);
> + if (ret) {
> + dev_err(arizona->dev,
> + "Failed to connect DCVDD: %d\n", ret);
> + goto err;
> + }
> + } else {
> + /*
> + * As this is only called for the internal regulator
> + * (where we know voltage ranges available) it is ok
> + * to request an exact range.
> + */
> + ret = regulator_set_voltage(arizona->dcvdd,
> + 1200000, 1200000);
> + if (ret < 0) {
> + dev_err(arizona->dev,
> + "Failed to set resume voltage: %d\n",
> + ret);
> + goto err;
> + }
> + }
> + break;
> default:
> ret = arizona_wait_for_boot(arizona);
> if (ret != 0) {
> @@ -528,6 +559,27 @@ static int arizona_runtime_suspend(struct device *dev)
> ret);
> return ret;
> }
> + } else {
> + switch (arizona->type) {
> + case WM5110:
> + case WM8280:
> + /*
> + * As this is only called for the internal regulator
> + * (where we know voltage ranges available) it is ok
> + * to request an exact range.
> + */
> + ret = regulator_set_voltage(arizona->dcvdd,
> + 1175000, 1175000);
> + if (ret < 0) {
> + dev_err(arizona->dev,
> + "Failed to set suspend voltage: %d\n",
> + ret);
> + return ret;
> + }
> + break;
> + default:
> + break;
> + }
> }
>
> regcache_cache_only(arizona->regmap, true);

--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

2015-05-13 12:21:59

by Lee Jones

[permalink] [raw]
Subject: Re: [RESEND PATCH v3 09/10] mfd: arizona: Add better support for system suspend

On Mon, 11 May 2015, Charles Keepax wrote:

> Allow the chip to completely power off if we enter runtime suspend and
> there is no jack detection active. This is helpful for systems where
> system suspend might remove the supplies to the CODEC, without informing
> us. Note the powering off is done in runtime suspend rather than system
> suspend, because we need to hold reset until the first time DCVDD is
> powered anyway (which would be in runtime resume), and we might as well
> save the extra power.
>
> Signed-off-by: Charles Keepax <[email protected]>
> Acked-by: Lee Jones <[email protected]>
> ---
> drivers/mfd/arizona-core.c | 94 +++++++++++++++++++++++++++++++-------
> include/linux/mfd/arizona/core.h | 1 +
> 2 files changed, 78 insertions(+), 17 deletions(-)

Applied, thanks.

> diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
> index 93024ac..f1ff68a 100644
> --- a/drivers/mfd/arizona-core.c
> +++ b/drivers/mfd/arizona-core.c
> @@ -442,12 +442,33 @@ static int arizona_runtime_resume(struct device *dev)
>
> dev_dbg(arizona->dev, "Leaving AoD mode\n");
>
> + if (arizona->has_fully_powered_off) {
> + dev_dbg(arizona->dev, "Re-enabling core supplies\n");
> +
> + ret = regulator_bulk_enable(arizona->num_core_supplies,
> + arizona->core_supplies);
> + if (ret) {
> + dev_err(dev, "Failed to enable core supplies: %d\n",
> + ret);
> + return ret;
> + }
> + }
> +
> ret = regulator_enable(arizona->dcvdd);
> if (ret != 0) {
> dev_err(arizona->dev, "Failed to enable DCVDD: %d\n", ret);
> + if (arizona->has_fully_powered_off)
> + regulator_bulk_disable(arizona->num_core_supplies,
> + arizona->core_supplies);
> return ret;
> }
>
> + if (arizona->has_fully_powered_off) {
> + arizona_disable_reset(arizona);
> + enable_irq(arizona->irq);
> + arizona->has_fully_powered_off = false;
> + }
> +
> regcache_cache_only(arizona->regmap, false);
>
> switch (arizona->type) {
> @@ -508,6 +529,14 @@ static int arizona_runtime_resume(struct device *dev)
> goto err;
> }
> }
> +
> + ret = wm5110_apply_sleep_patch(arizona);
> + if (ret) {
> + dev_err(arizona->dev,
> + "Failed to re-apply sleep patch: %d\n",
> + ret);
> + goto err;
> + }
> break;
> default:
> ret = arizona_wait_for_boot(arizona);
> @@ -545,10 +574,17 @@ err:
> static int arizona_runtime_suspend(struct device *dev)
> {
> struct arizona *arizona = dev_get_drvdata(dev);
> + unsigned int val;
> int ret;
>
> dev_dbg(arizona->dev, "Entering AoD mode\n");
>
> + ret = regmap_read(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, &val);
> + if (ret) {
> + dev_err(dev, "Failed to check jack det status: %d\n", ret);
> + return ret;
> + }
> +
> if (arizona->external_dcvdd) {
> ret = regmap_update_bits(arizona->regmap,
> ARIZONA_ISOLATION_CONTROL,
> @@ -559,33 +595,57 @@ static int arizona_runtime_suspend(struct device *dev)
> ret);
> return ret;
> }
> - } else {
> - switch (arizona->type) {
> - case WM5110:
> - case WM8280:
> - /*
> - * As this is only called for the internal regulator
> - * (where we know voltage ranges available) it is ok
> - * to request an exact range.
> - */
> - ret = regulator_set_voltage(arizona->dcvdd,
> - 1175000, 1175000);
> - if (ret < 0) {
> + }
> +
> + switch (arizona->type) {
> + case WM5110:
> + case WM8280:
> + if (arizona->external_dcvdd)
> + break;
> +
> + /*
> + * As this is only called for the internal regulator
> + * (where we know voltage ranges available) it is ok
> + * to request an exact range.
> + */
> + ret = regulator_set_voltage(arizona->dcvdd, 1175000, 1175000);
> + if (ret < 0) {
> + dev_err(arizona->dev,
> + "Failed to set suspend voltage: %d\n", ret);
> + return ret;
> + }
> + break;
> + case WM5102:
> + if (!(val & ARIZONA_JD1_ENA))
> + ret = regmap_write(arizona->regmap,
> + ARIZONA_WRITE_SEQUENCER_CTRL_3, 0x0);
> + if (ret) {
> dev_err(arizona->dev,
> - "Failed to set suspend voltage: %d\n",
> + "Failed to clear write sequencer: %d\n",
> ret);
> return ret;
> }
> - break;
> - default:
> - break;
> - }
> + break;
> + default:
> + break;
> }
>
> regcache_cache_only(arizona->regmap, true);
> regcache_mark_dirty(arizona->regmap);
> regulator_disable(arizona->dcvdd);
>
> + /* Allow us to completely power down if no jack detection */
> + if (!(val & ARIZONA_JD1_ENA)) {
> + dev_dbg(arizona->dev, "Fully powering off\n");
> +
> + arizona->has_fully_powered_off = true;
> +
> + disable_irq(arizona->irq);
> + arizona_enable_reset(arizona);
> + regulator_bulk_disable(arizona->num_core_supplies,
> + arizona->core_supplies);
> + }
> +
> return 0;
> }
> #endif
> diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h
> index 16a498f..847bdaf 100644
> --- a/include/linux/mfd/arizona/core.h
> +++ b/include/linux/mfd/arizona/core.h
> @@ -117,6 +117,7 @@ struct arizona {
> int num_core_supplies;
> struct regulator_bulk_data core_supplies[ARIZONA_MAX_CORE_SUPPLIES];
> struct regulator *dcvdd;
> + bool has_fully_powered_off;
>
> struct arizona_pdata pdata;
>

--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

2015-05-13 12:22:09

by Lee Jones

[permalink] [raw]
Subject: Re: [RESEND PATCH v3 10/10] mfd: wm5110: Add delay before releasing reset line

On Mon, 11 May 2015, Charles Keepax wrote:

> On the wm5110 it is important the reset line is held for slightly longer
> to ensure the device starts up well. This patch adds a 5mS delay for
> this.
>
> Signed-off-by: Charles Keepax <[email protected]>
> Acked-by: Lee Jones <[email protected]>
> ---
> drivers/mfd/arizona-core.c | 10 ++++++++++
> 1 files changed, 10 insertions(+), 0 deletions(-)

Applied, thanks.

> diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
> index f1ff68a..93e4d94 100644
> --- a/drivers/mfd/arizona-core.c
> +++ b/drivers/mfd/arizona-core.c
> @@ -259,6 +259,16 @@ static inline void arizona_enable_reset(struct arizona *arizona)
> static void arizona_disable_reset(struct arizona *arizona)
> {
> if (arizona->pdata.reset) {
> + switch (arizona->type) {
> + case WM5110:
> + case WM8280:
> + /* Meet requirements for minimum reset duration */
> + msleep(5);
> + break;
> + default:
> + break;
> + }
> +
> gpio_set_value_cansleep(arizona->pdata.reset, 1);
> msleep(1);
> }

--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog