File: | dev/pci/drm/amd/amdgpu/smu_v11_0_i2c.c |
Warning: | line 662, column 24 Value stored to 'adev' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright 2019 Advanced Micro Devices, Inc. |
3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), |
6 | * to deal in the Software without restriction, including without limitation |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
8 | * and/or sell copies of the Software, and to permit persons to whom the |
9 | * Software is furnished to do so, subject to the following conditions: |
10 | * |
11 | * The above copyright notice and this permission notice shall be included in |
12 | * all copies or substantial portions of the Software. |
13 | * |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
20 | * OTHER DEALINGS IN THE SOFTWARE. |
21 | * |
22 | */ |
23 | |
24 | #include "smuio/smuio_11_0_0_offset.h" |
25 | #include "smuio/smuio_11_0_0_sh_mask.h" |
26 | |
27 | #include "smu_v11_0_i2c.h" |
28 | #include "amdgpu.h" |
29 | #include "soc15_common.h" |
30 | #include <drm/drm_fixed.h> |
31 | #include <drm/drm_drv.h> |
32 | #include "amdgpu_amdkfd.h" |
33 | #include <linux/i2c.h> |
34 | #include <linux/pci.h> |
35 | |
36 | /* error codes */ |
37 | #define I2C_OK0 0 |
38 | #define I2C_NAK_7B_ADDR_NOACK1 1 |
39 | #define I2C_NAK_TXDATA_NOACK2 2 |
40 | #define I2C_TIMEOUT4 4 |
41 | #define I2C_SW_TIMEOUT8 8 |
42 | #define I2C_ABORT0x10 0x10 |
43 | |
44 | /* I2C transaction flags */ |
45 | #define I2C_NO_STOP1 1 |
46 | #define I2C_RESTART2 2 |
47 | |
48 | #define to_amdgpu_device(x)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (x); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof (struct amdgpu_device, pm.smu_i2c) );})) (container_of(x, struct amdgpu_device, pm.smu_i2c)({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (x); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof (struct amdgpu_device, pm.smu_i2c) );})) |
49 | |
50 | static void smu_v11_0_i2c_set_clock_gating(struct i2c_adapter *control, bool_Bool en) |
51 | { |
52 | struct amdgpu_device *adev = to_amdgpu_device(control)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (control); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
53 | uint32_t reg = RREG32_SOC15(SMUIO, 0, mmSMUIO_PWRMGT)amdgpu_device_rreg(adev, (adev->reg_offset[SMUIO_HWIP][0][ 0] + 0x00c8), 0); |
54 | |
55 | reg = REG_SET_FIELD(reg, SMUIO_PWRMGT, i2c_clk_gate_en, en ? 1 : 0)(((reg) & ~0x00000001L) | (0x00000001L & ((en ? 1 : 0 ) << 0x0))); |
56 | WREG32_SOC15(SMUIO, 0, mmSMUIO_PWRMGT, reg)amdgpu_device_wreg(adev, ((adev->reg_offset[SMUIO_HWIP][0] [0] + 0x00c8)), (reg), 0); |
57 | } |
58 | |
59 | |
60 | static void smu_v11_0_i2c_enable(struct i2c_adapter *control, bool_Bool enable) |
61 | { |
62 | struct amdgpu_device *adev = to_amdgpu_device(control)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (control); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
63 | |
64 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE, enable ? 1 : 0)amdgpu_device_wreg(adev, ((adev->reg_offset[SMUIO_HWIP][0] [0] + 0x005b)), (enable ? 1 : 0), 0); |
65 | } |
66 | |
67 | static void smu_v11_0_i2c_clear_status(struct i2c_adapter *control) |
68 | { |
69 | struct amdgpu_device *adev = to_amdgpu_device(control)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (control); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
70 | /* do */ |
71 | { |
72 | RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_CLR_INTR)amdgpu_device_rreg(adev, (adev->reg_offset[SMUIO_HWIP][0][ 0] + 0x0050), 0); |
73 | |
74 | } /* while (reg_CKSVII2C_ic_clr_intr == 0) */ |
75 | } |
76 | |
77 | static void smu_v11_0_i2c_configure(struct i2c_adapter *control) |
78 | { |
79 | struct amdgpu_device *adev = to_amdgpu_device(control)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (control); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
80 | uint32_t reg = 0; |
81 | |
82 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_SLAVE_DISABLE, 1)(((reg) & ~0x00000040L) | (0x00000040L & ((1) << 0x6))); |
83 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_RESTART_EN, 1)(((reg) & ~0x00000020L) | (0x00000020L & ((1) << 0x5))); |
84 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_10BITADDR_MASTER, 0)(((reg) & ~0x00000010L) | (0x00000010L & ((0) << 0x4))); |
85 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_10BITADDR_SLAVE, 0)(((reg) & ~0x00000008L) | (0x00000008L & ((0) << 0x3))); |
86 | /* Standard mode */ |
87 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MAX_SPEED_MODE, 2)(((reg) & ~0x00000006L) | (0x00000006L & ((2) << 0x1))); |
88 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MASTER_MODE, 1)(((reg) & ~0x00000001L) | (0x00000001L & ((1) << 0x0))); |
89 | |
90 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_CON, reg)amdgpu_device_wreg(adev, ((adev->reg_offset[SMUIO_HWIP][0] [0] + 0x0040)), (reg), 0); |
91 | } |
92 | |
93 | static void smu_v11_0_i2c_set_clock(struct i2c_adapter *control) |
94 | { |
95 | struct amdgpu_device *adev = to_amdgpu_device(control)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (control); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
96 | |
97 | /* |
98 | * Standard mode speed, These values are taken from SMUIO MAS, |
99 | * but are different from what is given is |
100 | * Synopsys spec. The values here are based on assumption |
101 | * that refclock is 100MHz |
102 | * |
103 | * Configuration for standard mode; Speed = 100kbps |
104 | * Scale linearly, for now only support standard speed clock |
105 | * This will work only with 100M ref clock |
106 | * |
107 | * TBD:Change the calculation to take into account ref clock values also. |
108 | */ |
109 | |
110 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_FS_SPKLEN, 2)amdgpu_device_wreg(adev, ((adev->reg_offset[SMUIO_HWIP][0] [0] + 0x0068)), (2), 0); |
111 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_SS_SCL_HCNT, 120)amdgpu_device_wreg(adev, ((adev->reg_offset[SMUIO_HWIP][0] [0] + 0x0045)), (120), 0); |
112 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_SS_SCL_LCNT, 130)amdgpu_device_wreg(adev, ((adev->reg_offset[SMUIO_HWIP][0] [0] + 0x0046)), (130), 0); |
113 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_SDA_HOLD, 20)amdgpu_device_wreg(adev, ((adev->reg_offset[SMUIO_HWIP][0] [0] + 0x005f)), (20), 0); |
114 | } |
115 | |
116 | static void smu_v11_0_i2c_set_address(struct i2c_adapter *control, uint8_t address) |
117 | { |
118 | struct amdgpu_device *adev = to_amdgpu_device(control)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (control); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
119 | |
120 | /* Convert fromr 8-bit to 7-bit address */ |
121 | address >>= 1; |
122 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_TAR, (address & 0xFF))amdgpu_device_wreg(adev, ((adev->reg_offset[SMUIO_HWIP][0] [0] + 0x0041)), ((address & 0xFF)), 0); |
123 | } |
124 | |
125 | static uint32_t smu_v11_0_i2c_poll_tx_status(struct i2c_adapter *control) |
126 | { |
127 | struct amdgpu_device *adev = to_amdgpu_device(control)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (control); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
128 | uint32_t ret = I2C_OK0; |
129 | uint32_t reg, reg_c_tx_abrt_source; |
130 | |
131 | /*Check if transmission is completed */ |
132 | unsigned long timeout_counter = jiffies + msecs_to_jiffies(20)(((uint64_t)(20)) * hz / 1000); |
133 | |
134 | do { |
135 | if (time_after(jiffies, timeout_counter)((long)(timeout_counter) - (long)(jiffies) < 0)) { |
136 | ret |= I2C_SW_TIMEOUT8; |
137 | break; |
138 | } |
139 | |
140 | reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS)amdgpu_device_rreg(adev, (adev->reg_offset[SMUIO_HWIP][0][ 0] + 0x005c), 0); |
141 | |
142 | } while (REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFE)(((reg) & 0x00000004L) >> 0x2) == 0); |
143 | |
144 | if (ret != I2C_OK0) |
145 | return ret; |
146 | |
147 | /* This only checks if NAK is received and transaction got aborted */ |
148 | reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_INTR_STAT)amdgpu_device_rreg(adev, (adev->reg_offset[SMUIO_HWIP][0][ 0] + 0x004b), 0); |
149 | |
150 | if (REG_GET_FIELD(reg, CKSVII2C_IC_INTR_STAT, R_TX_ABRT)(((reg) & 0x00000040L) >> 0x6) == 1) { |
151 | reg_c_tx_abrt_source = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_TX_ABRT_SOURCE)amdgpu_device_rreg(adev, (adev->reg_offset[SMUIO_HWIP][0][ 0] + 0x0060), 0); |
152 | DRM_INFO("TX was terminated, IC_TX_ABRT_SOURCE val is:%x", reg_c_tx_abrt_source)printk("\0016" "[" "drm" "] " "TX was terminated, IC_TX_ABRT_SOURCE val is:%x" , reg_c_tx_abrt_source); |
153 | |
154 | /* Check for stop due to NACK */ |
155 | if (REG_GET_FIELD(reg_c_tx_abrt_source,(((reg_c_tx_abrt_source) & 0x00000008L) >> 0x3) |
156 | CKSVII2C_IC_TX_ABRT_SOURCE,(((reg_c_tx_abrt_source) & 0x00000008L) >> 0x3) |
157 | ABRT_TXDATA_NOACK)(((reg_c_tx_abrt_source) & 0x00000008L) >> 0x3) == 1) { |
158 | |
159 | ret |= I2C_NAK_TXDATA_NOACK2; |
160 | |
161 | } else if (REG_GET_FIELD(reg_c_tx_abrt_source,(((reg_c_tx_abrt_source) & 0x00000001L) >> 0x0) |
162 | CKSVII2C_IC_TX_ABRT_SOURCE,(((reg_c_tx_abrt_source) & 0x00000001L) >> 0x0) |
163 | ABRT_7B_ADDR_NOACK)(((reg_c_tx_abrt_source) & 0x00000001L) >> 0x0) == 1) { |
164 | |
165 | ret |= I2C_NAK_7B_ADDR_NOACK1; |
166 | } else { |
167 | ret |= I2C_ABORT0x10; |
168 | } |
169 | |
170 | smu_v11_0_i2c_clear_status(control); |
171 | } |
172 | |
173 | return ret; |
174 | } |
175 | |
176 | static uint32_t smu_v11_0_i2c_poll_rx_status(struct i2c_adapter *control) |
177 | { |
178 | struct amdgpu_device *adev = to_amdgpu_device(control)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (control); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
179 | uint32_t ret = I2C_OK0; |
180 | uint32_t reg_ic_status, reg_c_tx_abrt_source; |
181 | |
182 | reg_c_tx_abrt_source = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_TX_ABRT_SOURCE)amdgpu_device_rreg(adev, (adev->reg_offset[SMUIO_HWIP][0][ 0] + 0x0060), 0); |
183 | |
184 | /* If slave is not present */ |
185 | if (REG_GET_FIELD(reg_c_tx_abrt_source,(((reg_c_tx_abrt_source) & 0x00000001L) >> 0x0) |
186 | CKSVII2C_IC_TX_ABRT_SOURCE,(((reg_c_tx_abrt_source) & 0x00000001L) >> 0x0) |
187 | ABRT_7B_ADDR_NOACK)(((reg_c_tx_abrt_source) & 0x00000001L) >> 0x0) == 1) { |
188 | ret |= I2C_NAK_7B_ADDR_NOACK1; |
189 | |
190 | smu_v11_0_i2c_clear_status(control); |
191 | } else { /* wait till some data is there in RXFIFO */ |
192 | /* Poll for some byte in RXFIFO */ |
193 | unsigned long timeout_counter = jiffies + msecs_to_jiffies(20)(((uint64_t)(20)) * hz / 1000); |
194 | |
195 | do { |
196 | if (time_after(jiffies, timeout_counter)((long)(timeout_counter) - (long)(jiffies) < 0)) { |
197 | ret |= I2C_SW_TIMEOUT8; |
198 | break; |
199 | } |
200 | |
201 | reg_ic_status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS)amdgpu_device_rreg(adev, (adev->reg_offset[SMUIO_HWIP][0][ 0] + 0x005c), 0); |
202 | |
203 | } while (REG_GET_FIELD(reg_ic_status, CKSVII2C_IC_STATUS, RFNE)(((reg_ic_status) & 0x00000008L) >> 0x3) == 0); |
204 | } |
205 | |
206 | return ret; |
207 | } |
208 | |
209 | |
210 | |
211 | |
212 | /** |
213 | * smu_v11_0_i2c_transmit - Send a block of data over the I2C bus to a slave device. |
214 | * |
215 | * @address: The I2C address of the slave device. |
216 | * @data: The data to transmit over the bus. |
217 | * @numbytes: The amount of data to transmit. |
218 | * @i2c_flag: Flags for transmission |
219 | * |
220 | * Returns 0 on success or error. |
221 | */ |
222 | static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter *control, |
223 | uint8_t address, uint8_t *data, |
224 | uint32_t numbytes, uint32_t i2c_flag) |
225 | { |
226 | struct amdgpu_device *adev = to_amdgpu_device(control)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (control); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
227 | uint32_t bytes_sent, reg, ret = 0; |
228 | unsigned long timeout_counter; |
229 | |
230 | bytes_sent = 0; |
231 | |
232 | DRM_DEBUG_DRIVER("I2C_Transmit(), address = %x, bytes = %d , data: ",__drm_dbg(DRM_UT_DRIVER, "I2C_Transmit(), address = %x, bytes = %d , data: " , (uint16_t)address, numbytes) |
233 | (uint16_t)address, numbytes)__drm_dbg(DRM_UT_DRIVER, "I2C_Transmit(), address = %x, bytes = %d , data: " , (uint16_t)address, numbytes); |
234 | |
235 | if (drm_debug_enabled(DRM_UT_DRIVER)) { |
236 | print_hex_dump(KERN_INFO"\0016", "data: ", DUMP_PREFIX_NONE, |
237 | 16, 1, data, numbytes, false0); |
238 | } |
239 | |
240 | /* Set the I2C slave address */ |
241 | smu_v11_0_i2c_set_address(control, address); |
242 | /* Enable I2C */ |
243 | smu_v11_0_i2c_enable(control, true1); |
244 | |
245 | /* Clear status bits */ |
246 | smu_v11_0_i2c_clear_status(control); |
247 | |
248 | |
249 | timeout_counter = jiffies + msecs_to_jiffies(20)(((uint64_t)(20)) * hz / 1000); |
250 | |
251 | while (numbytes > 0) { |
252 | reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS)amdgpu_device_rreg(adev, (adev->reg_offset[SMUIO_HWIP][0][ 0] + 0x005c), 0); |
253 | if (REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)(((reg) & 0x00000002L) >> 0x1)) { |
254 | do { |
255 | reg = 0; |
256 | /* |
257 | * Prepare transaction, no need to set RESTART. I2C engine will send |
258 | * START as soon as it sees data in TXFIFO |
259 | */ |
260 | if (bytes_sent == 0) |
261 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, RESTART,(((reg) & ~0x00000400L) | (0x00000400L & (((i2c_flag & 2) ? 1 : 0) << 0xa))) |
262 | (i2c_flag & I2C_RESTART) ? 1 : 0)(((reg) & ~0x00000400L) | (0x00000400L & (((i2c_flag & 2) ? 1 : 0) << 0xa))); |
263 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, data[bytes_sent])(((reg) & ~0x000000FFL) | (0x000000FFL & ((data[bytes_sent ]) << 0x0))); |
264 | |
265 | /* determine if we need to send STOP bit or not */ |
266 | if (numbytes == 1) |
267 | /* Final transaction, so send stop unless I2C_NO_STOP */ |
268 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, STOP,(((reg) & ~0x00000200L) | (0x00000200L & (((i2c_flag & 1) ? 0 : 1) << 0x9))) |
269 | (i2c_flag & I2C_NO_STOP) ? 0 : 1)(((reg) & ~0x00000200L) | (0x00000200L & (((i2c_flag & 1) ? 0 : 1) << 0x9))); |
270 | /* Write */ |
271 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 0)(((reg) & ~0x00000100L) | (0x00000100L & ((0) << 0x8))); |
272 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg)amdgpu_device_wreg(adev, ((adev->reg_offset[SMUIO_HWIP][0] [0] + 0x0044)), (reg), 0); |
273 | |
274 | /* Record that the bytes were transmitted */ |
275 | bytes_sent++; |
276 | numbytes--; |
277 | |
278 | reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS)amdgpu_device_rreg(adev, (adev->reg_offset[SMUIO_HWIP][0][ 0] + 0x005c), 0); |
279 | |
280 | } while (numbytes && REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)(((reg) & 0x00000002L) >> 0x1)); |
281 | } |
282 | |
283 | /* |
284 | * We waited too long for the transmission FIFO to become not-full. |
285 | * Exit the loop with error. |
286 | */ |
287 | if (time_after(jiffies, timeout_counter)((long)(timeout_counter) - (long)(jiffies) < 0)) { |
288 | ret |= I2C_SW_TIMEOUT8; |
289 | goto Err; |
290 | } |
291 | } |
292 | |
293 | ret = smu_v11_0_i2c_poll_tx_status(control); |
294 | |
295 | Err: |
296 | /* Any error, no point in proceeding */ |
297 | if (ret != I2C_OK0) { |
298 | if (ret & I2C_SW_TIMEOUT8) |
299 | DRM_ERROR("TIMEOUT ERROR !!!")__drm_err("TIMEOUT ERROR !!!"); |
300 | |
301 | if (ret & I2C_NAK_7B_ADDR_NOACK1) |
302 | DRM_ERROR("Received I2C_NAK_7B_ADDR_NOACK !!!")__drm_err("Received I2C_NAK_7B_ADDR_NOACK !!!"); |
303 | |
304 | |
305 | if (ret & I2C_NAK_TXDATA_NOACK2) |
306 | DRM_ERROR("Received I2C_NAK_TXDATA_NOACK !!!")__drm_err("Received I2C_NAK_TXDATA_NOACK !!!"); |
307 | } |
308 | |
309 | return ret; |
310 | } |
311 | |
312 | |
313 | /** |
314 | * smu_v11_0_i2c_receive - Receive a block of data over the I2C bus from a slave device. |
315 | * |
316 | * @address: The I2C address of the slave device. |
317 | * @numbytes: The amount of data to transmit. |
318 | * @i2c_flag: Flags for transmission |
319 | * |
320 | * Returns 0 on success or error. |
321 | */ |
322 | static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter *control, |
323 | uint8_t address, uint8_t *data, |
324 | uint32_t numbytes, uint8_t i2c_flag) |
325 | { |
326 | struct amdgpu_device *adev = to_amdgpu_device(control)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (control); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
327 | uint32_t bytes_received, ret = I2C_OK0; |
328 | |
329 | bytes_received = 0; |
330 | |
331 | /* Set the I2C slave address */ |
332 | smu_v11_0_i2c_set_address(control, address); |
333 | |
334 | /* Enable I2C */ |
335 | smu_v11_0_i2c_enable(control, true1); |
336 | |
337 | while (numbytes > 0) { |
338 | uint32_t reg = 0; |
339 | |
340 | smu_v11_0_i2c_clear_status(control); |
341 | |
342 | |
343 | /* Prepare transaction */ |
344 | |
345 | /* Each time we disable I2C, so this is not a restart */ |
346 | if (bytes_received == 0) |
347 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, RESTART,(((reg) & ~0x00000400L) | (0x00000400L & (((i2c_flag & 2) ? 1 : 0) << 0xa))) |
348 | (i2c_flag & I2C_RESTART) ? 1 : 0)(((reg) & ~0x00000400L) | (0x00000400L & (((i2c_flag & 2) ? 1 : 0) << 0xa))); |
349 | |
350 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, 0)(((reg) & ~0x000000FFL) | (0x000000FFL & ((0) << 0x0))); |
351 | /* Read */ |
352 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 1)(((reg) & ~0x00000100L) | (0x00000100L & ((1) << 0x8))); |
353 | |
354 | /* Transmitting last byte */ |
355 | if (numbytes == 1) |
356 | /* Final transaction, so send stop if requested */ |
357 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, STOP,(((reg) & ~0x00000200L) | (0x00000200L & (((i2c_flag & 1) ? 0 : 1) << 0x9))) |
358 | (i2c_flag & I2C_NO_STOP) ? 0 : 1)(((reg) & ~0x00000200L) | (0x00000200L & (((i2c_flag & 1) ? 0 : 1) << 0x9))); |
359 | |
360 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg)amdgpu_device_wreg(adev, ((adev->reg_offset[SMUIO_HWIP][0] [0] + 0x0044)), (reg), 0); |
361 | |
362 | ret = smu_v11_0_i2c_poll_rx_status(control); |
363 | |
364 | /* Any error, no point in proceeding */ |
365 | if (ret != I2C_OK0) { |
366 | if (ret & I2C_SW_TIMEOUT8) |
367 | DRM_ERROR("TIMEOUT ERROR !!!")__drm_err("TIMEOUT ERROR !!!"); |
368 | |
369 | if (ret & I2C_NAK_7B_ADDR_NOACK1) |
370 | DRM_ERROR("Received I2C_NAK_7B_ADDR_NOACK !!!")__drm_err("Received I2C_NAK_7B_ADDR_NOACK !!!"); |
371 | |
372 | if (ret & I2C_NAK_TXDATA_NOACK2) |
373 | DRM_ERROR("Received I2C_NAK_TXDATA_NOACK !!!")__drm_err("Received I2C_NAK_TXDATA_NOACK !!!"); |
374 | |
375 | break; |
376 | } |
377 | |
378 | reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD)amdgpu_device_rreg(adev, (adev->reg_offset[SMUIO_HWIP][0][ 0] + 0x0044), 0); |
379 | data[bytes_received] = REG_GET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT)(((reg) & 0x000000FFL) >> 0x0); |
380 | |
381 | /* Record that the bytes were received */ |
382 | bytes_received++; |
383 | numbytes--; |
384 | } |
385 | |
386 | DRM_DEBUG_DRIVER("I2C_Receive(), address = %x, bytes = %d, data :",__drm_dbg(DRM_UT_DRIVER, "I2C_Receive(), address = %x, bytes = %d, data :" , (uint16_t)address, bytes_received) |
387 | (uint16_t)address, bytes_received)__drm_dbg(DRM_UT_DRIVER, "I2C_Receive(), address = %x, bytes = %d, data :" , (uint16_t)address, bytes_received); |
388 | |
389 | if (drm_debug_enabled(DRM_UT_DRIVER)) { |
390 | print_hex_dump(KERN_INFO"\0016", "data: ", DUMP_PREFIX_NONE, |
391 | 16, 1, data, bytes_received, false0); |
392 | } |
393 | |
394 | return ret; |
395 | } |
396 | |
397 | static void smu_v11_0_i2c_abort(struct i2c_adapter *control) |
398 | { |
399 | struct amdgpu_device *adev = to_amdgpu_device(control)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (control); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
400 | uint32_t reg = 0; |
401 | |
402 | /* Enable I2C engine; */ |
403 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_ENABLE, ENABLE, 1)(((reg) & ~0x00000001L) | (0x00000001L & ((1) << 0x0))); |
404 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE, reg)amdgpu_device_wreg(adev, ((adev->reg_offset[SMUIO_HWIP][0] [0] + 0x005b)), (reg), 0); |
405 | |
406 | /* Abort previous transaction */ |
407 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_ENABLE, ABORT, 1)(((reg) & ~0x00000002L) | (0x00000002L & ((1) << 0x1))); |
408 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE, reg)amdgpu_device_wreg(adev, ((adev->reg_offset[SMUIO_HWIP][0] [0] + 0x005b)), (reg), 0); |
409 | |
410 | DRM_DEBUG_DRIVER("I2C_Abort() Done.")__drm_dbg(DRM_UT_DRIVER, "I2C_Abort() Done."); |
411 | } |
412 | |
413 | |
414 | static bool_Bool smu_v11_0_i2c_activity_done(struct i2c_adapter *control) |
415 | { |
416 | struct amdgpu_device *adev = to_amdgpu_device(control)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (control); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
417 | |
418 | const uint32_t IDLE_TIMEOUT = 1024; |
419 | uint32_t timeout_count = 0; |
420 | uint32_t reg_ic_enable, reg_ic_enable_status, reg_ic_clr_activity; |
421 | |
422 | reg_ic_enable_status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE_STATUS)amdgpu_device_rreg(adev, (adev->reg_offset[SMUIO_HWIP][0][ 0] + 0x0067), 0); |
423 | reg_ic_enable = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE)amdgpu_device_rreg(adev, (adev->reg_offset[SMUIO_HWIP][0][ 0] + 0x005b), 0); |
424 | |
425 | |
426 | if ((REG_GET_FIELD(reg_ic_enable, CKSVII2C_IC_ENABLE, ENABLE)(((reg_ic_enable) & 0x00000001L) >> 0x0) == 0) && |
427 | (REG_GET_FIELD(reg_ic_enable_status, CKSVII2C_IC_ENABLE_STATUS, IC_EN)(((reg_ic_enable_status) & 0x00000001L) >> 0x0) == 1)) { |
428 | /* |
429 | * Nobody is using I2C engine, but engine remains active because |
430 | * someone missed to send STOP |
431 | */ |
432 | smu_v11_0_i2c_abort(control); |
433 | } else if (REG_GET_FIELD(reg_ic_enable, CKSVII2C_IC_ENABLE, ENABLE)(((reg_ic_enable) & 0x00000001L) >> 0x0) == 0) { |
434 | /* Nobody is using I2C engine */ |
435 | return true1; |
436 | } |
437 | |
438 | /* Keep reading activity bit until it's cleared */ |
439 | do { |
440 | reg_ic_clr_activity = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_CLR_ACTIVITY)amdgpu_device_rreg(adev, (adev->reg_offset[SMUIO_HWIP][0][ 0] + 0x0057), 0); |
441 | |
442 | if (REG_GET_FIELD(reg_ic_clr_activity,(((reg_ic_clr_activity) & 0x00000001L) >> 0x0) |
443 | CKSVII2C_IC_CLR_ACTIVITY, CLR_ACTIVITY)(((reg_ic_clr_activity) & 0x00000001L) >> 0x0) == 0) |
444 | return true1; |
445 | |
446 | ++timeout_count; |
447 | |
448 | } while (timeout_count < IDLE_TIMEOUT); |
449 | |
450 | return false0; |
451 | } |
452 | |
453 | static void smu_v11_0_i2c_init(struct i2c_adapter *control) |
454 | { |
455 | /* Disable clock gating */ |
456 | smu_v11_0_i2c_set_clock_gating(control, false0); |
457 | |
458 | if (!smu_v11_0_i2c_activity_done(control)) |
459 | DRM_WARN("I2C busy !")printk("\0014" "[" "drm" "] " "I2C busy !"); |
460 | |
461 | /* Disable I2C */ |
462 | smu_v11_0_i2c_enable(control, false0); |
463 | |
464 | /* Configure I2C to operate as master and in standard mode */ |
465 | smu_v11_0_i2c_configure(control); |
466 | |
467 | /* Initialize the clock to 50 kHz default */ |
468 | smu_v11_0_i2c_set_clock(control); |
469 | |
470 | } |
471 | |
472 | static void smu_v11_0_i2c_fini(struct i2c_adapter *control) |
473 | { |
474 | struct amdgpu_device *adev = to_amdgpu_device(control)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (control); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
475 | uint32_t reg_ic_enable_status, reg_ic_enable; |
476 | |
477 | smu_v11_0_i2c_enable(control, false0); |
478 | |
479 | /* Double check if disabled, else force abort */ |
480 | reg_ic_enable_status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE_STATUS)amdgpu_device_rreg(adev, (adev->reg_offset[SMUIO_HWIP][0][ 0] + 0x0067), 0); |
481 | reg_ic_enable = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE)amdgpu_device_rreg(adev, (adev->reg_offset[SMUIO_HWIP][0][ 0] + 0x005b), 0); |
482 | |
483 | if ((REG_GET_FIELD(reg_ic_enable, CKSVII2C_IC_ENABLE, ENABLE)(((reg_ic_enable) & 0x00000001L) >> 0x0) == 0) && |
484 | (REG_GET_FIELD(reg_ic_enable_status,(((reg_ic_enable_status) & 0x00000001L) >> 0x0) |
485 | CKSVII2C_IC_ENABLE_STATUS, IC_EN)(((reg_ic_enable_status) & 0x00000001L) >> 0x0) == 1)) { |
486 | /* |
487 | * Nobody is using I2C engine, but engine remains active because |
488 | * someone missed to send STOP |
489 | */ |
490 | smu_v11_0_i2c_abort(control); |
491 | } |
492 | |
493 | /* Restore clock gating */ |
494 | |
495 | /* |
496 | * TODO Reenabling clock gating seems to break subsequent SMU operation |
497 | * on the I2C bus. My guess is that SMU doesn't disable clock gating like |
498 | * we do here before working with the bus. So for now just don't restore |
499 | * it but later work with SMU to see if they have this issue and can |
500 | * update their code appropriately |
501 | */ |
502 | /* smu_v11_0_i2c_set_clock_gating(control, true); */ |
503 | |
504 | } |
505 | |
506 | static bool_Bool smu_v11_0_i2c_bus_lock(struct i2c_adapter *control) |
507 | { |
508 | struct amdgpu_device *adev = to_amdgpu_device(control)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (control); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
509 | |
510 | /* Send PPSMC_MSG_RequestI2CBus */ |
511 | if (!amdgpu_dpm_smu_i2c_bus_access(adev, true1)) |
512 | return true1; |
513 | |
514 | return false0; |
515 | } |
516 | |
517 | static bool_Bool smu_v11_0_i2c_bus_unlock(struct i2c_adapter *control) |
518 | { |
519 | struct amdgpu_device *adev = to_amdgpu_device(control)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (control); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
520 | |
521 | /* Send PPSMC_MSG_ReleaseI2CBus */ |
522 | if (!amdgpu_dpm_smu_i2c_bus_access(adev, false0)) |
523 | return true1; |
524 | |
525 | return false0; |
526 | } |
527 | |
528 | /***************************** I2C GLUE ****************************/ |
529 | |
530 | static uint32_t smu_v11_0_i2c_read_data(struct i2c_adapter *control, |
531 | uint8_t address, |
532 | uint8_t *data, |
533 | uint32_t numbytes) |
534 | { |
535 | uint32_t ret = 0; |
536 | |
537 | /* First 2 bytes are dummy write to set EEPROM address */ |
538 | ret = smu_v11_0_i2c_transmit(control, address, data, 2, I2C_NO_STOP1); |
539 | if (ret != I2C_OK0) |
540 | goto Fail; |
541 | |
542 | /* Now read data starting with that address */ |
543 | ret = smu_v11_0_i2c_receive(control, address, data + 2, numbytes - 2, |
544 | I2C_RESTART2); |
545 | |
546 | Fail: |
547 | if (ret != I2C_OK0) |
548 | DRM_ERROR("ReadData() - I2C error occurred :%x", ret)__drm_err("ReadData() - I2C error occurred :%x", ret); |
549 | |
550 | return ret; |
551 | } |
552 | |
553 | static uint32_t smu_v11_0_i2c_write_data(struct i2c_adapter *control, |
554 | uint8_t address, |
555 | uint8_t *data, |
556 | uint32_t numbytes) |
557 | { |
558 | uint32_t ret; |
559 | |
560 | ret = smu_v11_0_i2c_transmit(control, address, data, numbytes, 0); |
561 | |
562 | if (ret != I2C_OK0) |
563 | DRM_ERROR("WriteI2CData() - I2C error occurred :%x", ret)__drm_err("WriteI2CData() - I2C error occurred :%x", ret); |
564 | else |
565 | /* |
566 | * According to EEPROM spec there is a MAX of 10 ms required for |
567 | * EEPROM to flush internal RX buffer after STOP was issued at the |
568 | * end of write transaction. During this time the EEPROM will not be |
569 | * responsive to any more commands - so wait a bit more. |
570 | * |
571 | * TODO Improve to wait for first ACK for slave address after |
572 | * internal write cycle done. |
573 | */ |
574 | drm_msleep(10)mdelay(10); |
575 | |
576 | return ret; |
577 | |
578 | } |
579 | |
580 | static void lock_bus(struct i2c_adapter *i2c, unsigned int flags) |
581 | { |
582 | struct amdgpu_device *adev = to_amdgpu_device(i2c)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (i2c); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
583 | |
584 | if (!smu_v11_0_i2c_bus_lock(i2c)) { |
585 | DRM_ERROR("Failed to lock the bus from SMU")__drm_err("Failed to lock the bus from SMU"); |
586 | return; |
587 | } |
588 | |
589 | adev->pm.bus_locked = true1; |
590 | } |
591 | |
592 | static int trylock_bus(struct i2c_adapter *i2c, unsigned int flags) |
593 | { |
594 | WARN_ONCE(1, "This operation not supposed to run in atomic context!")({ static int __warned; int __ret = !!(1); if (__ret && !__warned) { printf("This operation not supposed to run in atomic context!" ); __warned = 1; } __builtin_expect(!!(__ret), 0); }); |
595 | return false0; |
596 | } |
597 | |
598 | static void unlock_bus(struct i2c_adapter *i2c, unsigned int flags) |
599 | { |
600 | struct amdgpu_device *adev = to_amdgpu_device(i2c)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (i2c); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
601 | |
602 | if (!smu_v11_0_i2c_bus_unlock(i2c)) { |
603 | DRM_ERROR("Failed to unlock the bus from SMU")__drm_err("Failed to unlock the bus from SMU"); |
604 | return; |
605 | } |
606 | |
607 | adev->pm.bus_locked = false0; |
608 | } |
609 | |
610 | static const struct i2c_lock_operations smu_v11_0_i2c_i2c_lock_ops = { |
611 | .lock_bus = lock_bus, |
612 | .trylock_bus = trylock_bus, |
613 | .unlock_bus = unlock_bus, |
614 | }; |
615 | |
616 | static int smu_v11_0_i2c_xfer(struct i2c_adapter *i2c_adap, |
617 | struct i2c_msg *msgs, int num) |
618 | { |
619 | int i, ret; |
620 | struct amdgpu_device *adev = to_amdgpu_device(i2c_adap)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (i2c_adap); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
621 | |
622 | if (!adev->pm.bus_locked) { |
623 | DRM_ERROR("I2C bus unlocked, stopping transaction!")__drm_err("I2C bus unlocked, stopping transaction!"); |
624 | return -EIO5; |
625 | } |
626 | |
627 | smu_v11_0_i2c_init(i2c_adap); |
628 | |
629 | for (i = 0; i < num; i++) { |
630 | if (msgs[i].flags & I2C_M_RD0x0001) |
631 | ret = smu_v11_0_i2c_read_data(i2c_adap, |
632 | (uint8_t)msgs[i].addr, |
633 | msgs[i].buf, msgs[i].len); |
634 | else |
635 | ret = smu_v11_0_i2c_write_data(i2c_adap, |
636 | (uint8_t)msgs[i].addr, |
637 | msgs[i].buf, msgs[i].len); |
638 | |
639 | if (ret != I2C_OK0) { |
640 | num = -EIO5; |
641 | break; |
642 | } |
643 | } |
644 | |
645 | smu_v11_0_i2c_fini(i2c_adap); |
646 | return num; |
647 | } |
648 | |
649 | static u32 smu_v11_0_i2c_func(struct i2c_adapter *adap) |
650 | { |
651 | return I2C_FUNC_I2C0 | I2C_FUNC_SMBUS_EMUL0; |
652 | } |
653 | |
654 | |
655 | static const struct i2c_algorithm smu_v11_0_i2c_algo = { |
656 | .master_xfer = smu_v11_0_i2c_xfer, |
657 | .functionality = smu_v11_0_i2c_func, |
658 | }; |
659 | |
660 | int smu_v11_0_i2c_control_init(struct i2c_adapter *control) |
661 | { |
662 | struct amdgpu_device *adev = to_amdgpu_device(control)(({ const __typeof( ((struct amdgpu_device *)0)->pm.smu_i2c ) *__mptr = (control); (struct amdgpu_device *)( (char *)__mptr - __builtin_offsetof(struct amdgpu_device, pm.smu_i2c) );})); |
Value stored to 'adev' during its initialization is never read | |
663 | int res; |
664 | |
665 | #ifdef __linux__ |
666 | control->owner = THIS_MODULE((void *)0); |
667 | control->class = I2C_CLASS_SPD; |
668 | control->dev.parent = &adev->pdev->dev; |
669 | #endif |
670 | control->algo = &smu_v11_0_i2c_algo; |
671 | snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); |
672 | control->lock_ops = &smu_v11_0_i2c_i2c_lock_ops; |
673 | |
674 | res = i2c_add_adapter(control)0; |
675 | if (res) |
676 | DRM_ERROR("Failed to register hw i2c, err: %d\n", res)__drm_err("Failed to register hw i2c, err: %d\n", res); |
677 | |
678 | return res; |
679 | } |
680 | |
681 | void smu_v11_0_i2c_control_fini(struct i2c_adapter *control) |
682 | { |
683 | i2c_del_adapter(control); |
684 | } |
685 | |
686 | /* |
687 | * Keep this for future unit test if bugs arise |
688 | */ |
689 | #if 0 |
690 | #define I2C_TARGET_ADDR 0xA0 |
691 | |
692 | bool_Bool smu_v11_0_i2c_test_bus(struct i2c_adapter *control) |
693 | { |
694 | |
695 | uint32_t ret = I2C_OK0; |
696 | uint8_t data[6] = {0xf, 0, 0xde, 0xad, 0xbe, 0xef}; |
697 | |
698 | |
699 | DRM_INFO("Begin")printk("\0016" "[" "drm" "] " "Begin"); |
700 | |
701 | if (!smu_v11_0_i2c_bus_lock(control)) { |
702 | DRM_ERROR("Failed to lock the bus!.")__drm_err("Failed to lock the bus!."); |
703 | return false0; |
704 | } |
705 | |
706 | smu_v11_0_i2c_init(control); |
707 | |
708 | /* Write 0xde to address 0x0000 on the EEPROM */ |
709 | ret = smu_v11_0_i2c_write_data(control, I2C_TARGET_ADDR, data, 6); |
710 | |
711 | ret = smu_v11_0_i2c_read_data(control, I2C_TARGET_ADDR, data, 6); |
712 | |
713 | smu_v11_0_i2c_fini(control); |
714 | |
715 | smu_v11_0_i2c_bus_unlock(control); |
716 | |
717 | |
718 | DRM_INFO("End")printk("\0016" "[" "drm" "] " "End"); |
719 | return true1; |
720 | } |
721 | #endif |