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 "platform-proxy-device.h" 8 9#include <ddk/protocol/clk.h> 10#include <ddk/protocol/gpio.h> 11#include <ddk/protocol/i2c.h> 12#include <ddktl/device.h> 13#include <ddktl/protocol/platform-device.h> 14#include <fbl/array.h> 15#include <fbl/ref_ptr.h> 16#include <fbl/unique_ptr.h> 17#include <fbl/vector.h> 18#include <lib/zx/channel.h> 19#include <lib/zx/handle.h> 20 21#include "proxy-protocol.h" 22 23namespace platform_bus { 24 25class PlatformProxy; 26class ProxyDevice; 27using ProxyDeviceType = ddk::FullDevice<ProxyDevice>; 28 29class ProxyDevice : public ProxyDeviceType, public ddk::PlatformDevProtocol<ProxyDevice> { 30public: 31 explicit ProxyDevice(zx_device_t* parent, uint32_t device_id, fbl::RefPtr<PlatformProxy> proxy); 32 33 // Creates a ProxyDevice to be the root platform device. 34 static zx_status_t CreateRoot(zx_device_t* parent, fbl::RefPtr<PlatformProxy> proxy); 35 36 // Creates a ProxyDevice to be a child platform device or a proxy client device. 37 static zx_status_t CreateChild(zx_device_t* parent, uint32_t device_id, 38 fbl::RefPtr<PlatformProxy> proxy, device_add_args_t* args); 39 40 // Full device protocol implementation. 41 // For child devices, these call through to the device protocol passed via pdev_device_add(). 42 zx_status_t DdkGetProtocol(uint32_t proto_id, void* out); 43 zx_status_t DdkOpen(zx_device_t** dev_out, uint32_t flags); 44 zx_status_t DdkOpenAt(zx_device_t** dev_out, const char* path, uint32_t flags); 45 zx_status_t DdkClose(uint32_t flags); 46 void DdkUnbind(); 47 void DdkRelease(); 48 zx_status_t DdkRead(void* buf, size_t count, zx_off_t off, size_t* actual); 49 zx_status_t DdkWrite(const void* buf, size_t count, zx_off_t off, size_t* actual); 50 zx_off_t DdkGetSize(); 51 zx_status_t DdkIoctl(uint32_t op, const void* in_buf, size_t in_len, void* out_buf, 52 size_t out_len, size_t* actual); 53 zx_status_t DdkSuspend(uint32_t flags); 54 zx_status_t DdkResume(uint32_t flags); 55 zx_status_t DdkRxrpc(zx_handle_t channel); 56 57 // Platform device protocol implementation. 58 zx_status_t GetMmio(uint32_t index, pdev_mmio_t* out_mmio); 59 zx_status_t MapMmio(uint32_t index, uint32_t cache_policy, void** out_vaddr, size_t* out_size, 60 zx_paddr_t* out_paddr, zx_handle_t* out_handle); 61 zx_status_t MapInterrupt(uint32_t index, uint32_t flags, zx_handle_t* out_handle); 62 zx_status_t GetBti(uint32_t index, zx_handle_t* out_handle); 63 zx_status_t GetDeviceInfo(pdev_device_info_t* out_info); 64 zx_status_t GetBoardInfo(pdev_board_info_t* out_info); 65 zx_status_t DeviceAdd(uint32_t index, device_add_args_t* args, zx_device_t** out); 66 zx_status_t GetProtocol(uint32_t proto_id, uint32_t index, void* out_protocol); 67 68 // Clock protocol implementation. 69 static zx_status_t ClkEnable(void* ctx, uint32_t index); 70 static zx_status_t ClkDisable(void* ctx, uint32_t index); 71 72 // GPIO protocol implementation. 73 static zx_status_t GpioConfigIn(void* ctx, uint32_t flags); 74 static zx_status_t GpioConfigOut(void* ctx, uint8_t initial_value); 75 static zx_status_t GpioSetAltFunction(void* ctx, uint64_t function); 76 static zx_status_t GpioRead(void* ctx, uint8_t* out_value); 77 static zx_status_t GpioWrite(void* ctx, uint8_t value); 78 static zx_status_t GpioGetInterrupt(void* ctx, uint32_t flags, 79 zx_handle_t* out_handle); 80 static zx_status_t GpioReleaseInterrupt(void* ctx); 81 static zx_status_t GpioSetPolarity(void* ctx, uint32_t polarity); 82 83 // I2C protocol implementation. 84 static zx_status_t I2cTransact(void* ctx, i2c_op_t* ops, size_t cnt, 85 i2c_transact_cb transact_cb, void* cookie); 86 static zx_status_t I2cGetMaxTransferSize(void* ctx, size_t* out_size); 87 static zx_status_t I2cGetInterrupt(void* ctx, uint32_t flags, zx_handle_t* out_handle); 88 89private: 90 struct Mmio { 91 zx_paddr_t base; 92 size_t length; 93 zx::handle resource; 94 }; 95 struct Irq { 96 uint32_t irq; 97 // ZX_INTERRUPT_MODE_* flags 98 uint32_t mode; 99 zx::handle resource; 100 }; 101 struct GpioCtx { 102 ProxyDevice* thiz; 103 uint32_t index; 104 }; 105 struct I2cCtx { 106 ProxyDevice* thiz; 107 uint32_t index; 108 }; 109 110 zx_status_t InitCommon(); 111 zx_status_t InitRoot(); 112 zx_status_t InitChild(device_add_args_t* args); 113 114 DISALLOW_COPY_ASSIGN_AND_MOVE(ProxyDevice); 115 116 const uint32_t device_id_; 117 fbl::RefPtr<PlatformProxy> proxy_; 118 fbl::Vector<Mmio> mmios_; 119 fbl::Vector<Irq> irqs_; 120 char name_[ZX_MAX_NAME_LEN]; 121 uint32_t metadata_count_; 122 123 // We can't used ddktl for these because ddktl only allows a device to implement one protocol, 124 // and we are using ddktl for the platform device protocol. 125 clk_protocol_ops_t clk_proto_ops_; 126 gpio_protocol_ops_t gpio_proto_ops_; 127 i2c_protocol_ops_t i2c_proto_ops_; 128 129 // Contexts 130 fbl::Array<GpioCtx> gpio_ctxs_; 131 fbl::Array<I2cCtx> i2c_ctxs_; 132 133 // These fields are saved values from the device_add_args_t passed to pdev_device_add(). 134 // These are unused for top level devices created via pbus_device_add(). 135 void* ctx_ = nullptr; 136 zx_protocol_device_t* device_ops_ = nullptr; 137 uint32_t proto_id_ = 0; 138 void* proto_ops_ = nullptr; 139}; 140 141} // namespace platform_bus 142