defer qspi bringup to when we really need it

This commit is contained in:
liquidraver
2026-08-11 13:57:49 +02:00
parent 557aef1883
commit daeff6d5e6
3 changed files with 52 additions and 1 deletions
@@ -110,6 +110,25 @@ bool ZephyrDataStore::mount()
* on /ext. Without this the store silently falls back to internal /lfs,
* and the next boot that does mount /ext runs a needless contact
* migration — the "Migrating contacts to external storage" churn. */
#if DT_NODE_HAS_PROP(DT_COMPAT_GET_ANY_STATUS_OKAY(nordic_qspi_nor), zephyr_deferred_init)
/* The flash is deferred-init: probing it at boot raced its own
* power rail and the JEDEC read came back 00 00 00, so the
* driver failed and /ext could never mount. Initialising it here
* instead means the part has had until first use to wake up —
* over a second — rather than us guessing a settling delay. */
{
const struct device *qspi_dev =
DEVICE_DT_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(nordic_qspi_nor));
if (!device_is_ready(qspi_dev)) {
int drc = device_init(qspi_dev);
LOG_INF("QSPI flash deferred init: rc=%d ready=%d",
drc, (int)device_is_ready(qspi_dev));
}
}
#endif
FS_FSTAB_DECLARE_ENTRY(DT_NODELABEL(qspi_lfs));
int rc = fs_mount(&FS_FSTAB_ENTRY(DT_NODELABEL(qspi_lfs)));
if (is_mounted(extMountPoint())) {
@@ -113,7 +113,13 @@
regulator-name = "flash-power";
enable-gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
regulator-boot-on;
startup-delay-us = <10000>;
/* Documents the part's requirement, but do not rely on it:
* regulator_fixed_init() drives the enable GPIO active and then
* passes is_enabled=true into regulator_common_init(), which
* takes the refcount-only branch regulator_delay() sits on the
* other one and never runs. The flash gets its settling time
* from deferred init instead (see the qspi_flash node). */
startup-delay-us = <100000>;
};
/* P1.06 — gates the battery ADC divider, enabled on demand */
@@ -328,6 +334,14 @@
qspi_flash: qspi_flash@0 {
compatible = "nordic,qspi-nor";
reg = <0>;
/* Do not probe this at boot. The rail is switched on by
* flash-power a few init priorities earlier, and the part is not
* driving the bus yet when the driver's JEDEC read goes out
* it answers 00 00 00 at 0.4 s and a correct c8 40 17 by 5.9 s
* on the very same boot. A fixed settling delay would only be a
* guess at where in between it wakes; instead the driver is
* initialised on demand, when the store first mounts /ext. */
zephyr,deferred-init;
writeoc = "pp4io";
readoc = "read4io";
sck-frequency = <16000000>;
+18
View File
@@ -24,6 +24,7 @@
#include <zephyr/init.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/regulator.h>
#include <zephyr/logging/log.h>
#if IS_ENABLED(CONFIG_ZEPHCORE_QSPI_RDID_PROBE) && \
@@ -81,6 +82,23 @@ static int qspi_rdid_probe(void)
flash->name, (int)flash->state->init_res,
P_SCK, P_CSN, P_IO0, P_IO1);
#if DT_NODE_EXISTS(DT_NODELABEL(flash_power))
/* The driver reading 00 00 00 says the part was not driving the bus,
* which is either "the rail never came up" or "it came up too late".
* Those need opposite fixes, and the supply state here separates them:
* enabled now but the JEDEC read failed means the rail is fine and the
* startup delay is short. */
{
const struct device *supply =
DEVICE_DT_GET(DT_NODELABEL(flash_power));
LOG_INF("flash supply '%s': ready=%d enabled=%d",
supply->name, (int)device_is_ready(supply),
device_is_ready(supply)
? (int)regulator_is_enabled(supply) : -1);
}
#endif
gpio_pin_configure(p0, P_CSN, GPIO_OUTPUT_HIGH);
gpio_pin_configure(p0, P_SCK, GPIO_OUTPUT_LOW);
gpio_pin_configure(p0, P_IO0, GPIO_OUTPUT_LOW);