root/sys/dev/ofw/ofw_misc.h
/*      $OpenBSD: ofw_misc.h,v 1.31 2023/09/21 20:26:17 kettenis Exp $  */
/*
 * Copyright (c) 2017-2021 Mark Kettenis
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _DEV_OFW_MISC_H_
#define _DEV_OFW_MISC_H_

/* Register maps */

void    regmap_register(int, bus_space_tag_t, bus_space_handle_t, bus_size_t);

struct regmap;
struct regmap *regmap_bycompatible(char *);
struct regmap *regmap_bynode(int);
struct regmap *regmap_byphandle(uint32_t);

uint32_t regmap_read_4(struct regmap *, bus_size_t);
void    regmap_write_4(struct regmap *, bus_size_t, uint32_t);

/* Interface support */

struct ifnet;

struct if_device {
        int              if_node;
        struct ifnet    *if_ifp;

        LIST_ENTRY(if_device) if_list;
        uint32_t         if_phandle;
};

void    if_register(struct if_device *);

struct ifnet *if_bynode(int);
struct ifnet *if_byphandle(uint32_t);

/* PHY support */

#define PHY_NONE        0
#define PHY_TYPE_SATA   1
#define PHY_TYPE_PCIE   2
#define PHY_TYPE_USB2   3
#define PHY_TYPE_USB3   4
#define PHY_TYPE_UFS    5

struct phy_device {
        int     pd_node;
        void    *pd_cookie;
        int     (*pd_enable)(void *, uint32_t *);

        LIST_ENTRY(phy_device) pd_list;
        uint32_t pd_phandle;
        uint32_t pd_cells;
};

void    phy_register(struct phy_device *);

int     phy_enable_prop_idx(int, char *, int);
int     phy_enable_idx(int, int);
int     phy_enable(int, const char *);

/* I2C support */

struct i2c_controller;
struct i2c_bus {
        int                     ib_node;
        struct i2c_controller   *ib_ic;

        LIST_ENTRY(i2c_bus) ib_list;
        uint32_t ib_phandle;
};

void    i2c_register(struct i2c_bus *);

struct i2c_controller *i2c_bynode(int);
struct i2c_controller *i2c_byphandle(uint32_t);

/* SFP support */

struct if_sffpage;
struct sfp_device {
        int     sd_node;
        void    *sd_cookie;
        int     (*sd_enable)(void *, int);
        int     (*sd_get_sffpage)(void *, struct if_sffpage *);

        LIST_ENTRY(sfp_device) sd_list;
        uint32_t sd_phandle;
};

void    sfp_register(struct sfp_device *);

struct mii_data;
int     sfp_enable(uint32_t);
int     sfp_disable(uint32_t);
int     sfp_add_media(uint32_t, struct mii_data *);
int     sfp_get_sffpage(uint32_t, struct if_sffpage *);

/* PWM support */

#define PWM_POLARITY_INVERTED   0x00000001

struct pwm_state {
        uint32_t ps_period;
        uint32_t ps_pulse_width;
        uint32_t ps_flags;
        int ps_enabled;
};

struct pwm_device {
        int     pd_node;
        void    *pd_cookie;
        int     (*pd_get_state)(void *, uint32_t *, struct pwm_state *);
        int     (*pd_set_state)(void *, uint32_t *, struct pwm_state *);

        LIST_ENTRY(pwm_device) pd_list;
        uint32_t pd_phandle;
        uint32_t pd_cells;
};

void    pwm_register(struct pwm_device *);

int     pwm_init_state(uint32_t *cells, struct pwm_state *ps);
int     pwm_get_state(uint32_t *cells, struct pwm_state *ps);
int     pwm_set_state(uint32_t *cells, struct pwm_state *ps);

/* Non-volatile memory support */

struct nvmem_device {
        int     nd_node;
        void    *nd_cookie;
        int     (*nd_read)(void *, bus_addr_t, void *, bus_size_t);
        int     (*nd_write)(void *, bus_addr_t, const void *, bus_size_t);

        LIST_ENTRY(nvmem_device) nd_list;
        uint32_t nd_phandle;
};

void    nvmem_register(struct nvmem_device *);
int     nvmem_read(uint32_t, bus_addr_t, void *, bus_size_t);
int     nvmem_read_cell(int, const char *name, void *, bus_size_t);
int     nvmem_write_cell(int, const char *name, const void *, bus_size_t);

/* Port/endpoint interface support */

struct endpoint;

struct device_ports {
        int     dp_node;
        void    *dp_cookie;

        int     (*dp_ep_activate)(void *, struct endpoint *, void *);
        void    *(*dp_ep_get_cookie)(void *, struct endpoint *);

        LIST_HEAD(, device_port) dp_ports;
};

struct device_port {
        int     dp_node;
        uint32_t dp_phandle;
        uint32_t dp_reg;
        struct device_ports *dp_ports;
        LIST_ENTRY(device_port) dp_list;
        LIST_HEAD(, endpoint) dp_endpoints;
};

enum endpoint_type {
        EP_DRM_BRIDGE = 1,      /* struct drm_bridge */
        EP_DRM_CONNECTOR,       /* struct drm_connector */
        EP_DRM_CRTC,            /* struct drm_crtc */
        EP_DRM_ENCODER,         /* struct drm_encoder */
        EP_DRM_PANEL,           /* struct drm_panel */
        EP_DAI_DEVICE,          /* struct dai_device */
        EP_USB_CONTROLLER_PORT, /* struct usb_controller_port */
};

