| /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| /* Peripheral stress tests */ |
| |
| #include "console.h" |
| #include "ec_commands.h" |
| #include "i2c.h" |
| #include "test_util.h" |
| #include "timer.h" |
| #include "util.h" |
| |
| #ifdef CONFIG_ADC |
| #include "adc.h" |
| #endif |
| |
| static int error_count; |
| |
| /*****************************************************************************/ |
| /* Test parameters */ |
| |
| /* I2C test */ |
| #define I2C_TEST_ITERATION 2000 |
| |
| struct i2c_test_param_t { |
| int width; /* 8 or 16 bits */ |
| int port; |
| int addr; |
| int offset; |
| int data; /* Non-negative represents data to write. -1 to read. */ |
| } i2c_test_params[] = { |
| #if defined(BOARD_PIT) |
| {8, 0, 0x90, 0x19, -1}, |
| #endif |
| }; |
| /* Disable I2C test for boards without test configuration */ |
| #if defined(BOARD_BDS) || defined(BOARD_AURON) |
| #undef CONFIG_I2C |
| #endif |
| |
| /* ADC test */ |
| #define ADC_TEST_ITERATION 2000 |
| |
| /*****************************************************************************/ |
| /* Test utilities */ |
| |
| /* period between 500us and 32ms */ |
| #define RAND_US() (((prng_no_seed() % 64) + 1) * 500) |
| |
| static int stress(const char *name, |
| int (*test_routine)(void), |
| const int iteration) |
| { |
| int i; |
| |
| for (i = 0; i < iteration; ++i) { |
| if (i % 10 == 0) { |
| ccprintf("\r%s...%d/%d", name, i, iteration); |
| usleep(RAND_US()); |
| } |
| if (test_routine() != EC_SUCCESS) |
| return EC_ERROR_UNKNOWN; |
| } |
| |
| ccprintf("\r%s...%d/%d\n", name, iteration, iteration); |
| return EC_SUCCESS; |
| } |
| |
| #define RUN_STRESS_TEST(n, r, iter) \ |
| do { \ |
| if (stress(n, r, iter) != EC_SUCCESS) { \ |
| ccputs("Fail\n"); \ |
| error_count++; \ |
| } \ |
| } while (0) |
| |
| /*****************************************************************************/ |
| /* Tests */ |
| #ifdef CONFIG_I2C_MASTER |
| static int test_i2c(void) |
| { |
| int res = EC_ERROR_UNKNOWN; |
| int dummy_data; |
| struct i2c_test_param_t *param; |
| param = i2c_test_params + (prng_no_seed() % (sizeof(i2c_test_params) / |
| sizeof(struct i2c_test_param_t))); |
| if (param->width == 8 && param->data == -1) |
| res = i2c_read8(param->port, param->addr, |
| param->offset, &dummy_data); |
| else if (param->width == 8 && param->data >= 0) |
| res = i2c_write8(param->port, param->addr, |
| param->offset, param->data); |
| else if (param->width == 16 && param->data == -1) |
| res = i2c_read16(param->port, param->addr, |
| param->offset, &dummy_data); |
| else if (param->width == 16 && param->data >= 0) |
| res = i2c_write16(param->port, param->addr, |
| param->offset, param->data); |
| else if (param->width == 32 && param->data == -1) |
| res = i2c_read32(param->port, param->addr, |
| param->offset, &dummy_data); |
| else if (param->width == 32 && param->data >= 0) |
| res = i2c_write32(param->port, param->addr, |
| param->offset, param->data); |
| |
| return res; |
| } |
| #endif |
| |
| #ifdef CONFIG_ADC |
| __attribute__((weak)) int adc_read_all_channels(int *data) |
| { |
| int i; |
| int rv = EC_SUCCESS; |
| |
| for (i = 0; i < ADC_CH_COUNT; ++i) { |
| data[i] = adc_read_channel(i); |
| if (data[i] == ADC_READ_ERROR) |
| rv = EC_ERROR_UNKNOWN; |
| } |
| |
| return rv; |
| } |
| |
| static int test_adc(void) |
| { |
| int data[ADC_CH_COUNT]; |
| return adc_read_all_channels(data); |
| } |
| #endif |
| |
| void run_test(void) |
| { |
| test_reset(); |
| |
| #ifdef CONFIG_I2C_MASTER |
| RUN_STRESS_TEST("I2C Stress Test", test_i2c, I2C_TEST_ITERATION); |
| #endif |
| #ifdef CONFIG_ADC |
| RUN_STRESS_TEST("ADC Stress Test", test_adc, ADC_TEST_ITERATION); |
| #endif |
| |
| test_print_result(); |
| } |