1// Copyright 2018 The Fuchsia 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#pragma once
6
7#include <ddk/protocol/i2c.h>
8
9#include <ddktl/device.h>
10#include <ddktl/protocol/i2c-impl.h>
11
12#include <fbl/atomic.h>
13#include <fbl/unique_ptr.h>
14
15#include <hw/reg.h>
16#include <hwreg/mmio.h>
17
18namespace imx_i2c {
19
20class ImxI2cDevice;
21using DeviceType = ddk::Device<ImxI2cDevice, ddk::Unbindable>;
22
23class ImxI2cDevice : public DeviceType,
24                     public ddk::I2cImplProtocol<ImxI2cDevice> {
25public:
26    ImxI2cDevice(zx_device_t* parent, int dev_cnt)
27        : DeviceType(parent), dev_cnt_(dev_cnt) {}
28
29    zx_status_t Bind(int id);
30
31    // Methods required by the ddk mixins
32    void DdkUnbind();
33    void DdkRelease();
34    uint32_t I2cImplGetBusCount();
35    zx_status_t I2cImplGetMaxTransferSize(uint32_t bus_id, size_t* out_size);
36    zx_status_t I2cImplSetBitRate(uint32_t bus_id, uint32_t bitrate);
37    zx_status_t I2cImplTransact(uint32_t bus_id, i2c_impl_op_t* ops, size_t count);
38
39private:
40    enum class Wait {
41        kBusy,
42        kIdle,
43        kInterruptPending
44    };
45    static constexpr const char* WaitStr(Wait type) {
46        switch (type) {
47        case Wait::kBusy:
48            return "BUSY";
49        case Wait::kIdle:
50            return "IDLE";
51        case Wait::kInterruptPending:
52            return "INTERRUPT_PENDING";
53        }
54        return "UNKNOWN";
55    }
56    const uint32_t dev_cnt_;
57    thrd_t thread_;
58    io_buffer_t regs_iobuff_;
59    fbl::unique_ptr<hwreg::RegisterIo> mmio_;
60    fbl::atomic<bool> ready_;
61
62    void Reset();
63    zx_status_t Read(uint8_t addr, void* buf, size_t len, bool stop);
64    zx_status_t Write(uint8_t addr, const void* buf, size_t len, bool stop);
65    zx_status_t Start();
66    void Stop();
67    zx_status_t RxData(uint8_t* buf, size_t length, bool stop);
68    zx_status_t TxData(const uint8_t* buf, size_t length, bool stop);
69    zx_status_t TxAddress(uint8_t addr, bool is_read);
70    zx_status_t WaitFor(Wait type);
71    int Thread();
72    void ShutDown();
73};
74} // namespace imx_i2c
75