| // Copyright 2023 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. |
| |
| #include "src/graphics/display/drivers/amlogic-display/board-resources.h" |
| |
| #include <fidl/fuchsia.hardware.platform.device/cpp/wire.h> |
| #include <lib/mmio/mmio-buffer.h> |
| #include <lib/zx/interrupt.h> |
| #include <lib/zx/result.h> |
| #include <zircon/assert.h> |
| #include <zircon/status.h> |
| |
| #include <cstdint> |
| |
| #include "src/graphics/display/lib/driver-framework-migration-utils/logging/zxlogf.h" |
| |
| namespace amlogic_display { |
| |
| zx::result<BoardInfo> GetBoardInfo( |
| fidl::UnownedClientEnd<fuchsia_hardware_platform_device::Device> platform_device) { |
| ZX_DEBUG_ASSERT(platform_device.is_valid()); |
| fidl::WireResult<fuchsia_hardware_platform_device::Device::GetBoardInfo> result = |
| fidl::WireCall(platform_device)->GetBoardInfo(); |
| if (!result.ok()) { |
| zxlogf(ERROR, "Failed to get board info: FIDL call failed: %s", result.status_string()); |
| return zx::error(result.status()); |
| } |
| if (result->is_error()) { |
| zxlogf(ERROR, "Failed to get board info: Platform device failed: %s", |
| zx_status_get_string(result->error_value())); |
| return zx::error(result->error_value()); |
| } |
| if (!result.value()->has_vid()) { |
| zxlogf(ERROR, "Failed to get board info: Vendor ID is missing"); |
| return zx::error(ZX_ERR_BAD_STATE); |
| } |
| if (!result.value()->has_pid()) { |
| zxlogf(ERROR, "Failed to get board info: Product ID is missing"); |
| return zx::error(ZX_ERR_BAD_STATE); |
| } |
| BoardInfo board_info = { |
| .board_vendor_id = result.value()->vid(), |
| .board_product_id = result.value()->pid(), |
| }; |
| return zx::ok(board_info); |
| } |
| |
| zx::result<fdf::MmioBuffer> MapMmio( |
| MmioResourceIndex mmio_index, |
| fidl::UnownedClientEnd<fuchsia_hardware_platform_device::Device> platform_device) { |
| ZX_DEBUG_ASSERT(platform_device.is_valid()); |
| fidl::WireResult<fuchsia_hardware_platform_device::Device::GetMmioById> result = |
| fidl::WireCall(platform_device)->GetMmioById(static_cast<uint32_t>(mmio_index)); |
| if (!result.ok()) { |
| zxlogf(ERROR, "Failed to map MMIO resource #%" PRIu32 ": FIDL call failed: %s", |
| static_cast<uint32_t>(mmio_index), result.status_string()); |
| return zx::error(result.status()); |
| } |
| if (result->is_error()) { |
| zxlogf(ERROR, "Failed to map MMIO resource #%" PRIu32 ": Platform device failed %s", |
| static_cast<uint32_t>(mmio_index), zx_status_get_string(result->error_value())); |
| return zx::error(result->error_value()); |
| } |
| const fuchsia_hardware_platform_device::wire::Mmio* mmio_params = result->value(); |
| if (!mmio_params->has_offset() || !mmio_params->has_size() || !mmio_params->has_vmo()) { |
| zxlogf(ERROR, "Failed to map MMIO resource #%" PRIu32 ": Platform device provided invalid MMIO", |
| static_cast<uint32_t>(mmio_index)); |
| return zx::error(ZX_ERR_BAD_STATE); |
| }; |
| |
| zx::result<fdf::MmioBuffer> create_mmio_result = fdf::MmioBuffer::Create( |
| mmio_params->offset(), mmio_params->size(), std::move(mmio_params->vmo()), |
| /*cache_policy=*/ZX_CACHE_POLICY_UNCACHED_DEVICE); |
| if (create_mmio_result.is_error()) { |
| zxlogf(ERROR, "Failed to create fdf::MmioBuffer: %s", create_mmio_result.status_string()); |
| return create_mmio_result.take_error(); |
| } |
| return zx::ok(std::move(create_mmio_result).value()); |
| } |
| |
| zx::result<zx::interrupt> GetInterrupt( |
| InterruptResourceIndex interrupt_index, |
| fidl::UnownedClientEnd<fuchsia_hardware_platform_device::Device> platform_device) { |
| ZX_DEBUG_ASSERT(platform_device.is_valid()); |
| fidl::WireResult<fuchsia_hardware_platform_device::Device::GetInterruptById> result = |
| fidl::WireCall(platform_device) |
| ->GetInterruptById(static_cast<uint32_t>(interrupt_index), /*flags=*/0); |
| if (result.status() != ZX_OK) { |
| zxlogf(ERROR, "Failed to get interrupt resource #%" PRIu32 ": FIDL failed %s", |
| static_cast<uint32_t>(interrupt_index), result.status_string()); |
| return zx::error(result.status()); |
| } |
| if (!result->is_ok()) { |
| zxlogf(ERROR, "Failed to get interrupt resource #%" PRIu32 ": Platform device failed %s", |
| static_cast<uint32_t>(interrupt_index), zx_status_get_string(result->error_value())); |
| return zx::error(result->error_value()); |
| } |
| zx::interrupt interrupt = std::move(result->value()->irq); |
| ZX_DEBUG_ASSERT_MSG(interrupt.is_valid(), |
| "GetInterruptById() succeeded but didn't populate the out-param"); |
| return zx::ok(std::move(interrupt)); |
| } |
| |
| zx::result<zx::bti> GetBti( |
| BtiResourceIndex bti_index, |
| fidl::UnownedClientEnd<fuchsia_hardware_platform_device::Device> platform_device) { |
| ZX_DEBUG_ASSERT(platform_device.is_valid()); |
| fidl::WireResult<fuchsia_hardware_platform_device::Device::GetBtiById> result = |
| fidl::WireCall(platform_device)->GetBtiById(static_cast<uint32_t>(bti_index)); |
| if (result.status() != ZX_OK) { |
| zxlogf(ERROR, "Failed to get BTI resource #%" PRIu32 ": FIDL failed %s", |
| static_cast<uint32_t>(bti_index), result.status_string()); |
| return zx::error(result.status()); |
| } |
| if (!result->is_ok()) { |
| zxlogf(ERROR, "Failed to get BTI resource #%" PRIu32 ": Platform device failed %s", |
| static_cast<uint32_t>(bti_index), zx_status_get_string(result->error_value())); |
| return zx::error(result->error_value()); |
| } |
| zx::bti bti = std::move(result->value()->bti); |
| ZX_DEBUG_ASSERT_MSG(bti.is_valid(), "GetBtiById() succeeded but didn't populate the out-param"); |
| return zx::ok(std::move(bti)); |
| } |
| |
| zx::result<zx::resource> GetSecureMonitorCall( |
| SecureMonitorCallResourceIndex secure_monitor_call_index, |
| fidl::UnownedClientEnd<fuchsia_hardware_platform_device::Device> platform_device) { |
| ZX_DEBUG_ASSERT(platform_device.is_valid()); |
| fidl::WireResult<fuchsia_hardware_platform_device::Device::GetSmcById> result = |
| fidl::WireCall(platform_device)->GetSmcById(static_cast<uint32_t>(secure_monitor_call_index)); |
| if (result.status() != ZX_OK) { |
| zxlogf(ERROR, "Failed to get SMC resource #%" PRIu32 ": FIDL failed %s", |
| static_cast<uint32_t>(secure_monitor_call_index), result.status_string()); |
| return zx::error(result.status()); |
| } |
| if (!result->is_ok()) { |
| zxlogf(ERROR, "Failed to get SMC resource #%" PRIu32 ": Platform device failed %s", |
| static_cast<uint32_t>(secure_monitor_call_index), |
| zx_status_get_string(result->error_value())); |
| return zx::error(result->error_value()); |
| } |
| zx::resource secure_monitor_call = std::move(result->value()->smc); |
| ZX_DEBUG_ASSERT_MSG(secure_monitor_call.is_valid(), |
| "GetSmcById() succeeded but didn't populate the out-param"); |
| return zx::ok(std::move(secure_monitor_call)); |
| } |
| |
| } // namespace amlogic_display |