diff mbox

[U-Boot,v2,08/12] sunxi: Add axp209 pmic support

Message ID 1401824522-11353-9-git-send-email-hdegoede@redhat.com
State Superseded
Delegated to: Albert ARIBAUD
Headers show

Commit Message

Hans de Goede June 3, 2014, 7:41 p.m. UTC
From: Henrik Nordstrom <henrik@henriknordstrom.net>

Add support for the x-powers axp209 pmic which is found on most A10, A13 and
A20 boards.

And enable AXP209 support for the Cubietruck and Cubieboard boards.

While changing the boards.cfg lines for the Cubietruck, add Ian and me as board
maintainers for the Cubietruck.

Signed-off-by: Henrik Nordstrom <henrik@henriknordstrom.net>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 board/sunxi/board.c            |  22 +++++
 boards.cfg                     |   6 +-
 drivers/power/Makefile         |   1 +
 drivers/power/axp209.c         | 180 +++++++++++++++++++++++++++++++++++++++++
 include/axp209.h               |  15 ++++
 include/configs/sun4i.h        |   1 +
 include/configs/sun5i.h        |   1 +
 include/configs/sun7i.h        |   1 +
 include/configs/sunxi-common.h |   5 ++
 9 files changed, 229 insertions(+), 3 deletions(-)
 create mode 100644 drivers/power/axp209.c
 create mode 100644 include/axp209.h

Comments

Ian Campbell June 5, 2014, 6:40 p.m. UTC | #1
On Tue, 2014-06-03 at 21:41 +0200, Hans de Goede wrote:
> +int axp209_set_ldo3(int mvolt)
> +{
> +	int cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25);
> +
> +	if (mvolt == -1)
> +		cfg = 0x80;	/* determined by LDO3IN pin */

Thus would seem more natural as 
	if (mvolt == -1)
		cfg = 0x80;	/* comment... */
	else
		cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25);

BTW, I've just noticed that cfg is often an int but axp209_write etc all
deal in u8's. Do you not want to be dealing with u8's throughout?

> +void axp209_poweroff(void)
> +{
> +	u8 val;
> +
> +	if (axp209_read(AXP209_SHUTDOWN, &val) != 0)
> +		return;
> +
> +	val |= AXP209_POWEROFF;
> +
> +	if (axp209_write(AXP209_SHUTDOWN, val) != 0)
> +		return;
> +
> +	udelay(10000);		/* wait for power to drain */

Is this essentially a "wait to die" loop? i.e. we expect power to
disappear while in the middle of it. In which case shouldn't it be
infinite? What would happen if we were to return from this function?
Nothing actually calls it AFAICT so maybe you can just punt on the whole
thing and drop the function for now...

Ian.
Hans de Goede June 9, 2014, 8:25 a.m. UTC | #2
Hi,

On 06/05/2014 08:40 PM, Ian Campbell wrote:
> On Tue, 2014-06-03 at 21:41 +0200, Hans de Goede wrote:
>> +int axp209_set_ldo3(int mvolt)
>> +{
>> +	int cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25);
>> +
>> +	if (mvolt == -1)
>> +		cfg = 0x80;	/* determined by LDO3IN pin */
> 
> Thus would seem more natural as 
> 	if (mvolt == -1)
> 		cfg = 0x80;	/* comment... */
> 	else
> 		cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25);
> 

I Agree that that would be better, fixed in my tree:

https://github.com/jwrdegoede/u-boot-sunxi/commits/sunxi-upstreaming

Note I often rebase + force push this branch.

> BTW, I've just noticed that cfg is often an int but axp209_write etc all
> deal in u8's. Do you not want to be dealing with u8's throughout?

Agreed that this should be u8 everywhere, fixed this for both the axp209
and axp152 code.

Note I won't be re-posting these until the i2c controller conversion to
the CONFIG_SYS_I2C framework is sorted out.

