193 lines
3.4 KiB
C
193 lines
3.4 KiB
C
/* Copyright 2019 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.
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include "console.h"
|
|
#include "i2c.h"
|
|
#include "i2c_bitbang.h"
|
|
#include "test_util.h"
|
|
#include "util.h"
|
|
|
|
const struct i2c_port_t i2c_bitbang_ports[] = {
|
|
{"", 0, 100, GPIO_I2C_SCL, GPIO_I2C_SDA}
|
|
};
|
|
const unsigned int i2c_bitbang_ports_used = 1;
|
|
|
|
struct pin_state {
|
|
int scl, sda;
|
|
} history[64];
|
|
|
|
int history_count;
|
|
|
|
void reset_state(void)
|
|
{
|
|
history[0] = (struct pin_state) {1, 1};
|
|
history_count = 1;
|
|
bitbang_set_started(0);
|
|
}
|
|
|
|
void gpio_set_level(enum gpio_signal signal, int level)
|
|
{
|
|
struct pin_state new = history[history_count - 1];
|
|
|
|
/* reject if stack is full */
|
|
if (history_count >= ARRAY_SIZE(history))
|
|
return;
|
|
|
|
if (signal == GPIO_I2C_SDA)
|
|
new.sda = level;
|
|
else if (signal == GPIO_I2C_SCL)
|
|
new.scl = level;
|
|
|
|
if (new.scl != history[history_count - 1].scl ||
|
|
new.sda != history[history_count - 1].sda)
|
|
history[history_count++] = new;
|
|
}
|
|
|
|
int gpio_get_level(enum gpio_signal signal)
|
|
{
|
|
if (signal == GPIO_I2C_SDA)
|
|
return history[history_count - 1].sda;
|
|
else if (signal == GPIO_I2C_SCL)
|
|
return history[history_count - 1].scl;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int test_i2c_start_stop(void)
|
|
{
|
|
struct pin_state expected[] = {
|
|
/* start */
|
|
{1, 1},
|
|
{1, 0},
|
|
{0, 0},
|
|
/* stop */
|
|
{1, 0},
|
|
{1, 1},
|
|
};
|
|
int i;
|
|
|
|
reset_state();
|
|
|
|
bitbang_start_cond(&i2c_bitbang_ports[0]);
|
|
bitbang_stop_cond(&i2c_bitbang_ports[0]);
|
|
|
|
TEST_EQ((int)ARRAY_SIZE(expected), history_count, "%d");
|
|
|
|
for (i = 0; i < ARRAY_SIZE(expected); i++) {
|
|
TEST_EQ(expected[i].scl, history[i].scl, "%d");
|
|
TEST_EQ(expected[i].sda, history[i].sda, "%d");
|
|
}
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
static int test_i2c_repeated_start(void)
|
|
{
|
|
struct pin_state expected[] = {
|
|
/* start */
|
|
{1, 1},
|
|
{1, 0},
|
|
{0, 0},
|
|
/* repeated start */
|
|
{0, 1},
|
|
{1, 1},
|
|
{1, 0},
|
|
{0, 0},
|
|
};
|
|
int i;
|
|
|
|
reset_state();
|
|
|
|
bitbang_start_cond(&i2c_bitbang_ports[0]);
|
|
bitbang_start_cond(&i2c_bitbang_ports[0]);
|
|
|
|
TEST_EQ((int)ARRAY_SIZE(expected), history_count, "%d");
|
|
|
|
for (i = 0; i < ARRAY_SIZE(expected); i++) {
|
|
TEST_EQ(expected[i].scl, history[i].scl, "%d");
|
|
TEST_EQ(expected[i].sda, history[i].sda, "%d");
|
|
}
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
static int test_i2c_write(void)
|
|
{
|
|
struct pin_state expected[] = {
|
|
/* start */
|
|
{1, 1},
|
|
{1, 0},
|
|
{0, 0},
|
|
/* bit 7: 0 */
|
|
{1, 0},
|
|
{0, 0},
|
|
/* bit 6: 1 */
|
|
{0, 1},
|
|
{1, 1},
|
|
{0, 1},
|
|
/* bit 5: 0 */
|
|
{0, 0},
|
|
{1, 0},
|
|
{0, 0},
|
|
/* bit 4: 1 */
|
|
{0, 1},
|
|
{1, 1},
|
|
{0, 1},
|
|
/* bit 3: 0 */
|
|
{0, 0},
|
|
{1, 0},
|
|
{0, 0},
|
|
/* bit 2: 1 */
|
|
{0, 1},
|
|
{1, 1},
|
|
{0, 1},
|
|
/* bit 1: 1 */
|
|
{1, 1},
|
|
{0, 1},
|
|
/* bit 0: 0 */
|
|
{0, 0},
|
|
{1, 0},
|
|
{0, 0},
|
|
/* read bit */
|
|
{0, 1},
|
|
{1, 1},
|
|
{0, 1},
|
|
/* stop */
|
|
{0, 0},
|
|
{1, 0},
|
|
{1, 1},
|
|
};
|
|
int i, ret;
|
|
|
|
reset_state();
|
|
|
|
bitbang_start_cond(&i2c_bitbang_ports[0]);
|
|
ret = bitbang_write_byte(&i2c_bitbang_ports[0], 0x56);
|
|
|
|
/* expected to fail because no slave answering the nack bit */
|
|
TEST_EQ(EC_ERROR_BUSY, ret, "%d");
|
|
|
|
TEST_EQ((int)ARRAY_SIZE(expected), history_count, "%d");
|
|
|
|
for (i = 0; i < ARRAY_SIZE(expected); i++) {
|
|
TEST_EQ(expected[i].scl, history[i].scl, "%d");
|
|
TEST_EQ(expected[i].sda, history[i].sda, "%d");
|
|
}
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
void run_test(int argc, char **argv)
|
|
{
|
|
test_reset();
|
|
|
|
RUN_TEST(test_i2c_start_stop);
|
|
RUN_TEST(test_i2c_repeated_start);
|
|
RUN_TEST(test_i2c_write);
|
|
|
|
test_print_result();
|
|
}
|