OSDN Git Service

staging: iio: adc: ad7192: fix external frequency setting
authorAlexandru Ardelean <alexandru.ardelean@analog.com>
Mon, 22 Jan 2018 09:53:12 +0000 (11:53 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 25 Feb 2018 10:07:52 +0000 (11:07 +0100)
commit e31b617d0a63c6558485aaa730fd162faa95a766 upstream.

The external clock frequency was set only when selecting
the internal clock, which is fixed at 4.9152 Mhz.

This is incorrect, since it should be set when any of
the external clock or crystal settings is selected.

Added range validation for the external (crystal/clock)
frequency setting.
Valid values are between 2.4576 and 5.12 Mhz.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/iio/adc/ad7192.c

index 6150d27..31a195d 100644 (file)
 #define AD7192_GPOCON_P1DAT    BIT(1) /* P1 state */
 #define AD7192_GPOCON_P0DAT    BIT(0) /* P0 state */
 
+#define AD7192_EXT_FREQ_MHZ_MIN        2457600
+#define AD7192_EXT_FREQ_MHZ_MAX        5120000
 #define AD7192_INT_FREQ_MHZ    4915200
 
 /* NOTE:
@@ -217,6 +219,12 @@ static int ad7192_calibrate_all(struct ad7192_state *st)
                                ARRAY_SIZE(ad7192_calib_arr));
 }
 
+static inline bool ad7192_valid_external_frequency(u32 freq)
+{
+       return (freq >= AD7192_EXT_FREQ_MHZ_MIN &&
+               freq <= AD7192_EXT_FREQ_MHZ_MAX);
+}
+
 static int ad7192_setup(struct ad7192_state *st,
                        const struct ad7192_platform_data *pdata)
 {
@@ -242,17 +250,20 @@ static int ad7192_setup(struct ad7192_state *st,
                         id);
 
        switch (pdata->clock_source_sel) {
-       case AD7192_CLK_EXT_MCLK1_2:
-       case AD7192_CLK_EXT_MCLK2:
-               st->mclk = AD7192_INT_FREQ_MHZ;
-               break;
        case AD7192_CLK_INT:
        case AD7192_CLK_INT_CO:
-               if (pdata->ext_clk_hz)
-                       st->mclk = pdata->ext_clk_hz;
-               else
-                       st->mclk = AD7192_INT_FREQ_MHZ;
+               st->mclk = AD7192_INT_FREQ_MHZ;
                break;
+       case AD7192_CLK_EXT_MCLK1_2:
+       case AD7192_CLK_EXT_MCLK2:
+               if (ad7192_valid_external_frequency(pdata->ext_clk_hz)) {
+                       st->mclk = pdata->ext_clk_hz;
+                       break;
+               }
+               dev_err(&st->sd.spi->dev, "Invalid frequency setting %u\n",
+                       pdata->ext_clk_hz);
+               ret = -EINVAL;
+               goto out;
        default:
                ret = -EINVAL;
                goto out;