>> +void axp209_poweroff(void)
>> +{
>> +	u8 val;
>> +
>> +	if (axp209_read(AXP209_SHUTDOWN, &val) != 0)
>> +		return;
>> +
>> +	val |= AXP209_POWEROFF;
>> +
>> +	if (axp209_write(AXP209_SHUTDOWN, val) != 0)
>> +		return;
>> +
>> +	udelay(10000);		/* wait for power to drain */
> 
> Is this essentially a "wait to die" loop? i.e. we expect power to
> disappear while in the middle of it. In which case shouldn't it be
> infinite? What would happen if we were to return from this function?
> Nothing actually calls it AFAICT so maybe you can just punt on the whole
> thing and drop the function for now...

I agree that just dropping this function for now is best, done.

Regards,

Hans
Ian Campbell June 9, 2014, 8:50 a.m. UTC | #3
On Mon, 2014-06-09 at 10:25 +0200, Hans de Goede wrote:
> https://github.com/jwrdegoede/u-boot-sunxi/commits/sunxi-upstreaming
> 
> Note I often rebase + force push this branch.

I noticed ;-)

> Note I won't be re-posting these until the i2c controller conversion to
> the CONFIG_SYS_I2C framework is sorted out.

No problem. Is that a big rework then?

How would you feel about reordering things a bit to push the i2c/power
and sun[45]i stuff to the end, most of the rest looks more or less
trivial/uncontroversial to me and could potentially be applied sooner
rather than later (ulterior motive: this would unblock my AHCI
patches ;-))

If you are ok with that in principal then I'm more than happy to do the
leg work of git rebase -i.

Ian.
Hans de Goede June 9, 2014, 8:59 a.m. UTC | #4
Hi,

On 06/09/2014 10:50 AM, Ian Campbell wrote:
> On Mon, 2014-06-09 at 10:25 +0200, Hans de Goede wrote:
>> https://github.com/jwrdegoede/u-boot-sunxi/commits/sunxi-upstreaming
>>
>> Note I often rebase + force push this branch.
> 
> I noticed ;-)
> 
>> Note I won't be re-posting these until the i2c controller conversion to
>> the CONFIG_SYS_I2C framework is sorted out.
> 
> No problem. Is that a big rework then?

Not all that big, I'm working on it now, I hope to have it finished by the
end of today.

> How would you feel about reordering things a bit to push the i2c/power
> and sun[45]i stuff to the end, most of the rest looks more or less
> trivial/uncontroversial to me and could potentially be applied sooner
> rather than later (ulterior motive: this would unblock my AHCI
> patches ;-))

I agree, actually if you look in where your u-boot list mails go you will
see a pull-req to Albert there for the entire set I've been working on minus
the i2c + axp patches :)

Regards,

Hans
Albert ARIBAUD June 9, 2014, 9:06 a.m. UTC | #5
Hi Hans,

On Mon, 09 Jun 2014 10:59:19 +0200, Hans de Goede <hdegoede@redhat.com>
wrote:

> Hi,
> 
> On 06/09/2014 10:50 AM, Ian Campbell wrote:
> > On Mon, 2014-06-09 at 10:25 +0200, Hans de Goede wrote:
> >> https://github.com/jwrdegoede/u-boot-sunxi/commits/sunxi-upstreaming
> >>
> >> Note I often rebase + force push this branch.
> > 
> > I noticed ;-)
> > 
> >> Note I won't be re-posting these until the i2c controller conversion to
> >> the CONFIG_SYS_I2C framework is sorted out.
> > 
> > No problem. Is that a big rework then?
> 
> Not all that big, I'm working on it now, I hope to have it finished by the
> end of today.
> 
> > How would you feel about reordering things a bit to push the i2c/power
> > and sun[45]i stuff to the end, most of the rest looks more or less
> > trivial/uncontroversial to me and could potentially be applied sooner
> > rather than later (ulterior motive: this would unblock my AHCI
> > patches ;-))
> 
> I agree, actually if you look in where your u-boot list mails go you will
> see a pull-req to Albert there for the entire set I've been working on minus
> the i2c + axp patches :)

