Messages in this thread Patch in this message | | | Date | Thu, 1 Jun 2023 23:52:17 +0300 | Subject | Re: [PATCH v1] meson saradc: fix clock divider mask length | From | George Stark <> |
| |
On 5/29/23 23:41, Martin Blumenstingl wrote: > Hi George, > > On Mon, May 22, 2023 at 5:47 PM Старк Георгий Николаевич > <GNStark@sberdevices.ru> wrote: >> Hello Martin >> >> Actually you were right that my patch affects only meson8 family not the all new ones, my bad. >> It's clear from the driver code meson_saradc.c and dts files. >> I've made an experiment on a113l soc - changingclock_rate inmeson_sar_adc_param and measuring adc channel many times >> and with low clockfrequency (priv->adc_clk) time of measurementis high >> and vice versa. ADC_CLK_DIV field in SAR_ADC_REG3 is always zero. > Thanks for sharing your findings! > >> I need to get s805 (meson8) board for example and made experiment on it. > If you don't find any Meson8 (S802)/Meson8b (S805) or Meson8m2 (S812) > board then please provide the code that you used for your experiment > as a patch so I can give it a try on my Odroid-C1 (Meson8b). > > > Best regards, > Martin > Hello Martin
Here the test I promised: Question: what's the real size of clock divder field in SAR_ADC_REG3 register in saradc in meson8 socs? The current kernel code says 5 bits The datasheet says 6 bit
The parent clock of adc clock is 24Mhz I can check it here by:
# cat /sys/kernel/debug/clk/clk_summary xtal 4 4 1 24000000 0 0 50000 Y c1108680.adc#adc_div 1 1 0 1142858 0 0 50000 Y c1108680.adc#adc_en 1 1 0 1142858 0 0 50000 Y
for divider width 5bit min adc clock is 24Mhz / 32 = 750KHZ for divider width 6bit min adc clock is 24Mhz / 64 = 375KHz
I suppose that the lower adc clock rate the higher measurement time so I need to get measurement time at both clk freqs and the times differ so 6bit divider is really applied
I performed test at Odroid-C1, kernel 6.2-rc8 Two kernel patches must be applied:
the topic starter patch and the helper patch at the end of the letter In the helper patch I turn on CLOCK_ALLOW_WRITE_DEBUGFS to change clock rate from she shell and use ktime_get_raw_ts64 to measure measurement time
So the the test itself: cat /sys/devices/platform/soc/c1100000.cbus/c1108680.adc/iio:device0/in_voltage3_raw [ 1781.226309] ==== freq: 1142858 time 42408000
# echo 750000 > /sys/kernel/debug/clk/c1108680.adc#adc_en/clk_rate # cat /sys/devices/platform/soc/c1100000.cbus/c1108680.adc/iio:device0/in_voltage3_raw [ 1790.728656] ==== freq: 750000 time 49173000
# echo 375000 > /sys/kernel/debug/clk/c1108680.adc#adc_en/clk_rate # cat /sys/devices/platform/soc/c1100000.cbus/c1108680.adc/iio:device0/in_voltage3_raw [ 1816.955477] ==== freq: 375000 time 68245000
# cat /sys/kernel/debug/clk/clk_summary xtal 4 4 1 24000000 0 0 50000 Y c1108680.adc#adc_div 1 1 0 375000 0 0 50000 Y c1108680.adc#adc_en 1 1 0 375000 0 0 50000 Y
Helper patch:
diff --git a/drivers/clk/baikal-t1/ccu-pll.c b/drivers/clk/baikal-t1/ccu-pll.c index 13ef28001439..226e0d46a994 100644 --- a/drivers/clk/baikal-t1/ccu-pll.c +++ b/drivers/clk/baikal-t1/ccu-pll.c @@ -363,7 +363,7 @@ static const struct ccu_pll_dbgfs_fld ccu_pll_flds[] = { * therefore we don't provide any kernel config based compile time option for * this feature to enable. */ -#undef CCU_PLL_ALLOW_WRITE_DEBUGFS +#define CCU_PLL_ALLOW_WRITE_DEBUGFS #ifdef CCU_PLL_ALLOW_WRITE_DEBUGFS
static int ccu_pll_dbgfs_bit_set(void *priv, u64 val) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index e62552a75f08..d552acdaa7bc 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3263,7 +3263,7 @@ static int clk_dump_show(struct seq_file *s, void *data) } DEFINE_SHOW_ATTRIBUTE(clk_dump);
-#undef CLOCK_ALLOW_WRITE_DEBUGFS +#define CLOCK_ALLOW_WRITE_DEBUGFS #ifdef CLOCK_ALLOW_WRITE_DEBUGFS /* * This can be dangerous, therefore don't provide any real compile time diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 6959a0064551..65132d3ca46a 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -24,6 +24,8 @@ #include <linux/regulator/consumer.h> #include <linux/mfd/syscon.h>
+#include <linux/timekeeping.h> + #define MESON_SAR_ADC_REG0 0x00 #define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31) #define MESON_SAR_ADC_REG0_BUSY_MASK GENMASK(30, 28) @@ -599,6 +601,8 @@ static int meson_sar_adc_get_sample(struct iio_dev *indio_dev, struct device *dev = indio_dev->dev.parent; int ret;
+ int i; + if (chan->type == IIO_TEMP && !priv->temperature_sensor_calibrated) return -ENOTSUPP;
@@ -606,16 +610,28 @@ static int meson_sar_adc_get_sample(struct iio_dev *indio_dev, if (ret) return ret;
- /* clear the FIFO to make sure we're not reading old values */ - meson_sar_adc_clear_fifo(indio_dev);
- meson_sar_adc_set_averaging(indio_dev, chan, avg_mode, avg_samples); + struct timespec64 ts0, ts1; + ktime_get_raw_ts64(&ts0);
- meson_sar_adc_enable_channel(indio_dev, chan); + for (i = 0; i < 1000; i++) {
- meson_sar_adc_start_sample_engine(indio_dev); - ret = meson_sar_adc_read_raw_sample(indio_dev, chan, val); - meson_sar_adc_stop_sample_engine(indio_dev); + /* clear the FIFO to make sure we're not reading old values */ + meson_sar_adc_clear_fifo(indio_dev); + + meson_sar_adc_set_averaging(indio_dev, chan, avg_mode, avg_samples); + + meson_sar_adc_enable_channel(indio_dev, chan); + + meson_sar_adc_start_sample_engine(indio_dev); + ret = meson_sar_adc_read_raw_sample(indio_dev, chan, val); + meson_sar_adc_stop_sample_engine(indio_dev); + } + + ktime_get_raw_ts64(&ts1); + u64 t0 = NSEC_PER_SEC * ts0.tv_sec + ts0.tv_nsec; + u64 t1 = NSEC_PER_SEC * ts1.tv_sec + ts1.tv_nsec; + printk("==== freq: %lu time %lld\n", clk_get_rate(priv->adc_clk), t1 - t0);
meson_sar_adc_unlock(indio_dev);
Best regards George
| |