Lines Matching +full:ati +full:- +full:mode
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
114 list_for_each_entry(fw_blk, &iqs62x->fw_blk_head, list) { in iqs62x_dev_init()
116 * In case ATI is in progress, wait for it to complete before 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()
191 * Place the device in streaming mode at first so as not to miss the in iqs62x_dev_init()
192 * limited number of interrupts that would otherwise occur after ATI in iqs62x_dev_init()
193 * completes. The device is subsequently placed in event mode by the 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()
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()
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()
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()
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()
528 * are restored and any interested sub-device drivers are notified. 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()
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()
550 "Failed to enable event mode: %d\n", ret); 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()
560 * until ATI has completed. Any other events that may have occurred in iqs62x_irq()
561 * during ATI are ignored. 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", },
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()
1026 * As per the datasheet, automatic mode switching must be disabled in iqs62x_suspend()
1027 * before the device is placed in or taken out of halt mode. 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");