Don't bother with the pull request, as I only apply PRs from git.denx.de
U-Boot repositories. I will happily apply your series from Patchwork.
Just make sure it is properly assigned to me.

> Regards,
> 
> Hans

Amicalement,
Hans de Goede June 9, 2014, 9:08 a.m. UTC | #6
Hi,

On 06/09/2014 11:06 AM, Albert ARIBAUD wrote:
> Hi Hans,
> 
> On Mon, 09 Jun 2014 10:59:19 +0200, Hans de Goede <hdegoede@redhat.com>
> wrote:
> 
>> Hi,
>>
>> On 06/09/2014 10:50 AM, Ian Campbell wrote:
>>> On Mon, 2014-06-09 at 10:25 +0200, Hans de Goede wrote:
>>>> https://github.com/jwrdegoede/u-boot-sunxi/commits/sunxi-upstreaming
>>>>
>>>> Note I often rebase + force push this branch.
>>>
>>> I noticed ;-)
>>>
>>>> Note I won't be re-posting these until the i2c controller conversion to
>>>> the CONFIG_SYS_I2C framework is sorted out.
>>>
>>> No problem. Is that a big rework then?
>>
>> Not all that big, I'm working on it now, I hope to have it finished by the
>> end of today.
>>
>>> How would you feel about reordering things a bit to push the i2c/power
>>> and sun[45]i stuff to the end, most of the rest looks more or less
>>> trivial/uncontroversial to me and could potentially be applied sooner
>>> rather than later (ulterior motive: this would unblock my AHCI
>>> patches ;-))
>>
>> I agree, actually if you look in where your u-boot list mails go you will
>> see a pull-req to Albert there for the entire set I've been working on minus
>> the i2c + axp patches :)
> 
> Don't bother with the pull request, as I only apply PRs from git.denx.de
> U-Boot repositories. I will happily apply your series from Patchwork.
> Just make sure it is properly assigned to me.

Ok, since I dropped some patches which need more work from the series, some
of the latter ones needed some manual rebasing to apply. So I will send
a new version of the set. How do I ensure that those patches end up being
assigned to you ? So far I've been sending my patches with you as the "To"
of the emails and the list in the Cc, is that sufficient ?

Regards,

Hans
Ian Campbell June 9, 2014, 10:09 a.m. UTC | #7
On Mon, 2014-06-09 at 10:59 +0200, Hans de Goede wrote:
> > How would you feel about reordering things a bit to push the i2c/power
> > and sun[45]i stuff to the end, most of the rest looks more or less
> > trivial/uncontroversial to me and could potentially be applied sooner
> > rather than later (ulterior motive: this would unblock my AHCI
> > patches ;-))
> 
> I agree, actually if you look in where your u-boot list mails go you will
> see a pull-req to Albert there for the entire set I've been working on minus
> the i2c + axp patches :)

Awesome, thanks!

Ian.
diff mbox

Patch

diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 543b809..8375711 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -12,6 +12,9 @@ 
  */
 
 #include <common.h>
+#ifdef CONFIG_AXP209_POWER
+#include <axp209.h>
+#endif
 #include <asm/arch/clock.h>
 #include <asm/arch/dram.h>
 #include <asm/arch/gpio.h>
