#define IQS62X_PROD_NUM                                0x00
 
 #define IQS62X_SYS_FLAGS                       0x10
-#define IQS62X_SYS_FLAGS_IN_ATI                        BIT(2)
 
 #define IQS620_HALL_FLAGS                      0x16
 #define IQS621_HALL_FLAGS                      0x19
 #define IQS62X_SYS_SETTINGS_ACK_RESET          BIT(6)
 #define IQS62X_SYS_SETTINGS_EVENT_MODE         BIT(5)
 #define IQS62X_SYS_SETTINGS_CLK_DIV            BIT(4)
+#define IQS62X_SYS_SETTINGS_COMM_ATI           BIT(3)
 #define IQS62X_SYS_SETTINGS_REDO_ATI           BIT(1)
 
 #define IQS62X_PWR_SETTINGS                    0xD2
 #define IQS62X_FW_REC_TYPE_MASK                        3
 #define IQS62X_FW_REC_TYPE_DATA                        4
 
-#define IQS62X_ATI_POLL_SLEEP_US               10000
-#define IQS62X_ATI_POLL_TIMEOUT_US             500000
-#define IQS62X_ATI_STABLE_DELAY_MS             150
+#define IQS62X_FILT_SETTLE_MS                  250
 
 struct iqs62x_fw_rec {
        u8 type;
        struct iqs62x_fw_blk *fw_blk;
        unsigned int val;
        int ret;
-       u8 clk_div = 1;
 
        list_for_each_entry(fw_blk, &iqs62x->fw_blk_head, list) {
                if (fw_blk->mask)
                        return ret;
        }
 
-       ret = regmap_read(iqs62x->regmap, IQS62X_SYS_SETTINGS, &val);
-       if (ret)
-               return ret;
-
-       if (val & IQS62X_SYS_SETTINGS_CLK_DIV)
-               clk_div = iqs62x->dev_desc->clk_div;
-
-       ret = regmap_write(iqs62x->regmap, IQS62X_SYS_SETTINGS, val |
-                          IQS62X_SYS_SETTINGS_ACK_RESET |
-                          IQS62X_SYS_SETTINGS_EVENT_MODE |
-                          IQS62X_SYS_SETTINGS_REDO_ATI);
-       if (ret)
-               return ret;
-
-       ret = regmap_read_poll_timeout(iqs62x->regmap, IQS62X_SYS_FLAGS, val,
-                                      !(val & IQS62X_SYS_FLAGS_IN_ATI),
-                                      IQS62X_ATI_POLL_SLEEP_US,
-                                      IQS62X_ATI_POLL_TIMEOUT_US * clk_div);
+       /*
+        * Place the device in streaming mode at first so as not to miss the
+        * limited number of interrupts that would otherwise occur after ATI
+        * completes. The device is subsequently placed in event mode by the
+        * interrupt handler.
+        *
+        * In the meantime, mask interrupts during ATI to prevent the device
+        * from soliciting I2C traffic until the noise-sensitive ATI process
+        * is complete.
+        */
+       ret = regmap_update_bits(iqs62x->regmap, IQS62X_SYS_SETTINGS,
+                                IQS62X_SYS_SETTINGS_ACK_RESET |
+                                IQS62X_SYS_SETTINGS_EVENT_MODE |
+                                IQS62X_SYS_SETTINGS_COMM_ATI |
+                                IQS62X_SYS_SETTINGS_REDO_ATI,
+                                IQS62X_SYS_SETTINGS_ACK_RESET |
+                                IQS62X_SYS_SETTINGS_REDO_ATI);
        if (ret)
                return ret;
 
-       msleep(IQS62X_ATI_STABLE_DELAY_MS * clk_div);
+       /*
+        * The following delay gives the device time to deassert its RDY output
+        * in case a communication window was open while the REDO_ATI field was
+        * written. This prevents an interrupt from being serviced prematurely.
+        */
+       usleep_range(5000, 5100);
 
        return 0;
 }
                .mask   = BIT(7),
                .val    = BIT(7),
        },
