85 lines
2.2 KiB
C
85 lines
2.2 KiB
C
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||
|
/*
|
||
|
* Copyright (c) 2023 Code Construct
|
||
|
*
|
||
|
* Author: Jeremy Kerr <jk@codeconstruct.com.au>
|
||
|
*/
|
||
|
|
||
|
#include <linux/clk.h>
|
||
|
#include <linux/i3c/master.h>
|
||
|
#include <linux/reset.h>
|
||
|
#include <linux/types.h>
|
||
|
|
||
|
#define DW_I3C_MAX_DEVS 32
|
||
|
|
||
|
struct dw_i3c_master_caps {
|
||
|
u8 cmdfifodepth;
|
||
|
u8 datafifodepth;
|
||
|
};
|
||
|
|
||
|
struct dw_i3c_dat_entry {
|
||
|
u8 addr;
|
||
|
struct i3c_dev_desc *ibi_dev;
|
||
|
};
|
||
|
|
||
|
struct dw_i3c_master {
|
||
|
struct i3c_master_controller base;
|
||
|
u16 maxdevs;
|
||
|
u16 datstartaddr;
|
||
|
u32 free_pos;
|
||
|
struct {
|
||
|
struct list_head list;
|
||
|
struct dw_i3c_xfer *cur;
|
||
|
spinlock_t lock;
|
||
|
} xferqueue;
|
||
|
struct dw_i3c_master_caps caps;
|
||
|
void __iomem *regs;
|
||
|
struct reset_control *core_rst;
|
||
|
struct clk *core_clk;
|
||
|
char version[5];
|
||
|
char type[5];
|
||
|
bool ibi_capable;
|
||
|
|
||
|
/*
|
||
|
* Per-device hardware data, used to manage the device address table
|
||
|
* (DAT)
|
||
|
*
|
||
|
* Locking: the devs array may be referenced in IRQ context while
|
||
|
* processing an IBI. However, IBIs (for a specific device, which
|
||
|
* implies a specific DAT entry) can only happen while interrupts are
|
||
|
* requested for that device, which is serialised against other
|
||
|
* insertions/removals from the array by the global i3c infrastructure.
|
||
|
* So, devs_lock protects against concurrent updates to devs->ibi_dev
|
||
|
* between request_ibi/free_ibi and the IBI irq event.
|
||
|
*/
|
||
|
struct dw_i3c_dat_entry devs[DW_I3C_MAX_DEVS];
|
||
|
spinlock_t devs_lock;
|
||
|
|
||
|
/* platform-specific data */
|
||
|
const struct dw_i3c_platform_ops *platform_ops;
|
||
|
};
|
||
|
|
||
|
struct dw_i3c_platform_ops {
|
||
|
/*
|
||
|
* Called on early bus init: the i3c has been set up, but before any
|
||
|
* transactions have taken place. Platform implementations may use to
|
||
|
* perform actual device enabling with the i3c core ready.
|
||
|
*/
|
||
|
int (*init)(struct dw_i3c_master *i3c);
|
||
|
|
||
|
/*
|
||
|
* Initialise a DAT entry to enable/disable IBIs. Allows the platform
|
||
|
* to perform any device workarounds on the DAT entry before
|
||
|
* inserting into the hardware table.
|
||
|
*
|
||
|
* Called with the DAT lock held; must not sleep.
|
||
|
*/
|
||
|
void (*set_dat_ibi)(struct dw_i3c_master *i3c,
|
||
|
struct i3c_dev_desc *dev, bool enable, u32 *reg);
|
||
|
};
|
||
|
|
||
|
extern int dw_i3c_common_probe(struct dw_i3c_master *master,
|
||
|
struct platform_device *pdev);
|
||
|
extern void dw_i3c_common_remove(struct dw_i3c_master *master);
|
||
|
|