So far, we had no explicit mapping table between bootsource_instance and device id numbering in barebox and mostly depended on DT aliases reflecting the numbering of the bootrom. Add a new bootsource_set() that optionally consults a mapping table in the DT to arrive at the correct numbers. Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx> --- .../devicetree/bindings/barebox/aliases.rst | 36 +++++++ common/bootsource.c | 101 +++++++++++++----- include/bootsource.h | 40 ++++++- 3 files changed, 149 insertions(+), 28 deletions(-) create mode 100644 Documentation/devicetree/bindings/barebox/aliases.rst diff --git a/Documentation/devicetree/bindings/barebox/aliases.rst b/Documentation/devicetree/bindings/barebox/aliases.rst new file mode 100644 index 000000000000..527cc85ef696 --- /dev/null +++ b/Documentation/devicetree/bindings/barebox/aliases.rst @@ -0,0 +1,36 @@ +barebox DT aliases +================== + +barebox can use the properties in the ``/aliases`` node to arrive +at deterministic names for devices, e.g.:: + +.. code-block:: none + / { + aliases { + mmc0 = &sdhci; + wdog0 = &iwdg; + }; + }; + +will assign the MMC device created from probing the node at ``&sdhci`` +the name ``/dev/mmc0``. Similarly, the watchdog device created from +probing the node at ``&iwdg`` will be named ``wdog0``. + +By default, barebox will assume the aliases in the DT to align with +the bootsource communicated by the firmware. If this is not the case, +a device tree override is possible via an +``/aliases/barebox,bootsource-${bootsource}${bootsource_instance}`` +property: + +.. code-block:: none + + &{/aliases} { + mmc0 = &sdmmc0; + mmc1 = &sdhci; + barebox,bootsource-mmc0 = &sdhci; + barebox,bootsource-mmc1 = &sdmmc0; + }; + +This will ensure that when booting from MMC, ``/dev/mmc${bootsource_instance}`` +will point at the correct boot device, despite bootrom and board DT alias +order being different. diff --git a/common/bootsource.c b/common/bootsource.c index c37da38f7f99..d74c5e5cbe9f 100644 --- a/common/bootsource.c +++ b/common/bootsource.c @@ -33,6 +33,34 @@ static enum bootsource bootsource = BOOTSOURCE_UNKNOWN; static int bootsource_instance = BOOTSOURCE_INSTANCE_UNKNOWN; const char *bootsource_alias_name = NULL; +const char *bootsource_get_alias_stem(enum bootsource bs) +{ + switch (bs) { + /* + * For I2C and SPI EEPROMs we set the stem to be 'i2c' + * and 'spi' correspondingly. The resulting alias will + * be pointing at the controller said EEPROM is + * attached to. + * + * NOTE: This code assumes single bootable EEPROM per + * controller + */ + case BOOTSOURCE_I2C_EEPROM: + return bootsource_str[BOOTSOURCE_I2C]; + case BOOTSOURCE_SPI_EEPROM: + case BOOTSOURCE_SPI_NOR: + return bootsource_str[BOOTSOURCE_SPI]; + case BOOTSOURCE_SERIAL: /* FALLTHROUGH */ + case BOOTSOURCE_I2C: /* FALLTHROUGH */ + case BOOTSOURCE_MMC: /* FALLTHROUGH */ + case BOOTSOURCE_SPI: /* FALLTHROUGH */ + case BOOTSOURCE_CAN: + return bootsource_str[bootsource]; + default: + return NULL; + } +} + /** * bootsource_get_alias_name() - Get the name of the bootsource alias * @@ -58,33 +86,9 @@ char *bootsource_get_alias_name(void) if (bootsource_alias_name) return strdup(bootsource_alias_name); - switch (bootsource) { - /* - * For I2C and SPI EEPROMs we set the stem to be 'i2c' - * and 'spi' correspondingly. The resulting alias will - * be pointing at the controller said EEPROM is - * attached to. - * - * NOTE: This code assumes single bootable EEPROM per - * controller - */ - case BOOTSOURCE_I2C_EEPROM: - stem = bootsource_str[BOOTSOURCE_I2C]; - break; - case BOOTSOURCE_SPI_EEPROM: - case BOOTSOURCE_SPI_NOR: - stem = bootsource_str[BOOTSOURCE_SPI]; - break; - case BOOTSOURCE_SERIAL: /* FALLTHROUGH */ - case BOOTSOURCE_I2C: /* FALLTHROUGH */ - case BOOTSOURCE_MMC: /* FALLTHROUGH */ - case BOOTSOURCE_SPI: /* FALLTHROUGH */ - case BOOTSOURCE_CAN: - stem = bootsource_str[bootsource]; - break; - default: + stem = bootsource_get_alias_stem(bootsource); + if (!stem) return NULL; - } /* * We expect SoC specific bootsource detection code to properly @@ -123,6 +127,51 @@ void bootsource_set_raw_instance(int instance) pr_setenv("bootsource_instance", "%d", instance); } +int bootsource_of_alias_xlate(enum bootsource bs, int instance) +{ + char alias[sizeof("barebox,bootsource-harddisk4294967295")]; + const char *bootsource_stem; + struct device_node *np; + int alias_id; + + if (!IS_ENABLED(CONFIG_OFDEVICE)) + return BOOTSOURCE_INSTANCE_UNKNOWN; + + if (bs == BOOTSOURCE_UNKNOWN || + instance == BOOTSOURCE_INSTANCE_UNKNOWN) + return BOOTSOURCE_INSTANCE_UNKNOWN; + + bootsource_stem = bootsource_get_alias_stem(bs); + if (!bootsource_stem) + return BOOTSOURCE_INSTANCE_UNKNOWN; + + scnprintf(alias, sizeof(alias), "barebox,bootsource-%s%u", + bootsource_stem, instance); + + np = of_find_node_by_alias(NULL, alias); + if (!np) + return BOOTSOURCE_INSTANCE_UNKNOWN; + + alias_id = of_alias_get_id(np, bootsource_stem); + if (alias_id < 0) + return BOOTSOURCE_INSTANCE_UNKNOWN; + + return alias_id; +} + +int bootsource_set(enum bootsource bs, int instance) +{ + int alias_id; + + alias_id = bootsource_of_alias_xlate(bs, instance); + if (alias_id == BOOTSOURCE_INSTANCE_UNKNOWN) + alias_id = instance; + + bootsource_set_raw(bs, alias_id); + + return alias_id; +} + enum bootsource bootsource_get(void) { return bootsource; diff --git a/include/bootsource.h b/include/bootsource.h index 390d6f5d2b3a..9ca4fcc525b5 100644 --- a/include/bootsource.h +++ b/include/bootsource.h @@ -26,9 +26,45 @@ enum bootsource { enum bootsource bootsource_get(void); int bootsource_get_instance(void); -void bootsource_set_raw(enum bootsource src, int instance); -void bootsource_set_raw_instance(int instance); void bootsource_set_alias_name(const char *name); char *bootsource_get_alias_name(void); +const char *bootsource_get_alias_stem(enum bootsource bs); +int bootsource_of_alias_xlate(enum bootsource bs, int instance); + +/** + * bootsource_set - set bootsource with optional DT mapping table + * @bs: bootrom reported bootsource + * @instance: bootrom reported instance + * + * Returns computed bootsource instace + * + * Normal bootsource_set_raw_instance() expects numbering used by + * bootrom for instance to align with DT aliases, e.g. + * $bootsource = "mmc" && $bootsource_instance = 1 -> /aliases/mmc1 + * bootsource_set() will instead consult + * /aliases/barebox,bootsource-mmc1 which may point at a different + * device than mmc1. In absence of appropriate barebox,bootsource-* + * alias, instance is set without translation. + */ +int bootsource_set(enum bootsource bs, int instance); + +/** + * bootsource_set_raw - set bootsource as-is + * @bs: bootsource to report + * @instance: bootsource instance to report + * + * This sets bootsource and bootsource_instance directly. + * Preferably, use bootsource_set in new code. + */ +void bootsource_set_raw(enum bootsource src, int instance); + +/** + * bootsource_set_raw_instance - set bootsource_instance as-is + * @bs: bootrom reported bootsource + * @instance: bootrom reported instance + * + * This directly sets bootsource_instance without changing bootsource. + */ +void bootsource_set_raw_instance(int instance); #endif /* __BOOTSOURCE_H__ */ -- 2.30.2