+       [IQS62X_EVENT_SYS_ATI] = {
+               .reg    = IQS62X_EVENT_SYS,
+               .mask   = BIT(2),
+               .val    = BIT(2),
+       },
 };
 EXPORT_SYMBOL_GPL(iqs62x_events);
 
                                "Failed to re-initialize device: %d\n", ret);
                        return IRQ_NONE;
                }
+
+               iqs62x->event_cache |= BIT(IQS62X_EVENT_SYS_RESET);
+               reinit_completion(&iqs62x->ati_done);
+       } else if (event_flags & BIT(IQS62X_EVENT_SYS_ATI)) {
+               iqs62x->event_cache |= BIT(IQS62X_EVENT_SYS_ATI);
+               reinit_completion(&iqs62x->ati_done);
+       } else if (!completion_done(&iqs62x->ati_done)) {
+               ret = regmap_update_bits(iqs62x->regmap, IQS62X_SYS_SETTINGS,
+                                        IQS62X_SYS_SETTINGS_EVENT_MODE, 0xFF);
+               if (ret) {
+                       dev_err(&client->dev,
+                               "Failed to enable event mode: %d\n", ret);
+                       return IRQ_NONE;
+               }
+
+               msleep(IQS62X_FILT_SETTLE_MS);
+               complete_all(&iqs62x->ati_done);
        }
 
