blob: 2987e91d0639bdfe7eaeed77ea51b80d511286b6 [file] [log] [blame]
Angel Pons4d94ae42020-04-05 13:21:31 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Varadarajan Narayanan3bbd9012016-03-02 13:15:47 +05302
3#include <boardid.h>
Kyösti Mälkkif1226962021-11-03 17:19:31 +02004#include <bootmode.h>
Varadarajan Narayanan3bbd9012016-03-02 13:15:47 +05305#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>
Varadarajan Narayanan25967642016-03-08 15:02:56 +053011#include <soc/blsp.h>
Varadarajan Narayanan3bbd9012016-03-02 13:15:47 +053012#include <timer.h>
Varadarajan Narayanan3bbd9012016-03-02 13:15:47 +053013
Joel Kitching99625b02019-03-21 00:30:38 +080014#define PP_SW 41
Varadarajan Narayanan3bbd9012016-03-02 13:15:47 +053015
Kan Yan041bc762016-07-14 18:05:20 -070016static int get_rec_sw_gpio_pin(void)
17{
18 uint8_t board_rev = board_id();
Kan Yand1a00512016-07-28 18:55:26 -070019
Kan Yan041bc762016-07-14 18:05:20 -070020 switch (board_rev) {
Kan Yan08492f72016-07-21 10:51:47 -070021 case BOARD_ID_GALE_PROTO:
Kan Yan041bc762016-07-14 18:05:20 -070022 case BOARD_ID_GALE_EVT:
Kan Yand1a00512016-07-28 18:55:26 -070023 case BOARD_ID_GALE_EVT2_0:
24 case BOARD_ID_GALE_EVT2_1:
Kan Yan041bc762016-07-14 18:05:20 -070025 return 7;
26 case BOARD_ID_GALE_EVT3:
27 default:
28 return 57;
29 }
30}
31
32static int get_wp_status_gpio_pin(void)
33{
34 uint8_t board_rev = board_id();
35 switch (board_rev) {
Kan Yan08492f72016-07-21 10:51:47 -070036 case BOARD_ID_GALE_PROTO:
Kan Yan041bc762016-07-14 18:05:20 -070037 case BOARD_ID_GALE_EVT:
Kan Yand1a00512016-07-28 18:55:26 -070038 case BOARD_ID_GALE_EVT2_0:
39 case BOARD_ID_GALE_EVT2_1:
Kan Yan041bc762016-07-14 18:05:20 -070040 return 6;
41 case BOARD_ID_GALE_EVT3:
42 default:
43 return 53;
44 }
45}
Varadarajan Narayanan3bbd9012016-03-02 13:15:47 +053046static 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
54void fill_lb_gpios(struct lb_gpios *gpios)
55{
56 struct lb_gpio chromeos_gpios[] = {
Joel Kitchingae0fb762019-04-07 00:37:14 +080057 {PP_SW, ACTIVE_LOW, read_gpio(PP_SW), "presence"},
Varadarajan Narayanan3bbd9012016-03-02 13:15:47 +053058 {-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
Varadarajan Narayanan3bbd9012016-03-02 13:15:47 +053064/*
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 */
76enum switch_state {
77 not_probed = -1,
78 no_req,
79 recovery_req,
80 wipeout_req
81};
82
83static void display_pattern(int pattern)
84{
Suresh Rajashekara6e69bfd2016-05-18 17:48:33 -070085 ww_ring_display_pattern(BLSP_QUP_ID_3, pattern);
Varadarajan Narayanan3bbd9012016-03-02 13:15:47 +053086}
87
88#define WIPEOUT_MODE_DELAY_MS (8 * 1000)
89#define RECOVERY_MODE_EXTRA_DELAY_MS (8 * 1000)
90
91static enum switch_state get_switch_state(void)
92{
93 struct stopwatch sw;
94 int sampled_value;
Kan Yan041bc762016-07-14 18:05:20 -070095 uint8_t rec_sw;
Varadarajan Narayanan3bbd9012016-03-02 13:15:47 +053096 static enum switch_state saved_state = not_probed;
97
98 if (saved_state != not_probed)
99 return saved_state;
100
Kan Yan041bc762016-07-14 18:05:20 -0700101 rec_sw = get_rec_sw_gpio_pin();
Joel Kitchingae0fb762019-04-07 00:37:14 +0800102 sampled_value = !read_gpio(rec_sw);
Varadarajan Narayanan3bbd9012016-03-02 13:15:47 +0530103
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 {
Joel Kitchingae0fb762019-04-07 00:37:14 +0800116 sampled_value = !read_gpio(rec_sw);
Varadarajan Narayanan3bbd9012016-03-02 13:15:47 +0530117 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 {
Joel Kitchingae0fb762019-04-07 00:37:14 +0800126 sampled_value = !read_gpio(rec_sw);
Varadarajan Narayanan3bbd9012016-03-02 13:15:47 +0530127 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
146int get_recovery_mode_switch(void)
147{
148 return get_switch_state() == recovery_req;
149}
150
151int get_wipeout_mode_switch(void)
152{
153 return get_switch_state() == wipeout_req;
154}
155
156int get_write_protect_state(void)
157{
Joel Kitchingae0fb762019-04-07 00:37:14 +0800158 return !read_gpio(get_wp_status_gpio_pin());
Varadarajan Narayanan3bbd9012016-03-02 13:15:47 +0530159}