struct usb_controller_port {
        void *up_cookie;
        void (*up_connect)(void *);
        void (*up_disconnect)(void *);
};

struct endpoint {
        int ep_node;
        uint32_t ep_phandle;
        uint32_t ep_reg;
        enum endpoint_type ep_type;
        struct device_port *ep_port;
        LIST_ENTRY(endpoint) ep_list;
        LIST_ENTRY(endpoint) ep_plist;
};

void    device_ports_register(struct device_ports *, enum endpoint_type);
struct device_ports *device_ports_byphandle(uint32_t);
int     device_port_activate(uint32_t, void *);
struct endpoint *endpoint_byreg(struct device_ports *, uint32_t, uint32_t);
struct endpoint *endpoint_remote(struct endpoint *);
int     endpoint_activate(struct endpoint *, void *);
void    *endpoint_get_cookie(struct endpoint *);

/* Digital audio interface support */

struct dai_device {
        int     dd_node;
        void    *dd_cookie;
        const void *dd_hw_if;
        int     (*dd_set_format)(void *, uint32_t, uint32_t, uint32_t);
        int     (*dd_set_sysclk)(void *, uint32_t);
        int     (*dd_set_tdm_slot)(void *, int);

        LIST_ENTRY(dai_device) dd_list;
        uint32_t dd_phandle;

        struct device_ports dd_ports;
};

void    dai_register(struct dai_device *);
struct dai_device *dai_byphandle(uint32_t);

#define DAI_FORMAT_I2S                  0
#define DAI_FORMAT_RJ                   1
#define DAI_FORMAT_LJ                   2
#define DAI_FORMAT_DSPA                 3
#define DAI_FORMAT_DSPB                 4
#define DAI_FORMAT_AC97                 5
#define DAI_FORMAT_PDM                  6
#define DAI_FORMAT_MSB                  7
#define DAI_FORMAT_LSB                  8

#define DAI_POLARITY_NB                 (0 << 0)
#define DAI_POLARITY_IB                 (1 << 0)
#define DAI_POLARITY_NF                 (0 << 1)
#define DAI_POLARITY_IF                 (1 << 1)

#define DAI_CLOCK_CBS                   (0 << 0)
#define DAI_CLOCK_CBM                   (1 << 0)
#define DAI_CLOCK_CFS                   (0 << 1)
#define DAI_CLOCK_CFM                   (1 << 1)

/* MII support */

struct mii_bus {
        int     md_node;
        void    *md_cookie;
        int     (*md_readreg)(struct device *, int, int);
        void    (*md_writereg)(struct device *, int, int, int);

        LIST_ENTRY(mii_bus) md_list;
};

void    mii_register(struct mii_bus *);
struct mii_bus *mii_bynode(int);
struct mii_bus *mii_byphandle(uint32_t);

/* IOMMU support */

struct iommu_device {
        int     id_node;
        void    *id_cookie;
        bus_dma_tag_t (*id_map)(void *, uint32_t *, bus_dma_tag_t);
        void (*id_reserve)(void *, uint32_t *, bus_addr_t, bus_size_t);

        LIST_ENTRY(iommu_device) id_list;
        uint32_t id_phandle;
};

void    iommu_device_register(struct iommu_device *);
int     iommu_device_lookup(int, uint32_t *, uint32_t *);
int     iommu_device_lookup_pci(int, uint32_t, uint32_t *, uint32_t *);
bus_dma_tag_t iommu_device_map(int, bus_dma_tag_t);
bus_dma_tag_t iommu_device_map_pci(int, uint32_t, bus_dma_tag_t);
void    iommu_reserve_region_pci(int, uint32_t, bus_addr_t, bus_size_t);

/* Mailbox support */

struct mbox_client {
        void    (*mc_rx_callback)(void *);
        void    *mc_rx_arg;
        int     mc_flags;
#define MC_WAKEUP               0x00000001
};

struct mbox_channel;

struct mbox_device {
        int     md_node;
        void    *md_cookie;
        void    *(*md_channel)(void *, uint32_t *, struct mbox_client *);
        int     (*md_recv)(void *, void *, size_t);
        int     (*md_send)(void *, const void *, size_t);

        LIST_ENTRY(mbox_device) md_list;
        uint32_t md_phandle;
        uint32_t md_cells;
};

void    mbox_register(struct mbox_device *);

struct mbox_channel *mbox_channel(int, const char *, struct mbox_client *);
struct mbox_channel *mbox_channel_idx(int, int, struct mbox_client *);

int     mbox_send(struct mbox_channel *, const void *, size_t);
int     mbox_recv(struct mbox_channel *, void *, size_t);

/* hwlock support */

struct hwlock_device {
        int     hd_node;
        void    *hd_cookie;
        int     (*hd_lock)(void *, uint32_t *, int);

        LIST_ENTRY(hwlock_device) hd_list;
        uint32_t hd_phandle;
        uint32_t hd_cells;
};

void    hwlock_register(struct hwlock_device *);

int     hwlock_lock_idx(int, int);
int     hwlock_lock_idx_timeout(int, int, int);
int     hwlock_unlock_idx(int, int);

#endif /* _DEV_OFW_MISC_H_ */