1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * AMD MP2 I2C adapter driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
6*4882a593Smuzhiyun * Elie Morisse <syniurge@gmail.com>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #ifndef I2C_AMD_PCI_MP2_H
10*4882a593Smuzhiyun #define I2C_AMD_PCI_MP2_H
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/i2c.h>
13*4882a593Smuzhiyun #include <linux/pci.h>
14*4882a593Smuzhiyun #include <linux/pm_runtime.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #define PCI_DEVICE_ID_AMD_MP2 0x15E6
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun struct amd_i2c_common;
19*4882a593Smuzhiyun struct amd_mp2_dev;
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun enum {
22*4882a593Smuzhiyun /* MP2 C2P Message Registers */
23*4882a593Smuzhiyun AMD_C2P_MSG0 = 0x10500, /* MP2 Message for I2C0 */
24*4882a593Smuzhiyun AMD_C2P_MSG1 = 0x10504, /* MP2 Message for I2C1 */
25*4882a593Smuzhiyun AMD_C2P_MSG2 = 0x10508, /* DRAM Address Lo / Data 0 */
26*4882a593Smuzhiyun AMD_C2P_MSG3 = 0x1050c, /* DRAM Address HI / Data 1 */
27*4882a593Smuzhiyun AMD_C2P_MSG4 = 0x10510, /* Data 2 */
28*4882a593Smuzhiyun AMD_C2P_MSG5 = 0x10514, /* Data 3 */
29*4882a593Smuzhiyun AMD_C2P_MSG6 = 0x10518, /* Data 4 */
30*4882a593Smuzhiyun AMD_C2P_MSG7 = 0x1051c, /* Data 5 */
31*4882a593Smuzhiyun AMD_C2P_MSG8 = 0x10520, /* Data 6 */
32*4882a593Smuzhiyun AMD_C2P_MSG9 = 0x10524, /* Data 7 */
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun /* MP2 P2C Message Registers */
35*4882a593Smuzhiyun AMD_P2C_MSG0 = 0x10680, /* Do not use */
36*4882a593Smuzhiyun AMD_P2C_MSG1 = 0x10684, /* I2C0 interrupt register */
37*4882a593Smuzhiyun AMD_P2C_MSG2 = 0x10688, /* I2C1 interrupt register */
38*4882a593Smuzhiyun AMD_P2C_MSG3 = 0x1068C, /* MP2 debug info */
39*4882a593Smuzhiyun AMD_P2C_MSG_INTEN = 0x10690, /* MP2 interrupt gen register */
40*4882a593Smuzhiyun AMD_P2C_MSG_INTSTS = 0x10694, /* Interrupt status */
41*4882a593Smuzhiyun };
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun /* Command register data structures */
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun #define i2c_none (-1)
46*4882a593Smuzhiyun enum i2c_cmd {
47*4882a593Smuzhiyun i2c_read = 0,
48*4882a593Smuzhiyun i2c_write,
49*4882a593Smuzhiyun i2c_enable,
50*4882a593Smuzhiyun i2c_disable,
51*4882a593Smuzhiyun number_of_sensor_discovered,
52*4882a593Smuzhiyun is_mp2_active,
53*4882a593Smuzhiyun invalid_cmd = 0xF,
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun enum speed_enum {
57*4882a593Smuzhiyun speed100k = 0,
58*4882a593Smuzhiyun speed400k = 1,
59*4882a593Smuzhiyun speed1000k = 2,
60*4882a593Smuzhiyun speed1400k = 3,
61*4882a593Smuzhiyun speed3400k = 4
62*4882a593Smuzhiyun };
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun enum mem_type {
65*4882a593Smuzhiyun use_dram = 0,
66*4882a593Smuzhiyun use_c2pmsg = 1,
67*4882a593Smuzhiyun };
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun /**
70*4882a593Smuzhiyun * union i2c_cmd_base : bit access of C2P commands
71*4882a593Smuzhiyun * @i2c_cmd: bit 0..3 i2c R/W command
72*4882a593Smuzhiyun * @bus_id: bit 4..7 i2c bus index
73*4882a593Smuzhiyun * @slave_addr: bit 8..15 slave address
74*4882a593Smuzhiyun * @length: bit 16..27 read/write length
75*4882a593Smuzhiyun * @i2c_speed: bit 28..30 bus speed
76*4882a593Smuzhiyun * @mem_type: bit 31 0-DRAM; 1-C2P msg o/p
77*4882a593Smuzhiyun */
78*4882a593Smuzhiyun union i2c_cmd_base {
79*4882a593Smuzhiyun u32 ul;
80*4882a593Smuzhiyun struct {
81*4882a593Smuzhiyun enum i2c_cmd i2c_cmd : 4;
82*4882a593Smuzhiyun u8 bus_id : 4;
83*4882a593Smuzhiyun u32 slave_addr : 8;
84*4882a593Smuzhiyun u32 length : 12;
85*4882a593Smuzhiyun enum speed_enum i2c_speed : 3;
86*4882a593Smuzhiyun enum mem_type mem_type : 1;
87*4882a593Smuzhiyun } s;
88*4882a593Smuzhiyun };
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun enum response_type {
91*4882a593Smuzhiyun invalid_response = 0,
92*4882a593Smuzhiyun command_success = 1,
93*4882a593Smuzhiyun command_failed = 2,
94*4882a593Smuzhiyun };
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun enum status_type {
97*4882a593Smuzhiyun i2c_readcomplete_event = 0,
98*4882a593Smuzhiyun i2c_readfail_event = 1,
99*4882a593Smuzhiyun i2c_writecomplete_event = 2,
100*4882a593Smuzhiyun i2c_writefail_event = 3,
101*4882a593Smuzhiyun i2c_busenable_complete = 4,
102*4882a593Smuzhiyun i2c_busenable_failed = 5,
103*4882a593Smuzhiyun i2c_busdisable_complete = 6,
104*4882a593Smuzhiyun i2c_busdisable_failed = 7,
105*4882a593Smuzhiyun invalid_data_length = 8,
106*4882a593Smuzhiyun invalid_slave_address = 9,
107*4882a593Smuzhiyun invalid_i2cbus_id = 10,
108*4882a593Smuzhiyun invalid_dram_addr = 11,
109*4882a593Smuzhiyun invalid_command = 12,
110*4882a593Smuzhiyun mp2_active = 13,
111*4882a593Smuzhiyun numberof_sensors_discovered_resp = 14,
112*4882a593Smuzhiyun i2c_bus_notinitialized
113*4882a593Smuzhiyun };
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /**
116*4882a593Smuzhiyun * union i2c_event : bit access of P2C events
117*4882a593Smuzhiyun * @response: bit 0..1 i2c response type
118*4882a593Smuzhiyun * @status: bit 2..6 status_type
119*4882a593Smuzhiyun * @mem_type: bit 7 0-DRAM; 1-C2P msg o/p
120*4882a593Smuzhiyun * @bus_id: bit 8..11 i2c bus id
121*4882a593Smuzhiyun * @length: bit 12..23 message length
122*4882a593Smuzhiyun * @slave_addr: bit 24-31 slave address
123*4882a593Smuzhiyun */
124*4882a593Smuzhiyun union i2c_event {
125*4882a593Smuzhiyun u32 ul;
126*4882a593Smuzhiyun struct {
127*4882a593Smuzhiyun enum response_type response : 2;
128*4882a593Smuzhiyun enum status_type status : 5;
129*4882a593Smuzhiyun enum mem_type mem_type : 1;
130*4882a593Smuzhiyun u8 bus_id : 4;
131*4882a593Smuzhiyun u32 length : 12;
132*4882a593Smuzhiyun u32 slave_addr : 8;
133*4882a593Smuzhiyun } r;
134*4882a593Smuzhiyun };
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun /**
137*4882a593Smuzhiyun * struct amd_i2c_common - per bus/i2c adapter context, shared
138*4882a593Smuzhiyun * between the pci and the platform driver
139*4882a593Smuzhiyun * @eventval: MP2 event value set by the IRQ handler
140*4882a593Smuzhiyun * @mp2_dev: MP2 pci device this adapter is part of
141*4882a593Smuzhiyun * @msg: i2c message
142*4882a593Smuzhiyun * @cmd_completion: function called by the IRQ handler to signal
143*4882a593Smuzhiyun * the platform driver
144*4882a593Smuzhiyun * @reqcmd: requested i2c command type
145*4882a593Smuzhiyun * @cmd_success: set to true if the MP2 responded to a command with
146*4882a593Smuzhiyun * the expected status and response type
147*4882a593Smuzhiyun * @bus_id: bus index
148*4882a593Smuzhiyun * @i2c_speed: i2c bus speed determined by the slowest slave
149*4882a593Smuzhiyun * @dma_buf: if msg length > 32, holds the DMA buffer virtual address
150*4882a593Smuzhiyun * @dma_addr: if msg length > 32, holds the DMA buffer address
151*4882a593Smuzhiyun */
152*4882a593Smuzhiyun struct amd_i2c_common {
153*4882a593Smuzhiyun union i2c_event eventval;
154*4882a593Smuzhiyun struct amd_mp2_dev *mp2_dev;
155*4882a593Smuzhiyun struct i2c_msg *msg;
156*4882a593Smuzhiyun void (*cmd_completion)(struct amd_i2c_common *i2c_common);
157*4882a593Smuzhiyun enum i2c_cmd reqcmd;
158*4882a593Smuzhiyun u8 cmd_success;
159*4882a593Smuzhiyun u8 bus_id;
160*4882a593Smuzhiyun enum speed_enum i2c_speed;
161*4882a593Smuzhiyun u8 *dma_buf;
162*4882a593Smuzhiyun dma_addr_t dma_addr;
163*4882a593Smuzhiyun #ifdef CONFIG_PM
164*4882a593Smuzhiyun int (*suspend)(struct amd_i2c_common *i2c_common);
165*4882a593Smuzhiyun int (*resume)(struct amd_i2c_common *i2c_common);
166*4882a593Smuzhiyun #endif /* CONFIG_PM */
167*4882a593Smuzhiyun };
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /**
170*4882a593Smuzhiyun * struct amd_mp2_dev - per PCI device context
171*4882a593Smuzhiyun * @pci_dev: PCI driver node
172*4882a593Smuzhiyun * @busses: MP2 devices may have up to two busses,
173*4882a593Smuzhiyun * each bus corresponding to an i2c adapter
174*4882a593Smuzhiyun * @mmio: iommapped registers
175*4882a593Smuzhiyun * @c2p_lock: controls access to the C2P mailbox shared between
176*4882a593Smuzhiyun * the two adapters
177*4882a593Smuzhiyun * @c2p_lock_busid: id of the adapter which locked c2p_lock
178*4882a593Smuzhiyun */
179*4882a593Smuzhiyun struct amd_mp2_dev {
180*4882a593Smuzhiyun struct pci_dev *pci_dev;
181*4882a593Smuzhiyun struct amd_i2c_common *busses[2];
182*4882a593Smuzhiyun void __iomem *mmio;
183*4882a593Smuzhiyun struct mutex c2p_lock;
184*4882a593Smuzhiyun u8 c2p_lock_busid;
185*4882a593Smuzhiyun unsigned int probed;
186*4882a593Smuzhiyun };
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun #define ndev_pdev(ndev) ((ndev)->pci_dev)
189*4882a593Smuzhiyun #define ndev_name(ndev) pci_name(ndev_pdev(ndev))
190*4882a593Smuzhiyun #define ndev_dev(ndev) (&ndev_pdev(ndev)->dev)
191*4882a593Smuzhiyun #define work_amd_i2c_common(__work) \
192*4882a593Smuzhiyun container_of(__work, struct amd_i2c_common, work.work)
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun /* PCIe communication driver */
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun int amd_mp2_rw(struct amd_i2c_common *i2c_common, enum i2c_cmd reqcmd);
197*4882a593Smuzhiyun int amd_mp2_bus_enable_set(struct amd_i2c_common *i2c_common, bool enable);
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun void amd_mp2_process_event(struct amd_i2c_common *i2c_common);
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun void amd_mp2_rw_timeout(struct amd_i2c_common *i2c_common);
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun int amd_mp2_register_cb(struct amd_i2c_common *i2c_common);
204*4882a593Smuzhiyun int amd_mp2_unregister_cb(struct amd_i2c_common *i2c_common);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun struct amd_mp2_dev *amd_mp2_find_device(void);
207*4882a593Smuzhiyun
amd_mp2_pm_runtime_get(struct amd_mp2_dev * mp2_dev)208*4882a593Smuzhiyun static inline void amd_mp2_pm_runtime_get(struct amd_mp2_dev *mp2_dev)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun pm_runtime_get_sync(&mp2_dev->pci_dev->dev);
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun
amd_mp2_pm_runtime_put(struct amd_mp2_dev * mp2_dev)213*4882a593Smuzhiyun static inline void amd_mp2_pm_runtime_put(struct amd_mp2_dev *mp2_dev)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun pm_runtime_mark_last_busy(&mp2_dev->pci_dev->dev);
216*4882a593Smuzhiyun pm_runtime_put_autosuspend(&mp2_dev->pci_dev->dev);
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun #endif
220