// 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.

#pragma once

#include <zircon/compiler.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

__BEGIN_CDECLS;

// DID reserved for the platform bus implementation driver
#define PDEV_BUS_IMPLEMENTOR_DID    0

// interface registered by the platform bus implementation driver
typedef struct {
    zx_status_t (*get_protocol)(void* ctx, uint32_t proto_id, void* out);
    zx_status_t (*add_gpios)(void* ctx, uint32_t start, uint32_t count, uint32_t mmio_index,
                             const uint32_t* irqs, uint32_t irq_count);

    // TODO(voydanoff) Add APIs for GPIOs, clocks I2C, etc
} pbus_interface_ops_t;

typedef struct {
    pbus_interface_ops_t* ops;
    void* ctx;
} pbus_interface_t;

static inline zx_status_t pbus_interface_get_protocol(pbus_interface_t* intf, uint32_t proto_id,
                                                      void* out) {
    return intf->ops->get_protocol(intf->ctx, proto_id, out);
}

static inline zx_status_t pbus_interface_add_gpios(pbus_interface_t* intf, uint32_t start,
                                                   uint32_t count, uint32_t mmio_index,
                                                   const uint32_t* irqs, uint32_t irq_count) {
    return intf->ops->add_gpios(intf->ctx, start, count, mmio_index, irqs, irq_count);
}

typedef struct {
    zx_status_t (*set_interface)(void* ctx, pbus_interface_t* interface);
    zx_status_t (*get_protocol)(void* ctx, uint32_t proto_id, void* out);
    zx_status_t (*map_mmio)(void* ctx, uint32_t index, uint32_t cache_policy, void** out_vaddr,
                            size_t* out_size, zx_handle_t* out_handle);

    zx_status_t (*map_interrupt)(void* ctx, uint32_t index, zx_handle_t* out_handle);
} platform_device_protocol_ops_t;

typedef struct {
    platform_device_protocol_ops_t* ops;
    void* ctx;
} platform_device_protocol_t;

static inline zx_status_t pdev_set_interface(platform_device_protocol_t* pdev,
                                             pbus_interface_t* interface) {
    return pdev->ops->set_interface(pdev->ctx, interface);
}

// Requests a given protocol from the platform bus implementation
static inline zx_status_t pdev_get_protocol(platform_device_protocol_t* pdev, uint32_t proto_id,
                                             void* out_proto) {
    return pdev->ops->get_protocol(pdev->ctx, proto_id, out_proto);
}

// Maps an MMIO region based on information in the MDI
// index is based on ordering of the device's mmio nodes in the MDI
static inline zx_status_t pdev_map_mmio(platform_device_protocol_t* pdev, uint32_t index,
                                        uint32_t cache_policy, void** out_vaddr, size_t* out_size,
                                        zx_handle_t* out_handle) {
    return pdev->ops->map_mmio(pdev->ctx, index, cache_policy, out_vaddr, out_size, out_handle);
}

// Returns an interrupt handle for an IRQ based on information in the MDI
// index is based on ordering of the device's irq nodes in the MDI
static inline zx_status_t pdev_map_interrupt(platform_device_protocol_t* pdev, uint32_t index,
                                             zx_handle_t* out_handle) {
    return pdev->ops->map_interrupt(pdev->ctx, index, out_handle);
}

// MMIO mapping helpers

typedef struct {
    void*       vaddr;
    size_t      size;
    zx_handle_t handle;
} pdev_mmio_buffer_t;

static inline zx_status_t pdev_map_mmio_buffer(platform_device_protocol_t* pdev, uint32_t index,
                                        uint32_t cache_policy, pdev_mmio_buffer_t* buffer) {
    return pdev->ops->map_mmio(pdev->ctx, index, cache_policy, &buffer->vaddr, &buffer->size,
                               &buffer->handle);
}

static inline void pdev_mmio_buffer_release(pdev_mmio_buffer_t* buffer) {
    if (buffer->vaddr) {
        zx_vmar_unmap(zx_vmar_root_self(), (uintptr_t)buffer->vaddr, buffer->size);
    }
    zx_handle_close(buffer->handle);
}

__END_CDECLS;
