• 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/blsp.h>
12 #include <timer.h>
13 
14 #define PP_SW   41
15 
get_rec_sw_gpio_pin(void)16 static int get_rec_sw_gpio_pin(void)
17 {
18 	uint8_t board_rev = board_id();
19 
20 	switch (board_rev) {
21 	case BOARD_ID_GALE_PROTO:
22 	case BOARD_ID_GALE_EVT:
23 	case BOARD_ID_GALE_EVT2_0:
24 	case BOARD_ID_GALE_EVT2_1:
25 		return 7;
26 	case BOARD_ID_GALE_EVT3:
27 	default:
28 		return 57;
29 	}
30 }
31 
get_wp_status_gpio_pin(void)32 static int get_wp_status_gpio_pin(void)
33 {
34 	uint8_t board_rev = board_id();
35 	switch (board_rev) {
36 	case BOARD_ID_GALE_PROTO:
37 	case BOARD_ID_GALE_EVT:
38 	case BOARD_ID_GALE_EVT2_0:
39 	case BOARD_ID_GALE_EVT2_1:
40 		return 6;
41 	case BOARD_ID_GALE_EVT3:
42 	default:
43 		return 53;
44 	}
45 }
read_gpio(gpio_t gpio_num)46 static int read_gpio(gpio_t gpio_num)
47 {
48 	gpio_tlmm_config_set(gpio_num, GPIO_FUNC_DISABLE,
49 			     GPIO_NO_PULL, GPIO_2MA, GPIO_DISABLE);
50 	udelay(10); /* Should be enough to settle. */
51 	return gpio_get(gpio_num);
52 }
53 
fill_lb_gpios(struct lb_gpios * gpios)54 void fill_lb_gpios(struct lb_gpios *gpios)
55 {
56 	struct lb_gpio chromeos_gpios[] = {
57 		{PP_SW, ACTIVE_LOW, read_gpio(PP_SW), "presence"},
58 		{-1, ACTIVE_LOW, 1, "power"},
59 		{-1, ACTIVE_LOW, 0, "lid"},
60 	};
61 	lb_add_gpios(gpios, chromeos_gpios, ARRAY_SIZE(chromeos_gpios));
62 }
63 
64 /*
65  * The recovery switch on storm is overloaded: it needs to be pressed for a
66  * certain duration at startup to signal different requests:
67  *
68  * - keeping it pressed for 8 to 16 seconds after startup signals the need for
69  *   factory reset (wipeout);
70  * - keeping it pressed for longer than 16 seconds signals the need for Chrome
71  *   OS recovery.
72  *
73  * The state is read once and cached for following inquiries. The below enum
74  * lists possible states.
75  */
76 enum switch_state {
77 	not_probed = -1,
78 	no_req,
79 	recovery_req,
80 	wipeout_req
81 };
82 
display_pattern(int pattern)83 static void display_pattern(int pattern)
84 {
85 	ww_ring_display_pattern(BLSP_QUP_ID_3, pattern);
86 }
87 
88 #define WIPEOUT_MODE_DELAY_MS (8 * 1000)
89 #define RECOVERY_MODE_EXTRA_DELAY_MS (8 * 1000)
90 
get_switch_state(void)91 static enum switch_state get_switch_state(void)
92 {
93 	struct stopwatch sw;
94 	int sampled_value;
95 	uint8_t rec_sw;
96 	static enum switch_state saved_state = not_probed;
97 
98 	if (saved_state != not_probed)
99 		return saved_state;
100 
101 	rec_sw = get_rec_sw_gpio_pin();
102 	sampled_value = !read_gpio(rec_sw);
103 
104 	if (!sampled_value) {
105 		saved_state = no_req;
106 		display_pattern(WWR_NORMAL_BOOT);
107 		return saved_state;
108 	}
109 
110 	display_pattern(WWR_RECOVERY_PUSHED);
111 	printk(BIOS_INFO, "recovery button pressed\n");
112 
113 	stopwatch_init_msecs_expire(&sw, WIPEOUT_MODE_DELAY_MS);
114 
115 	do {
116 		sampled_value = !read_gpio(rec_sw);
117 		if (!sampled_value)
118 			break;
119 	} while (!stopwatch_expired(&sw));
120 
121 	if (sampled_value) {
122 		display_pattern(WWR_WIPEOUT_REQUEST);
123 		printk(BIOS_INFO, "wipeout requested, checking recovery\n");
124 		stopwatch_init_msecs_expire(&sw, RECOVERY_MODE_EXTRA_DELAY_MS);
125 		do {
126 			sampled_value = !read_gpio(rec_sw);
127 			if (!sampled_value)
128 				break;
129 		} while (!stopwatch_expired(&sw));
130 
131 		if (sampled_value) {
132 			saved_state = recovery_req;
133 			display_pattern(WWR_RECOVERY_REQUEST);
134 			printk(BIOS_INFO, "recovery requested\n");
135 		} else {
136 			saved_state = wipeout_req;
137 		}
138 	} else {
139 		saved_state = no_req;
140 		display_pattern(WWR_NORMAL_BOOT);
141 	}
142 
143 	return saved_state;
144 }
145 
get_recovery_mode_switch(void)146 int get_recovery_mode_switch(void)
147 {
148 	return get_switch_state() == recovery_req;
149 }
150 
get_wipeout_mode_switch(void)151 int get_wipeout_mode_switch(void)
152 {
153 	return get_switch_state() == wipeout_req;
154 }
155 
get_write_protect_state(void)156 int get_write_protect_state(void)
157 {
158 	return !read_gpio(get_wp_status_gpio_pin());
159 }
160 
get_ec_is_trusted(void)161 int get_ec_is_trusted(void)
162 {
163 	/* Do not have a Chrome EC involved in entering recovery mode;
164 	   Always return trusted. */
165 	return 1;
166 }
167