Jonas Karlman b032ac74ac rockchip: odroid-go2: Use env from same storage FIT was loaded from
Change to dynamically select what storage media to use for the U-Boot
environment depending on from what storage media the FIT images was
loaded from, fall back to use env from nowhere.

  U-Boot SPL 2025.07 (Jul 13 2025 - 10:07:16 +0000)
  Trying to boot from MMC1
  ...
  Loading Environment from MMC... Reading from MMC(0)...

or

  U-Boot SPL 2025.07 (Jul 13 2025 - 10:07:16 +0000)
  Trying to boot from SPI
  ...
  Loading Environment from SPIFlash...

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Quentin Schulz <quentin.schulz@cherry.de>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>
2025-11-02 12:14:09 -06:00

166 lines
3.4 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2019 Rockchip Electronics Co., Ltd
*/
#include <linux/stddef.h>
#include <adc.h>
#include <asm/io.h>
#include <dm.h>
#include <dm/uclass-internal.h>
#include <env.h>
#include <env_internal.h>
#include <stdlib.h>
DECLARE_GLOBAL_DATA_PTR;
#define DTB_DIR "rockchip/"
struct oga_model {
const u16 adc_value;
const char *board;
const char *board_name;
const char *fdtfile;
};
enum oga_device_id {
OGA = 1,
OGA_V11,
OGS,
};
/*
* All ADC values from schematic of Odroid Go Advance Black Edition.
* Value for OGS is inferred based on schematic and observed values.
*/
static const struct oga_model oga_model_details[] = {
[OGA] = {
856,
"rk3326-odroid-go2",
"ODROID-GO Advance",
DTB_DIR "rk3326-odroid-go2.dtb",
},
[OGA_V11] = {
677,
"rk3326-odroid-go2-v11",
"ODROID-GO Advance Black Edition",
DTB_DIR "rk3326-odroid-go2-v11.dtb",
},
[OGS] = {
85,
"rk3326-odroid-go3",
"ODROID-GO Super",
DTB_DIR "rk3326-odroid-go3.dtb",
},
};
static int oga_read_board_id(void)
{
u32 adc_info;
int i, ret;
ret = adc_channel_single_shot("saradc@ff288000", 0, &adc_info);
if (ret) {
printf("Read SARADC failed with error %d\n", ret);
return ret;
}
/*
* Get the correct device from the table. The ADC value is
* determined by a resistor on ADC channel 0. The manufacturer
* accounted for this with a 5% tolerance, so assume a +- value
* of 50 should be enough.
*/
for (i = 1; i < ARRAY_SIZE(oga_model_details); i++) {
u32 adc_min = oga_model_details[i].adc_value - 50;
u32 adc_max = oga_model_details[i].adc_value + 50;
if (adc_min < adc_info && adc_max > adc_info)
return i;
}
return -ENODEV;
}
/* Detect which Odroid Go Advance device we are using so as to load the
* correct devicetree for Linux. Set an environment variable once
* found. The detection depends on the value of ADC channel 0.
*/
static int oga_detect_device(void)
{
int board_id;
board_id = oga_read_board_id();
if (board_id < 0)
return board_id;
gd->board_type = board_id;
env_set("board", oga_model_details[board_id].board);
env_set("board_name", oga_model_details[board_id].board_name);
env_set("fdtfile", oga_model_details[board_id].fdtfile);
return 0;
}
int rk_board_late_init(void)
{
int ret;
ret = oga_detect_device();
if (ret) {
printf("Unable to detect device type: %d\n", ret);
return ret;
}
return 0;
}
int board_fit_config_name_match(const char *name)
{
int board_id;
if (!gd->board_type) {
board_id = oga_read_board_id();
if (board_id < 0)
return board_id;
gd->board_type = board_id;
}
if (!strcmp(name, oga_model_details[gd->board_type].fdtfile))
return 0;
return -EINVAL;
}
enum env_location env_get_location(enum env_operation op, int prio)
{
const char *boot_device;
struct udevice *dev;
ofnode node;
if (prio)
return ENVL_UNKNOWN;
boot_device = ofnode_read_chosen_string("u-boot,spl-boot-device");
if (!boot_device) {
debug("%s: /chosen/u-boot,spl-boot-device not set\n", __func__);
return ENVL_NOWHERE;
}
debug("%s: booted from %s\n", __func__, boot_device);
node = ofnode_path(boot_device);
if (!ofnode_valid(node))
return ENVL_NOWHERE;
if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH) &&
!uclass_find_device_by_ofnode(UCLASS_SPI_FLASH, node, &dev))
return ENVL_SPI_FLASH;
if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC) &&
!uclass_find_device_by_ofnode(UCLASS_MMC, node, &dev))
return ENVL_MMC;
return ENVL_NOWHERE;
}