linux/drivers/spmi/spmi-pmic-arb.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2012-2015, 2017, 2021, The Linux Foundation. All rights reserved.
 */
#include <linux/bitmap.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spmi.h>

/* PMIC Arbiter configuration registers */
#define PMIC_ARB_VERSION
#define PMIC_ARB_VERSION_V2_MIN
#define PMIC_ARB_VERSION_V3_MIN
#define PMIC_ARB_VERSION_V5_MIN
#define PMIC_ARB_VERSION_V7_MIN
#define PMIC_ARB_INT_EN

#define PMIC_ARB_FEATURES
#define PMIC_ARB_FEATURES_PERIPH_MASK

#define PMIC_ARB_FEATURES1

/* PMIC Arbiter channel registers offsets */
#define PMIC_ARB_CMD
#define PMIC_ARB_CONFIG
#define PMIC_ARB_STATUS
#define PMIC_ARB_WDATA0
#define PMIC_ARB_WDATA1
#define PMIC_ARB_RDATA0
#define PMIC_ARB_RDATA1

/* Mapping Table */
#define SPMI_MAPPING_TABLE_REG(N)
#define SPMI_MAPPING_BIT_INDEX(X)
#define SPMI_MAPPING_BIT_IS_0_FLAG(X)
#define SPMI_MAPPING_BIT_IS_0_RESULT(X)
#define SPMI_MAPPING_BIT_IS_1_FLAG(X)
#define SPMI_MAPPING_BIT_IS_1_RESULT(X)

#define SPMI_MAPPING_TABLE_TREE_DEPTH
#define PMIC_ARB_MAX_PPID
#define PMIC_ARB_APID_VALID
#define PMIC_ARB_CHAN_IS_IRQ_OWNER(reg)
#define INVALID_EE

/* Ownership Table */
#define SPMI_OWNERSHIP_PERIPH2OWNER(X)

/* Channel Status fields */
enum pmic_arb_chnl_status {};

/* Command register fields */
#define PMIC_ARB_CMD_MAX_BYTE_COUNT

/* Command Opcodes */
enum pmic_arb_cmd_op_code {};

/*
 * PMIC arbiter version 5 uses different register offsets for read/write vs
 * observer channels.
 */
enum pmic_arb_channel {};

#define PMIC_ARB_MAX_BUSES

/* Maximum number of support PMIC peripherals */
#define PMIC_ARB_MAX_PERIPHS
#define PMIC_ARB_MAX_PERIPHS_V7
#define PMIC_ARB_TIMEOUT_US
#define PMIC_ARB_MAX_TRANS_BYTES

#define PMIC_ARB_APID_MASK
#define PMIC_ARB_PPID_MASK

/* interrupt enable bit */
#define SPMI_PIC_ACC_ENABLE_BIT

#define spec_to_hwirq(slave_id, periph_id, irq_id, apid)

#define hwirq_to_sid(hwirq)
#define hwirq_to_per(hwirq)
#define hwirq_to_irq(hwirq)
#define hwirq_to_apid(hwirq)

struct pmic_arb_ver_ops;

struct apid_data {};

struct spmi_pmic_arb;

/**
 * struct spmi_pmic_arb_bus - SPMI PMIC Arbiter Bus object
 *
 * @pmic_arb:		the SPMI PMIC Arbiter the bus belongs to.
 * @domain:		irq domain object for PMIC IRQ domain
 * @intr:		address of the SPMI interrupt control registers.
 * @cnfg:		address of the PMIC Arbiter configuration registers.
 * @spmic:		spmi controller registered for this bus
 * @lock:		lock to synchronize accesses.
 * @base_apid:		on v7: minimum APID associated with the particular SPMI
 *			bus instance
 * @apid_count:		on v5 and v7: number of APIDs associated with the
 *			particular SPMI bus instance
 * @mapping_table:	in-memory copy of PPID -> APID mapping table.
 * @mapping_table_valid:bitmap containing valid-only periphs
 * @ppid_to_apid:	in-memory copy of PPID -> APID mapping table.
 * @last_apid:		Highest value APID in use
 * @apid_data:		Table of data for all APIDs
 * @min_apid:		minimum APID (used for bounding IRQ search)
 * @max_apid:		maximum APID
 * @irq:		PMIC ARB interrupt.
 * @id:			unique ID of the bus
 */
struct spmi_pmic_arb_bus {};

