| 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 |