blob: 7598fe4c43d40d8d5f70e5b0ffba58df28df0cea [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Andy Yan70378cb2017-10-11 15:00:16 +08002/*
3 * (C) Copyright 2016 Rockchip Electronics Co., Ltd
Andy Yan70378cb2017-10-11 15:00:16 +08004 */
5
6#include <common.h>
Andy Yan215db9c2017-10-11 15:01:31 +08007#include <adc.h>
Andy Yan70378cb2017-10-11 15:00:16 +08008#include <asm/io.h>
Kever Yang9fbe17c2019-03-28 11:01:23 +08009#include <asm/arch-rockchip/boot_mode.h>
Hugh Cole-Baker82820942020-01-25 16:19:36 +000010#include <dm/device.h>
11#include <dm/uclass.h>
Andy Yan70378cb2017-10-11 15:00:16 +080012
Philipp Tomsich3a0df082017-11-24 14:44:58 +010013#if (CONFIG_ROCKCHIP_BOOT_MODE_REG == 0)
14
15int setup_boot_mode(void)
16{
17 return 0;
18}
19
20#else
21
Andy Yan215db9c2017-10-11 15:01:31 +080022void set_back_to_bootrom_dnl_flag(void)
23{
24 writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG);
25}
26
27/*
28 * detect download key status by adc, most rockchip
29 * based boards use adc sample the download key status,
30 * but there are also some use gpio. So it's better to
31 * make this a weak function that can be override by
32 * some special boards.
33 */
34#define KEY_DOWN_MIN_VAL 0
35#define KEY_DOWN_MAX_VAL 30
36
37__weak int rockchip_dnl_key_pressed(void)
38{
39 unsigned int val;
Hugh Cole-Baker82820942020-01-25 16:19:36 +000040 struct udevice *dev;
41 struct uclass *uc;
42 int ret;
43
44 ret = uclass_get(UCLASS_ADC, &uc);
45 if (ret)
46 return false;
47
48 ret = -ENODEV;
49 uclass_foreach_dev(dev, uc) {
50 if (!strncmp(dev->name, "saradc", 6)) {
51 ret = adc_channel_single_shot(dev->name, 1, &val);
52 break;
53 }
54 }
Andy Yan215db9c2017-10-11 15:01:31 +080055
Hugh Cole-Baker82820942020-01-25 16:19:36 +000056 if (ret == -ENODEV) {
57 pr_warn("%s: no saradc device found\n", __func__);
58 return false;
59 } else if (ret) {
Andy Yan215db9c2017-10-11 15:01:31 +080060 pr_err("%s: adc_channel_single_shot fail!\n", __func__);
61 return false;
62 }
63
64 if ((val >= KEY_DOWN_MIN_VAL) && (val <= KEY_DOWN_MAX_VAL))
65 return true;
66 else
67 return false;
68}
69
70void rockchip_dnl_mode_check(void)
71{
72 if (rockchip_dnl_key_pressed()) {
73 printf("download key pressed, entering download mode...");
74 set_back_to_bootrom_dnl_flag();
75 do_reset(NULL, 0, 0, NULL);
76 }
77}
78
Andy Yan70378cb2017-10-11 15:00:16 +080079int setup_boot_mode(void)
80{
81 void *reg = (void *)CONFIG_ROCKCHIP_BOOT_MODE_REG;
82 int boot_mode = readl(reg);
83
Philipp Tomsiche91b8452019-03-29 09:21:13 +010084 rockchip_dnl_mode_check();
Andy Yan215db9c2017-10-11 15:01:31 +080085
86 boot_mode = readl(reg);
87 debug("%s: boot mode 0x%08x\n", __func__, boot_mode);
Andy Yan70378cb2017-10-11 15:00:16 +080088
89 /* Clear boot mode */
90 writel(BOOT_NORMAL, reg);
91
92 switch (boot_mode) {
93 case BOOT_FASTBOOT:
Andy Yan215db9c2017-10-11 15:01:31 +080094 debug("%s: enter fastboot!\n", __func__);
Andy Yan70378cb2017-10-11 15:00:16 +080095 env_set("preboot", "setenv preboot; fastboot usb0");
96 break;
97 case BOOT_UMS:
Andy Yan215db9c2017-10-11 15:01:31 +080098 debug("%s: enter UMS!\n", __func__);
Andy Yan70378cb2017-10-11 15:00:16 +080099 env_set("preboot", "setenv preboot; ums mmc 0");
100 break;
101 }
102
103 return 0;
104}
Philipp Tomsich3a0df082017-11-24 14:44:58 +0100105
106#endif