@@ -1290,6 +1290,287 @@ void thc_spi_input_output_address_config(struct thc_device *dev, u32 input_hdr_a
12901290}
12911291EXPORT_SYMBOL_NS_GPL (thc_spi_input_output_address_config , "INTEL_THC" );
12921292
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+
12931574MODULE_AUTHOR (
"Xinpeng Sun <[email protected] >" );
12941575MODULE_AUTHOR (
"Even Xu <[email protected] >" );
12951576
0 commit comments