blob: 06871bdcfd44f500fdda2ce4fbcc67a8b3a02488 [file] [log] [blame]
// 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.
#ifndef SRC_DEVICES_SERIAL_DRIVERS_FTDI_FTDI_MPSSE_H_
#define SRC_DEVICES_SERIAL_DRIVERS_FTDI_FTDI_MPSSE_H_
#include <lib/sync/completion.h>
#include <lib/zx/event.h>
#include <lib/zx/time.h>
#include <stdint.h>
#include <threads.h>
#include <zircon/types.h>
#include <vector>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddktl/protocol/serialimpl.h>
namespace ftdi_mpsse {
// This class represents FTDI's Multi-Process Synchronous Serial Engine.
// It is responsible for Reading and Writing to the underlying Serial driver.
// It is also responsible for doing setup work for things like GPIO pins
// and clock commands.
class Mpsse {
public:
enum Direction {
IN,
OUT,
};
enum Level {
HIGH,
LOW,
};
Mpsse(zx_device_t* parent) : ftdi_(parent) {}
zx_status_t Init();
zx_status_t IsValid() { return ftdi_.is_valid(); }
zx_status_t Sync();
zx_status_t Read(uint8_t* buf, size_t len);
zx_status_t Write(uint8_t* buf, size_t len);
zx_status_t SetGpio(int pin, Direction dir, Level lvl);
void GpioWriteCommandToBuffer(size_t index, std::vector<uint8_t>* buffer, size_t* bytes_written);
zx_status_t FlushGpio();
zx_status_t SetClock(bool adaptive, bool three_phase, int hz);
private:
static void NotifyCallback(void* ctx, serial_state_t state);
// Commands to set the GPIO pins levels and directions. Must be followed
// by one byte of gpio levels and one byte of gpio directions. Lower pins
// are pins 0-7 and higher pins are pins 8-15.
static constexpr uint8_t kGpioSetCommandLowerPins = 0x80;
static constexpr uint8_t kGpioSetCommandHigherPins = 0x82;
static constexpr uint8_t kClockSetCommandByte1 = 0x8A;
static constexpr uint8_t kClockSetCommandByte2 = 0x97;
static constexpr uint8_t kClockSetCommandByte2AdaptiveOn = 0x96;
static constexpr uint8_t kClockSetCommandByte3 = 0x8D;
static constexpr uint8_t kClockSetCommandByte3ThreePhaseOn = 0x8C;
static constexpr uint8_t kClockSetCommandByte4 = 0x86;
static constexpr uint8_t kMpsseErrorInvalidCommand = 0xFA;
static constexpr zx::duration kSerialReadWriteTimeout = zx::sec(1);
static constexpr zx_signals_t kMpsseSignalReadable = ZX_USER_SIGNAL_0;
static constexpr zx_signals_t kMpsseSignalWritable = ZX_USER_SIGNAL_1;
ddk::SerialImplProtocolClient ftdi_ = {};
uint16_t gpio_levels_ = 0;
uint16_t gpio_directions_ = 0;
sync_completion_t serial_readable_;
sync_completion_t serial_writable_;
serial_notify_t notify_cb_ = {};
};
} // namespace ftdi_mpsse
#endif // SRC_DEVICES_SERIAL_DRIVERS_FTDI_FTDI_MPSSE_H_