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 | |