102
102
#define IQS269_MISC_B_TRACKING_UI_ENABLE BIT(4)
103
103
#define IQS269_MISC_B_FILT_STR_SLIDER GENMASK(1, 0)
104
104
105
+ #define IQS269_TOUCH_HOLD_SLIDER_SEL 0x89
106
+ #define IQS269_TOUCH_HOLD_DEFAULT 0x14
107
+ #define IQS269_TOUCH_HOLD_MS_MIN 256
108
+ #define IQS269_TOUCH_HOLD_MS_MAX 65280
109
+
105
110
#define IQS269_TIMEOUT_TAP_MS_MAX 4080
106
111
#define IQS269_TIMEOUT_SWIPE_MS_MAX 4080
107
112
#define IQS269_THRESH_SWIPE_MAX 255
151
156
152
157
#define IQS269_MAX_REG 0xFF
153
158
159
+ #define IQS269_OTP_OPTION_DEFAULT 0x00
160
+ #define IQS269_OTP_OPTION_TWS 0xD0
161
+ #define IQS269_OTP_OPTION_HOLD BIT(7)
162
+
154
163
#define IQS269_NUM_CH 8
155
164
#define IQS269_NUM_SL 2
156
165
@@ -315,6 +324,7 @@ struct iqs269_private {
315
324
struct input_dev * slider [IQS269_NUM_SL ];
316
325
unsigned int keycode [ARRAY_SIZE (iqs269_events ) * IQS269_NUM_CH ];
317
326
unsigned int sl_code [IQS269_NUM_SL ][IQS269_NUM_GESTURES ];
327
+ unsigned int otp_option ;
318
328
unsigned int ch_num ;
319
329
bool hall_enable ;
320
330
bool ati_current ;
@@ -325,6 +335,14 @@ static enum iqs269_slider_id iqs269_slider_type(struct iqs269_private *iqs269,
325
335
{
326
336
int i ;
327
337
338
+ /*
339
+ * Slider 1 is unavailable if the touch-and-hold option is enabled via
340
+ * OTP. In that case, the channel selection register is repurposed for
341
+ * the touch-and-hold timer ceiling.
342
+ */
343
+ if (slider_num && (iqs269 -> otp_option & IQS269_OTP_OPTION_HOLD ))
344
+ return IQS269_SLIDER_NONE ;
345
+
328
346
if (!iqs269 -> sys_reg .slider_select [slider_num ])
329
347
return IQS269_SLIDER_NONE ;
330
348
@@ -565,7 +583,8 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269,
565
583
if (fwnode_property_present (ch_node , "azoteq,slider0-select" ))
566
584
iqs269 -> sys_reg .slider_select [0 ] |= BIT (reg );
567
585
568
- if (fwnode_property_present (ch_node , "azoteq,slider1-select" ))
586
+ if (fwnode_property_present (ch_node , "azoteq,slider1-select" ) &&
587
+ !(iqs269 -> otp_option & IQS269_OTP_OPTION_HOLD ))
569
588
iqs269 -> sys_reg .slider_select [1 ] |= BIT (reg );
570
589
571
590
ch_reg = & iqs269 -> sys_reg .ch_reg [reg ];
@@ -990,7 +1009,43 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)
990
1009
sys_reg -> blocking = 0 ;
991
1010
992
1011
sys_reg -> slider_select [0 ] = 0 ;
993
- sys_reg -> slider_select [1 ] = 0 ;
1012
+
1013
+ /*
1014
+ * If configured via OTP to do so, the device asserts a pulse on the
1015
+ * GPIO4 pin for approximately 60 ms once a selected channel is held
1016
+ * in a state of touch for a configurable length of time.
1017
+ *
1018
+ * In that case, the register used for slider 1 channel selection is
1019
+ * repurposed for the touch-and-hold timer ceiling.
1020
+ */
1021
+ if (iqs269 -> otp_option & IQS269_OTP_OPTION_HOLD ) {
1022
+ if (!device_property_read_u32 (& client -> dev ,
1023
+ "azoteq,touch-hold-ms" , & val )) {
1024
+ if (val < IQS269_TOUCH_HOLD_MS_MIN ||
1025
+ val > IQS269_TOUCH_HOLD_MS_MAX ) {
1026
+ dev_err (& client -> dev ,
1027
+ "Invalid touch-and-hold ceiling: %u\n" ,
1028
+ val );
1029
+ return - EINVAL ;
1030
+ }
1031
+
1032
+ sys_reg -> slider_select [1 ] = val / 256 ;
1033
+ } else if (iqs269 -> ver_info .fw_num < IQS269_VER_INFO_FW_NUM_3 ) {
1034
+ /*
1035
+ * The default touch-and-hold timer ceiling initially
1036
+ * read from early revisions of silicon is invalid if
1037
+ * the device experienced a soft reset between power-
1038
+ * on and the read operation.
1039
+ *
1040
+ * To protect against this case, explicitly cache the
1041
+ * default value so that it is restored each time the
1042
+ * device is re-initialized.
1043
+ */
1044
+ sys_reg -> slider_select [1 ] = IQS269_TOUCH_HOLD_DEFAULT ;
1045
+ }
1046
+ } else {
1047
+ sys_reg -> slider_select [1 ] = 0 ;
1048
+ }
994
1049
995
1050
sys_reg -> event_mask = ~((u8 )IQS269_EVENT_MASK_SYS );
996
1051
@@ -1137,12 +1192,30 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)
1137
1192
return 0 ;
1138
1193
}
1139
1194
1195
+ static const struct reg_sequence iqs269_tws_init [] = {
1196
+ { IQS269_TOUCH_HOLD_SLIDER_SEL , IQS269_TOUCH_HOLD_DEFAULT },
1197
+ { 0xF0 , 0x580F },
1198
+ { 0xF0 , 0x59EF },
1199
+ };
1200
+
1140
1201
static int iqs269_dev_init (struct iqs269_private * iqs269 )
1141
1202
{
1142
1203
int error ;
1143
1204
1144
1205
mutex_lock (& iqs269 -> lock );
1145
1206
1207
+ /*
1208
+ * Early revisions of silicon require the following workaround in order
1209
+ * to restore any OTP-enabled functionality after a soft reset.
1210
+ */
1211
+ if (iqs269 -> otp_option == IQS269_OTP_OPTION_TWS &&
1212
+ iqs269 -> ver_info .fw_num < IQS269_VER_INFO_FW_NUM_3 ) {
1213
+ error = regmap_multi_reg_write (iqs269 -> regmap , iqs269_tws_init ,
1214
+ ARRAY_SIZE (iqs269_tws_init ));
1215
+ if (error )
1216
+ goto err_mutex ;
1217
+ }
1218
+
1146
1219
error = regmap_update_bits (iqs269 -> regmap , IQS269_HALL_UI ,
1147
1220
IQS269_HALL_UI_ENABLE ,
1148
1221
iqs269 -> hall_enable ? ~0 : 0 );
@@ -1779,6 +1852,8 @@ static int iqs269_probe(struct i2c_client *client)
1779
1852
mutex_init (& iqs269 -> lock );
1780
1853
init_completion (& iqs269 -> ati_done );
1781
1854
1855
+ iqs269 -> otp_option = (uintptr_t )device_get_match_data (& client -> dev );
1856
+
1782
1857
error = regmap_raw_read (iqs269 -> regmap , IQS269_VER_INFO ,
1783
1858
& iqs269 -> ver_info , sizeof (iqs269 -> ver_info ));
1784
1859
if (error )
@@ -1889,7 +1964,18 @@ static int iqs269_resume(struct device *dev)
1889
1964
static DEFINE_SIMPLE_DEV_PM_OPS (iqs269_pm , iqs269_suspend , iqs269_resume ) ;
1890
1965
1891
1966
static const struct of_device_id iqs269_of_match [] = {
1892
- { .compatible = "azoteq,iqs269a" },
1967
+ {
1968
+ .compatible = "azoteq,iqs269a" ,
1969
+ .data = (void * )IQS269_OTP_OPTION_DEFAULT ,
1970
+ },
1971
+ {
1972
+ .compatible = "azoteq,iqs269a-00" ,
1973
+ .data = (void * )IQS269_OTP_OPTION_DEFAULT ,
1974
+ },
1975
+ {
1976
+ .compatible = "azoteq,iqs269a-d0" ,
1977
+ .data = (void * )IQS269_OTP_OPTION_TWS ,
1978
+ },
1893
1979
{ }
1894
1980
};
1895
1981
MODULE_DEVICE_TABLE (of , iqs269_of_match );
0 commit comments