linux/drivers/i3c/master/svc-i3c-master.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Silvaco dual-role I3C master driver
 *
 * Copyright (C) 2020 Silvaco
 * Author: Miquel RAYNAL <[email protected]>
 * Based on a work from: Conor Culhane <[email protected]>
 */

#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/errno.h>
#include <linux/i3c/master.h>
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>

/* Master Mode Registers */
#define SVC_I3C_MCONFIG
#define SVC_I3C_MCONFIG_MASTER_EN
#define SVC_I3C_MCONFIG_DISTO(x)
#define SVC_I3C_MCONFIG_HKEEP(x)
#define SVC_I3C_MCONFIG_ODSTOP(x)
#define SVC_I3C_MCONFIG_PPBAUD(x)
#define SVC_I3C_MCONFIG_PPLOW(x)
#define SVC_I3C_MCONFIG_ODBAUD(x)
#define SVC_I3C_MCONFIG_ODHPP(x)
#define SVC_I3C_MCONFIG_SKEW(x)
#define SVC_I3C_MCONFIG_I2CBAUD(x)

#define SVC_I3C_MCTRL
#define SVC_I3C_MCTRL_REQUEST_MASK
#define SVC_I3C_MCTRL_REQUEST_NONE
#define SVC_I3C_MCTRL_REQUEST_START_ADDR
#define SVC_I3C_MCTRL_REQUEST_STOP
#define SVC_I3C_MCTRL_REQUEST_IBI_ACKNACK
#define SVC_I3C_MCTRL_REQUEST_PROC_DAA
#define SVC_I3C_MCTRL_REQUEST_AUTO_IBI
#define SVC_I3C_MCTRL_TYPE_I3C
#define SVC_I3C_MCTRL_TYPE_I2C
#define SVC_I3C_MCTRL_IBIRESP_AUTO
#define SVC_I3C_MCTRL_IBIRESP_ACK_WITHOUT_BYTE
#define SVC_I3C_MCTRL_IBIRESP_ACK_WITH_BYTE
#define SVC_I3C_MCTRL_IBIRESP_NACK
#define SVC_I3C_MCTRL_IBIRESP_MANUAL
#define SVC_I3C_MCTRL_DIR(x)
#define SVC_I3C_MCTRL_DIR_WRITE
#define SVC_I3C_MCTRL_DIR_READ
#define SVC_I3C_MCTRL_ADDR(x)
#define SVC_I3C_MCTRL_RDTERM(x)

#define SVC_I3C_MSTATUS
#define SVC_I3C_MSTATUS_STATE(x)
#define SVC_I3C_MSTATUS_STATE_DAA(x)
#define SVC_I3C_MSTATUS_STATE_IDLE(x)
#define SVC_I3C_MSTATUS_BETWEEN(x)
#define SVC_I3C_MSTATUS_NACKED(x)
#define SVC_I3C_MSTATUS_IBITYPE(x)
#define SVC_I3C_MSTATUS_IBITYPE_IBI
#define SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST
#define SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN
#define SVC_I3C_MINT_SLVSTART
#define SVC_I3C_MINT_MCTRLDONE
#define SVC_I3C_MINT_COMPLETE
#define SVC_I3C_MINT_RXPEND
#define SVC_I3C_MINT_TXNOTFULL
#define SVC_I3C_MINT_IBIWON
#define SVC_I3C_MINT_ERRWARN
#define SVC_I3C_MSTATUS_SLVSTART(x)
#define SVC_I3C_MSTATUS_MCTRLDONE(x)
#define SVC_I3C_MSTATUS_COMPLETE(x)
#define SVC_I3C_MSTATUS_RXPEND(x)
#define SVC_I3C_MSTATUS_TXNOTFULL(x)
#define SVC_I3C_MSTATUS_IBIWON(x)
#define SVC_I3C_MSTATUS_ERRWARN(x)
#define SVC_I3C_MSTATUS_IBIADDR(x)

#define SVC_I3C_IBIRULES
#define SVC_I3C_IBIRULES_ADDR(slot, addr)
#define SVC_I3C_IBIRULES_ADDRS
#define SVC_I3C_IBIRULES_MSB0
#define SVC_I3C_IBIRULES_NOBYTE
#define SVC_I3C_IBIRULES_MANDBYTE
#define SVC_I3C_MINTSET
#define SVC_I3C_MINTCLR
#define SVC_I3C_MINTMASKED
#define SVC_I3C_MERRWARN
#define SVC_I3C_MERRWARN_NACK
#define SVC_I3C_MERRWARN_TIMEOUT
#define SVC_I3C_MDMACTRL
#define SVC_I3C_MDATACTRL
#define SVC_I3C_MDATACTRL_FLUSHTB
#define SVC_I3C_MDATACTRL_FLUSHRB
#define SVC_I3C_MDATACTRL_UNLOCK_TRIG
#define SVC_I3C_MDATACTRL_TXTRIG_FIFO_NOT_FULL
#define SVC_I3C_MDATACTRL_RXTRIG_FIFO_NOT_EMPTY
#define SVC_I3C_MDATACTRL_RXCOUNT(x)
#define SVC_I3C_MDATACTRL_TXFULL
#define SVC_I3C_MDATACTRL_RXEMPTY

