blob: 099eea60c39ebd4cca58fcc21647f4f7a1633226 [file] [log] [blame]
Chris Morgan8c4e3042023-04-21 10:59:19 -05001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2023 Chris Morgan <macromorgan@hotmail.com>
4 */
5
6#include <abuf.h>
7#include <adc.h>
8#include <asm/io.h>
Chris Morgan448d9cc2024-02-05 12:58:55 -06009#include <command.h>
Chris Morgan3db220e2023-05-15 11:00:30 -050010#include <display.h>
Chris Morgan8c4e3042023-04-21 10:59:19 -050011#include <dm.h>
Chris Morgana824aa62023-05-15 11:00:29 -050012#include <dm/lists.h>
13#include <env.h>
14#include <fdt_support.h>
Chris Morgan8c4e3042023-04-21 10:59:19 -050015#include <linux/delay.h>
Chris Morgan448d9cc2024-02-05 12:58:55 -060016#include <linux/iopoll.h>
Chris Morgan3db220e2023-05-15 11:00:30 -050017#include <mipi_dsi.h>
Chris Morgana824aa62023-05-15 11:00:29 -050018#include <mmc.h>
Chris Morgan3db220e2023-05-15 11:00:30 -050019#include <panel.h>
Chris Morgan8c4e3042023-04-21 10:59:19 -050020#include <pwm.h>
Chris Morgan8c4e3042023-04-21 10:59:19 -050021#include <stdlib.h>
Chris Morgan3db220e2023-05-15 11:00:30 -050022#include <video_bridge.h>
Chris Morgan8c4e3042023-04-21 10:59:19 -050023
Chris Morgan448d9cc2024-02-05 12:58:55 -060024#define BOOT_BROM_DOWNLOAD 0xef08a53c
25
Chris Morgan8c4e3042023-04-21 10:59:19 -050026#define GPIO0_BASE 0xfdd60000
Chris Morgan3db220e2023-05-15 11:00:30 -050027#define GPIO4_BASE 0xfe770000
Chris Morgana824aa62023-05-15 11:00:29 -050028#define GPIO_SWPORT_DR_L 0x0000
Chris Morgan8c4e3042023-04-21 10:59:19 -050029#define GPIO_SWPORT_DR_H 0x0004
Chris Morgana824aa62023-05-15 11:00:29 -050030#define GPIO_SWPORT_DDR_L 0x0008
Chris Morgan8c4e3042023-04-21 10:59:19 -050031#define GPIO_SWPORT_DDR_H 0x000c
Chris Morgan3db220e2023-05-15 11:00:30 -050032#define GPIO_A0 BIT(0)
Chris Morgana824aa62023-05-15 11:00:29 -050033#define GPIO_C5 BIT(5)
34#define GPIO_C6 BIT(6)
35#define GPIO_C7 BIT(7)
Chris Morgan8c4e3042023-04-21 10:59:19 -050036
37#define GPIO_WRITEMASK(bits) ((bits) << 16)
38
Chris Morgan448d9cc2024-02-05 12:58:55 -060039#define SARADC_BASE 0xfe720000
40#define SARADC_DATA 0x0000
41#define SARADC_STAS 0x0004
42#define SARADC_ADC_STATUS BIT(0)
43#define SARADC_CTRL 0x0008
44#define SARADC_INPUT_SRC_MSK 0x7
45#define SARADC_POWER_CTRL BIT(3)
46
Chris Morgan8c4e3042023-04-21 10:59:19 -050047#define DTB_DIR "rockchip/"
48
49struct rg3xx_model {
Chris Morgana824aa62023-05-15 11:00:29 -050050 const u16 adc_value;
Chris Morgan8c4e3042023-04-21 10:59:19 -050051 const char *board;
52 const char *board_name;
53 const char *fdtfile;
Chris Morgana63ff502024-01-02 09:46:48 -060054 const bool detect_panel;
Chris Morgan8c4e3042023-04-21 10:59:19 -050055};
56
57enum rgxx3_device_id {
58 RG353M,
59 RG353P,
60 RG353V,
Chris Morgan8c4e3042023-04-21 10:59:19 -050061 RG503,
Chris Morgan95db0c02024-01-02 09:46:53 -060062 RGB30,
63 RK2023,
64 RGARCD,
Chris Morgan4b181142024-02-05 12:58:53 -060065 RGB10MAX3,
Chris Morgana824aa62023-05-15 11:00:29 -050066 /* Devices with duplicate ADC value */
67 RG353PS,
68 RG353VS,
Chris Morgan95db0c02024-01-02 09:46:53 -060069 RGARCS,
Chris Morgan8c4e3042023-04-21 10:59:19 -050070};
71
72static const struct rg3xx_model rg3xx_model_details[] = {
73 [RG353M] = {
Chris Morgana63ff502024-01-02 09:46:48 -060074 .adc_value = 517, /* Observed average from device */
75 .board = "rk3566-anbernic-rg353m",
76 .board_name = "RG353M",
77 /* Device is identical to RG353P. */
78 .fdtfile = DTB_DIR "rk3566-anbernic-rg353p.dtb",
79 .detect_panel = 1,
Chris Morgan8c4e3042023-04-21 10:59:19 -050080 },
81 [RG353P] = {
Chris Morgana63ff502024-01-02 09:46:48 -060082 .adc_value = 860, /* Documented value of 860 */
83 .board = "rk3566-anbernic-rg353p",
84 .board_name = "RG353P",
85 .fdtfile = DTB_DIR "rk3566-anbernic-rg353p.dtb",
86 .detect_panel = 1,
Chris Morgan8c4e3042023-04-21 10:59:19 -050087 },
88 [RG353V] = {
Chris Morgana63ff502024-01-02 09:46:48 -060089 .adc_value = 695, /* Observed average from device */
90 .board = "rk3566-anbernic-rg353v",
91 .board_name = "RG353V",
92 .fdtfile = DTB_DIR "rk3566-anbernic-rg353v.dtb",
93 .detect_panel = 1,
Chris Morgan8c4e3042023-04-21 10:59:19 -050094 },
Chris Morgan8c4e3042023-04-21 10:59:19 -050095 [RG503] = {
Chris Morgana63ff502024-01-02 09:46:48 -060096 .adc_value = 1023, /* Observed average from device */
97 .board = "rk3566-anbernic-rg503",
98 .board_name = "RG503",
99 .fdtfile = DTB_DIR "rk3566-anbernic-rg503.dtb",
100 .detect_panel = 0,
Chris Morgan8c4e3042023-04-21 10:59:19 -0500101 },
Chris Morgan95db0c02024-01-02 09:46:53 -0600102 [RGB30] = {
103 .adc_value = 383, /* Gathered from second hand information */
104 .board = "rk3566-powkiddy-rgb30",
105 .board_name = "RGB30",
106 .fdtfile = DTB_DIR "rk3566-powkiddy-rgb30.dtb",
107 .detect_panel = 0,
108 },
109 [RK2023] = {
110 .adc_value = 635, /* Observed average from device */
111 .board = "rk3566-powkiddy-rk2023",
112 .board_name = "RK2023",
113 .fdtfile = DTB_DIR "rk3566-powkiddy-rk2023.dtb",
114 .detect_panel = 0,
115 },
116 [RGARCD] = {
117 .adc_value = 183, /* Observed average from device */
118 .board = "rk3566-anbernic-rg-arc-d",
119 .board_name = "Anbernic RG ARC-D",
120 .fdtfile = DTB_DIR "rk3566-anbernic-rg-arc-d.dtb",
121 .detect_panel = 0,
122 },
Chris Morgan4b181142024-02-05 12:58:53 -0600123 [RGB10MAX3] = {
124 .adc_value = 765, /* Observed average from device */
125 .board = "rk3566-powkiddy-rgb10max3",
126 .board_name = "Powkiddy RGB10MAX3",
127 .fdtfile = DTB_DIR "rk3566-powkiddy-rgb10max3.dtb",
128 .detect_panel = 0,
129 },
Chris Morgana824aa62023-05-15 11:00:29 -0500130 /* Devices with duplicate ADC value */
131 [RG353PS] = {
Chris Morgana63ff502024-01-02 09:46:48 -0600132 .adc_value = 860, /* Observed average from device */
133 .board = "rk3566-anbernic-rg353ps",
134 .board_name = "RG353PS",
135 .fdtfile = DTB_DIR "rk3566-anbernic-rg353ps.dtb",
136 .detect_panel = 1,
Chris Morgana824aa62023-05-15 11:00:29 -0500137 },
138 [RG353VS] = {
Chris Morgana63ff502024-01-02 09:46:48 -0600139 .adc_value = 695, /* Gathered from second hand information */
140 .board = "rk3566-anbernic-rg353vs",
141 .board_name = "RG353VS",
142 .fdtfile = DTB_DIR "rk3566-anbernic-rg353vs.dtb",
143 .detect_panel = 1,
Chris Morgana824aa62023-05-15 11:00:29 -0500144 },
Chris Morgan95db0c02024-01-02 09:46:53 -0600145 [RGARCS] = {
146 .adc_value = 183, /* Observed average from device */
147 .board = "rk3566-anbernic-rg-arc-s",
148 .board_name = "Anbernic RG ARC-S",
149 .fdtfile = DTB_DIR "rk3566-anbernic-rg-arc-s.dtb",
150 .detect_panel = 0,
151 },
Chris Morgan8c4e3042023-04-21 10:59:19 -0500152};
153
Chris Morgan3db220e2023-05-15 11:00:30 -0500154struct rg353_panel {
155 const u16 id;
Chris Morgana63ff502024-01-02 09:46:48 -0600156 const char *panel_compat[2];
Chris Morgan3db220e2023-05-15 11:00:30 -0500157};
158
159static const struct rg353_panel rg353_panel_details[] = {
Chris Morgana63ff502024-01-02 09:46:48 -0600160 {
161 .id = 0x3052,
162 .panel_compat[0] = "anbernic,rg353p-panel",
163 .panel_compat[1] = "newvision,nv3051d",
164 },
165 {
166 .id = 0x3821,
167 .panel_compat[0] = "anbernic,rg353v-panel-v2",
168 .panel_compat[1] = NULL,
169 },
Chris Morgan3db220e2023-05-15 11:00:30 -0500170};
171
Chris Morgan8c4e3042023-04-21 10:59:19 -0500172/*
Chris Morgan448d9cc2024-02-05 12:58:55 -0600173 * The device has internal eMMC, and while some devices have an exposed
174 * clk pin you can ground to force a bypass not all devices do. As a
175 * result it may be possible for some devices to become a perma-brick
176 * if a corrupted TPL or SPL stage with a valid header is flashed to
177 * the internal eMMC. Add functionality to read ADC channel 0 (the func
178 * button) as early as possible in the boot process to provide some
179 * protection against this. If we ever get an open TPL stage, we should
180 * consider moving this function there.
181 */
182void read_func_button(void)
183{
184 int ret;
185 u32 reg;
186
187 /* Turn off SARADC to reset it. */
188 writel(0, (SARADC_BASE + SARADC_CTRL));
189
190 /* Enable channel 0 and power on SARADC. */
191 writel(((0 & SARADC_INPUT_SRC_MSK) | SARADC_POWER_CTRL),
192 (SARADC_BASE + SARADC_CTRL));
193
194 /*
195 * Wait for data to be ready. Use timeout of 20000us from
196 * rockchip_saradc driver.
197 */
198 ret = readl_poll_timeout((SARADC_BASE + SARADC_STAS), reg,
199 !(reg & SARADC_ADC_STATUS), 20000);
200 if (ret) {
201 printf("ADC Timeout");
202 return;
203 }
204
205 /* Read the data from the SARADC. */
206 reg = readl((SARADC_BASE + SARADC_DATA));
207
208 /* Turn the SARADC back off so it's ready to be used again. */
209 writel(0, (SARADC_BASE + SARADC_CTRL));
210
211 /*
212 * If the value is less than 30 the button is being pressed.
213 * Reset the device back into Rockchip download mode.
214 */
215 if (reg <= 30) {
216 printf("download key pressed, entering download mode...");
217 writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG);
218 do_reset(NULL, 0, 0, NULL);
219 }
220};
221
222/*
Chris Morgan8c4e3042023-04-21 10:59:19 -0500223 * Start LED very early so user knows device is on. Set color
Chris Morgana824aa62023-05-15 11:00:29 -0500224 * to red.
Chris Morgan8c4e3042023-04-21 10:59:19 -0500225 */
226void spl_board_init(void)
227{
Chris Morgan448d9cc2024-02-05 12:58:55 -0600228 read_func_button();
229
Chris Morgana824aa62023-05-15 11:00:29 -0500230 /* Set GPIO0_C5, GPIO0_C6, and GPIO0_C7 to output. */
231 writel(GPIO_WRITEMASK(GPIO_C7 | GPIO_C6 | GPIO_C5) | \
232 (GPIO_C7 | GPIO_C6 | GPIO_C5),
Chris Morgan8c4e3042023-04-21 10:59:19 -0500233 (GPIO0_BASE + GPIO_SWPORT_DDR_H));
Chris Morgana824aa62023-05-15 11:00:29 -0500234 /* Set GPIO0_C5 and GPIO_C6 to 0 and GPIO0_C7 to 1. */
235 writel(GPIO_WRITEMASK(GPIO_C7 | GPIO_C6 | GPIO_C5) | GPIO_C7,
Chris Morgan8c4e3042023-04-21 10:59:19 -0500236 (GPIO0_BASE + GPIO_SWPORT_DR_H));
237}
238
Chris Morgan8c4e3042023-04-21 10:59:19 -0500239/*
240 * Buzz the buzzer so the user knows something is going on. Make it
241 * optional in case PWM is disabled.
242 */
243void __maybe_unused startup_buzz(void)
244{
245 struct udevice *dev;
246 int err;
247
248 err = uclass_get_device(UCLASS_PWM, 0, &dev);
249 if (err)
250 printf("pwm not found\n");
251
252 pwm_set_enable(dev, 0, 1);
253 mdelay(200);
254 pwm_set_enable(dev, 0, 0);
255}
256
Chris Morgan3db220e2023-05-15 11:00:30 -0500257/*
258 * Provide the bare minimum to identify the panel for the RG353
259 * series. Since we don't have a working framebuffer device, no
260 * need to init the panel; just identify it and provide the
261 * clocks so we know what to set the different clock values to.
262 */
263
264static const struct display_timing rg353_default_timing = {
265 .pixelclock.typ = 24150000,
266 .hactive.typ = 640,
267 .hfront_porch.typ = 40,
268 .hback_porch.typ = 80,
269 .hsync_len.typ = 2,
270 .vactive.typ = 480,
271 .vfront_porch.typ = 18,
272 .vback_porch.typ = 28,
273 .vsync_len.typ = 2,
274 .flags = DISPLAY_FLAGS_HSYNC_HIGH |
275 DISPLAY_FLAGS_VSYNC_HIGH,
276};
277
278static int anbernic_rg353_panel_get_timing(struct udevice *dev,
279 struct display_timing *timings)
280{
281 memcpy(timings, &rg353_default_timing, sizeof(*timings));
282
283 return 0;
284}
285
286static int anbernic_rg353_panel_probe(struct udevice *dev)
287{
288 struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
289
290 plat->lanes = 4;
291 plat->format = MIPI_DSI_FMT_RGB888;
292 plat->mode_flags = MIPI_DSI_MODE_VIDEO |
293 MIPI_DSI_MODE_VIDEO_BURST |
294 MIPI_DSI_MODE_EOT_PACKET |
295 MIPI_DSI_MODE_LPM;
296
297 return 0;
298}
299
300static const struct panel_ops anbernic_rg353_panel_ops = {
301 .get_display_timing = anbernic_rg353_panel_get_timing,
302};
303
304U_BOOT_DRIVER(anbernic_rg353_panel) = {
305 .name = "anbernic_rg353_panel",
306 .id = UCLASS_PANEL,
307 .ops = &anbernic_rg353_panel_ops,
308 .probe = anbernic_rg353_panel_probe,
309 .plat_auto = sizeof(struct mipi_dsi_panel_plat),
310};
311
312int rgxx3_detect_display(void)
313{
314 struct udevice *dev;
315 struct mipi_dsi_device *dsi;
316 struct mipi_dsi_panel_plat *mplat;
317 const struct rg353_panel *panel;
318 int ret = 0;
319 int i;
320 u8 panel_id[2];
321
322 /*
323 * Take panel out of reset status.
324 * Set GPIO4_A0 to output.
325 */
326 writel(GPIO_WRITEMASK(GPIO_A0) | GPIO_A0,
327 (GPIO4_BASE + GPIO_SWPORT_DDR_L));
328 /* Set GPIO4_A0 to 1. */
329 writel(GPIO_WRITEMASK(GPIO_A0) | GPIO_A0,
330 (GPIO4_BASE + GPIO_SWPORT_DR_L));
331
332 /* Probe the DSI controller. */
333 ret = uclass_get_device_by_name(UCLASS_VIDEO_BRIDGE,
334 "dsi@fe060000", &dev);
335 if (ret) {
336 printf("DSI host not probed: %d\n", ret);
337 return ret;
338 }
339
340 /* Probe the DSI panel. */
341 ret = device_bind_driver_to_node(dev, "anbernic_rg353_panel",
342 "anbernic_rg353_panel",
343 dev_ofnode(dev), NULL);
344 if (ret) {
345 printf("Failed to probe RG353 panel: %d\n", ret);
346 return ret;
347 }
348
349 /*
350 * Attach the DSI controller which will also probe and attach
351 * the DSIDPHY.
352 */
353 ret = video_bridge_attach(dev);
354 if (ret) {
355 printf("Failed to attach DSI controller: %d\n", ret);
356 return ret;
357 }
358
359 /*
360 * Get the panel which should have already been probed by the
361 * video_bridge_attach() function.
362 */
363 ret = uclass_first_device_err(UCLASS_PANEL, &dev);
364 if (ret) {
365 printf("Panel device error: %d\n", ret);
366 return ret;
367 }
368
369 /* Now call the panel via DSI commands to get the panel ID. */
370 mplat = dev_get_plat(dev);
371 dsi = mplat->device;
372 mipi_dsi_set_maximum_return_packet_size(dsi, sizeof(panel_id));
373 ret = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_DISPLAY_ID, &panel_id,
374 sizeof(panel_id));
375 if (ret < 0) {
376 printf("Unable to read panel ID: %d\n", ret);
377 return ret;
378 }
379
380 /* Get the correct panel compatible from the table. */
381 for (i = 0; i < ARRAY_SIZE(rg353_panel_details); i++) {
382 if (rg353_panel_details[i].id == ((panel_id[0] << 8) |
383 panel_id[1])) {
384 panel = &rg353_panel_details[i];
385 break;
386 }
387 }
388
389 if (!panel) {
390 printf("Unable to identify panel_id %x\n",
391 (panel_id[0] << 8) | panel_id[1]);
Chris Morgan3db220e2023-05-15 11:00:30 -0500392 return -EINVAL;
393 }
394
Chris Morgana63ff502024-01-02 09:46:48 -0600395 env_set("panel", panel->panel_compat[0]);
Chris Morgan3db220e2023-05-15 11:00:30 -0500396
397 return 0;
398}
399
Chris Morgan8c4e3042023-04-21 10:59:19 -0500400/* Detect which Anbernic RGXX3 device we are using so as to load the
401 * correct devicetree for Linux. Set an environment variable once
402 * found. The detection depends on the value of ADC channel 1, the
Chris Morgana824aa62023-05-15 11:00:29 -0500403 * presence of an eMMC on mmc0, and querying the DSI panel.
Chris Morgan8c4e3042023-04-21 10:59:19 -0500404 */
405int rgxx3_detect_device(void)
406{
407 u32 adc_info;
Chris Morgana824aa62023-05-15 11:00:29 -0500408 int ret, i;
Chris Morgan8c4e3042023-04-21 10:59:19 -0500409 int board_id = -ENXIO;
410 struct mmc *mmc;
411
412 ret = adc_channel_single_shot("saradc@fe720000", 1, &adc_info);
413 if (ret) {
414 printf("Read SARADC failed with error %d\n", ret);
415 return ret;
416 }
417
Chris Morgana824aa62023-05-15 11:00:29 -0500418 /*
419 * Get the correct device from the table. The ADC value is
420 * determined by a resistor on ADC channel 0. The hardware
421 * design calls for no more than a 1% variance on the
422 * resistor, so assume a +- value of 15 should be enough.
423 */
424 for (i = 0; i < ARRAY_SIZE(rg3xx_model_details); i++) {
425 u32 adc_min = rg3xx_model_details[i].adc_value - 15;
426 u32 adc_max = rg3xx_model_details[i].adc_value + 15;
427
428 if (adc_min < adc_info && adc_max > adc_info) {
429 board_id = i;
430 break;
431 }
432 }
Chris Morgan8c4e3042023-04-21 10:59:19 -0500433
434 /*
Chris Morgan95db0c02024-01-02 09:46:53 -0600435 * Try to access the eMMC on an RG353V, RG353P, or RG Arc D.
436 * If it's missing, it's an RG353VS, RG353PS, or RG Arc S.
437 * Note we could also check for a touchscreen at 0x1a on i2c2.
Chris Morgan8c4e3042023-04-21 10:59:19 -0500438 */
Chris Morgan95db0c02024-01-02 09:46:53 -0600439 if (board_id == RG353V || board_id == RG353P || board_id == RGARCD) {
Chris Morgan8c4e3042023-04-21 10:59:19 -0500440 mmc = find_mmc_device(0);
441 if (mmc) {
442 ret = mmc_init(mmc);
Chris Morgana824aa62023-05-15 11:00:29 -0500443 if (ret) {
444 if (board_id == RG353V)
445 board_id = RG353VS;
Chris Morgan95db0c02024-01-02 09:46:53 -0600446 else if (board_id == RG353P)
Chris Morgana824aa62023-05-15 11:00:29 -0500447 board_id = RG353PS;
Chris Morgan95db0c02024-01-02 09:46:53 -0600448 else
449 board_id = RGARCS;
Chris Morgana824aa62023-05-15 11:00:29 -0500450 }
Chris Morgan8c4e3042023-04-21 10:59:19 -0500451 }
452 }
453
454 if (board_id < 0)
455 return board_id;
456
457 env_set("board", rg3xx_model_details[board_id].board);
458 env_set("board_name",
459 rg3xx_model_details[board_id].board_name);
460 env_set("fdtfile", rg3xx_model_details[board_id].fdtfile);
461
Chris Morgana63ff502024-01-02 09:46:48 -0600462 /* Skip panel detection for when it is not needed. */
463 if (!rg3xx_model_details[board_id].detect_panel)
Chris Morgan3db220e2023-05-15 11:00:30 -0500464 return 0;
465
Chris Morgana63ff502024-01-02 09:46:48 -0600466 /* Warn but don't fail for errors in auto-detection of the panel. */
Chris Morgan3db220e2023-05-15 11:00:30 -0500467 ret = rgxx3_detect_display();
468 if (ret)
Chris Morgana63ff502024-01-02 09:46:48 -0600469 printf("Failed to detect panel type\n");
Chris Morgan3db220e2023-05-15 11:00:30 -0500470
Chris Morgan8c4e3042023-04-21 10:59:19 -0500471 return 0;
472}
473
474int rk_board_late_init(void)
475{
476 int ret;
477
Chris Morgan8c4e3042023-04-21 10:59:19 -0500478 ret = rgxx3_detect_device();
479 if (ret) {
480 printf("Unable to detect device type: %d\n", ret);
481 return ret;
482 }
483
Chris Morgana824aa62023-05-15 11:00:29 -0500484 /* Turn off red LED and turn on orange LED. */
485 writel(GPIO_WRITEMASK(GPIO_C7 | GPIO_C6 | GPIO_C5) | GPIO_C6,
486 (GPIO0_BASE + GPIO_SWPORT_DR_H));
487
Chris Morgan8c4e3042023-04-21 10:59:19 -0500488 if (IS_ENABLED(CONFIG_DM_PWM))
489 startup_buzz();
490
491 return 0;
492}
Chris Morgana824aa62023-05-15 11:00:29 -0500493
494int ft_board_setup(void *blob, struct bd_info *bd)
495{
Chris Morgana63ff502024-01-02 09:46:48 -0600496 const struct rg353_panel *panel = NULL;
497 int node, ret, i;
Chris Morgana824aa62023-05-15 11:00:29 -0500498 char *env;
499
500 /* No fixups necessary for the RG503 */
501 env = env_get("board_name");
502 if (env && (!strcmp(env, rg3xx_model_details[RG503].board_name)))
503 return 0;
504
505 /* Change the model name of the RG353M */
506 if (env && (!strcmp(env, rg3xx_model_details[RG353M].board_name)))
507 fdt_setprop(blob, 0, "model",
508 rg3xx_model_details[RG353M].board_name,
509 sizeof(rg3xx_model_details[RG353M].board_name));
510
Chris Morgana63ff502024-01-02 09:46:48 -0600511 env = env_get("panel");
512 if (!env) {
513 printf("Can't get panel env\n");
514 return 0;
515 }
516
Chris Morgan3db220e2023-05-15 11:00:30 -0500517 /*
518 * Check if the environment variable doesn't equal the panel.
519 * If it doesn't, update the devicetree to the correct panel.
520 */
521 node = fdt_path_offset(blob, "/dsi@fe060000/panel@0");
522 if (!(node > 0)) {
523 printf("Can't find the DSI node\n");
524 return -ENODEV;
525 }
526
Chris Morgan3db220e2023-05-15 11:00:30 -0500527 ret = fdt_node_check_compatible(blob, node, env);
528 if (ret < 0)
529 return -ENODEV;
530
531 /* Panels match, return 0. */
532 if (!ret)
533 return 0;
534
Chris Morgana63ff502024-01-02 09:46:48 -0600535 /* Panels don't match, search by first compatible value. */
536 for (i = 0; i < ARRAY_SIZE(rg353_panel_details); i++) {
537 if (!strcmp(env, rg353_panel_details[i].panel_compat[0])) {
538 panel = &rg353_panel_details[i];
539 break;
540 }
541 }
542
543 if (!panel) {
544 printf("Unable to identify panel by compat string\n");
545 return -ENODEV;
546 }
547
548 /* Set the compatible with the auto-detected values */
549 fdt_setprop_string(blob, node, "compatible", panel->panel_compat[0]);
550 if (panel->panel_compat[1])
551 fdt_appendprop_string(blob, node, "compatible",
552 panel->panel_compat[1]);
Chris Morgan3db220e2023-05-15 11:00:30 -0500553
Chris Morgana824aa62023-05-15 11:00:29 -0500554 return 0;
555}