/**
 * struct spmi_pmic_arb - SPMI PMIC Arbiter object
 *
 * @rd_base:		on v1 "core", on v2 "observer" register base off DT.
 * @wr_base:		on v1 "core", on v2 "chnls"    register base off DT.
 * @core:		core register base for v2 and above only (see above)
 * @core_size:		core register base size
 * @channel:		execution environment channel to use for accesses.
 * @ee:			the current Execution Environment
 * @ver_ops:		version dependent operations.
 * @max_periphs:	Number of elements in apid_data[]
 * @buses:		per arbiter buses instances
 * @buses_available:	number of buses registered
 */
struct spmi_pmic_arb {};

/**
 * struct pmic_arb_ver_ops - version dependent functionality.
 *
 * @ver_str:		version string.
 * @get_core_resources:	initializes the core, observer and channels
 * @init_apid:		finds the apid base and count
 * @ppid_to_apid:	finds the apid for a given ppid.
 * @non_data_cmd:	on v1 issues an spmi non-data command.
 *			on v2 no HW support, returns -EOPNOTSUPP.
 * @offset:		on v1 offset of per-ee channel.
 *			on v2 offset of per-ee and per-ppid channel.
 * @fmt_cmd:		formats a GENI/SPMI command.
 * @owner_acc_status:	on v1 address of PMIC_ARB_SPMI_PIC_OWNERm_ACC_STATUSn
 *			on v2 address of SPMI_PIC_OWNERm_ACC_STATUSn.
 * @acc_enable:		on v1 address of PMIC_ARB_SPMI_PIC_ACC_ENABLEn
 *			on v2 address of SPMI_PIC_ACC_ENABLEn.
 * @irq_status:		on v1 address of PMIC_ARB_SPMI_PIC_IRQ_STATUSn
 *			on v2 address of SPMI_PIC_IRQ_STATUSn.
 * @irq_clear:		on v1 address of PMIC_ARB_SPMI_PIC_IRQ_CLEARn
 *			on v2 address of SPMI_PIC_IRQ_CLEARn.
 * @apid_map_offset:	offset of PMIC_ARB_REG_CHNLn
 * @apid_owner:		on v2 and later address of SPMI_PERIPHn_2OWNER_TABLE_REG
 */
struct pmic_arb_ver_ops {};

static inline void pmic_arb_base_write(struct spmi_pmic_arb *pmic_arb,
				       u32 offset, u32 val)
{}

static inline void pmic_arb_set_rd_cmd(struct spmi_pmic_arb *pmic_arb,
				       u32 offset, u32 val)
{}

/**
 * pmic_arb_read_data: reads pmic-arb's register and copy 1..4 bytes to buf
 * @pmic_arb:	the SPMI PMIC arbiter
 * @bc:		byte count -1. range: 0..3
 * @reg:	register's address
 * @buf:	output parameter, length must be bc + 1
 */
static void
pmic_arb_read_data(struct spmi_pmic_arb *pmic_arb, u8 *buf, u32 reg, u8 bc)
{}

/**
 * pmic_arb_write_data: write 1..4 bytes from buf to pmic-arb's register
 * @pmic_arb:	the SPMI PMIC arbiter
 * @bc:		byte-count -1. range: 0..3.
 * @reg:	register's address.
 * @buf:	buffer to write. length must be bc + 1.
 */
static void pmic_arb_write_data(struct spmi_pmic_arb *pmic_arb, const u8 *buf,
				u32 reg, u8 bc)
{}

static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
				  void __iomem *base, u8 sid, u16 addr,
				  enum pmic_arb_channel ch_type)
{}

static int
pmic_arb_non_data_cmd_v1(struct spmi_controller *ctrl, u8 opc, u8 sid)
{}

static int
pmic_arb_non_data_cmd_v2(struct spmi_controller *ctrl, u8 opc, u8 sid)
{}

/* Non-data command */
static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
{}

static int pmic_arb_fmt_read_cmd(struct spmi_pmic_arb_bus *bus, u8 opc, u8 sid,
				 u16 addr, size_t len, u32 *cmd, u32 *offset)
{}

static int pmic_arb_read_cmd_unlocked(struct spmi_controller *ctrl, u32 cmd,
				      u32 offset, u8 sid, u16 addr, u8 *buf,
				      size_t len)
{}

static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
			     u16 addr, u8 *buf, size_t len)
{}

static int pmic_arb_fmt_write_cmd(struct spmi_pmic_arb_bus *bus, u8 opc,
				  u8 sid, u16 addr, size_t len, u32 *cmd,
				  u32 *offset)
{}