#define SVC_I3C_MWDATAB
#define SVC_I3C_MWDATAB_END

#define SVC_I3C_MWDATABE
#define SVC_I3C_MWDATAH
#define SVC_I3C_MWDATAHE
#define SVC_I3C_MRDATAB
#define SVC_I3C_MRDATAH
#define SVC_I3C_MWMSG_SDR
#define SVC_I3C_MRMSG_SDR
#define SVC_I3C_MWMSG_DDR
#define SVC_I3C_MRMSG_DDR

#define SVC_I3C_MDYNADDR
#define SVC_MDYNADDR_VALID
#define SVC_MDYNADDR_ADDR(x)

#define SVC_I3C_MAX_DEVS
#define SVC_I3C_PM_TIMEOUT_MS

/* This parameter depends on the implementation and may be tuned */
#define SVC_I3C_FIFO_SIZE
#define SVC_I3C_PPBAUD_MAX
#define SVC_I3C_QUICK_I2C_CLK

#define SVC_I3C_EVENT_IBI
#define SVC_I3C_EVENT_HOTJOIN

struct svc_i3c_cmd {};

struct svc_i3c_xfer {};

struct svc_i3c_regs_save {};

/**
 * struct svc_i3c_master - Silvaco I3C Master structure
 * @base: I3C master controller
 * @dev: Corresponding device
 * @regs: Memory mapping
 * @saved_regs: Volatile values for PM operations
 * @free_slots: Bit array of available slots
 * @addrs: Array containing the dynamic addresses of each attached device
 * @descs: Array of descriptors, one per attached device
 * @hj_work: Hot-join work
 * @ibi_work: IBI work
 * @irq: Main interrupt
 * @pclk: System clock
 * @fclk: Fast clock (bus)
 * @sclk: Slow clock (other events)
 * @xferqueue: Transfer queue structure
 * @xferqueue.list: List member
 * @xferqueue.cur: Current ongoing transfer
 * @xferqueue.lock: Queue lock
 * @ibi: IBI structure
 * @ibi.num_slots: Number of slots available in @ibi.slots
 * @ibi.slots: Available IBI slots
 * @ibi.tbq_slot: To be queued IBI slot
 * @ibi.lock: IBI lock
 * @lock: Transfer lock, protect between IBI work thread and callbacks from master
 * @enabled_events: Bit masks for enable events (IBI, HotJoin).
 * @mctrl_config: Configuration value in SVC_I3C_MCTRL for setting speed back.
 */
struct svc_i3c_master {};

/**
 * struct svc_i3c_i2c_dev_data - Device specific data
 * @index: Index in the master tables corresponding to this device
 * @ibi: IBI slot index in the master structure
 * @ibi_pool: IBI pool associated to this device
 */
struct svc_i3c_i2c_dev_data {};

static inline bool is_events_enabled(struct svc_i3c_master *master, u32 mask)
{}

static bool svc_i3c_master_error(struct svc_i3c_master *master)
{}

static void svc_i3c_master_enable_interrupts(struct svc_i3c_master *master, u32 mask)
{}

static void svc_i3c_master_disable_interrupts(struct svc_i3c_master *master)
{}

static void svc_i3c_master_clear_merrwarn(struct svc_i3c_master *master)
{}

static void svc_i3c_master_flush_fifo(struct svc_i3c_master *master)
{}

static void svc_i3c_master_reset_fifo_trigger(struct svc_i3c_master *master)
{}

static void svc_i3c_master_reset(struct svc_i3c_master *master)
{}

static inline struct svc_i3c_master *
to_svc_i3c_master(struct i3c_master_controller *master)
{}

static void svc_i3c_master_hj_work(struct work_struct *work)
{}

static struct i3c_dev_desc *
svc_i3c_master_dev_from_addr(struct svc_i3c_master *master,
			     unsigned int ibiaddr)
{}

static void svc_i3c_master_emit_stop(struct svc_i3c_master *master)
{}

static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master,
				     struct i3c_dev_desc *dev)
{}

static void svc_i3c_master_ack_ibi(struct svc_i3c_master *master,
				   bool mandatory_byte)
{}

static void svc_i3c_master_nack_ibi(struct svc_i3c_master *master)
{}

static void svc_i3c_master_ibi_work(struct work_struct *work)
{}

static irqreturn_t svc_i3c_master_irq_handler(int irq, void *dev_id)
{}

