blob: 37e2cccd9afecfbb259669c5940e83a3830a124f [file] [log] [blame]
Marek Vasut08743f32021-07-03 20:38:26 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2021 Marek Vasut <marek.vasut+renesas@gmail.com>
4 */
5
Marek Vasut08743f32021-07-03 20:38:26 +02006#include <dm.h>
7#include <i2c_eeprom.h>
8#include <log.h>
9#include <sysinfo.h>
10
11#define BOARD_CODE_MASK 0xF8
12#define BOARD_REV_MASK 0x07
13#define BOARD_CODE_SHIFT 0x03
14
15#define BOARD_SALVATOR_X 0x0
16#define BOARD_KRIEK 0x1
17#define BOARD_STARTER_KIT 0x2
Tam Nguyen21518852023-02-27 23:58:46 +010018#define BOARD_EAGLE 0x3
Marek Vasut08743f32021-07-03 20:38:26 +020019#define BOARD_SALVATOR_XS 0x4
Tam Nguyen5d5664f2023-02-27 23:58:47 +010020#define BOARD_CONDOR 0x6
Tam Nguyen21518852023-02-27 23:58:46 +010021#define BOARD_DRAAK 0x7
Marek Vasut08743f32021-07-03 20:38:26 +020022#define BOARD_EBISU 0x8
23#define BOARD_STARTER_KIT_PRE 0xB
24#define BOARD_EBISU_4D 0xD
Tam Nguyen5d5664f2023-02-27 23:58:47 +010025#define BOARD_CONDOR_I 0x10
Marek Vasut08743f32021-07-03 20:38:26 +020026
27/**
28 * struct sysinfo_rcar_priv - sysinfo private data
29 * @boardname: board model and revision
30 * @val: board ID value from eeprom
31 */
32struct sysinfo_rcar_priv {
33 char boardmodel[64];
34 u8 val;
35};
36
37static int sysinfo_rcar_detect(struct udevice *dev)
38{
39 struct sysinfo_rcar_priv *priv = dev_get_priv(dev);
40
41 return priv->val == 0xff;
42}
43
44static int sysinfo_rcar_get_str(struct udevice *dev, int id, size_t size, char *val)
45{
46 struct sysinfo_rcar_priv *priv = dev_get_priv(dev);
47
48 switch (id) {
49 case SYSINFO_ID_BOARD_MODEL:
50 strncpy(val, priv->boardmodel, size);
51 val[size - 1] = '\0';
52 return 0;
53 default:
54 return -EINVAL;
55 };
56}
57
58static const struct sysinfo_ops sysinfo_rcar_ops = {
59 .detect = sysinfo_rcar_detect,
60 .get_str = sysinfo_rcar_get_str,
61};
62
63static void sysinfo_rcar_parse(struct sysinfo_rcar_priv *priv)
64{
65 const u8 board_id = (priv->val & BOARD_CODE_MASK) >> BOARD_CODE_SHIFT;
66 const u8 board_rev = priv->val & BOARD_REV_MASK;
67 bool salvator_xs = false;
68 bool ebisu_4d = false;
Tam Nguyen5d5664f2023-02-27 23:58:47 +010069 bool condor_i = false;
Marek Vasut08743f32021-07-03 20:38:26 +020070 char rev_major = '?';
71 char rev_minor = '?';
72
73 switch (board_id) {
74 case BOARD_SALVATOR_XS:
75 salvator_xs = true;
76 fallthrough;
77 case BOARD_SALVATOR_X:
78 if (!(board_rev & ~1)) { /* Only rev 0 and 1 is valid */
79 rev_major = '1';
80 rev_minor = '0' + (board_rev & BIT(0));
81 }
82 snprintf(priv->boardmodel, sizeof(priv->boardmodel),
83 "Renesas Salvator-X%s board rev %c.%c",
84 salvator_xs ? "S" : "", rev_major, rev_minor);
85 return;
86 case BOARD_STARTER_KIT:
87 if (!(board_rev & ~1)) { /* Only rev 0 and 1 is valid */
88 rev_major = (board_rev & BIT(0)) ? '3' : '1';
89 rev_minor = '0';
90 }
91 snprintf(priv->boardmodel, sizeof(priv->boardmodel),
92 "Renesas Starter Kit board rev %c.%c",
93 rev_major, rev_minor);
94 return;
95 case BOARD_STARTER_KIT_PRE:
96 if (!(board_rev & ~3)) { /* Only rev 0..3 is valid */
97 rev_major = (board_rev & BIT(1)) ? '2' : '1';
98 rev_minor = (board_rev == 3) ? '1' : '0';
99 }
100 snprintf(priv->boardmodel, sizeof(priv->boardmodel),
101 "Renesas Starter Kit Premier board rev %c.%c",
102 rev_major, rev_minor);
103 return;
104 case BOARD_EAGLE:
105 if (!board_rev) { /* Only rev 0 is valid */
106 rev_major = '1';
107 rev_minor = '0';
108 }
109 snprintf(priv->boardmodel, sizeof(priv->boardmodel),
110 "Renesas Eagle board rev %c.%c",
111 rev_major, rev_minor);
112 return;
113 case BOARD_EBISU_4D:
114 ebisu_4d = true;
115 fallthrough;
116 case BOARD_EBISU:
117 if (!board_rev) { /* Only rev 0 is valid */
118 rev_major = '1';
119 rev_minor = '0';
120 }
121 snprintf(priv->boardmodel, sizeof(priv->boardmodel),
122 "Renesas Ebisu%s board rev %c.%c",
123 ebisu_4d ? "-4D" : "", rev_major, rev_minor);
124 return;
125 case BOARD_DRAAK:
126 if (!board_rev) { /* Only rev 0 is valid */
127 rev_major = '1';
128 rev_minor = '0';
129 }
130 snprintf(priv->boardmodel, sizeof(priv->boardmodel),
131 "Renesas Draak board rev %c.%c",
132 rev_major, rev_minor);
133 return;
134 case BOARD_KRIEK:
135 if (!board_rev) { /* Only rev 0 is valid */
136 rev_major = '1';
137 rev_minor = '0';
138 }
139 snprintf(priv->boardmodel, sizeof(priv->boardmodel),
140 "Renesas Kriek board rev %c.%c",
141 rev_major, rev_minor);
142 return;
Tam Nguyen5d5664f2023-02-27 23:58:47 +0100143 case BOARD_CONDOR_I:
144 condor_i = true;
145 fallthrough;
146 case BOARD_CONDOR:
147 if (!board_rev) { /* Only rev 0 is valid */
148 rev_major = '1';
149 rev_minor = '0';
150 }
151 snprintf(priv->boardmodel, sizeof(priv->boardmodel),
152 "Renesas Condor%s board rev %c.%c",
153 condor_i ? "-I" : "", rev_major, rev_minor);
154 return;
Marek Vasut08743f32021-07-03 20:38:26 +0200155 default:
156 snprintf(priv->boardmodel, sizeof(priv->boardmodel),
157 "Renesas -Unknown- board rev ?.?");
158 priv->val = 0xff;
159 return;
160 }
161}
162
163static int sysinfo_rcar_probe(struct udevice *dev)
164{
165 struct sysinfo_rcar_priv *priv = dev_get_priv(dev);
166 struct ofnode_phandle_args phandle_args;
167 struct udevice *i2c_eeprom;
168 u32 offset;
169 int ret;
170
171 offset = dev_read_u32_default(dev, "offset", 0x70);
172
173 ret = dev_read_phandle_with_args(dev, "i2c-eeprom", NULL,
174 0, 0, &phandle_args);
175 if (ret) {
176 debug("%s: i2c-eeprom backing device not specified\n",
177 dev->name);
178 return ret;
179 }
180
181 ret = uclass_get_device_by_ofnode(UCLASS_I2C_EEPROM, phandle_args.node,
182 &i2c_eeprom);
183 if (ret) {
184 debug("%s: could not get backing device\n", dev->name);
185 return ret;
186 }
187
188 ret = i2c_eeprom_read(i2c_eeprom, offset, &priv->val, 1);
189 if (ret < 0) {
190 debug("%s: read failed\n", __func__);
191 return -EIO;
192 }
193
194 sysinfo_rcar_parse(priv);
195
196 return 0;
197}
198
199static const struct udevice_id sysinfo_rcar_ids[] = {
200 { .compatible = "renesas,rcar-sysinfo" },
201 { /* sentinel */ }
202};
203
204U_BOOT_DRIVER(sysinfo_rcar) = {
205 .name = "sysinfo_rcar",
206 .id = UCLASS_SYSINFO,
207 .of_match = sysinfo_rcar_ids,
208 .ops = &sysinfo_rcar_ops,
209 .priv_auto = sizeof(struct sysinfo_rcar_priv),
210 .probe = sysinfo_rcar_probe,
211};