@@ -1061,6 +1061,235 @@ int thc_interrupt_handler(struct thc_device *dev)
1061
1061
}
1062
1062
EXPORT_SYMBOL_NS_GPL (thc_interrupt_handler , "INTEL_THC" );
1063
1063
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
+
1064
1293
MODULE_AUTHOR (
"Xinpeng Sun <[email protected] >" );
1065
1294
MODULE_AUTHOR (
"Even Xu <[email protected] >" );
1066
1295
0 commit comments