@@ -1266,6 +1266,233 @@ static bool aldebaran_is_dpm_running(struct smu_context *smu)
1266
1266
return !!(feature_enabled & SMC_DPM_FEATURE );
1267
1267
}
1268
1268
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
+
1269
1496
static void aldebaran_get_unique_id (struct smu_context * smu )
1270
1497
{
1271
1498
struct amdgpu_device * adev = smu -> adev ;
@@ -1585,6 +1812,8 @@ static const struct pptable_funcs aldebaran_ppt_funcs = {
1585
1812
.set_mp1_state = aldebaran_set_mp1_state ,
1586
1813
.mode2_reset = aldebaran_mode2_reset ,
1587
1814
.wait_for_event = smu_v13_0_wait_for_event ,
1815
+ .i2c_init = aldebaran_i2c_control_init ,
1816
+ .i2c_fini = aldebaran_i2c_control_fini ,
1588
1817
};
1589
1818
1590
1819
void aldebaran_set_ppt_funcs (struct smu_context * smu )
0 commit comments