| // Copyright 2017 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_BUS_DRIVERS_PLATFORM_PLATFORM_BUS_H_ |
| #define SRC_DEVICES_BUS_DRIVERS_PLATFORM_PLATFORM_BUS_H_ |
| |
| #include <fidl/fuchsia.boot/cpp/wire.h> |
| #include <fidl/fuchsia.hardware.platform.bus/cpp/driver/fidl.h> |
| #include <fidl/fuchsia.sysinfo/cpp/wire.h> |
| #include <fuchsia/hardware/clockimpl/cpp/banjo.h> |
| #include <fuchsia/hardware/iommu/cpp/banjo.h> |
| #include <lib/async/cpp/task.h> |
| #include <lib/ddk/device.h> |
| #include <lib/fdf/cpp/channel.h> |
| #include <lib/fdf/cpp/dispatcher.h> |
| #include <lib/sync/completion.h> |
| #include <lib/zbi-format/board.h> |
| #include <lib/zx/channel.h> |
| #include <lib/zx/iommu.h> |
| #include <lib/zx/resource.h> |
| #include <lib/zx/result.h> |
| #include <lib/zx/vmo.h> |
| #include <zircon/types.h> |
| |
| #include <fbl/array.h> |
| #include <fbl/auto_lock.h> |
| #include <fbl/mutex.h> |
| #include <sdk/lib/component/outgoing/cpp/outgoing_directory.h> |
| |
| #include "platform-device.h" |
| #include "proxy-protocol.h" |
| |
| namespace platform_bus { |
| |
| class PlatformBus; |
| using PlatformBusType = ddk::Device<PlatformBus, ddk::GetProtocolable, ddk::Initializable, |
| ddk::Messageable<fuchsia_sysinfo::SysInfo>::Mixin>; |
| |
| // This is the main class for the platform bus driver. |
| class PlatformBus : public PlatformBusType, |
| public fdf::WireServer<fuchsia_hardware_platform_bus::PlatformBus>, |
| public ddk::IommuProtocol<PlatformBus> { |
| public: |
| static zx_status_t Create(zx_device_t* parent, const char* name, zx::channel items_svc); |
| |
| PlatformBus(zx_device_t* parent, zx::channel items_svc); |
| |
| // Device protocol implementation. |
| zx_status_t DdkGetProtocol(uint32_t proto_id, void* out); |
| void DdkInit(ddk::InitTxn txn); |
| void DdkRelease(); |
| |
| // fuchsia.hardware.platform.bus.PlatformBus implementation. |
| void NodeAdd(NodeAddRequestView request, fdf::Arena& arena, |
| NodeAddCompleter::Sync& completer) override; |
| void ProtocolNodeAdd(ProtocolNodeAddRequestView request, fdf::Arena& arena, |
| ProtocolNodeAddCompleter::Sync& completer) override; |
| void RegisterProtocol(RegisterProtocolRequestView request, fdf::Arena& arena, |
| RegisterProtocolCompleter::Sync& completer) override; |
| |
| void GetBoardInfo(fdf::Arena& arena, GetBoardInfoCompleter::Sync& completer) override; |
| void SetBoardInfo(SetBoardInfoRequestView request, fdf::Arena& arena, |
| SetBoardInfoCompleter::Sync& completer) override; |
| void SetBootloaderInfo(SetBootloaderInfoRequestView request, fdf::Arena& arena, |
| SetBootloaderInfoCompleter::Sync& completer) override; |
| |
| void RegisterSysSuspendCallback(RegisterSysSuspendCallbackRequestView request, fdf::Arena& arena, |
| RegisterSysSuspendCallbackCompleter::Sync& completer) override; |
| void AddCompositeNodeSpec(AddCompositeNodeSpecRequestView request, fdf::Arena& arena, |
| AddCompositeNodeSpecCompleter::Sync& completer) override; |
| |
| // SysInfo protocol implementation. |
| void GetBoardName(GetBoardNameCompleter::Sync& completer) override; |
| void GetBoardRevision(GetBoardRevisionCompleter::Sync& completer) override; |
| void GetBootloaderVendor(GetBootloaderVendorCompleter::Sync& completer) override; |
| void GetInterruptControllerInfo(GetInterruptControllerInfoCompleter::Sync& completer) override; |
| void GetSerialNumber(GetSerialNumberCompleter::Sync& completer) override; |
| |
| // IOMMU protocol implementation. |
| zx_status_t IommuGetBti(uint32_t iommu_index, uint32_t bti_id, zx::bti* out_bti); |
| |
| zx::unowned_resource GetIrqResource() const { |
| return zx::unowned_resource(get_irq_resource(parent())); |
| } |
| |
| zx::unowned_resource GetMmioResource() const { |
| return zx::unowned_resource(get_mmio_resource(parent())); |
| } |
| |
| zx::unowned_resource GetSmcResource() const { |
| return zx::unowned_resource(get_smc_resource(parent())); |
| } |
| |
| struct BootItemResult { |
| zx::vmo vmo; |
| uint32_t length; |
| }; |
| // Returns ZX_ERR_NOT_FOUND when boot item wasn't found. |
| zx::result<BootItemResult> GetBootItem(uint32_t type, uint32_t extra); |
| zx::result<fbl::Array<uint8_t>> GetBootItemArray(uint32_t type, uint32_t extra); |
| |
| fidl::WireClient<fuchsia_hardware_platform_bus::SysSuspend>& suspend_cb() { return suspend_cb_; } |
| |
| fuchsia_hardware_platform_bus::TemporaryBoardInfo board_info() { |
| fbl::AutoLock lock(&board_info_lock_); |
| return board_info_; |
| } |
| |
| fdf::OutgoingDirectory& outgoing() { return outgoing_; } |
| |
| fdf::UnownedDispatcher dispatcher() { return dispatcher_->borrow(); } |
| |
| fdf::ServerBindingGroup<fuchsia_hardware_platform_bus::PlatformBus>& bindings() { |
| return bindings_; |
| } |
| |
| private: |
| fidl::WireClient<fuchsia_hardware_platform_bus::SysSuspend> suspend_cb_; |
| |
| DISALLOW_COPY_ASSIGN_AND_MOVE(PlatformBus); |
| |
| zx::result<zbi_board_info_t> GetBoardInfo(); |
| zx_status_t Init(); |
| |
| zx::result<> NodeAddInternal(fuchsia_hardware_platform_bus::Node& node); |
| zx::result<> ValidateResources(fuchsia_hardware_platform_bus::Node& node); |
| |
| fidl::ClientEnd<fuchsia_boot::Items> items_svc_; |
| |
| // Protects board_name_completer_. |
| fbl::Mutex board_info_lock_; |
| fuchsia_hardware_platform_bus::TemporaryBoardInfo board_info_ __TA_GUARDED(board_info_lock_) = {}; |
| // List to cache requests when board_name is not yet set. |
| std::vector<GetBoardNameCompleter::Async> board_name_completer_ __TA_GUARDED(board_info_lock_); |
| |
| fbl::Mutex bootloader_info_lock_; |
| fuchsia_hardware_platform_bus::BootloaderInfo bootloader_info_ |
| __TA_GUARDED(bootloader_info_lock_) = {}; |
| // List to cache requests when vendor is not yet set. |
| std::vector<GetBootloaderVendorCompleter::Async> bootloader_vendor_completer_ |
| __TA_GUARDED(bootloader_info_lock_); |
| |
| fuchsia_sysinfo::wire::InterruptControllerType interrupt_controller_type_ = |
| fuchsia_sysinfo::wire::InterruptControllerType::kUnknown; |
| |
| // Protocols that are optionally provided by the board driver. |
| std::optional<ddk::ClockImplProtocolClient> clock_; |
| std::optional<ddk::IommuProtocolClient> iommu_; |
| |
| struct ProtoReadyResponse { |
| fdf::Arena arena; |
| ProtocolNodeAddCompleter::Async completer; |
| std::unique_ptr<async::Task> timeout_task; |
| }; |
| // Key is the protocol ID (i.e. ZX_PROTOCOL_GPIO, etc). |
| std::unordered_map<uint32_t, ProtoReadyResponse> proto_ready_responders_ |
| __TA_GUARDED(proto_completion_mutex_); |
| // Protects proto_ready_responders_. |
| fbl::Mutex proto_completion_mutex_; |
| |
| // Dummy IOMMU. |
| zx::iommu iommu_handle_; |
| |
| std::map<std::pair<uint32_t, uint32_t>, zx::bti> cached_btis_; |
| |
| zx_device_t* protocol_passthrough_ = nullptr; |
| fdf::OutgoingDirectory outgoing_; |
| fdf::ServerBindingGroup<fuchsia_hardware_platform_bus::PlatformBus> bindings_; |
| fdf::UnownedDispatcher dispatcher_; |
| }; |
| |
| } // namespace platform_bus |
| |
| __BEGIN_CDECLS |
| zx_status_t platform_bus_create(void* ctx, zx_device_t* parent, const char* name, const char* args, |
| zx_handle_t rpc_channel); |
| __END_CDECLS |
| |
| #endif // SRC_DEVICES_BUS_DRIVERS_PLATFORM_PLATFORM_BUS_H_ |