@@ -1061,6 +1061,235 @@ int thc_interrupt_handler(struct thc_device *dev)
10611061}
10621062EXPORT_SYMBOL_NS_GPL (thc_interrupt_handler , "INTEL_THC" );
10631063
1064+ /**
1065+ * thc_port_select - Set THC port type
1066+ *
1067+ * @dev: The pointer of THC private device context
1068+ * @port_type: THC port type to use for current device
1069+ *
1070+ * Return: 0 on success, other error codes on failed.
1071+ */
1072+ int thc_port_select (struct thc_device * dev , enum thc_port_type port_type )
1073+ {
1074+ u32 ctrl , mask ;
1075+
1076+ if (port_type == THC_PORT_TYPE_SPI ) {
1077+ dev_dbg (dev -> dev , "Set THC port type to SPI\n" );
1078+ dev -> port_type = THC_PORT_TYPE_SPI ;
1079+
1080+ /* Enable delay of CS assertion and set to default value */
1081+ ctrl = THC_M_PRT_SPI_DUTYC_CFG_SPI_CSA_CK_DELAY_EN |
1082+ FIELD_PREP (THC_M_PRT_SPI_DUTYC_CFG_SPI_CSA_CK_DELAY_VAL ,
1083+ THC_CSA_CK_DELAY_VAL_DEFAULT );
1084+ mask = THC_M_PRT_SPI_DUTYC_CFG_SPI_CSA_CK_DELAY_EN |
1085+ THC_M_PRT_SPI_DUTYC_CFG_SPI_CSA_CK_DELAY_VAL ;
1086+ regmap_write_bits (dev -> thc_regmap , THC_M_PRT_SPI_DUTYC_CFG_OFFSET ,
1087+ mask , ctrl );
1088+ } else if (port_type == THC_PORT_TYPE_I2C ) {
1089+ dev_dbg (dev -> dev , "Set THC port type to I2C\n" );
1090+ dev -> port_type = THC_PORT_TYPE_I2C ;
1091+
1092+ /* Set THC transition arbitration policy to frame boundary for I2C */
1093+ ctrl = FIELD_PREP (THC_M_PRT_CONTROL_THC_ARB_POLICY ,
1094+ THC_ARB_POLICY_FRAME_BOUNDARY );
1095+ mask = THC_M_PRT_CONTROL_THC_ARB_POLICY ;
1096+
1097+ regmap_write_bits (dev -> thc_regmap , THC_M_PRT_CONTROL_OFFSET , mask , ctrl );
1098+ } else {
1099+ dev_err (dev -> dev , "unsupported THC port type: %d\n" , port_type );
1100+ return - EINVAL ;
1101+ }
1102+
1103+ ctrl = FIELD_PREP (THC_M_PRT_CONTROL_PORT_TYPE , port_type );
1104+ mask = THC_M_PRT_CONTROL_PORT_TYPE ;
1105+
1106+ regmap_write_bits (dev -> thc_regmap , THC_M_PRT_CONTROL_OFFSET , mask , ctrl );
1107+
1108+ return 0 ;
1109+ }
1110+ EXPORT_SYMBOL_NS_GPL (thc_port_select , "INTEL_THC" );
1111+
1112+ #define THC_SPI_FREQUENCY_7M 7812500
1113+ #define THC_SPI_FREQUENCY_15M 15625000
1114+ #define THC_SPI_FREQUENCY_17M 17857100
1115+ #define THC_SPI_FREQUENCY_20M 20833000
1116+ #define THC_SPI_FREQUENCY_25M 25000000
1117+ #define THC_SPI_FREQUENCY_31M 31250000
1118+ #define THC_SPI_FREQUENCY_41M 41666700
1119+
1120+ #define THC_SPI_LOW_FREQUENCY THC_SPI_FREQUENCY_17M
1121+
1122+ static u8 thc_get_spi_freq_div_val (struct thc_device * dev , u32 spi_freq_val )
1123+ {
1124+ int frequency [] = {
1125+ THC_SPI_FREQUENCY_7M ,
1126+ THC_SPI_FREQUENCY_15M ,
1127+ THC_SPI_FREQUENCY_17M ,
1128+ THC_SPI_FREQUENCY_20M ,
1129+ THC_SPI_FREQUENCY_25M ,
1130+ THC_SPI_FREQUENCY_31M ,
1131+ THC_SPI_FREQUENCY_41M ,
1132+ };
1133+ u8 frequency_div [] = {
1134+ THC_SPI_FRQ_DIV_2 ,
1135+ THC_SPI_FRQ_DIV_1 ,
1136+ THC_SPI_FRQ_DIV_7 ,
1137+ THC_SPI_FRQ_DIV_6 ,
1138+ THC_SPI_FRQ_DIV_5 ,
1139+ THC_SPI_FRQ_DIV_4 ,
1140+ THC_SPI_FRQ_DIV_3 ,
1141+ };
1142+ int size = ARRAY_SIZE (frequency );
1143+ u32 closest_freq ;
1144+ u8 freq_div ;
1145+ int i ;
1146+
1147+ for (i = size - 1 ; i >= 0 ; i -- )
1148+ if ((int )spi_freq_val - frequency [i ] >= 0 )
1149+ break ;
1150+
1151+ if (i < 0 ) {
1152+ dev_err_once (dev -> dev , "Not supported SPI frequency %d\n" , spi_freq_val );
1153+ return THC_SPI_FRQ_RESERVED ;
1154+ }
1155+
1156+ closest_freq = frequency [i ];
1157+ freq_div = frequency_div [i ];
1158+
1159+ dev_dbg (dev -> dev ,
1160+ "Setting SPI frequency: spi_freq_val = %u, Closest freq = %u\n" ,
1161+ spi_freq_val , closest_freq );
1162+
1163+ return freq_div ;
1164+ }
1165+
1166+ /**
1167+ * thc_spi_read_config - Configure SPI bus read attributes
1168+ *
1169+ * @dev: The pointer of THC private device context
1170+ * @spi_freq_val: SPI read frequecy value
1171+ * @io_mode: SPI read IO mode
1172+ * @opcode: Read opcode
1173+ * @spi_rd_mps: SPI read max packet size
1174+ *
1175+ * Return: 0 on success, other error codes on failed.
1176+ */
1177+ int thc_spi_read_config (struct thc_device * dev , u32 spi_freq_val ,
1178+ u32 io_mode , u32 opcode , u32 spi_rd_mps )
1179+ {
1180+ bool is_low_freq = false;
1181+ u32 cfg , mask ;
1182+ u8 freq_div ;
1183+
1184+ freq_div = thc_get_spi_freq_div_val (dev , spi_freq_val );
1185+ if (freq_div == THC_SPI_FRQ_RESERVED )
1186+ return - EINVAL ;
1187+
1188+ if (spi_freq_val < THC_SPI_LOW_FREQUENCY )
1189+ is_low_freq = true;
1190+
1191+ cfg = FIELD_PREP (THC_M_PRT_SPI_CFG_SPI_TCRF , freq_div ) |
1192+ FIELD_PREP (THC_M_PRT_SPI_CFG_SPI_TRMODE , io_mode ) |
1193+ (is_low_freq ? THC_M_PRT_SPI_CFG_SPI_LOW_FREQ_EN : 0 ) |
1194+ FIELD_PREP (THC_M_PRT_SPI_CFG_SPI_RD_MPS , spi_rd_mps );
1195+ mask = THC_M_PRT_SPI_CFG_SPI_TCRF |
1196+ THC_M_PRT_SPI_CFG_SPI_TRMODE |
1197+ THC_M_PRT_SPI_CFG_SPI_LOW_FREQ_EN |
1198+ THC_M_PRT_SPI_CFG_SPI_RD_MPS ;
1199+
1200+ regmap_write_bits (dev -> thc_regmap ,
1201+ THC_M_PRT_SPI_CFG_OFFSET , mask , cfg );
1202+
1203+ if (io_mode == THC_QUAD_IO )
1204+ opcode = FIELD_PREP (THC_M_PRT_SPI_ICRRD_OPCODE_SPI_QIO , opcode );
1205+ else if (io_mode == THC_DUAL_IO )
1206+ opcode = FIELD_PREP (THC_M_PRT_SPI_ICRRD_OPCODE_SPI_DIO , opcode );
1207+ else
1208+ opcode = FIELD_PREP (THC_M_PRT_SPI_ICRRD_OPCODE_SPI_SIO , opcode );
1209+
1210+ regmap_write (dev -> thc_regmap , THC_M_PRT_SPI_ICRRD_OPCODE_OFFSET , opcode );
1211+ regmap_write (dev -> thc_regmap , THC_M_PRT_SPI_DMARD_OPCODE_OFFSET , opcode );
1212+
1213+ return 0 ;
1214+ }
1215+ EXPORT_SYMBOL_NS_GPL (thc_spi_read_config , "INTEL_THC" );
1216+
1217+ /**
1218+ * thc_spi_write_config - Configure SPI bus write attributes
1219+ *
1220+ * @dev: The pointer of THC private device context
1221+ * @spi_freq_val: SPI write frequecy value
1222+ * @io_mode: SPI write IO mode
1223+ * @opcode: Write opcode
1224+ * @spi_wr_mps: SPI write max packet size
1225+ * @perf_limit: Performance limitation in unit of 10us
1226+ *
1227+ * Return: 0 on success, other error codes on failed.
1228+ */
1229+ int thc_spi_write_config (struct thc_device * dev , u32 spi_freq_val ,
1230+ u32 io_mode , u32 opcode , u32 spi_wr_mps ,
1231+ u32 perf_limit )
1232+ {
1233+ bool is_low_freq = false;
1234+ u32 cfg , mask ;
1235+ u8 freq_div ;
1236+
1237+ freq_div = thc_get_spi_freq_div_val (dev , spi_freq_val );
1238+ if (freq_div == THC_SPI_FRQ_RESERVED )
1239+ return - EINVAL ;
1240+
1241+ if (spi_freq_val < THC_SPI_LOW_FREQUENCY )
1242+ is_low_freq = true;
1243+
1244+ cfg = FIELD_PREP (THC_M_PRT_SPI_CFG_SPI_TCWF , freq_div ) |
1245+ FIELD_PREP (THC_M_PRT_SPI_CFG_SPI_TWMODE , io_mode ) |
1246+ (is_low_freq ? THC_M_PRT_SPI_CFG_SPI_LOW_FREQ_EN : 0 ) |
1247+ FIELD_PREP (THC_M_PRT_SPI_CFG_SPI_WR_MPS , spi_wr_mps );
1248+ mask = THC_M_PRT_SPI_CFG_SPI_TCWF |
1249+ THC_M_PRT_SPI_CFG_SPI_TWMODE |
1250+ THC_M_PRT_SPI_CFG_SPI_LOW_FREQ_EN |
1251+ THC_M_PRT_SPI_CFG_SPI_WR_MPS ;
1252+
1253+ regmap_write_bits (dev -> thc_regmap ,
1254+ THC_M_PRT_SPI_CFG_OFFSET , mask , cfg );
1255+
1256+ if (io_mode == THC_QUAD_IO )
1257+ opcode = FIELD_PREP (THC_M_PRT_SPI_ICRRD_OPCODE_SPI_QIO , opcode );
1258+ else if (io_mode == THC_DUAL_IO )
1259+ opcode = FIELD_PREP (THC_M_PRT_SPI_ICRRD_OPCODE_SPI_DIO , opcode );
1260+ else
1261+ opcode = FIELD_PREP (THC_M_PRT_SPI_ICRRD_OPCODE_SPI_SIO , opcode );
1262+
1263+ regmap_write (dev -> thc_regmap , THC_M_PRT_SPI_WR_OPCODE_OFFSET , opcode );
1264+
1265+ dev -> perf_limit = perf_limit ;
1266+
1267+ return 0 ;
1268+ }
1269+ EXPORT_SYMBOL_NS_GPL (thc_spi_write_config , "INTEL_THC" );
1270+
1271+ /**
1272+ * thc_spi_input_output_address_config - Configure SPI input and output addresses
1273+ *
1274+ * @dev: the pointer of THC private device context
1275+ * @input_hdr_addr: input report header address
1276+ * @input_bdy_addr: input report body address
1277+ * @output_addr: output report address
1278+ */
1279+ void thc_spi_input_output_address_config (struct thc_device * dev , u32 input_hdr_addr ,
1280+ u32 input_bdy_addr , u32 output_addr )
1281+ {
1282+ regmap_write (dev -> thc_regmap ,
1283+ THC_M_PRT_DEV_INT_CAUSE_ADDR_OFFSET , input_hdr_addr );
1284+ regmap_write (dev -> thc_regmap ,
1285+ THC_M_PRT_RD_BULK_ADDR_1_OFFSET , input_bdy_addr );
1286+ regmap_write (dev -> thc_regmap ,
1287+ THC_M_PRT_RD_BULK_ADDR_2_OFFSET , input_bdy_addr );
1288+ regmap_write (dev -> thc_regmap ,
1289+ THC_M_PRT_WR_BULK_ADDR_OFFSET , output_addr );
1290+ }
1291+ EXPORT_SYMBOL_NS_GPL (thc_spi_input_output_address_config , "INTEL_THC" );
1292+
10641293MODULE_AUTHOR (
"Xinpeng Sun <[email protected] >" );
10651294MODULE_AUTHOR (
"Even Xu <[email protected] >" );
10661295
0 commit comments