summaryrefslogtreecommitdiff
path: root/board/amlogic/odroid-n2/odroid-n2.c
blob: 88a60f34fe8c70a8b78c1e54eaa92a66a0dcc8df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2020 BayLibre, SAS
 * Author: Neil Armstrong <narmstrong@baylibre.com>
 */

#include <common.h>
#include <dm.h>
#include <adc.h>
#include <env.h>
#include <init.h>
#include <net.h>
#include <asm/io.h>
#include <asm/arch/boot.h>
#include <asm/arch/sm.h>
#include <asm/arch/eth.h>
#include <asm/arch/boot.h>

#define EFUSE_MAC_OFFSET	20
#define EFUSE_MAC_SIZE		12
#define MAC_ADDR_LEN		6

#define ODROID_HW_VS_ADC_CHANNEL	1

#define MESON_SOC_ID_G12B	0x29
#define MESON_SOC_ID_SM1	0x2b

int mmc_get_env_dev(void)
{
	if (meson_get_boot_device() == BOOT_DEVICE_EMMC)
		return 1;
	return 0;
}

/* Variant detection is based on the ADC RAW values for the channel #1 */
static struct meson_odroid_boards {
	unsigned int soc_id;
	unsigned int adc_min;
	unsigned int adc_max;
	char *variant;
} boards[] = {
	/* OdroidN2 rev 2018,7,23 */
	{ MESON_SOC_ID_G12B, 80 * 4,  90 * 4, "n2" },
	/* OdroidN2 rev 2018,12,6 */
	{ MESON_SOC_ID_G12B, 160 * 4, 170 * 4, "n2" },
	/* OdroidN2 rev 2019,1,17 */
	{ MESON_SOC_ID_G12B, 245 * 4, 255 * 4, "n2" },
	/* OdroidN2 rev 2019,2,7 */
	{ MESON_SOC_ID_G12B, 330 * 4, 350 * 4, "n2" },
	/* OdroidN2plus rev 2019,11,20 */
	{ MESON_SOC_ID_G12B, 410 * 4, 430 * 4, "n2_plus" },
	/* OdroidC4 rev 2020,01,29 */
	{ MESON_SOC_ID_SM1,   80 * 4, 100 * 4, "c4" },
	/* OdroidHC4 rev 2019,12,10 */
	{ MESON_SOC_ID_SM1,  300 * 4, 320 * 4, "hc4" },
	/* OdroidC4 rev 2019,11,29 */
	{ MESON_SOC_ID_SM1,  335 * 4, 345 * 4, "c4" },
	/* OdroidHC4 rev 2020,8,7 */
	{ MESON_SOC_ID_SM1,  590 * 4, 610 * 4, "hc4" },
};

static void odroid_set_fdtfile(char *soc, char *variant)
{
	char s[128];

	snprintf(s, sizeof(s), "amlogic/meson-%s-odroid-%s.dtb", soc, variant);
	env_set("fdtfile", s);
}

static int odroid_detect_variant(void)
{
	char *variant = "", *soc = "";
	unsigned int adcval = 0;
	int ret, i, soc_id = 0;

	if (of_machine_is_compatible("amlogic,sm1")) {
		soc_id = MESON_SOC_ID_SM1;
		soc = "sm1";
	} else if (of_machine_is_compatible("amlogic,g12b")) {
		soc_id = MESON_SOC_ID_G12B;
		soc = "g12b";
	} else {
		return -1;
	}

	ret = adc_channel_single_shot("adc@9000", ODROID_HW_VS_ADC_CHANNEL,
				      &adcval);
	if (ret)
		return ret;

	for (i = 0 ; i < ARRAY_SIZE(boards) ; ++i) {
		if (soc_id == boards[i].soc_id &&
		    adcval >= boards[i].adc_min &&
		    adcval < boards[i].adc_max) {
			variant = boards[i].variant;
			break;
		}
	}

	printf("Board variant: %s\n", variant);
	env_set("variant", variant);

	odroid_set_fdtfile(soc, variant);

	return 0;
}

int misc_init_r(void)
{
	u8 mac_addr[MAC_ADDR_LEN];
	char efuse_mac_addr[EFUSE_MAC_SIZE], tmp[3];
	ssize_t len;

	if (IS_ENABLED(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG) &&
	    meson_get_soc_rev(tmp, sizeof(tmp)) > 0)
		env_set("soc_rev", tmp);

	if (!eth_env_get_enetaddr("ethaddr", mac_addr)) {
		len = meson_sm_read_efuse(EFUSE_MAC_OFFSET,
					  efuse_mac_addr, EFUSE_MAC_SIZE);
		if (len != EFUSE_MAC_SIZE)
			return 0;

		/* MAC is stored in ASCII format, 1bytes = 2characters */
		for (int i = 0; i < 6; i++) {
			tmp[0] = efuse_mac_addr[i * 2];
			tmp[1] = efuse_mac_addr[i * 2 + 1];
			tmp[2] = '\0';
			mac_addr[i] = simple_strtoul(tmp, NULL, 16);
		}

		if (is_valid_ethaddr(mac_addr))
			eth_env_set_enetaddr("ethaddr", mac_addr);
		else
			meson_generate_serial_ethaddr();
	}

	odroid_detect_variant();
	return 0;
}