@@ -116,12 +119,31 @@  void i2c_init_board(void)
 #ifdef CONFIG_SPL_BUILD
 void sunxi_board_init(void)
 {
+	int power_failed = 0;
 	unsigned long ramsize;
 
+#ifdef CONFIG_AXP209_POWER
+	power_failed |= axp209_init();
+	power_failed |= axp209_set_dcdc2(1400);
+	power_failed |= axp209_set_dcdc3(1250);
+	power_failed |= axp209_set_ldo2(3000);
+	power_failed |= axp209_set_ldo3(2800);
+	power_failed |= axp209_set_ldo4(2800);
+#endif
+
 	printf("DRAM:");
 	ramsize = sunxi_dram_init();
 	printf(" %lu MiB\n", ramsize >> 20);
 	if (!ramsize)
 		hang();
+
+	/*
+	 * Only clock up the CPU to full speed if we are reasonably
+	 * assured it's being powered with suitable core voltage
+	 */
+	if (!power_failed)
+		clock_set_pll1(CONFIG_CLK_FULL_SPEED);
+	else
+		printf("Failed to set core voltage! Can't set CPU frequency\n");
 }
 #endif
diff --git a/boards.cfg b/boards.cfg
index f2da564..151c443 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -382,9 +382,9 @@  Active  arm         armv7          s5pc1xx     samsung         goni
 Active  arm         armv7          s5pc1xx     samsung         smdkc100            smdkc100                              -                                                                                                                                 Minkyu Kang <mk7.kang@samsung.com>
 Active  arm         armv7          socfpga     altera          socfpga             socfpga_cyclone5                      -                                                                                                                                 -
 Active  arm         armv7          sunxi       -               sunxi               A13-OLinuXinoM                        sun5i:A13_OLINUXINOM,SPL,CONS_INDEX=2                                                                                             Hans de Goede <hdegoede@redhat.com>
-Active  arm         armv7          sunxi       -               sunxi               Cubieboard                            sun4i:CUBIEBOARD,SPL                                                                                                              Hans de Goede <hdegoede@redhat.com>
-Active  arm         armv7          sunxi       -               sunxi               Cubietruck                            sun7i:CUBIETRUCK,SPL,SUNXI_GMAC,RGMII                                                                                             -
-Active  arm         armv7          sunxi       -               sunxi               Cubietruck_FEL                        sun7i:CUBIETRUCK,SPL_FEL,SUNXI_GMAC,RGMII                                                                                         -
+Active  arm         armv7          sunxi       -               sunxi               Cubieboard                            sun4i:CUBIEBOARD,SPL,AXP209_POWER                                                                                                 Hans de Goede <hdegoede@redhat.com>
+Active  arm         armv7          sunxi       -               sunxi               Cubietruck                            sun7i:CUBIETRUCK,SPL,AXP209_POWER,SUNXI_GMAC,RGMII                                                                                Ian Campbell <ijc@hellion.org.uk>:Hans de Goede <hdegoede@redhat.com>
+Active  arm         armv7          sunxi       -               sunxi               Cubietruck_FEL                        sun7i:CUBIETRUCK,SPL_FEL,AXP209_POWER,SUNXI_GMAC,RGMII                                                                            Ian Campbell <ijc@hellion.org.uk>:Hans de Goede <hdegoede@redhat.com>
 Active  arm         armv7          sunxi       -               sunxi               r7-tv-dongle                          sun5i:R7DONGLE,SPL                                                                                                                Hans de Goede <hdegoede@redhat.com>
 Active  arm         armv7          u8500       st-ericsson     snowball            snowball                              -                                                                                                                                 Mathieu Poirier <mathieu.poirier@linaro.org>
 Active  arm         armv7          u8500       st-ericsson     u8500               u8500_href                            -                                                                                                                                 -
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 53ff97d..063ac8f 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -5,6 +5,7 @@ 
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+obj-$(CONFIG_AXP209_POWER)	+= axp209.o
 obj-$(CONFIG_EXYNOS_TMU)	+= exynos-tmu.o
 obj-$(CONFIG_FTPMU010_POWER)	+= ftpmu010.o
 obj-$(CONFIG_TPS6586X_POWER)	+= tps6586x.o
