1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
/* Copyright 2022 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Track USER_PRES_L
*/
#include "extension.h"
#include "gpio.h"
#include "hooks.h"
#include "registers.h"
#include "scratch_reg1.h"
#include "timer.h"
static uint64_t last_press;
static uint8_t asserted;
/* Save the timestamp when DIOM4 is deasserted. */
void diom4_deasserted(enum gpio_signal unused)
{
if (!board_use_diom4())
return;
asserted = 1;
last_press = get_time().val;
}
void disable_user_pres(void)
{
asserted = 0;
gpio_set_wakepin(GPIO_DIOM4, 0);
/* Disable the pullup and input on DIOM4 */
GWRITE_FIELD(PINMUX, DIOM4_CTL, PU, 0);
GWRITE_FIELD(PINMUX, DIOM4_CTL, IE, 0);
gpio_disable_interrupt(GPIO_DIOM4);
}
void enable_user_pres(void)
{
/*
* The interrupt happens on the rising edge. Wake on the falling edge
* to ensure cr50 sees the rising edge interrupt.
*/
gpio_set_wakepin(GPIO_DIOM4, GPIO_HIB_WAKE_FALLING);
/*
* Some boards don't have an external pull up. Add an internal one to
* make sure the signal isn't floating.
* Enable the pullup and input on DIOM4
*/
GWRITE_FIELD(PINMUX, DIOM4_CTL, PU, 1);
GWRITE_FIELD(PINMUX, DIOM4_CTL, IE, 1);
/* Enable interrupts for user_pres_l detection */
gpio_enable_interrupt(GPIO_DIOM4);
}
/*
* Vendor command to for tracking USER_PRES_L
*
* This vendor command can be used to enable tracking USER_PRES_L on DIOM4 and
* get the time since DIOM4 was deasserted.
*
* checks:
* - batt_is_present - Factory reset can only be done if HW write protect is
* removed.
* - FWMP disables ccd - If FWMP has disabled ccd, then we can't bypass it with
* a factory reset.
* - CCD password is set - If there is a password, someone will have to use that
* to open ccd and enable ccd manually. A factory reset cannot be
* used to get around the password.
*/
static enum vendor_cmd_rc vc_user_pres(enum vendor_cmd_cc code,
void *buf,
size_t input_size,
size_t *response_size)
{
struct user_pres_response response;
uint8_t *buffer = buf;
*response_size = 0;
if (input_size == 1) {
uint8_t *cmd = buffer;
if (*cmd == USER_PRES_DISABLE) {
board_write_prop(BOARD_USE_DIOM4, 0);
disable_user_pres();
} else if (*cmd == USER_PRES_ENABLE) {
board_write_prop(BOARD_USE_DIOM4, 1);
enable_user_pres();
} else {
return VENDOR_RC_BOGUS_ARGS;
}
return VENDOR_RC_SUCCESS;
} else if (input_size) {
return VENDOR_RC_BOGUS_ARGS;
}
*response_size = sizeof(response);
response.state = board_use_diom4() ? USER_PRES_ENABLE :
USER_PRES_DISABLE;
if (board_use_diom4() && asserted) {
response.state |= USER_PRES_PRESSED;
response.last_press = get_time().val - last_press;
}
memcpy(buffer, &response, sizeof(response));
return VENDOR_RC_SUCCESS;
}
DECLARE_VENDOR_COMMAND(VENDOR_CC_USER_PRES, vc_user_pres);
/**
* Setup DIOM4 interrupts if the board uses them.
*/
static void init_user_pres(void)
{
if (!board_use_diom4()) {
disable_user_pres();
return;
}
enable_user_pres();
}
DECLARE_HOOK(HOOK_INIT, init_user_pres, HOOK_PRIO_DEFAULT);
|