-       ret = blocking_notifier_call_chain(&iqs62x->nh, event_flags,
-                                          &event_data);
-       if (ret & NOTIFY_STOP_MASK)
-               return IRQ_NONE;
+       /*
+        * Reset and ATI events are not broadcast to the sub-device drivers
+        * until ATI has completed. Any other events that may have occurred
+        * during ATI are ignored.
+        */
+       if (completion_done(&iqs62x->ati_done)) {
+               event_flags |= iqs62x->event_cache;
+               ret = blocking_notifier_call_chain(&iqs62x->nh, event_flags,
+                                                  &event_data);
+               if (ret & NOTIFY_STOP_MASK)
+                       return IRQ_NONE;
+
+               iqs62x->event_cache = 0;
+       }
 
        /*
         * Once the communication window is closed, a small delay is added to
                goto err_out;
        }
 
+       if (!wait_for_completion_timeout(&iqs62x->ati_done,
+                                        msecs_to_jiffies(2000))) {
+               dev_err(&client->dev, "Failed to complete ATI\n");
+               goto err_out;
+       }
+
        ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
                                   iqs62x->dev_desc->sub_devs,
                                   iqs62x->dev_desc->num_sub_devs,
                .dev_name       = "iqs620at",
                .sub_devs       = iqs620at_sub_devs,
                .num_sub_devs   = ARRAY_SIZE(iqs620at_sub_devs),
-
                .prod_num       = IQS620_PROD_NUM,
                .sw_num         = 0x08,
                .cal_regs       = iqs620at_cal_regs,
                .num_cal_regs   = ARRAY_SIZE(iqs620at_cal_regs),
-
                .prox_mask      = BIT(0),
                .sar_mask       = BIT(1) | BIT(7),
                .hall_mask      = BIT(2),
                .hyst_mask      = BIT(3),
                .temp_mask      = BIT(4),
-
                .prox_settings  = IQS620_PROX_SETTINGS_4,
                .hall_flags     = IQS620_HALL_FLAGS,
-
-               .clk_div        = 4,
                .fw_name        = "iqs620a.bin",
                .event_regs     = &iqs620a_event_regs[IQS62X_UI_PROX],
        },
                .dev_name       = "iqs620a",
                .sub_devs       = iqs620a_sub_devs,
                .num_sub_devs   = ARRAY_SIZE(iqs620a_sub_devs),
-
                .prod_num       = IQS620_PROD_NUM,
                .sw_num         = 0x08,
-
                .prox_mask      = BIT(0),
                .sar_mask       = BIT(1) | BIT(7),
                .hall_mask      = BIT(2),
                .hyst_mask      = BIT(3),
                .temp_mask      = BIT(4),
-
                .prox_settings  = IQS620_PROX_SETTINGS_4,
                .hall_flags     = IQS620_HALL_FLAGS,
-
-               .clk_div        = 4,
                .fw_name        = "iqs620a.bin",
                .event_regs     = &iqs620a_event_regs[IQS62X_UI_PROX],
        },
                .dev_name       = "iqs621",
                .sub_devs       = iqs621_sub_devs,
                .num_sub_devs   = ARRAY_SIZE(iqs621_sub_devs),
-
                .prod_num       = IQS621_PROD_NUM,
                .sw_num         = 0x09,
                .cal_regs       = iqs621_cal_regs,
                .num_cal_regs   = ARRAY_SIZE(iqs621_cal_regs),
-
                .prox_mask      = BIT(0),
                .hall_mask      = BIT(1),
                .als_mask       = BIT(2),
                .hyst_mask      = BIT(3),
                .temp_mask      = BIT(4),
-
                .als_flags      = IQS621_ALS_FLAGS,
                .hall_flags     = IQS621_HALL_FLAGS,
                .hyst_shift     = 5,
-
-               .clk_div        = 2,
                .fw_name        = "iqs621.bin",
                .event_regs     = &iqs621_event_regs[IQS62X_UI_PROX],
        },
                .dev_name       = "iqs622",
                .sub_devs       = iqs622_sub_devs,
                .num_sub_devs   = ARRAY_SIZE(iqs622_sub_devs),
-
                .prod_num       = IQS622_PROD_NUM,
                .sw_num         = 0x06,
-
                .prox_mask      = BIT(0),
                .sar_mask       = BIT(1),
                .hall_mask      = BIT(2),
                .als_mask       = BIT(3),
                .ir_mask        = BIT(4),
-
                .prox_settings  = IQS622_PROX_SETTINGS_4,
                .als_flags      = IQS622_ALS_FLAGS,
                .hall_flags     = IQS622_HALL_FLAGS,
-
-               .clk_div        = 2,
                .fw_name        = "iqs622.bin",
                .event_regs     = &iqs622_event_regs[IQS62X_UI_PROX],
        },
                .dev_name       = "iqs624",
                .sub_devs       = iqs624_sub_devs,
                .num_sub_devs   = ARRAY_SIZE(iqs624_sub_devs),
-
                .prod_num       = IQS624_PROD_NUM,
                .sw_num         = 0x0B,
-
                .interval       = IQS624_INTERVAL_NUM,
                .interval_div   = 3,
-
-               .clk_div        = 2,
                .fw_name        = "iqs624.bin",
                .event_regs     = &iqs624_event_regs[IQS62X_UI_PROX],
        },
                .dev_name       = "iqs625",
                .sub_devs       = iqs625_sub_devs,
                .num_sub_devs   = ARRAY_SIZE(iqs625_sub_devs),
-
                .prod_num       = IQS625_PROD_NUM,
                .sw_num         = 0x0B,
-
                .interval       = IQS625_INTERVAL_NUM,
                .interval_div   = 10,
-
-               .clk_div        = 2,
                .fw_name        = "iqs625.bin",
                .event_regs     = &iqs625_event_regs[IQS62X_UI_PROX],
        },
 
        BLOCKING_INIT_NOTIFIER_HEAD(&iqs62x->nh);
        INIT_LIST_HEAD(&iqs62x->fw_blk_head);
+
+       init_completion(&iqs62x->ati_done);
        init_completion(&iqs62x->fw_done);
 
        iqs62x->regmap = devm_regmap_init_i2c(client, &iqs62x_regmap_config);