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