@@ -1290,6 +1290,287 @@ void thc_spi_input_output_address_config(struct thc_device *dev, u32 input_hdr_a
1290
1290
}
1291
1291
EXPORT_SYMBOL_NS_GPL (thc_spi_input_output_address_config , "INTEL_THC" );
1292
1292
1293
+ static int thc_i2c_subip_pio_read (struct thc_device * dev , const u32 address ,
1294
+ u32 * size , u32 * buffer )
1295
+ {
1296
+ int ret ;
1297
+
1298
+ if (!size || * size == 0 || !buffer ) {
1299
+ dev_err (dev -> dev , "Invalid input parameters, size %p, buffer %p\n" ,
1300
+ size , buffer );
1301
+ return - EINVAL ;
1302
+ }
1303
+
1304
+ if (mutex_lock_interruptible (& dev -> thc_bus_lock ))
1305
+ return - EINTR ;
1306
+
1307
+ ret = prepare_pio (dev , THC_PIO_OP_I2C_SUBSYSTEM_READ , address , * size );
1308
+ if (ret < 0 )
1309
+ goto end ;
1310
+
1311
+ pio_start (dev , 0 , NULL );
1312
+
1313
+ ret = pio_wait (dev );
1314
+ if (ret < 0 )
1315
+ goto end ;
1316
+
1317
+ ret = pio_complete (dev , buffer , size );
1318
+ if (ret < 0 )
1319
+ goto end ;
1320
+
1321
+ end :
1322
+ mutex_unlock (& dev -> thc_bus_lock );
1323
+
1324
+ if (ret )
1325
+ dev_err_once (dev -> dev , "Read THC I2C SubIP register failed %d, offset %u\n" ,
1326
+ ret , address );
1327
+
1328
+ return ret ;
1329
+ }
1330
+
1331
+ static int thc_i2c_subip_pio_write (struct thc_device * dev , const u32 address ,
1332
+ const u32 size , const u32 * buffer )
1333
+ {
1334
+ int ret ;
1335
+
1336
+ if (size == 0 || !buffer ) {
1337
+ dev_err (dev -> dev , "Invalid input parameters, size %u, buffer %p\n" ,
1338
+ size , buffer );
1339
+ return - EINVAL ;
1340
+ }
1341
+
1342
+ if (mutex_lock_interruptible (& dev -> thc_bus_lock ))
1343
+ return - EINTR ;
1344
+
1345
+ ret = prepare_pio (dev , THC_PIO_OP_I2C_SUBSYSTEM_WRITE , address , size );
1346
+ if (ret < 0 )
1347
+ goto end ;
1348
+
1349
+ pio_start (dev , size , buffer );
1350
+
1351
+ ret = pio_wait (dev );
1352
+ if (ret < 0 )
1353
+ goto end ;
1354
+
1355
+ ret = pio_complete (dev , NULL , NULL );
1356
+ if (ret < 0 )
1357
+ goto end ;
1358
+
1359
+ end :
1360
+ mutex_unlock (& dev -> thc_bus_lock );
1361
+
1362
+ if (ret )
1363
+ dev_err_once (dev -> dev , "Write THC I2C SubIP register failed %d, offset %u\n" ,
1364
+ ret , address );
1365
+
1366
+ return ret ;
1367
+ }
1368
+
1369
+ #define I2C_SUBIP_CON_DEFAULT 0x663
1370
+ #define I2C_SUBIP_INT_MASK_DEFAULT 0x7FFF
1371
+ #define I2C_SUBIP_RX_TL_DEFAULT 62
1372
+ #define I2C_SUBIP_TX_TL_DEFAULT 0
1373
+ #define I2C_SUBIP_DMA_TDLR_DEFAULT 7
1374
+ #define I2C_SUBIP_DMA_RDLR_DEFAULT 7
1375
+
1376
+ static int thc_i2c_subip_set_speed (struct thc_device * dev , const u32 speed ,
1377
+ const u32 hcnt , const u32 lcnt )
1378
+ {
1379
+ u32 hcnt_offset , lcnt_offset ;
1380
+ u32 val ;
1381
+ int ret ;
1382
+
1383
+ switch (speed ) {
1384
+ case THC_I2C_STANDARD :
1385
+ hcnt_offset = THC_I2C_IC_SS_SCL_HCNT_OFFSET ;
1386
+ lcnt_offset = THC_I2C_IC_SS_SCL_LCNT_OFFSET ;
1387
+ break ;
1388
+
1389
+ case THC_I2C_FAST_AND_PLUS :
1390
+ hcnt_offset = THC_I2C_IC_FS_SCL_HCNT_OFFSET ;
1391
+ lcnt_offset = THC_I2C_IC_FS_SCL_LCNT_OFFSET ;
1392
+ break ;
1393
+
1394
+ case THC_I2C_HIGH_SPEED :
1395
+ hcnt_offset = THC_I2C_IC_HS_SCL_HCNT_OFFSET ;
1396
+ lcnt_offset = THC_I2C_IC_HS_SCL_LCNT_OFFSET ;
1397
+ break ;
1398
+
1399
+ default :
1400
+ dev_err_once (dev -> dev , "Unsupported i2c speed %d\n" , speed );
1401
+ ret = - EINVAL ;
1402
+ return ret ;
1403
+ }
1404
+
1405
+ ret = thc_i2c_subip_pio_write (dev , hcnt_offset , sizeof (u32 ), & hcnt );
1406
+ if (ret < 0 )
1407
+ return ret ;
1408
+
1409
+ ret = thc_i2c_subip_pio_write (dev , lcnt_offset , sizeof (u32 ), & lcnt );
1410
+ if (ret < 0 )
1411
+ return ret ;
1412
+
1413
+ val = I2C_SUBIP_CON_DEFAULT & ~THC_I2C_IC_CON_SPEED ;
1414
+ val |= FIELD_PREP (THC_I2C_IC_CON_SPEED , speed );
1415
+ ret = thc_i2c_subip_pio_write (dev , THC_I2C_IC_CON_OFFSET , sizeof (u32 ), & val );
1416
+ if (ret < 0 )
1417
+ return ret ;
1418
+
1419
+ return 0 ;
1420
+ }
1421
+
1422
+ static u32 i2c_subip_regs [] = {
1423
+ THC_I2C_IC_CON_OFFSET ,
1424
+ THC_I2C_IC_TAR_OFFSET ,
1425
+ THC_I2C_IC_INTR_MASK_OFFSET ,
1426
+ THC_I2C_IC_RX_TL_OFFSET ,
1427
+ THC_I2C_IC_TX_TL_OFFSET ,
1428
+ THC_I2C_IC_DMA_CR_OFFSET ,
1429
+ THC_I2C_IC_DMA_TDLR_OFFSET ,
1430
+ THC_I2C_IC_DMA_RDLR_OFFSET ,
1431
+ THC_I2C_IC_SS_SCL_HCNT_OFFSET ,
1432
+ THC_I2C_IC_SS_SCL_LCNT_OFFSET ,
1433
+ THC_I2C_IC_FS_SCL_HCNT_OFFSET ,
1434
+ THC_I2C_IC_FS_SCL_LCNT_OFFSET ,
1435
+ THC_I2C_IC_HS_SCL_HCNT_OFFSET ,
1436
+ THC_I2C_IC_HS_SCL_LCNT_OFFSET ,
1437
+ THC_I2C_IC_ENABLE_OFFSET ,
1438
+ };
1439
+
1440
+ /**
1441
+ * thc_i2c_subip_init - Initialize and configure THC I2C subsystem
1442
+ *
1443
+ * @dev: The pointer of THC private device context
1444
+ * @target_address: Slave address of touch device (TIC)
1445
+ * @speed: I2C bus frequency speed mode
1446
+ * @hcnt: I2C clock SCL high count
1447
+ * @lcnt: I2C clock SCL low count
1448
+ *
1449
+ * Return: 0 on success, other error codes on failed.
1450
+ */
1451
+ int thc_i2c_subip_init (struct thc_device * dev , const u32 target_address ,
1452
+ const u32 speed , const u32 hcnt , const u32 lcnt )
1453
+ {
1454
+ u32 read_size = sizeof (u32 );
1455
+ u32 val ;
1456
+ int ret ;
1457
+
1458
+ ret = thc_i2c_subip_pio_read (dev , THC_I2C_IC_ENABLE_OFFSET , & read_size , & val );
1459
+ if (ret < 0 )
1460
+ return ret ;
1461
+
1462
+ val &= ~THC_I2C_IC_ENABLE_ENABLE ;
1463
+ ret = thc_i2c_subip_pio_write (dev , THC_I2C_IC_ENABLE_OFFSET , sizeof (u32 ), & val );
1464
+ if (ret < 0 )
1465
+ return ret ;
1466
+
1467
+ ret = thc_i2c_subip_pio_read (dev , THC_I2C_IC_TAR_OFFSET , & read_size , & val );
1468
+ if (ret < 0 )
1469
+ return ret ;
1470
+
1471
+ val &= ~THC_I2C_IC_TAR_IC_TAR ;
1472
+ val |= FIELD_PREP (THC_I2C_IC_TAR_IC_TAR , target_address );
1473
+ ret = thc_i2c_subip_pio_write (dev , THC_I2C_IC_TAR_OFFSET , sizeof (u32 ), & val );
1474
+ if (ret < 0 )
1475
+ return ret ;
1476
+
1477
+ ret = thc_i2c_subip_set_speed (dev , speed , hcnt , lcnt );
1478
+ if (ret < 0 )
1479
+ return ret ;
1480
+
1481
+ val = I2C_SUBIP_INT_MASK_DEFAULT ;
1482
+ ret = thc_i2c_subip_pio_write (dev , THC_I2C_IC_INTR_MASK_OFFSET , sizeof (u32 ), & val );
1483
+ if (ret < 0 )
1484
+ return ret ;
1485
+
1486
+ val = I2C_SUBIP_RX_TL_DEFAULT ;
1487
+ ret = thc_i2c_subip_pio_write (dev , THC_I2C_IC_RX_TL_OFFSET , sizeof (u32 ), & val );
1488
+ if (ret < 0 )
1489
+ return ret ;
1490
+
1491
+ val = I2C_SUBIP_TX_TL_DEFAULT ;
1492
+ ret = thc_i2c_subip_pio_write (dev , THC_I2C_IC_TX_TL_OFFSET , sizeof (u32 ), & val );
1493
+ if (ret < 0 )
1494
+ return ret ;
1495
+
1496
+ val = THC_I2C_IC_DMA_CR_RDMAE | THC_I2C_IC_DMA_CR_TDMAE ;
1497
+ ret = thc_i2c_subip_pio_write (dev , THC_I2C_IC_DMA_CR_OFFSET , sizeof (u32 ), & val );
1498
+ if (ret < 0 )
1499
+ return ret ;
1500
+
1501
+ val = I2C_SUBIP_DMA_TDLR_DEFAULT ;
1502
+ ret = thc_i2c_subip_pio_write (dev , THC_I2C_IC_DMA_TDLR_OFFSET , sizeof (u32 ), & val );
1503
+ if (ret < 0 )
1504
+ return ret ;
1505
+
1506
+ val = I2C_SUBIP_DMA_RDLR_DEFAULT ;
1507
+ ret = thc_i2c_subip_pio_write (dev , THC_I2C_IC_DMA_RDLR_OFFSET , sizeof (u32 ), & val );
1508
+ if (ret < 0 )
1509
+ return ret ;
1510
+
1511
+ ret = thc_i2c_subip_pio_read (dev , THC_I2C_IC_ENABLE_OFFSET , & read_size , & val );
1512
+ if (ret < 0 )
1513
+ return ret ;
1514
+
1515
+ val |= THC_I2C_IC_ENABLE_ENABLE ;
1516
+ ret = thc_i2c_subip_pio_write (dev , THC_I2C_IC_ENABLE_OFFSET , sizeof (u32 ), & val );
1517
+ if (ret < 0 )
1518
+ return ret ;
1519
+
1520
+ dev -> i2c_subip_regs = devm_kzalloc (dev -> dev , sizeof (i2c_subip_regs ), GFP_KERNEL );
1521
+ if (!dev -> i2c_subip_regs )
1522
+ return PTR_ERR (dev -> i2c_subip_regs );
1523
+
1524
+ return 0 ;
1525
+ }
1526
+ EXPORT_SYMBOL_NS_GPL (thc_i2c_subip_init , "INTEL_THC" );
1527
+
1528
+ /**
1529
+ * thc_i2c_subip_regs_save - Save THC I2C sub-subsystem register values to THC device context
1530
+ *
1531
+ * @dev: The pointer of THC private device context
1532
+ *
1533
+ * Return: 0 on success, other error codes on failed.
1534
+ */
1535
+ int thc_i2c_subip_regs_save (struct thc_device * dev )
1536
+ {
1537
+ int ret ;
1538
+ u32 read_size = sizeof (u32 );
1539
+
1540
+ for (int i = 0 ; i < ARRAY_SIZE (i2c_subip_regs ); i ++ ) {
1541
+ ret = thc_i2c_subip_pio_read (dev , i2c_subip_regs [i ],
1542
+ & read_size , (u32 * )& dev -> i2c_subip_regs + i );
1543
+ if (ret < 0 )
1544
+ return ret ;
1545
+ }
1546
+
1547
+ return 0 ;
1548
+ }
1549
+ EXPORT_SYMBOL_NS_GPL (thc_i2c_subip_regs_save , "INTEL_THC" );
1550
+
1551
+ /**
1552
+ * thc_i2c_subip_regs_restore - Restore THC I2C subsystem registers from THC device context
1553
+ *
1554
+ * @dev: The pointer of THC private device context
1555
+ *
1556
+ * Return: 0 on success, other error codes on failed.
1557
+ */
1558
+ int thc_i2c_subip_regs_restore (struct thc_device * dev )
1559
+ {
1560
+ int ret ;
1561
+ u32 write_size = sizeof (u32 );
1562
+
1563
+ for (int i = 0 ; i < ARRAY_SIZE (i2c_subip_regs ); i ++ ) {
1564
+ ret = thc_i2c_subip_pio_write (dev , i2c_subip_regs [i ],
1565
+ write_size , (u32 * )& dev -> i2c_subip_regs + i );
1566
+ if (ret < 0 )
1567
+ return ret ;
1568
+ }
1569
+
1570
+ return 0 ;
1571
+ }
1572
+ EXPORT_SYMBOL_NS_GPL (thc_i2c_subip_regs_restore , "INTEL_THC" );
1573
+
1293
1574
MODULE_AUTHOR (
"Xinpeng Sun <[email protected] >" );
1294
1575
MODULE_AUTHOR (
"Even Xu <[email protected] >" );
1295
1576
0 commit comments