| // Copyright 2019 The Fuchsia 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 "dw-i2c.h" |
| |
| #include <lib/device-protocol/platform-device.h> |
| #include <lib/fake_ddk/fake_ddk.h> |
| #include <lib/sync/completion.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <threads.h> |
| #include <unistd.h> |
| #include <zircon/assert.h> |
| #include <zircon/process.h> |
| |
| #include <memory> |
| |
| #include <ddk/debug.h> |
| #include <ddk/device.h> |
| #include <ddk/mmio-buffer.h> |
| #include <ddk/platform-defs.h> |
| #include <ddk/protocol/i2cimpl.h> |
| #include <ddk/protocol/platform/bus.h> |
| #include <ddk/protocol/platform/device.h> |
| #include <fbl/algorithm.h> |
| #include <fbl/alloc_checker.h> |
| #include <fbl/array.h> |
| #include <fbl/auto_call.h> |
| #include <hw/reg.h> |
| #include <mock-mmio-reg/mock-mmio-reg.h> |
| #include <zxtest/zxtest.h> |
| |
| namespace dw_i2c { |
| |
| class DwI2cTester { |
| public: |
| static constexpr uint32_t kBufferDepth = 0x80; |
| DwI2cTester() |
| : mock_i2c_regs_(i2c_reg_array_, kRegSize, kRegBytes), |
| mmio_buffer_(mock_i2c_regs_.GetMmioBuffer()) { |
| SetupRegisters(); |
| |
| fbl::AllocChecker ac; |
| /* Create DwI2cBus instance */ |
| auto dw_i2c_bus = fbl::make_unique_checked<DwI2cBus>(&ac, std::move(mmio_buffer_), irq_); |
| ASSERT_TRUE(ac.check()); |
| ASSERT_OK(dw_i2c_bus->Init()); |
| |
| fbl::Vector<std::unique_ptr<DwI2cBus>> bus_list; |
| bus_list.push_back(std::move(dw_i2c_bus), &ac); |
| ASSERT_TRUE(ac.check()); |
| |
| /* Create DwI2c instance */ |
| dw_i2c_ = fbl::make_unique_checked<DwI2c>(&ac, fake_ddk::kFakeParent, std::move(bus_list)); |
| ASSERT_TRUE(ac.check()); |
| } |
| |
| void SetupRegisters() { |
| mock_i2c_regs_[CompTypeReg::Get().addr()].ReadReturns(DwI2cBus::kDwCompTypeNum); |
| auto comp_param = CompParam1Reg::Get().FromValue(0); |
| comp_param.set_rx_buffer_depth(kBufferDepth); |
| comp_param.set_tx_buffer_depth(kBufferDepth); |
| mock_i2c_regs_[comp_param.reg_addr()].ReadReturns(comp_param.reg_value()); |
| } |
| |
| auto GetDUT() { return std::move(dw_i2c_); } |
| |
| void VerifyAll() {} |
| |
| fake_ddk::Bind ddk; |
| |
| private: |
| static constexpr uint32_t kRegSize = sizeof(uint32_t); |
| static constexpr uint32_t kRegBytes = 0x100; |
| static constexpr uint32_t kRegCount = kRegBytes / kRegSize; |
| std::unique_ptr<DwI2c> dw_i2c_; |
| ddk_mock::MockMmioReg i2c_reg_array_[kRegCount]; |
| ddk_mock::MockMmioRegRegion mock_i2c_regs_; |
| ddk::MmioBuffer mmio_buffer_; |
| zx::interrupt irq_; |
| }; |
| |
| TEST(DwI2cTest, DdkLifecyle) { |
| DwI2cTester tester; |
| auto dut = tester.GetDUT(); |
| ASSERT_OK(dut->DdkAdd("dw-i2c")); |
| ASSERT_OK(dut->Init()); |
| dut->DdkAsyncRemove(); |
| ASSERT_TRUE(tester.ddk.Ok()); |
| } |
| |
| TEST(DwI2cTest, I2cImplGetBusCount) { |
| DwI2cTester tester; |
| auto dut = tester.GetDUT(); |
| ASSERT_OK(dut->Init()); |
| EXPECT_EQ(dut->I2cImplGetBusCount(), 1, ""); |
| tester.VerifyAll(); |
| } |
| |
| TEST(DwI2cTest, I2cImplGetMaxTransferSize) { |
| DwI2cTester tester; |
| auto dut = tester.GetDUT(); |
| ASSERT_OK(dut->Init()); |
| size_t out_size; |
| ASSERT_OK(dut->I2cImplGetMaxTransferSize(0, &out_size)); |
| EXPECT_TRUE(out_size == DwI2cTester::kBufferDepth); |
| tester.VerifyAll(); |
| } |
| |
| } // namespace dw_i2c |