Angel Pons | 210a008 | 2020-04-02 23:48:24 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 2 | |
| 3 | #include <stdint.h> |
Stefan Reinauer | aaaf689 | 2013-08-29 15:57:11 -0700 | [diff] [blame] | 4 | #include <string.h> |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 5 | #include <assert.h> |
Tim Wawrzynczak | e607829 | 2020-01-22 15:22:18 -0700 | [diff] [blame] | 6 | #include <console/console.h> |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 7 | #include <delay.h> |
Tim Wawrzynczak | e607829 | 2020-01-22 15:22:18 -0700 | [diff] [blame] | 8 | #include <device/device.h> |
| 9 | #include <device/path.h> |
Furquan Shaikh | bce8bb6 | 2016-11-11 13:57:55 -0800 | [diff] [blame] | 10 | #include <elog.h> |
Simon Glass | 7865932 | 2016-06-10 20:58:24 -0600 | [diff] [blame] | 11 | #include <rtc.h> |
Philipp Deppenwiese | fea2429 | 2017-10-17 17:02:29 +0200 | [diff] [blame] | 12 | #include <security/vboot/vboot_common.h> |
Tim Wawrzynczak | e607829 | 2020-01-22 15:22:18 -0700 | [diff] [blame] | 13 | #include <stdlib.h> |
Daisuke Nojiri | ebb86be | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 14 | #include <timer.h> |
Edward O'Callaghan | b57fef9 | 2014-06-17 20:13:08 +1000 | [diff] [blame] | 15 | |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 16 | #include "ec.h" |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 17 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 18 | #define CROS_EC_COMMAND_INFO const void |
| 19 | #define CROS_EC_COMMAND(h, c, v, p, ps, r, rs) \ |
| 20 | google_chromeec_command(&(struct chromeec_command) { \ |
| 21 | .cmd_code = (c), \ |
| 22 | .cmd_version = (v), \ |
| 23 | .cmd_data_in = (p), \ |
| 24 | .cmd_size_in = (ps), \ |
| 25 | .cmd_data_out = (r), \ |
| 26 | .cmd_size_out = (rs), \ |
| 27 | .cmd_dev_index = 0, \ |
| 28 | }) |
| 29 | |
| 30 | #include "ec_cmd_api.h" |
| 31 | |
| 32 | /* |
| 33 | * coreboot only supports a single platform EC, so there is no need to |
| 34 | * provide a context handle for the EC. |
| 35 | */ |
| 36 | #define PLAT_EC NULL |
| 37 | |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 38 | #define INVALID_HCMD 0xFF |
| 39 | |
| 40 | /* |
| 41 | * Map UHEPI masks to non UHEPI commands in order to support old EC FW |
| 42 | * which does not support UHEPI command. |
| 43 | */ |
| 44 | static const struct { |
| 45 | uint8_t set_cmd; |
| 46 | uint8_t clear_cmd; |
| 47 | uint8_t get_cmd; |
| 48 | } event_map[] = { |
| 49 | [EC_HOST_EVENT_MAIN] = { |
| 50 | INVALID_HCMD, EC_CMD_HOST_EVENT_CLEAR, |
| 51 | INVALID_HCMD, |
| 52 | }, |
| 53 | [EC_HOST_EVENT_B] = { |
| 54 | INVALID_HCMD, EC_CMD_HOST_EVENT_CLEAR_B, |
| 55 | EC_CMD_HOST_EVENT_GET_B, |
| 56 | }, |
| 57 | [EC_HOST_EVENT_SCI_MASK] = { |
| 58 | EC_CMD_HOST_EVENT_SET_SCI_MASK, INVALID_HCMD, |
| 59 | EC_CMD_HOST_EVENT_GET_SCI_MASK, |
| 60 | }, |
| 61 | [EC_HOST_EVENT_SMI_MASK] = { |
| 62 | EC_CMD_HOST_EVENT_SET_SMI_MASK, INVALID_HCMD, |
| 63 | EC_CMD_HOST_EVENT_GET_SMI_MASK, |
| 64 | }, |
| 65 | [EC_HOST_EVENT_ALWAYS_REPORT_MASK] = { |
| 66 | INVALID_HCMD, INVALID_HCMD, INVALID_HCMD, |
| 67 | }, |
| 68 | [EC_HOST_EVENT_ACTIVE_WAKE_MASK] = { |
| 69 | EC_CMD_HOST_EVENT_SET_WAKE_MASK, INVALID_HCMD, |
| 70 | EC_CMD_HOST_EVENT_GET_WAKE_MASK, |
| 71 | }, |
Patrick Georgi | a29d234 | 2018-05-02 17:12:49 +0200 | [diff] [blame] | 72 | [EC_HOST_EVENT_LAZY_WAKE_MASK_S0IX] = { |
| 73 | EC_CMD_HOST_EVENT_SET_WAKE_MASK, INVALID_HCMD, |
| 74 | EC_CMD_HOST_EVENT_GET_WAKE_MASK, |
| 75 | }, |
| 76 | [EC_HOST_EVENT_LAZY_WAKE_MASK_S3] = { |
| 77 | EC_CMD_HOST_EVENT_SET_WAKE_MASK, INVALID_HCMD, |
| 78 | EC_CMD_HOST_EVENT_GET_WAKE_MASK, |
| 79 | }, |
| 80 | [EC_HOST_EVENT_LAZY_WAKE_MASK_S5] = { |
| 81 | EC_CMD_HOST_EVENT_SET_WAKE_MASK, INVALID_HCMD, |
| 82 | EC_CMD_HOST_EVENT_GET_WAKE_MASK, |
| 83 | }, |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 84 | }; |
| 85 | |
Hung-Te Lin | 6bfbb33 | 2013-04-15 18:27:24 +0800 | [diff] [blame] | 86 | uint8_t google_chromeec_calc_checksum(const uint8_t *data, int size) |
| 87 | { |
| 88 | int csum; |
| 89 | |
| 90 | for (csum = 0; size > 0; data++, size--) |
| 91 | csum += *data; |
| 92 | return (uint8_t)(csum & 0xff); |
| 93 | } |
| 94 | |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 95 | int google_chromeec_kbbacklight(int percent) |
| 96 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 97 | const struct ec_params_pwm_set_keyboard_backlight params = { |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 98 | .percent = percent % 101, |
| 99 | }; |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 100 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 101 | if (ec_cmd_pwm_set_keyboard_backlight(PLAT_EC, ¶ms) != 0) |
Caveh Jalali | 2320c03 | 2022-11-02 19:55:39 -0700 | [diff] [blame] | 102 | return -1; |
| 103 | |
| 104 | return 0; |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 105 | } |
| 106 | |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 107 | void google_chromeec_post(uint8_t postcode) |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 108 | { |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 109 | /* backlight is a percent. postcode is a uint8_t. |
| 110 | * Convert the uint8_t to %. |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 111 | */ |
| 112 | postcode = (postcode/4) + (postcode/8); |
| 113 | google_chromeec_kbbacklight(postcode); |
| 114 | } |
| 115 | |
| 116 | /* |
| 117 | * Query the EC for specified mask indicating enabled events. |
| 118 | * The EC maintains separate event masks for SMI, SCI and WAKE. |
| 119 | */ |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 120 | static int google_chromeec_uhepi_cmd(uint8_t mask, uint8_t action, |
| 121 | uint64_t *value) |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 122 | { |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 123 | int ret; |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 124 | struct ec_params_host_event params = { |
| 125 | .action = action, |
| 126 | .mask_type = mask, |
| 127 | }; |
| 128 | struct ec_response_host_event resp = {}; |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 129 | |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 130 | if (action != EC_HOST_EVENT_GET) |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 131 | params.value = *value; |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 132 | else |
| 133 | *value = 0; |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 134 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 135 | ret = ec_cmd_host_event(PLAT_EC, ¶ms, &resp); |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 136 | |
| 137 | if (action != EC_HOST_EVENT_GET) |
| 138 | return ret; |
| 139 | if (ret == 0) |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 140 | *value = resp.value; |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 141 | return ret; |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 142 | } |
| 143 | |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 144 | static int google_chromeec_handle_non_uhepi_cmd(uint8_t hcmd, uint8_t action, |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 145 | uint64_t *value) |
Sheng-Liang Song | 1d6560f | 2014-04-30 15:46:45 -0700 | [diff] [blame] | 146 | { |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 147 | int ret = -1; |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 148 | struct ec_params_host_event_mask params = {}; |
| 149 | struct ec_response_host_event_mask resp = {}; |
| 150 | struct chromeec_command cmd = { |
| 151 | .cmd_code = hcmd, |
| 152 | .cmd_version = 0, |
| 153 | .cmd_data_in = ¶ms, |
| 154 | .cmd_size_in = sizeof(params), |
| 155 | .cmd_data_out = &resp, |
| 156 | .cmd_size_out = sizeof(resp), |
| 157 | .cmd_dev_index = 0, |
| 158 | }; |
Sheng-Liang Song | 1d6560f | 2014-04-30 15:46:45 -0700 | [diff] [blame] | 159 | |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 160 | if (hcmd == INVALID_HCMD) |
| 161 | return ret; |
| 162 | |
| 163 | if (action != EC_HOST_EVENT_GET) |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 164 | params.mask = (uint32_t)*value; |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 165 | else |
| 166 | *value = 0; |
| 167 | |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 168 | ret = google_chromeec_command(&cmd); |
| 169 | |
| 170 | if (action != EC_HOST_EVENT_GET) |
| 171 | return ret; |
| 172 | if (ret == 0) |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 173 | *value = resp.mask; |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 174 | |
| 175 | return ret; |
| 176 | } |
| 177 | |
| 178 | bool google_chromeec_is_uhepi_supported(void) |
| 179 | { |
| 180 | #define UHEPI_SUPPORTED 1 |
| 181 | #define UHEPI_NOT_SUPPORTED 2 |
| 182 | |
Arthur Heymans | 95b3f28 | 2019-11-20 21:23:16 +0100 | [diff] [blame] | 183 | static int uhepi_support; |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 184 | |
| 185 | if (!uhepi_support) { |
| 186 | uhepi_support = google_chromeec_check_feature |
Matt DeVillier | 4132893 | 2018-03-04 00:05:12 -0600 | [diff] [blame] | 187 | (EC_FEATURE_UNIFIED_WAKE_MASKS) > 0 ? UHEPI_SUPPORTED : |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 188 | UHEPI_NOT_SUPPORTED; |
| 189 | printk(BIOS_DEBUG, "Chrome EC: UHEPI %s\n", |
| 190 | uhepi_support == UHEPI_SUPPORTED ? |
| 191 | "supported" : "not supported"); |
| 192 | } |
| 193 | return uhepi_support == UHEPI_SUPPORTED; |
| 194 | } |
| 195 | |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 196 | static uint64_t google_chromeec_get_mask(uint8_t type) |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 197 | { |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 198 | uint64_t value = 0; |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 199 | |
| 200 | if (google_chromeec_is_uhepi_supported()) { |
| 201 | google_chromeec_uhepi_cmd(type, EC_HOST_EVENT_GET, &value); |
| 202 | } else { |
| 203 | assert(type < ARRAY_SIZE(event_map)); |
| 204 | google_chromeec_handle_non_uhepi_cmd( |
| 205 | event_map[type].get_cmd, |
| 206 | EC_HOST_EVENT_GET, &value); |
| 207 | } |
| 208 | return value; |
| 209 | } |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 210 | |
| 211 | static int google_chromeec_clear_mask(uint8_t type, uint64_t mask) |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 212 | { |
| 213 | if (google_chromeec_is_uhepi_supported()) |
| 214 | return google_chromeec_uhepi_cmd(type, |
| 215 | EC_HOST_EVENT_CLEAR, &mask); |
| 216 | |
| 217 | assert(type < ARRAY_SIZE(event_map)); |
| 218 | return google_chromeec_handle_non_uhepi_cmd( |
| 219 | event_map[type].clear_cmd, |
| 220 | EC_HOST_EVENT_CLEAR, &mask); |
| 221 | } |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 222 | |
Bill XIE | ac136250 | 2022-07-08 16:53:21 +0800 | [diff] [blame] | 223 | static int google_chromeec_set_mask(uint8_t type, uint64_t mask) |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 224 | { |
| 225 | if (google_chromeec_is_uhepi_supported()) |
| 226 | return google_chromeec_uhepi_cmd(type, |
| 227 | EC_HOST_EVENT_SET, &mask); |
| 228 | |
| 229 | assert(type < ARRAY_SIZE(event_map)); |
| 230 | return google_chromeec_handle_non_uhepi_cmd( |
| 231 | event_map[type].set_cmd, |
| 232 | EC_HOST_EVENT_SET, &mask); |
| 233 | } |
| 234 | |
| 235 | static int google_chromeec_set_s3_lazy_wake_mask(uint64_t mask) |
| 236 | { |
Furquan Shaikh | 8389fe6 | 2018-02-23 16:07:25 -0800 | [diff] [blame] | 237 | printk(BIOS_DEBUG, "Chrome EC: Set S3 LAZY WAKE mask to 0x%016llx\n", |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 238 | mask); |
| 239 | return google_chromeec_set_mask |
| 240 | (EC_HOST_EVENT_LAZY_WAKE_MASK_S3, mask); |
| 241 | } |
| 242 | |
| 243 | static int google_chromeec_set_s5_lazy_wake_mask(uint64_t mask) |
| 244 | { |
Furquan Shaikh | 8389fe6 | 2018-02-23 16:07:25 -0800 | [diff] [blame] | 245 | printk(BIOS_DEBUG, "Chrome EC: Set S5 LAZY WAKE mask to 0x%016llx\n", |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 246 | mask); |
| 247 | return google_chromeec_set_mask |
| 248 | (EC_HOST_EVENT_LAZY_WAKE_MASK_S5, mask); |
| 249 | } |
| 250 | |
| 251 | static int google_chromeec_set_s0ix_lazy_wake_mask(uint64_t mask) |
| 252 | { |
Furquan Shaikh | 8389fe6 | 2018-02-23 16:07:25 -0800 | [diff] [blame] | 253 | printk(BIOS_DEBUG, "Chrome EC: Set S0iX LAZY WAKE mask to 0x%016llx\n", |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 254 | mask); |
| 255 | return google_chromeec_set_mask |
| 256 | (EC_HOST_EVENT_LAZY_WAKE_MASK_S0IX, mask); |
| 257 | } |
| 258 | static void google_chromeec_set_lazy_wake_masks(uint64_t s5_mask, |
| 259 | uint64_t s3_mask, uint64_t s0ix_mask) |
| 260 | { |
| 261 | if (google_chromeec_set_s5_lazy_wake_mask(s5_mask)) |
| 262 | printk(BIOS_DEBUG, "Error: Set S5 LAZY WAKE mask failed\n"); |
| 263 | if (google_chromeec_set_s3_lazy_wake_mask(s3_mask)) |
| 264 | printk(BIOS_DEBUG, "Error: Set S3 LAZY WAKE mask failed\n"); |
Paul Moy | 88900dc | 2018-09-14 15:24:23 -0600 | [diff] [blame] | 265 | /* |
| 266 | * Make sure S0Ix is supported before trying to set up the EC's |
| 267 | * S0Ix lazy wake mask. |
| 268 | */ |
| 269 | if (s0ix_mask && google_chromeec_set_s0ix_lazy_wake_mask(s0ix_mask)) |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 270 | printk(BIOS_DEBUG, "Error: Set S0iX LAZY WAKE mask failed\n"); |
Sheng-Liang Song | 1d6560f | 2014-04-30 15:46:45 -0700 | [diff] [blame] | 271 | } |
| 272 | |
Furquan Shaikh | 8788fd6 | 2017-11-20 20:28:18 -0800 | [diff] [blame] | 273 | uint64_t google_chromeec_get_events_b(void) |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 274 | { |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 275 | return google_chromeec_get_mask(EC_HOST_EVENT_B); |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 276 | } |
| 277 | |
Furquan Shaikh | 8788fd6 | 2017-11-20 20:28:18 -0800 | [diff] [blame] | 278 | int google_chromeec_clear_events_b(uint64_t mask) |
Sheng-Liang Song | 1d6560f | 2014-04-30 15:46:45 -0700 | [diff] [blame] | 279 | { |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 280 | printk(BIOS_DEBUG, |
| 281 | "Chrome EC: clear events_b mask to 0x%016llx\n", mask); |
| 282 | return google_chromeec_clear_mask(EC_HOST_EVENT_B, mask); |
Sheng-Liang Song | 1d6560f | 2014-04-30 15:46:45 -0700 | [diff] [blame] | 283 | } |
| 284 | |
Furquan Shaikh | e01bf64 | 2017-10-13 10:59:51 -0700 | [diff] [blame] | 285 | int google_chromeec_get_mkbp_event(struct ec_response_get_next_event *event) |
| 286 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 287 | return ec_cmd_get_next_event(PLAT_EC, event); |
Furquan Shaikh | e01bf64 | 2017-10-13 10:59:51 -0700 | [diff] [blame] | 288 | } |
| 289 | |
Duncan Laurie | 7378a17 | 2017-06-29 23:52:17 -0700 | [diff] [blame] | 290 | /* Get the current device event mask */ |
Furquan Shaikh | 8788fd6 | 2017-11-20 20:28:18 -0800 | [diff] [blame] | 291 | uint64_t google_chromeec_get_device_enabled_events(void) |
Duncan Laurie | 7378a17 | 2017-06-29 23:52:17 -0700 | [diff] [blame] | 292 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 293 | const struct ec_params_device_event params = { |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 294 | .param = EC_DEVICE_EVENT_PARAM_GET_ENABLED_EVENTS, |
| 295 | }; |
| 296 | struct ec_response_device_event resp = {}; |
Duncan Laurie | 7378a17 | 2017-06-29 23:52:17 -0700 | [diff] [blame] | 297 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 298 | if (ec_cmd_device_event(PLAT_EC, ¶ms, &resp) == 0) |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 299 | return resp.event_mask; |
| 300 | |
Duncan Laurie | 7378a17 | 2017-06-29 23:52:17 -0700 | [diff] [blame] | 301 | return 0; |
| 302 | } |
| 303 | |
| 304 | /* Set the current device event mask */ |
Furquan Shaikh | 8788fd6 | 2017-11-20 20:28:18 -0800 | [diff] [blame] | 305 | int google_chromeec_set_device_enabled_events(uint64_t mask) |
Duncan Laurie | 7378a17 | 2017-06-29 23:52:17 -0700 | [diff] [blame] | 306 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 307 | const struct ec_params_device_event params = { |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 308 | .event_mask = (uint32_t)mask, |
| 309 | .param = EC_DEVICE_EVENT_PARAM_SET_ENABLED_EVENTS, |
| 310 | }; |
| 311 | struct ec_response_device_event resp = {}; |
Duncan Laurie | 7378a17 | 2017-06-29 23:52:17 -0700 | [diff] [blame] | 312 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 313 | return ec_cmd_device_event(PLAT_EC, ¶ms, &resp); |
Duncan Laurie | 7378a17 | 2017-06-29 23:52:17 -0700 | [diff] [blame] | 314 | } |
| 315 | |
| 316 | /* Read and clear pending device events */ |
Furquan Shaikh | 8788fd6 | 2017-11-20 20:28:18 -0800 | [diff] [blame] | 317 | uint64_t google_chromeec_get_device_current_events(void) |
Duncan Laurie | 7378a17 | 2017-06-29 23:52:17 -0700 | [diff] [blame] | 318 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 319 | const struct ec_params_device_event params = { |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 320 | .param = EC_DEVICE_EVENT_PARAM_GET_CURRENT_EVENTS, |
| 321 | }; |
| 322 | struct ec_response_device_event resp = {}; |
Duncan Laurie | 7378a17 | 2017-06-29 23:52:17 -0700 | [diff] [blame] | 323 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 324 | if (ec_cmd_device_event(PLAT_EC, ¶ms, &resp) == 0) |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 325 | return resp.event_mask; |
| 326 | |
Duncan Laurie | 7378a17 | 2017-06-29 23:52:17 -0700 | [diff] [blame] | 327 | return 0; |
| 328 | } |
| 329 | |
Furquan Shaikh | 8788fd6 | 2017-11-20 20:28:18 -0800 | [diff] [blame] | 330 | static void google_chromeec_log_device_events(uint64_t mask) |
Duncan Laurie | 7378a17 | 2017-06-29 23:52:17 -0700 | [diff] [blame] | 331 | { |
Furquan Shaikh | 8788fd6 | 2017-11-20 20:28:18 -0800 | [diff] [blame] | 332 | uint64_t events; |
Duncan Laurie | 7378a17 | 2017-06-29 23:52:17 -0700 | [diff] [blame] | 333 | int i; |
| 334 | |
Julius Werner | cd49cce | 2019-03-05 16:53:33 -0800 | [diff] [blame] | 335 | if (!CONFIG(ELOG) || !mask) |
Duncan Laurie | 7378a17 | 2017-06-29 23:52:17 -0700 | [diff] [blame] | 336 | return; |
| 337 | |
| 338 | if (google_chromeec_check_feature(EC_FEATURE_DEVICE_EVENT) != 1) |
| 339 | return; |
| 340 | |
| 341 | events = google_chromeec_get_device_current_events() & mask; |
Furquan Shaikh | 8788fd6 | 2017-11-20 20:28:18 -0800 | [diff] [blame] | 342 | printk(BIOS_INFO, "EC Device Events: 0x%016llx\n", events); |
Duncan Laurie | 7378a17 | 2017-06-29 23:52:17 -0700 | [diff] [blame] | 343 | |
| 344 | for (i = 0; i < sizeof(events) * 8; i++) { |
| 345 | if (EC_DEVICE_EVENT_MASK(i) & events) |
| 346 | elog_add_event_byte(ELOG_TYPE_EC_DEVICE_EVENT, i); |
| 347 | } |
| 348 | } |
| 349 | |
Furquan Shaikh | 8788fd6 | 2017-11-20 20:28:18 -0800 | [diff] [blame] | 350 | void google_chromeec_log_events(uint64_t mask) |
Furquan Shaikh | 2749c52 | 2017-10-04 14:01:41 -0700 | [diff] [blame] | 351 | { |
Ravi Chandra Sadineni | 6ae8b50 | 2019-06-18 10:10:19 -0700 | [diff] [blame] | 352 | uint64_t events; |
| 353 | int i; |
Furquan Shaikh | 2749c52 | 2017-10-04 14:01:41 -0700 | [diff] [blame] | 354 | |
Julius Werner | cd49cce | 2019-03-05 16:53:33 -0800 | [diff] [blame] | 355 | if (!CONFIG(ELOG)) |
Furquan Shaikh | 2749c52 | 2017-10-04 14:01:41 -0700 | [diff] [blame] | 356 | return; |
| 357 | |
Ravi Chandra Sadineni | 6ae8b50 | 2019-06-18 10:10:19 -0700 | [diff] [blame] | 358 | events = google_chromeec_get_events_b() & mask; |
Tim Wawrzynczak | 7777e1c | 2020-07-14 13:30:46 -0600 | [diff] [blame] | 359 | |
| 360 | /* |
| 361 | * This loop starts at 1 because the EC_HOST_EVENT_MASK macro subtracts |
| 362 | * 1 from its argument before applying the left-shift operator. This |
| 363 | * prevents a left-shift of -1 happening, and covers the entire 64-bit |
| 364 | * range of the event mask. |
| 365 | */ |
| 366 | for (i = 1; i <= sizeof(events) * 8; i++) { |
Ravi Chandra Sadineni | 6ae8b50 | 2019-06-18 10:10:19 -0700 | [diff] [blame] | 367 | if (EC_HOST_EVENT_MASK(i) & events) |
| 368 | elog_add_event_byte(ELOG_TYPE_EC_EVENT, i); |
Furquan Shaikh | 1432cbc | 2017-10-13 11:31:35 -0700 | [diff] [blame] | 369 | } |
Furquan Shaikh | 2749c52 | 2017-10-04 14:01:41 -0700 | [diff] [blame] | 370 | |
Ravi Chandra Sadineni | 6ae8b50 | 2019-06-18 10:10:19 -0700 | [diff] [blame] | 371 | google_chromeec_clear_events_b(events); |
Furquan Shaikh | 2749c52 | 2017-10-04 14:01:41 -0700 | [diff] [blame] | 372 | } |
| 373 | |
| 374 | void google_chromeec_events_init(const struct google_chromeec_event_info *info, |
| 375 | bool is_s3_wakeup) |
| 376 | { |
| 377 | if (is_s3_wakeup) { |
| 378 | google_chromeec_log_events(info->log_events | |
| 379 | info->s3_wake_events); |
| 380 | |
| 381 | /* Log and clear device events that may wake the system. */ |
| 382 | google_chromeec_log_device_events(info->s3_device_events); |
| 383 | |
| 384 | /* Disable SMI and wake events. */ |
| 385 | google_chromeec_set_smi_mask(0); |
| 386 | |
Furquan Shaikh | 2749c52 | 2017-10-04 14:01:41 -0700 | [diff] [blame] | 387 | /* Restore SCI event mask. */ |
| 388 | google_chromeec_set_sci_mask(info->sci_events); |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 389 | |
| 390 | } else { |
Furquan Shaikh | 1a5b7c6 | 2018-05-30 11:51:23 -0700 | [diff] [blame] | 391 | google_chromeec_set_smi_mask(info->smi_events); |
| 392 | |
Furquan Shaikh | 2749c52 | 2017-10-04 14:01:41 -0700 | [diff] [blame] | 393 | google_chromeec_log_events(info->log_events | |
| 394 | info->s5_wake_events); |
Furquan Shaikh | 1a5b7c6 | 2018-05-30 11:51:23 -0700 | [diff] [blame] | 395 | |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 396 | if (google_chromeec_is_uhepi_supported()) |
| 397 | google_chromeec_set_lazy_wake_masks |
| 398 | (info->s5_wake_events, |
| 399 | info->s3_wake_events, |
| 400 | info->s0ix_wake_events); |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 401 | } |
Furquan Shaikh | 2749c52 | 2017-10-04 14:01:41 -0700 | [diff] [blame] | 402 | |
| 403 | /* Clear wake event mask. */ |
| 404 | google_chromeec_set_wake_mask(0); |
| 405 | } |
| 406 | |
Duncan Laurie | e2cea4f | 2015-12-01 19:14:09 -0800 | [diff] [blame] | 407 | int google_chromeec_check_feature(int feature) |
| 408 | { |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 409 | struct ec_response_get_features resp = {}; |
Duncan Laurie | e2cea4f | 2015-12-01 19:14:09 -0800 | [diff] [blame] | 410 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 411 | if (ec_cmd_get_features(PLAT_EC, &resp) != 0) |
Duncan Laurie | e2cea4f | 2015-12-01 19:14:09 -0800 | [diff] [blame] | 412 | return -1; |
| 413 | |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 414 | if (feature >= 8 * sizeof(resp.flags)) |
Duncan Laurie | e2cea4f | 2015-12-01 19:14:09 -0800 | [diff] [blame] | 415 | return -1; |
| 416 | |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 417 | return resp.flags[feature / 32] & EC_FEATURE_MASK_0(feature); |
Duncan Laurie | e2cea4f | 2015-12-01 19:14:09 -0800 | [diff] [blame] | 418 | } |
| 419 | |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 420 | int google_chromeec_get_cmd_versions(int command, uint32_t *pmask) |
| 421 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 422 | const struct ec_params_get_cmd_versions_v1 params = { |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 423 | .cmd = command, |
| 424 | }; |
| 425 | struct ec_response_get_cmd_versions resp = {}; |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 426 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 427 | if (ec_cmd_get_cmd_versions_v1(PLAT_EC, ¶ms, &resp) != 0) |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 428 | return -1; |
| 429 | |
| 430 | *pmask = resp.version_mask; |
| 431 | return 0; |
| 432 | } |
| 433 | |
| 434 | int google_chromeec_get_vboot_hash(uint32_t offset, |
| 435 | struct ec_response_vboot_hash *resp) |
| 436 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 437 | const struct ec_params_vboot_hash params = { |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 438 | .cmd = EC_VBOOT_HASH_GET, |
| 439 | .offset = offset, |
| 440 | }; |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 441 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 442 | if (ec_cmd_vboot_hash(PLAT_EC, ¶ms, resp) != 0) |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 443 | return -1; |
| 444 | |
| 445 | return 0; |
| 446 | } |
| 447 | |
| 448 | int google_chromeec_start_vboot_hash(enum ec_vboot_hash_type hash_type, |
| 449 | uint32_t hash_offset, |
| 450 | struct ec_response_vboot_hash *resp) |
| 451 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 452 | const struct ec_params_vboot_hash params = { |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 453 | .cmd = EC_VBOOT_HASH_START, |
| 454 | .hash_type = hash_type, |
| 455 | .nonce_size = 0, |
| 456 | .offset = hash_offset, |
| 457 | }; |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 458 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 459 | if (ec_cmd_vboot_hash(PLAT_EC, ¶ms, resp) != 0) |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 460 | return -1; |
| 461 | |
| 462 | return 0; |
| 463 | } |
| 464 | |
| 465 | int google_chromeec_flash_protect(uint32_t mask, uint32_t flags, |
| 466 | struct ec_response_flash_protect *resp) |
| 467 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 468 | const struct ec_params_flash_protect params = { |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 469 | .mask = mask, |
| 470 | .flags = flags, |
| 471 | }; |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 472 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 473 | if (ec_cmd_flash_protect_v1(PLAT_EC, ¶ms, resp) != 0) |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 474 | return -1; |
| 475 | |
| 476 | return 0; |
| 477 | } |
| 478 | |
| 479 | int google_chromeec_flash_region_info(enum ec_flash_region region, |
| 480 | uint32_t *offset, uint32_t *size) |
| 481 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 482 | const struct ec_params_flash_region_info params = { |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 483 | .region = region, |
| 484 | }; |
| 485 | struct ec_response_flash_region_info resp = {}; |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 486 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 487 | if (ec_cmd_flash_region_info_v1(PLAT_EC, ¶ms, &resp) != 0) |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 488 | return -1; |
| 489 | |
| 490 | if (offset) |
| 491 | *offset = resp.offset; |
| 492 | if (size) |
| 493 | *size = resp.size; |
| 494 | |
| 495 | return 0; |
| 496 | } |
| 497 | |
| 498 | int google_chromeec_flash_erase(uint32_t offset, uint32_t size) |
| 499 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 500 | const struct ec_params_flash_erase params = { |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 501 | .offset = offset, |
| 502 | .size = size, |
| 503 | }; |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 504 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 505 | if (ec_cmd_flash_erase(PLAT_EC, ¶ms) != 0) |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 506 | return -1; |
| 507 | |
| 508 | return 0; |
| 509 | } |
| 510 | |
| 511 | int google_chromeec_flash_info(struct ec_response_flash_info *info) |
| 512 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 513 | if (ec_cmd_flash_info(PLAT_EC, info) != 0) |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 514 | return -1; |
| 515 | |
| 516 | return 0; |
| 517 | } |
| 518 | |
| 519 | /* |
| 520 | * Write a block into EC flash. Expects params_data to be a buffer where |
| 521 | * the first N bytes are a struct ec_params_flash_write, and the rest of it |
| 522 | * is the data to write to flash. |
| 523 | */ |
| 524 | int google_chromeec_flash_write_block(const uint8_t *params_data, |
| 525 | uint32_t bufsize) |
| 526 | { |
| 527 | struct chromeec_command cmd = { |
| 528 | .cmd_code = EC_CMD_FLASH_WRITE, |
| 529 | .cmd_version = EC_VER_FLASH_WRITE, |
| 530 | .cmd_size_out = 0, |
| 531 | .cmd_data_out = NULL, |
| 532 | .cmd_size_in = bufsize, |
| 533 | .cmd_data_in = params_data, |
| 534 | .cmd_dev_index = 0, |
| 535 | }; |
| 536 | |
| 537 | assert(params_data); |
| 538 | |
| 539 | return google_chromeec_command(&cmd); |
| 540 | } |
| 541 | |
| 542 | /* |
| 543 | * EFS verification of flash. |
| 544 | */ |
| 545 | int google_chromeec_efs_verify(enum ec_flash_region region) |
| 546 | { |
| 547 | struct ec_params_efs_verify params = { |
| 548 | .region = region, |
| 549 | }; |
| 550 | struct chromeec_command cmd = { |
| 551 | .cmd_code = EC_CMD_EFS_VERIFY, |
| 552 | .cmd_version = 0, |
| 553 | .cmd_size_in = sizeof(params), |
| 554 | .cmd_data_in = ¶ms, |
| 555 | .cmd_size_out = 0, |
| 556 | .cmd_data_out = NULL, |
| 557 | .cmd_dev_index = 0, |
| 558 | }; |
| 559 | int rv; |
| 560 | |
| 561 | /* It's okay if the EC doesn't support EFS */ |
| 562 | rv = google_chromeec_command(&cmd); |
| 563 | if (rv != 0 && (cmd.cmd_code == EC_RES_INVALID_COMMAND)) |
| 564 | return 0; |
| 565 | else if (rv != 0) |
| 566 | return -1; |
| 567 | |
| 568 | return 0; |
| 569 | } |
| 570 | |
| 571 | int google_chromeec_battery_cutoff(uint8_t flags) |
| 572 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 573 | const struct ec_params_battery_cutoff params = { |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 574 | .flags = flags, |
| 575 | }; |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 576 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 577 | if (ec_cmd_battery_cut_off_v1(PLAT_EC, ¶ms) != 0) |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 578 | return -1; |
| 579 | |
| 580 | return 0; |
| 581 | } |
| 582 | |
| 583 | int google_chromeec_read_limit_power_request(int *limit_power) |
| 584 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 585 | const struct ec_params_charge_state params = { |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 586 | .cmd = CHARGE_STATE_CMD_GET_PARAM, |
| 587 | .get_param.param = CS_PARAM_LIMIT_POWER, |
| 588 | }; |
| 589 | struct ec_response_charge_state resp = {}; |
| 590 | struct chromeec_command cmd = { |
| 591 | .cmd_code = EC_CMD_CHARGE_STATE, |
| 592 | .cmd_version = 0, |
| 593 | .cmd_size_in = sizeof(params), |
| 594 | .cmd_data_in = ¶ms, |
| 595 | .cmd_size_out = sizeof(resp), |
| 596 | .cmd_data_out = &resp, |
| 597 | .cmd_dev_index = 0, |
| 598 | }; |
Tim Wawrzynczak | 0d9fb55 | 2019-12-25 19:14:30 +1100 | [diff] [blame] | 599 | int rv; |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 600 | |
Tim Wawrzynczak | 0d9fb55 | 2019-12-25 19:14:30 +1100 | [diff] [blame] | 601 | rv = google_chromeec_command(&cmd); |
Rizwan Qureshi | cf42578 | 2019-12-27 21:41:07 +0530 | [diff] [blame] | 602 | |
| 603 | if (rv != 0 && (cmd.cmd_code == EC_RES_INVALID_COMMAND || |
| 604 | cmd.cmd_code == EC_RES_INVALID_PARAM)) { |
Tim Wawrzynczak | 0d9fb55 | 2019-12-25 19:14:30 +1100 | [diff] [blame] | 605 | printk(BIOS_INFO, "PARAM_LIMIT_POWER not supported by EC.\n"); |
| 606 | *limit_power = 0; |
| 607 | return 0; |
Rizwan Qureshi | cf42578 | 2019-12-27 21:41:07 +0530 | [diff] [blame] | 608 | } else if (rv != 0) { |
| 609 | return -1; |
Tim Wawrzynczak | 0d9fb55 | 2019-12-25 19:14:30 +1100 | [diff] [blame] | 610 | } |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 611 | |
| 612 | *limit_power = resp.get_param.value; |
Rizwan Qureshi | cf42578 | 2019-12-27 21:41:07 +0530 | [diff] [blame] | 613 | |
| 614 | return 0; |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 615 | } |
| 616 | |
| 617 | int google_chromeec_get_protocol_info( |
| 618 | struct ec_response_get_protocol_info *resp) |
| 619 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 620 | if (ec_cmd_get_protocol_info(PLAT_EC, resp)) |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 621 | return -1; |
| 622 | |
| 623 | return 0; |
| 624 | } |
| 625 | |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 626 | int google_chromeec_set_sku_id(uint32_t skuid) |
Kevin Chiu | e2bb059 | 2017-09-12 09:13:41 +0800 | [diff] [blame] | 627 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 628 | const struct ec_sku_id_info params = { |
Kevin Chiu | e2bb059 | 2017-09-12 09:13:41 +0800 | [diff] [blame] | 629 | .sku_id = skuid |
| 630 | }; |
Kevin Chiu | e2bb059 | 2017-09-12 09:13:41 +0800 | [diff] [blame] | 631 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 632 | if (ec_cmd_set_sku_id(PLAT_EC, ¶ms) != 0) |
Kevin Chiu | e2bb059 | 2017-09-12 09:13:41 +0800 | [diff] [blame] | 633 | return -1; |
| 634 | |
| 635 | return 0; |
| 636 | } |
| 637 | |
Julius Werner | cd49cce | 2019-03-05 16:53:33 -0800 | [diff] [blame] | 638 | #if CONFIG(EC_GOOGLE_CHROMEEC_RTC) |
Simon Glass | 7865932 | 2016-06-10 20:58:24 -0600 | [diff] [blame] | 639 | int rtc_get(struct rtc_time *time) |
| 640 | { |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 641 | struct ec_response_rtc resp = {}; |
Simon Glass | 7865932 | 2016-06-10 20:58:24 -0600 | [diff] [blame] | 642 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 643 | if (ec_cmd_rtc_get_value(PLAT_EC, &resp) != 0) |
Simon Glass | 7865932 | 2016-06-10 20:58:24 -0600 | [diff] [blame] | 644 | return -1; |
| 645 | |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 646 | return rtc_to_tm(resp.time, time); |
Simon Glass | 7865932 | 2016-06-10 20:58:24 -0600 | [diff] [blame] | 647 | } |
| 648 | #endif |
| 649 | |
Caveh Jalali | 603de3f | 2022-11-01 02:02:56 -0700 | [diff] [blame] | 650 | int google_chromeec_reboot(enum ec_reboot_cmd type, uint8_t flags) |
Aaron Durbin | e68d22f | 2017-05-04 12:32:52 -0500 | [diff] [blame] | 651 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 652 | const struct ec_params_reboot_ec params = { |
Aaron Durbin | e68d22f | 2017-05-04 12:32:52 -0500 | [diff] [blame] | 653 | .cmd = type, |
| 654 | .flags = flags, |
| 655 | }; |
Aaron Durbin | e68d22f | 2017-05-04 12:32:52 -0500 | [diff] [blame] | 656 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 657 | return ec_cmd_reboot_ec(PLAT_EC, ¶ms); |
Aaron Durbin | e68d22f | 2017-05-04 12:32:52 -0500 | [diff] [blame] | 658 | } |
| 659 | |
Jonathan Brandmeyer | 6bffc5c | 2018-07-23 16:30:44 -0600 | [diff] [blame] | 660 | static int cbi_get_uint32(uint32_t *id, uint32_t tag) |
Daisuke Nojiri | 07f9748f | 2018-02-01 07:46:02 -0800 | [diff] [blame] | 661 | { |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 662 | struct ec_params_get_cbi params = { |
| 663 | .tag = tag, |
| 664 | }; |
Zhuohao Lee | 7824d9b | 2018-03-30 10:18:04 +0800 | [diff] [blame] | 665 | uint32_t r = 0; |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 666 | struct chromeec_command cmd = { |
| 667 | .cmd_code = EC_CMD_GET_CROS_BOARD_INFO, |
| 668 | .cmd_version = 0, |
| 669 | .cmd_data_in = ¶ms, |
| 670 | .cmd_data_out = &r, |
| 671 | .cmd_size_in = sizeof(params), |
| 672 | .cmd_size_out = sizeof(r), |
| 673 | .cmd_dev_index = 0, |
| 674 | }; |
Daisuke Nojiri | 07f9748f | 2018-02-01 07:46:02 -0800 | [diff] [blame] | 675 | int rv; |
| 676 | |
Daisuke Nojiri | 07f9748f | 2018-02-01 07:46:02 -0800 | [diff] [blame] | 677 | rv = google_chromeec_command(&cmd); |
YH Lin | 40f6542 | 2019-02-26 09:56:06 -0800 | [diff] [blame] | 678 | if (rv != 0) |
Daisuke Nojiri | 07f9748f | 2018-02-01 07:46:02 -0800 | [diff] [blame] | 679 | return rv; |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 680 | |
Daisuke Nojiri | 07f9748f | 2018-02-01 07:46:02 -0800 | [diff] [blame] | 681 | *id = r; |
| 682 | return 0; |
| 683 | } |
| 684 | |
| 685 | int google_chromeec_cbi_get_sku_id(uint32_t *id) |
| 686 | { |
Daisuke Nojiri | f984a05 | 2018-02-15 12:38:15 -0800 | [diff] [blame] | 687 | return cbi_get_uint32(id, CBI_TAG_SKU_ID); |
Daisuke Nojiri | 07f9748f | 2018-02-01 07:46:02 -0800 | [diff] [blame] | 688 | } |
| 689 | |
Tim Wawrzynczak | 24b4af6 | 2020-10-01 15:41:31 -0600 | [diff] [blame] | 690 | int google_chromeec_cbi_get_fw_config(uint64_t *fw_config) |
Jett Rink | 8db8a61 | 2020-01-14 11:41:47 -0700 | [diff] [blame] | 691 | { |
Tim Wawrzynczak | 24b4af6 | 2020-10-01 15:41:31 -0600 | [diff] [blame] | 692 | uint32_t config; |
| 693 | |
| 694 | if (cbi_get_uint32(&config, CBI_TAG_FW_CONFIG)) |
| 695 | return -1; |
| 696 | |
Tim Wawrzynczak | 24b4af6 | 2020-10-01 15:41:31 -0600 | [diff] [blame] | 697 | *fw_config = (uint64_t)config; |
Karthikeyan Ramasubramanian | 8672884 | 2021-02-25 00:29:14 -0700 | [diff] [blame] | 698 | /* |
| 699 | * If SSFC is configured to be part of FW_CONFIG, add it at the most significant |
| 700 | * 32 bits. |
| 701 | */ |
| 702 | if (CONFIG(EC_GOOGLE_CHROMEEC_INCLUDE_SSFC_IN_FW_CONFIG)) { |
| 703 | uint32_t ssfc; |
| 704 | |
Kangheui Won | 082be10 | 2021-04-09 15:37:15 +1000 | [diff] [blame] | 705 | if (!google_chromeec_cbi_get_ssfc(&ssfc)) |
| 706 | *fw_config |= (uint64_t)ssfc << 32; |
Karthikeyan Ramasubramanian | 8672884 | 2021-02-25 00:29:14 -0700 | [diff] [blame] | 707 | } |
Tim Wawrzynczak | 24b4af6 | 2020-10-01 15:41:31 -0600 | [diff] [blame] | 708 | return 0; |
Jett Rink | 8db8a61 | 2020-01-14 11:41:47 -0700 | [diff] [blame] | 709 | } |
| 710 | |
Daisuke Nojiri | 07f9748f | 2018-02-01 07:46:02 -0800 | [diff] [blame] | 711 | int google_chromeec_cbi_get_oem_id(uint32_t *id) |
| 712 | { |
Daisuke Nojiri | f984a05 | 2018-02-15 12:38:15 -0800 | [diff] [blame] | 713 | return cbi_get_uint32(id, CBI_TAG_OEM_ID); |
Daisuke Nojiri | 07f9748f | 2018-02-01 07:46:02 -0800 | [diff] [blame] | 714 | } |
| 715 | |
Aaron Durbin | 5352577 | 2020-04-13 22:24:09 -0600 | [diff] [blame] | 716 | int google_chromeec_cbi_get_board_version(uint32_t *version) |
| 717 | { |
| 718 | return cbi_get_uint32(version, CBI_TAG_BOARD_VERSION); |
| 719 | } |
| 720 | |
Marco Chen | 525cc46 | 2020-12-11 14:29:23 +0800 | [diff] [blame] | 721 | int google_chromeec_cbi_get_ssfc(uint32_t *ssfc) |
| 722 | { |
| 723 | return cbi_get_uint32(ssfc, CBI_TAG_SSFC); |
| 724 | } |
| 725 | |
Wisley Chen | c1efec7 | 2018-11-06 09:28:23 +0800 | [diff] [blame] | 726 | static int cbi_get_string(char *buf, size_t bufsize, uint32_t tag) |
Aaron Durbin | b388c0e | 2018-08-07 12:24:21 -0600 | [diff] [blame] | 727 | { |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 728 | struct ec_params_get_cbi params = { |
Wisley Chen | c1efec7 | 2018-11-06 09:28:23 +0800 | [diff] [blame] | 729 | .tag = tag, |
Aaron Durbin | b388c0e | 2018-08-07 12:24:21 -0600 | [diff] [blame] | 730 | }; |
| 731 | struct chromeec_command cmd = { |
| 732 | .cmd_code = EC_CMD_GET_CROS_BOARD_INFO, |
| 733 | .cmd_version = 0, |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 734 | .cmd_data_in = ¶ms, |
Aaron Durbin | b388c0e | 2018-08-07 12:24:21 -0600 | [diff] [blame] | 735 | .cmd_data_out = buf, |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 736 | .cmd_size_in = sizeof(params), |
Aaron Durbin | b388c0e | 2018-08-07 12:24:21 -0600 | [diff] [blame] | 737 | .cmd_size_out = bufsize, |
| 738 | }; |
| 739 | int rv; |
| 740 | |
| 741 | rv = google_chromeec_command(&cmd); |
YH Lin | 40f6542 | 2019-02-26 09:56:06 -0800 | [diff] [blame] | 742 | if (rv != 0) |
Aaron Durbin | b388c0e | 2018-08-07 12:24:21 -0600 | [diff] [blame] | 743 | return rv; |
| 744 | |
| 745 | /* Ensure NUL termination. */ |
| 746 | buf[bufsize - 1] = '\0'; |
| 747 | |
| 748 | return 0; |
| 749 | } |
| 750 | |
Wisley Chen | c1efec7 | 2018-11-06 09:28:23 +0800 | [diff] [blame] | 751 | int google_chromeec_cbi_get_dram_part_num(char *buf, size_t bufsize) |
| 752 | { |
| 753 | return cbi_get_string(buf, bufsize, CBI_TAG_DRAM_PART_NUM); |
| 754 | } |
| 755 | |
| 756 | int google_chromeec_cbi_get_oem_name(char *buf, size_t bufsize) |
| 757 | { |
| 758 | return cbi_get_string(buf, bufsize, CBI_TAG_OEM_NAME); |
| 759 | } |
| 760 | |
Karthikeyan Ramasubramanian | c80ff84 | 2018-09-17 16:19:34 -0600 | [diff] [blame] | 761 | int google_chromeec_get_board_version(uint32_t *version) |
Shawn Nematbakhsh | d0a6a38 | 2013-07-08 14:18:01 -0700 | [diff] [blame] | 762 | { |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 763 | struct ec_response_board_version resp; |
Shawn Nematbakhsh | d0a6a38 | 2013-07-08 14:18:01 -0700 | [diff] [blame] | 764 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 765 | if (ec_cmd_get_board_version(PLAT_EC, &resp)) |
Karthikeyan Ramasubramanian | c80ff84 | 2018-09-17 16:19:34 -0600 | [diff] [blame] | 766 | return -1; |
Shawn Nematbakhsh | d0a6a38 | 2013-07-08 14:18:01 -0700 | [diff] [blame] | 767 | |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 768 | *version = resp.board_version; |
Karthikeyan Ramasubramanian | c80ff84 | 2018-09-17 16:19:34 -0600 | [diff] [blame] | 769 | return 0; |
Shawn Nematbakhsh | d0a6a38 | 2013-07-08 14:18:01 -0700 | [diff] [blame] | 770 | } |
Stefan Reinauer | aaaf689 | 2013-08-29 15:57:11 -0700 | [diff] [blame] | 771 | |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 772 | uint32_t google_chromeec_get_sku_id(void) |
Patrick Georgi | 69206d9 | 2017-07-31 14:20:07 +0200 | [diff] [blame] | 773 | { |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 774 | struct ec_sku_id_info resp; |
Patrick Georgi | 69206d9 | 2017-07-31 14:20:07 +0200 | [diff] [blame] | 775 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 776 | if (ec_cmd_get_sku_id(PLAT_EC, &resp) != 0) |
Patrick Georgi | 69206d9 | 2017-07-31 14:20:07 +0200 | [diff] [blame] | 777 | return 0; |
| 778 | |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 779 | return resp.sku_id; |
Patrick Georgi | 69206d9 | 2017-07-31 14:20:07 +0200 | [diff] [blame] | 780 | } |
| 781 | |
Caveh Jalali | 0bab8ed | 2022-11-02 20:34:43 -0700 | [diff] [blame] | 782 | static bool google_chromeec_get_uptime_info( |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 783 | struct ec_response_uptime_info *resp) |
You-Cheng Syu | 85bb874 | 2019-03-12 13:02:18 +0800 | [diff] [blame] | 784 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 785 | return ec_cmd_get_uptime_info(PLAT_EC, resp) == 0; |
You-Cheng Syu | 85bb874 | 2019-03-12 13:02:18 +0800 | [diff] [blame] | 786 | } |
| 787 | |
| 788 | bool google_chromeec_get_ap_watchdog_flag(void) |
| 789 | { |
Yu-Ping Wu | 8a82ea9 | 2021-01-05 17:05:40 +0800 | [diff] [blame] | 790 | int i; |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 791 | struct ec_response_uptime_info resp; |
Yu-Ping Wu | 8a82ea9 | 2021-01-05 17:05:40 +0800 | [diff] [blame] | 792 | |
Caveh Jalali | 0bab8ed | 2022-11-02 20:34:43 -0700 | [diff] [blame] | 793 | if (!google_chromeec_get_uptime_info(&resp)) |
Yu-Ping Wu | 8a82ea9 | 2021-01-05 17:05:40 +0800 | [diff] [blame] | 794 | return false; |
| 795 | |
| 796 | if (resp.ec_reset_flags & EC_RESET_FLAG_AP_WATCHDOG) |
| 797 | return true; |
| 798 | |
| 799 | /* Find the last valid entry */ |
| 800 | for (i = ARRAY_SIZE(resp.recent_ap_reset) - 1; i >= 0; i--) { |
| 801 | if (resp.recent_ap_reset[i].reset_time_ms == 0) |
| 802 | continue; |
| 803 | return (resp.recent_ap_reset[i].reset_cause == |
| 804 | CHIPSET_RESET_AP_WATCHDOG); |
| 805 | } |
| 806 | |
| 807 | return false; |
You-Cheng Syu | 85bb874 | 2019-03-12 13:02:18 +0800 | [diff] [blame] | 808 | } |
| 809 | |
Gabe Black | 9f96aa6 | 2013-06-28 14:24:33 -0700 | [diff] [blame] | 810 | int google_chromeec_i2c_xfer(uint8_t chip, uint8_t addr, int alen, |
| 811 | uint8_t *buffer, int len, int is_read) |
| 812 | { |
| 813 | union { |
| 814 | struct ec_params_i2c_passthru p; |
| 815 | uint8_t outbuf[EC_HOST_PARAM_SIZE]; |
| 816 | } params; |
| 817 | union { |
| 818 | struct ec_response_i2c_passthru r; |
| 819 | uint8_t inbuf[EC_HOST_PARAM_SIZE]; |
| 820 | } response; |
| 821 | struct ec_params_i2c_passthru *p = ¶ms.p; |
| 822 | struct ec_response_i2c_passthru *r = &response.r; |
| 823 | struct ec_params_i2c_passthru_msg *msg = p->msg; |
| 824 | struct chromeec_command cmd; |
| 825 | uint8_t *pdata; |
| 826 | int read_len, write_len; |
| 827 | int size; |
| 828 | int rv; |
| 829 | |
| 830 | p->port = 0; |
| 831 | |
| 832 | if (alen != 1) { |
| 833 | printk(BIOS_ERR, "Unsupported address length %d\n", alen); |
| 834 | return -1; |
| 835 | } |
| 836 | if (is_read) { |
| 837 | read_len = len; |
| 838 | write_len = alen; |
| 839 | p->num_msgs = 2; |
| 840 | } else { |
| 841 | read_len = 0; |
| 842 | write_len = alen + len; |
| 843 | p->num_msgs = 1; |
| 844 | } |
| 845 | |
| 846 | size = sizeof(*p) + p->num_msgs * sizeof(*msg); |
| 847 | if (size + write_len > sizeof(params)) { |
| 848 | printk(BIOS_ERR, "Params too large for buffer\n"); |
| 849 | return -1; |
| 850 | } |
| 851 | if (sizeof(*r) + read_len > sizeof(response)) { |
| 852 | printk(BIOS_ERR, "Read length too big for buffer\n"); |
| 853 | return -1; |
| 854 | } |
| 855 | |
| 856 | /* Create a message to write the register address and optional data */ |
| 857 | pdata = (uint8_t *)p + size; |
| 858 | msg->addr_flags = chip; |
| 859 | msg->len = write_len; |
| 860 | pdata[0] = addr; |
| 861 | if (!is_read) |
| 862 | memcpy(pdata + 1, buffer, len); |
| 863 | msg++; |
| 864 | |
| 865 | if (read_len) { |
| 866 | msg->addr_flags = chip | EC_I2C_FLAG_READ; |
| 867 | msg->len = read_len; |
| 868 | } |
| 869 | |
| 870 | cmd.cmd_code = EC_CMD_I2C_PASSTHRU; |
| 871 | cmd.cmd_version = 0; |
| 872 | cmd.cmd_data_in = p; |
| 873 | cmd.cmd_size_in = size + write_len; |
| 874 | cmd.cmd_data_out = r; |
| 875 | cmd.cmd_size_out = sizeof(*r) + read_len; |
Duncan Laurie | fc0f517 | 2014-09-18 12:54:02 -0700 | [diff] [blame] | 876 | cmd.cmd_dev_index = 0; |
Gabe Black | 9f96aa6 | 2013-06-28 14:24:33 -0700 | [diff] [blame] | 877 | rv = google_chromeec_command(&cmd); |
| 878 | if (rv != 0) |
| 879 | return rv; |
| 880 | |
| 881 | /* Parse response */ |
| 882 | if (r->i2c_status & EC_I2C_STATUS_ERROR) { |
| 883 | printk(BIOS_ERR, "Transfer failed with status=0x%x\n", |
| 884 | r->i2c_status); |
| 885 | return -1; |
| 886 | } |
| 887 | |
| 888 | if (cmd.cmd_size_out < sizeof(*r) + read_len) { |
| 889 | printk(BIOS_ERR, "Truncated read response\n"); |
| 890 | return -1; |
| 891 | } |
| 892 | |
| 893 | if (read_len) |
| 894 | memcpy(buffer, r->data, read_len); |
| 895 | |
| 896 | return 0; |
| 897 | } |
| 898 | |
Furquan Shaikh | 8788fd6 | 2017-11-20 20:28:18 -0800 | [diff] [blame] | 899 | int google_chromeec_set_sci_mask(uint64_t mask) |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 900 | { |
Furquan Shaikh | 8788fd6 | 2017-11-20 20:28:18 -0800 | [diff] [blame] | 901 | printk(BIOS_DEBUG, "Chrome EC: Set SCI mask to 0x%016llx\n", mask); |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 902 | return google_chromeec_set_mask(EC_HOST_EVENT_SCI_MASK, mask); |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 903 | } |
| 904 | |
Furquan Shaikh | 8788fd6 | 2017-11-20 20:28:18 -0800 | [diff] [blame] | 905 | int google_chromeec_set_smi_mask(uint64_t mask) |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 906 | { |
Furquan Shaikh | 8788fd6 | 2017-11-20 20:28:18 -0800 | [diff] [blame] | 907 | printk(BIOS_DEBUG, "Chrome EC: Set SMI mask to 0x%016llx\n", mask); |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 908 | return google_chromeec_set_mask(EC_HOST_EVENT_SMI_MASK, mask); |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 909 | } |
| 910 | |
Furquan Shaikh | 8788fd6 | 2017-11-20 20:28:18 -0800 | [diff] [blame] | 911 | int google_chromeec_set_wake_mask(uint64_t mask) |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 912 | { |
Furquan Shaikh | 8788fd6 | 2017-11-20 20:28:18 -0800 | [diff] [blame] | 913 | printk(BIOS_DEBUG, "Chrome EC: Set WAKE mask to 0x%016llx\n", mask); |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 914 | return google_chromeec_set_mask |
| 915 | (EC_HOST_EVENT_ACTIVE_WAKE_MASK, mask); |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 916 | } |
| 917 | |
Furquan Shaikh | 8788fd6 | 2017-11-20 20:28:18 -0800 | [diff] [blame] | 918 | uint64_t google_chromeec_get_wake_mask(void) |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 919 | { |
Jenny TC | 1dfc2c3 | 2017-12-14 14:24:39 +0530 | [diff] [blame] | 920 | return google_chromeec_get_mask(EC_HOST_EVENT_ACTIVE_WAKE_MASK); |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 921 | } |
| 922 | |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 923 | int google_chromeec_set_usb_charge_mode(uint8_t port_id, enum usb_charge_mode mode) |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 924 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 925 | const struct ec_params_usb_charge_set_mode params = { |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 926 | .usb_port_id = port_id, |
| 927 | .mode = mode, |
| 928 | }; |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 929 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 930 | return ec_cmd_usb_charge_set_mode(PLAT_EC, ¶ms); |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 931 | } |
| 932 | |
Gaggery Tsai | 52f18df | 2020-03-25 11:34:25 -0700 | [diff] [blame] | 933 | /* Get charger voltage and current. Also returns type of charger */ |
Shelley Chen | ebd5330 | 2017-09-29 14:15:11 -0700 | [diff] [blame] | 934 | int google_chromeec_get_usb_pd_power_info(enum usb_chg_type *type, |
Gaggery Tsai | 52f18df | 2020-03-25 11:34:25 -0700 | [diff] [blame] | 935 | uint16_t *current_max, uint16_t *voltage_max) |
Shelley Chen | ebd5330 | 2017-09-29 14:15:11 -0700 | [diff] [blame] | 936 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 937 | const struct ec_params_usb_pd_power_info params = { |
Shelley Chen | ebd5330 | 2017-09-29 14:15:11 -0700 | [diff] [blame] | 938 | .port = PD_POWER_CHARGING_PORT, |
| 939 | }; |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 940 | struct ec_response_usb_pd_power_info resp = {}; |
Shelley Chen | ebd5330 | 2017-09-29 14:15:11 -0700 | [diff] [blame] | 941 | struct usb_chg_measures m; |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 942 | int rv; |
| 943 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 944 | rv = ec_cmd_usb_pd_power_info(PLAT_EC, ¶ms, &resp); |
Shelley Chen | ebd5330 | 2017-09-29 14:15:11 -0700 | [diff] [blame] | 945 | if (rv != 0) |
| 946 | return rv; |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 947 | |
Shelley Chen | ebd5330 | 2017-09-29 14:15:11 -0700 | [diff] [blame] | 948 | /* values are given in milliAmps and milliVolts */ |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 949 | *type = resp.type; |
| 950 | m = resp.meas; |
Gaggery Tsai | 52f18df | 2020-03-25 11:34:25 -0700 | [diff] [blame] | 951 | *voltage_max = m.voltage_max; |
| 952 | *current_max = m.current_max; |
Shelley Chen | ebd5330 | 2017-09-29 14:15:11 -0700 | [diff] [blame] | 953 | return 0; |
| 954 | } |
| 955 | |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 956 | int google_chromeec_override_dedicated_charger_limit(uint16_t current_lim, |
| 957 | uint16_t voltage_lim) |
Daisuke Nojiri | 93fd8fa | 2017-11-28 14:11:30 -0800 | [diff] [blame] | 958 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 959 | const struct ec_params_dedicated_charger_limit params = { |
Daisuke Nojiri | 93fd8fa | 2017-11-28 14:11:30 -0800 | [diff] [blame] | 960 | .current_lim = current_lim, |
| 961 | .voltage_lim = voltage_lim, |
| 962 | }; |
Daisuke Nojiri | 93fd8fa | 2017-11-28 14:11:30 -0800 | [diff] [blame] | 963 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 964 | return ec_cmd_override_dedicated_charger_limit(PLAT_EC, ¶ms); |
Daisuke Nojiri | 93fd8fa | 2017-11-28 14:11:30 -0800 | [diff] [blame] | 965 | } |
| 966 | |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 967 | int google_chromeec_set_usb_pd_role(uint8_t port, enum usb_pd_control_role role) |
Julius Werner | ea79d2b | 2016-11-21 20:14:07 -0800 | [diff] [blame] | 968 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 969 | const struct ec_params_usb_pd_control params = { |
Julius Werner | ea79d2b | 2016-11-21 20:14:07 -0800 | [diff] [blame] | 970 | .port = port, |
| 971 | .role = role, |
| 972 | .mux = USB_PD_CTRL_MUX_NO_CHANGE, |
| 973 | .swap = USB_PD_CTRL_SWAP_NONE, |
| 974 | }; |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 975 | struct ec_response_usb_pd_control resp; |
Julius Werner | ea79d2b | 2016-11-21 20:14:07 -0800 | [diff] [blame] | 976 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 977 | return ec_cmd_usb_pd_control(PLAT_EC, ¶ms, &resp); |
Julius Werner | ea79d2b | 2016-11-21 20:14:07 -0800 | [diff] [blame] | 978 | } |
| 979 | |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 980 | int google_chromeec_hello(void) |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 981 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 982 | const struct ec_params_hello params = { |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 983 | .in_data = 0x10203040, |
| 984 | }; |
| 985 | struct ec_response_hello resp = {}; |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 986 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 987 | int rv = ec_cmd_hello(PLAT_EC, ¶ms, &resp); |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 988 | if (rv) |
| 989 | return -1; |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 990 | |
| 991 | if (resp.out_data != (params.in_data + 0x01020304)) |
| 992 | return -1; |
| 993 | |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 994 | return 0; |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 995 | } |
| 996 | |
Jonathan Brandmeyer | bd21f2844 | 2018-07-23 16:44:51 -0600 | [diff] [blame] | 997 | /* |
| 998 | * Convert a reset cause ID to human-readable string, providing total coverage |
| 999 | * of the 'cause' space. The returned string points to static storage and must |
| 1000 | * not be free()ed. |
| 1001 | */ |
| 1002 | static const char *reset_cause_to_str(uint16_t cause) |
| 1003 | { |
| 1004 | /* See also ChromiumOS EC include/chipset.h for details. */ |
| 1005 | static const char * const reset_causes[] = { |
| 1006 | "(reset unknown)", |
| 1007 | "reset: board custom", |
| 1008 | "reset: ap hang detected", |
| 1009 | "reset: console command", |
| 1010 | "reset: keyboard sysreset", |
| 1011 | "reset: keyboard warm reboot", |
| 1012 | "reset: debug warm reboot", |
| 1013 | "reset: at AP's request", |
| 1014 | "reset: during EC initialization", |
You-Cheng Syu | 85bb874 | 2019-03-12 13:02:18 +0800 | [diff] [blame] | 1015 | "reset: AP watchdog", |
Jonathan Brandmeyer | bd21f2844 | 2018-07-23 16:44:51 -0600 | [diff] [blame] | 1016 | }; |
| 1017 | |
| 1018 | static const size_t shutdown_cause_begin = 1 << 15; |
| 1019 | static const char * const shutdown_causes[] = { |
| 1020 | "shutdown: power failure", |
| 1021 | "shutdown: during EC initialization", |
| 1022 | "shutdown: board custom", |
| 1023 | "shutdown: battery voltage startup inhibit", |
| 1024 | "shutdown: power wait asserted", |
| 1025 | "shutdown: critical battery", |
| 1026 | "shutdown: by console command", |
| 1027 | "shutdown: entering G3", |
| 1028 | "shutdown: thermal", |
| 1029 | "shutdown: power button", |
| 1030 | }; |
| 1031 | |
| 1032 | if (cause < ARRAY_SIZE(reset_causes)) |
| 1033 | return reset_causes[cause]; |
| 1034 | |
| 1035 | if (cause < shutdown_cause_begin) |
| 1036 | return "(reset unknown)"; |
| 1037 | |
| 1038 | if (cause < shutdown_cause_begin + ARRAY_SIZE(shutdown_causes)) |
| 1039 | return shutdown_causes[cause - shutdown_cause_begin]; |
| 1040 | |
| 1041 | return "(shutdown unknown)"; |
| 1042 | } |
| 1043 | |
| 1044 | /* |
| 1045 | * Copy the EC's information about resets of the AP and its own uptime for |
| 1046 | * debugging purposes. |
| 1047 | */ |
| 1048 | static void google_chromeec_log_uptimeinfo(void) |
| 1049 | { |
You-Cheng Syu | 8d6ea6a | 2019-03-13 21:37:23 +0800 | [diff] [blame] | 1050 | /* See also ec_commands.h EC_RESET_FLAG_* for details. */ |
Jonathan Brandmeyer | bd21f2844 | 2018-07-23 16:44:51 -0600 | [diff] [blame] | 1051 | static const char * const reset_flag_strings[] = { |
| 1052 | "other", |
| 1053 | "reset-pin", |
| 1054 | "brownout", |
| 1055 | "power-on", |
| 1056 | "watchdog", |
| 1057 | "soft", |
| 1058 | "hibernate", |
| 1059 | "rtc-alarm", |
| 1060 | "wake-pin", |
| 1061 | "low-battery", |
| 1062 | "sysjump", |
| 1063 | "hard", |
| 1064 | "ap-off", |
| 1065 | "preserved", |
| 1066 | "usb-resume", |
| 1067 | "rdd", |
| 1068 | "rbox", |
You-Cheng Syu | 85bb874 | 2019-03-12 13:02:18 +0800 | [diff] [blame] | 1069 | "security", |
| 1070 | "ap-watchdog", |
Jonathan Brandmeyer | bd21f2844 | 2018-07-23 16:44:51 -0600 | [diff] [blame] | 1071 | }; |
| 1072 | struct ec_response_uptime_info cmd_resp; |
| 1073 | int i, flag, flag_count; |
| 1074 | |
Caveh Jalali | 0bab8ed | 2022-11-02 20:34:43 -0700 | [diff] [blame] | 1075 | if (!google_chromeec_get_uptime_info(&cmd_resp)) { |
Jonathan Brandmeyer | bd21f2844 | 2018-07-23 16:44:51 -0600 | [diff] [blame] | 1076 | /* |
| 1077 | * Deliberately say nothing for EC's that don't support this |
| 1078 | * command |
| 1079 | */ |
| 1080 | return; |
| 1081 | } |
| 1082 | |
| 1083 | printk(BIOS_DEBUG, "Google Chrome EC uptime: %d.%03d seconds\n", |
| 1084 | cmd_resp.time_since_ec_boot_ms / MSECS_PER_SEC, |
| 1085 | cmd_resp.time_since_ec_boot_ms % MSECS_PER_SEC); |
| 1086 | |
| 1087 | printk(BIOS_DEBUG, "Google Chrome AP resets since EC boot: %d\n", |
| 1088 | cmd_resp.ap_resets_since_ec_boot); |
| 1089 | |
| 1090 | printk(BIOS_DEBUG, "Google Chrome most recent AP reset causes:\n"); |
| 1091 | for (i = 0; i != ARRAY_SIZE(cmd_resp.recent_ap_reset); ++i) { |
| 1092 | if (cmd_resp.recent_ap_reset[i].reset_time_ms == 0) |
| 1093 | continue; |
| 1094 | |
| 1095 | printk(BIOS_DEBUG, "\t%d.%03d: %d %s\n", |
| 1096 | cmd_resp.recent_ap_reset[i].reset_time_ms / |
| 1097 | MSECS_PER_SEC, |
| 1098 | cmd_resp.recent_ap_reset[i].reset_time_ms % |
| 1099 | MSECS_PER_SEC, |
| 1100 | cmd_resp.recent_ap_reset[i].reset_cause, |
| 1101 | reset_cause_to_str( |
| 1102 | cmd_resp.recent_ap_reset[i].reset_cause)); |
| 1103 | } |
| 1104 | |
| 1105 | printk(BIOS_DEBUG, "Google Chrome EC reset flags at last EC boot: "); |
| 1106 | flag_count = 0; |
| 1107 | for (flag = 0; flag != ARRAY_SIZE(reset_flag_strings); ++flag) { |
| 1108 | if ((cmd_resp.ec_reset_flags & (1 << flag)) != 0) { |
| 1109 | if (flag_count) |
| 1110 | printk(BIOS_DEBUG, " | "); |
Greg V | ae47a6f | 2019-10-04 02:49:20 +0300 | [diff] [blame] | 1111 | printk(BIOS_DEBUG, "%s", reset_flag_strings[flag]); |
Jonathan Brandmeyer | bd21f2844 | 2018-07-23 16:44:51 -0600 | [diff] [blame] | 1112 | flag_count++; |
| 1113 | } |
| 1114 | } |
| 1115 | printk(BIOS_DEBUG, "\n"); |
| 1116 | } |
| 1117 | |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 1118 | /* Cache and retrieve the EC image type (ro or rw) */ |
Furquan Shaikh | a6cf8d6 | 2020-04-07 22:22:22 -0700 | [diff] [blame] | 1119 | enum ec_image google_chromeec_get_current_image(void) |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 1120 | { |
Kyösti Mälkki | fcbbb91 | 2020-04-20 10:21:39 +0300 | [diff] [blame] | 1121 | static enum ec_image ec_image_type = EC_IMAGE_UNKNOWN; |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 1122 | |
| 1123 | if (ec_image_type != EC_IMAGE_UNKNOWN) |
| 1124 | return ec_image_type; |
| 1125 | |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 1126 | struct ec_response_get_version resp = {}; |
Caveh Jalali | 675de75 | 2022-11-02 20:48:51 -0700 | [diff] [blame] | 1127 | int rv; |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 1128 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1129 | rv = ec_cmd_get_version(PLAT_EC, &resp); |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 1130 | |
Caveh Jalali | 675de75 | 2022-11-02 20:48:51 -0700 | [diff] [blame] | 1131 | if (rv != 0) { |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 1132 | printk(BIOS_DEBUG, |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 1133 | "Google Chrome EC: version command failed!\n"); |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 1134 | } else { |
| 1135 | printk(BIOS_DEBUG, "Google Chrome EC: version:\n"); |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 1136 | printk(BIOS_DEBUG, " ro: %s\n", resp.version_string_ro); |
| 1137 | printk(BIOS_DEBUG, " rw: %s\n", resp.version_string_rw); |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 1138 | printk(BIOS_DEBUG, " running image: %d\n", |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 1139 | resp.current_image); |
| 1140 | ec_image_type = resp.current_image; |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 1141 | } |
Jonathan Brandmeyer | bd21f2844 | 2018-07-23 16:44:51 -0600 | [diff] [blame] | 1142 | |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 1143 | /* Will still be UNKNOWN if command failed */ |
| 1144 | return ec_image_type; |
| 1145 | } |
| 1146 | |
Divya Sasidharan | 49d74de | 2019-10-22 13:41:15 -0700 | [diff] [blame] | 1147 | int google_chromeec_get_num_pd_ports(unsigned int *num_ports) |
Tim Wawrzynczak | e607829 | 2020-01-22 15:22:18 -0700 | [diff] [blame] | 1148 | { |
Caveh Jalali | 21552ae | 2022-11-02 18:59:36 -0700 | [diff] [blame] | 1149 | struct ec_response_usb_pd_ports resp = {}; |
Tim Wawrzynczak | e607829 | 2020-01-22 15:22:18 -0700 | [diff] [blame] | 1150 | int rv; |
| 1151 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1152 | rv = ec_cmd_usb_pd_ports(PLAT_EC, &resp); |
Tim Wawrzynczak | e607829 | 2020-01-22 15:22:18 -0700 | [diff] [blame] | 1153 | if (rv) |
| 1154 | return rv; |
| 1155 | |
Caveh Jalali | 21552ae | 2022-11-02 18:59:36 -0700 | [diff] [blame] | 1156 | *num_ports = resp.num_ports; |
Tim Wawrzynczak | e607829 | 2020-01-22 15:22:18 -0700 | [diff] [blame] | 1157 | return 0; |
| 1158 | } |
| 1159 | |
| 1160 | int google_chromeec_get_pd_port_caps(int port, |
| 1161 | struct usb_pd_port_caps *port_caps) |
| 1162 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1163 | const struct ec_params_get_pd_port_caps params = { |
Tim Wawrzynczak | e607829 | 2020-01-22 15:22:18 -0700 | [diff] [blame] | 1164 | .port = port, |
| 1165 | }; |
| 1166 | struct ec_response_get_pd_port_caps resp = {}; |
Tim Wawrzynczak | e607829 | 2020-01-22 15:22:18 -0700 | [diff] [blame] | 1167 | int rv; |
| 1168 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1169 | rv = ec_cmd_get_pd_port_caps(PLAT_EC, ¶ms, &resp); |
Tim Wawrzynczak | e607829 | 2020-01-22 15:22:18 -0700 | [diff] [blame] | 1170 | if (rv) |
| 1171 | return rv; |
| 1172 | |
| 1173 | port_caps->power_role_cap = resp.pd_power_role_cap; |
| 1174 | port_caps->try_power_role_cap = resp.pd_try_power_role_cap; |
| 1175 | port_caps->data_role_cap = resp.pd_data_role_cap; |
| 1176 | port_caps->port_location = resp.pd_port_location; |
| 1177 | |
| 1178 | return 0; |
| 1179 | } |
| 1180 | |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 1181 | void google_chromeec_init(void) |
| 1182 | { |
Jonathan Brandmeyer | bd21f2844 | 2018-07-23 16:44:51 -0600 | [diff] [blame] | 1183 | google_chromeec_log_uptimeinfo(); |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 1184 | } |
| 1185 | |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 1186 | int google_ec_running_ro(void) |
| 1187 | { |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 1188 | return (google_chromeec_get_current_image() == EC_IMAGE_RO); |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 1189 | } |
Stefan Reinauer | d6682e8 | 2013-02-21 15:39:35 -0800 | [diff] [blame] | 1190 | |
Derek Huang | 796ea82 | 2021-09-29 22:05:04 +0800 | [diff] [blame] | 1191 | /* Returns data role and type of device connected */ |
| 1192 | static int google_chromeec_usb_pd_get_info(int port, bool *ufp, bool *dbg_acc, |
Derek Huang | f1f9b3d | 2021-09-29 16:39:01 +0800 | [diff] [blame] | 1193 | bool *active_cable, uint8_t *dp_mode) |
Divya Sasidharan | 49d74de | 2019-10-22 13:41:15 -0700 | [diff] [blame] | 1194 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1195 | const struct ec_params_usb_pd_control pd_control = { |
Divya Sasidharan | 49d74de | 2019-10-22 13:41:15 -0700 | [diff] [blame] | 1196 | .port = port, |
| 1197 | .role = USB_PD_CTRL_ROLE_NO_CHANGE, |
| 1198 | .mux = USB_PD_CTRL_ROLE_NO_CHANGE, |
| 1199 | .swap = USB_PD_CTRL_SWAP_NONE, |
| 1200 | }; |
| 1201 | struct ec_response_usb_pd_control_v2 resp = {}; |
Divya Sasidharan | 49d74de | 2019-10-22 13:41:15 -0700 | [diff] [blame] | 1202 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1203 | if (ec_cmd_usb_pd_control_v2(PLAT_EC, &pd_control, &resp) < 0) |
Divya Sasidharan | 49d74de | 2019-10-22 13:41:15 -0700 | [diff] [blame] | 1204 | return -1; |
| 1205 | |
Dtrain Hsu | bb20e42 | 2022-08-29 15:43:01 +0800 | [diff] [blame] | 1206 | *ufp = !(resp.role & PD_CTRL_RESP_ROLE_DATA); |
Divya Sasidharan | 49d74de | 2019-10-22 13:41:15 -0700 | [diff] [blame] | 1207 | *dbg_acc = (resp.cc_state == PD_CC_DFP_DEBUG_ACC); |
Derek Huang | f1f9b3d | 2021-09-29 16:39:01 +0800 | [diff] [blame] | 1208 | *active_cable = !!(resp.control_flags & USB_PD_CTRL_ACTIVE_CABLE); |
Divya Sasidharan | 49d74de | 2019-10-22 13:41:15 -0700 | [diff] [blame] | 1209 | *dp_mode = resp.dp_mode; |
| 1210 | |
| 1211 | return 0; |
| 1212 | } |
| 1213 | |
Derek Huang | c0bd123 | 2021-08-25 17:19:39 +0800 | [diff] [blame] | 1214 | int google_chromeec_typec_control_enter_dp_mode(int port) |
| 1215 | { |
Kapil Porwal | c2c5801 | 2023-07-10 11:27:17 +0000 | [diff] [blame] | 1216 | int ret; |
| 1217 | struct usbc_mux_info mux_info; |
| 1218 | |
Derek Huang | c0bd123 | 2021-08-25 17:19:39 +0800 | [diff] [blame] | 1219 | if (!google_chromeec_check_feature(EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY)) |
| 1220 | return 0; |
| 1221 | |
Kapil Porwal | c2c5801 | 2023-07-10 11:27:17 +0000 | [diff] [blame] | 1222 | ret = google_chromeec_get_usbc_mux_info(port, &mux_info); |
| 1223 | if ((ret < 0) || (!mux_info.usb)) |
| 1224 | return -1; |
| 1225 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1226 | const struct ec_params_typec_control typec_control = { |
Derek Huang | c0bd123 | 2021-08-25 17:19:39 +0800 | [diff] [blame] | 1227 | .port = port, |
| 1228 | .command = TYPEC_CONTROL_COMMAND_ENTER_MODE, |
| 1229 | .mode_to_enter = TYPEC_MODE_DP, |
| 1230 | }; |
| 1231 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1232 | if (ec_cmd_typec_control(PLAT_EC, &typec_control) < 0) |
Derek Huang | c0bd123 | 2021-08-25 17:19:39 +0800 | [diff] [blame] | 1233 | return -1; |
| 1234 | |
| 1235 | return 0; |
| 1236 | } |
| 1237 | |
Divya Sasidharan | 49d74de | 2019-10-22 13:41:15 -0700 | [diff] [blame] | 1238 | /** |
| 1239 | * Check for the current mux state in EC. Flags representing the mux state found |
| 1240 | * in ec_commands.h |
| 1241 | */ |
| 1242 | int google_chromeec_usb_get_pd_mux_info(int port, uint8_t *flags) |
| 1243 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1244 | const struct ec_params_usb_pd_mux_info req_mux = { |
Divya Sasidharan | 49d74de | 2019-10-22 13:41:15 -0700 | [diff] [blame] | 1245 | .port = port, |
| 1246 | }; |
| 1247 | struct ec_response_usb_pd_mux_info resp_mux = {}; |
Divya Sasidharan | 49d74de | 2019-10-22 13:41:15 -0700 | [diff] [blame] | 1248 | |
| 1249 | if (port < 0) |
| 1250 | return -1; |
| 1251 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1252 | if (ec_cmd_usb_pd_mux_info(PLAT_EC, &req_mux, &resp_mux) < 0) |
Divya Sasidharan | 49d74de | 2019-10-22 13:41:15 -0700 | [diff] [blame] | 1253 | return -1; |
| 1254 | |
| 1255 | *flags = resp_mux.flags; |
| 1256 | return 0; |
| 1257 | } |
| 1258 | |
Derek Huang | 63ffc1a | 2021-09-29 21:59:45 +0800 | [diff] [blame] | 1259 | /* |
| 1260 | * Obtain any USB-C mux data needed for the specified port |
| 1261 | * in: physical port number of the type-c port |
| 1262 | * out: struct usbc_mux_info mux_info stores USB-C mux data |
| 1263 | * Return: 0 on success, -1 on error |
| 1264 | */ |
| 1265 | int google_chromeec_get_usbc_mux_info(int port, struct usbc_mux_info *mux_info) |
| 1266 | { |
| 1267 | uint8_t mux_flags; |
| 1268 | uint8_t dp_pin_mode; |
| 1269 | bool ufp, dbg_acc, active_cable; |
| 1270 | |
| 1271 | if (google_chromeec_usb_get_pd_mux_info(port, &mux_flags) < 0) { |
| 1272 | printk(BIOS_ERR, "Port C%d: get_pd_mux_info failed\n", port); |
| 1273 | return -1; |
| 1274 | } |
| 1275 | |
| 1276 | if (google_chromeec_usb_pd_get_info(port, &ufp, &dbg_acc, |
| 1277 | &active_cable, &dp_pin_mode) < 0) { |
| 1278 | printk(BIOS_ERR, "Port C%d: pd_control failed\n", port); |
| 1279 | return -1; |
| 1280 | } |
| 1281 | |
| 1282 | mux_info->usb = !!(mux_flags & USB_PD_MUX_USB_ENABLED); |
| 1283 | mux_info->dp = !!(mux_flags & USB_PD_MUX_DP_ENABLED); |
| 1284 | mux_info->polarity = !!(mux_flags & USB_PD_MUX_POLARITY_INVERTED); |
| 1285 | mux_info->hpd_irq = !!(mux_flags & USB_PD_MUX_HPD_IRQ); |
| 1286 | mux_info->hpd_lvl = !!(mux_flags & USB_PD_MUX_HPD_LVL); |
| 1287 | mux_info->ufp = !!ufp; |
| 1288 | mux_info->dbg_acc = !!dbg_acc; |
| 1289 | mux_info->cable = !!active_cable; |
| 1290 | mux_info->dp_pin_mode = dp_pin_mode; |
| 1291 | |
| 1292 | return 0; |
| 1293 | } |
| 1294 | |
Daisuke Nojiri | 476c2c5 | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1295 | /** |
| 1296 | * Check if EC/TCPM is in an alternate mode or not. |
| 1297 | * |
| 1298 | * @param svid SVID of the alternate mode to check |
Derek Huang | c0f005a | 2021-09-29 17:38:31 +0800 | [diff] [blame] | 1299 | * @return 0: Not in the mode. -1: Error. |
| 1300 | * >=1: bitmask of the ports that are in the mode. |
Daisuke Nojiri | 476c2c5 | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1301 | */ |
Derek Huang | c0f005a | 2021-09-29 17:38:31 +0800 | [diff] [blame] | 1302 | static int google_chromeec_pd_get_amode(uint16_t svid) |
Daisuke Nojiri | 476c2c5 | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1303 | { |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 1304 | struct ec_response_usb_pd_ports resp; |
Daisuke Nojiri | 476c2c5 | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1305 | int i; |
Derek Huang | c0f005a | 2021-09-29 17:38:31 +0800 | [diff] [blame] | 1306 | int ret = 0; |
Daisuke Nojiri | 476c2c5 | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1307 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1308 | if (ec_cmd_usb_pd_ports(PLAT_EC, &resp) < 0) |
Daisuke Nojiri | 476c2c5 | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1309 | return -1; |
| 1310 | |
Tim Wawrzynczak | b5c345a | 2019-10-24 10:12:01 -0600 | [diff] [blame] | 1311 | for (i = 0; i < resp.num_ports; i++) { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1312 | struct chromeec_command cmd = { }; |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 1313 | struct ec_params_usb_pd_get_mode_request params; |
| 1314 | struct ec_params_usb_pd_get_mode_response resp2; |
Daisuke Nojiri | ccfa18f | 2018-04-26 12:59:58 -0700 | [diff] [blame] | 1315 | int svid_idx = 0; |
Daisuke Nojiri | 476c2c5 | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1316 | |
| 1317 | do { |
Daisuke Nojiri | ccfa18f | 2018-04-26 12:59:58 -0700 | [diff] [blame] | 1318 | /* Reset cmd in each iteration in case |
| 1319 | google_chromeec_command changes it. */ |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 1320 | params.port = i; |
| 1321 | params.svid_idx = svid_idx; |
Daisuke Nojiri | ccfa18f | 2018-04-26 12:59:58 -0700 | [diff] [blame] | 1322 | cmd.cmd_code = EC_CMD_USB_PD_GET_AMODE; |
| 1323 | cmd.cmd_version = 0; |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 1324 | cmd.cmd_data_in = ¶ms; |
| 1325 | cmd.cmd_size_in = sizeof(params); |
| 1326 | cmd.cmd_data_out = &resp2; |
| 1327 | cmd.cmd_size_out = sizeof(resp2); |
Daisuke Nojiri | ccfa18f | 2018-04-26 12:59:58 -0700 | [diff] [blame] | 1328 | cmd.cmd_dev_index = 0; |
| 1329 | |
Daisuke Nojiri | 476c2c5 | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1330 | if (google_chromeec_command(&cmd) < 0) |
| 1331 | return -1; |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 1332 | if (resp2.svid == svid) |
Derek Huang | c0f005a | 2021-09-29 17:38:31 +0800 | [diff] [blame] | 1333 | ret |= BIT(i); |
Daisuke Nojiri | ccfa18f | 2018-04-26 12:59:58 -0700 | [diff] [blame] | 1334 | svid_idx++; |
Tim Wawrzynczak | 1966b5c80 | 2019-10-21 13:09:09 -0600 | [diff] [blame] | 1335 | } while (resp2.svid); |
Daisuke Nojiri | 476c2c5 | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1336 | } |
| 1337 | |
Derek Huang | c0f005a | 2021-09-29 17:38:31 +0800 | [diff] [blame] | 1338 | return ret; |
Daisuke Nojiri | 476c2c5 | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1339 | } |
Daisuke Nojiri | ebb86be | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1340 | |
Daisuke Nojiri | ebb86be | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1341 | #define USB_SID_DISPLAYPORT 0xff01 |
| 1342 | |
Daisuke Nojiri | d182b63 | 2018-02-16 17:50:06 -0800 | [diff] [blame] | 1343 | /** |
| 1344 | * Wait for DisplayPort to be ready |
| 1345 | * |
Derek Huang | c0f005a | 2021-09-29 17:38:31 +0800 | [diff] [blame] | 1346 | * @param timeout_ms Wait aborts after <timeout_ms> ms. |
| 1347 | * @return -1: Error. 0: Timeout. |
| 1348 | * >=1: Bitmask of the ports that DP device is connected |
Daisuke Nojiri | d182b63 | 2018-02-16 17:50:06 -0800 | [diff] [blame] | 1349 | */ |
Derek Huang | c0f005a | 2021-09-29 17:38:31 +0800 | [diff] [blame] | 1350 | int google_chromeec_wait_for_displayport(long timeout_ms) |
Daisuke Nojiri | ebb86be | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1351 | { |
| 1352 | struct stopwatch sw; |
Derek Huang | c0f005a | 2021-09-29 17:38:31 +0800 | [diff] [blame] | 1353 | int ret = 0; |
Daisuke Nojiri | ebb86be | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1354 | |
Kapil Porwal | 9a127bf | 2023-07-10 11:29:40 +0000 | [diff] [blame] | 1355 | if (google_chromeec_check_feature(EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY)) { |
| 1356 | printk(BIOS_INFO, "AP Mode Entry enabled, skip waiting for DisplayPort connection\n"); |
| 1357 | return -1; |
| 1358 | } |
| 1359 | |
Daisuke Nojiri | d182b63 | 2018-02-16 17:50:06 -0800 | [diff] [blame] | 1360 | printk(BIOS_INFO, "Waiting for DisplayPort\n"); |
Derek Huang | c0f005a | 2021-09-29 17:38:31 +0800 | [diff] [blame] | 1361 | stopwatch_init_msecs_expire(&sw, timeout_ms); |
| 1362 | while (1) { |
| 1363 | ret = google_chromeec_pd_get_amode(USB_SID_DISPLAYPORT); |
| 1364 | if (ret > 0) |
| 1365 | break; |
| 1366 | |
| 1367 | if (ret < 0) { |
| 1368 | printk(BIOS_ERR, "Can't get alternate mode!\n"); |
| 1369 | return ret; |
| 1370 | } |
| 1371 | |
Daisuke Nojiri | ebb86be | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1372 | if (stopwatch_expired(&sw)) { |
| 1373 | printk(BIOS_WARNING, |
Daisuke Nojiri | d182b63 | 2018-02-16 17:50:06 -0800 | [diff] [blame] | 1374 | "DisplayPort not ready after %ldms. Abort.\n", |
Derek Huang | c0f005a | 2021-09-29 17:38:31 +0800 | [diff] [blame] | 1375 | timeout_ms); |
Daisuke Nojiri | d182b63 | 2018-02-16 17:50:06 -0800 | [diff] [blame] | 1376 | return 0; |
Daisuke Nojiri | ebb86be | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1377 | } |
| 1378 | mdelay(200); |
| 1379 | } |
Rob Barnes | d522f38 | 2022-09-12 06:31:47 -0600 | [diff] [blame] | 1380 | printk(BIOS_INFO, "DisplayPort ready after %lld ms\n", |
Daisuke Nojiri | ebb86be | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1381 | stopwatch_duration_msecs(&sw)); |
Daisuke Nojiri | d182b63 | 2018-02-16 17:50:06 -0800 | [diff] [blame] | 1382 | |
Derek Huang | c0f005a | 2021-09-29 17:38:31 +0800 | [diff] [blame] | 1383 | return ret; |
Daisuke Nojiri | ebb86be | 2018-01-26 17:36:44 -0800 | [diff] [blame] | 1384 | } |
Rajat Jain | 89eef55 | 2020-04-10 15:48:49 -0700 | [diff] [blame] | 1385 | |
Kapil Porwal | 2ba4b1b | 2023-07-10 11:37:26 +0000 | [diff] [blame] | 1386 | /** |
| 1387 | * Check for given flag in PD mux info for a port. |
| 1388 | * |
| 1389 | * @param port Type-C port number |
| 1390 | * flag Flag to check |
| 1391 | * @return 1: Flag is set. 0: Flag is not set. |
| 1392 | */ |
| 1393 | static int google_chromeec_check_mux_flag(int port, uint8_t flag) |
Derek Huang | c0bd123 | 2021-08-25 17:19:39 +0800 | [diff] [blame] | 1394 | { |
Kapil Porwal | 2ba4b1b | 2023-07-10 11:37:26 +0000 | [diff] [blame] | 1395 | uint8_t mux_flags = 0; |
| 1396 | google_chromeec_usb_get_pd_mux_info(port, &mux_flags); |
| 1397 | if ((mux_flags & flag) == flag) |
| 1398 | return 1; |
| 1399 | return 0; |
| 1400 | } |
| 1401 | |
| 1402 | int google_chromeec_wait_for_dp_mode_entry(int port, long timeout_ms) |
| 1403 | { |
Derek Huang | c0bd123 | 2021-08-25 17:19:39 +0800 | [diff] [blame] | 1404 | struct stopwatch sw; |
| 1405 | |
Kapil Porwal | 1d85464 | 2023-07-10 11:31:59 +0000 | [diff] [blame] | 1406 | if (!google_chromeec_check_feature(EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY)) { |
Kapil Porwal | 2ba4b1b | 2023-07-10 11:37:26 +0000 | [diff] [blame] | 1407 | if (!google_chromeec_check_mux_flag(port, USB_PD_MUX_DP_ENABLED)) { |
| 1408 | printk(BIOS_WARNING, "DP mode entry is not ready. Abort.\n"); |
Kapil Porwal | 1d85464 | 2023-07-10 11:31:59 +0000 | [diff] [blame] | 1409 | return -1; |
| 1410 | } |
| 1411 | |
| 1412 | return 0; |
| 1413 | } |
| 1414 | |
Derek Huang | c0bd123 | 2021-08-25 17:19:39 +0800 | [diff] [blame] | 1415 | stopwatch_init_msecs_expire(&sw, timeout_ms); |
Kapil Porwal | 2ba4b1b | 2023-07-10 11:37:26 +0000 | [diff] [blame] | 1416 | while (!google_chromeec_check_mux_flag(port, USB_PD_MUX_DP_ENABLED)) { |
| 1417 | if (stopwatch_expired(&sw)) { |
| 1418 | printk(BIOS_WARNING, "DP not ready after %ldms. Abort.\n", timeout_ms); |
| 1419 | return -1; |
| 1420 | } |
| 1421 | mdelay(100); |
| 1422 | } |
| 1423 | printk(BIOS_INFO, "DP ready after %lld ms\n", stopwatch_duration_msecs(&sw)); |
| 1424 | |
| 1425 | return 0; |
| 1426 | } |
| 1427 | |
| 1428 | int google_chromeec_wait_for_hpd(int port, long timeout_ms) |
| 1429 | { |
| 1430 | struct stopwatch sw; |
| 1431 | |
| 1432 | if (!google_chromeec_check_feature(EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY)) { |
| 1433 | if (!google_chromeec_check_mux_flag(port, USB_PD_MUX_HPD_LVL)) { |
| 1434 | printk(BIOS_WARNING, "HPD not ready. Abort.\n"); |
| 1435 | return -1; |
| 1436 | } |
| 1437 | |
| 1438 | return 0; |
| 1439 | } |
| 1440 | |
| 1441 | stopwatch_init_msecs_expire(&sw, timeout_ms); |
| 1442 | while (!google_chromeec_check_mux_flag(port, USB_PD_MUX_HPD_LVL)) { |
Derek Huang | c0bd123 | 2021-08-25 17:19:39 +0800 | [diff] [blame] | 1443 | if (stopwatch_expired(&sw)) { |
| 1444 | printk(BIOS_WARNING, "HPD not ready after %ldms. Abort.\n", timeout_ms); |
| 1445 | return -1; |
| 1446 | } |
| 1447 | mdelay(100); |
Kapil Porwal | 2ba4b1b | 2023-07-10 11:37:26 +0000 | [diff] [blame] | 1448 | } |
Rob Barnes | d522f38 | 2022-09-12 06:31:47 -0600 | [diff] [blame] | 1449 | printk(BIOS_INFO, "HPD ready after %lld ms\n", stopwatch_duration_msecs(&sw)); |
Derek Huang | c0bd123 | 2021-08-25 17:19:39 +0800 | [diff] [blame] | 1450 | |
| 1451 | return 0; |
| 1452 | } |
| 1453 | |
Rajat Jain | 89eef55 | 2020-04-10 15:48:49 -0700 | [diff] [blame] | 1454 | int google_chromeec_get_keybd_config(struct ec_response_keybd_config *keybd) |
| 1455 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1456 | if (ec_cmd_get_keybd_config(PLAT_EC, keybd)) |
Rajat Jain | 89eef55 | 2020-04-10 15:48:49 -0700 | [diff] [blame] | 1457 | return -1; |
Rajat Jain | 89eef55 | 2020-04-10 15:48:49 -0700 | [diff] [blame] | 1458 | return 0; |
| 1459 | } |
Karthikeyan Ramasubramanian | c96d12e | 2020-08-04 16:50:02 -0600 | [diff] [blame] | 1460 | |
| 1461 | int google_chromeec_ap_reset(void) |
| 1462 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1463 | if (ec_cmd_ap_reset(NULL)) |
Karthikeyan Ramasubramanian | c96d12e | 2020-08-04 16:50:02 -0600 | [diff] [blame] | 1464 | return -1; |
| 1465 | |
| 1466 | return 0; |
| 1467 | } |
Yidi Lin | 79a812e | 2020-09-21 20:25:54 +0800 | [diff] [blame] | 1468 | |
Yidi Lin | 99e6dd9 | 2020-10-23 16:02:59 +0800 | [diff] [blame] | 1469 | int google_chromeec_regulator_enable(uint32_t index, uint8_t enable) |
| 1470 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1471 | const struct ec_params_regulator_enable params = { |
Yidi Lin | 99e6dd9 | 2020-10-23 16:02:59 +0800 | [diff] [blame] | 1472 | .index = index, |
| 1473 | .enable = enable, |
| 1474 | }; |
Yidi Lin | 99e6dd9 | 2020-10-23 16:02:59 +0800 | [diff] [blame] | 1475 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1476 | if (ec_cmd_regulator_enable(PLAT_EC, ¶ms)) |
Yidi Lin | 99e6dd9 | 2020-10-23 16:02:59 +0800 | [diff] [blame] | 1477 | return -1; |
| 1478 | |
| 1479 | return 0; |
| 1480 | } |
| 1481 | |
| 1482 | int google_chromeec_regulator_is_enabled(uint32_t index, uint8_t *enabled) |
| 1483 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1484 | const struct ec_params_regulator_is_enabled params = { |
Yidi Lin | 99e6dd9 | 2020-10-23 16:02:59 +0800 | [diff] [blame] | 1485 | .index = index, |
| 1486 | }; |
| 1487 | struct ec_response_regulator_is_enabled resp = {}; |
Yidi Lin | 99e6dd9 | 2020-10-23 16:02:59 +0800 | [diff] [blame] | 1488 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1489 | if (ec_cmd_regulator_is_enabled(PLAT_EC, ¶ms, &resp)) |
Yidi Lin | 99e6dd9 | 2020-10-23 16:02:59 +0800 | [diff] [blame] | 1490 | return -1; |
| 1491 | |
| 1492 | *enabled = resp.enabled; |
| 1493 | |
| 1494 | return 0; |
| 1495 | } |
| 1496 | |
Yidi Lin | 79a812e | 2020-09-21 20:25:54 +0800 | [diff] [blame] | 1497 | int google_chromeec_regulator_set_voltage(uint32_t index, uint32_t min_mv, |
| 1498 | uint32_t max_mv) |
| 1499 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1500 | const struct ec_params_regulator_set_voltage params = { |
Yidi Lin | 79a812e | 2020-09-21 20:25:54 +0800 | [diff] [blame] | 1501 | .index = index, |
| 1502 | .min_mv = min_mv, |
| 1503 | .max_mv = max_mv, |
| 1504 | }; |
Yidi Lin | 79a812e | 2020-09-21 20:25:54 +0800 | [diff] [blame] | 1505 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1506 | if (ec_cmd_regulator_set_voltage(PLAT_EC, ¶ms)) |
Yidi Lin | 79a812e | 2020-09-21 20:25:54 +0800 | [diff] [blame] | 1507 | return -1; |
| 1508 | |
| 1509 | return 0; |
| 1510 | } |
| 1511 | |
| 1512 | int google_chromeec_regulator_get_voltage(uint32_t index, uint32_t *voltage_mv) |
| 1513 | { |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1514 | const struct ec_params_regulator_get_voltage params = { |
Yidi Lin | 79a812e | 2020-09-21 20:25:54 +0800 | [diff] [blame] | 1515 | .index = index, |
| 1516 | }; |
| 1517 | struct ec_response_regulator_get_voltage resp = {}; |
Yidi Lin | 79a812e | 2020-09-21 20:25:54 +0800 | [diff] [blame] | 1518 | |
Caveh Jalali | beaa8f89 | 2022-11-01 01:28:31 -0700 | [diff] [blame] | 1519 | if (ec_cmd_regulator_get_voltage(PLAT_EC, ¶ms, &resp)) |
Yidi Lin | 79a812e | 2020-09-21 20:25:54 +0800 | [diff] [blame] | 1520 | return -1; |
| 1521 | |
| 1522 | *voltage_mv = resp.voltage_mv; |
| 1523 | return 0; |
| 1524 | } |
Derek Huang | c6f4738 | 2023-09-01 04:17:11 +0000 | [diff] [blame] | 1525 | |
| 1526 | void google_chromeec_clear_ec_ap_idle(void) |
| 1527 | { |
| 1528 | /* Send EC command to clear AP_IDLE flag */ |
| 1529 | if (!google_chromeec_reboot(EC_REBOOT_NO_OP, EC_REBOOT_FLAG_CLEAR_AP_IDLE | |
| 1530 | EC_REBOOT_FLAG_ON_AP_SHUTDOWN)) |
| 1531 | printk(BIOS_INFO, "Successfully clear AP_IDLE flag\n"); |
| 1532 | else |
| 1533 | printk(BIOS_ERR, "Failed to clear EC AP_IDLE flag\n"); |
| 1534 | } |
Jamie Ryu | 19080a7 | 2023-10-11 20:11:52 -0700 | [diff] [blame] | 1535 | |
| 1536 | bool google_chromeec_is_battery_present_and_above_critical_threshold(void) |
| 1537 | { |
| 1538 | struct ec_params_battery_dynamic_info params = { |
| 1539 | .index = 0, |
| 1540 | }; |
| 1541 | struct ec_response_battery_dynamic_info resp; |
| 1542 | |
| 1543 | if (ec_cmd_battery_get_dynamic(PLAT_EC, ¶ms, &resp) == 0) { |
| 1544 | /* Check if battery is present and LEVEL_CRITICAL is not set */ |
| 1545 | if (resp.flags && !(resp.flags & EC_BATT_FLAG_LEVEL_CRITICAL)) |
| 1546 | return true; |
| 1547 | } |
| 1548 | |
| 1549 | return false; |
| 1550 | } |