diff --git a/drivers/power/axp209.c b/drivers/power/axp209.c
new file mode 100644
index 0000000..fc1befa
--- /dev/null
+++ b/drivers/power/axp209.c
@@ -0,0 +1,180 @@ 
+/*
+ * (C) Copyright 2012
+ * Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <axp209.h>
+
+enum axp209_reg {
+	AXP209_POWER_STATUS = 0x00,
+	AXP209_CHIP_VERSION = 0x03,
+	AXP209_DCDC2_VOLTAGE = 0x23,
+	AXP209_DCDC3_VOLTAGE = 0x27,
+	AXP209_LDO24_VOLTAGE = 0x28,
+	AXP209_LDO3_VOLTAGE = 0x29,
+	AXP209_IRQ_STATUS5 = 0x4c,
+	AXP209_SHUTDOWN = 0x32,
+};
+
+#define AXP209_POWER_STATUS_ON_BY_DC	(1 << 0)
+
+#define AXP209_IRQ5_PEK_UP		(1 << 6)
+#define AXP209_IRQ5_PEK_DOWN		(1 << 5)
+
+#define AXP209_POWEROFF			(1 << 7)
+
+static int axp209_write(enum axp209_reg reg, u8 val)
+{
+	return i2c_write(0x34, reg, 1, &val, 1);
+}
+
+static int axp209_read(enum axp209_reg reg, u8 *val)
+{
+	return i2c_read(0x34, reg, 1, val, 1);
+}
+
+static int axp209_mvolt_to_cfg(int mvolt, int min, int max, int div)
+{
+	if (mvolt < min)
+		mvolt = min;
+	else if (mvolt > max)
+		mvolt = max;
+
+	return (mvolt - min) / div;
+}
+
+int axp209_set_dcdc2(int mvolt)
+{
+	int cfg, rc;
+	u8 current;
+
+	cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25);
+
+	/* Do we really need to be this gentle? It has built-in voltage slope */
+	while ((rc = axp209_read(AXP209_DCDC2_VOLTAGE, &current)) == 0 &&
+	       current != cfg) {
+		if (current < cfg)
+			current++;
+		else
+			current--;
+
+		rc = axp209_write(AXP209_DCDC2_VOLTAGE, current);
+		if (rc)
+			break;
+	}
+
+	return rc;
+}
+
+int axp209_set_dcdc3(int mvolt)
+{
+	int cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25);
+
+	return axp209_write(AXP209_DCDC3_VOLTAGE, cfg);
+}
+
+int axp209_set_ldo2(int mvolt)
+{
+	int rc, cfg;
+	u8 reg;
+
+	cfg = axp209_mvolt_to_cfg(mvolt, 1800, 3300, 100);
+
+	rc = axp209_read(AXP209_LDO24_VOLTAGE, &reg);
+	if (rc)
+		return rc;
+
+	/* LDO2 configuration is in upper 4 bits */
+	reg = (reg & 0x0f) | (cfg << 4);
+	return axp209_write(AXP209_LDO24_VOLTAGE, reg);
+}
+
+int axp209_set_ldo3(int mvolt)
+{
+	int cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25);
+
+	if (mvolt == -1)
+		cfg = 0x80;	/* determined by LDO3IN pin */
+
+	return axp209_write(AXP209_LDO3_VOLTAGE, cfg);
+}
+
+int axp209_set_ldo4(int mvolt)
+{
+	int cfg, rc;
+	static const int vindex[] = {
+		1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2500,
+		2700, 2800, 3000, 3100, 3200, 3300
+	};
+	u8 reg;
+
+	/* Translate mvolt to register cfg value, requested <= selected */
+	for (cfg = 15; vindex[cfg] > mvolt && cfg > 0; cfg--);
+
+	rc = axp209_read(AXP209_LDO24_VOLTAGE, &reg);
+	if (rc)
+		return rc;
+
+	/* LDO4 configuration is in lower 4 bits */
+	reg = (reg & 0xf0) | (cfg << 0);
+	return axp209_write(AXP209_LDO24_VOLTAGE, reg);
+}
+
+void axp209_poweroff(void)
+{
+	u8 val;
+
+	if (axp209_read(AXP209_SHUTDOWN, &val) != 0)
+		return;
+
+	val |= AXP209_POWEROFF;
+
+	if (axp209_write(AXP209_SHUTDOWN, val) != 0)
+		return;
+
+	udelay(10000);		/* wait for power to drain */
+}
+
+int axp209_init(void)
+{
+	u8 ver;
+	int rc;
+
+	rc = axp209_read(AXP209_CHIP_VERSION, &ver);
+	if (rc)
+		return rc;
+
+	/* Low 4 bits is chip version */
+	ver &= 0x0f;
+
+	if (ver != 0x1)
+		return -1;
+
+	return 0;
+}
+
+int axp209_poweron_by_dc(void)
+{
+	u8 v;
+
+	if (axp209_read(AXP209_POWER_STATUS, &v))
+		return 0;
+
+	return (v & AXP209_POWER_STATUS_ON_BY_DC);
+}
+
+int axp209_power_button(void)
+{
+	u8 v;
+
+	if (axp209_read(AXP209_IRQ_STATUS5, &v))
+		return 0;
+
+	axp209_write(AXP209_IRQ_STATUS5, AXP209_IRQ5_PEK_DOWN);
+
+	return v & AXP209_IRQ5_PEK_DOWN;
+}
diff --git a/include/axp209.h b/include/axp209.h
new file mode 100644
index 0000000..9edfa3f
--- /dev/null
+++ b/include/axp209.h
@@ -0,0 +1,15 @@ 
+/*
+ * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+extern int axp209_set_dcdc2(int mvolt);
+extern int axp209_set_dcdc3(int mvolt);
+extern int axp209_set_ldo2(int mvolt);
+extern int axp209_set_ldo3(int mvolt);
+extern int axp209_set_ldo4(int mvolt);
+extern void axp209_poweroff(void);
+extern int axp209_init(void);
+extern int axp209_poweron_by_dc(void);
+extern int axp209_power_button(void);
diff --git a/include/configs/sun4i.h b/include/configs/sun4i.h
index 6560b65..037f995 100644
--- a/include/configs/sun4i.h
+++ b/include/configs/sun4i.h
@@ -12,6 +12,7 @@ 
  * A10 specific configuration
  */
 #define CONFIG_SUN4I		/* sun4i SoC generation */
