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 <ddktl/device.h>
8 #include <fbl/unique_ptr.h>
9 #include <fbl/vector.h>
10 
11 #include "device-resources.h"
12 #include "proxy-protocol.h"
13 
14 // This class, along with PlatformProxyDevice, represent a platform device.
15 // Platform devices run in separate devhosts than the platform bus driver.
16 // PlatformDevice exists in the platform bus devhost and PlatformProxyDevice
17 // exists in the platform device's devhost. PlatformProxyDevice proxys
18 // requests from the platform device via a channel, which are then
19 // handled by PlatformDevice::DdkRxrpc and then handled by relevant Rpc* methods.
20 //
21 // Resource handles passed to the proxy to allow it to access MMIOs and interrupts.
22 // This ensures if the proxy driver dies we will release their address space resources
23 // back to the kernel if necessary.
24 
25 namespace platform_bus {
26 
27 class PlatformBus;
28 
29 class PlatformDevice;
30 using PlatformDeviceType = ddk::Device<PlatformDevice, ddk::Rxrpcable>;
31 
32 // This class represents a platform device attached to the platform bus.
33 // Instances of this class are created by PlatformBus at boot time when the board driver
34 // calls the platform bus protocol method pbus_device_add().
35 
36 class PlatformDevice : public PlatformDeviceType {
37 public:
38     // Creates a new PlatformDevice instance.
39     // *flags* contains zero or more PDEV_ADD_* flags from the platform bus protocol.
40     static zx_status_t Create(const pbus_dev_t* pdev, zx_device_t* parent, PlatformBus* bus,
41                               fbl::unique_ptr<platform_bus::PlatformDevice>* out);
42 
vid()43     inline uint32_t vid() const { return vid_; }
pid()44     inline uint32_t pid() const { return pid_; }
did()45     inline uint32_t did() const { return did_; }
46 
47     // Device protocol implementation.
48     void DdkRelease();
49     zx_status_t DdkRxrpc(zx_handle_t channel);
50 
51     // Starts the underlying devmgr device.
52     zx_status_t Start();
53 
54 private:
55     // *flags* contains zero or more PDEV_ADD_* flags from the platform bus protocol.
56     explicit PlatformDevice(zx_device_t* parent, PlatformBus* bus, const pbus_dev_t* pdev);
57     zx_status_t Init(const pbus_dev_t* pdev);
58 
59     // Handlers for RPCs from PlatformProxy.
60     zx_status_t RpcGetMmio(const DeviceResources* dr, uint32_t index, zx_paddr_t* out_paddr,
61                            size_t* out_length, zx_handle_t* out_handle, uint32_t* out_handle_count);
62     zx_status_t RpcGetInterrupt(const DeviceResources* dr, uint32_t index, uint32_t* out_irq,
63                                 uint32_t* out_mode, zx_handle_t* out_handle,
64                                 uint32_t* out_handle_count);
65     zx_status_t RpcGetBti(const DeviceResources* dr, uint32_t index, zx_handle_t* out_handle,
66                           uint32_t* out_handle_count);
67     zx_status_t RpcGetSmc(const DeviceResources* dr, uint32_t index,
68                           zx_handle_t* out_handle, uint32_t* out_handle_count);
69     zx_status_t RpcGetDeviceInfo(const DeviceResources* dr, pdev_device_info_t* out_info);
70     zx_status_t RpcDeviceAdd(const DeviceResources* dr, uint32_t index, uint32_t* out_device_id);
71     zx_status_t RpcGetMetadata(const DeviceResources* dr, uint32_t index, uint32_t* out_type,
72                                uint8_t* buf, uint32_t buf_size, uint32_t* actual);
73     zx_status_t RpcGetProtocols(const DeviceResources* dr, uint32_t* out_protocols,
74                                 uint32_t* out_protocol_count);
75     zx_status_t RpcGpioConfigIn(const DeviceResources* dr, uint32_t index, uint32_t flags);
76     zx_status_t RpcGpioConfigOut(const DeviceResources* dr, uint32_t index, uint8_t initial_value);
77     zx_status_t RpcGpioSetAltFunction(const DeviceResources* dr, uint32_t index, uint64_t function);
78     zx_status_t RpcGpioRead(const DeviceResources* dr, uint32_t index, uint8_t* out_value);
79     zx_status_t RpcGpioWrite(const DeviceResources* dr, uint32_t index, uint8_t value);
80     zx_status_t RpcGpioGetInterrupt(const DeviceResources* dr, uint32_t index, uint32_t flags,
81                                     zx_handle_t* out_handle, uint32_t* out_handle_count);
82     zx_status_t RpcGpioReleaseInterrupt(const DeviceResources* dr, uint32_t index);
83     zx_status_t RpcGpioSetPolarity(const DeviceResources* dr, uint32_t index, uint32_t flags);
84     zx_status_t RpcI2cTransact(const DeviceResources* dr, uint32_t txid, rpc_i2c_req_t* req,
85                                zx_handle_t channel);
86     zx_status_t RpcI2cGetMaxTransferSize(const DeviceResources* dr, uint32_t index,
87                                          size_t* out_size);
88     zx_status_t RpcClkEnable(const DeviceResources* dr, uint32_t index);
89     zx_status_t RpcClkDisable(const DeviceResources* dr, uint32_t index);
90 
91     PlatformBus* bus_;
92     char name_[ZX_DEVICE_NAME_MAX + 1];
93     const uint32_t vid_;
94     const uint32_t pid_;
95     const uint32_t did_;
96 
97     // Tree of platform bus resources for this device and its children.
98     DeviceResources resource_tree_;
99 
100     // Flattened list of DeviceResources, indexed by device ID.
101     // device_index_[0] returns the DeviceResources for this top level device.
102     fbl::Vector<const DeviceResources*> device_index_;
103 };
104 
105 } // namespace platform_bus
106