static int svc_i3c_master_set_speed(struct i3c_master_controller *m,
				     enum i3c_open_drain_speed speed)
{}

static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
{}

static void svc_i3c_master_bus_cleanup(struct i3c_master_controller *m)
{}

static int svc_i3c_master_reserve_slot(struct svc_i3c_master *master)
{}

static void svc_i3c_master_release_slot(struct svc_i3c_master *master,
					unsigned int slot)
{}

static int svc_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev)
{}

static int svc_i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
					   u8 old_dyn_addr)
{}

static void svc_i3c_master_detach_i3c_dev(struct i3c_dev_desc *dev)
{}

static int svc_i3c_master_attach_i2c_dev(struct i2c_dev_desc *dev)
{}

static void svc_i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev)
{}

static int svc_i3c_master_readb(struct svc_i3c_master *master, u8 *dst,
				unsigned int len)
{}

static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
					u8 *addrs, unsigned int *count)
{}

static int svc_i3c_update_ibirules(struct svc_i3c_master *master)
{}

static int svc_i3c_master_do_daa(struct i3c_master_controller *m)
{}

static int svc_i3c_master_read(struct svc_i3c_master *master,
			       u8 *in, unsigned int len)
{}

static int svc_i3c_master_write(struct svc_i3c_master *master,
				const u8 *out, unsigned int len)
{}

static int svc_i3c_master_xfer(struct svc_i3c_master *master,
			       bool rnw, unsigned int xfer_type, u8 addr,
			       u8 *in, const u8 *out, unsigned int xfer_len,
			       unsigned int *actual_len, bool continued)
{}

static struct svc_i3c_xfer *
svc_i3c_master_alloc_xfer(struct svc_i3c_master *master, unsigned int ncmds)
{}

static void svc_i3c_master_free_xfer(struct svc_i3c_xfer *xfer)
{}

static void svc_i3c_master_dequeue_xfer_locked(struct svc_i3c_master *master,
					       struct svc_i3c_xfer *xfer)
{}

static void svc_i3c_master_dequeue_xfer(struct svc_i3c_master *master,
					struct svc_i3c_xfer *xfer)
{}

static void svc_i3c_master_start_xfer_locked(struct svc_i3c_master *master)
{}

static void svc_i3c_master_enqueue_xfer(struct svc_i3c_master *master,
					struct svc_i3c_xfer *xfer)
{}

static bool
svc_i3c_master_supports_ccc_cmd(struct i3c_master_controller *master,
				const struct i3c_ccc_cmd *cmd)
{}

static int svc_i3c_master_send_bdcast_ccc_cmd(struct svc_i3c_master *master,
					      struct i3c_ccc_cmd *ccc)
{}

static int svc_i3c_master_send_direct_ccc_cmd(struct svc_i3c_master *master,
					      struct i3c_ccc_cmd *ccc)
{}

static int svc_i3c_master_send_ccc_cmd(struct i3c_master_controller *m,
				       struct i3c_ccc_cmd *cmd)
{}

static int svc_i3c_master_priv_xfers(struct i3c_dev_desc *dev,
				     struct i3c_priv_xfer *xfers,
				     int nxfers)
{}

static int svc_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
				    const struct i2c_msg *xfers,
				    int nxfers)
{}

static int svc_i3c_master_request_ibi(struct i3c_dev_desc *dev,
				      const struct i3c_ibi_setup *req)
{}

static void svc_i3c_master_free_ibi(struct i3c_dev_desc *dev)
{}

static int svc_i3c_master_enable_ibi(struct i3c_dev_desc *dev)
{}

static int svc_i3c_master_disable_ibi(struct i3c_dev_desc *dev)
{}

static int svc_i3c_master_enable_hotjoin(struct i3c_master_controller *m)
{}

static int svc_i3c_master_disable_hotjoin(struct i3c_master_controller *m)
{}

static void svc_i3c_master_recycle_ibi_slot(struct i3c_dev_desc *dev,
					    struct i3c_ibi_slot *slot)
{}

static const struct i3c_master_controller_ops svc_i3c_master_ops =;

static int svc_i3c_master_prepare_clks(struct svc_i3c_master *master)
{}

static void svc_i3c_master_unprepare_clks(struct svc_i3c_master *master)
{}

static int svc_i3c_master_probe(struct platform_device *pdev)
{}

static void svc_i3c_master_remove(struct platform_device *pdev)
{}

static void svc_i3c_save_regs(struct svc_i3c_master *master)
{}

static void svc_i3c_restore_regs(struct svc_i3c_master *master)
{}

static int __maybe_unused svc_i3c_runtime_suspend(struct device *dev)
{}

static int __maybe_unused svc_i3c_runtime_resume(struct device *dev)
{}

static const struct dev_pm_ops svc_i3c_pm_ops =;

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

static struct platform_driver svc_i3c_master =;
module_platform_driver();

MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();