root/sys/dev/dpaa2/dpaa2_mc.h
/*-
 * SPDX-License-Identifier: BSD-2-Clause
 *
 * Copyright © 2021-2022 Dmitry Salychev
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef _DPAA2_MC_H
#define _DPAA2_MC_H

#include <sys/rman.h>
#include <sys/bus.h>
#include <sys/queue.h>

#include <net/ethernet.h>

#include <dev/ofw/openfirm.h>

#include "pci_if.h"

#include "dpaa2_types.h"
#include "dpaa2_mcp.h"
#include "dpaa2_swp.h"
#include "dpaa2_ni.h"
#include "dpaa2_io.h"
#include "dpaa2_mac.h"
#include "dpaa2_con.h"
#include "dpaa2_bp.h"

/*
 * Maximum number of MSIs supported by the MC for its children without IOMMU.
 *
 * TODO: Should be much more with IOMMU translation.
 */
#define DPAA2_MC_MSI_COUNT       32

/* Flags for DPAA2 devices as resources. */
#define DPAA2_MC_DEV_ALLOCATABLE 0x01u /* to be managed by DPAA2-specific rman */
#define DPAA2_MC_DEV_ASSOCIATED  0x02u /* to obtain info about DPAA2 device  */
#define DPAA2_MC_DEV_SHAREABLE   0x04u /* to be shared among DPAA2 devices */

struct dpaa2_mc_devinfo; /* about managed DPAA2 devices */

/**
 * @brief Software context for the DPAA2 Management Complex (MC) driver.
 *
 * dev:         Device associated with this software context.
 * rcdev:       Child device associated with the root resource container.
 * acpi_based:  Attached using ACPI (true) or FDT (false).
 * ofw_node:    FDT node of the Management Complex (acpi_based == false).
 *
 * res:         Unmapped MC command portal and control registers resources.
 * map:         Mapped MC command portal and control registers resources.
 *
 * dpio_rman:   I/O objects resource manager.
 * dpbp_rman:   Buffer Pools resource manager.
 * dpcon_rman:  Concentrators resource manager.
 * dpmcp_rman:  MC portals resource manager.
 */
struct dpaa2_mc_softc {
        device_t                 dev;
        device_t                 rcdev;
        bool                     acpi_based;
        phandle_t                ofw_node;

        struct resource         *res[2];
        struct resource_map      map[2];

        /* For allocatable managed DPAA2 objects. */
        struct rman              dpio_rman;
        struct rman              dpbp_rman;
        struct rman              dpcon_rman;
        struct rman              dpmcp_rman;

        /* For managed DPAA2 objects. */
        struct mtx               mdev_lock;
        STAILQ_HEAD(, dpaa2_mc_devinfo) mdev_list;

        /* NOTE: Workaround in case of no IOMMU available. */
#ifndef IOMMU
        device_t                 msi_owner;
        bool                     msi_allocated;
        struct mtx               msi_lock;
        struct {
                device_t         child;
                int              irq;
        } msi[DPAA2_MC_MSI_COUNT];
#endif
};

/**
 * @brief Software context for the DPAA2 Resource Container (RC) driver.
 *
 * dev:         Device associated with this software context.
 * portal:      Helper object to send commands to the MC portal.
 * unit:        Helps to distinguish between root (0) and child DRPCs.
 * cont_id:     Container ID.
 */
struct dpaa2_rc_softc {
        device_t                 dev;
        int                      unit;
        uint32_t                 cont_id;
};

/**
 * @brief Information about MSI messages supported by the DPAA2 object.
 *
 * msi_msgnum:   Number of MSI messages supported by the DPAA2 object.
 * msi_alloc:    Number of MSI messages allocated for the DPAA2 object.
 * msi_handlers: Number of MSI message handlers configured.
 */
struct dpaa2_msinfo {
        uint8_t                  msi_msgnum;
        uint8_t                  msi_alloc;
        uint32_t                 msi_handlers;
};

/**
 * @brief Information about DPAA2 device.
 *
 * pdev:        Parent device.
 * dev:         Device this devinfo is associated with.
 *
 * id:          ID of a logical DPAA2 object resource.
 * portal_id:   ID of the MC portal which belongs to the object's container.
 * icid:        Isolation context ID of the DPAA2 object. It is shared
 *              between a resource container and all of its children.
 *
 * dtype:       Type of the DPAA2 object.
 * resources:   Resources available for this DPAA2 device.
 * msi:         Information about MSI messages supported by the DPAA2 object.
 */
struct dpaa2_devinfo {
        device_t                 pdev;
        device_t                 dev;

        uint32_t                 id;
        uint32_t                 portal_id;
        uint32_t                 icid;

        enum dpaa2_dev_type      dtype;
        struct resource_list     resources;
        struct dpaa2_msinfo      msi;

        /*
         * DPAA2 object might or might not have its own portal allocated to
         * execute MC commands. If the portal has been allocated, it takes
         * precedence over the portal owned by the resource container.
         */
        struct dpaa2_mcp        *portal;
};

DECLARE_CLASS(dpaa2_mc_driver);

/* For device interface. */

int dpaa2_mc_attach(device_t dev);
int dpaa2_mc_detach(device_t dev);

/* For bus interface. */

struct rman *dpaa2_mc_rman(device_t mcdev, int type, u_int flags);
struct resource * dpaa2_mc_alloc_resource(device_t mcdev, device_t child,
    int type, int rid, rman_res_t start, rman_res_t end, rman_res_t count,
    u_int flags);
int dpaa2_mc_adjust_resource(device_t mcdev, device_t child,
    struct resource *r, rman_res_t start, rman_res_t end);
int dpaa2_mc_release_resource(device_t mcdev, device_t child,
    struct resource *r);
int dpaa2_mc_activate_resource(device_t mcdev, device_t child,
    struct resource *r);
int dpaa2_mc_deactivate_resource(device_t mcdev, device_t child,
    struct resource *r);

/* For pseudo-pcib interface. */

int dpaa2_mc_alloc_msi(device_t mcdev, device_t child, int count, int maxcount,
    int *irqs);
int dpaa2_mc_release_msi(device_t mcdev, device_t child, int count, int *irqs);
int dpaa2_mc_map_msi(device_t mcdev, device_t child, int irq, uint64_t *addr,
    uint32_t *data);
int dpaa2_mc_get_id(device_t mcdev, device_t child, enum pci_id_type type,
    uintptr_t *id);

/* For DPAA2 MC bus interface. */

int dpaa2_mc_manage_dev(device_t mcdev, device_t dpaa2_dev, uint32_t flags);
int dpaa2_mc_get_free_dev(device_t mcdev, device_t *dpaa2_dev,
    enum dpaa2_dev_type devtype);
int dpaa2_mc_get_dev(device_t mcdev, device_t *dpaa2_dev,
    enum dpaa2_dev_type devtype, uint32_t obj_id);
int dpaa2_mc_get_shared_dev(device_t mcdev, device_t *dpaa2_dev,
    enum dpaa2_dev_type devtype);
int dpaa2_mc_reserve_dev(device_t mcdev, device_t dpaa2_dev,
    enum dpaa2_dev_type devtype);
int dpaa2_mc_release_dev(device_t mcdev, device_t dpaa2_dev,
    enum dpaa2_dev_type devtype);

#endif /* _DPAA2_MC_H */