* [PATCH v6 1/6] dt-bindings: iio: filter: Add lpf/hpf freq margins
@ 2025-03-07 15:02 Sam Winchenbach
2025-03-07 15:02 ` [PATCH v6 2/6] iio: filter: admv8818: fix band 4, state 15 Sam Winchenbach
` (5 more replies)
0 siblings, 6 replies; 13+ messages in thread
From: Sam Winchenbach @ 2025-03-07 15:02 UTC (permalink / raw)
To: linux-kernel
Cc: lars, Michael.Hennerich, antoniu.miclaus, jic23, robh, krzk+dt,
conor+dt, linux-iio, devicetree, sam.winchenbach, bpellegrino
Adds two properties to add a margin when automatically finding the
corner frequencies.
Signed-off-by: Sam Winchenbach <sam.winchenbach@framepointer.org>
---
.../bindings/iio/filter/adi,admv8818.yaml | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/filter/adi,admv8818.yaml b/Documentation/devicetree/bindings/iio/filter/adi,admv8818.yaml
index b77e855bd594..ff0cb553e871 100644
--- a/Documentation/devicetree/bindings/iio/filter/adi,admv8818.yaml
+++ b/Documentation/devicetree/bindings/iio/filter/adi,admv8818.yaml
@@ -44,6 +44,24 @@ properties:
'#clock-cells':
const: 0
+ adi,lpf-margin-mhz:
+ description:
+ Sets the minimum distance between the fundamental frequency of `rf_in`
+ and the corner frequency of the low-pass, output filter when operated in
+ 'auto' mode. The selected low-pass corner frequency will be greater than,
+ or equal to, `rf_in` + `lpf-margin-hz`. If not setting is found that
+ satisfies this relationship the filter will be put into 'bypass'.
+ default: 0
+
+ adi,hpf-margin-mhz:
+ description:
+ Sets the minimum distance between the fundamental frequency of `rf_in`
+ and the corner frequency of the high-pass, input filter when operated in
+ 'auto' mode. The selected high-pass corner frequency will be less than,
+ or equal to, `rf_in` - `hpf-margin-hz`. If not setting is found that
+ satisfies this relationship the filter will be put into 'bypass'.
+ default: 0
+
required:
- compatible
- reg
@@ -61,6 +79,8 @@ examples:
spi-max-frequency = <10000000>;
clocks = <&admv8818_rfin>;
clock-names = "rf_in";
+ adi,lpf-margin-mhz = <300>;
+ adi,hpf-margin-mhz = <300>;
};
};
...
--
2.48.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 2/6] iio: filter: admv8818: fix band 4, state 15
2025-03-07 15:02 [PATCH v6 1/6] dt-bindings: iio: filter: Add lpf/hpf freq margins Sam Winchenbach
@ 2025-03-07 15:02 ` Sam Winchenbach
2025-03-07 15:02 ` [PATCH v6 3/6] iio: filter: admv8818: fix integer overflow Sam Winchenbach
` (4 subsequent siblings)
5 siblings, 0 replies; 13+ messages in thread
From: Sam Winchenbach @ 2025-03-07 15:02 UTC (permalink / raw)
To: linux-kernel
Cc: lars, Michael.Hennerich, antoniu.miclaus, jic23, robh, krzk+dt,
conor+dt, linux-iio, devicetree, sam.winchenbach, bpellegrino
Corrects the upper range of LPF Band 4 from 18.5 GHz to 18.85 GHz per
the ADMV8818 datasheet
Fixes: f34fe888ad05 ("iio:filter:admv8818: add support for ADMV8818")
Signed-off-by: Sam Winchenbach <sam.winchenbach@framepointer.org>
---
drivers/iio/filter/admv8818.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/iio/filter/admv8818.c b/drivers/iio/filter/admv8818.c
index 848baa6e3bbf..8f563a426232 100644
--- a/drivers/iio/filter/admv8818.c
+++ b/drivers/iio/filter/admv8818.c
@@ -103,7 +103,7 @@ static const unsigned long long freq_range_lpf[4][2] = {
{2050000000ULL, 3850000000ULL},
{3350000000ULL, 7250000000ULL},
{7000000000, 13000000000},
- {12550000000, 18500000000}
+ {12550000000, 18850000000}
};
static const struct regmap_config admv8818_regmap_config = {
--
2.48.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 3/6] iio: filter: admv8818: fix integer overflow
2025-03-07 15:02 [PATCH v6 1/6] dt-bindings: iio: filter: Add lpf/hpf freq margins Sam Winchenbach
2025-03-07 15:02 ` [PATCH v6 2/6] iio: filter: admv8818: fix band 4, state 15 Sam Winchenbach
@ 2025-03-07 15:02 ` Sam Winchenbach
2025-03-07 15:02 ` [PATCH v6 4/6] iio: filter: admv8818: fix range calculation Sam Winchenbach
` (3 subsequent siblings)
5 siblings, 0 replies; 13+ messages in thread
From: Sam Winchenbach @ 2025-03-07 15:02 UTC (permalink / raw)
To: linux-kernel
Cc: lars, Michael.Hennerich, antoniu.miclaus, jic23, robh, krzk+dt,
conor+dt, linux-iio, devicetree, sam.winchenbach, bpellegrino
HZ_PER_MHZ is only unsigned long. This math overflows, leading to
incorrect results.
Fixes: f34fe888ad05 ("iio:filter:admv8818: add support for ADMV8818")
Signed-off-by: Sam Winchenbach <sam.winchenbach@framepointer.org>
---
drivers/iio/filter/admv8818.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/iio/filter/admv8818.c b/drivers/iio/filter/admv8818.c
index 8f563a426232..a059282e0251 100644
--- a/drivers/iio/filter/admv8818.c
+++ b/drivers/iio/filter/admv8818.c
@@ -154,7 +154,7 @@ static int __admv8818_hpf_select(struct admv8818_state *st, u64 freq)
}
/* Close HPF frequency gap between 12 and 12.5 GHz */
- if (freq >= 12000 * HZ_PER_MHZ && freq <= 12500 * HZ_PER_MHZ) {
+ if (freq >= 12000ULL * HZ_PER_MHZ && freq < 12500ULL * HZ_PER_MHZ) {
hpf_band = 3;
hpf_step = 15;
}
--
2.48.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 4/6] iio: filter: admv8818: fix range calculation
2025-03-07 15:02 [PATCH v6 1/6] dt-bindings: iio: filter: Add lpf/hpf freq margins Sam Winchenbach
2025-03-07 15:02 ` [PATCH v6 2/6] iio: filter: admv8818: fix band 4, state 15 Sam Winchenbach
2025-03-07 15:02 ` [PATCH v6 3/6] iio: filter: admv8818: fix integer overflow Sam Winchenbach
@ 2025-03-07 15:02 ` Sam Winchenbach
2025-03-08 14:03 ` Jonathan Cameron
2025-03-07 15:02 ` [PATCH v6 5/6] driver core: Add support for writing 64 bit attrs Sam Winchenbach
` (2 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Sam Winchenbach @ 2025-03-07 15:02 UTC (permalink / raw)
To: linux-kernel
Cc: lars, Michael.Hennerich, antoniu.miclaus, jic23, robh, krzk+dt,
conor+dt, linux-iio, devicetree, sam.winchenbach, bpellegrino
Search for the minimum error while ensuring that the LPF corner
frequency is greater than the target, and the HPF corner frequency
is lower than the target
This fixes issues where the range calculations were suboptimal.
Add two new DTS properties to set the margin between the input frequency
and the calculated corner frequency
Below is a generated table of the differences between the old algorithm
and the new. This is a sweep from 0 to 20 GHz in 10 MHz steps.
=== HPF ===
freq = 1750 MHz, 3db: bypass => 1750 MHz
freq = 3400 MHz, 3db: 3310 => 3400 MHz
freq = 3410 MHz, 3db: 3310 => 3400 MHz
freq = 3420 MHz, 3db: 3310 => 3400 MHz
freq = 3660 MHz, 3db: 3550 => 3656 MHz
freq = 6600 MHz, 3db: 6479 => 6600 MHz
freq = 6610 MHz, 3db: 6479 => 6600 MHz
freq = 6620 MHz, 3db: 6479 => 6600 MHz
freq = 6630 MHz, 3db: 6479 => 6600 MHz
freq = 6640 MHz, 3db: 6479 => 6600 MHz
freq = 6650 MHz, 3db: 6479 => 6600 MHz
freq = 6660 MHz, 3db: 6479 => 6600 MHz
freq = 6670 MHz, 3db: 6479 => 6600 MHz
freq = 6680 MHz, 3db: 6479 => 6600 MHz
freq = 6690 MHz, 3db: 6479 => 6600 MHz
freq = 6700 MHz, 3db: 6479 => 6600 MHz
freq = 6710 MHz, 3db: 6479 => 6600 MHz
freq = 6720 MHz, 3db: 6479 => 6600 MHz
freq = 6730 MHz, 3db: 6479 => 6600 MHz
freq = 6960 MHz, 3db: 6736 => 6960 MHz
freq = 6970 MHz, 3db: 6736 => 6960 MHz
freq = 6980 MHz, 3db: 6736 => 6960 MHz
freq = 6990 MHz, 3db: 6736 => 6960 MHz
freq = 7320 MHz, 3db: 7249 => 7320 MHz
freq = 7330 MHz, 3db: 7249 => 7320 MHz
freq = 7340 MHz, 3db: 7249 => 7320 MHz
freq = 7350 MHz, 3db: 7249 => 7320 MHz
freq = 7360 MHz, 3db: 7249 => 7320 MHz
freq = 7370 MHz, 3db: 7249 => 7320 MHz
freq = 7380 MHz, 3db: 7249 => 7320 MHz
freq = 7390 MHz, 3db: 7249 => 7320 MHz
freq = 7400 MHz, 3db: 7249 => 7320 MHz
freq = 7410 MHz, 3db: 7249 => 7320 MHz
freq = 7420 MHz, 3db: 7249 => 7320 MHz
freq = 7430 MHz, 3db: 7249 => 7320 MHz
freq = 7440 MHz, 3db: 7249 => 7320 MHz
freq = 7450 MHz, 3db: 7249 => 7320 MHz
freq = 7460 MHz, 3db: 7249 => 7320 MHz
freq = 7470 MHz, 3db: 7249 => 7320 MHz
freq = 7480 MHz, 3db: 7249 => 7320 MHz
freq = 7490 MHz, 3db: 7249 => 7320 MHz
freq = 7500 MHz, 3db: 7249 => 7320 MHz
freq = 12500 MHz, 3db: 12000 => 12500 MHz
=== LPF ===
freq = 2050 MHz, 3db: bypass => 2050 MHz
freq = 2170 MHz, 3db: 2290 => 2170 MHz
freq = 2290 MHz, 3db: 2410 => 2290 MHz
freq = 2410 MHz, 3db: 2530 => 2410 MHz
freq = 2530 MHz, 3db: 2650 => 2530 MHz
freq = 2650 MHz, 3db: 2770 => 2650 MHz
freq = 2770 MHz, 3db: 2890 => 2770 MHz
freq = 2890 MHz, 3db: 3010 => 2890 MHz
freq = 3010 MHz, 3db: 3130 => 3010 MHz
freq = 3130 MHz, 3db: 3250 => 3130 MHz
freq = 3250 MHz, 3db: 3370 => 3250 MHz
freq = 3260 MHz, 3db: 3370 => 3350 MHz
freq = 3270 MHz, 3db: 3370 => 3350 MHz
freq = 3280 MHz, 3db: 3370 => 3350 MHz
freq = 3290 MHz, 3db: 3370 => 3350 MHz
freq = 3300 MHz, 3db: 3370 => 3350 MHz
freq = 3310 MHz, 3db: 3370 => 3350 MHz
freq = 3320 MHz, 3db: 3370 => 3350 MHz
freq = 3330 MHz, 3db: 3370 => 3350 MHz
freq = 3340 MHz, 3db: 3370 => 3350 MHz
freq = 3350 MHz, 3db: 3370 => 3350 MHz
freq = 3370 MHz, 3db: 3490 => 3370 MHz
freq = 3490 MHz, 3db: 3610 => 3490 MHz
freq = 3610 MHz, 3db: 3730 => 3610 MHz
freq = 3730 MHz, 3db: 3850 => 3730 MHz
freq = 3850 MHz, 3db: 3870 => 3850 MHz
freq = 3870 MHz, 3db: 4130 => 3870 MHz
freq = 4130 MHz, 3db: 4390 => 4130 MHz
freq = 4390 MHz, 3db: 4650 => 4390 MHz
freq = 4650 MHz, 3db: 4910 => 4650 MHz
freq = 4910 MHz, 3db: 5170 => 4910 MHz
freq = 5170 MHz, 3db: 5430 => 5170 MHz
freq = 5430 MHz, 3db: 5690 => 5430 MHz
freq = 5690 MHz, 3db: 5950 => 5690 MHz
freq = 5950 MHz, 3db: 6210 => 5950 MHz
freq = 6210 MHz, 3db: 6470 => 6210 MHz
freq = 6470 MHz, 3db: 6730 => 6470 MHz
freq = 6730 MHz, 3db: 6990 => 6730 MHz
freq = 6990 MHz, 3db: 7250 => 6990 MHz
freq = 7000 MHz, 3db: 7250 => 7000 MHz
freq = 7250 MHz, 3db: 7400 => 7250 MHz
freq = 7400 MHz, 3db: 7800 => 7400 MHz
freq = 7800 MHz, 3db: 8200 => 7800 MHz
freq = 8200 MHz, 3db: 8600 => 8200 MHz
freq = 8600 MHz, 3db: 9000 => 8600 MHz
freq = 9000 MHz, 3db: 9400 => 9000 MHz
freq = 9400 MHz, 3db: 9800 => 9400 MHz
freq = 9800 MHz, 3db: 10200 => 9800 MHz
freq = 10200 MHz, 3db: 10600 => 10200 MHz
freq = 10600 MHz, 3db: 11000 => 10600 MHz
freq = 11000 MHz, 3db: 11400 => 11000 MHz
freq = 11400 MHz, 3db: 11800 => 11400 MHz
freq = 11800 MHz, 3db: 12200 => 11800 MHz
freq = 12200 MHz, 3db: 12600 => 12200 MHz
freq = 12210 MHz, 3db: 12600 => 12550 MHz
freq = 12220 MHz, 3db: 12600 => 12550 MHz
freq = 12230 MHz, 3db: 12600 => 12550 MHz
freq = 12240 MHz, 3db: 12600 => 12550 MHz
freq = 12250 MHz, 3db: 12600 => 12550 MHz
freq = 12260 MHz, 3db: 12600 => 12550 MHz
freq = 12270 MHz, 3db: 12600 => 12550 MHz
freq = 12280 MHz, 3db: 12600 => 12550 MHz
freq = 12290 MHz, 3db: 12600 => 12550 MHz
freq = 12300 MHz, 3db: 12600 => 12550 MHz
freq = 12310 MHz, 3db: 12600 => 12550 MHz
freq = 12320 MHz, 3db: 12600 => 12550 MHz
freq = 12330 MHz, 3db: 12600 => 12550 MHz
freq = 12340 MHz, 3db: 12600 => 12550 MHz
freq = 12350 MHz, 3db: 12600 => 12550 MHz
freq = 12360 MHz, 3db: 12600 => 12550 MHz
freq = 12370 MHz, 3db: 12600 => 12550 MHz
freq = 12380 MHz, 3db: 12600 => 12550 MHz
freq = 12390 MHz, 3db: 12600 => 12550 MHz
freq = 12400 MHz, 3db: 12600 => 12550 MHz
freq = 12410 MHz, 3db: 12600 => 12550 MHz
freq = 12420 MHz, 3db: 12600 => 12550 MHz
freq = 12430 MHz, 3db: 12600 => 12550 MHz
freq = 12440 MHz, 3db: 12600 => 12550 MHz
freq = 12450 MHz, 3db: 12600 => 12550 MHz
freq = 12460 MHz, 3db: 12600 => 12550 MHz
freq = 12470 MHz, 3db: 12600 => 12550 MHz
freq = 12480 MHz, 3db: 12600 => 12550 MHz
freq = 12490 MHz, 3db: 12600 => 12550 MHz
freq = 12500 MHz, 3db: 12600 => 12550 MHz
freq = 12510 MHz, 3db: 12600 => 12550 MHz
freq = 12520 MHz, 3db: 12600 => 12550 MHz
freq = 12530 MHz, 3db: 12600 => 12550 MHz
freq = 12540 MHz, 3db: 12600 => 12550 MHz
freq = 12550 MHz, 3db: 12600 => 12550 MHz
freq = 12600 MHz, 3db: 13000 => 12600 MHz
freq = 12610 MHz, 3db: 13000 => 12970 MHz
freq = 12620 MHz, 3db: 13000 => 12970 MHz
freq = 12630 MHz, 3db: 13000 => 12970 MHz
freq = 12640 MHz, 3db: 13000 => 12970 MHz
freq = 12650 MHz, 3db: 13000 => 12970 MHz
freq = 12660 MHz, 3db: 13000 => 12970 MHz
freq = 12670 MHz, 3db: 13000 => 12970 MHz
freq = 12680 MHz, 3db: 13000 => 12970 MHz
freq = 12690 MHz, 3db: 13000 => 12970 MHz
freq = 12700 MHz, 3db: 13000 => 12970 MHz
freq = 12710 MHz, 3db: 13000 => 12970 MHz
freq = 12720 MHz, 3db: 13000 => 12970 MHz
freq = 12730 MHz, 3db: 13000 => 12970 MHz
freq = 12740 MHz, 3db: 13000 => 12970 MHz
freq = 12750 MHz, 3db: 13000 => 12970 MHz
freq = 12760 MHz, 3db: 13000 => 12970 MHz
freq = 12770 MHz, 3db: 13000 => 12970 MHz
freq = 12780 MHz, 3db: 13000 => 12970 MHz
freq = 12790 MHz, 3db: 13000 => 12970 MHz
freq = 12800 MHz, 3db: 13000 => 12970 MHz
freq = 12810 MHz, 3db: 13000 => 12970 MHz
freq = 12820 MHz, 3db: 13000 => 12970 MHz
freq = 12830 MHz, 3db: 13000 => 12970 MHz
freq = 12840 MHz, 3db: 13000 => 12970 MHz
freq = 12850 MHz, 3db: 13000 => 12970 MHz
freq = 12860 MHz, 3db: 13000 => 12970 MHz
freq = 12870 MHz, 3db: 13000 => 12970 MHz
freq = 12880 MHz, 3db: 13000 => 12970 MHz
freq = 12890 MHz, 3db: 13000 => 12970 MHz
freq = 12900 MHz, 3db: 13000 => 12970 MHz
freq = 12910 MHz, 3db: 13000 => 12970 MHz
freq = 12920 MHz, 3db: 13000 => 12970 MHz
freq = 12930 MHz, 3db: 13000 => 12970 MHz
freq = 12940 MHz, 3db: 13000 => 12970 MHz
freq = 12950 MHz, 3db: 13000 => 12970 MHz
freq = 12960 MHz, 3db: 13000 => 12970 MHz
freq = 12970 MHz, 3db: 13000 => 12970 MHz
freq = 13000 MHz, 3db: 13390 => 13000 MHz
freq = 13390 MHz, 3db: 13810 => 13390 MHz
freq = 13810 MHz, 3db: 14230 => 13810 MHz
freq = 14230 MHz, 3db: 14650 => 14230 MHz
freq = 14650 MHz, 3db: 15070 => 14650 MHz
freq = 15070 MHz, 3db: 15490 => 15070 MHz
freq = 15490 MHz, 3db: 15910 => 15490 MHz
freq = 15910 MHz, 3db: 16330 => 15910 MHz
freq = 16330 MHz, 3db: 16750 => 16330 MHz
freq = 16750 MHz, 3db: 17170 => 16750 MHz
freq = 17170 MHz, 3db: 17590 => 17170 MHz
freq = 17590 MHz, 3db: 18010 => 17590 MHz
freq = 18010 MHz, 3db: 18430 => 18010 MHz
freq = 18430 MHz, 3db: 18850 => 18430 MHz
freq = 18850 MHz, 3db: bypass => 18850 MHz
Fixes: f34fe888ad05 ("iio:filter:admv8818: add support for ADMV8818")
Signed-off-by: Sam Winchenbach <sam.winchenbach@framepointer.org>
---
drivers/iio/filter/admv8818.c | 205 +++++++++++++++++++++++++---------
1 file changed, 152 insertions(+), 53 deletions(-)
diff --git a/drivers/iio/filter/admv8818.c b/drivers/iio/filter/admv8818.c
index a059282e0251..e9602bfd4af7 100644
--- a/drivers/iio/filter/admv8818.c
+++ b/drivers/iio/filter/admv8818.c
@@ -14,6 +14,7 @@
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/notifier.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <linux/units.h>
@@ -70,6 +71,16 @@
#define ADMV8818_HPF_WR0_MSK GENMASK(7, 4)
#define ADMV8818_LPF_WR0_MSK GENMASK(3, 0)
+#define ADMV8818_BAND_BYPASS 0
+#define ADMV8818_BAND_MIN 1
+#define ADMV8818_BAND_MAX 4
+#define ADMV8818_BAND_CORNER_LOW 0
+#define ADMV8818_BAND_CORNER_HIGH 1
+
+#define ADMV8818_STATE_MIN 0
+#define ADMV8818_STATE_MAX 15
+#define ADMV8818_NUM_STATES 16
+
enum {
ADMV8818_BW_FREQ,
ADMV8818_CENTER_FREQ
@@ -90,16 +101,20 @@ struct admv8818_state {
struct mutex lock;
unsigned int filter_mode;
u64 cf_hz;
+ u64 lpf_margin_hz;
+ u64 hpf_margin_hz;
};
-static const unsigned long long freq_range_hpf[4][2] = {
+static const unsigned long long freq_range_hpf[5][2] = {
+ {0ULL, 0ULL}, /* bypass */
{1750000000ULL, 3550000000ULL},
{3400000000ULL, 7250000000ULL},
{6600000000, 12000000000},
{12500000000, 19900000000}
};
-static const unsigned long long freq_range_lpf[4][2] = {
+static const unsigned long long freq_range_lpf[5][2] = {
+ {U64_MAX, U64_MAX}, /* bypass */
{2050000000ULL, 3850000000ULL},
{3350000000ULL, 7250000000ULL},
{7000000000, 13000000000},
@@ -121,44 +136,59 @@ static const char * const admv8818_modes[] = {
static int __admv8818_hpf_select(struct admv8818_state *st, u64 freq)
{
- unsigned int hpf_step = 0, hpf_band = 0, i, j;
- u64 freq_step;
- int ret;
+ int band, state, ret;
+ unsigned int hpf_state = ADMV8818_STATE_MIN, hpf_band = ADMV8818_BAND_BYPASS;
+ u64 freq_error, min_freq_error, freq_corner, freq_step;
- if (freq < freq_range_hpf[0][0])
+ if (freq < freq_range_hpf[ADMV8818_BAND_MIN][ADMV8818_BAND_CORNER_LOW])
goto hpf_write;
- if (freq > freq_range_hpf[3][1]) {
- hpf_step = 15;
- hpf_band = 4;
-
+ if (freq >= freq_range_hpf[ADMV8818_BAND_MAX][ADMV8818_BAND_CORNER_HIGH]) {
+ hpf_state = ADMV8818_STATE_MAX;
+ hpf_band = ADMV8818_BAND_MAX;
goto hpf_write;
}
- for (i = 0; i < 4; i++) {
- freq_step = div_u64((freq_range_hpf[i][1] -
- freq_range_hpf[i][0]), 15);
+ /* Close HPF frequency gap between 12 and 12.5 GHz */
+ if (freq >= 12000ULL * HZ_PER_MHZ && freq < 12500ULL * HZ_PER_MHZ) {
+ hpf_state = ADMV8818_STATE_MAX;
+ hpf_band = 3;
+ goto hpf_write;
+ }
- if (freq > freq_range_hpf[i][0] &&
- (freq < freq_range_hpf[i][1] + freq_step)) {
- hpf_band = i + 1;
+ min_freq_error = U64_MAX;
+ for (band = ADMV8818_BAND_MIN; band <= ADMV8818_BAND_MAX; band++) {
+ /*
+ * This (and therefore all other ranges) have a corner
+ * frequency higher than the target frequency.
+ */
+ if (freq_range_hpf[band][ADMV8818_BAND_CORNER_LOW] > freq)
+ break;
- for (j = 1; j <= 16; j++) {
- if (freq < (freq_range_hpf[i][0] + (freq_step * j))) {
- hpf_step = j - 1;
- break;
- }
+ freq_step = freq_range_hpf[band][ADMV8818_BAND_CORNER_HIGH] -
+ freq_range_hpf[band][ADMV8818_BAND_CORNER_LOW];
+ freq_step = div_u64(freq_step, ADMV8818_NUM_STATES - 1);
+
+ for (state = ADMV8818_STATE_MIN; state <= ADMV8818_STATE_MAX; state++) {
+ freq_corner = freq_range_hpf[band][ADMV8818_BAND_CORNER_LOW] +
+ freq_step * state;
+
+ /*
+ * This (and therefore all other states) have a corner
+ * frequency higher than the target frequency.
+ */
+ if (freq_corner > freq)
+ break;
+
+ freq_error = freq - freq_corner;
+ if (freq_error < min_freq_error) {
+ min_freq_error = freq_error;
+ hpf_state = state;
+ hpf_band = band;
}
- break;
}
}
- /* Close HPF frequency gap between 12 and 12.5 GHz */
- if (freq >= 12000ULL * HZ_PER_MHZ && freq < 12500ULL * HZ_PER_MHZ) {
- hpf_band = 3;
- hpf_step = 15;
- }
-
hpf_write:
ret = regmap_update_bits(st->regmap, ADMV8818_REG_WR0_SW,
ADMV8818_SW_IN_SET_WR0_MSK |
@@ -170,7 +200,7 @@ static int __admv8818_hpf_select(struct admv8818_state *st, u64 freq)
return regmap_update_bits(st->regmap, ADMV8818_REG_WR0_FILTER,
ADMV8818_HPF_WR0_MSK,
- FIELD_PREP(ADMV8818_HPF_WR0_MSK, hpf_step));
+ FIELD_PREP(ADMV8818_HPF_WR0_MSK, hpf_state));
}
static int admv8818_hpf_select(struct admv8818_state *st, u64 freq)
@@ -186,31 +216,52 @@ static int admv8818_hpf_select(struct admv8818_state *st, u64 freq)
static int __admv8818_lpf_select(struct admv8818_state *st, u64 freq)
{
- unsigned int lpf_step = 0, lpf_band = 0, i, j;
- u64 freq_step;
- int ret;
+ int band, state, ret;
+ unsigned int lpf_state = ADMV8818_STATE_MIN, lpf_band = ADMV8818_BAND_BYPASS;
+ u64 freq_error, min_freq_error, freq_corner, freq_step;
- if (freq > freq_range_lpf[3][1])
+ if (freq > freq_range_lpf[ADMV8818_BAND_MAX][ADMV8818_BAND_CORNER_HIGH])
goto lpf_write;
- if (freq < freq_range_lpf[0][0]) {
- lpf_band = 1;
-
+ if (freq < freq_range_lpf[ADMV8818_BAND_MIN][ADMV8818_BAND_CORNER_LOW]) {
+ lpf_state = ADMV8818_STATE_MIN;
+ lpf_band = ADMV8818_BAND_MIN;
goto lpf_write;
}
- for (i = 0; i < 4; i++) {
- if (freq > freq_range_lpf[i][0] && freq < freq_range_lpf[i][1]) {
- lpf_band = i + 1;
- freq_step = div_u64((freq_range_lpf[i][1] - freq_range_lpf[i][0]), 15);
+ min_freq_error = U64_MAX;
+ for (band = ADMV8818_BAND_MAX; band >= ADMV8818_BAND_MIN; --band) {
+ /*
+ * At this point the highest corner frequency of
+ * all remaining ranges is below the target.
+ * LPF corner should be >= the target.
+ */
+ if (freq > freq_range_lpf[band][ADMV8818_BAND_CORNER_HIGH])
+ break;
+
+ freq_step = freq_range_lpf[band][ADMV8818_BAND_CORNER_HIGH] -
+ freq_range_lpf[band][ADMV8818_BAND_CORNER_LOW];
+ freq_step = div_u64(freq_step, ADMV8818_NUM_STATES - 1);
+
+ for (state = ADMV8818_STATE_MAX; state >= ADMV8818_STATE_MIN; --state) {
- for (j = 0; j <= 15; j++) {
- if (freq < (freq_range_lpf[i][0] + (freq_step * j))) {
- lpf_step = j;
- break;
- }
+ freq_corner = freq_range_lpf[band][ADMV8818_BAND_CORNER_LOW] +
+ state * freq_step;
+
+ /*
+ * At this point all other states in range will
+ * place the corner frequency below the target
+ * LPF corner should >= the target.
+ */
+ if (freq > freq_corner)
+ break;
+
+ freq_error = freq_corner - freq;
+ if (freq_error < min_freq_error) {
+ min_freq_error = freq_error;
+ lpf_state = state;
+ lpf_band = band;
}
- break;
}
}
@@ -225,7 +276,7 @@ static int __admv8818_lpf_select(struct admv8818_state *st, u64 freq)
return regmap_update_bits(st->regmap, ADMV8818_REG_WR0_FILTER,
ADMV8818_LPF_WR0_MSK,
- FIELD_PREP(ADMV8818_LPF_WR0_MSK, lpf_step));
+ FIELD_PREP(ADMV8818_LPF_WR0_MSK, lpf_state));
}
static int admv8818_lpf_select(struct admv8818_state *st, u64 freq)
@@ -242,16 +293,28 @@ static int admv8818_lpf_select(struct admv8818_state *st, u64 freq)
static int admv8818_rfin_band_select(struct admv8818_state *st)
{
int ret;
+ u64 hpf_corner_target, lpf_corner_target;
st->cf_hz = clk_get_rate(st->clkin);
+ /* Check for underflow */
+ if (st->cf_hz > st->hpf_margin_hz)
+ hpf_corner_target = st->cf_hz - st->hpf_margin_hz;
+ else
+ hpf_corner_target = 0;
+
+ /* Check for overflow */
+ lpf_corner_target = st->cf_hz + st->lpf_margin_hz;
+ if (lpf_corner_target < st->cf_hz)
+ lpf_corner_target = U64_MAX;
+
mutex_lock(&st->lock);
- ret = __admv8818_hpf_select(st, st->cf_hz);
+ ret = __admv8818_hpf_select(st, hpf_corner_target);
if (ret)
goto exit;
- ret = __admv8818_lpf_select(st, st->cf_hz);
+ ret = __admv8818_lpf_select(st, lpf_corner_target);
exit:
mutex_unlock(&st->lock);
return ret;
@@ -278,8 +341,11 @@ static int __admv8818_read_hpf_freq(struct admv8818_state *st, u64 *hpf_freq)
hpf_state = FIELD_GET(ADMV8818_HPF_WR0_MSK, data);
- *hpf_freq = div_u64(freq_range_hpf[hpf_band - 1][1] - freq_range_hpf[hpf_band - 1][0], 15);
- *hpf_freq = freq_range_hpf[hpf_band - 1][0] + (*hpf_freq * hpf_state);
+ *hpf_freq = freq_range_hpf[hpf_band][ADMV8818_BAND_CORNER_HIGH] -
+ freq_range_hpf[hpf_band][ADMV8818_BAND_CORNER_LOW];
+ *hpf_freq = div_u64(*hpf_freq, ADMV8818_NUM_STATES - 1);
+ *hpf_freq = freq_range_hpf[hpf_band][ADMV8818_BAND_CORNER_LOW] +
+ (*hpf_freq * hpf_state);
return ret;
}
@@ -316,8 +382,11 @@ static int __admv8818_read_lpf_freq(struct admv8818_state *st, u64 *lpf_freq)
lpf_state = FIELD_GET(ADMV8818_LPF_WR0_MSK, data);
- *lpf_freq = div_u64(freq_range_lpf[lpf_band - 1][1] - freq_range_lpf[lpf_band - 1][0], 15);
- *lpf_freq = freq_range_lpf[lpf_band - 1][0] + (*lpf_freq * lpf_state);
+ *lpf_freq = freq_range_lpf[lpf_band][ADMV8818_BAND_CORNER_HIGH] -
+ freq_range_lpf[lpf_band][ADMV8818_BAND_CORNER_LOW];
+ *lpf_freq = div_u64(*lpf_freq, ADMV8818_NUM_STATES - 1);
+ *lpf_freq = freq_range_lpf[lpf_band][ADMV8818_BAND_CORNER_LOW] +
+ (*lpf_freq * lpf_state);
return ret;
}
@@ -647,6 +716,32 @@ static int admv8818_clk_setup(struct admv8818_state *st)
return devm_add_action_or_reset(&spi->dev, admv8818_clk_notifier_unreg, st);
}
+static int admv8818_read_properties(struct admv8818_state *st)
+{
+ struct spi_device *spi = st->spi;
+ u32 mhz;
+ int ret;
+
+ ret = device_property_read_u32(&spi->dev, "adi,lpf-margin-mhz", &mhz);
+ if (ret == 0)
+ st->lpf_margin_hz = (u64)mhz * HZ_PER_MHZ;
+ else if (ret == -EINVAL)
+ st->lpf_margin_hz = 0;
+ else
+ return ret;
+
+
+ ret = device_property_read_u32(&spi->dev, "adi,hpf-margin-mhz", &mhz);
+ if (ret == 0)
+ st->hpf_margin_hz = (u64)mhz * HZ_PER_MHZ;
+ else if (ret == -EINVAL)
+ st->hpf_margin_hz = 0;
+ else if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
static int admv8818_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
@@ -678,6 +773,10 @@ static int admv8818_probe(struct spi_device *spi)
mutex_init(&st->lock);
+ ret = admv8818_read_properties(st);
+ if (ret)
+ return ret;
+
ret = admv8818_init(st);
if (ret)
return ret;
--
2.48.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 5/6] driver core: Add support for writing 64 bit attrs
2025-03-07 15:02 [PATCH v6 1/6] dt-bindings: iio: filter: Add lpf/hpf freq margins Sam Winchenbach
` (2 preceding siblings ...)
2025-03-07 15:02 ` [PATCH v6 4/6] iio: filter: admv8818: fix range calculation Sam Winchenbach
@ 2025-03-07 15:02 ` Sam Winchenbach
2025-03-08 14:00 ` Jonathan Cameron
2025-03-07 15:02 ` [PATCH v6 6/6] iio: filter: admv8818: Support frequencies >= 2^32 Sam Winchenbach
2025-03-10 9:22 ` [PATCH v6 1/6] dt-bindings: iio: filter: Add lpf/hpf freq margins Krzysztof Kozlowski
5 siblings, 1 reply; 13+ messages in thread
From: Sam Winchenbach @ 2025-03-07 15:02 UTC (permalink / raw)
To: linux-kernel
Cc: lars, Michael.Hennerich, antoniu.miclaus, jic23, robh, krzk+dt,
conor+dt, linux-iio, devicetree, sam.winchenbach, bpellegrino
Prior to this patch it was only possible to read 64 bit integers.
Signed-off-by: Sam Winchenbach <sam.winchenbach@framepointer.org>
---
drivers/iio/industrialio-core.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index a2117ad1337d..b2436b8f3eea 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -965,8 +965,10 @@ static ssize_t iio_write_channel_info(struct device *dev,
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret, fract_mult = 100000;
int integer, fract = 0;
+ long long integer64;
bool is_char = false;
bool scale_db = false;
+ bool is_64bit = false;
/* Assumes decimal - precision based on number of digits */
if (!indio_dev->info->write_raw)
@@ -990,6 +992,9 @@ static ssize_t iio_write_channel_info(struct device *dev,
case IIO_VAL_CHAR:
is_char = true;
break;
+ case IIO_VAL_INT_64:
+ is_64bit = true;
+ break;
default:
return -EINVAL;
}
@@ -1000,6 +1005,13 @@ static ssize_t iio_write_channel_info(struct device *dev,
if (sscanf(buf, "%c", &ch) != 1)
return -EINVAL;
integer = ch;
+ } else if (is_64bit) {
+ ret = kstrtoll(buf, 0, &integer64);
+ if (ret)
+ return ret;
+
+ fract = (int)(integer64 >> 32);
+ integer = (int)(integer64 & 0xFFFFFFFF);
} else {
ret = __iio_str_to_fixpoint(buf, fract_mult, &integer, &fract,
scale_db);
--
2.48.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 6/6] iio: filter: admv8818: Support frequencies >= 2^32
2025-03-07 15:02 [PATCH v6 1/6] dt-bindings: iio: filter: Add lpf/hpf freq margins Sam Winchenbach
` (3 preceding siblings ...)
2025-03-07 15:02 ` [PATCH v6 5/6] driver core: Add support for writing 64 bit attrs Sam Winchenbach
@ 2025-03-07 15:02 ` Sam Winchenbach
2025-03-08 14:01 ` Jonathan Cameron
2025-03-10 9:22 ` [PATCH v6 1/6] dt-bindings: iio: filter: Add lpf/hpf freq margins Krzysztof Kozlowski
5 siblings, 1 reply; 13+ messages in thread
From: Sam Winchenbach @ 2025-03-07 15:02 UTC (permalink / raw)
To: linux-kernel
Cc: lars, Michael.Hennerich, antoniu.miclaus, jic23, robh, krzk+dt,
conor+dt, linux-iio, devicetree, sam.winchenbach, bpellegrino
From: Brian Pellegrino <bpellegrino@arka.org>
This patch allows writing u64 values to the ADMV8818's high and low-pass
filter frequencies. It includes the following changes:
- Rejects negative frequencies in admv8818_write_raw.
- Adds a write_raw_get_fmt function to admv8818's iio_info, returning
IIO_VAL_INT_64 for the high and low-pass filter 3dB frequency channels.
Fixes: f34fe888ad05 ("iio:filter:admv8818: add support for ADMV8818")
Signed-off-by: Brian Pellegrino <bpellegrino@arka.org>
Signed-off-by: Sam Winchenbach <sam.winchenbach@framepointer.org>
---
drivers/iio/filter/admv8818.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/iio/filter/admv8818.c b/drivers/iio/filter/admv8818.c
index e9602bfd4af7..9785533d0cdd 100644
--- a/drivers/iio/filter/admv8818.c
+++ b/drivers/iio/filter/admv8818.c
@@ -402,6 +402,19 @@ static int admv8818_read_lpf_freq(struct admv8818_state *st, u64 *lpf_freq)
return ret;
}
+static int admv8818_write_raw_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
+ return IIO_VAL_INT_64;
+ default:
+ return -EINVAL;
+ }
+}
+
static int admv8818_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long info)
@@ -410,6 +423,9 @@ static int admv8818_write_raw(struct iio_dev *indio_dev,
u64 freq = ((u64)val2 << 32 | (u32)val);
+ if ((s64)freq < 0)
+ return -EINVAL;
+
switch (info) {
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
return admv8818_lpf_select(st, freq);
@@ -571,6 +587,7 @@ static int admv8818_set_mode(struct iio_dev *indio_dev,
static const struct iio_info admv8818_info = {
.write_raw = admv8818_write_raw,
+ .write_raw_get_fmt = admv8818_write_raw_get_fmt,
.read_raw = admv8818_read_raw,
.debugfs_reg_access = &admv8818_reg_access,
};
--
2.48.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v6 5/6] driver core: Add support for writing 64 bit attrs
2025-03-07 15:02 ` [PATCH v6 5/6] driver core: Add support for writing 64 bit attrs Sam Winchenbach
@ 2025-03-08 14:00 ` Jonathan Cameron
0 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron @ 2025-03-08 14:00 UTC (permalink / raw)
To: Sam Winchenbach
Cc: linux-kernel, lars, Michael.Hennerich, antoniu.miclaus, robh,
krzk+dt, conor+dt, linux-iio, devicetree, bpellegrino
On Fri, 7 Mar 2025 10:02:15 -0500
Sam Winchenbach <sam.winchenbach@framepointer.org> wrote:
Patch title should be iio: core:
driver core is stuff in drivers/base/
> Prior to this patch it was only possible to read 64 bit integers.
>
> Signed-off-by: Sam Winchenbach <sam.winchenbach@framepointer.org>
> ---
> drivers/iio/industrialio-core.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
> index a2117ad1337d..b2436b8f3eea 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
> @@ -965,8 +965,10 @@ static ssize_t iio_write_channel_info(struct device *dev,
> struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
> int ret, fract_mult = 100000;
> int integer, fract = 0;
> + long long integer64;
> bool is_char = false;
> bool scale_db = false;
> + bool is_64bit = false;
>
> /* Assumes decimal - precision based on number of digits */
> if (!indio_dev->info->write_raw)
> @@ -990,6 +992,9 @@ static ssize_t iio_write_channel_info(struct device *dev,
> case IIO_VAL_CHAR:
> is_char = true;
> break;
> + case IIO_VAL_INT_64:
> + is_64bit = true;
> + break;
> default:
> return -EINVAL;
> }
> @@ -1000,6 +1005,13 @@ static ssize_t iio_write_channel_info(struct device *dev,
> if (sscanf(buf, "%c", &ch) != 1)
> return -EINVAL;
> integer = ch;
> + } else if (is_64bit) {
> + ret = kstrtoll(buf, 0, &integer64);
> + if (ret)
> + return ret;
> +
> + fract = (int)(integer64 >> 32);
> + integer = (int)(integer64 & 0xFFFFFFFF);
> } else {
> ret = __iio_str_to_fixpoint(buf, fract_mult, &integer, &fract,
> scale_db);
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v6 6/6] iio: filter: admv8818: Support frequencies >= 2^32
2025-03-07 15:02 ` [PATCH v6 6/6] iio: filter: admv8818: Support frequencies >= 2^32 Sam Winchenbach
@ 2025-03-08 14:01 ` Jonathan Cameron
2025-03-12 12:16 ` Sam Winchenbach
0 siblings, 1 reply; 13+ messages in thread
From: Jonathan Cameron @ 2025-03-08 14:01 UTC (permalink / raw)
To: Sam Winchenbach
Cc: linux-kernel, lars, Michael.Hennerich, antoniu.miclaus, robh,
krzk+dt, conor+dt, linux-iio, devicetree, bpellegrino
On Fri, 7 Mar 2025 10:02:16 -0500
Sam Winchenbach <sam.winchenbach@framepointer.org> wrote:
> From: Brian Pellegrino <bpellegrino@arka.org>
>
> This patch allows writing u64 values to the ADMV8818's high and low-pass
> filter frequencies. It includes the following changes:
>
> - Rejects negative frequencies in admv8818_write_raw.
> - Adds a write_raw_get_fmt function to admv8818's iio_info, returning
> IIO_VAL_INT_64 for the high and low-pass filter 3dB frequency channels.
>
> Fixes: f34fe888ad05 ("iio:filter:admv8818: add support for ADMV8818")
> Signed-off-by: Brian Pellegrino <bpellegrino@arka.org>
> Signed-off-by: Sam Winchenbach <sam.winchenbach@framepointer.org>
I only have that minor comment on patch 5. If nothing else comes up
and the dt binding ack comes in I may just tidy that up whilst applying.
> ---
> drivers/iio/filter/admv8818.c | 17 +++++++++++++++++
> 1 file changed, 17 insertions(+)
>
> diff --git a/drivers/iio/filter/admv8818.c b/drivers/iio/filter/admv8818.c
> index e9602bfd4af7..9785533d0cdd 100644
> --- a/drivers/iio/filter/admv8818.c
> +++ b/drivers/iio/filter/admv8818.c
> @@ -402,6 +402,19 @@ static int admv8818_read_lpf_freq(struct admv8818_state *st, u64 *lpf_freq)
> return ret;
> }
>
> +static int admv8818_write_raw_get_fmt(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + long mask)
> +{
> + switch (mask) {
> + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
> + case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
> + return IIO_VAL_INT_64;
> + default:
> + return -EINVAL;
> + }
> +}
> +
> static int admv8818_write_raw(struct iio_dev *indio_dev,
> struct iio_chan_spec const *chan,
> int val, int val2, long info)
> @@ -410,6 +423,9 @@ static int admv8818_write_raw(struct iio_dev *indio_dev,
>
> u64 freq = ((u64)val2 << 32 | (u32)val);
>
> + if ((s64)freq < 0)
> + return -EINVAL;
> +
> switch (info) {
> case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
> return admv8818_lpf_select(st, freq);
> @@ -571,6 +587,7 @@ static int admv8818_set_mode(struct iio_dev *indio_dev,
>
> static const struct iio_info admv8818_info = {
> .write_raw = admv8818_write_raw,
> + .write_raw_get_fmt = admv8818_write_raw_get_fmt,
> .read_raw = admv8818_read_raw,
> .debugfs_reg_access = &admv8818_reg_access,
> };
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v6 4/6] iio: filter: admv8818: fix range calculation
2025-03-07 15:02 ` [PATCH v6 4/6] iio: filter: admv8818: fix range calculation Sam Winchenbach
@ 2025-03-08 14:03 ` Jonathan Cameron
0 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron @ 2025-03-08 14:03 UTC (permalink / raw)
To: Sam Winchenbach
Cc: linux-kernel, lars, Michael.Hennerich, antoniu.miclaus, robh,
krzk+dt, conor+dt, linux-iio, devicetree, bpellegrino
On Fri, 7 Mar 2025 10:02:14 -0500
Sam Winchenbach <sam.winchenbach@framepointer.org> wrote:
> Search for the minimum error while ensuring that the LPF corner
> frequency is greater than the target, and the HPF corner frequency
> is lower than the target
>
> This fixes issues where the range calculations were suboptimal.
>
> Add two new DTS properties to set the margin between the input frequency
> and the calculated corner frequency
>
This is a bit fiddly so I'd like Antoniu or one of the other
ADI folk to take a look ideally. No more comments from me.
Jonathan
> Below is a generated table of the differences between the old algorithm
> and the new. This is a sweep from 0 to 20 GHz in 10 MHz steps.
> === HPF ===
> freq = 1750 MHz, 3db: bypass => 1750 MHz
> freq = 3400 MHz, 3db: 3310 => 3400 MHz
> freq = 3410 MHz, 3db: 3310 => 3400 MHz
> freq = 3420 MHz, 3db: 3310 => 3400 MHz
> freq = 3660 MHz, 3db: 3550 => 3656 MHz
> freq = 6600 MHz, 3db: 6479 => 6600 MHz
> freq = 6610 MHz, 3db: 6479 => 6600 MHz
> freq = 6620 MHz, 3db: 6479 => 6600 MHz
> freq = 6630 MHz, 3db: 6479 => 6600 MHz
> freq = 6640 MHz, 3db: 6479 => 6600 MHz
> freq = 6650 MHz, 3db: 6479 => 6600 MHz
> freq = 6660 MHz, 3db: 6479 => 6600 MHz
> freq = 6670 MHz, 3db: 6479 => 6600 MHz
> freq = 6680 MHz, 3db: 6479 => 6600 MHz
> freq = 6690 MHz, 3db: 6479 => 6600 MHz
> freq = 6700 MHz, 3db: 6479 => 6600 MHz
> freq = 6710 MHz, 3db: 6479 => 6600 MHz
> freq = 6720 MHz, 3db: 6479 => 6600 MHz
> freq = 6730 MHz, 3db: 6479 => 6600 MHz
> freq = 6960 MHz, 3db: 6736 => 6960 MHz
> freq = 6970 MHz, 3db: 6736 => 6960 MHz
> freq = 6980 MHz, 3db: 6736 => 6960 MHz
> freq = 6990 MHz, 3db: 6736 => 6960 MHz
> freq = 7320 MHz, 3db: 7249 => 7320 MHz
> freq = 7330 MHz, 3db: 7249 => 7320 MHz
> freq = 7340 MHz, 3db: 7249 => 7320 MHz
> freq = 7350 MHz, 3db: 7249 => 7320 MHz
> freq = 7360 MHz, 3db: 7249 => 7320 MHz
> freq = 7370 MHz, 3db: 7249 => 7320 MHz
> freq = 7380 MHz, 3db: 7249 => 7320 MHz
> freq = 7390 MHz, 3db: 7249 => 7320 MHz
> freq = 7400 MHz, 3db: 7249 => 7320 MHz
> freq = 7410 MHz, 3db: 7249 => 7320 MHz
> freq = 7420 MHz, 3db: 7249 => 7320 MHz
> freq = 7430 MHz, 3db: 7249 => 7320 MHz
> freq = 7440 MHz, 3db: 7249 => 7320 MHz
> freq = 7450 MHz, 3db: 7249 => 7320 MHz
> freq = 7460 MHz, 3db: 7249 => 7320 MHz
> freq = 7470 MHz, 3db: 7249 => 7320 MHz
> freq = 7480 MHz, 3db: 7249 => 7320 MHz
> freq = 7490 MHz, 3db: 7249 => 7320 MHz
> freq = 7500 MHz, 3db: 7249 => 7320 MHz
> freq = 12500 MHz, 3db: 12000 => 12500 MHz
>
> === LPF ===
> freq = 2050 MHz, 3db: bypass => 2050 MHz
> freq = 2170 MHz, 3db: 2290 => 2170 MHz
> freq = 2290 MHz, 3db: 2410 => 2290 MHz
> freq = 2410 MHz, 3db: 2530 => 2410 MHz
> freq = 2530 MHz, 3db: 2650 => 2530 MHz
> freq = 2650 MHz, 3db: 2770 => 2650 MHz
> freq = 2770 MHz, 3db: 2890 => 2770 MHz
> freq = 2890 MHz, 3db: 3010 => 2890 MHz
> freq = 3010 MHz, 3db: 3130 => 3010 MHz
> freq = 3130 MHz, 3db: 3250 => 3130 MHz
> freq = 3250 MHz, 3db: 3370 => 3250 MHz
> freq = 3260 MHz, 3db: 3370 => 3350 MHz
> freq = 3270 MHz, 3db: 3370 => 3350 MHz
> freq = 3280 MHz, 3db: 3370 => 3350 MHz
> freq = 3290 MHz, 3db: 3370 => 3350 MHz
> freq = 3300 MHz, 3db: 3370 => 3350 MHz
> freq = 3310 MHz, 3db: 3370 => 3350 MHz
> freq = 3320 MHz, 3db: 3370 => 3350 MHz
> freq = 3330 MHz, 3db: 3370 => 3350 MHz
> freq = 3340 MHz, 3db: 3370 => 3350 MHz
> freq = 3350 MHz, 3db: 3370 => 3350 MHz
> freq = 3370 MHz, 3db: 3490 => 3370 MHz
> freq = 3490 MHz, 3db: 3610 => 3490 MHz
> freq = 3610 MHz, 3db: 3730 => 3610 MHz
> freq = 3730 MHz, 3db: 3850 => 3730 MHz
> freq = 3850 MHz, 3db: 3870 => 3850 MHz
> freq = 3870 MHz, 3db: 4130 => 3870 MHz
> freq = 4130 MHz, 3db: 4390 => 4130 MHz
> freq = 4390 MHz, 3db: 4650 => 4390 MHz
> freq = 4650 MHz, 3db: 4910 => 4650 MHz
> freq = 4910 MHz, 3db: 5170 => 4910 MHz
> freq = 5170 MHz, 3db: 5430 => 5170 MHz
> freq = 5430 MHz, 3db: 5690 => 5430 MHz
> freq = 5690 MHz, 3db: 5950 => 5690 MHz
> freq = 5950 MHz, 3db: 6210 => 5950 MHz
> freq = 6210 MHz, 3db: 6470 => 6210 MHz
> freq = 6470 MHz, 3db: 6730 => 6470 MHz
> freq = 6730 MHz, 3db: 6990 => 6730 MHz
> freq = 6990 MHz, 3db: 7250 => 6990 MHz
> freq = 7000 MHz, 3db: 7250 => 7000 MHz
> freq = 7250 MHz, 3db: 7400 => 7250 MHz
> freq = 7400 MHz, 3db: 7800 => 7400 MHz
> freq = 7800 MHz, 3db: 8200 => 7800 MHz
> freq = 8200 MHz, 3db: 8600 => 8200 MHz
> freq = 8600 MHz, 3db: 9000 => 8600 MHz
> freq = 9000 MHz, 3db: 9400 => 9000 MHz
> freq = 9400 MHz, 3db: 9800 => 9400 MHz
> freq = 9800 MHz, 3db: 10200 => 9800 MHz
> freq = 10200 MHz, 3db: 10600 => 10200 MHz
> freq = 10600 MHz, 3db: 11000 => 10600 MHz
> freq = 11000 MHz, 3db: 11400 => 11000 MHz
> freq = 11400 MHz, 3db: 11800 => 11400 MHz
> freq = 11800 MHz, 3db: 12200 => 11800 MHz
> freq = 12200 MHz, 3db: 12600 => 12200 MHz
> freq = 12210 MHz, 3db: 12600 => 12550 MHz
> freq = 12220 MHz, 3db: 12600 => 12550 MHz
> freq = 12230 MHz, 3db: 12600 => 12550 MHz
> freq = 12240 MHz, 3db: 12600 => 12550 MHz
> freq = 12250 MHz, 3db: 12600 => 12550 MHz
> freq = 12260 MHz, 3db: 12600 => 12550 MHz
> freq = 12270 MHz, 3db: 12600 => 12550 MHz
> freq = 12280 MHz, 3db: 12600 => 12550 MHz
> freq = 12290 MHz, 3db: 12600 => 12550 MHz
> freq = 12300 MHz, 3db: 12600 => 12550 MHz
> freq = 12310 MHz, 3db: 12600 => 12550 MHz
> freq = 12320 MHz, 3db: 12600 => 12550 MHz
> freq = 12330 MHz, 3db: 12600 => 12550 MHz
> freq = 12340 MHz, 3db: 12600 => 12550 MHz
> freq = 12350 MHz, 3db: 12600 => 12550 MHz
> freq = 12360 MHz, 3db: 12600 => 12550 MHz
> freq = 12370 MHz, 3db: 12600 => 12550 MHz
> freq = 12380 MHz, 3db: 12600 => 12550 MHz
> freq = 12390 MHz, 3db: 12600 => 12550 MHz
> freq = 12400 MHz, 3db: 12600 => 12550 MHz
> freq = 12410 MHz, 3db: 12600 => 12550 MHz
> freq = 12420 MHz, 3db: 12600 => 12550 MHz
> freq = 12430 MHz, 3db: 12600 => 12550 MHz
> freq = 12440 MHz, 3db: 12600 => 12550 MHz
> freq = 12450 MHz, 3db: 12600 => 12550 MHz
> freq = 12460 MHz, 3db: 12600 => 12550 MHz
> freq = 12470 MHz, 3db: 12600 => 12550 MHz
> freq = 12480 MHz, 3db: 12600 => 12550 MHz
> freq = 12490 MHz, 3db: 12600 => 12550 MHz
> freq = 12500 MHz, 3db: 12600 => 12550 MHz
> freq = 12510 MHz, 3db: 12600 => 12550 MHz
> freq = 12520 MHz, 3db: 12600 => 12550 MHz
> freq = 12530 MHz, 3db: 12600 => 12550 MHz
> freq = 12540 MHz, 3db: 12600 => 12550 MHz
> freq = 12550 MHz, 3db: 12600 => 12550 MHz
> freq = 12600 MHz, 3db: 13000 => 12600 MHz
> freq = 12610 MHz, 3db: 13000 => 12970 MHz
> freq = 12620 MHz, 3db: 13000 => 12970 MHz
> freq = 12630 MHz, 3db: 13000 => 12970 MHz
> freq = 12640 MHz, 3db: 13000 => 12970 MHz
> freq = 12650 MHz, 3db: 13000 => 12970 MHz
> freq = 12660 MHz, 3db: 13000 => 12970 MHz
> freq = 12670 MHz, 3db: 13000 => 12970 MHz
> freq = 12680 MHz, 3db: 13000 => 12970 MHz
> freq = 12690 MHz, 3db: 13000 => 12970 MHz
> freq = 12700 MHz, 3db: 13000 => 12970 MHz
> freq = 12710 MHz, 3db: 13000 => 12970 MHz
> freq = 12720 MHz, 3db: 13000 => 12970 MHz
> freq = 12730 MHz, 3db: 13000 => 12970 MHz
> freq = 12740 MHz, 3db: 13000 => 12970 MHz
> freq = 12750 MHz, 3db: 13000 => 12970 MHz
> freq = 12760 MHz, 3db: 13000 => 12970 MHz
> freq = 12770 MHz, 3db: 13000 => 12970 MHz
> freq = 12780 MHz, 3db: 13000 => 12970 MHz
> freq = 12790 MHz, 3db: 13000 => 12970 MHz
> freq = 12800 MHz, 3db: 13000 => 12970 MHz
> freq = 12810 MHz, 3db: 13000 => 12970 MHz
> freq = 12820 MHz, 3db: 13000 => 12970 MHz
> freq = 12830 MHz, 3db: 13000 => 12970 MHz
> freq = 12840 MHz, 3db: 13000 => 12970 MHz
> freq = 12850 MHz, 3db: 13000 => 12970 MHz
> freq = 12860 MHz, 3db: 13000 => 12970 MHz
> freq = 12870 MHz, 3db: 13000 => 12970 MHz
> freq = 12880 MHz, 3db: 13000 => 12970 MHz
> freq = 12890 MHz, 3db: 13000 => 12970 MHz
> freq = 12900 MHz, 3db: 13000 => 12970 MHz
> freq = 12910 MHz, 3db: 13000 => 12970 MHz
> freq = 12920 MHz, 3db: 13000 => 12970 MHz
> freq = 12930 MHz, 3db: 13000 => 12970 MHz
> freq = 12940 MHz, 3db: 13000 => 12970 MHz
> freq = 12950 MHz, 3db: 13000 => 12970 MHz
> freq = 12960 MHz, 3db: 13000 => 12970 MHz
> freq = 12970 MHz, 3db: 13000 => 12970 MHz
> freq = 13000 MHz, 3db: 13390 => 13000 MHz
> freq = 13390 MHz, 3db: 13810 => 13390 MHz
> freq = 13810 MHz, 3db: 14230 => 13810 MHz
> freq = 14230 MHz, 3db: 14650 => 14230 MHz
> freq = 14650 MHz, 3db: 15070 => 14650 MHz
> freq = 15070 MHz, 3db: 15490 => 15070 MHz
> freq = 15490 MHz, 3db: 15910 => 15490 MHz
> freq = 15910 MHz, 3db: 16330 => 15910 MHz
> freq = 16330 MHz, 3db: 16750 => 16330 MHz
> freq = 16750 MHz, 3db: 17170 => 16750 MHz
> freq = 17170 MHz, 3db: 17590 => 17170 MHz
> freq = 17590 MHz, 3db: 18010 => 17590 MHz
> freq = 18010 MHz, 3db: 18430 => 18010 MHz
> freq = 18430 MHz, 3db: 18850 => 18430 MHz
> freq = 18850 MHz, 3db: bypass => 18850 MHz
>
> Fixes: f34fe888ad05 ("iio:filter:admv8818: add support for ADMV8818")
> Signed-off-by: Sam Winchenbach <sam.winchenbach@framepointer.org>
> ---
> drivers/iio/filter/admv8818.c | 205 +++++++++++++++++++++++++---------
> 1 file changed, 152 insertions(+), 53 deletions(-)
>
> diff --git a/drivers/iio/filter/admv8818.c b/drivers/iio/filter/admv8818.c
> index a059282e0251..e9602bfd4af7 100644
> --- a/drivers/iio/filter/admv8818.c
> +++ b/drivers/iio/filter/admv8818.c
> @@ -14,6 +14,7 @@
> #include <linux/mod_devicetable.h>
> #include <linux/mutex.h>
> #include <linux/notifier.h>
> +#include <linux/property.h>
> #include <linux/regmap.h>
> #include <linux/spi/spi.h>
> #include <linux/units.h>
> @@ -70,6 +71,16 @@
> #define ADMV8818_HPF_WR0_MSK GENMASK(7, 4)
> #define ADMV8818_LPF_WR0_MSK GENMASK(3, 0)
>
> +#define ADMV8818_BAND_BYPASS 0
> +#define ADMV8818_BAND_MIN 1
> +#define ADMV8818_BAND_MAX 4
> +#define ADMV8818_BAND_CORNER_LOW 0
> +#define ADMV8818_BAND_CORNER_HIGH 1
> +
> +#define ADMV8818_STATE_MIN 0
> +#define ADMV8818_STATE_MAX 15
> +#define ADMV8818_NUM_STATES 16
> +
> enum {
> ADMV8818_BW_FREQ,
> ADMV8818_CENTER_FREQ
> @@ -90,16 +101,20 @@ struct admv8818_state {
> struct mutex lock;
> unsigned int filter_mode;
> u64 cf_hz;
> + u64 lpf_margin_hz;
> + u64 hpf_margin_hz;
> };
>
> -static const unsigned long long freq_range_hpf[4][2] = {
> +static const unsigned long long freq_range_hpf[5][2] = {
> + {0ULL, 0ULL}, /* bypass */
> {1750000000ULL, 3550000000ULL},
> {3400000000ULL, 7250000000ULL},
> {6600000000, 12000000000},
> {12500000000, 19900000000}
> };
>
> -static const unsigned long long freq_range_lpf[4][2] = {
> +static const unsigned long long freq_range_lpf[5][2] = {
> + {U64_MAX, U64_MAX}, /* bypass */
> {2050000000ULL, 3850000000ULL},
> {3350000000ULL, 7250000000ULL},
> {7000000000, 13000000000},
> @@ -121,44 +136,59 @@ static const char * const admv8818_modes[] = {
>
> static int __admv8818_hpf_select(struct admv8818_state *st, u64 freq)
> {
> - unsigned int hpf_step = 0, hpf_band = 0, i, j;
> - u64 freq_step;
> - int ret;
> + int band, state, ret;
> + unsigned int hpf_state = ADMV8818_STATE_MIN, hpf_band = ADMV8818_BAND_BYPASS;
> + u64 freq_error, min_freq_error, freq_corner, freq_step;
>
> - if (freq < freq_range_hpf[0][0])
> + if (freq < freq_range_hpf[ADMV8818_BAND_MIN][ADMV8818_BAND_CORNER_LOW])
> goto hpf_write;
>
> - if (freq > freq_range_hpf[3][1]) {
> - hpf_step = 15;
> - hpf_band = 4;
> -
> + if (freq >= freq_range_hpf[ADMV8818_BAND_MAX][ADMV8818_BAND_CORNER_HIGH]) {
> + hpf_state = ADMV8818_STATE_MAX;
> + hpf_band = ADMV8818_BAND_MAX;
> goto hpf_write;
> }
>
> - for (i = 0; i < 4; i++) {
> - freq_step = div_u64((freq_range_hpf[i][1] -
> - freq_range_hpf[i][0]), 15);
> + /* Close HPF frequency gap between 12 and 12.5 GHz */
> + if (freq >= 12000ULL * HZ_PER_MHZ && freq < 12500ULL * HZ_PER_MHZ) {
> + hpf_state = ADMV8818_STATE_MAX;
> + hpf_band = 3;
> + goto hpf_write;
> + }
>
> - if (freq > freq_range_hpf[i][0] &&
> - (freq < freq_range_hpf[i][1] + freq_step)) {
> - hpf_band = i + 1;
> + min_freq_error = U64_MAX;
> + for (band = ADMV8818_BAND_MIN; band <= ADMV8818_BAND_MAX; band++) {
> + /*
> + * This (and therefore all other ranges) have a corner
> + * frequency higher than the target frequency.
> + */
> + if (freq_range_hpf[band][ADMV8818_BAND_CORNER_LOW] > freq)
> + break;
>
> - for (j = 1; j <= 16; j++) {
> - if (freq < (freq_range_hpf[i][0] + (freq_step * j))) {
> - hpf_step = j - 1;
> - break;
> - }
> + freq_step = freq_range_hpf[band][ADMV8818_BAND_CORNER_HIGH] -
> + freq_range_hpf[band][ADMV8818_BAND_CORNER_LOW];
> + freq_step = div_u64(freq_step, ADMV8818_NUM_STATES - 1);
> +
> + for (state = ADMV8818_STATE_MIN; state <= ADMV8818_STATE_MAX; state++) {
> + freq_corner = freq_range_hpf[band][ADMV8818_BAND_CORNER_LOW] +
> + freq_step * state;
> +
> + /*
> + * This (and therefore all other states) have a corner
> + * frequency higher than the target frequency.
> + */
> + if (freq_corner > freq)
> + break;
> +
> + freq_error = freq - freq_corner;
> + if (freq_error < min_freq_error) {
> + min_freq_error = freq_error;
> + hpf_state = state;
> + hpf_band = band;
> }
> - break;
> }
> }
>
> - /* Close HPF frequency gap between 12 and 12.5 GHz */
> - if (freq >= 12000ULL * HZ_PER_MHZ && freq < 12500ULL * HZ_PER_MHZ) {
> - hpf_band = 3;
> - hpf_step = 15;
> - }
> -
> hpf_write:
> ret = regmap_update_bits(st->regmap, ADMV8818_REG_WR0_SW,
> ADMV8818_SW_IN_SET_WR0_MSK |
> @@ -170,7 +200,7 @@ static int __admv8818_hpf_select(struct admv8818_state *st, u64 freq)
>
> return regmap_update_bits(st->regmap, ADMV8818_REG_WR0_FILTER,
> ADMV8818_HPF_WR0_MSK,
> - FIELD_PREP(ADMV8818_HPF_WR0_MSK, hpf_step));
> + FIELD_PREP(ADMV8818_HPF_WR0_MSK, hpf_state));
> }
>
> static int admv8818_hpf_select(struct admv8818_state *st, u64 freq)
> @@ -186,31 +216,52 @@ static int admv8818_hpf_select(struct admv8818_state *st, u64 freq)
>
> static int __admv8818_lpf_select(struct admv8818_state *st, u64 freq)
> {
> - unsigned int lpf_step = 0, lpf_band = 0, i, j;
> - u64 freq_step;
> - int ret;
> + int band, state, ret;
> + unsigned int lpf_state = ADMV8818_STATE_MIN, lpf_band = ADMV8818_BAND_BYPASS;
> + u64 freq_error, min_freq_error, freq_corner, freq_step;
>
> - if (freq > freq_range_lpf[3][1])
> + if (freq > freq_range_lpf[ADMV8818_BAND_MAX][ADMV8818_BAND_CORNER_HIGH])
> goto lpf_write;
>
> - if (freq < freq_range_lpf[0][0]) {
> - lpf_band = 1;
> -
> + if (freq < freq_range_lpf[ADMV8818_BAND_MIN][ADMV8818_BAND_CORNER_LOW]) {
> + lpf_state = ADMV8818_STATE_MIN;
> + lpf_band = ADMV8818_BAND_MIN;
> goto lpf_write;
> }
>
> - for (i = 0; i < 4; i++) {
> - if (freq > freq_range_lpf[i][0] && freq < freq_range_lpf[i][1]) {
> - lpf_band = i + 1;
> - freq_step = div_u64((freq_range_lpf[i][1] - freq_range_lpf[i][0]), 15);
> + min_freq_error = U64_MAX;
> + for (band = ADMV8818_BAND_MAX; band >= ADMV8818_BAND_MIN; --band) {
> + /*
> + * At this point the highest corner frequency of
> + * all remaining ranges is below the target.
> + * LPF corner should be >= the target.
> + */
> + if (freq > freq_range_lpf[band][ADMV8818_BAND_CORNER_HIGH])
> + break;
> +
> + freq_step = freq_range_lpf[band][ADMV8818_BAND_CORNER_HIGH] -
> + freq_range_lpf[band][ADMV8818_BAND_CORNER_LOW];
> + freq_step = div_u64(freq_step, ADMV8818_NUM_STATES - 1);
> +
> + for (state = ADMV8818_STATE_MAX; state >= ADMV8818_STATE_MIN; --state) {
>
> - for (j = 0; j <= 15; j++) {
> - if (freq < (freq_range_lpf[i][0] + (freq_step * j))) {
> - lpf_step = j;
> - break;
> - }
> + freq_corner = freq_range_lpf[band][ADMV8818_BAND_CORNER_LOW] +
> + state * freq_step;
> +
> + /*
> + * At this point all other states in range will
> + * place the corner frequency below the target
> + * LPF corner should >= the target.
> + */
> + if (freq > freq_corner)
> + break;
> +
> + freq_error = freq_corner - freq;
> + if (freq_error < min_freq_error) {
> + min_freq_error = freq_error;
> + lpf_state = state;
> + lpf_band = band;
> }
> - break;
> }
> }
>
> @@ -225,7 +276,7 @@ static int __admv8818_lpf_select(struct admv8818_state *st, u64 freq)
>
> return regmap_update_bits(st->regmap, ADMV8818_REG_WR0_FILTER,
> ADMV8818_LPF_WR0_MSK,
> - FIELD_PREP(ADMV8818_LPF_WR0_MSK, lpf_step));
> + FIELD_PREP(ADMV8818_LPF_WR0_MSK, lpf_state));
> }
>
> static int admv8818_lpf_select(struct admv8818_state *st, u64 freq)
> @@ -242,16 +293,28 @@ static int admv8818_lpf_select(struct admv8818_state *st, u64 freq)
> static int admv8818_rfin_band_select(struct admv8818_state *st)
> {
> int ret;
> + u64 hpf_corner_target, lpf_corner_target;
>
> st->cf_hz = clk_get_rate(st->clkin);
>
> + /* Check for underflow */
> + if (st->cf_hz > st->hpf_margin_hz)
> + hpf_corner_target = st->cf_hz - st->hpf_margin_hz;
> + else
> + hpf_corner_target = 0;
> +
> + /* Check for overflow */
> + lpf_corner_target = st->cf_hz + st->lpf_margin_hz;
> + if (lpf_corner_target < st->cf_hz)
> + lpf_corner_target = U64_MAX;
> +
> mutex_lock(&st->lock);
>
> - ret = __admv8818_hpf_select(st, st->cf_hz);
> + ret = __admv8818_hpf_select(st, hpf_corner_target);
> if (ret)
> goto exit;
>
> - ret = __admv8818_lpf_select(st, st->cf_hz);
> + ret = __admv8818_lpf_select(st, lpf_corner_target);
> exit:
> mutex_unlock(&st->lock);
> return ret;
> @@ -278,8 +341,11 @@ static int __admv8818_read_hpf_freq(struct admv8818_state *st, u64 *hpf_freq)
>
> hpf_state = FIELD_GET(ADMV8818_HPF_WR0_MSK, data);
>
> - *hpf_freq = div_u64(freq_range_hpf[hpf_band - 1][1] - freq_range_hpf[hpf_band - 1][0], 15);
> - *hpf_freq = freq_range_hpf[hpf_band - 1][0] + (*hpf_freq * hpf_state);
> + *hpf_freq = freq_range_hpf[hpf_band][ADMV8818_BAND_CORNER_HIGH] -
> + freq_range_hpf[hpf_band][ADMV8818_BAND_CORNER_LOW];
> + *hpf_freq = div_u64(*hpf_freq, ADMV8818_NUM_STATES - 1);
> + *hpf_freq = freq_range_hpf[hpf_band][ADMV8818_BAND_CORNER_LOW] +
> + (*hpf_freq * hpf_state);
>
> return ret;
> }
> @@ -316,8 +382,11 @@ static int __admv8818_read_lpf_freq(struct admv8818_state *st, u64 *lpf_freq)
>
> lpf_state = FIELD_GET(ADMV8818_LPF_WR0_MSK, data);
>
> - *lpf_freq = div_u64(freq_range_lpf[lpf_band - 1][1] - freq_range_lpf[lpf_band - 1][0], 15);
> - *lpf_freq = freq_range_lpf[lpf_band - 1][0] + (*lpf_freq * lpf_state);
> + *lpf_freq = freq_range_lpf[lpf_band][ADMV8818_BAND_CORNER_HIGH] -
> + freq_range_lpf[lpf_band][ADMV8818_BAND_CORNER_LOW];
> + *lpf_freq = div_u64(*lpf_freq, ADMV8818_NUM_STATES - 1);
> + *lpf_freq = freq_range_lpf[lpf_band][ADMV8818_BAND_CORNER_LOW] +
> + (*lpf_freq * lpf_state);
>
> return ret;
> }
> @@ -647,6 +716,32 @@ static int admv8818_clk_setup(struct admv8818_state *st)
> return devm_add_action_or_reset(&spi->dev, admv8818_clk_notifier_unreg, st);
> }
>
> +static int admv8818_read_properties(struct admv8818_state *st)
> +{
> + struct spi_device *spi = st->spi;
> + u32 mhz;
> + int ret;
> +
> + ret = device_property_read_u32(&spi->dev, "adi,lpf-margin-mhz", &mhz);
> + if (ret == 0)
> + st->lpf_margin_hz = (u64)mhz * HZ_PER_MHZ;
> + else if (ret == -EINVAL)
> + st->lpf_margin_hz = 0;
> + else
> + return ret;
> +
> +
> + ret = device_property_read_u32(&spi->dev, "adi,hpf-margin-mhz", &mhz);
> + if (ret == 0)
> + st->hpf_margin_hz = (u64)mhz * HZ_PER_MHZ;
> + else if (ret == -EINVAL)
> + st->hpf_margin_hz = 0;
> + else if (ret < 0)
> + return ret;
> +
> + return 0;
> +}
> +
> static int admv8818_probe(struct spi_device *spi)
> {
> struct iio_dev *indio_dev;
> @@ -678,6 +773,10 @@ static int admv8818_probe(struct spi_device *spi)
>
> mutex_init(&st->lock);
>
> + ret = admv8818_read_properties(st);
> + if (ret)
> + return ret;
> +
> ret = admv8818_init(st);
> if (ret)
> return ret;
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v6 1/6] dt-bindings: iio: filter: Add lpf/hpf freq margins
2025-03-07 15:02 [PATCH v6 1/6] dt-bindings: iio: filter: Add lpf/hpf freq margins Sam Winchenbach
` (4 preceding siblings ...)
2025-03-07 15:02 ` [PATCH v6 6/6] iio: filter: admv8818: Support frequencies >= 2^32 Sam Winchenbach
@ 2025-03-10 9:22 ` Krzysztof Kozlowski
5 siblings, 0 replies; 13+ messages in thread
From: Krzysztof Kozlowski @ 2025-03-10 9:22 UTC (permalink / raw)
To: Sam Winchenbach
Cc: linux-kernel, lars, Michael.Hennerich, antoniu.miclaus, jic23,
robh, krzk+dt, conor+dt, linux-iio, devicetree, bpellegrino
On Fri, Mar 07, 2025 at 10:02:11AM -0500, Sam Winchenbach wrote:
> Adds two properties to add a margin when automatically finding the
> corner frequencies.
>
> Signed-off-by: Sam Winchenbach <sam.winchenbach@framepointer.org>
> ---
> .../bindings/iio/filter/adi,admv8818.yaml | 20 +++++++++++++++++++
> 1 file changed, 20 insertions(+)
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v6 6/6] iio: filter: admv8818: Support frequencies >= 2^32
2025-03-08 14:01 ` Jonathan Cameron
@ 2025-03-12 12:16 ` Sam Winchenbach
2025-03-15 18:26 ` Jonathan Cameron
0 siblings, 1 reply; 13+ messages in thread
From: Sam Winchenbach @ 2025-03-12 12:16 UTC (permalink / raw)
To: Jonathan Cameron
Cc: linux-kernel, lars, Michael.Hennerich, antoniu.miclaus, robh,
krzk+dt, conor+dt, linux-iio, devicetree, bpellegrino
On Sat, Mar 08, 2025 at 02:01:43PM +0000, Jonathan Cameron wrote:
> On Fri, 7 Mar 2025 10:02:16 -0500
> Sam Winchenbach <sam.winchenbach@framepointer.org> wrote:
>
> > From: Brian Pellegrino <bpellegrino@arka.org>
> >
> > This patch allows writing u64 values to the ADMV8818's high and low-pass
> > filter frequencies. It includes the following changes:
> >
> > - Rejects negative frequencies in admv8818_write_raw.
> > - Adds a write_raw_get_fmt function to admv8818's iio_info, returning
> > IIO_VAL_INT_64 for the high and low-pass filter 3dB frequency channels.
> >
> > Fixes: f34fe888ad05 ("iio:filter:admv8818: add support for ADMV8818")
> > Signed-off-by: Brian Pellegrino <bpellegrino@arka.org>
> > Signed-off-by: Sam Winchenbach <sam.winchenbach@framepointer.org>
> I only have that minor comment on patch 5. If nothing else comes up
> and the dt binding ack comes in I may just tidy that up whilst applying.
>
Sounds good. If given the opportunity I would like to submit
the patchset once more; I would like to use my work email
for author and signoff, and use the framepointer address
as an envelope. If I do this, I can update patch 5 as noted.
Would that be ok?
Thanks,
-Sam
> > ---
> > drivers/iio/filter/admv8818.c | 17 +++++++++++++++++
> > 1 file changed, 17 insertions(+)
> >
> > diff --git a/drivers/iio/filter/admv8818.c b/drivers/iio/filter/admv8818.c
> > index e9602bfd4af7..9785533d0cdd 100644
> > --- a/drivers/iio/filter/admv8818.c
> > +++ b/drivers/iio/filter/admv8818.c
> > @@ -402,6 +402,19 @@ static int admv8818_read_lpf_freq(struct admv8818_state *st, u64 *lpf_freq)
> > return ret;
> > }
> >
> > +static int admv8818_write_raw_get_fmt(struct iio_dev *indio_dev,
> > + struct iio_chan_spec const *chan,
> > + long mask)
> > +{
> > + switch (mask) {
> > + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
> > + case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
> > + return IIO_VAL_INT_64;
> > + default:
> > + return -EINVAL;
> > + }
> > +}
> > +
> > static int admv8818_write_raw(struct iio_dev *indio_dev,
> > struct iio_chan_spec const *chan,
> > int val, int val2, long info)
> > @@ -410,6 +423,9 @@ static int admv8818_write_raw(struct iio_dev *indio_dev,
> >
> > u64 freq = ((u64)val2 << 32 | (u32)val);
> >
> > + if ((s64)freq < 0)
> > + return -EINVAL;
> > +
> > switch (info) {
> > case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
> > return admv8818_lpf_select(st, freq);
> > @@ -571,6 +587,7 @@ static int admv8818_set_mode(struct iio_dev *indio_dev,
> >
> > static const struct iio_info admv8818_info = {
> > .write_raw = admv8818_write_raw,
> > + .write_raw_get_fmt = admv8818_write_raw_get_fmt,
> > .read_raw = admv8818_read_raw,
> > .debugfs_reg_access = &admv8818_reg_access,
> > };
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v6 6/6] iio: filter: admv8818: Support frequencies >= 2^32
2025-03-12 12:16 ` Sam Winchenbach
@ 2025-03-15 18:26 ` Jonathan Cameron
2025-03-16 13:54 ` Sam Winchenbach
0 siblings, 1 reply; 13+ messages in thread
From: Jonathan Cameron @ 2025-03-15 18:26 UTC (permalink / raw)
To: Sam Winchenbach
Cc: linux-kernel, lars, Michael.Hennerich, antoniu.miclaus, robh,
krzk+dt, conor+dt, linux-iio, devicetree, bpellegrino
On Wed, 12 Mar 2025 08:16:00 -0400
Sam Winchenbach <sam.winchenbach@framepointer.org> wrote:
> On Sat, Mar 08, 2025 at 02:01:43PM +0000, Jonathan Cameron wrote:
> > On Fri, 7 Mar 2025 10:02:16 -0500
> > Sam Winchenbach <sam.winchenbach@framepointer.org> wrote:
> >
> > > From: Brian Pellegrino <bpellegrino@arka.org>
> > >
> > > This patch allows writing u64 values to the ADMV8818's high and low-pass
> > > filter frequencies. It includes the following changes:
> > >
> > > - Rejects negative frequencies in admv8818_write_raw.
> > > - Adds a write_raw_get_fmt function to admv8818's iio_info, returning
> > > IIO_VAL_INT_64 for the high and low-pass filter 3dB frequency channels.
> > >
> > > Fixes: f34fe888ad05 ("iio:filter:admv8818: add support for ADMV8818")
> > > Signed-off-by: Brian Pellegrino <bpellegrino@arka.org>
> > > Signed-off-by: Sam Winchenbach <sam.winchenbach@framepointer.org>
> > I only have that minor comment on patch 5. If nothing else comes up
> > and the dt binding ack comes in I may just tidy that up whilst applying.
> >
>
> Sounds good. If given the opportunity I would like to submit
> the patchset once more; I would like to use my work email
> for author and signoff, and use the framepointer address
> as an envelope. If I do this, I can update patch 5 as noted.
> Would that be ok?
>
Absolutely. That's fine.
> Thanks,
> -Sam
>
> > > ---
> > > drivers/iio/filter/admv8818.c | 17 +++++++++++++++++
> > > 1 file changed, 17 insertions(+)
> > >
> > > diff --git a/drivers/iio/filter/admv8818.c b/drivers/iio/filter/admv8818.c
> > > index e9602bfd4af7..9785533d0cdd 100644
> > > --- a/drivers/iio/filter/admv8818.c
> > > +++ b/drivers/iio/filter/admv8818.c
> > > @@ -402,6 +402,19 @@ static int admv8818_read_lpf_freq(struct admv8818_state *st, u64 *lpf_freq)
> > > return ret;
> > > }
> > >
> > > +static int admv8818_write_raw_get_fmt(struct iio_dev *indio_dev,
> > > + struct iio_chan_spec const *chan,
> > > + long mask)
> > > +{
> > > + switch (mask) {
> > > + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
> > > + case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
> > > + return IIO_VAL_INT_64;
> > > + default:
> > > + return -EINVAL;
> > > + }
> > > +}
> > > +
> > > static int admv8818_write_raw(struct iio_dev *indio_dev,
> > > struct iio_chan_spec const *chan,
> > > int val, int val2, long info)
> > > @@ -410,6 +423,9 @@ static int admv8818_write_raw(struct iio_dev *indio_dev,
> > >
> > > u64 freq = ((u64)val2 << 32 | (u32)val);
> > >
> > > + if ((s64)freq < 0)
> > > + return -EINVAL;
> > > +
> > > switch (info) {
> > > case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
> > > return admv8818_lpf_select(st, freq);
> > > @@ -571,6 +587,7 @@ static int admv8818_set_mode(struct iio_dev *indio_dev,
> > >
> > > static const struct iio_info admv8818_info = {
> > > .write_raw = admv8818_write_raw,
> > > + .write_raw_get_fmt = admv8818_write_raw_get_fmt,
> > > .read_raw = admv8818_read_raw,
> > > .debugfs_reg_access = &admv8818_reg_access,
> > > };
> >
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v6 6/6] iio: filter: admv8818: Support frequencies >= 2^32
2025-03-15 18:26 ` Jonathan Cameron
@ 2025-03-16 13:54 ` Sam Winchenbach
0 siblings, 0 replies; 13+ messages in thread
From: Sam Winchenbach @ 2025-03-16 13:54 UTC (permalink / raw)
To: Jonathan Cameron
Cc: linux-kernel, lars, Michael.Hennerich, antoniu.miclaus, robh,
krzk+dt, conor+dt, linux-iio, devicetree, bpellegrino
On Sat, Mar 15, 2025 at 06:26:05PM +0000, Jonathan Cameron wrote:
> On Wed, 12 Mar 2025 08:16:00 -0400
> Sam Winchenbach <sam.winchenbach@framepointer.org> wrote:
>
> > On Sat, Mar 08, 2025 at 02:01:43PM +0000, Jonathan Cameron wrote:
> > > On Fri, 7 Mar 2025 10:02:16 -0500
> > > Sam Winchenbach <sam.winchenbach@framepointer.org> wrote:
> > >
> > > > From: Brian Pellegrino <bpellegrino@arka.org>
> > > >
> > > > This patch allows writing u64 values to the ADMV8818's high and low-pass
> > > > filter frequencies. It includes the following changes:
> > > >
> > > > - Rejects negative frequencies in admv8818_write_raw.
> > > > - Adds a write_raw_get_fmt function to admv8818's iio_info, returning
> > > > IIO_VAL_INT_64 for the high and low-pass filter 3dB frequency channels.
> > > >
> > > > Fixes: f34fe888ad05 ("iio:filter:admv8818: add support for ADMV8818")
> > > > Signed-off-by: Brian Pellegrino <bpellegrino@arka.org>
> > > > Signed-off-by: Sam Winchenbach <sam.winchenbach@framepointer.org>
> > > I only have that minor comment on patch 5. If nothing else comes up
> > > and the dt binding ack comes in I may just tidy that up whilst applying.
> > >
> >
> > Sounds good. If given the opportunity I would like to submit
> > the patchset once more; I would like to use my work email
> > for author and signoff, and use the framepointer address
> > as an envelope. If I do this, I can update patch 5 as noted.
> > Would that be ok?
> >
> Absolutely. That's fine.
>
Done, patch v7 is up.
The only changes are:
* "driver core:" -> "iio: core:"
* "sam.winchenach@framepointer.org" -> "swinchenbach@arka.org"
Thanks,
-Sam
> > Thanks,
> > -Sam
> >
> > > > ---
> > > > drivers/iio/filter/admv8818.c | 17 +++++++++++++++++
> > > > 1 file changed, 17 insertions(+)
> > > >
> > > > diff --git a/drivers/iio/filter/admv8818.c b/drivers/iio/filter/admv8818.c
> > > > index e9602bfd4af7..9785533d0cdd 100644
> > > > --- a/drivers/iio/filter/admv8818.c
> > > > +++ b/drivers/iio/filter/admv8818.c
> > > > @@ -402,6 +402,19 @@ static int admv8818_read_lpf_freq(struct admv8818_state *st, u64 *lpf_freq)
> > > > return ret;
> > > > }
> > > >
> > > > +static int admv8818_write_raw_get_fmt(struct iio_dev *indio_dev,
> > > > + struct iio_chan_spec const *chan,
> > > > + long mask)
> > > > +{
> > > > + switch (mask) {
> > > > + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
> > > > + case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
> > > > + return IIO_VAL_INT_64;
> > > > + default:
> > > > + return -EINVAL;
> > > > + }
> > > > +}
> > > > +
> > > > static int admv8818_write_raw(struct iio_dev *indio_dev,
> > > > struct iio_chan_spec const *chan,
> > > > int val, int val2, long info)
> > > > @@ -410,6 +423,9 @@ static int admv8818_write_raw(struct iio_dev *indio_dev,
> > > >
> > > > u64 freq = ((u64)val2 << 32 | (u32)val);
> > > >
> > > > + if ((s64)freq < 0)
> > > > + return -EINVAL;
> > > > +
> > > > switch (info) {
> > > > case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
> > > > return admv8818_lpf_select(st, freq);
> > > > @@ -571,6 +587,7 @@ static int admv8818_set_mode(struct iio_dev *indio_dev,
> > > >
> > > > static const struct iio_info admv8818_info = {
> > > > .write_raw = admv8818_write_raw,
> > > > + .write_raw_get_fmt = admv8818_write_raw_get_fmt,
> > > > .read_raw = admv8818_read_raw,
> > > > .debugfs_reg_access = &admv8818_reg_access,
> > > > };
> > >
>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2025-03-16 13:54 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-07 15:02 [PATCH v6 1/6] dt-bindings: iio: filter: Add lpf/hpf freq margins Sam Winchenbach
2025-03-07 15:02 ` [PATCH v6 2/6] iio: filter: admv8818: fix band 4, state 15 Sam Winchenbach
2025-03-07 15:02 ` [PATCH v6 3/6] iio: filter: admv8818: fix integer overflow Sam Winchenbach
2025-03-07 15:02 ` [PATCH v6 4/6] iio: filter: admv8818: fix range calculation Sam Winchenbach
2025-03-08 14:03 ` Jonathan Cameron
2025-03-07 15:02 ` [PATCH v6 5/6] driver core: Add support for writing 64 bit attrs Sam Winchenbach
2025-03-08 14:00 ` Jonathan Cameron
2025-03-07 15:02 ` [PATCH v6 6/6] iio: filter: admv8818: Support frequencies >= 2^32 Sam Winchenbach
2025-03-08 14:01 ` Jonathan Cameron
2025-03-12 12:16 ` Sam Winchenbach
2025-03-15 18:26 ` Jonathan Cameron
2025-03-16 13:54 ` Sam Winchenbach
2025-03-10 9:22 ` [PATCH v6 1/6] dt-bindings: iio: filter: Add lpf/hpf freq margins Krzysztof Kozlowski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).