@@ -1266,6 +1266,233 @@ static bool aldebaran_is_dpm_running(struct smu_context *smu)
12661266 return !!(feature_enabled & SMC_DPM_FEATURE );
12671267}
12681268
1269+ static void aldebaran_fill_i2c_req (SwI2cRequest_t * req , bool write ,
1270+ uint8_t address , uint32_t numbytes ,
1271+ uint8_t * data )
1272+ {
1273+ int i ;
1274+
1275+ req -> I2CcontrollerPort = 0 ;
1276+ req -> I2CSpeed = 2 ;
1277+ req -> SlaveAddress = address ;
1278+ req -> NumCmds = numbytes ;
1279+
1280+ for (i = 0 ; i < numbytes ; i ++ ) {
1281+ SwI2cCmd_t * cmd = & req -> SwI2cCmds [i ];
1282+
1283+ /* First 2 bytes are always write for lower 2b EEPROM address */
1284+ if (i < 2 )
1285+ cmd -> CmdConfig = CMDCONFIG_READWRITE_MASK ;
1286+ else
1287+ cmd -> CmdConfig = write ? CMDCONFIG_READWRITE_MASK : 0 ;
1288+
1289+
1290+ /* Add RESTART for read after address filled */
1291+ cmd -> CmdConfig |= (i == 2 && !write ) ? CMDCONFIG_RESTART_MASK : 0 ;
1292+
1293+ /* Add STOP in the end */
1294+ cmd -> CmdConfig |= (i == (numbytes - 1 )) ? CMDCONFIG_STOP_MASK : 0 ;
1295+
1296+ /* Fill with data regardless if read or write to simplify code */
1297+ cmd -> ReadWriteData = data [i ];
1298+ }
1299+ }
1300+
1301+ static int aldebaran_i2c_read_data (struct i2c_adapter * control ,
1302+ uint8_t address ,
1303+ uint8_t * data ,
1304+ uint32_t numbytes )
1305+ {
1306+ uint32_t i , ret = 0 ;
1307+ SwI2cRequest_t req ;
1308+ struct amdgpu_device * adev = to_amdgpu_device (control );
1309+ struct smu_table_context * smu_table = & adev -> smu .smu_table ;
1310+ struct smu_table * table = & smu_table -> driver_table ;
1311+
1312+ if (numbytes > MAX_SW_I2C_COMMANDS ) {
1313+ dev_err (adev -> dev , "numbytes requested %d is over max allowed %d\n" ,
1314+ numbytes , MAX_SW_I2C_COMMANDS );
1315+ return - EINVAL ;
1316+ }
1317+
1318+ memset (& req , 0 , sizeof (req ));
1319+ aldebaran_fill_i2c_req (& req , false, address , numbytes , data );
1320+
1321+ mutex_lock (& adev -> smu .mutex );
1322+ /* Now read data starting with that address */
1323+ ret = smu_cmn_update_table (& adev -> smu , SMU_TABLE_I2C_COMMANDS , 0 , & req ,
1324+ true);
1325+ mutex_unlock (& adev -> smu .mutex );
1326+
1327+ if (!ret ) {
1328+ SwI2cRequest_t * res = (SwI2cRequest_t * )table -> cpu_addr ;
1329+
1330+ /* Assume SMU fills res.SwI2cCmds[i].Data with read bytes */
1331+ for (i = 0 ; i < numbytes ; i ++ )
1332+ data [i ] = res -> SwI2cCmds [i ].ReadWriteData ;
1333+
1334+ dev_dbg (adev -> dev , "aldebaran_i2c_read_data, address = %x, bytes = %d, data :" ,
1335+ (uint16_t )address , numbytes );
1336+
1337+ print_hex_dump (KERN_DEBUG , "data: " , DUMP_PREFIX_NONE ,
1338+ 8 , 1 , data , numbytes , false);
1339+ } else
1340+ dev_err (adev -> dev , "aldebaran_i2c_read_data - error occurred :%x" , ret );
1341+
1342+ return ret ;
1343+ }
1344+
1345+ static int aldebaran_i2c_write_data (struct i2c_adapter * control ,
1346+ uint8_t address ,
1347+ uint8_t * data ,
1348+ uint32_t numbytes )
1349+ {
1350+ uint32_t ret ;
1351+ SwI2cRequest_t req ;
1352+ struct amdgpu_device * adev = to_amdgpu_device (control );
1353+
1354+ if (numbytes > MAX_SW_I2C_COMMANDS ) {
1355+ dev_err (adev -> dev , "numbytes requested %d is over max allowed %d\n" ,
1356+ numbytes , MAX_SW_I2C_COMMANDS );
1357+ return - EINVAL ;
1358+ }
1359+
1360+ memset (& req , 0 , sizeof (req ));
1361+ aldebaran_fill_i2c_req (& req , true, address , numbytes , data );
1362+
1363+ mutex_lock (& adev -> smu .mutex );
1364+ ret = smu_cmn_update_table (& adev -> smu , SMU_TABLE_I2C_COMMANDS , 0 , & req , true);
1365+ mutex_unlock (& adev -> smu .mutex );
1366+
1367+ if (!ret ) {
1368+ dev_dbg (adev -> dev , "aldebaran_i2c_write(), address = %x, bytes = %d , data: " ,
1369+ (uint16_t )address , numbytes );
1370+
1371+ print_hex_dump (KERN_DEBUG , "data: " , DUMP_PREFIX_NONE ,
1372+ 8 , 1 , data , numbytes , false);
1373+ /*
1374+ * According to EEPROM spec there is a MAX of 10 ms required for
1375+ * EEPROM to flush internal RX buffer after STOP was issued at the
1376+ * end of write transaction. During this time the EEPROM will not be
1377+ * responsive to any more commands - so wait a bit more.
1378+ */
1379+ msleep (10 );
1380+
1381+ } else
1382+ dev_err (adev -> dev , "aldebaran_i2c_write- error occurred :%x" , ret );
1383+
1384+ return ret ;
1385+ }
1386+
1387+ static int aldebaran_i2c_xfer (struct i2c_adapter * i2c_adap ,
1388+ struct i2c_msg * msgs , int num )
1389+ {
1390+ uint32_t i , j , ret , data_size , data_chunk_size , next_eeprom_addr = 0 ;
1391+ uint8_t * data_ptr , data_chunk [MAX_SW_I2C_COMMANDS ] = { 0 };
1392+
1393+ for (i = 0 ; i < num ; i ++ ) {
1394+ /*
1395+ * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at
1396+ * once and hence the data needs to be spliced into chunks and sent each
1397+ * chunk separately
1398+ */
1399+ data_size = msgs [i ].len - 2 ;
1400+ data_chunk_size = MAX_SW_I2C_COMMANDS - 2 ;
1401+ next_eeprom_addr = (msgs [i ].buf [0 ] << 8 & 0xff00 ) | (msgs [i ].buf [1 ] & 0xff );
1402+ data_ptr = msgs [i ].buf + 2 ;
1403+
1404+ for (j = 0 ; j < data_size / data_chunk_size ; j ++ ) {
1405+ /* Insert the EEPROM dest addess, bits 0-15 */
1406+ data_chunk [0 ] = ((next_eeprom_addr >> 8 ) & 0xff );
1407+ data_chunk [1 ] = (next_eeprom_addr & 0xff );
1408+
1409+ if (msgs [i ].flags & I2C_M_RD ) {
1410+ ret = aldebaran_i2c_read_data (i2c_adap ,
1411+ (uint8_t )msgs [i ].addr ,
1412+ data_chunk , MAX_SW_I2C_COMMANDS );
1413+
1414+ memcpy (data_ptr , data_chunk + 2 , data_chunk_size );
1415+ } else {
1416+
1417+ memcpy (data_chunk + 2 , data_ptr , data_chunk_size );
1418+
1419+ ret = aldebaran_i2c_write_data (i2c_adap ,
1420+ (uint8_t )msgs [i ].addr ,
1421+ data_chunk , MAX_SW_I2C_COMMANDS );
1422+ }
1423+
1424+ if (ret ) {
1425+ num = - EIO ;
1426+ goto fail ;
1427+ }
1428+
1429+ next_eeprom_addr += data_chunk_size ;
1430+ data_ptr += data_chunk_size ;
1431+ }
1432+
1433+ if (data_size % data_chunk_size ) {
1434+ data_chunk [0 ] = ((next_eeprom_addr >> 8 ) & 0xff );
1435+ data_chunk [1 ] = (next_eeprom_addr & 0xff );
1436+
1437+ if (msgs [i ].flags & I2C_M_RD ) {
1438+ ret = aldebaran_i2c_read_data (i2c_adap ,
1439+ (uint8_t )msgs [i ].addr ,
1440+ data_chunk , (data_size % data_chunk_size ) + 2 );
1441+
1442+ memcpy (data_ptr , data_chunk + 2 , data_size % data_chunk_size );
1443+ } else {
1444+ memcpy (data_chunk + 2 , data_ptr , data_size % data_chunk_size );
1445+
1446+ ret = aldebaran_i2c_write_data (i2c_adap ,
1447+ (uint8_t )msgs [i ].addr ,
1448+ data_chunk , (data_size % data_chunk_size ) + 2 );
1449+ }
1450+
1451+ if (ret ) {
1452+ num = - EIO ;
1453+ goto fail ;
1454+ }
1455+ }
1456+ }
1457+
1458+ fail :
1459+ return num ;
1460+ }
1461+
1462+ static u32 aldebaran_i2c_func (struct i2c_adapter * adap )
1463+ {
1464+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL ;
1465+ }
1466+
1467+
1468+ static const struct i2c_algorithm aldebaran_i2c_algo = {
1469+ .master_xfer = aldebaran_i2c_xfer ,
1470+ .functionality = aldebaran_i2c_func ,
1471+ };
1472+
1473+ static int aldebaran_i2c_control_init (struct smu_context * smu , struct i2c_adapter * control )
1474+ {
1475+ struct amdgpu_device * adev = to_amdgpu_device (control );
1476+ int res ;
1477+
1478+ control -> owner = THIS_MODULE ;
1479+ control -> class = I2C_CLASS_SPD ;
1480+ control -> dev .parent = & adev -> pdev -> dev ;
1481+ control -> algo = & aldebaran_i2c_algo ;
1482+ snprintf (control -> name , sizeof (control -> name ), "AMDGPU SMU" );
1483+
1484+ res = i2c_add_adapter (control );
1485+ if (res )
1486+ DRM_ERROR ("Failed to register hw i2c, err: %d\n" , res );
1487+
1488+ return res ;
1489+ }
1490+
1491+ static void aldebaran_i2c_control_fini (struct smu_context * smu , struct i2c_adapter * control )
1492+ {
1493+ i2c_del_adapter (control );
1494+ }
1495+
12691496static void aldebaran_get_unique_id (struct smu_context * smu )
12701497{
12711498 struct amdgpu_device * adev = smu -> adev ;
@@ -1585,6 +1812,8 @@ static const struct pptable_funcs aldebaran_ppt_funcs = {
15851812 .set_mp1_state = aldebaran_set_mp1_state ,
15861813 .mode2_reset = aldebaran_mode2_reset ,
15871814 .wait_for_event = smu_v13_0_wait_for_event ,
1815+ .i2c_init = aldebaran_i2c_control_init ,
1816+ .i2c_fini = aldebaran_i2c_control_fini ,
15881817};
15891818
15901819void aldebaran_set_ppt_funcs (struct smu_context * smu )
0 commit comments