Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 1 | # Copyright 2017 The Chromium OS Authors. All rights reserved. |
| 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
| 4 | |
| 5 | import logging |
| 6 | import pprint |
| 7 | import time |
Mary Ruthven | 992c8db | 2018-05-07 11:28:57 -0700 | [diff] [blame] | 8 | import re |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 9 | |
| 10 | from autotest_lib.client.common_lib import error |
| 11 | from autotest_lib.server import autotest |
Mary Ruthven | 9b09406 | 2018-04-25 17:39:20 -0700 | [diff] [blame] | 12 | from autotest_lib.server.cros.faft.cr50_test import Cr50Test |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 13 | |
| 14 | |
Mary Ruthven | 9b09406 | 2018-04-25 17:39:20 -0700 | [diff] [blame] | 15 | class firmware_Cr50DeviceState(Cr50Test): |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 16 | """Verify Cr50 tracks the EC and AP state correctly. |
| 17 | |
Mary Ruthven | 7bd39a8 | 2018-01-12 10:09:31 -0800 | [diff] [blame] | 18 | Put the device through S0, S0ix, S3, and G3. Cr50 responds to these state |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 19 | changes by enabling/disabling uart and changing its suspend type. Verify |
| 20 | that none of these cause any interrupt storms on Cr50. Make sure that there |
| 21 | aren't any interrupt storms and that Cr50 enters regular or deep sleep a |
| 22 | reasonable amount of times. |
| 23 | """ |
| 24 | version = 1 |
| 25 | |
| 26 | DEEP_SLEEP_STEP_SUFFIX = ' Num Deep Sleep Steps' |
| 27 | |
| 28 | # Use negative numbers to keep track of counts not in the IRQ list. |
| 29 | KEY_DEEP_SLEEP = -3 |
| 30 | KEY_TIME = -2 |
| 31 | KEY_RESET = -1 |
| 32 | KEY_REGULAR_SLEEP = 112 |
| 33 | INT_NAME = { |
| 34 | KEY_RESET : 'Reset Count', |
| 35 | KEY_DEEP_SLEEP : 'Deep Sleep Count', |
| 36 | KEY_TIME : 'Cr50 Time', |
| 37 | 4 : 'HOST_CMD_DONE', |
| 38 | 81 : 'GPIO0', |
| 39 | 98 : 'GPIO1', |
| 40 | 103 : 'I2CS WRITE', |
| 41 | KEY_REGULAR_SLEEP : 'PMU WAKEUP', |
Mary Ruthven | 9c5349d | 2018-01-12 12:39:24 -0800 | [diff] [blame] | 42 | 113 : 'AC present FED', |
| 43 | 114 : 'AC present RED', |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 44 | 124 : 'RBOX_INTR_PWRB', |
Mary Ruthven | 9c5349d | 2018-01-12 12:39:24 -0800 | [diff] [blame] | 45 | 130 : 'SPS CS deassert', |
| 46 | 138 : 'SPS RXFIFO LVL', |
| 47 | 159 : 'SPS RXFIFO overflow', |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 48 | 160 : 'EVENT TIMER', |
| 49 | 174 : 'CR50_RX_SERVO_TX', |
| 50 | 177 : 'CR50_TX_SERVO_RX', |
| 51 | 181 : 'AP_TX_CR50_RX', |
| 52 | 184 : 'AP_RX_CR50_TX', |
| 53 | 188 : 'EC_TX_CR50_RX', |
| 54 | 191 : 'EC_RX_CR50_TX', |
| 55 | 193 : 'USB', |
| 56 | } |
Mary Ruthven | f6c4509 | 2018-01-29 15:35:10 -0800 | [diff] [blame] | 57 | SLEEP_KEYS = [ KEY_REGULAR_SLEEP, KEY_DEEP_SLEEP ] |
Mary Ruthven | aef9067 | 2018-01-12 15:16:55 -0800 | [diff] [blame] | 58 | # Cr50 won't enable any form of sleep until it has been up for 20 seconds. |
| 59 | SLEEP_DELAY = 20 |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 60 | # The time in seconds to wait in each state |
| 61 | SLEEP_TIME = 30 |
| 62 | SHORT_WAIT = 5 |
| 63 | CONSERVATIVE_WAIT_TIME = SLEEP_TIME + SHORT_WAIT + 10 |
| 64 | # Cr50 should wake up twice per second while in regular sleep |
| 65 | SLEEP_RATE = 2 |
| 66 | |
Mary Ruthven | 8e2d6f5 | 2018-02-21 14:44:36 -0800 | [diff] [blame] | 67 | DEEP_SLEEP_MAX = 2 |
Mary Ruthven | 9c5349d | 2018-01-12 12:39:24 -0800 | [diff] [blame] | 68 | ARM = 'ARM ' |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 69 | |
| 70 | # If there are over 100,000 interrupts, it is an interrupt storm. |
| 71 | DEFAULT_COUNTS = [0, 100000] |
| 72 | # A dictionary of ok count values for each irq that shouldn't follow the |
| 73 | # DEFAULT_COUNTS range. |
| 74 | EXPECTED_IRQ_COUNT_RANGE = { |
| 75 | KEY_RESET : [0, 0], |
| 76 | KEY_DEEP_SLEEP : [0, DEEP_SLEEP_MAX], |
| 77 | KEY_TIME : [0, CONSERVATIVE_WAIT_TIME], |
Mary Ruthven | e989f3d | 2018-05-10 14:16:44 -0700 | [diff] [blame] | 78 | 'S0ix' + DEEP_SLEEP_STEP_SUFFIX : [0, 0], |
Mary Ruthven | 8e2d6f5 | 2018-02-21 14:44:36 -0800 | [diff] [blame] | 79 | # Cr50 may enter deep sleep an extra time, because of how the test |
| 80 | # collects taskinfo counts. Just verify that it does enter deep sleep |
Mary Ruthven | e989f3d | 2018-05-10 14:16:44 -0700 | [diff] [blame] | 81 | 'S3' + DEEP_SLEEP_STEP_SUFFIX : [1, 2], |
| 82 | 'G3' + DEEP_SLEEP_STEP_SUFFIX : [1, 2], |
Mary Ruthven | 8e2d6f5 | 2018-02-21 14:44:36 -0800 | [diff] [blame] | 83 | # ARM devices don't enter deep sleep in S3 |
| 84 | ARM + 'S3' + DEEP_SLEEP_STEP_SUFFIX : [0, 0], |
| 85 | ARM + 'G3' + DEEP_SLEEP_STEP_SUFFIX : [1, 2], |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 86 | # Regular sleep is calculated based on the cr50 time |
| 87 | } |
| 88 | |
| 89 | GET_TASKINFO = ['IRQ counts by type:(.*)Service calls'] |
| 90 | |
| 91 | START = '' |
| 92 | INCREASE = '+' |
| 93 | DS_RESUME = 'DS' |
| 94 | |
Mary Ruthven | eb417f2 | 2018-04-05 17:29:51 -0700 | [diff] [blame] | 95 | def cleanup(self): |
| 96 | """Make sure the device is on at the end of the test.""" |
| 97 | self.trigger_s0() |
| 98 | super(firmware_Cr50DeviceState, self).cleanup() |
| 99 | |
| 100 | |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 101 | def get_taskinfo_output(self): |
| 102 | """Return a dict with the irq numbers as keys and counts as values""" |
| 103 | output = self.cr50.send_command_get_output('taskinfo', |
| 104 | self.GET_TASKINFO)[0][1].strip() |
Mary Ruthven | 992c8db | 2018-05-07 11:28:57 -0700 | [diff] [blame] | 105 | logging.info(output) |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 106 | return output |
| 107 | |
| 108 | |
| 109 | def get_irq_counts(self): |
| 110 | """Return a dict with the irq numbers as keys and counts as values""" |
| 111 | output = self.get_taskinfo_output() |
Mary Ruthven | 992c8db | 2018-05-07 11:28:57 -0700 | [diff] [blame] | 112 | irq_list = re.findall('\d+\s+\d+\r', output) |
Mary Ruthven | f6c4509 | 2018-01-29 15:35:10 -0800 | [diff] [blame] | 113 | # Make sure the regular sleep irq is in the dictionary, even if cr50 |
| 114 | # hasn't seen any interrupts. It's important the test sees that there's |
| 115 | # never an interrupt. |
| 116 | irq_counts = { self.KEY_REGULAR_SLEEP : 0 } |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 117 | for irq_info in irq_list: |
Mary Ruthven | 992c8db | 2018-05-07 11:28:57 -0700 | [diff] [blame] | 118 | logging.debug(irq_info) |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 119 | num, count = irq_info.split() |
| 120 | irq_counts[int(num)] = int(count) |
| 121 | irq_counts[self.KEY_RESET] = int(self.servo.get('cr50_reset_count')) |
| 122 | irq_counts[self.KEY_DEEP_SLEEP] = int(self.cr50.get_deep_sleep_count()) |
| 123 | irq_counts[self.KEY_TIME] = int(self.cr50.gettime()) |
| 124 | return irq_counts |
| 125 | |
| 126 | |
| 127 | def get_expected_count(self, irq_key, cr50_time): |
| 128 | """Get the expected irq increase for the given irq and state |
| 129 | |
| 130 | Args: |
| 131 | irq_key: the irq int |
| 132 | cr50_time: the cr50 time in seconds |
| 133 | |
| 134 | Returns: |
| 135 | A list with the expected irq count range [min, max] |
| 136 | """ |
Mary Ruthven | f6c4509 | 2018-01-29 15:35:10 -0800 | [diff] [blame] | 137 | # CCD will prevent sleep |
Mary Ruthven | eb9afff | 2018-02-21 17:56:42 -0800 | [diff] [blame] | 138 | if self.ccd_enabled and (irq_key in self.SLEEP_KEYS or |
| 139 | self.DEEP_SLEEP_STEP_SUFFIX in str(irq_key)): |
Mary Ruthven | f6c4509 | 2018-01-29 15:35:10 -0800 | [diff] [blame] | 140 | return [0, 0] |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 141 | if irq_key == self.KEY_REGULAR_SLEEP: |
Mary Ruthven | f149055 | 2018-04-18 16:13:29 -0700 | [diff] [blame] | 142 | # If cr50_time is really low, we probably woke cr50 up using |
| 143 | # taskinfo, which would be a pmu wakeup. |
| 144 | if cr50_time == 0: |
| 145 | return [0, 1] |
| 146 | |
Mary Ruthven | aef9067 | 2018-01-12 15:16:55 -0800 | [diff] [blame] | 147 | min_count = max(cr50_time - self.SLEEP_DELAY, 0) |
| 148 | # Just checking there is not a lot of extra sleep wakeups. Add 1 to |
| 149 | # the sleep rate so cr50 can have some extra wakeups, but not too |
| 150 | # many. |
| 151 | max_count = cr50_time * (self.SLEEP_RATE + 1) |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 152 | return [min_count, max_count] |
| 153 | return self.EXPECTED_IRQ_COUNT_RANGE.get(irq_key, self.DEFAULT_COUNTS) |
| 154 | |
| 155 | |
| 156 | def check_increase(self, irq_key, name, increase, expected_range): |
| 157 | """Verify the irq count is within the expected range |
| 158 | |
| 159 | Args: |
| 160 | irq_key: the irq int |
| 161 | name: the irq name string |
| 162 | increase: the irq count |
| 163 | expected_range: A list with the valid irq count range [min, max] |
| 164 | |
| 165 | Returns: |
| 166 | '' if increase is in the given range. If the increase isn't in the |
| 167 | range, it returns an error message. |
| 168 | """ |
| 169 | min_count, max_count = expected_range |
| 170 | if min_count > increase or max_count < increase: |
| 171 | err_msg = '%s %s: %s not in range %s' % (name, irq_key, increase, |
| 172 | expected_range) |
| 173 | return err_msg |
| 174 | return '' |
| 175 | |
| 176 | |
| 177 | def get_step_events(self): |
| 178 | """Use the deep sleep counts to determine the step events""" |
| 179 | ds_counts = self.get_irq_step_counts(self.KEY_DEEP_SLEEP) |
| 180 | events = [] |
| 181 | for i, count in enumerate(ds_counts): |
| 182 | if not i: |
| 183 | events.append(self.START) |
| 184 | elif count != ds_counts[i - 1]: |
| 185 | # If the deep sleep count changed, Cr50 recovered deep sleep |
| 186 | # and the irq counts are reset. |
| 187 | events.append(self.DS_RESUME) |
| 188 | else: |
| 189 | events.append(self.INCREASE) |
| 190 | return events |
| 191 | |
| 192 | |
| 193 | def get_irq_step_counts(self, irq_key): |
| 194 | """Get a list of the all of the step counts for the given irq""" |
| 195 | return [ irq_dict.get(irq_key, 0) for irq_dict in self.steps ] |
| 196 | |
| 197 | |
Mary Ruthven | 6a4a9bc | 2018-01-12 10:29:06 -0800 | [diff] [blame] | 198 | def check_for_errors(self, state): |
| 199 | """Check for unexpected IRQ counts at each step. |
| 200 | |
Mary Ruthven | f6c4509 | 2018-01-29 15:35:10 -0800 | [diff] [blame] | 201 | Find the irq count errors and add them to run_errors. |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 202 | |
| 203 | Args: |
Mary Ruthven | 7bd39a8 | 2018-01-12 10:09:31 -0800 | [diff] [blame] | 204 | state: The power state: S0, S0ix, S3, or G3. |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 205 | """ |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 206 | num_steps = len(self.steps) |
| 207 | # Get all of the deep sleep counts |
| 208 | events = self.get_step_events() |
| 209 | |
| 210 | irq_list = list(self.irqs) |
| 211 | irq_list.sort() |
| 212 | |
Mary Ruthven | 9c5349d | 2018-01-12 12:39:24 -0800 | [diff] [blame] | 213 | irq_diff = ['%23s' % 'step' + ''.join(self.step_names)] |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 214 | step_errors = [ [] for i in range(num_steps) ] |
| 215 | |
| 216 | cr50_times = self.get_irq_step_counts(self.KEY_TIME) |
| 217 | cr50_diffs = [] |
| 218 | for i, cr50_time in enumerate(cr50_times): |
| 219 | if events[i] == self.INCREASE: |
| 220 | cr50_time -= cr50_times[i - 1] |
| 221 | cr50_diffs.append(cr50_time) |
| 222 | |
| 223 | # Go through each irq and update its info in the progress dict |
| 224 | for irq_key in irq_list: |
| 225 | name = self.INT_NAME.get(irq_key, 'Unknown') |
Mary Ruthven | 9c5349d | 2018-01-12 12:39:24 -0800 | [diff] [blame] | 226 | irq_progress_str = ['%19s %3s:' % (name, irq_key)] |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 227 | |
| 228 | irq_counts = self.get_irq_step_counts(irq_key) |
| 229 | for step, count in enumerate(irq_counts): |
| 230 | event = events[step] |
| 231 | |
| 232 | # The deep sleep counts are not reset after deep sleep. Change |
| 233 | # the event to INCREASE. |
| 234 | if irq_key == self.KEY_DEEP_SLEEP and event == self.DS_RESUME: |
| 235 | event = self.INCREASE |
| 236 | |
| 237 | if event == self.INCREASE: |
| 238 | count -= irq_counts[step - 1] |
| 239 | |
| 240 | # Check that the count increase is within the expected value. |
| 241 | if event != self.START: |
| 242 | expected_range = self.get_expected_count(irq_key, |
| 243 | cr50_diffs[step]) |
| 244 | |
| 245 | rv = self.check_increase(irq_key, name, count, |
| 246 | expected_range) |
| 247 | if rv: |
| 248 | logging.info('Unexpected count for %s %s', state, rv) |
| 249 | step_errors[step].append(rv) |
| 250 | |
| 251 | irq_progress_str.append(' %2s %7d' % (event, count)) |
| 252 | |
| 253 | irq_diff.append(''.join(irq_progress_str)) |
| 254 | |
| 255 | errors = {} |
| 256 | |
Mary Ruthven | 9c5349d | 2018-01-12 12:39:24 -0800 | [diff] [blame] | 257 | ds_key = self.ARM if self.is_arm else '' |
| 258 | ds_key += state + self.DEEP_SLEEP_STEP_SUFFIX |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 259 | expected_range = self.get_expected_count(ds_key, 0) |
| 260 | rv = self.check_increase(None, ds_key, events.count(self.DS_RESUME), |
| 261 | expected_range) |
| 262 | if rv: |
| 263 | logging.info('Unexpected count for %s %s', state, rv) |
| 264 | errors[ds_key] = rv |
| 265 | for i, step_error in enumerate(step_errors): |
| 266 | if step_error: |
| 267 | logging.error('Step %d errors:\n%s', i, |
| 268 | pprint.pformat(step_error)) |
| 269 | step = '%s step %d %s' % (state, i, self.step_names[i].strip()) |
| 270 | errors[step] = step_error |
| 271 | |
| 272 | logging.info('DIFF %s IRQ Counts:\n%s', state, pprint.pformat(irq_diff)) |
| 273 | if errors: |
| 274 | logging.info('ERRORS %s IRQ Counts:\n%s', state, |
| 275 | pprint.pformat(errors)) |
Mary Ruthven | f6c4509 | 2018-01-29 15:35:10 -0800 | [diff] [blame] | 276 | self.run_errors.update(errors) |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 277 | |
| 278 | |
Mary Ruthven | eb417f2 | 2018-04-05 17:29:51 -0700 | [diff] [blame] | 279 | def trigger_s0(self): |
| 280 | """Press the power button so the DUT will wake up.""" |
| 281 | self.servo.power_short_press() |
| 282 | |
| 283 | |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 284 | def enter_state(self, state): |
| 285 | """Get the command to enter the power state""" |
| 286 | self.stage_irq_add(self.get_irq_counts(), 'start %s' % state) |
| 287 | if state == 'S0': |
Mary Ruthven | eb417f2 | 2018-04-05 17:29:51 -0700 | [diff] [blame] | 288 | self.trigger_s0() |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 289 | else: |
| 290 | if state == 'S0ix': |
| 291 | full_command = 'echo freeze > /sys/power/state &' |
| 292 | elif state == 'S3': |
| 293 | full_command = 'echo mem > /sys/power/state &' |
Mary Ruthven | 7bd39a8 | 2018-01-12 10:09:31 -0800 | [diff] [blame] | 294 | elif state == 'G3': |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 295 | full_command = 'poweroff' |
| 296 | self.faft_client.system.run_shell_command(full_command) |
| 297 | |
| 298 | time.sleep(self.SHORT_WAIT); |
| 299 | # check S3 state transition |
Mary Ruthven | 6a4a9bc | 2018-01-12 10:29:06 -0800 | [diff] [blame] | 300 | if not self.wait_power_state(state, self.SHORT_WAIT): |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 301 | raise error.TestFail('Platform failed to reach %s state.' % state) |
| 302 | self.stage_irq_add(self.get_irq_counts(), 'in %s' % state) |
| 303 | |
| 304 | |
| 305 | def stage_irq_add(self, irq_dict, name=''): |
| 306 | """Add the current irq counts to the stored dictionary of irq info""" |
| 307 | self.steps.append(irq_dict) |
| 308 | self.step_names.append('%11s' % name) |
| 309 | self.irqs.update(irq_dict.keys()) |
| 310 | |
| 311 | |
| 312 | def reset_irq_counts(self): |
| 313 | """Reset the test IRQ counts""" |
| 314 | self.steps = [] |
| 315 | self.step_names = [] |
| 316 | self.irqs = set() |
| 317 | |
| 318 | |
| 319 | def run_transition(self, state): |
Mary Ruthven | 6e0a32c | 2018-05-10 14:39:26 -0700 | [diff] [blame] | 320 | """Enter the given power state and reenter s0 |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 321 | |
Mary Ruthven | 6e0a32c | 2018-05-10 14:39:26 -0700 | [diff] [blame] | 322 | Enter the power state and return to S0. Wait long enough to ensure cr50 |
| 323 | will enter sleep mode, so we can verify that as well. |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 324 | |
| 325 | Args: |
Mary Ruthven | 7bd39a8 | 2018-01-12 10:09:31 -0800 | [diff] [blame] | 326 | state: the power state: S0ix, S3, or G3 |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 327 | """ |
| 328 | self.reset_irq_counts() |
| 329 | |
| 330 | # Enter the given state |
| 331 | self.enter_state(state) |
| 332 | |
| 333 | logging.info('waiting %d seconds', self.SLEEP_TIME) |
| 334 | time.sleep(self.SLEEP_TIME) |
| 335 | |
| 336 | # Return to S0 |
| 337 | self.enter_state('S0') |
| 338 | |
Mary Ruthven | 6e0a32c | 2018-05-10 14:39:26 -0700 | [diff] [blame] | 339 | |
| 340 | def verify_state(self, state): |
| 341 | """Verify cr50 behavior while running through the power state""" |
| 342 | |
| 343 | try: |
| 344 | self.run_transition(state) |
| 345 | finally: |
| 346 | # reset the system to S0 no matter what happens |
| 347 | self.trigger_s0() |
| 348 | |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 349 | # Check that the progress of the irq counts seems reasonable |
Mary Ruthven | 6a4a9bc | 2018-01-12 10:29:06 -0800 | [diff] [blame] | 350 | self.check_for_errors(state) |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 351 | |
Mary Ruthven | f6c4509 | 2018-01-29 15:35:10 -0800 | [diff] [blame] | 352 | |
| 353 | def is_arm_family(self): |
| 354 | """Returns True if the DUT is an ARM device.""" |
| 355 | arch = self.host.run('arch').stdout.strip() |
Mary Ruthven | 9c5349d | 2018-01-12 12:39:24 -0800 | [diff] [blame] | 356 | return arch in ['aarch64', 'armv7l'] |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 357 | |
Mary Ruthven | f6c4509 | 2018-01-29 15:35:10 -0800 | [diff] [blame] | 358 | |
| 359 | def run_through_power_states(self): |
Mary Ruthven | 7bd39a8 | 2018-01-12 10:09:31 -0800 | [diff] [blame] | 360 | """Go through S0ix, S3, and G3. Verify there are no interrupt storms""" |
Mary Ruthven | f6c4509 | 2018-01-29 15:35:10 -0800 | [diff] [blame] | 361 | self.run_errors = {} |
| 362 | self.ccd_str = 'ccd ' + ('enabled' if self.ccd_enabled else 'disabled') |
| 363 | logging.info('Running through states with %s', self.ccd_str) |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 364 | |
| 365 | # Initialize the Test IRQ counts |
| 366 | self.reset_irq_counts() |
| 367 | |
| 368 | # Make sure the DUT is in s0 |
| 369 | self.enter_state('S0') |
| 370 | |
Mary Ruthven | ca1df1a | 2018-05-04 18:23:11 -0700 | [diff] [blame] | 371 | # Check if the device supports S0ix. The exit status will be 0 if it |
| 372 | # does 1 if it doesn't. |
| 373 | result = self.host.run('check_powerd_config --suspend_to_idle', |
| 374 | ignore_status=True) |
| 375 | if not result.exit_status: |
| 376 | # Login before entering S0ix so cr50 will be able to enter regular |
| 377 | # sleep |
Mary Ruthven | f6c4509 | 2018-01-29 15:35:10 -0800 | [diff] [blame] | 378 | client_at = autotest.Autotest(self.host) |
Mary Ruthven | 9c5349d | 2018-01-12 12:39:24 -0800 | [diff] [blame] | 379 | client_at.run_test('login_LoginSuccess') |
Mary Ruthven | 6e0a32c | 2018-05-10 14:39:26 -0700 | [diff] [blame] | 380 | self.verify_state('S0ix') |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 381 | |
| 382 | # Enter S3 |
Mary Ruthven | 6e0a32c | 2018-05-10 14:39:26 -0700 | [diff] [blame] | 383 | self.verify_state('S3') |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 384 | |
Mary Ruthven | 7bd39a8 | 2018-01-12 10:09:31 -0800 | [diff] [blame] | 385 | # Enter G3 |
Mary Ruthven | 6e0a32c | 2018-05-10 14:39:26 -0700 | [diff] [blame] | 386 | self.verify_state('G3') |
Mary Ruthven | f6c4509 | 2018-01-29 15:35:10 -0800 | [diff] [blame] | 387 | if self.run_errors: |
| 388 | self.all_errors[self.ccd_str] = self.run_errors |
| 389 | |
| 390 | |
| 391 | def run_once(self, host): |
| 392 | """Go through S0ix, S3, and G3. Verify there are no interrupt storms""" |
| 393 | self.all_errors = {} |
| 394 | self.host = host |
| 395 | self.is_arm = self.is_arm_family() |
Mary Ruthven | f149055 | 2018-04-18 16:13:29 -0700 | [diff] [blame] | 396 | supports_dts_control = self.cr50.servo_v4_supports_dts_mode() |
| 397 | |
| 398 | if supports_dts_control: |
| 399 | self.cr50.ccd_disable(raise_error=True) |
| 400 | |
Mary Ruthven | f6c4509 | 2018-01-29 15:35:10 -0800 | [diff] [blame] | 401 | self.ccd_enabled = self.cr50.ccd_is_enabled() |
| 402 | self.run_through_power_states() |
| 403 | |
Mary Ruthven | f149055 | 2018-04-18 16:13:29 -0700 | [diff] [blame] | 404 | if supports_dts_control: |
| 405 | ccd_was_enabled = self.ccd_enabled |
| 406 | self.cr50.ccd_enable(raise_error=supports_dts_control) |
| 407 | self.ccd_enabled = self.cr50.ccd_is_enabled() |
| 408 | # If the first run had ccd disabled, and the test was able to enable |
| 409 | # ccd, run through the states again to make sure there are no issues |
| 410 | # come up when ccd is enabled. |
| 411 | if not ccd_was_enabled and self.ccd_enabled: |
| 412 | # Reboot the EC to reset the device |
| 413 | self.ec.reboot() |
| 414 | self.run_through_power_states() |
| 415 | else: |
| 416 | logging.info('Current setup only supports test with ccd %sabled.', |
| 417 | 'en' if self.ccd_enabled else 'dis') |
Mary Ruthven | 9bf599e | 2017-10-13 16:47:06 -0700 | [diff] [blame] | 418 | |
Mary Ruthven | ea1222e | 2018-10-30 10:05:54 -0700 | [diff] [blame^] | 419 | self.trigger_s0() |
Mary Ruthven | 6a4a9bc | 2018-01-12 10:29:06 -0800 | [diff] [blame] | 420 | if self.all_errors: |
Mary Ruthven | 9d4ba2a | 2018-05-04 17:52:43 -0700 | [diff] [blame] | 421 | raise error.TestFail('Unexpected Device State: %s' % |
| 422 | self.all_errors) |
Mary Ruthven | f149055 | 2018-04-18 16:13:29 -0700 | [diff] [blame] | 423 | if not supports_dts_control: |
| 424 | raise error.TestNAError('Verified device state with %s. Please ' |
| 425 | 'run with type c servo v4 to test full device state.' % |
| 426 | self.ccd_str) |