Reboot command

Yes. The correct approach here will be SBI SRST extension which landed in SBI v0.3 specification. Note that Linux changes to use this new extension is currently not merged and most likely will land in v5.15 kernel.

There are also U-Boot patches for UEFI ResetSystem() support on RISC-V which uses SBI SRST extension. I don’t think it landed yet too, but most likely will sooner than later.

IIRC there are no GPIO for reset. In order to reset you need to talk to PMIC via I2C. There is no I2C driver in OpenSBI too. I believe BeagleV also needs to talk to PMIC via I2C within OpenSBI.

Using SBI SRST does nothing as long as OpenSBI has no reboot functionality for this board, so the problem of finding the “correct” sequence to perform the actual reboot remains regardless if we put the reboot code in Linux or OpenSBI. (As you say there is no I2C driver in OpenSBI, which makes the I2C method more work to implement there. I’ll venture that reboot from OpenSBI doesn’t work on BeagleV either…)

Please reference the HiFive Unmatched schematics and pp4 is the GPIO function list. Unfortunately, no GPIO is dedicated for system reset.

1 Like

This sequence may be better than what I originally posted:

i2c dev 0;i2c mw 0x58 0x00 0x00;i2c mw 0x58 0x96 0xdf;i2c mw 0x58 0x4a 0x20;i2c mw 0x58 0x4b 0x80;i2c mw 0x58 0x06 0x4;i2c mw 0x58 0x0e 0x68;

It configures the power sequencer standby mode (PART_DOWN pointer) to be the same as the last step of the SYSTEM power domain sequence, and then enters standby mode. The same 1-second tick alarm trick as before is used to wake the system back up again.

The way the PMIC power sequencer is programmed, this should leave all power supplies enabled (provided I understood the datasheet correctly, and read and decoded the register settings correctly).

The previous command moved the power sequencer all the way back to slot 0, turning off all but the default supplies.

Here is a patch for Linux that basically executes similar I2C writes at the end of the shutdown routine. I guess that’s the best thing you can do at this point: riscv-bringup/kernel-reboot.diff at bbef412a4456acefdf814a9e14a75ce2778992ed · carlosedp/riscv-bringup · GitHub
(Not sure what the initial patch in this thread did since the pastbin expired… don’t pastebin patches please).

1 Like

The patch you link to is exactly what I posted on pastebin. It was put there because it was a PoC not meant as a permanent solution. It should probably be updated to use Anders’ new sequence at least.

I and some other folks tried the original patchset without a success, i.e. it wasn’t consistently rebooting the system and seemed to worked randomly (i.e. it just power downs). I believe similar concerns were raised in the DA forums where this didn’t seem reliable.

Did someone tried testing a new command seq in a reboot cycle, let’s say 100 consecutive reboots? (you could setup systemd unit to reboot every 30 seconds after successful boot, increment a counter, or something similar).

It is possible there is a race against the one-second tick. The documentation isn’t entirely clear if the event register must be cleared before a new event can trigger a wakeup. If that is the problem, it should be possible to instead set the RTC alarm some large enough number of seconds into the future.

In terms of Linux implementation, based on the above patch, this sequence would be this, right?

static int da9063_restart_notify(struct notifier_block *this,
                                unsigned long mode, void *cmd)
{
    struct da9063 *da9063 = container_of(this, struct da9063, restart_handler);
    
    regmap_write(da9063->regmap, DA9063_REG_PAGE_CON, 0x00);
    regmap_write(da9063->regmap, DA9063_REG_SEQ_B, 0xdf);
    regmap_write(da9063->regmap, DA9063_BB_REG_ALARM_MO, 0x20);
    regmap_write(da9063->regmap, DA9063_BB_REG_ALARM_Y, 0x80);
    regmap_write(da9063->regmap, DA9063_REG_EVENT_A, 0x4);
    regmap_write(da9063->regmap, DA9063_REG_CONTROL_A, 0x68);
    
    return NOTIFY_DONE;
}

Edit: updated according to andersm’s comment below

Use the “BB” register definitions to match the datasheet. The “AD” register map is for an old prerelease chip revision.

