Lines Matching +full:bit +full:- +full:mask
1 // SPDX-License-Identifier: GPL-2.0+
3 * Azoteq IQS620A/621/622/624/625 Multi-Function Sensors
7 * These devices rely on application-specific register settings and calibration
9 * separate tool converts the GUIs' ASCII-based output into a standard firmware
14 * Link to conversion tool: https://github.com/jlabundy/iqs62x-h2bin.git
49 #define IQS620_PROX_SETTINGS_4_SAR_EN BIT(7)
59 #define IQS62X_SYS_SETTINGS_ACK_RESET BIT(6)
60 #define IQS62X_SYS_SETTINGS_EVENT_MODE BIT(5)
61 #define IQS62X_SYS_SETTINGS_CLK_DIV BIT(4)
62 #define IQS62X_SYS_SETTINGS_COMM_ATI BIT(3)
63 #define IQS62X_SYS_SETTINGS_REDO_ATI BIT(1)
66 #define IQS62X_PWR_SETTINGS_DIS_AUTO BIT(5)
67 #define IQS62X_PWR_SETTINGS_PWR_MODE_MASK (BIT(4) | BIT(3))
68 #define IQS62X_PWR_SETTINGS_PWR_MODE_HALT (BIT(4) | BIT(3))
97 u8 mask; member
114 list_for_each_entry(fw_blk, &iqs62x->fw_blk_head, list) { in iqs62x_dev_init()
119 if (fw_blk->addr == IQS62X_SYS_SETTINGS && in iqs62x_dev_init()
120 *fw_blk->data & IQS62X_SYS_SETTINGS_CLK_DIV) in iqs62x_dev_init()
123 if (fw_blk->mask) in iqs62x_dev_init()
124 ret = regmap_update_bits(iqs62x->regmap, fw_blk->addr, in iqs62x_dev_init()
125 fw_blk->mask, *fw_blk->data); in iqs62x_dev_init()
127 ret = regmap_raw_write(iqs62x->regmap, fw_blk->addr, in iqs62x_dev_init()
128 fw_blk->data, fw_blk->len); in iqs62x_dev_init()
133 switch (iqs62x->dev_desc->prod_num) { in iqs62x_dev_init()
136 ret = regmap_read(iqs62x->regmap, in iqs62x_dev_init()
137 iqs62x->dev_desc->prox_settings, &val); in iqs62x_dev_init()
142 iqs62x->ui_sel = IQS62X_UI_SAR1; in iqs62x_dev_init()
146 ret = regmap_write(iqs62x->regmap, IQS620_GLBL_EVENT_MASK, in iqs62x_dev_init()
148 iqs62x->dev_desc->prox_mask | in iqs62x_dev_init()
149 iqs62x->dev_desc->sar_mask | in iqs62x_dev_init()
150 iqs62x->dev_desc->hall_mask | in iqs62x_dev_init()
151 iqs62x->dev_desc->hyst_mask | in iqs62x_dev_init()
152 iqs62x->dev_desc->temp_mask | in iqs62x_dev_init()
153 iqs62x->dev_desc->als_mask | in iqs62x_dev_init()
154 iqs62x->dev_desc->ir_mask); in iqs62x_dev_init()
160 ret = regmap_write(iqs62x->regmap, IQS624_HALL_UI, in iqs62x_dev_init()
173 * To protect against an unacceptably low user-entered value in iqs62x_dev_init()
177 ret = regmap_read(iqs62x->regmap, IQS624_INTERVAL_DIV, &val); in iqs62x_dev_init()
181 if (val >= iqs62x->dev_desc->interval_div) in iqs62x_dev_init()
184 ret = regmap_write(iqs62x->regmap, IQS624_INTERVAL_DIV, in iqs62x_dev_init()
185 iqs62x->dev_desc->interval_div); in iqs62x_dev_init()
196 * In the meantime, mask interrupts during ATI to prevent the device in iqs62x_dev_init()
197 * from soliciting I2C traffic until the noise-sensitive ATI process in iqs62x_dev_init()
200 ret = regmap_update_bits(iqs62x->regmap, IQS62X_SYS_SETTINGS, in iqs62x_dev_init()
223 struct i2c_client *client = iqs62x->client; in iqs62x_firmware_parse()
229 u8 mask, len, *data; in iqs62x_firmware_parse() local
232 while (pos < fw->size) { in iqs62x_firmware_parse()
233 if (pos + sizeof(*fw_rec) > fw->size) { in iqs62x_firmware_parse()
234 ret = -EINVAL; in iqs62x_firmware_parse()
237 fw_rec = (struct iqs62x_fw_rec *)(fw->data + pos); in iqs62x_firmware_parse()
240 if (pos + fw_rec->len - 1 > fw->size) { in iqs62x_firmware_parse()
241 ret = -EINVAL; in iqs62x_firmware_parse()
244 pos += fw_rec->len - 1; in iqs62x_firmware_parse()
246 switch (fw_rec->type) { in iqs62x_firmware_parse()
251 if (fw_rec->data == iqs62x->dev_desc->prod_num) in iqs62x_firmware_parse()
254 dev_err(&client->dev, in iqs62x_firmware_parse()
256 fw_rec->data); in iqs62x_firmware_parse()
257 ret = -EINVAL; in iqs62x_firmware_parse()
262 ret = regmap_write(iqs62x->regmap, in iqs62x_firmware_parse()
268 ret = regmap_read(iqs62x->regmap, in iqs62x_firmware_parse()
275 dev_err(&client->dev, in iqs62x_firmware_parse()
277 ret = -ENODATA; in iqs62x_firmware_parse()
282 if (hall_cal_index > fw_rec->len) { in iqs62x_firmware_parse()
283 ret = -EINVAL; in iqs62x_firmware_parse()
287 mask = 0; in iqs62x_firmware_parse()
288 data = &fw_rec->data + hall_cal_index - 1; in iqs62x_firmware_parse()
293 if (fw_rec->len < (sizeof(mask) + sizeof(*data))) { in iqs62x_firmware_parse()
294 ret = -EINVAL; in iqs62x_firmware_parse()
298 mask = fw_rec->data; in iqs62x_firmware_parse()
299 data = &fw_rec->data + sizeof(mask); in iqs62x_firmware_parse()
304 mask = 0; in iqs62x_firmware_parse()
305 data = &fw_rec->data; in iqs62x_firmware_parse()
306 len = fw_rec->len; in iqs62x_firmware_parse()
310 dev_err(&client->dev, in iqs62x_firmware_parse()
312 fw_rec->type); in iqs62x_firmware_parse()
313 ret = -EINVAL; in iqs62x_firmware_parse()
319 fw_blk = devm_kzalloc(&client->dev, in iqs62x_firmware_parse()
323 ret = -ENOMEM; in iqs62x_firmware_parse()
327 fw_blk->addr = fw_rec->addr; in iqs62x_firmware_parse()
328 fw_blk->mask = mask; in iqs62x_firmware_parse()
329 fw_blk->len = len; in iqs62x_firmware_parse()
330 memcpy(fw_blk->data, data, len); in iqs62x_firmware_parse()
332 list_add(&fw_blk->list, &iqs62x->fw_blk_head); in iqs62x_firmware_parse()
343 .mask = BIT(4),
344 .val = BIT(4),
348 .mask = BIT(0),
349 .val = BIT(0),
353 .mask = BIT(5),
354 .val = BIT(5),
358 .mask = BIT(1),
359 .val = BIT(1),
363 .mask = BIT(6),
364 .val = BIT(6),
368 .mask = BIT(2),
369 .val = BIT(2),
373 .mask = BIT(6) | BIT(7),
374 .val = BIT(6),
378 .mask = BIT(5) | BIT(7),
379 .val = BIT(5),
383 .mask = BIT(6) | BIT(7),
384 .val = BIT(6) | BIT(7),
388 .mask = BIT(5) | BIT(7),
389 .val = BIT(5) | BIT(7),
393 .mask = BIT(4),
394 .val = BIT(4),
398 .mask = BIT(2),
399 .val = BIT(2),
403 .mask = BIT(1),
404 .val = BIT(1),
408 .mask = BIT(0),
409 .val = BIT(0),
413 .mask = BIT(7) | BIT(6),
414 .val = BIT(7),
418 .mask = BIT(7) | BIT(6),
419 .val = BIT(7) | BIT(6),
423 .mask = BIT(2) | BIT(0),
424 .val = BIT(2),
428 .mask = BIT(1) | BIT(0),
429 .val = BIT(1),
433 .mask = BIT(2) | BIT(0),
434 .val = BIT(2) | BIT(0),
438 .mask = BIT(1) | BIT(0),
439 .val = BIT(1) | BIT(0),
443 .mask = BIT(7),
444 .val = BIT(7),
448 .mask = BIT(2),
449 .val = BIT(2),
457 struct i2c_client *client = iqs62x->client; in iqs62x_irq()
469 * broadcast to any interested sub-device drivers. in iqs62x_irq()
471 ret = regmap_raw_read(iqs62x->regmap, IQS62X_SYS_FLAGS, event_map, in iqs62x_irq()
474 dev_err(&client->dev, "Failed to read device status: %d\n", in iqs62x_irq()
480 event_reg = iqs62x->dev_desc->event_regs[iqs62x->ui_sel][i]; in iqs62x_irq()
504 event_map[i] <<= iqs62x->dev_desc->hyst_shift; in iqs62x_irq()
520 if ((event_map[i] & event_desc.mask) == event_desc.val) in iqs62x_irq()
521 event_flags |= BIT(j); in iqs62x_irq()
528 * are restored and any interested sub-device drivers are notified. in iqs62x_irq()
530 if (event_flags & BIT(IQS62X_EVENT_SYS_RESET)) { in iqs62x_irq()
531 dev_err(&client->dev, "Unexpected device reset\n"); in iqs62x_irq()
535 dev_err(&client->dev, in iqs62x_irq()
536 "Failed to re-initialize device: %d\n", ret); in iqs62x_irq()
540 iqs62x->event_cache |= BIT(IQS62X_EVENT_SYS_RESET); in iqs62x_irq()
541 reinit_completion(&iqs62x->ati_done); in iqs62x_irq()
542 } else if (event_flags & BIT(IQS62X_EVENT_SYS_ATI)) { in iqs62x_irq()
543 iqs62x->event_cache |= BIT(IQS62X_EVENT_SYS_ATI); in iqs62x_irq()
544 reinit_completion(&iqs62x->ati_done); in iqs62x_irq()
545 } else if (!completion_done(&iqs62x->ati_done)) { in iqs62x_irq()
546 ret = regmap_update_bits(iqs62x->regmap, IQS62X_SYS_SETTINGS, in iqs62x_irq()
549 dev_err(&client->dev, in iqs62x_irq()
555 complete_all(&iqs62x->ati_done); in iqs62x_irq()
559 * Reset and ATI events are not broadcast to the sub-device drivers in iqs62x_irq()
563 if (completion_done(&iqs62x->ati_done)) { in iqs62x_irq()
564 event_flags |= iqs62x->event_cache; in iqs62x_irq()
565 ret = blocking_notifier_call_chain(&iqs62x->nh, event_flags, in iqs62x_irq()
570 iqs62x->event_cache = 0; in iqs62x_irq()
586 struct i2c_client *client = iqs62x->client; in iqs62x_firmware_load()
592 dev_err(&client->dev, "Failed to parse firmware: %d\n", in iqs62x_firmware_load()
600 dev_err(&client->dev, "Failed to initialize device: %d\n", ret); in iqs62x_firmware_load()
604 ret = devm_request_threaded_irq(&client->dev, client->irq, in iqs62x_firmware_load()
606 client->name, iqs62x); in iqs62x_firmware_load()
608 dev_err(&client->dev, "Failed to request IRQ: %d\n", ret); in iqs62x_firmware_load()
612 if (!wait_for_completion_timeout(&iqs62x->ati_done, in iqs62x_firmware_load()
614 dev_err(&client->dev, "Failed to complete ATI\n"); in iqs62x_firmware_load()
618 ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, in iqs62x_firmware_load()
619 iqs62x->dev_desc->sub_devs, in iqs62x_firmware_load()
620 iqs62x->dev_desc->num_sub_devs, in iqs62x_firmware_load()
623 dev_err(&client->dev, "Failed to add sub-devices: %d\n", ret); in iqs62x_firmware_load()
626 complete_all(&iqs62x->fw_done); in iqs62x_firmware_load()
631 .name = "iqs62x-keys",
632 .of_compatible = "azoteq,iqs620a-keys",
635 .name = "iqs620a-pwm",
636 .of_compatible = "azoteq,iqs620a-pwm",
638 { .name = "iqs620at-temp", },
643 .name = "iqs62x-keys",
644 .of_compatible = "azoteq,iqs620a-keys",
647 .name = "iqs620a-pwm",
648 .of_compatible = "azoteq,iqs620a-pwm",
654 .name = "iqs62x-keys",
655 .of_compatible = "azoteq,iqs621-keys",
657 { .name = "iqs621-als", },
662 .name = "iqs62x-keys",
663 .of_compatible = "azoteq,iqs622-keys",
665 { .name = "iqs621-als", },
670 .name = "iqs62x-keys",
671 .of_compatible = "azoteq,iqs624-keys",
673 { .name = "iqs624-pos", },
678 .name = "iqs62x-keys",
679 .of_compatible = "azoteq,iqs625-keys",
681 { .name = "iqs624-pos", },
803 .prox_mask = BIT(0),
804 .sar_mask = BIT(1) | BIT(7),
805 .hall_mask = BIT(2),
806 .hyst_mask = BIT(3),
807 .temp_mask = BIT(4),
819 .prox_mask = BIT(0),
820 .sar_mask = BIT(1) | BIT(7),
821 .hall_mask = BIT(2),
822 .hyst_mask = BIT(3),
823 .temp_mask = BIT(4),
837 .prox_mask = BIT(0),
838 .hall_mask = BIT(1),
839 .als_mask = BIT(2),
840 .hyst_mask = BIT(3),
841 .temp_mask = BIT(4),
854 .prox_mask = BIT(0),
855 .sar_mask = BIT(1),
856 .hall_mask = BIT(2),
857 .als_mask = BIT(3),
858 .ir_mask = BIT(4),
903 iqs62x = devm_kzalloc(&client->dev, sizeof(*iqs62x), GFP_KERNEL); in iqs62x_probe()
905 return -ENOMEM; in iqs62x_probe()
908 iqs62x->client = client; in iqs62x_probe()
910 BLOCKING_INIT_NOTIFIER_HEAD(&iqs62x->nh); in iqs62x_probe()
911 INIT_LIST_HEAD(&iqs62x->fw_blk_head); in iqs62x_probe()
913 init_completion(&iqs62x->ati_done); in iqs62x_probe()
914 init_completion(&iqs62x->fw_done); in iqs62x_probe()
916 iqs62x->regmap = devm_regmap_init_i2c(client, &iqs62x_regmap_config); in iqs62x_probe()
917 if (IS_ERR(iqs62x->regmap)) { in iqs62x_probe()
918 ret = PTR_ERR(iqs62x->regmap); in iqs62x_probe()
919 dev_err(&client->dev, "Failed to initialize register map: %d\n", in iqs62x_probe()
924 ret = regmap_raw_read(iqs62x->regmap, IQS62X_PROD_NUM, &info, in iqs62x_probe()
931 * numbers. It then determines if the device is factory-calibrated by in iqs62x_probe()
946 iqs62x->dev_desc = &iqs62x_devs[i]; in iqs62x_probe()
948 if (info.sw_num < iqs62x->dev_desc->sw_num) in iqs62x_probe()
951 iqs62x->sw_num = info.sw_num; in iqs62x_probe()
952 iqs62x->hw_num = info.hw_num; in iqs62x_probe()
961 for (j = 0; j < iqs62x->dev_desc->num_cal_regs; j++) { in iqs62x_probe()
962 ret = regmap_read(iqs62x->regmap, in iqs62x_probe()
963 iqs62x->dev_desc->cal_regs[j], &val); in iqs62x_probe()
978 if (j == iqs62x->dev_desc->num_cal_regs) in iqs62x_probe()
982 if (!iqs62x->dev_desc) { in iqs62x_probe()
983 dev_err(&client->dev, "Unrecognized product number: 0x%02X\n", in iqs62x_probe()
985 return -EINVAL; in iqs62x_probe()
988 if (!iqs62x->sw_num) { in iqs62x_probe()
989 dev_err(&client->dev, "Unrecognized software number: 0x%02X\n", in iqs62x_probe()
991 return -EINVAL; in iqs62x_probe()
995 dev_err(&client->dev, "Uncalibrated device\n"); in iqs62x_probe()
996 return -ENODATA; in iqs62x_probe()
999 device_property_read_string(&client->dev, "firmware-name", &fw_name); in iqs62x_probe()
1002 fw_name ? : iqs62x->dev_desc->fw_name, in iqs62x_probe()
1003 &client->dev, GFP_KERNEL, iqs62x, in iqs62x_probe()
1006 dev_err(&client->dev, "Failed to request firmware: %d\n", ret); in iqs62x_probe()
1015 wait_for_completion(&iqs62x->fw_done); in iqs62x_remove()
1023 wait_for_completion(&iqs62x->fw_done); in iqs62x_suspend()
1029 ret = regmap_update_bits(iqs62x->regmap, IQS62X_PWR_SETTINGS, in iqs62x_suspend()
1034 return regmap_update_bits(iqs62x->regmap, IQS62X_PWR_SETTINGS, in iqs62x_suspend()
1044 ret = regmap_update_bits(iqs62x->regmap, IQS62X_PWR_SETTINGS, in iqs62x_resume()
1050 return regmap_update_bits(iqs62x->regmap, IQS62X_PWR_SETTINGS, in iqs62x_resume()
1078 MODULE_DESCRIPTION("Azoteq IQS620A/621/622/624/625 Multi-Function Sensors");