static int pmic_arb_write_cmd_unlocked(struct spmi_controller *ctrl, u32 cmd,
				      u32 offset, u8 sid, u16 addr,
				      const u8 *buf, size_t len)
{}

static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
			      u16 addr, const u8 *buf, size_t len)
{}

static int pmic_arb_masked_write(struct spmi_controller *ctrl, u8 sid, u16 addr,
				 const u8 *buf, const u8 *mask, size_t len)
{}

enum qpnpint_regs {};

struct spmi_pmic_arb_qpnpint_type {} __packed;

/* Simplified accessor functions for irqchip callbacks */
static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf,
			       size_t len)
{}

static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len)
{}

static int qpnpint_spmi_masked_write(struct irq_data *d, u8 reg,
				     const void *buf, const void *mask,
				     size_t len)
{}

static void cleanup_irq(struct spmi_pmic_arb_bus *bus, u16 apid, int id)
{}

static int periph_interrupt(struct spmi_pmic_arb_bus *bus, u16 apid)
{}

static void pmic_arb_chained_irq(struct irq_desc *desc)
{}

static void qpnpint_irq_ack(struct irq_data *d)
{}

static void qpnpint_irq_mask(struct irq_data *d)
{}

static void qpnpint_irq_unmask(struct irq_data *d)
{}

static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
{}

static int qpnpint_irq_set_wake(struct irq_data *d, unsigned int on)
{}

static int qpnpint_get_irqchip_state(struct irq_data *d,
				     enum irqchip_irq_state which,
				     bool *state)
{}

static int qpnpint_irq_domain_activate(struct irq_domain *domain,
				       struct irq_data *d, bool reserve)
{}

static struct irq_chip pmic_arb_irqchip =;

static int qpnpint_irq_domain_translate(struct irq_domain *d,
					struct irq_fwspec *fwspec,
					unsigned long *out_hwirq,
					unsigned int *out_type)
{}

static struct lock_class_key qpnpint_irq_lock_class, qpnpint_irq_request_class;

static void qpnpint_irq_domain_map(struct spmi_pmic_arb_bus *bus,
				   struct irq_domain *domain, unsigned int virq,
				   irq_hw_number_t hwirq, unsigned int type)
{}

static int qpnpint_irq_domain_alloc(struct irq_domain *domain,
				    unsigned int virq, unsigned int nr_irqs,
				    void *data)
{}

static int pmic_arb_init_apid_min_max(struct spmi_pmic_arb_bus *bus)
{}

static int pmic_arb_get_core_resources_v1(struct platform_device *pdev,
					  void __iomem *core)
{}

static int pmic_arb_init_apid_v1(struct spmi_pmic_arb_bus *bus, int index)
{}

static int pmic_arb_ppid_to_apid_v1(struct spmi_pmic_arb_bus *bus, u16 ppid)
{}

/* v1 offset per ee */
static int pmic_arb_offset_v1(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr,
			      enum pmic_arb_channel ch_type)
{}

static u16 pmic_arb_find_apid(struct spmi_pmic_arb_bus *bus, u16 ppid)
{}

static int pmic_arb_get_obsrvr_chnls_v2(struct platform_device *pdev)
{}

static int pmic_arb_get_core_resources_v2(struct platform_device *pdev,
					  void __iomem *core)
{}

static int pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb_bus *bus, u16 ppid)
{}

static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb_bus *bus)
{}

static int pmic_arb_ppid_to_apid_v5(struct spmi_pmic_arb_bus *bus, u16 ppid)
{}

/* v2 offset per ppid and per ee */
static int pmic_arb_offset_v2(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr,
			      enum pmic_arb_channel ch_type)
{}

static int pmic_arb_init_apid_v5(struct spmi_pmic_arb_bus *bus, int index)
{}

/*
 * v5 offset per ee and per apid for observer channels and per apid for
 * read/write channels.
 */
static int pmic_arb_offset_v5(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr,
			      enum pmic_arb_channel ch_type)
{}

static int pmic_arb_get_core_resources_v7(struct platform_device *pdev,
					  void __iomem *core)
{}

/*
 * Only v7 supports 2 buses. Each bus will get a different apid count, read
 * from different registers.
 */
static int pmic_arb_init_apid_v7(struct spmi_pmic_arb_bus *bus, int index)
{}

/*
 * v7 offset per ee and per apid for observer channels and per apid for
 * read/write channels.
 */
static int pmic_arb_offset_v7(struct spmi_pmic_arb_bus *bus, u8 sid, u16 addr,
			      enum pmic_arb_channel ch_type)
{}