regmap_write(da9063->regmap, DA9063_BB_REG_ALARM_MO, 0x20);
regmap_write(da9063->regmap, DA9063_BB_REG_ALARM_Y, 0x80);
1 Like

Thanks, I’m going to try this and leave it in a reboot loop overnight.

  • The old sequence powers down the board about half of the time on “reboot”. The other half it does reboot.
  • The new sequence does nothing at all. The system just hangs after reboot: Restarting system. I did enable CONFIG_MFD_DA9063, and have verified that the code gets run by adding a printk.

It’s possible the Linux device drivers configure the PMIC registers in some way that stops it from working. Try the following:

  • Completely remove power from the board and let it sit for a few minutes to make sure the PMIC is initialized to the OTP settings
  • At the U-boot prompt, try the reset sequence a few times
  • Boot to Linux
  • Use the reset button to restart the board, preserving the PMIC state
  • Try the U-boot sequence again

If it stops working only after booting to Linux, either read the driver sources to figure out what they’re doing, or dump the PMIC registers before and after starting the OS, and see which have changed.

Thank you. That helped me figure it out!

It was indeed a matter of the kernel setting a PMIC register that stopped it from working. It was buried pretty deeply: the initialization for the regmap IRQ chip caused all events to be masked. Once found it was straightforward to work around. Adding

regmap_write(da9063->regmap, DA9063_REG_IRQ_MASK_A, 0x00);

makes it work 100% reliably, here :sweat_smile: . Here’s the full patch.

1 Like

I put this newest sequence in a reboot loop over night, and by morning it had rebooted 282 times without incident. So I concur that this is 100% (or at least >99.6% :smile:) reliable.

1 Like

Hi guys,

I ported your sequence to a u-boot driver and noticed that, although it works reliably, turning off the board within 16seconds after this sequence is not possible since the board would restart. Weirdly, I did not have this issue when launching the sequence from the u-boot shell: by adding a few sleeps between the register writes in my u-boot driver, it finally worked. It seems the behavior I’m facing is described in the thread shared before (Power Management ICs (PMICs) | Dialog) and I don’t quite understand why it does not happen all the time.

Anyway, as the “sleeps” solution did not suit me, I digged the datasheet and found a shorter sequence that does not give rise to the issue:

i2c dev 0;
i2c mw 0x58 0x13 0x4; // Set the WAKE_UP bit to CONTROL_F
i2c mw 0x58 0xe 0x68; // Powerdown

It works reliably for me, if you have a chance to test this, any feedback is welcome.

1 Like

That’s neat! I ported that sequence to the kernel hack and it seems to work reliably (only tried about ~10 times for now, manually).

static int da9063_restart_notify(struct notifier_block *this,
                                unsigned long mode, void *cmd)
{
        struct da9063 *da9063 = container_of(this, struct da9063, restart_handler);

        regmap_write(da9063->regmap, DA9063_REG_CONTROL_F, 0x04);
        regmap_write(da9063->regmap, DA9063_REG_CONTROL_A, 0x68);

        return NOTIFY_DONE;
}

I have sent 2 PR to u-boot and linux kernel here:

https://patchwork.ozlabs.org/project/uboot/patch/20210920154809.1695453-1-alexandre.ghiti@canonical.com/

https://patchwork.kernel.org/project/linux-riscv/patch/20210921053356.1705833-1-alexandre.ghiti@canonical.com/

I’ll keep you posted when/if this gets merged.

Thank you guys,

Alex

2 Likes

I hope so!!! I’m slightly worried about prospects for getting the Linux one merged, according to other posts above reset functionality is supposed to go into opensbi, however that has no I2C driver at all at this point:

Seems like quite a lot of work… at least to add proper I2C infrastructure. Another idea would be to add an fdt_reset_sifive_unmatched.c that hardcodes the I2C controller register write sequence, but not sure that’s more acceptable :slight_smile:

Maybe SiFive wants to carry the patches in https://github.com/sifive/meta-sifive for the meantime.

Those patches are only there to finally have a functional reset on those boards. I’m preparing the proper solution with openSBI i2c driver and Linux using SBI SRST extension, I’ll keep this thread updated :slight_smile:

1 Like