1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (c) 2023 Code Construct 4 * 5 * Author: Jeremy Kerr <jk@codeconstruct.com.au> 6 */ 7 8 #include <linux/clk.h> 9 #include <linux/i3c/master.h> 10 #include <linux/reset.h> 11 #include <linux/types.h> 12 13 #define DW_I3C_MAX_DEVS 32 14 15 struct dw_i3c_master_caps { 16 u8 cmdfifodepth; 17 u8 datafifodepth; 18 }; 19 20 struct dw_i3c_dat_entry { 21 u8 addr; 22 struct i3c_dev_desc *ibi_dev; 23 }; 24 25 struct dw_i3c_master { 26 struct i3c_master_controller base; 27 u16 maxdevs; 28 u16 datstartaddr; 29 u32 free_pos; 30 struct { 31 struct list_head list; 32 struct dw_i3c_xfer *cur; 33 spinlock_t lock; 34 } xferqueue; 35 struct dw_i3c_master_caps caps; 36 void __iomem *regs; 37 struct reset_control *core_rst; 38 struct clk *core_clk; 39 char version[5]; 40 char type[5]; 41 bool ibi_capable; 42 43 /* 44 * Per-device hardware data, used to manage the device address table 45 * (DAT) 46 * 47 * Locking: the devs array may be referenced in IRQ context while 48 * processing an IBI. However, IBIs (for a specific device, which 49 * implies a specific DAT entry) can only happen while interrupts are 50 * requested for that device, which is serialised against other 51 * insertions/removals from the array by the global i3c infrastructure. 52 * So, devs_lock protects against concurrent updates to devs->ibi_dev 53 * between request_ibi/free_ibi and the IBI irq event. 54 */ 55 struct dw_i3c_dat_entry devs[DW_I3C_MAX_DEVS]; 56 spinlock_t devs_lock; 57 58 /* platform-specific data */ 59 const struct dw_i3c_platform_ops *platform_ops; 60 }; 61 62 struct dw_i3c_platform_ops { 63 /* 64 * Called on early bus init: the i3c has been set up, but before any 65 * transactions have taken place. Platform implementations may use to 66 * perform actual device enabling with the i3c core ready. 67 */ 68 int (*init)(struct dw_i3c_master *i3c); 69 70 /* 71 * Initialise a DAT entry to enable/disable IBIs. Allows the platform 72 * to perform any device workarounds on the DAT entry before 73 * inserting into the hardware table. 74 * 75 * Called with the DAT lock held; must not sleep. 76 */ 77 void (*set_dat_ibi)(struct dw_i3c_master *i3c, 78 struct i3c_dev_desc *dev, bool enable, u32 *reg); 79 }; 80 81 extern int dw_i3c_common_probe(struct dw_i3c_master *master, 82 struct platform_device *pdev); 83 extern void dw_i3c_common_remove(struct dw_i3c_master *master); 84 85