+#define CONFIG_CLK_FULL_SPEED		1008000000
 
 #define CONFIG_SYS_PROMPT		"sun4i# "
 
diff --git a/include/configs/sun5i.h b/include/configs/sun5i.h
index 43f0d67..c6138b7 100644
--- a/include/configs/sun5i.h
+++ b/include/configs/sun5i.h
@@ -12,6 +12,7 @@ 
  * High Level Configuration Options
  */
 #define CONFIG_SUN5I		/* sun5i SoC generation */
+#define CONFIG_CLK_FULL_SPEED		1008000000
 
 #define CONFIG_SYS_PROMPT		"sun5i# "
 
diff --git a/include/configs/sun7i.h b/include/configs/sun7i.h
index 9b693f7..d9be104 100644
--- a/include/configs/sun7i.h
+++ b/include/configs/sun7i.h
@@ -13,6 +13,7 @@ 
  * A20 specific configuration
  */
 #define CONFIG_SUN7I		/* sun7i SoC generation */
+#define CONFIG_CLK_FULL_SPEED		912000000
 
 #define CONFIG_SYS_PROMPT		"sun7i# "
 
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 2db083c..b76227e 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -170,6 +170,11 @@ 
 #define CONFIG_SYS_I2C_SLAVE		0x7f
 #define CONFIG_CMD_I2C
 
+/* PMU */
+#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || defined CONFIG_AXP221_POWER
+#define CONFIG_SPL_POWER_SUPPORT
+#endif
+
 #ifndef CONFIG_CONS_INDEX
 #define CONFIG_CONS_INDEX              1       /* UART0 */
 #endif