xref: /openbmc/linux/drivers/i2c/busses/i2c-amd-mp2.h (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
1529766e0SElie Morisse /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
2529766e0SElie Morisse /*
3529766e0SElie Morisse  * AMD MP2 I2C adapter driver
4529766e0SElie Morisse  *
5529766e0SElie Morisse  * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
6529766e0SElie Morisse  *          Elie Morisse <syniurge@gmail.com>
7529766e0SElie Morisse  */
8529766e0SElie Morisse 
9529766e0SElie Morisse #ifndef I2C_AMD_PCI_MP2_H
10529766e0SElie Morisse #define I2C_AMD_PCI_MP2_H
11529766e0SElie Morisse 
12529766e0SElie Morisse #include <linux/i2c.h>
13529766e0SElie Morisse #include <linux/pci.h>
14529766e0SElie Morisse #include <linux/pm_runtime.h>
15529766e0SElie Morisse 
16529766e0SElie Morisse #define PCI_DEVICE_ID_AMD_MP2	0x15E6
17529766e0SElie Morisse 
18529766e0SElie Morisse struct amd_i2c_common;
19529766e0SElie Morisse struct amd_mp2_dev;
20529766e0SElie Morisse 
21529766e0SElie Morisse enum {
22529766e0SElie Morisse 	/* MP2 C2P Message Registers */
23529766e0SElie Morisse 	AMD_C2P_MSG0 = 0x10500,			/* MP2 Message for I2C0 */
24529766e0SElie Morisse 	AMD_C2P_MSG1 = 0x10504,			/* MP2 Message for I2C1 */
25529766e0SElie Morisse 	AMD_C2P_MSG2 = 0x10508,			/* DRAM Address Lo / Data 0 */
26529766e0SElie Morisse 	AMD_C2P_MSG3 = 0x1050c,			/* DRAM Address HI / Data 1 */
27529766e0SElie Morisse 	AMD_C2P_MSG4 = 0x10510,			/* Data 2 */
28529766e0SElie Morisse 	AMD_C2P_MSG5 = 0x10514,			/* Data 3 */
29529766e0SElie Morisse 	AMD_C2P_MSG6 = 0x10518,			/* Data 4 */
30529766e0SElie Morisse 	AMD_C2P_MSG7 = 0x1051c,			/* Data 5 */
31529766e0SElie Morisse 	AMD_C2P_MSG8 = 0x10520,			/* Data 6 */
32529766e0SElie Morisse 	AMD_C2P_MSG9 = 0x10524,			/* Data 7 */
33529766e0SElie Morisse 
34529766e0SElie Morisse 	/* MP2 P2C Message Registers */
35529766e0SElie Morisse 	AMD_P2C_MSG0 = 0x10680,			/* Do not use */
36529766e0SElie Morisse 	AMD_P2C_MSG1 = 0x10684,			/* I2C0 interrupt register */
37529766e0SElie Morisse 	AMD_P2C_MSG2 = 0x10688,			/* I2C1 interrupt register */
38529766e0SElie Morisse 	AMD_P2C_MSG3 = 0x1068C,			/* MP2 debug info */
39529766e0SElie Morisse 	AMD_P2C_MSG_INTEN = 0x10690,		/* MP2 interrupt gen register */
40529766e0SElie Morisse 	AMD_P2C_MSG_INTSTS = 0x10694,		/* Interrupt status */
41529766e0SElie Morisse };
42529766e0SElie Morisse 
43529766e0SElie Morisse /* Command register data structures */
44529766e0SElie Morisse 
45529766e0SElie Morisse #define i2c_none (-1)
46529766e0SElie Morisse enum i2c_cmd {
47529766e0SElie Morisse 	i2c_read = 0,
48529766e0SElie Morisse 	i2c_write,
49529766e0SElie Morisse 	i2c_enable,
50529766e0SElie Morisse 	i2c_disable,
51529766e0SElie Morisse 	number_of_sensor_discovered,
52529766e0SElie Morisse 	is_mp2_active,
53529766e0SElie Morisse 	invalid_cmd = 0xF,
54529766e0SElie Morisse };
55529766e0SElie Morisse 
56529766e0SElie Morisse enum speed_enum {
57529766e0SElie Morisse 	speed100k = 0,
58529766e0SElie Morisse 	speed400k = 1,
59529766e0SElie Morisse 	speed1000k = 2,
60529766e0SElie Morisse 	speed1400k = 3,
61529766e0SElie Morisse 	speed3400k = 4
62529766e0SElie Morisse };
63529766e0SElie Morisse 
64529766e0SElie Morisse enum mem_type {
65529766e0SElie Morisse 	use_dram = 0,
66529766e0SElie Morisse 	use_c2pmsg = 1,
67529766e0SElie Morisse };
68529766e0SElie Morisse 
69529766e0SElie Morisse /**
70529766e0SElie Morisse  * union i2c_cmd_base : bit access of C2P commands
71529766e0SElie Morisse  * @i2c_cmd: bit 0..3 i2c R/W command
72529766e0SElie Morisse  * @bus_id: bit 4..7 i2c bus index
73529766e0SElie Morisse  * @slave_addr: bit 8..15 slave address
74529766e0SElie Morisse  * @length: bit 16..27 read/write length
75529766e0SElie Morisse  * @i2c_speed: bit 28..30 bus speed
76529766e0SElie Morisse  * @mem_type: bit 31 0-DRAM; 1-C2P msg o/p
77529766e0SElie Morisse  */
78529766e0SElie Morisse union i2c_cmd_base {
79529766e0SElie Morisse 	u32 ul;
80529766e0SElie Morisse 	struct {
81529766e0SElie Morisse 		enum i2c_cmd i2c_cmd : 4;
82529766e0SElie Morisse 		u8 bus_id : 4;
83529766e0SElie Morisse 		u32 slave_addr : 8;
84529766e0SElie Morisse 		u32 length : 12;
85529766e0SElie Morisse 		enum speed_enum i2c_speed : 3;
86529766e0SElie Morisse 		enum mem_type mem_type : 1;
87529766e0SElie Morisse 	} s;
88529766e0SElie Morisse };
89529766e0SElie Morisse 
90529766e0SElie Morisse enum response_type {
91529766e0SElie Morisse 	invalid_response = 0,
92529766e0SElie Morisse 	command_success = 1,
93529766e0SElie Morisse 	command_failed = 2,
94529766e0SElie Morisse };
95529766e0SElie Morisse 
96529766e0SElie Morisse enum status_type {
97529766e0SElie Morisse 	i2c_readcomplete_event = 0,
98529766e0SElie Morisse 	i2c_readfail_event = 1,
99529766e0SElie Morisse 	i2c_writecomplete_event = 2,
100529766e0SElie Morisse 	i2c_writefail_event = 3,
101529766e0SElie Morisse 	i2c_busenable_complete = 4,
102529766e0SElie Morisse 	i2c_busenable_failed = 5,
103529766e0SElie Morisse 	i2c_busdisable_complete = 6,
104529766e0SElie Morisse 	i2c_busdisable_failed = 7,
105529766e0SElie Morisse 	invalid_data_length = 8,
106529766e0SElie Morisse 	invalid_slave_address = 9,
107529766e0SElie Morisse 	invalid_i2cbus_id = 10,
108529766e0SElie Morisse 	invalid_dram_addr = 11,
109529766e0SElie Morisse 	invalid_command = 12,
110529766e0SElie Morisse 	mp2_active = 13,
111529766e0SElie Morisse 	numberof_sensors_discovered_resp = 14,
112529766e0SElie Morisse 	i2c_bus_notinitialized
113529766e0SElie Morisse };
114529766e0SElie Morisse 
115529766e0SElie Morisse /**
116529766e0SElie Morisse  * union i2c_event : bit access of P2C events
117529766e0SElie Morisse  * @response: bit 0..1 i2c response type
118529766e0SElie Morisse  * @status: bit 2..6 status_type
119529766e0SElie Morisse  * @mem_type: bit 7 0-DRAM; 1-C2P msg o/p
120529766e0SElie Morisse  * @bus_id: bit 8..11 i2c bus id
121529766e0SElie Morisse  * @length: bit 12..23 message length
122529766e0SElie Morisse  * @slave_addr: bit 24-31 slave address
123529766e0SElie Morisse  */
124529766e0SElie Morisse union i2c_event {
125529766e0SElie Morisse 	u32 ul;
126529766e0SElie Morisse 	struct {
127529766e0SElie Morisse 		enum response_type response : 2;
128529766e0SElie Morisse 		enum status_type status : 5;
129529766e0SElie Morisse 		enum mem_type mem_type : 1;
130529766e0SElie Morisse 		u8 bus_id : 4;
131529766e0SElie Morisse 		u32 length : 12;
132529766e0SElie Morisse 		u32 slave_addr : 8;
133529766e0SElie Morisse 	} r;
134529766e0SElie Morisse };
135529766e0SElie Morisse 
136529766e0SElie Morisse /**
137529766e0SElie Morisse  * struct amd_i2c_common - per bus/i2c adapter context, shared
138529766e0SElie Morisse  *	between the pci and the platform driver
139529766e0SElie Morisse  * @eventval: MP2 event value set by the IRQ handler
140529766e0SElie Morisse  * @mp2_dev: MP2 pci device this adapter is part of
141529766e0SElie Morisse  * @msg: i2c message
142529766e0SElie Morisse  * @cmd_completion: function called by the IRQ handler to signal
143529766e0SElie Morisse  *		    the platform driver
144529766e0SElie Morisse  * @reqcmd: requested i2c command type
145529766e0SElie Morisse  * @cmd_success: set to true if the MP2 responded to a command with
146529766e0SElie Morisse  *		 the expected status and response type
147529766e0SElie Morisse  * @bus_id: bus index
148529766e0SElie Morisse  * @i2c_speed: i2c bus speed determined by the slowest slave
149529766e0SElie Morisse  * @dma_buf: if msg length > 32, holds the DMA buffer virtual address
150529766e0SElie Morisse  * @dma_addr: if msg length > 32, holds the DMA buffer address
151529766e0SElie Morisse  */
152529766e0SElie Morisse struct amd_i2c_common {
153529766e0SElie Morisse 	union i2c_event eventval;
154529766e0SElie Morisse 	struct amd_mp2_dev *mp2_dev;
155529766e0SElie Morisse 	struct i2c_msg *msg;
156529766e0SElie Morisse 	void (*cmd_completion)(struct amd_i2c_common *i2c_common);
157529766e0SElie Morisse 	enum i2c_cmd reqcmd;
158529766e0SElie Morisse 	u8 cmd_success;
159529766e0SElie Morisse 	u8 bus_id;
160529766e0SElie Morisse 	enum speed_enum i2c_speed;
161529766e0SElie Morisse 	u8 *dma_buf;
162529766e0SElie Morisse 	dma_addr_t dma_addr;
163529766e0SElie Morisse #ifdef CONFIG_PM
164529766e0SElie Morisse 	int (*suspend)(struct amd_i2c_common *i2c_common);
165529766e0SElie Morisse 	int (*resume)(struct amd_i2c_common *i2c_common);
166529766e0SElie Morisse #endif /* CONFIG_PM */
167529766e0SElie Morisse };
168529766e0SElie Morisse 
169529766e0SElie Morisse /**
170529766e0SElie Morisse  * struct amd_mp2_dev - per PCI device context
171529766e0SElie Morisse  * @pci_dev: PCI driver node
172529766e0SElie Morisse  * @busses: MP2 devices may have up to two busses,
173529766e0SElie Morisse  *	    each bus corresponding to an i2c adapter
174529766e0SElie Morisse  * @mmio: iommapped registers
175529766e0SElie Morisse  * @c2p_lock: controls access to the C2P mailbox shared between
176529766e0SElie Morisse  *	      the two adapters
177529766e0SElie Morisse  * @c2p_lock_busid: id of the adapter which locked c2p_lock
178529766e0SElie Morisse  */
179529766e0SElie Morisse struct amd_mp2_dev {
180529766e0SElie Morisse 	struct pci_dev *pci_dev;
181529766e0SElie Morisse 	struct amd_i2c_common *busses[2];
182529766e0SElie Morisse 	void __iomem *mmio;
183529766e0SElie Morisse 	struct mutex c2p_lock;
184529766e0SElie Morisse 	u8 c2p_lock_busid;
185529766e0SElie Morisse 	unsigned int probed;
186*969864efSRaju Rangoju 	int dev_irq;
187529766e0SElie Morisse };
188529766e0SElie Morisse 
189529766e0SElie Morisse /* PCIe communication driver */
190529766e0SElie Morisse 
191529766e0SElie Morisse int amd_mp2_rw(struct amd_i2c_common *i2c_common, enum i2c_cmd reqcmd);
192529766e0SElie Morisse int amd_mp2_bus_enable_set(struct amd_i2c_common *i2c_common, bool enable);
193529766e0SElie Morisse 
194529766e0SElie Morisse void amd_mp2_process_event(struct amd_i2c_common *i2c_common);
195529766e0SElie Morisse 
196529766e0SElie Morisse void amd_mp2_rw_timeout(struct amd_i2c_common *i2c_common);
197529766e0SElie Morisse 
198529766e0SElie Morisse int amd_mp2_register_cb(struct amd_i2c_common *i2c_common);
199529766e0SElie Morisse int amd_mp2_unregister_cb(struct amd_i2c_common *i2c_common);
200529766e0SElie Morisse 
201529766e0SElie Morisse struct amd_mp2_dev *amd_mp2_find_device(void);
202529766e0SElie Morisse 
amd_mp2_pm_runtime_get(struct amd_mp2_dev * mp2_dev)203529766e0SElie Morisse static inline void amd_mp2_pm_runtime_get(struct amd_mp2_dev *mp2_dev)
204529766e0SElie Morisse {
205529766e0SElie Morisse 	pm_runtime_get_sync(&mp2_dev->pci_dev->dev);
206529766e0SElie Morisse }
207529766e0SElie Morisse 
amd_mp2_pm_runtime_put(struct amd_mp2_dev * mp2_dev)208529766e0SElie Morisse static inline void amd_mp2_pm_runtime_put(struct amd_mp2_dev *mp2_dev)
209529766e0SElie Morisse {
210529766e0SElie Morisse 	pm_runtime_mark_last_busy(&mp2_dev->pci_dev->dev);
211529766e0SElie Morisse 	pm_runtime_put_autosuspend(&mp2_dev->pci_dev->dev);
212529766e0SElie Morisse }
213529766e0SElie Morisse 
214529766e0SElie Morisse #endif
215