// Copyright 2022 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.
library fuchsia.hardware.platform.device;

using fuchsia.driver.framework;
using fuchsia.hardware.power;
using zx;

type NodeDeviceInfo = table {
    /// Vendor ID, specified in //zircon/system/ulib/ddk-platform-defs/include/lib/ddk/platform-defs.h
    1: vid uint32;
    /// Platform ID, specified in //zircon/system/ulib/ddk-platform-defs/include/lib/ddk/platform-defs.h
    2: pid uint32;
    /// Device ID, specified in //zircon/system/ulib/ddk-platform-defs/include/lib/ddk/platform-defs.h
    3: did uint32;
    /// The number of MMIO regions provided to this device.
    4: mmio_count uint32;
    /// The number of interrupts provided to this device.
    5: irq_count uint32;
    /// The number of bus transaction initiaitors provided to this device.
    6: bti_count uint32;
    /// The number of secure monitor call resources provided to this device.
    7: smc_count uint32;
    /// The number of metadata blobs associated provided this device.
    8: metadata_count uint32;
    /// The name the board driver provided for this device.
    9: name string:32;
};

type BoardInfo = table {
    /// Vendor ID for the board.
    1: vid uint32;
    /// Product ID for the board.
    2: pid uint32;
    /// Board name from the boot image platform ID record,
    /// (or from the BIOS on x86 platforms).
    3: board_name string:32;
    /// Board specific revision number.
    4: board_revision uint32;
};

type Mmio = resource table {
    /// Offset from beginning of VMO where the mmio region begins.
    1: offset zx.Off;
    /// Size of mmio region.
    2: size uint64;
    /// The virtual memory object which should be mapped into the driver's address space.
    3: vmo zx.Handle:VMO;
};

@discoverable(server="platform")
open protocol Device {
    /// Returns a memory mapped IO (MMIO) resource for the given |index|.
    /// * error `ZX_ERR_OUT_OF_RANGE` if |index| is equal or greater than the number of
    /// mmios.
    /// * error `ZX_ERR_INTERNAL` if the retrieved mmio is not valid.
    /// * error `ZX_ERR_NOT_FOUND` if the retrieved mmio's base address is NULL.
    flexible GetMmioById(struct {
        index uint32;
    }) -> (Mmio) error zx.Status;

    /// Returns a memory mapped IO (MMIO) resource for the given |name|.
    /// * error `ZX_ERR_INVALID_ARGS` if |name| is an empty string.
    /// * error `ZX_ERR_OUT_OF_RANGE` if |name| is not found.
    /// * error `ZX_ERR_INTERNAL` if the retrieved mmio is not valid.
    /// * error `ZX_ERR_NOT_FOUND` if the retrieved's mmio base address is NULL.
    flexible GetMmioByName(struct {
        name string:fuchsia.driver.framework.MAX_RESOURCE_NAME_LENGTH;
    }) -> (Mmio) error zx.Status;

    /// Returns an interrupt handle for the given |index|.
    /// |flags| is forwarded as the |options| parameter to `zx_interrupt_create`.
    /// * error `ZX_ERR_OUT_OF_RANGE` if |index| is equal or greater than the number of
    /// interrupts.
    /// * error `ZX_ERR_INTERNAL` if the retrieved interrupt is not valid.
    flexible GetInterruptById(struct {
        index uint32;
        flags uint32;
    }) -> (resource struct {
        irq zx.Handle:INTERRUPT;
    }) error zx.Status;

    /// Returns an interrupt handle for the given |name|.
    /// |flags| is forwarded as the |options| parameter to `zx_interrupt_create`.
    /// * error `ZX_ERR_INVALID_ARGS` if |name| is an empty string.
    /// * error `ZX_ERR_OUT_OF_RANGE` if |name| is not found.
    /// * error `ZX_ERR_INTERNAL` if the retrieved interrupt is not valid.
    flexible GetInterruptByName(struct {
        name string:fuchsia.driver.framework.MAX_RESOURCE_NAME_LENGTH;
        flags uint32;
    }) -> (resource struct {
        irq zx.Handle:INTERRUPT;
    }) error zx.Status;

    /// Returns a bus transaction initiator (bti) handle for the given |index|.
    /// * error `ZX_ERR_OUT_OF_RANGE` if |index| is equal or greater than the number of
    /// btis.
    /// * error `ZX_ERR_INTERNAL` if the retrieved bti is not valid.
    flexible GetBtiById(struct {
        index uint32;
    }) -> (resource struct {
        bti zx.Handle:BTI;
    }) error zx.Status;

    /// Returns a bus transaction initiator (bti) handle for the given |name|.
    /// * error `ZX_ERR_INVALID_ARGS` if |name| is an empty string.
    /// * error `ZX_ERR_OUT_OF_RANGE` if |name| is not found.
    /// * error `ZX_ERR_INTERNAL` if the retrieved bti is not valid.
    flexible GetBtiByName(struct {
        name string:fuchsia.driver.framework.MAX_RESOURCE_NAME_LENGTH;
    }) -> (resource struct {
        bti zx.Handle:BTI;
    }) error zx.Status;

    /// Returns a secure monitor call (smc) handle for the given |index|.
    /// * error `ZX_ERR_OUT_OF_RANGE` if |index| is equal or greater than the number of
    /// smcs.
    /// * error `ZX_ERR_INTERNAL` if the retrieved smc is not valid.
    flexible GetSmcById(struct {
        index uint32;
    }) -> (resource struct {
        smc zx.Handle:RESOURCE;
    }) error zx.Status;

    /// Returns a secure monitor call (smc) handle for the given |name|.
    /// * error `ZX_ERR_INVALID_ARGS` if |name| is an empty string.
    /// * error `ZX_ERR_OUT_OF_RANGE` if |name| is not found.
    /// * error `ZX_ERR_INTERNAL` if the retrieved smc is not valid.
    flexible GetSmcByName(struct {
        name string:fuchsia.driver.framework.MAX_RESOURCE_NAME_LENGTH;
    }) -> (resource struct {
        smc zx.Handle:RESOURCE;
    }) error zx.Status;

    /// Returns power configuration for the device the driver has bound to.
    @available(added=HEAD)
    flexible GetPowerConfiguration() -> (struct {
        config vector<fuchsia.hardware.power.PowerElementConfiguration>:32;
    }) error zx.Status;

    /// Returns information about the device corresponding to the node
    /// that the driver has bound to.
    flexible GetNodeDeviceInfo() -> (NodeDeviceInfo) error zx.Status;

    /// Return information about the board the device is attached to.
    flexible GetBoardInfo() -> (BoardInfo) error zx.Status;
};

service Service {
    device client_end:Device;
};