static u32 pmic_arb_fmt_cmd_v1(u8 opc, u8 sid, u16 addr, u8 bc)
{}

static u32 pmic_arb_fmt_cmd_v2(u8 opc, u8 sid, u16 addr, u8 bc)
{}

static void __iomem *
pmic_arb_owner_acc_status_v1(struct spmi_pmic_arb_bus *bus, u8 m, u16 n)
{}

static void __iomem *
pmic_arb_owner_acc_status_v2(struct spmi_pmic_arb_bus *bus, u8 m, u16 n)
{}

static void __iomem *
pmic_arb_owner_acc_status_v3(struct spmi_pmic_arb_bus *bus, u8 m, u16 n)
{}

static void __iomem *
pmic_arb_owner_acc_status_v5(struct spmi_pmic_arb_bus *bus, u8 m, u16 n)
{}

static void __iomem *
pmic_arb_owner_acc_status_v7(struct spmi_pmic_arb_bus *bus, u8 m, u16 n)
{}

static void __iomem *
pmic_arb_acc_enable_v1(struct spmi_pmic_arb_bus *bus, u16 n)
{}

static void __iomem *
pmic_arb_acc_enable_v2(struct spmi_pmic_arb_bus *bus, u16 n)
{}

static void __iomem *
pmic_arb_acc_enable_v5(struct spmi_pmic_arb_bus *bus, u16 n)
{}

static void __iomem *
pmic_arb_acc_enable_v7(struct spmi_pmic_arb_bus *bus, u16 n)
{}

static void __iomem *
pmic_arb_irq_status_v1(struct spmi_pmic_arb_bus *bus, u16 n)
{}

static void __iomem *
pmic_arb_irq_status_v2(struct spmi_pmic_arb_bus *bus, u16 n)
{}

static void __iomem *
pmic_arb_irq_status_v5(struct spmi_pmic_arb_bus *bus, u16 n)
{}

static void __iomem *
pmic_arb_irq_status_v7(struct spmi_pmic_arb_bus *bus, u16 n)
{}

static void __iomem *
pmic_arb_irq_clear_v1(struct spmi_pmic_arb_bus *bus, u16 n)
{}

static void __iomem *
pmic_arb_irq_clear_v2(struct spmi_pmic_arb_bus *bus, u16 n)
{}

static void __iomem *
pmic_arb_irq_clear_v5(struct spmi_pmic_arb_bus *bus, u16 n)
{}

static void __iomem *
pmic_arb_irq_clear_v7(struct spmi_pmic_arb_bus *bus, u16 n)
{}

static u32 pmic_arb_apid_map_offset_v2(u16 n)
{}

static u32 pmic_arb_apid_map_offset_v5(u16 n)
{}

static u32 pmic_arb_apid_map_offset_v7(u16 n)
{}

static void __iomem *
pmic_arb_apid_owner_v2(struct spmi_pmic_arb_bus *bus, u16 n)
{}

/*
 * For arbiter version 7, APID ownership table registers have independent
 * numbering space for each SPMI bus instance, so each is indexed starting from
 * 0.
 */
static void __iomem *
pmic_arb_apid_owner_v7(struct spmi_pmic_arb_bus *bus, u16 n)
{}

static const struct pmic_arb_ver_ops pmic_arb_v1 =;

static const struct pmic_arb_ver_ops pmic_arb_v2 =;

static const struct pmic_arb_ver_ops pmic_arb_v3 =;

static const struct pmic_arb_ver_ops pmic_arb_v5 =;

static const struct pmic_arb_ver_ops pmic_arb_v7 =;

static const struct irq_domain_ops pmic_arb_irq_domain_ops =;

static int spmi_pmic_arb_bus_init(struct platform_device *pdev,
				  struct device_node *node,
				  struct spmi_pmic_arb *pmic_arb)
{}

static int spmi_pmic_arb_register_buses(struct spmi_pmic_arb *pmic_arb,
					struct platform_device *pdev)
{}

static void spmi_pmic_arb_deregister_buses(struct spmi_pmic_arb *pmic_arb)
{}

static int spmi_pmic_arb_probe(struct platform_device *pdev)
{}

static void spmi_pmic_arb_remove(struct platform_device *pdev)
{}

static const struct of_device_id spmi_pmic_arb_match_table[] =;
MODULE_DEVICE_TABLE(of, spmi_pmic_arb_match_table);

static struct platform_driver spmi_pmic_arb_driver =;
module_platform_driver();

MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_ALIAS();