aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Grodzovsky <andrey.grodzovsky@amd.com>2019-05-01 10:57:14 -0400
committerAlex Deucher <alexander.deucher@amd.com>2019-08-27 10:17:35 -0400
commit691bac9d093b13abf39f95bd82db0430a152246c (patch)
treecffdc737b07aefda49bf2432c055414df78bba8c
parent6acaa6af1501d17d40bb9aa5d76d5bb0b4936ed9 (diff)
drm/amdgpu: Vega20 SMU I2C HW engine controller.
Implement HW I2C enigne controller to be used by the RAS EEPROM table manager. This is based on code from ATITOOLs. v2: Rename the file and all function prefixes to smu_v11_0_i2c By Luben's observation always fill the TX fifo to full so we don't have garbadge interpreted by the slave as valid data. v3: Remove preemption disable as the HW I2C controller will not stop the clock on empty TX fifo and so it's not critical to keep not empty queue. Switch to fast mode 400 khz SCL clock for faster read and write. v5: Restore clock gating before releasing I2C bus and fix some style comments. v6: squash in warning fix, fix includes (Alex) Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Reviewed-by: Luben Tuikov <Luben.Tuikov@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/amdgpu/Makefile2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c724
-rw-r--r--drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h34
4 files changed, 762 insertions, 3 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index f016cf118b1b..42e2c1f57152 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -54,7 +54,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
54 amdgpu_gtt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o amdgpu_atomfirmware.o \ 54 amdgpu_gtt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o amdgpu_atomfirmware.o \
55 amdgpu_vf_error.o amdgpu_sched.o amdgpu_debugfs.o amdgpu_ids.o \ 55 amdgpu_vf_error.o amdgpu_sched.o amdgpu_debugfs.o amdgpu_ids.o \
56 amdgpu_gmc.o amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \ 56 amdgpu_gmc.o amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \
57 amdgpu_vm_sdma.o amdgpu_pmu.o amdgpu_discovery.o amdgpu_ras_eeprom.o 57 amdgpu_vm_sdma.o amdgpu_pmu.o amdgpu_discovery.o amdgpu_ras_eeprom.o smu_v11_0_i2c.o
58 58
59amdgpu-$(CONFIG_PERF_EVENTS) += amdgpu_pmu.o 59amdgpu-$(CONFIG_PERF_EVENTS) += amdgpu_pmu.o
60 60
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index b544e0a05925..86110e6095cc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -25,6 +25,7 @@
25#include "amdgpu.h" 25#include "amdgpu.h"
26#include "amdgpu_ras.h" 26#include "amdgpu_ras.h"
27#include <linux/bits.h> 27#include <linux/bits.h>
28#include "smu_v11_0_i2c.h"
28 29
29#define EEPROM_I2C_TARGET_ADDR 0xA0 30#define EEPROM_I2C_TARGET_ADDR 0xA0
30 31
@@ -118,7 +119,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
118 119
119 switch (adev->asic_type) { 120 switch (adev->asic_type) {
120 case CHIP_VEGA20: 121 case CHIP_VEGA20:
121 /*TODO Add MI-60 */ 122 ret = smu_v11_0_i2c_eeprom_control_init(&control->eeprom_accessor);
122 break; 123 break;
123 124
124 default: 125 default:
@@ -170,7 +171,7 @@ void amdgpu_ras_eeprom_fini(struct amdgpu_ras_eeprom_control *control)
170 171
171 switch (adev->asic_type) { 172 switch (adev->asic_type) {
172 case CHIP_VEGA20: 173 case CHIP_VEGA20:
173 /*TODO Add MI-60 */ 174 smu_v11_0_i2c_eeprom_control_fini(&control->eeprom_accessor);
174 break; 175 break;
175 176
176 default: 177 default:
diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
new file mode 100644
index 000000000000..4a5951036927
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
@@ -0,0 +1,724 @@
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#include "amdgpu_ras.h"
36
37/* error codes */
38#define I2C_OK 0
39#define I2C_NAK_7B_ADDR_NOACK 1
40#define I2C_NAK_TXDATA_NOACK 2
41#define I2C_TIMEOUT 4
42#define I2C_SW_TIMEOUT 8
43#define I2C_ABORT 0x10
44
45/* I2C transaction flags */
46#define I2C_NO_STOP 1
47#define I2C_RESTART 2
48
49#define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, eeprom_control.eeprom_accessor))->adev
50#define to_eeprom_control(x) container_of(x, struct amdgpu_ras_eeprom_control, eeprom_accessor)
51
52static void smu_v11_0_i2c_set_clock_gating(struct i2c_adapter *control, bool en)
53{
54 struct amdgpu_device *adev = to_amdgpu_device(control);
55 uint32_t reg = RREG32_SOC15(SMUIO, 0, mmSMUIO_PWRMGT);
56
57 reg = REG_SET_FIELD(reg, SMUIO_PWRMGT, i2c_clk_gate_en, en ? 1 : 0);
58 WREG32_SOC15(SMUIO, 0, mmSMUIO_PWRMGT, reg);
59}
60
61
62static void smu_v11_0_i2c_enable(struct i2c_adapter *control, bool enable)
63{
64 struct amdgpu_device *adev = to_amdgpu_device(control);
65
66 WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE, enable ? 1 : 0);
67}
68
69static void smu_v11_0_i2c_clear_status(struct i2c_adapter *control)
70{
71 struct amdgpu_device *adev = to_amdgpu_device(control);
72 /* do */
73 {
74 RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_CLR_INTR);
75
76 } /* while (reg_CKSVII2C_ic_clr_intr == 0) */
77}
78
79static void smu_v11_0_i2c_configure(struct i2c_adapter *control)
80{
81 struct amdgpu_device *adev = to_amdgpu_device(control);
82 uint32_t reg = 0;
83
84 reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_SLAVE_DISABLE, 1);
85 reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_RESTART_EN, 1);
86 reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_10BITADDR_MASTER, 0);
87 reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_10BITADDR_SLAVE, 0);
88 /* Standard mode */
89 reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MAX_SPEED_MODE, 2);
90 reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MASTER_MODE, 1);
91
92 WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_CON, reg);
93}
94
95static void smu_v11_0_i2c_set_clock(struct i2c_adapter *control)
96{
97 struct amdgpu_device *adev = to_amdgpu_device(control);
98
99 /*
100 * Standard mode speed, These values are taken from SMUIO MAS,
101 * but are different from what is given is
102 * Synopsys spec. The values here are based on assumption
103 * that refclock is 100MHz
104 *
105 * Configuration for standard mode; Speed = 100kbps
106 * Scale linearly, for now only support standard speed clock
107 * This will work only with 100M ref clock
108 *
109 * TBD:Change the calculation to take into account ref clock values also.
110 */
111
112 WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_FS_SPKLEN, 2);
113 WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_SS_SCL_HCNT, 120);
114 WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_SS_SCL_LCNT, 130);
115 WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_SDA_HOLD, 20);
116}
117
118static void smu_v11_0_i2c_set_address(struct i2c_adapter *control, uint8_t address)
119{
120 struct amdgpu_device *adev = to_amdgpu_device(control);
121
122 /* Convert fromr 8-bit to 7-bit address */
123 address >>= 1;
124 WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_TAR, (address & 0xFF));
125}
126
127static uint32_t smu_v11_0_i2c_poll_tx_status(struct i2c_adapter *control)
128{
129 struct amdgpu_device *adev = to_amdgpu_device(control);
130 uint32_t ret = I2C_OK;
131 uint32_t reg, reg_c_tx_abrt_source;
132
133 /*Check if transmission is completed */
134 unsigned long timeout_counter = jiffies + msecs_to_jiffies(20);
135
136 do {
137 if (time_after(jiffies, timeout_counter)) {
138 ret |= I2C_SW_TIMEOUT;
139 break;
140 }
141
142 reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS);
143
144 } while (REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFE) == 0);
145
146 if (ret != I2C_OK)
147 return ret;
148
149 /* This only checks if NAK is received and transaction got aborted */
150 reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_INTR_STAT);
151
152 if (REG_GET_FIELD(reg, CKSVII2C_IC_INTR_STAT, R_TX_ABRT) == 1) {
153 reg_c_tx_abrt_source = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_TX_ABRT_SOURCE);
154 DRM_INFO("TX was terminated, IC_TX_ABRT_SOURCE val is:%x", reg_c_tx_abrt_source);
155
156 /* Check for stop due to NACK */
157 if (REG_GET_FIELD(reg_c_tx_abrt_source,
158 CKSVII2C_IC_TX_ABRT_SOURCE,
159 ABRT_TXDATA_NOACK) == 1) {
160
161 ret |= I2C_NAK_TXDATA_NOACK;
162
163 } else if (REG_GET_FIELD(reg_c_tx_abrt_source,
164 CKSVII2C_IC_TX_ABRT_SOURCE,
165 ABRT_7B_ADDR_NOACK) == 1) {
166
167 ret |= I2C_NAK_7B_ADDR_NOACK;
168 } else {
169 ret |= I2C_ABORT;
170 }
171
172 smu_v11_0_i2c_clear_status(control);
173 }
174
175 return ret;
176}
177
178static uint32_t smu_v11_0_i2c_poll_rx_status(struct i2c_adapter *control)
179{
180 struct amdgpu_device *adev = to_amdgpu_device(control);
181 uint32_t ret = I2C_OK;
182 uint32_t reg_ic_status, reg_c_tx_abrt_source;
183
184 reg_c_tx_abrt_source = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_TX_ABRT_SOURCE);
185
186 /* If slave is not present */
187 if (REG_GET_FIELD(reg_c_tx_abrt_source,
188 CKSVII2C_IC_TX_ABRT_SOURCE,
189 ABRT_7B_ADDR_NOACK) == 1) {
190 ret |= I2C_NAK_7B_ADDR_NOACK;
191
192 smu_v11_0_i2c_clear_status(control);
193 } else { /* wait till some data is there in RXFIFO */
194 /* Poll for some byte in RXFIFO */
195 unsigned long timeout_counter = jiffies + msecs_to_jiffies(20);
196
197 do {
198 if (time_after(jiffies, timeout_counter)) {
199 ret |= I2C_SW_TIMEOUT;
200 break;
201 }
202
203 reg_ic_status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS);
204
205 } while (REG_GET_FIELD(reg_ic_status, CKSVII2C_IC_STATUS, RFNE) == 0);
206 }
207
208 return ret;
209}
210
211
212
213
214/**
215 * smu_v11_0_i2c_transmit - Send a block of data over the I2C bus to a slave device.
216 *
217 * @address: The I2C address of the slave device.
218 * @data: The data to transmit over the bus.
219 * @numbytes: The amount of data to transmit.
220 * @i2c_flag: Flags for transmission
221 *
222 * Returns 0 on success or error.
223 */
224static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter *control,
225 uint8_t address, uint8_t *data,
226 uint32_t numbytes, uint32_t i2c_flag)
227{
228 struct amdgpu_device *adev = to_amdgpu_device(control);
229 uint32_t bytes_sent, reg, ret = 0;
230 unsigned long timeout_counter;
231
232 bytes_sent = 0;
233
234 DRM_DEBUG_DRIVER("I2C_Transmit(), address = %x, bytes = %d , data: ",
235 (uint16_t)address, numbytes);
236
237 if (drm_debug & DRM_UT_DRIVER) {
238 print_hex_dump(KERN_INFO, "data: ", DUMP_PREFIX_NONE,
239 16, 1, data, numbytes, false);
240 }
241
242 /* Set the I2C slave address */
243 smu_v11_0_i2c_set_address(control, address);
244 /* Enable I2C */
245 smu_v11_0_i2c_enable(control, true);
246
247 /* Clear status bits */
248 smu_v11_0_i2c_clear_status(control);
249
250
251 timeout_counter = jiffies + msecs_to_jiffies(20);
252
253 while (numbytes > 0) {
254 reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS);
255 if (REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)) {
256 do {
257 reg = 0;
258 /*
259 * Prepare transaction, no need to set RESTART. I2C engine will send
260 * START as soon as it sees data in TXFIFO
261 */
262 if (bytes_sent == 0)
263 reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, RESTART,
264 (i2c_flag & I2C_RESTART) ? 1 : 0);
265 reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, data[bytes_sent]);
266
267 /* determine if we need to send STOP bit or not */
268 if (numbytes == 1)
269 /* Final transaction, so send stop unless I2C_NO_STOP */
270 reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, STOP,
271 (i2c_flag & I2C_NO_STOP) ? 0 : 1);
272 /* Write */
273 reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 0);
274 WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg);
275
276 /* Record that the bytes were transmitted */
277 bytes_sent++;
278 numbytes--;
279
280 reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS);
281
282 } while (numbytes && REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF));
283 }
284
285 /*
286 * We waited too long for the transmission FIFO to become not-full.
287 * Exit the loop with error.
288 */
289 if (time_after(jiffies, timeout_counter)) {
290 ret |= I2C_SW_TIMEOUT;
291 goto Err;
292 }
293 }
294
295 ret = smu_v11_0_i2c_poll_tx_status(control);
296
297Err:
298 /* Any error, no point in proceeding */
299 if (ret != I2C_OK) {
300 if (ret & I2C_SW_TIMEOUT)
301 DRM_ERROR("TIMEOUT ERROR !!!");
302
303 if (ret & I2C_NAK_7B_ADDR_NOACK)
304 DRM_ERROR("Received I2C_NAK_7B_ADDR_NOACK !!!");
305
306
307 if (ret & I2C_NAK_TXDATA_NOACK)
308 DRM_ERROR("Received I2C_NAK_TXDATA_NOACK !!!");
309 }
310
311 return ret;
312}
313
314
315/**
316 * smu_v11_0_i2c_receive - Receive a block of data over the I2C bus from a slave device.
317 *
318 * @address: The I2C address of the slave device.
319 * @numbytes: The amount of data to transmit.
320 * @i2c_flag: Flags for transmission
321 *
322 * Returns 0 on success or error.
323 */
324static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter *control,
325 uint8_t address, uint8_t *data,
326 uint32_t numbytes, uint8_t i2c_flag)
327{
328 struct amdgpu_device *adev = to_amdgpu_device(control);
329 uint32_t bytes_received, ret = I2C_OK;
330
331 bytes_received = 0;
332
333 /* Set the I2C slave address */
334 smu_v11_0_i2c_set_address(control, address);
335
336 /* Enable I2C */
337 smu_v11_0_i2c_enable(control, true);
338
339 while (numbytes > 0) {
340 uint32_t reg = 0;
341
342 smu_v11_0_i2c_clear_status(control);
343
344
345 /* Prepare transaction */
346
347 /* Each time we disable I2C, so this is not a restart */
348 if (bytes_received == 0)
349 reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, RESTART,
350 (i2c_flag & I2C_RESTART) ? 1 : 0);
351
352 reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, 0);
353 /* Read */
354 reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 1);
355
356 /* Transmitting last byte */
357 if (numbytes == 1)
358 /* Final transaction, so send stop if requested */
359 reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, STOP,
360 (i2c_flag & I2C_NO_STOP) ? 0 : 1);
361
362 WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg);
363
364 ret = smu_v11_0_i2c_poll_rx_status(control);
365
366 /* Any error, no point in proceeding */
367 if (ret != I2C_OK) {
368 if (ret & I2C_SW_TIMEOUT)
369 DRM_ERROR("TIMEOUT ERROR !!!");
370
371 if (ret & I2C_NAK_7B_ADDR_NOACK)
372 DRM_ERROR("Received I2C_NAK_7B_ADDR_NOACK !!!");
373
374 if (ret & I2C_NAK_TXDATA_NOACK)
375 DRM_ERROR("Received I2C_NAK_TXDATA_NOACK !!!");
376
377 break;
378 }
379
380 reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD);
381 data[bytes_received] = REG_GET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT);
382
383 /* Record that the bytes were received */
384 bytes_received++;
385 numbytes--;
386 }
387
388 DRM_DEBUG_DRIVER("I2C_Receive(), address = %x, bytes = %d, data :",
389 (uint16_t)address, bytes_received);
390
391 if (drm_debug & DRM_UT_DRIVER) {
392 print_hex_dump(KERN_INFO, "data: ", DUMP_PREFIX_NONE,
393 16, 1, data, bytes_received, false);
394 }
395
396 return ret;
397}
398
399static void smu_v11_0_i2c_abort(struct i2c_adapter *control)
400{
401 struct amdgpu_device *adev = to_amdgpu_device(control);
402 uint32_t reg = 0;
403
404 /* Enable I2C engine; */
405 reg = REG_SET_FIELD(reg, CKSVII2C_IC_ENABLE, ENABLE, 1);
406 WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE, reg);
407
408 /* Abort previous transaction */
409 reg = REG_SET_FIELD(reg, CKSVII2C_IC_ENABLE, ABORT, 1);
410 WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE, reg);
411
412 DRM_DEBUG_DRIVER("I2C_Abort() Done.");
413}
414
415
416static bool smu_v11_0_i2c_activity_done(struct i2c_adapter *control)
417{
418 struct amdgpu_device *adev = to_amdgpu_device(control);
419
420 const uint32_t IDLE_TIMEOUT = 1024;
421 uint32_t timeout_count = 0;
422 uint32_t reg_ic_enable, reg_ic_enable_status, reg_ic_clr_activity;
423
424 reg_ic_enable_status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE_STATUS);
425 reg_ic_enable = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE);
426
427
428 if ((REG_GET_FIELD(reg_ic_enable, CKSVII2C_IC_ENABLE, ENABLE) == 0) &&
429 (REG_GET_FIELD(reg_ic_enable_status, CKSVII2C_IC_ENABLE_STATUS, IC_EN) == 1)) {
430 /*
431 * Nobody is using I2C engine, but engine remains active because
432 * someone missed to send STOP
433 */
434 smu_v11_0_i2c_abort(control);
435 } else if (REG_GET_FIELD(reg_ic_enable, CKSVII2C_IC_ENABLE, ENABLE) == 0) {
436 /* Nobody is using I2C engine */
437 return true;
438 }
439
440 /* Keep reading activity bit until it's cleared */
441 do {
442 reg_ic_clr_activity = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_CLR_ACTIVITY);
443
444 if (REG_GET_FIELD(reg_ic_clr_activity,
445 CKSVII2C_IC_CLR_ACTIVITY, CLR_ACTIVITY) == 0)
446 return true;
447
448 ++timeout_count;
449
450 } while (timeout_count < IDLE_TIMEOUT);
451
452 return false;
453}
454
455static void smu_v11_0_i2c_init(struct i2c_adapter *control)
456{
457 /* Disable clock gating */
458 smu_v11_0_i2c_set_clock_gating(control, false);
459
460 if (!smu_v11_0_i2c_activity_done(control))
461 DRM_WARN("I2C busy !");
462
463 /* Disable I2C */
464 smu_v11_0_i2c_enable(control, false);
465
466 /* Configure I2C to operate as master and in standard mode */
467 smu_v11_0_i2c_configure(control);
468
469 /* Initialize the clock to 50 kHz default */
470 smu_v11_0_i2c_set_clock(control);
471
472}
473
474static void smu_v11_0_i2c_fini(struct i2c_adapter *control)
475{
476 struct amdgpu_device *adev = to_amdgpu_device(control);
477 uint32_t reg_ic_enable_status, reg_ic_enable;
478
479 smu_v11_0_i2c_enable(control, false);
480
481 /* Double check if disabled, else force abort */
482 reg_ic_enable_status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE_STATUS);
483 reg_ic_enable = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE);
484
485 if ((REG_GET_FIELD(reg_ic_enable, CKSVII2C_IC_ENABLE, ENABLE) == 0) &&
486 (REG_GET_FIELD(reg_ic_enable_status,
487 CKSVII2C_IC_ENABLE_STATUS, IC_EN) == 1)) {
488 /*
489 * Nobody is using I2C engine, but engine remains active because
490 * someone missed to send STOP
491 */
492 smu_v11_0_i2c_abort(control);
493 }
494
495 /* Restore clock gating */
496 smu_v11_0_i2c_set_clock_gating(control, true);
497
498}
499
500static bool smu_v11_0_i2c_bus_lock(struct i2c_adapter *control)
501{
502 struct amdgpu_device *adev = to_amdgpu_device(control);
503
504 /* Send PPSMC_MSG_RequestI2CBus */
505 if (!adev->powerplay.pp_funcs->smu_i2c_bus_access)
506 goto Fail;
507
508
509 if (!adev->powerplay.pp_funcs->smu_i2c_bus_access(adev->powerplay.pp_handle, true))
510 return true;
511
512Fail:
513 return false;
514}
515
516static bool smu_v11_0_i2c_bus_unlock(struct i2c_adapter *control)
517{
518 struct amdgpu_device *adev = to_amdgpu_device(control);
519
520 /* Send PPSMC_MSG_RequestI2CBus */
521 if (!adev->powerplay.pp_funcs->smu_i2c_bus_access)
522 goto Fail;
523
524 /* Send PPSMC_MSG_ReleaseI2CBus */
525 if (!adev->powerplay.pp_funcs->smu_i2c_bus_access(adev->powerplay.pp_handle,
526 false))
527 return true;
528
529Fail:
530 return false;
531}
532
533/***************************** EEPROM I2C GLUE ****************************/
534
535static uint32_t smu_v11_0_i2c_eeprom_read_data(struct i2c_adapter *control,
536 uint8_t address,
537 uint8_t *data,
538 uint32_t numbytes)
539{
540 uint32_t ret = 0;
541
542 /* First 2 bytes are dummy write to set EEPROM address */
543 ret = smu_v11_0_i2c_transmit(control, address, data, 2, I2C_NO_STOP);
544 if (ret != I2C_OK)
545 goto Fail;
546
547 /* Now read data starting with that address */
548 ret = smu_v11_0_i2c_receive(control, address, data + 2, numbytes - 2,
549 I2C_RESTART);
550
551Fail:
552 if (ret != I2C_OK)
553 DRM_ERROR("ReadData() - I2C error occurred :%x", ret);
554
555 return ret;
556}
557
558static uint32_t smu_v11_0_i2c_eeprom_write_data(struct i2c_adapter *control,
559 uint8_t address,
560 uint8_t *data,
561 uint32_t numbytes)
562{
563 uint32_t ret;
564
565 ret = smu_v11_0_i2c_transmit(control, address, data, numbytes, 0);
566
567 if (ret != I2C_OK)
568 DRM_ERROR("WriteI2CData() - I2C error occurred :%x", ret);
569 else
570 /*
571 * According to EEPROM spec there is a MAX of 10 ms required for
572 * EEPROM to flush internal RX buffer after STOP was issued at the
573 * end of write transaction. During this time the EEPROM will not be
574 * responsive to any more commands - so wait a bit more.
575 *
576 * TODO Improve to wait for first ACK for slave address after
577 * internal write cycle done.
578 */
579 msleep(10);
580
581 return ret;
582
583}
584
585static void lock_bus(struct i2c_adapter *i2c, unsigned int flags)
586{
587 struct amdgpu_ras_eeprom_control *control = to_eeprom_control(i2c);
588
589 if (!smu_v11_0_i2c_bus_lock(i2c)) {
590 DRM_ERROR("Failed to lock the bus from SMU");
591 return;
592 }
593
594 control->bus_locked = true;
595}
596
597static int trylock_bus(struct i2c_adapter *i2c, unsigned int flags)
598{
599 WARN_ONCE(1, "This operation not supposed to run in atomic context!");
600 return false;
601}
602
603static void unlock_bus(struct i2c_adapter *i2c, unsigned int flags)
604{
605 struct amdgpu_ras_eeprom_control *control = to_eeprom_control(i2c);
606
607 if (!smu_v11_0_i2c_bus_unlock(i2c)) {
608 DRM_ERROR("Failed to unlock the bus from SMU");
609 return;
610 }
611
612 control->bus_locked = false;
613}
614
615static const struct i2c_lock_operations smu_v11_0_i2c_i2c_lock_ops = {
616 .lock_bus = lock_bus,
617 .trylock_bus = trylock_bus,
618 .unlock_bus = unlock_bus,
619};
620
621static int smu_v11_0_i2c_eeprom_i2c_xfer(struct i2c_adapter *i2c_adap,
622 struct i2c_msg *msgs, int num)
623{
624 int i, ret;
625 struct amdgpu_ras_eeprom_control *control = to_eeprom_control(i2c_adap);
626
627 if (!control->bus_locked) {
628 DRM_ERROR("I2C bus unlocked, stopping transaction!");
629 return -EIO;
630 }
631
632 smu_v11_0_i2c_init(i2c_adap);
633
634 for (i = 0; i < num; i++) {
635 if (msgs[i].flags & I2C_M_RD)
636 ret = smu_v11_0_i2c_eeprom_read_data(i2c_adap,
637 (uint8_t)msgs[i].addr,
638 msgs[i].buf, msgs[i].len);
639 else
640 ret = smu_v11_0_i2c_eeprom_write_data(i2c_adap,
641 (uint8_t)msgs[i].addr,
642 msgs[i].buf, msgs[i].len);
643
644 if (ret != I2C_OK) {
645 num = -EIO;
646 break;
647 }
648 }
649
650 smu_v11_0_i2c_fini(i2c_adap);
651 return num;
652}
653
654static u32 smu_v11_0_i2c_eeprom_i2c_func(struct i2c_adapter *adap)
655{
656 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
657}
658
659
660static const struct i2c_algorithm smu_v11_0_i2c_eeprom_i2c_algo = {
661 .master_xfer = smu_v11_0_i2c_eeprom_i2c_xfer,
662 .functionality = smu_v11_0_i2c_eeprom_i2c_func,
663};
664
665int smu_v11_0_i2c_eeprom_control_init(struct i2c_adapter *control)
666{
667 struct amdgpu_device *adev = to_amdgpu_device(control);
668 int res;
669
670 control->owner = THIS_MODULE;
671 control->class = I2C_CLASS_SPD;
672 control->dev.parent = &adev->pdev->dev;
673 control->algo = &smu_v11_0_i2c_eeprom_i2c_algo;
674 snprintf(control->name, sizeof(control->name), "RAS EEPROM");
675 control->lock_ops = &smu_v11_0_i2c_i2c_lock_ops;
676
677 res = i2c_add_adapter(control);
678 if (res)
679 DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
680
681 return res;
682}
683
684void smu_v11_0_i2c_eeprom_control_fini(struct i2c_adapter *control)
685{
686 i2c_del_adapter(control);
687}
688
689/*
690 * Keep this for future unit test if bugs arise
691 */
692#if 0
693#define I2C_TARGET_ADDR 0xA0
694
695bool smu_v11_0_i2c_test_bus(struct i2c_adapter *control)
696{
697
698 uint32_t ret = I2C_OK;
699 uint8_t data[6] = {0xf, 0, 0xde, 0xad, 0xbe, 0xef};
700
701
702 DRM_INFO("Begin");
703
704 if (!smu_v11_0_i2c_bus_lock(control)) {
705 DRM_ERROR("Failed to lock the bus!.");
706 return false;
707 }
708
709 smu_v11_0_i2c_init(control);
710
711 /* Write 0xde to address 0x0000 on the EEPROM */
712 ret = smu_v11_0_i2c_eeprom_write_data(control, I2C_TARGET_ADDR, data, 6);
713
714 ret = smu_v11_0_i2c_eeprom_read_data(control, I2C_TARGET_ADDR, data, 6);
715
716 smu_v11_0_i2c_fini(control);
717
718 smu_v11_0_i2c_bus_unlock(control);
719
720
721 DRM_INFO("End");
722 return true;
723}
724#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h
new file mode 100644
index 000000000000..973f28d68e70
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h
@@ -0,0 +1,34 @@
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#ifndef SMU_V11_I2C_CONTROL_H
25#define SMU_V11_I2C_CONTROL_H
26
27#include <linux/types.h>
28
29struct i2c_adapter;
30
31int smu_v11_0_i2c_eeprom_control_init(struct i2c_adapter *control);
32void smu_v11_0_i2c_eeprom_control_fini(struct i2c_adapter *control);
33
34#endif