2023-03-31 09:14:59 +00:00
|
|
|
/* 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;
|
|
|
|
};
|
|
|
|
|
2023-03-30 07:50:33 +00:00
|
|
|
struct dw_i3c_dat_entry {
|
|
|
|
u8 addr;
|
2024-07-08 06:21:01 +00:00
|
|
|
bool is_i2c_addr;
|
2023-03-30 07:50:34 +00:00
|
|
|
struct i3c_dev_desc *ibi_dev;
|
2023-03-30 07:50:33 +00:00
|
|
|
};
|
|
|
|
|
2023-03-31 09:14:59 +00:00
|
|
|
struct dw_i3c_master {
|
|
|
|
struct i3c_master_controller base;
|
2024-07-08 06:21:03 +00:00
|
|
|
struct device *dev;
|
2023-03-31 09:14:59 +00:00
|
|
|
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;
|
2024-06-28 15:46:18 +00:00
|
|
|
struct clk *pclk;
|
2023-03-31 09:14:59 +00:00
|
|
|
char version[5];
|
|
|
|
char type[5];
|
2024-06-07 07:20:30 +00:00
|
|
|
u32 sir_rej_mask;
|
2024-07-08 06:21:01 +00:00
|
|
|
bool i2c_slv_prsnt;
|
|
|
|
u32 dev_addr;
|
|
|
|
u32 i3c_pp_timing;
|
|
|
|
u32 i3c_od_timing;
|
|
|
|
u32 ext_lcnt_timing;
|
|
|
|
u32 bus_free_timing;
|
|
|
|
u32 i2c_fm_timing;
|
|
|
|
u32 i2c_fmp_timing;
|
2023-03-30 07:50:33 +00:00
|
|
|
/*
|
|
|
|
* Per-device hardware data, used to manage the device address table
|
|
|
|
* (DAT)
|
2023-03-30 07:50:34 +00:00
|
|
|
*
|
|
|
|
* 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.
|
2023-03-30 07:50:33 +00:00
|
|
|
*/
|
|
|
|
struct dw_i3c_dat_entry devs[DW_I3C_MAX_DEVS];
|
2023-03-30 07:50:34 +00:00
|
|
|
spinlock_t devs_lock;
|
2023-03-31 09:14:59 +00:00
|
|
|
|
|
|
|
/* platform-specific data */
|
|
|
|
const struct dw_i3c_platform_ops *platform_ops;
|
2024-04-29 07:36:24 +00:00
|
|
|
|
|
|
|
struct work_struct hj_work;
|
2023-03-31 09:14:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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);
|
2023-03-30 07:50:35 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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);
|
2023-03-31 09:14:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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);
|
|
|
|
|