#include <linux/bitfield.h>
 #include <linux/counter.h>
-#include <linux/iio/iio.h>
 #include <linux/mfd/stm32-lptimer.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
        return regmap_update_bits(priv->regmap, STM32_LPTIM_CFGR, mask, val);
 }
 
-static int stm32_lptim_write_raw(struct iio_dev *indio_dev,
-                                struct iio_chan_spec const *chan,
-                                int val, int val2, long mask)
-{
-       struct stm32_lptim_cnt *priv = iio_priv(indio_dev);
-       int ret;
-
-       switch (mask) {
-       case IIO_CHAN_INFO_ENABLE:
-               if (val < 0 || val > 1)
-                       return -EINVAL;
-
-               /* Check nobody uses the timer, or already disabled/enabled */
-               ret = stm32_lptim_is_enabled(priv);
-               if ((ret < 0) || (!ret && !val))
-                       return ret;
-               if (val && ret)
-                       return -EBUSY;
-
-               ret = stm32_lptim_setup(priv, val);
-               if (ret)
-                       return ret;
-               return stm32_lptim_set_enable_state(priv, val);
-
-       default:
-               return -EINVAL;
-       }
-}
-
-static int stm32_lptim_read_raw(struct iio_dev *indio_dev,
-                               struct iio_chan_spec const *chan,
-                               int *val, int *val2, long mask)
-{
-       struct stm32_lptim_cnt *priv = iio_priv(indio_dev);
-       u32 dat;
-       int ret;
-
-       switch (mask) {
-       case IIO_CHAN_INFO_RAW:
-               ret = regmap_read(priv->regmap, STM32_LPTIM_CNT, &dat);
-               if (ret)
-                       return ret;
-               *val = dat;
-               return IIO_VAL_INT;
-
-       case IIO_CHAN_INFO_ENABLE:
-               ret = stm32_lptim_is_enabled(priv);
-               if (ret < 0)
-                       return ret;
-               *val = ret;
-               return IIO_VAL_INT;
-
-       case IIO_CHAN_INFO_SCALE:
-               /* Non-quadrature mode: scale = 1 */
-               *val = 1;
-               *val2 = 0;
-               if (priv->quadrature_mode) {
-                       /*
-                        * Quadrature encoder mode:
-                        * - both edges, quarter cycle, scale is 0.25
-                        * - either rising/falling edge scale is 0.5
-                        */
-                       if (priv->polarity > 1)
-                               *val2 = 2;
-                       else
-                               *val2 = 1;
-               }
-               return IIO_VAL_FRACTIONAL_LOG2;
-
-       default:
-               return -EINVAL;
-       }
-}
-
-static const struct iio_info stm32_lptim_cnt_iio_info = {
-       .read_raw = stm32_lptim_read_raw,
-       .write_raw = stm32_lptim_write_raw,
-};
-
-static const char *const stm32_lptim_quadrature_modes[] = {
-       "non-quadrature",
-       "quadrature",
-};
-
-static int stm32_lptim_get_quadrature_mode(struct iio_dev *indio_dev,
-                                          const struct iio_chan_spec *chan)
-{
-       struct stm32_lptim_cnt *priv = iio_priv(indio_dev);
-
-       return priv->quadrature_mode;
-}
-
-static int stm32_lptim_set_quadrature_mode(struct iio_dev *indio_dev,
-                                          const struct iio_chan_spec *chan,
-                                          unsigned int type)
-{
-       struct stm32_lptim_cnt *priv = iio_priv(indio_dev);
-
-       if (stm32_lptim_is_enabled(priv))
-               return -EBUSY;
-
-       priv->quadrature_mode = type;
-
-       return 0;
-}
-
-static const struct iio_enum stm32_lptim_quadrature_mode_en = {
-       .items = stm32_lptim_quadrature_modes,
-       .num_items = ARRAY_SIZE(stm32_lptim_quadrature_modes),
-       .get = stm32_lptim_get_quadrature_mode,
-       .set = stm32_lptim_set_quadrature_mode,
-};
-
-static const char * const stm32_lptim_cnt_polarity[] = {
-       "rising-edge", "falling-edge", "both-edges",
-};
-
-static int stm32_lptim_cnt_get_polarity(struct iio_dev *indio_dev,
-                                       const struct iio_chan_spec *chan)
-{
-       struct stm32_lptim_cnt *priv = iio_priv(indio_dev);
-
-       return priv->polarity;
-}
-
-static int stm32_lptim_cnt_set_polarity(struct iio_dev *indio_dev,
-                                       const struct iio_chan_spec *chan,
-                                       unsigned int type)
-{
-       struct stm32_lptim_cnt *priv = iio_priv(indio_dev);
-
-       if (stm32_lptim_is_enabled(priv))
-               return -EBUSY;
-
-       priv->polarity = type;
-
-       return 0;
-}
-
-static const struct iio_enum stm32_lptim_cnt_polarity_en = {
-       .items = stm32_lptim_cnt_polarity,
-       .num_items = ARRAY_SIZE(stm32_lptim_cnt_polarity),
-       .get = stm32_lptim_cnt_get_polarity,
-       .set = stm32_lptim_cnt_set_polarity,
-};
-
-static ssize_t stm32_lptim_cnt_get_ceiling(struct stm32_lptim_cnt *priv,
-                                          char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%u\n", priv->ceiling);
-}
-
-static ssize_t stm32_lptim_cnt_set_ceiling(struct stm32_lptim_cnt *priv,
-                                          const char *buf, size_t len)
-{
-       int ret;
-
-       if (stm32_lptim_is_enabled(priv))
-               return -EBUSY;
-
-       ret = kstrtouint(buf, 0, &priv->ceiling);
-       if (ret)
-               return ret;
-
-       if (priv->ceiling > STM32_LPTIM_MAX_ARR)
-               return -EINVAL;
-
-       return len;
-}
-
-static ssize_t stm32_lptim_cnt_get_preset_iio(struct iio_dev *indio_dev,
-                                             uintptr_t private,
-                                             const struct iio_chan_spec *chan,
-                                             char *buf)
-{
-       struct stm32_lptim_cnt *priv = iio_priv(indio_dev);
-
-       return stm32_lptim_cnt_get_ceiling(priv, buf);
-}
-
-static ssize_t stm32_lptim_cnt_set_preset_iio(struct iio_dev *indio_dev,
-                                             uintptr_t private,
-                                             const struct iio_chan_spec *chan,
-                                             const char *buf, size_t len)
-{
-       struct stm32_lptim_cnt *priv = iio_priv(indio_dev);
-
-       return stm32_lptim_cnt_set_ceiling(priv, buf, len);
-}
-
-/* LP timer with encoder */
-static const struct iio_chan_spec_ext_info stm32_lptim_enc_ext_info[] = {
-       {
-               .name = "preset",
-               .shared = IIO_SEPARATE,
-               .read = stm32_lptim_cnt_get_preset_iio,
-               .write = stm32_lptim_cnt_set_preset_iio,
-       },
-       IIO_ENUM("polarity", IIO_SEPARATE, &stm32_lptim_cnt_polarity_en),
-       IIO_ENUM_AVAILABLE("polarity", &stm32_lptim_cnt_polarity_en),
-       IIO_ENUM("quadrature_mode", IIO_SEPARATE,
-                &stm32_lptim_quadrature_mode_en),
-       IIO_ENUM_AVAILABLE("quadrature_mode", &stm32_lptim_quadrature_mode_en),
-       {}
-};
-
-static const struct iio_chan_spec stm32_lptim_enc_channels = {
-       .type = IIO_COUNT,
-       .channel = 0,
-       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-                             BIT(IIO_CHAN_INFO_ENABLE) |
-                             BIT(IIO_CHAN_INFO_SCALE),
-       .ext_info = stm32_lptim_enc_ext_info,
-       .indexed = 1,
-};
-
-/* LP timer without encoder (counter only) */
-static const struct iio_chan_spec_ext_info stm32_lptim_cnt_ext_info[] = {
-       {
-               .name = "preset",
-               .shared = IIO_SEPARATE,
-               .read = stm32_lptim_cnt_get_preset_iio,
-               .write = stm32_lptim_cnt_set_preset_iio,
-       },
-       IIO_ENUM("polarity", IIO_SEPARATE, &stm32_lptim_cnt_polarity_en),
-       IIO_ENUM_AVAILABLE("polarity", &stm32_lptim_cnt_polarity_en),
-       {}
-};
-
-static const struct iio_chan_spec stm32_lptim_cnt_channels = {
-       .type = IIO_COUNT,
-       .channel = 0,
-       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-                             BIT(IIO_CHAN_INFO_ENABLE) |
-                             BIT(IIO_CHAN_INFO_SCALE),
-       .ext_info = stm32_lptim_cnt_ext_info,
-       .indexed = 1,
-};
-
 /**
  * enum stm32_lptim_cnt_function - enumerates LPTimer counter & encoder modes
  * @STM32_LPTIM_COUNTER_INCREASE: up count on IN1 rising, falling or both edges
  * @STM32_LPTIM_ENCODER_BOTH_EDGE: count on both edges (IN1 & IN2 quadrature)
+ *
+ * In non-quadrature mode, device counts up on active edge.
+ * In quadrature mode, encoder counting scenarios are as follows:
+ * +---------+----------+--------------------+--------------------+
+ * | Active  | Level on |      IN1 signal    |     IN2 signal     |
+ * | edge    | opposite +----------+---------+----------+---------+
+ * |         | signal   |  Rising  | Falling |  Rising  | Falling |
+ * +---------+----------+----------+---------+----------+---------+
+ * | Rising  | High ->  |   Down   |    -    |   Up     |    -    |
+ * | edge    | Low  ->  |   Up     |    -    |   Down   |    -    |
+ * +---------+----------+----------+---------+----------+---------+
+ * | Falling | High ->  |    -     |   Up    |    -     |   Down  |
+ * | edge    | Low  ->  |    -     |   Down  |    -     |   Up    |
+ * +---------+----------+----------+---------+----------+---------+
+ * | Both    | High ->  |   Down   |   Up    |   Up     |   Down  |
+ * | edges   | Low  ->  |   Up     |   Down  |   Down   |   Up    |
+ * +---------+----------+----------+---------+----------+---------+
  */
 enum stm32_lptim_cnt_function {
        STM32_LPTIM_COUNTER_INCREASE,
 {
        struct stm32_lptim_cnt *const priv = counter->priv;
 
-       return stm32_lptim_cnt_get_ceiling(priv, buf);
+       return snprintf(buf, PAGE_SIZE, "%u\n", priv->ceiling);
 }
 
 static ssize_t stm32_lptim_cnt_ceiling_write(struct counter_device *counter,
                                             const char *buf, size_t len)
 {
        struct stm32_lptim_cnt *const priv = counter->priv;
+       unsigned int ceiling;
+       int ret;
+
+       if (stm32_lptim_is_enabled(priv))
+               return -EBUSY;
+
+       ret = kstrtouint(buf, 0, &ceiling);
+       if (ret)
+               return ret;
+
+       if (ceiling > STM32_LPTIM_MAX_ARR)
+               return -EINVAL;
+
+       priv->ceiling = ceiling;
 
-       return stm32_lptim_cnt_set_ceiling(priv, buf, len);
+       return len;
 }
 
 static const struct counter_count_ext stm32_lptim_cnt_ext[] = {
 {
        struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent);
        struct stm32_lptim_cnt *priv;
-       struct iio_dev *indio_dev;
-       int ret;
 
        if (IS_ERR_OR_NULL(ddata))
                return -EINVAL;
 
-       indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
-       if (!indio_dev)
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
                return -ENOMEM;
 
-       priv = iio_priv(indio_dev);
        priv->dev = &pdev->dev;
        priv->regmap = ddata->regmap;
        priv->clk = ddata->clk;
        priv->ceiling = STM32_LPTIM_MAX_ARR;
 
-       /* Initialize IIO device */
-       indio_dev->name = dev_name(&pdev->dev);
-       indio_dev->dev.of_node = pdev->dev.of_node;
-       indio_dev->info = &stm32_lptim_cnt_iio_info;
-       if (ddata->has_encoder)
-               indio_dev->channels = &stm32_lptim_enc_channels;
-       else
-               indio_dev->channels = &stm32_lptim_cnt_channels;
-       indio_dev->num_channels = 1;
-
        /* Initialize Counter device */
        priv->counter.name = dev_name(&pdev->dev);
        priv->counter.parent = &pdev->dev;
 
        platform_set_drvdata(pdev, priv);
 
-       ret = devm_iio_device_register(&pdev->dev, indio_dev);
-       if (ret)
-               return ret;
-
        return devm_counter_register(&pdev->dev, &priv->counter);
 }