• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <boardid.h>
4 #include <bootmode.h>
5 #include <boot/coreboot_tables.h>
6 #include <console/console.h>
7 #include <delay.h>
8 #include <drivers/i2c/ww_ring/ww_ring.h>
9 #include <gpio.h>
10 #include <soc/cdp.h>
11 #include <soc/gsbi.h>
12 #include <timer.h>
13 
14 #define DEV_SW 15
15 #define REC_SW 16
16 #define WP_SW  17
17 
read_gpio(gpio_t gpio_num)18 static int read_gpio(gpio_t gpio_num)
19 {
20 	gpio_tlmm_config_set(gpio_num, GPIO_FUNC_DISABLE,
21 			     GPIO_NO_PULL, GPIO_2MA, GPIO_DISABLE);
22 	udelay(10); /* Should be enough to settle. */
23 	return gpio_get(gpio_num);
24 }
25 
fill_lb_gpios(struct lb_gpios * gpios)26 void fill_lb_gpios(struct lb_gpios *gpios)
27 {
28 	struct lb_gpio chromeos_gpios[] = {
29 		{DEV_SW, ACTIVE_LOW, read_gpio(REC_SW), "presence"},
30 		{-1, ACTIVE_LOW, 1, "power"},
31 		{-1, ACTIVE_LOW, 0, "lid"},
32 	};
33 	lb_add_gpios(gpios, chromeos_gpios, ARRAY_SIZE(chromeos_gpios));
34 }
35 
36 /*
37  * The recovery switch on storm is overloaded: it needs to be pressed for a
38  * certain duration at startup to signal different requests:
39  *
40  * - keeping it pressed for 8 to 16 seconds after startup signals the need for
41  *   factory reset (wipeout);
42  * - keeping it pressed for longer than 16 seconds signals the need for Chrome
43  *   OS recovery.
44  *
45  * The state is read once and cached for following inquiries. The below enum
46  * lists possible states.
47  */
48 enum switch_state {
49 	not_probed = -1,
50 	no_req,
51 	recovery_req,
52 	wipeout_req
53 };
54 
display_pattern(int pattern)55 static void display_pattern(int pattern)
56 {
57 	if (board_id() == BOARD_ID_WHIRLWIND_SP5)
58 		ww_ring_display_pattern(GSBI_ID_7, pattern);
59 }
60 
61 #define WIPEOUT_MODE_DELAY_MS (8 * 1000)
62 #define RECOVERY_MODE_EXTRA_DELAY_MS (8 * 1000)
63 
get_switch_state(void)64 static enum switch_state get_switch_state(void)
65 {
66 	struct stopwatch sw;
67 	int sampled_value;
68 	static enum switch_state saved_state = not_probed;
69 
70 	if (saved_state != not_probed)
71 		return saved_state;
72 
73 	sampled_value = !read_gpio(REC_SW);
74 
75 	if (!sampled_value) {
76 		saved_state = no_req;
77 		display_pattern(WWR_NORMAL_BOOT);
78 		return saved_state;
79 	}
80 
81 	display_pattern(WWR_RECOVERY_PUSHED);
82 	printk(BIOS_INFO, "recovery button pressed\n");
83 
84 	stopwatch_init_msecs_expire(&sw, WIPEOUT_MODE_DELAY_MS);
85 
86 	do {
87 		sampled_value = !read_gpio(REC_SW);
88 		if (!sampled_value)
89 			break;
90 	} while (!stopwatch_expired(&sw));
91 
92 	if (sampled_value) {
93 		display_pattern(WWR_WIPEOUT_REQUEST);
94 		printk(BIOS_INFO, "wipeout requested, checking recovery\n");
95 		stopwatch_init_msecs_expire(&sw, RECOVERY_MODE_EXTRA_DELAY_MS);
96 		do {
97 			sampled_value = !read_gpio(REC_SW);
98 			if (!sampled_value)
99 				break;
100 		} while (!stopwatch_expired(&sw));
101 
102 		if (sampled_value) {
103 			saved_state = recovery_req;
104 			display_pattern(WWR_RECOVERY_REQUEST);
105 			printk(BIOS_INFO, "recovery requested\n");
106 		} else {
107 			saved_state = wipeout_req;
108 		}
109 	} else {
110 		saved_state = no_req;
111 		display_pattern(WWR_NORMAL_BOOT);
112 	}
113 
114 	return saved_state;
115 }
116 
get_recovery_mode_switch(void)117 int get_recovery_mode_switch(void)
118 {
119 	return get_switch_state() == recovery_req;
120 }
121 
get_wipeout_mode_switch(void)122 int get_wipeout_mode_switch(void)
123 {
124 	return get_switch_state() == wipeout_req;
125 }
126 
get_write_protect_state(void)127 int get_write_protect_state(void)
128 {
129 	return !read_gpio(WP_SW);
130 }
131 
get_ec_is_trusted(void)132 int get_ec_is_trusted(void)
133 {
134 	/* Do not have a Chrome EC involved in entering recovery mode;
135 	   Always return trusted. */
136 	return 1;
137 }
138