Automatic power-on when applying power

Hi,

Seems like there’s no documented way of having the system turn on automatically when power is applied. This is quite limiting – in particular since rebooting is broken out of the box.

Is there any (not yet) documented simple rework to enable this, per chance? If not, having a jumper to enable/disable said behavior on future generations of the platform would be highly appreciated.

2 Likes

Correct, there is no way to set auto-boot. You would need to use PSU with remote control and some micro-controller to short pins on the front panel header.

1 Like

This is a very good question. Due to the noise of the fan I’d like to put my Unmatched into a closet. In the past I’ve been using a remote-controller power socket to switch such devices on (works fine with the Unleashed).

The power supply of the Unmatched is controlled by a DA9063 (U36). This is a complex power management IC that can do a lot of tricks and is programmable via I2C. I have not much experience with such devices but from the schematic and a brief look into the datasheet of the DA9063 I think moving R223 to R357 to connect the DA9063’s SYS_EN pin to its own 2.5V regulator output instead of GND could enable the desired behavior.

Since this pin can be configured in different ways there is no way to determine from the documentation alone if that’s correct. Also, this would obviously be a reason to reject warranty claims in any case but it would be nice if somebody from SiFive would chime in here to give us some info one that SYS_EN idea but also possible (future) software fixes in this regard.

I played a bit around and making some progress. The data sheet is really unclear regarding persistence of register contents… maybe all of them are persistent/in flash and only some are overwritten at reset by OTP memory. In any case, I was able to write the AUTO_BOOT bit of CONTROL_C and that sticks even after removing power. It also changes the behavior but not completely. When power is supplied, the PSU turns on automatically now but the CPU is not started.

1 Like

Did you remove power completely, i.e. flip the switch on the PSU, or remove the power cord? My understanding is that in case of total power loss, the configuration is read from OTP.

Yes, you seem to be right. Apparently some capacitors supply enough energy for some time (at least some seconds). Later I discovered that after that, the registers reset to the previous values (and supplying the PSU with power again does not start it anymore). I have not installed the coin battery. I wonder if that would change anything in this regard. Edit: It does not (tested with 2.6V).

It all does not matter if I cannot get the PMIC to deassert the PORESET of the SoC automatically though. I have tried setting RESET_EVENT to 11 (edit: and also RESET_TIMER to maximum) but that didn’t change anything so I am slowly running out of ideas.

If anybody wants to play around with the PMIC in u-boot, here is what I currently got:

diff --git a/board/sifive/unmatched/unmatched.c b/board/sifive/unmatched/unmatched.c
index da23a6ce24..c2c834fbb8 100644
--- a/board/sifive/unmatched/unmatched.c
+++ b/board/sifive/unmatched/unmatched.c
@@ -8,6 +8,8 @@
 
 #include <common.h>
 #include <dm.h>
+#include <power/pmic.h>
+#include <power/da9063_pmic.h>
 #include <asm/arch/cache.h>
 #include <asm/sections.h>
 
@@ -21,6 +23,67 @@ void *board_fdt_blob_setup(void)
 	}
 }
 
+static int read_reg(struct udevice * const dev, const char * const name, uint8_t reg) {
+	int ret = pmic_reg_read(dev, reg);
+	if (ret < 0) {
+		printf("%s: error reading %s: %d\n", __func__, name, ret);
+		return ret;
+	}
+	printf("%s: %s[0x%02X]=0x%02X\n", __func__, name, reg, ret);
+	return ret;
+}
+
+int board_late_init(void)
+{
+	struct udevice *dev;
+	int off;
+	int ret;
+
+	off = fdt_path_offset(gd->fdt_blob, "/soc/i2c/pmic");
+	if (off < 0) {
+		printf("%s: No pmic path offset: %d\n", __func__, off);
+		return off;
+	}
+
+	ret = uclass_get_device_by_of_offset(UCLASS_PMIC, off, &dev);
+	if (ret) {
+		printf("%s: Could not find PMIC, %d\n", __func__, ret);
+		return ret;
+	}
+
+	ret = pmic_reg_write(dev, DA9063_REG_PAGE_CON, 0x00); // Select page 0
+	if (ret < 0) {
+		printf("%s: error selecting page 0: %d\n", __func__, ret);
+		return ret;
+	}
+
+	(void)read_reg(dev, "CONTROL_A", DA9063_REG_CONTROL_A);
+	(void)read_reg(dev, "CONTROL_B", DA9063_REG_CONTROL_B);
+	int ctrl_c = read_reg(dev, "CONTROL_C", DA9063_REG_CONTROL_C);
+	(void)read_reg(dev, "CONTROL_D", DA9063_REG_CONTROL_D);
+	(void)read_reg(dev, "CONTROL_E", DA9063_REG_CONTROL_E);
+	(void)read_reg(dev, "CONTROL_F", DA9063_REG_CONTROL_F);
+	int rst = read_reg(dev, "RESET", DA9063_REG_RESET);
+
+	ctrl_c |= 0x08; // Set AUTO_BOOT
+	printf("%s: writing 0x%02X to CONTROL_C\n", __func__, ctrl_c);
+	ret = pmic_reg_write(dev, DA9063_REG_CONTROL_C, ctrl_c);
+	if (ret < 0) {
+		printf("%s: error writing CONTROL_C: %d\n", __func__, ret);
+		return ret;
+	}
+
+	rst =0xFF; // set reset event and duration |= 0xC0; // Set RESET_EVENT in RESET
+	printf("%s: writing 0x%02X to RESET\n", __func__, rst);
+	ret = pmic_reg_write(dev, DA9063_REG_RESET, rst);
+	if (ret < 0) {
+		printf("%s: error writing RESET: %d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 int board_init(void)
 {
 	int ret;
diff --git a/configs/sifive_unmatched_defconfig b/configs/sifive_unmatched_defconfig
index 548fcec17a..31911c37f0 100644
--- a/configs/sifive_unmatched_defconfig
+++ b/configs/sifive_unmatched_defconfig
@@ -23,6 +23,12 @@ CONFIG_DEFAULT_FDT_FILE="sifive/hifive-unmatched-a00.dtb"
 CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DISPLAY_BOARDINFO=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_CHILDREN=y
+CONFIG_SPL_PMIC_CHILDREN=y
+CONFIG_DM_PMIC_DA9063=y
+CONFIG_SPL_DM_PMIC_DA9063=y
+CONFIG_BOARD_LATE_INIT=y
 CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_DM_SPI_FLASH=y

While not an expert here on the PMIC (which is complicated and has multiple states). On the cold reset (power loss) the initial configuration is loaded from OTP. Setting things like AUTO_BOOT after the system boots doesn’t have much effect (or shouldn’t to my understanding) as PMIC will reload it’s initial configuration from OTP to begin with.

WDT also doesn’t work because AUTO_BOOT is set to OFF in OTP. Thus the system will power down and will be waiting for a wake up signal. The only wya to wake up the system is RTC tick wake up event IIRC.