/*
         * Following fields are used to compare equality. If you
         * make adaptations in it, you most likely also have to adapt
-        * ad7173_find_live_config(), too.
+        * ad7173_is_setup_equal(), too.
         */
        struct_group(config_props,
                bool bipolar;
        st->config_usage_counter = 0;
 }
 
-static struct ad7173_channel_config *
-ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *cfg)
+/**
+ * ad7173_is_setup_equal - Compare two channel setups
+ * @cfg1: First channel configuration
+ * @cfg2: Second channel configuration
+ *
+ * Compares all configuration options that affect the registers connected to
+ * SETUP_SEL, namely CONFIGx, FILTERx, GAINx and OFFSETx.
+ *
+ * Returns: true if the setups are identical, false otherwise
+ */
+static bool ad7173_is_setup_equal(const struct ad7173_channel_config *cfg1,
+                                 const struct ad7173_channel_config *cfg2)
 {
-       struct ad7173_channel_config *cfg_aux;
-       int i;
-
        /*
         * This is just to make sure that the comparison is adapted after
         * struct ad7173_channel_config was changed.
                                     u8 ref_sel;
                             }));
 
+       return cfg1->bipolar == cfg2->bipolar &&
+              cfg1->input_buf == cfg2->input_buf &&
+              cfg1->odr == cfg2->odr &&
+              cfg1->ref_sel == cfg2->ref_sel;
+}
+
+static struct ad7173_channel_config *
+ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *cfg)
+{
+       struct ad7173_channel_config *cfg_aux;
+       int i;
+
        for (i = 0; i < st->num_channels; i++) {
                cfg_aux = &st->channels[i].cfg;
 
-               if (cfg_aux->live &&
-                   cfg->bipolar == cfg_aux->bipolar &&
-                   cfg->input_buf == cfg_aux->input_buf &&
-                   cfg->odr == cfg_aux->odr &&
-                   cfg->ref_sel == cfg_aux->ref_sel)
+               if (cfg_aux->live && ad7173_is_setup_equal(cfg, cfg_aux))
                        return cfg_aux;
        }
        return NULL;
                                   const unsigned long *scan_mask)
 {
        struct ad7173_state *st = iio_priv(indio_dev);
-       int i, ret;
+       int i, j, k, ret;
 
        for (i = 0; i < indio_dev->num_channels; i++) {
                if (test_bit(i, scan_mask))
                        return ret;
        }
 
+       /*
+        * On some chips, there are more channels that setups, so if there were
+        * more unique setups requested than the number of available slots,
+        * ad7173_set_channel() will have written over some of the slots. We
+        * can detect this by making sure each assigned cfg_slot matches the
+        * requested configuration. If it doesn't, we know that the slot was
+        * overwritten by a different channel.
+        */
+       for_each_set_bit(i, scan_mask, indio_dev->num_channels) {
+               const struct ad7173_channel_config *cfg1, *cfg2;
+
+               cfg1 = &st->channels[i].cfg;
+
+               for_each_set_bit(j, scan_mask, indio_dev->num_channels) {
+                       cfg2 = &st->channels[j].cfg;
+
+                       /*
+                        * Only compare configs that are assigned to the same
+                        * SETUP_SEL slot and don't compare channel to itself.
+                        */
+                       if (i == j || cfg1->cfg_slot != cfg2->cfg_slot)
+                               continue;
+
+                       /*
+                        * If we find two different configs trying to use the
+                        * same SETUP_SEL slot, then we know that the that we
+                        * have too many unique configurations requested for
+                        * the available slots and at least one was overwritten.
+                        */
+                       if (!ad7173_is_setup_equal(cfg1, cfg2)) {
+                               /*
+                                * At this point, there isn't a way to tell
+                                * which setups are actually programmed in the
+                                * ADC anymore, so we could read them back to
+                                * see, but it is simpler to just turn off all
+                                * of the live flags so that everything gets
+                                * reprogramed on the next attempt read a sample.
+                                */
+                               for (k = 0; k < st->num_channels; k++)
+                                       st->channels[k].cfg.live = false;
+
+                               dev_err(&st->sd.spi->dev,
+                                       "Too many unique channel configurations requested for scan\n");
+                               return -EINVAL;
+                       }
+               }
+       }
+
        return 0;
 }