blob: 69f0fcca2be8d746e32819522a763c5eb2ffcc13 [file] [log] [blame]
Angel Pons7caffce2020-04-05 13:22:51 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Daisuke Nojiri81193e62014-11-12 14:44:13 -08002
Vadim Bendebury8a6e6352015-03-10 13:03:58 -07003#include <boardid.h>
Kyösti Mälkkif1226962021-11-03 17:19:31 +02004#include <bootmode.h>
Daisuke Nojiri81193e62014-11-12 14:44:13 -08005#include <boot/coreboot_tables.h>
6#include <console/console.h>
7#include <delay.h>
Vadim Bendebury8a6e6352015-03-10 13:03:58 -07008#include <drivers/i2c/ww_ring/ww_ring.h>
Daisuke Nojiri81193e62014-11-12 14:44:13 -08009#include <gpio.h>
Vadim Bendebury8a6e6352015-03-10 13:03:58 -070010#include <soc/cdp.h>
11#include <soc/gsbi.h>
Vadim Bendeburyf61809a2015-02-20 12:49:47 -080012#include <timer.h>
Daisuke Nojiri81193e62014-11-12 14:44:13 -080013
14#define DEV_SW 15
Daisuke Nojiri81193e62014-11-12 14:44:13 -080015#define REC_SW 16
Daisuke Nojiri81193e62014-11-12 14:44:13 -080016#define WP_SW 17
Daisuke Nojiri81193e62014-11-12 14:44:13 -080017
18static 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
26void fill_lb_gpios(struct lb_gpios *gpios)
27{
Julius Wernerc445b4f2016-03-31 17:27:05 -070028 struct lb_gpio chromeos_gpios[] = {
Matt Delco2cb39962019-04-30 14:59:43 -070029 {DEV_SW, ACTIVE_LOW, read_gpio(REC_SW), "presence"},
Julius Wernerc445b4f2016-03-31 17:27:05 -070030 {-1, ACTIVE_LOW, 1, "power"},
31 {-1, ACTIVE_LOW, 0, "lid"},
32 };
33 lb_add_gpios(gpios, chromeos_gpios, ARRAY_SIZE(chromeos_gpios));
Daisuke Nojiri81193e62014-11-12 14:44:13 -080034}
35
Vadim Bendeburyf61809a2015-02-20 12:49:47 -080036/*
Vadim Bendebury381785d2015-03-12 19:47:22 -070037 * 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.
Vadim Bendeburyf61809a2015-02-20 12:49:47 -080047 */
Vadim Bendebury381785d2015-03-12 19:47:22 -070048enum switch_state {
49 not_probed = -1,
50 no_req,
51 recovery_req,
52 wipeout_req
53};
54
Vadim Bendebury4e0de322015-03-17 15:37:54 -070055static 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
Vadim Bendebury381785d2015-03-12 19:47:22 -070061#define WIPEOUT_MODE_DELAY_MS (8 * 1000)
62#define RECOVERY_MODE_EXTRA_DELAY_MS (8 * 1000)
63
64static enum switch_state get_switch_state(void)
Daisuke Nojiri81193e62014-11-12 14:44:13 -080065{
Vadim Bendeburyf61809a2015-02-20 12:49:47 -080066 struct stopwatch sw;
Vadim Bendebury381785d2015-03-12 19:47:22 -070067 int sampled_value;
68 static enum switch_state saved_state = not_probed;
Vadim Bendeburyf61809a2015-02-20 12:49:47 -080069
Vadim Bendebury381785d2015-03-12 19:47:22 -070070 if (saved_state != not_probed)
71 return saved_state;
Vadim Bendeburyf61809a2015-02-20 12:49:47 -080072
Joel Kitchingae0fb762019-04-07 00:37:14 +080073 sampled_value = !read_gpio(REC_SW);
Vadim Bendebury381785d2015-03-12 19:47:22 -070074
75 if (!sampled_value) {
76 saved_state = no_req;
Vadim Bendebury6897f4e2015-04-13 16:32:45 -070077 display_pattern(WWR_NORMAL_BOOT);
Vadim Bendebury381785d2015-03-12 19:47:22 -070078 return saved_state;
79 }
Vadim Bendeburyf61809a2015-02-20 12:49:47 -080080
Vadim Bendebury4e0de322015-03-17 15:37:54 -070081 display_pattern(WWR_RECOVERY_PUSHED);
Vadim Bendeburyf61809a2015-02-20 12:49:47 -080082 printk(BIOS_INFO, "recovery button pressed\n");
Vadim Bendebury4e0de322015-03-17 15:37:54 -070083
Vadim Bendebury381785d2015-03-12 19:47:22 -070084 stopwatch_init_msecs_expire(&sw, WIPEOUT_MODE_DELAY_MS);
Vadim Bendeburyf61809a2015-02-20 12:49:47 -080085
86 do {
Joel Kitchingae0fb762019-04-07 00:37:14 +080087 sampled_value = !read_gpio(REC_SW);
Vadim Bendeburyf61809a2015-02-20 12:49:47 -080088 if (!sampled_value)
89 break;
90 } while (!stopwatch_expired(&sw));
91
Vadim Bendebury8a6e6352015-03-10 13:03:58 -070092 if (sampled_value) {
Vadim Bendebury4e0de322015-03-17 15:37:54 -070093 display_pattern(WWR_WIPEOUT_REQUEST);
Vadim Bendebury381785d2015-03-12 19:47:22 -070094 printk(BIOS_INFO, "wipeout requested, checking recovery\n");
95 stopwatch_init_msecs_expire(&sw, RECOVERY_MODE_EXTRA_DELAY_MS);
96 do {
Joel Kitchingae0fb762019-04-07 00:37:14 +080097 sampled_value = !read_gpio(REC_SW);
Vadim Bendebury381785d2015-03-12 19:47:22 -070098 if (!sampled_value)
99 break;
100 } while (!stopwatch_expired(&sw));
101
102 if (sampled_value) {
103 saved_state = recovery_req;
Vadim Bendebury4e0de322015-03-17 15:37:54 -0700104 display_pattern(WWR_RECOVERY_REQUEST);
Vadim Bendebury381785d2015-03-12 19:47:22 -0700105 printk(BIOS_INFO, "recovery requested\n");
106 } else {
107 saved_state = wipeout_req;
108 }
109 } else {
110 saved_state = no_req;
Vadim Bendebury6897f4e2015-04-13 16:32:45 -0700111 display_pattern(WWR_NORMAL_BOOT);
Vadim Bendebury8a6e6352015-03-10 13:03:58 -0700112 }
Vadim Bendebury381785d2015-03-12 19:47:22 -0700113
114 return saved_state;
115}
116
117int get_recovery_mode_switch(void)
118{
119 return get_switch_state() == recovery_req;
120}
121
122int get_wipeout_mode_switch(void)
123{
124 return get_switch_state() == wipeout_req;
Daisuke Nojiri81193e62014-11-12 14:44:13 -0800125}
126
127int get_write_protect_state(void)
128{
Joel Kitchingae0fb762019-04-07 00:37:14 +0800129 return !read_gpio(WP_SW);
Daisuke Nojiri81193e62014-11-12 14:44:13 -0800130}