1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * (C) Copyright 2019 Rockchip Electronics Co., Ltd
4 */
5
6 #include <linux/stddef.h>
7 #include <adc.h>
8 #include <asm/io.h>
9 #include <dm.h>
10 #include <env.h>
11 #include <stdlib.h>
12
13 #define DTB_DIR "rockchip/"
14
15 struct oga_model {
16 const u16 adc_value;
17 const char *board;
18 const char *board_name;
19 const char *fdtfile;
20 };
21
22 enum oga_device_id {
23 OGA,
24 OGA_V11,
25 OGS,
26 };
27
28 /*
29 * All ADC values from schematic of Odroid Go Advance Black Edition.
30 * Value for OGS is inferred based on schematic and observed values.
31 */
32 static const struct oga_model oga_model_details[] = {
33 [OGA] = {
34 856,
35 "rk3326-odroid-go2",
36 "ODROID-GO Advance",
37 DTB_DIR "rk3326-odroid-go2.dtb",
38 },
39 [OGA_V11] = {
40 677,
41 "rk3326-odroid-go2-v11",
42 "ODROID-GO Advance Black Edition",
43 DTB_DIR "rk3326-odroid-go2-v11.dtb",
44 },
45 [OGS] = {
46 85,
47 "rk3326-odroid-go3",
48 "ODROID-GO Super",
49 DTB_DIR "rk3326-odroid-go3.dtb",
50 },
51 };
52
53 /* Detect which Odroid Go Advance device we are using so as to load the
54 * correct devicetree for Linux. Set an environment variable once
55 * found. The detection depends on the value of ADC channel 0.
56 */
oga_detect_device(void)57 int oga_detect_device(void)
58 {
59 u32 adc_info;
60 int ret, i;
61 int board_id = -ENXIO;
62
63 ret = adc_channel_single_shot("saradc@ff288000", 0, &adc_info);
64 if (ret) {
65 printf("Read SARADC failed with error %d\n", ret);
66 return ret;
67 }
68
69 /*
70 * Get the correct device from the table. The ADC value is
71 * determined by a resistor on ADC channel 0. The manufacturer
72 * accounted for this with a 5% tolerance, so assume a +- value
73 * of 50 should be enough.
74 */
75 for (i = 0; i < ARRAY_SIZE(oga_model_details); i++) {
76 u32 adc_min = oga_model_details[i].adc_value - 50;
77 u32 adc_max = oga_model_details[i].adc_value + 50;
78
79 if (adc_min < adc_info && adc_max > adc_info) {
80 board_id = i;
81 break;
82 }
83 }
84
85 if (board_id < 0)
86 return board_id;
87
88 env_set("board", oga_model_details[board_id].board);
89 env_set("board_name",
90 oga_model_details[board_id].board_name);
91 env_set("fdtfile", oga_model_details[board_id].fdtfile);
92
93 return 0;
94 }
95
rk_board_late_init(void)96 int rk_board_late_init(void)
97 {
98 int ret;
99
100 ret = oga_detect_device();
101 if (ret) {
102 printf("Unable to detect device type: %d\n", ret);
103 return ret;
104 }
105
106 return 0;
107 }
108