* [PATCH 0/2] iio: frequency: adf4377: add clock provider support @ 2025-11-14 12:09 Antoniu Miclaus 2025-11-14 12:09 ` [PATCH 1/2] dt-bindings: frequency: adf4377: add clk provider Antoniu Miclaus 2025-11-14 12:09 ` [PATCH 2/2] iio: frequency: adf4377: add clk provider support Antoniu Miclaus 0 siblings, 2 replies; 9+ messages in thread From: Antoniu Miclaus @ 2025-11-14 12:09 UTC (permalink / raw) To: jic23, robh, conor+dt, linux-iio, linux-kernel, devicetree Cc: Antoniu Miclaus This series adds clock provider functionality to the ADF4377 frequency synthesizer driver to address user requests for controlling output frequencies from userspace. While implemented as an IIO driver, the ADF4377 is commonly used as a clock source. This patch series enables it to function as either: - A traditional IIO device (when #clock-cells is not specified) - A clock provider (when #clock-cells is present in device tree) The implementation provides standard clock framework integration with rate control, enable/disable support, and maintains backward compatibility with existing IIO configurations. Antoniu Miclaus (2): dt-bindings: frequency: adf4377: add clk provider iio: frequency: adf4377: add clk provider support .../bindings/iio/frequency/adi,adf4377.yaml | 20 +++ drivers/iio/frequency/adf4377.c | 131 +++++++++++++++++- 2 files changed, 149 insertions(+), 2 deletions(-) -- 2.43.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] dt-bindings: frequency: adf4377: add clk provider 2025-11-14 12:09 [PATCH 0/2] iio: frequency: adf4377: add clock provider support Antoniu Miclaus @ 2025-11-14 12:09 ` Antoniu Miclaus 2025-11-15 17:25 ` Jonathan Cameron 2025-11-14 12:09 ` [PATCH 2/2] iio: frequency: adf4377: add clk provider support Antoniu Miclaus 1 sibling, 1 reply; 9+ messages in thread From: Antoniu Miclaus @ 2025-11-14 12:09 UTC (permalink / raw) To: jic23, robh, conor+dt, linux-iio, linux-kernel, devicetree Cc: Antoniu Miclaus Add support for clock provider. Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com> --- .../bindings/iio/frequency/adi,adf4377.yaml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/frequency/adi,adf4377.yaml b/Documentation/devicetree/bindings/iio/frequency/adi,adf4377.yaml index 5f950ee9aec7..dab1591a36b3 100644 --- a/Documentation/devicetree/bindings/iio/frequency/adi,adf4377.yaml +++ b/Documentation/devicetree/bindings/iio/frequency/adi,adf4377.yaml @@ -40,6 +40,12 @@ properties: items: - const: ref_in + '#clock-cells': + const: 0 + + clock-output-names: + maxItems: 1 + chip-enable-gpios: description: GPIO that controls the Chip Enable Pin. @@ -99,4 +105,18 @@ examples: clock-names = "ref_in"; }; }; + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + frequency@0 { + compatible = "adi,adf4378"; + reg = <0>; + spi-max-frequency = <10000000>; + clocks = <&adf4378_ref_in>; + clock-names = "ref_in"; + #clock-cells = <0>; + clock-output-names = "adf4378_clk"; + }; + }; ... -- 2.43.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] dt-bindings: frequency: adf4377: add clk provider 2025-11-14 12:09 ` [PATCH 1/2] dt-bindings: frequency: adf4377: add clk provider Antoniu Miclaus @ 2025-11-15 17:25 ` Jonathan Cameron 0 siblings, 0 replies; 9+ messages in thread From: Jonathan Cameron @ 2025-11-15 17:25 UTC (permalink / raw) To: Antoniu Miclaus; +Cc: robh, conor+dt, linux-iio, linux-kernel, devicetree On Fri, 14 Nov 2025 12:09:07 +0000 Antoniu Miclaus <antoniu.miclaus@analog.com> wrote: Title should be dt-bindings: iio: frequency: ... > Add support for clock provider. > > Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com> > --- > .../bindings/iio/frequency/adi,adf4377.yaml | 20 +++++++++++++++++++ > 1 file changed, 20 insertions(+) > > diff --git a/Documentation/devicetree/bindings/iio/frequency/adi,adf4377.yaml b/Documentation/devicetree/bindings/iio/frequency/adi,adf4377.yaml > index 5f950ee9aec7..dab1591a36b3 100644 > --- a/Documentation/devicetree/bindings/iio/frequency/adi,adf4377.yaml > +++ b/Documentation/devicetree/bindings/iio/frequency/adi,adf4377.yaml > @@ -40,6 +40,12 @@ properties: > items: > - const: ref_in > > + '#clock-cells': > + const: 0 > + > + clock-output-names: > + maxItems: 1 > + > chip-enable-gpios: > description: > GPIO that controls the Chip Enable Pin. > @@ -99,4 +105,18 @@ examples: > clock-names = "ref_in"; > }; > }; > + - | > + spi { > + #address-cells = <1>; > + #size-cells = <0>; > + frequency@0 { > + compatible = "adi,adf4378"; > + reg = <0>; > + spi-max-frequency = <10000000>; > + clocks = <&adf4378_ref_in>; > + clock-names = "ref_in"; > + #clock-cells = <0>; > + clock-output-names = "adf4378_clk"; > + }; > + }; > ... ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/2] iio: frequency: adf4377: add clk provider support 2025-11-14 12:09 [PATCH 0/2] iio: frequency: adf4377: add clock provider support Antoniu Miclaus 2025-11-14 12:09 ` [PATCH 1/2] dt-bindings: frequency: adf4377: add clk provider Antoniu Miclaus @ 2025-11-14 12:09 ` Antoniu Miclaus 2025-11-15 17:24 ` Jonathan Cameron 2025-11-21 3:13 ` Stephen Boyd 1 sibling, 2 replies; 9+ messages in thread From: Antoniu Miclaus @ 2025-11-14 12:09 UTC (permalink / raw) To: jic23, robh, conor+dt, linux-iio, linux-kernel, devicetree Cc: Antoniu Miclaus Add clk provider feature for the adf4377. Even though the driver was sent as an IIO driver in most cases the device is actually seen as a clock provider. This patch aims to cover actual usecases requested by users in order to completely control the output frequencies from userspace. Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com> --- drivers/iio/frequency/adf4377.c | 131 +++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 2 deletions(-) diff --git a/drivers/iio/frequency/adf4377.c b/drivers/iio/frequency/adf4377.c index 08833b7035e4..08dc2110cf8c 100644 --- a/drivers/iio/frequency/adf4377.c +++ b/drivers/iio/frequency/adf4377.c @@ -8,6 +8,7 @@ #include <linux/bitfield.h> #include <linux/bits.h> #include <linux/clk.h> +#include <linux/clk-provider.h> #include <linux/clkdev.h> #include <linux/delay.h> #include <linux/device.h> @@ -435,9 +436,14 @@ struct adf4377_state { struct gpio_desc *gpio_ce; struct gpio_desc *gpio_enclk1; struct gpio_desc *gpio_enclk2; + struct clk *clk; + struct clk *clkout; + struct clk_hw hw; u8 buf[2] __aligned(IIO_DMA_MINALIGN); }; +#define to_adf4377_state(h) container_of(h, struct adf4377_state, hw) + static const char * const adf4377_muxout_modes[] = { [ADF4377_MUXOUT_HIGH_Z] = "high_z", [ADF4377_MUXOUT_LKDET] = "lock_detect", @@ -929,6 +935,120 @@ static int adf4377_freq_change(struct notifier_block *nb, unsigned long action, return NOTIFY_OK; } +static void adf4377_clk_del_provider(void *data) +{ + struct adf4377_state *st = data; + + of_clk_del_provider(st->spi->dev.of_node); +} + +static unsigned long adf4377_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct adf4377_state *st = to_adf4377_state(hw); + u64 freq; + int ret; + + ret = adf4377_get_freq(st, &freq); + if (ret) + return 0; + + return freq; +} + +static int adf4377_clk_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct adf4377_state *st = to_adf4377_state(hw); + + return adf4377_set_freq(st, rate); +} + +static int adf4377_clk_prepare(struct clk_hw *hw) +{ + struct adf4377_state *st = to_adf4377_state(hw); + + return regmap_update_bits(st->regmap, 0x1a, ADF4377_001A_PD_CLKOUT1_MSK | + ADF4377_001A_PD_CLKOUT2_MSK, + FIELD_PREP(ADF4377_001A_PD_CLKOUT1_MSK, 0) | + FIELD_PREP(ADF4377_001A_PD_CLKOUT2_MSK, 0)); +} + +static void adf4377_clk_unprepare(struct clk_hw *hw) +{ + struct adf4377_state *st = to_adf4377_state(hw); + + regmap_update_bits(st->regmap, 0x1a, ADF4377_001A_PD_CLKOUT1_MSK | + ADF4377_001A_PD_CLKOUT2_MSK, + FIELD_PREP(ADF4377_001A_PD_CLKOUT1_MSK, 1) | + FIELD_PREP(ADF4377_001A_PD_CLKOUT2_MSK, 1)); +} + +static int adf4377_clk_is_enabled(struct clk_hw *hw) +{ + struct adf4377_state *st = to_adf4377_state(hw); + unsigned int readval; + int ret; + + ret = regmap_read(st->regmap, 0x1a, &readval); + if (ret) + return ret; + + return !(readval & (ADF4377_001A_PD_CLKOUT1_MSK | ADF4377_001A_PD_CLKOUT2_MSK)); +} + +static const struct clk_ops adf4377_clk_ops = { + .recalc_rate = adf4377_clk_recalc_rate, + .set_rate = adf4377_clk_set_rate, + .prepare = adf4377_clk_prepare, + .unprepare = adf4377_clk_unprepare, + .is_enabled = adf4377_clk_is_enabled, +}; + +static int adf4377_clk_register(struct adf4377_state *st) +{ + struct spi_device *spi = st->spi; + struct clk_init_data init; + struct clk *clk; + const char *parent_name; + int ret; + + if (!device_property_present(&spi->dev, "#clock-cells")) + return 0; + + if (device_property_read_string(&spi->dev, "clock-output-names", &init.name)) { + init.name = devm_kasprintf(&spi->dev, GFP_KERNEL, "%s-clk", + fwnode_get_name(dev_fwnode(&spi->dev))); + if (!init.name) + return -ENOMEM; + } + + parent_name = of_clk_get_parent_name(spi->dev.of_node, 0); + if (!parent_name) + return -EINVAL; + + init.ops = &adf4377_clk_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = CLK_SET_RATE_PARENT; + + st->hw.init = &init; + clk = devm_clk_register(&spi->dev, &st->hw); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + st->clk = clk; + + ret = of_clk_add_provider(spi->dev.of_node, of_clk_src_simple_get, clk); + if (ret) + return ret; + + st->clkout = clk; + + return devm_add_action_or_reset(&spi->dev, adf4377_clk_del_provider, st); +} + static const struct adf4377_chip_info adf4377_chip_info = { .name = "adf4377", .has_gpio_enclk2 = true, @@ -958,8 +1078,6 @@ static int adf4377_probe(struct spi_device *spi) indio_dev->info = &adf4377_info; indio_dev->name = "adf4377"; - indio_dev->channels = adf4377_channels; - indio_dev->num_channels = ARRAY_SIZE(adf4377_channels); st->regmap = regmap; st->spi = spi; @@ -979,6 +1097,15 @@ static int adf4377_probe(struct spi_device *spi) if (ret) return ret; + ret = adf4377_clk_register(st); + if (ret) + return ret; + + if (!st->clkout) { + indio_dev->channels = adf4377_channels; + indio_dev->num_channels = ARRAY_SIZE(adf4377_channels); + } + return devm_iio_device_register(&spi->dev, indio_dev); } -- 2.43.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] iio: frequency: adf4377: add clk provider support 2025-11-14 12:09 ` [PATCH 2/2] iio: frequency: adf4377: add clk provider support Antoniu Miclaus @ 2025-11-15 17:24 ` Jonathan Cameron 2025-11-17 8:35 ` Nuno Sá 2025-11-17 9:09 ` Miclaus, Antoniu 2025-11-21 3:13 ` Stephen Boyd 1 sibling, 2 replies; 9+ messages in thread From: Jonathan Cameron @ 2025-11-15 17:24 UTC (permalink / raw) To: Antoniu Miclaus Cc: robh, conor+dt, linux-iio, linux-kernel, devicetree, linux-clk, Michael Turquette, Stephen Boyd On Fri, 14 Nov 2025 12:09:08 +0000 Antoniu Miclaus <antoniu.miclaus@analog.com> wrote: > Add clk provider feature for the adf4377. > > Even though the driver was sent as an IIO driver in most cases the > device is actually seen as a clock provider. > > This patch aims to cover actual usecases requested by users in order to > completely control the output frequencies from userspace. > > Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com> Given this new code is basically a clock driver, I'd expect to see some relevant folk +CC. Added Michael, Stephen and linux-clk. One question from me right at the end around whether it makes sense to register an IIO device with no channels. I left the rest so it was easy for the people added to the thread to see all the code. Thanks, Jonathan > --- > drivers/iio/frequency/adf4377.c | 131 +++++++++++++++++++++++++++++++- > 1 file changed, 129 insertions(+), 2 deletions(-) > > diff --git a/drivers/iio/frequency/adf4377.c b/drivers/iio/frequency/adf4377.c > index 08833b7035e4..08dc2110cf8c 100644 > --- a/drivers/iio/frequency/adf4377.c > +++ b/drivers/iio/frequency/adf4377.c > @@ -8,6 +8,7 @@ > #include <linux/bitfield.h> > #include <linux/bits.h> > #include <linux/clk.h> > +#include <linux/clk-provider.h> > #include <linux/clkdev.h> > #include <linux/delay.h> > #include <linux/device.h> > @@ -435,9 +436,14 @@ struct adf4377_state { > struct gpio_desc *gpio_ce; > struct gpio_desc *gpio_enclk1; > struct gpio_desc *gpio_enclk2; > + struct clk *clk; > + struct clk *clkout; > + struct clk_hw hw; > u8 buf[2] __aligned(IIO_DMA_MINALIGN); > }; > > +#define to_adf4377_state(h) container_of(h, struct adf4377_state, hw) > + > static const char * const adf4377_muxout_modes[] = { > [ADF4377_MUXOUT_HIGH_Z] = "high_z", > [ADF4377_MUXOUT_LKDET] = "lock_detect", > @@ -929,6 +935,120 @@ static int adf4377_freq_change(struct notifier_block *nb, unsigned long action, > return NOTIFY_OK; > } > > +static void adf4377_clk_del_provider(void *data) > +{ > + struct adf4377_state *st = data; > + > + of_clk_del_provider(st->spi->dev.of_node); > +} > + > +static unsigned long adf4377_clk_recalc_rate(struct clk_hw *hw, > + unsigned long parent_rate) > +{ > + struct adf4377_state *st = to_adf4377_state(hw); > + u64 freq; > + int ret; > + > + ret = adf4377_get_freq(st, &freq); > + if (ret) > + return 0; > + > + return freq; > +} > + > +static int adf4377_clk_set_rate(struct clk_hw *hw, > + unsigned long rate, > + unsigned long parent_rate) > +{ > + struct adf4377_state *st = to_adf4377_state(hw); > + > + return adf4377_set_freq(st, rate); > +} > + > +static int adf4377_clk_prepare(struct clk_hw *hw) > +{ > + struct adf4377_state *st = to_adf4377_state(hw); > + > + return regmap_update_bits(st->regmap, 0x1a, ADF4377_001A_PD_CLKOUT1_MSK | > + ADF4377_001A_PD_CLKOUT2_MSK, > + FIELD_PREP(ADF4377_001A_PD_CLKOUT1_MSK, 0) | > + FIELD_PREP(ADF4377_001A_PD_CLKOUT2_MSK, 0)); > +} > + > +static void adf4377_clk_unprepare(struct clk_hw *hw) > +{ > + struct adf4377_state *st = to_adf4377_state(hw); > + > + regmap_update_bits(st->regmap, 0x1a, ADF4377_001A_PD_CLKOUT1_MSK | > + ADF4377_001A_PD_CLKOUT2_MSK, > + FIELD_PREP(ADF4377_001A_PD_CLKOUT1_MSK, 1) | > + FIELD_PREP(ADF4377_001A_PD_CLKOUT2_MSK, 1)); > +} > + > +static int adf4377_clk_is_enabled(struct clk_hw *hw) > +{ > + struct adf4377_state *st = to_adf4377_state(hw); > + unsigned int readval; > + int ret; > + > + ret = regmap_read(st->regmap, 0x1a, &readval); > + if (ret) > + return ret; > + > + return !(readval & (ADF4377_001A_PD_CLKOUT1_MSK | ADF4377_001A_PD_CLKOUT2_MSK)); > +} > + > +static const struct clk_ops adf4377_clk_ops = { > + .recalc_rate = adf4377_clk_recalc_rate, > + .set_rate = adf4377_clk_set_rate, > + .prepare = adf4377_clk_prepare, > + .unprepare = adf4377_clk_unprepare, > + .is_enabled = adf4377_clk_is_enabled, > +}; > + > +static int adf4377_clk_register(struct adf4377_state *st) > +{ > + struct spi_device *spi = st->spi; > + struct clk_init_data init; > + struct clk *clk; > + const char *parent_name; > + int ret; > + > + if (!device_property_present(&spi->dev, "#clock-cells")) > + return 0; > + > + if (device_property_read_string(&spi->dev, "clock-output-names", &init.name)) { > + init.name = devm_kasprintf(&spi->dev, GFP_KERNEL, "%s-clk", > + fwnode_get_name(dev_fwnode(&spi->dev))); > + if (!init.name) > + return -ENOMEM; > + } > + > + parent_name = of_clk_get_parent_name(spi->dev.of_node, 0); > + if (!parent_name) > + return -EINVAL; > + > + init.ops = &adf4377_clk_ops; > + init.parent_names = &parent_name; > + init.num_parents = 1; > + init.flags = CLK_SET_RATE_PARENT; > + > + st->hw.init = &init; > + clk = devm_clk_register(&spi->dev, &st->hw); > + if (IS_ERR(clk)) > + return PTR_ERR(clk); > + > + st->clk = clk; > + > + ret = of_clk_add_provider(spi->dev.of_node, of_clk_src_simple_get, clk); > + if (ret) > + return ret; > + > + st->clkout = clk; > + > + return devm_add_action_or_reset(&spi->dev, adf4377_clk_del_provider, st); > +} > + > static const struct adf4377_chip_info adf4377_chip_info = { > .name = "adf4377", > .has_gpio_enclk2 = true, > @@ -958,8 +1078,6 @@ static int adf4377_probe(struct spi_device *spi) > > indio_dev->info = &adf4377_info; > indio_dev->name = "adf4377"; > - indio_dev->channels = adf4377_channels; > - indio_dev->num_channels = ARRAY_SIZE(adf4377_channels); > > st->regmap = regmap; > st->spi = spi; > @@ -979,6 +1097,15 @@ static int adf4377_probe(struct spi_device *spi) > if (ret) > return ret; > > + ret = adf4377_clk_register(st); > + if (ret) > + return ret; > + > + if (!st->clkout) { > + indio_dev->channels = adf4377_channels; > + indio_dev->num_channels = ARRAY_SIZE(adf4377_channels); Why register a channel free iio device? Probably better to just not register it at all in this path. > + } > + > return devm_iio_device_register(&spi->dev, indio_dev); > } > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] iio: frequency: adf4377: add clk provider support 2025-11-15 17:24 ` Jonathan Cameron @ 2025-11-17 8:35 ` Nuno Sá 2025-11-17 9:09 ` Miclaus, Antoniu 1 sibling, 0 replies; 9+ messages in thread From: Nuno Sá @ 2025-11-17 8:35 UTC (permalink / raw) To: Jonathan Cameron, Antoniu Miclaus Cc: robh, conor+dt, linux-iio, linux-kernel, devicetree, linux-clk, Michael Turquette, Stephen Boyd On Sat, 2025-11-15 at 17:24 +0000, Jonathan Cameron wrote: > On Fri, 14 Nov 2025 12:09:08 +0000 > Antoniu Miclaus <antoniu.miclaus@analog.com> wrote: > > > Add clk provider feature for the adf4377. > > > > Even though the driver was sent as an IIO driver in most cases the > > device is actually seen as a clock provider. > > > > This patch aims to cover actual usecases requested by users in order to > > completely control the output frequencies from userspace. > > > > Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com> > > Given this new code is basically a clock driver, I'd expect to see some > relevant folk +CC. > > Added Michael, Stephen and linux-clk. > > One question from me right at the end around whether it makes sense > to register an IIO device with no channels. I left the rest so it was > easy for the people added to the thread to see all the code. > > Thanks, > > Jonathan > > > > --- > > drivers/iio/frequency/adf4377.c | 131 +++++++++++++++++++++++++++++++- > > 1 file changed, 129 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/iio/frequency/adf4377.c b/drivers/iio/frequency/adf4377.c > > index 08833b7035e4..08dc2110cf8c 100644 > > --- a/drivers/iio/frequency/adf4377.c > > +++ b/drivers/iio/frequency/adf4377.c > > @@ -8,6 +8,7 @@ > > #include <linux/bitfield.h> > > #include <linux/bits.h> > > #include <linux/clk.h> > > +#include <linux/clk-provider.h> > > #include <linux/clkdev.h> > > #include <linux/delay.h> > > #include <linux/device.h> > > @@ -435,9 +436,14 @@ struct adf4377_state { > > struct gpio_desc *gpio_ce; > > struct gpio_desc *gpio_enclk1; > > struct gpio_desc *gpio_enclk2; > > + struct clk *clk; > > + struct clk *clkout; > > + struct clk_hw hw; > > u8 buf[2] __aligned(IIO_DMA_MINALIGN); > > }; > > > > +#define to_adf4377_state(h) container_of(h, struct adf4377_state, hw) > > + > > static const char * const adf4377_muxout_modes[] = { > > [ADF4377_MUXOUT_HIGH_Z] = "high_z", > > [ADF4377_MUXOUT_LKDET] = "lock_detect", > > @@ -929,6 +935,120 @@ static int adf4377_freq_change(struct notifier_block *nb, > > unsigned long action, > > return NOTIFY_OK; > > } > > > > +static void adf4377_clk_del_provider(void *data) > > +{ > > + struct adf4377_state *st = data; > > + > > + of_clk_del_provider(st->spi->dev.of_node); > > +} > > + > > +static unsigned long adf4377_clk_recalc_rate(struct clk_hw *hw, > > + unsigned long parent_rate) > > +{ > > + struct adf4377_state *st = to_adf4377_state(hw); > > + u64 freq; > > + int ret; > > + > > + ret = adf4377_get_freq(st, &freq); > > + if (ret) > > + return 0; > > + > > + return freq; > > +} > > + > > +static int adf4377_clk_set_rate(struct clk_hw *hw, > > + unsigned long rate, > > + unsigned long parent_rate) > > +{ > > + struct adf4377_state *st = to_adf4377_state(hw); > > + > > + return adf4377_set_freq(st, rate); > > +} > > + > > +static int adf4377_clk_prepare(struct clk_hw *hw) > > +{ > > + struct adf4377_state *st = to_adf4377_state(hw); > > + > > + return regmap_update_bits(st->regmap, 0x1a, ADF4377_001A_PD_CLKOUT1_MSK > > | > > + ADF4377_001A_PD_CLKOUT2_MSK, > > + FIELD_PREP(ADF4377_001A_PD_CLKOUT1_MSK, 0) | > > + FIELD_PREP(ADF4377_001A_PD_CLKOUT2_MSK, 0)); > > +} > > + > > +static void adf4377_clk_unprepare(struct clk_hw *hw) > > +{ > > + struct adf4377_state *st = to_adf4377_state(hw); > > + > > + regmap_update_bits(st->regmap, 0x1a, ADF4377_001A_PD_CLKOUT1_MSK | > > + ADF4377_001A_PD_CLKOUT2_MSK, > > + FIELD_PREP(ADF4377_001A_PD_CLKOUT1_MSK, 1) | > > + FIELD_PREP(ADF4377_001A_PD_CLKOUT2_MSK, 1)); > > +} > > + > > +static int adf4377_clk_is_enabled(struct clk_hw *hw) > > +{ > > + struct adf4377_state *st = to_adf4377_state(hw); > > + unsigned int readval; > > + int ret; > > + > > + ret = regmap_read(st->regmap, 0x1a, &readval); > > + if (ret) > > + return ret; > > + > > + return !(readval & (ADF4377_001A_PD_CLKOUT1_MSK | > > ADF4377_001A_PD_CLKOUT2_MSK)); > > +} > > + > > +static const struct clk_ops adf4377_clk_ops = { > > + .recalc_rate = adf4377_clk_recalc_rate, > > + .set_rate = adf4377_clk_set_rate, > > + .prepare = adf4377_clk_prepare, > > + .unprepare = adf4377_clk_unprepare, > > + .is_enabled = adf4377_clk_is_enabled, > > +}; > > + > > +static int adf4377_clk_register(struct adf4377_state *st) > > +{ > > + struct spi_device *spi = st->spi; > > + struct clk_init_data init; > > + struct clk *clk; > > + const char *parent_name; > > + int ret; > > + > > + if (!device_property_present(&spi->dev, "#clock-cells")) > > + return 0; > > + > > + if (device_property_read_string(&spi->dev, "clock-output-names", > > &init.name)) { > > + init.name = devm_kasprintf(&spi->dev, GFP_KERNEL, "%s-clk", > > + fwnode_get_name(dev_fwnode(&spi- > > >dev))); > > + if (!init.name) > > + return -ENOMEM; > > + } > > + > > + parent_name = of_clk_get_parent_name(spi->dev.of_node, 0); > > + if (!parent_name) > > + return -EINVAL; > > + > > + init.ops = &adf4377_clk_ops; > > + init.parent_names = &parent_name; > > + init.num_parents = 1; > > + init.flags = CLK_SET_RATE_PARENT; > > + > > + st->hw.init = &init; > > + clk = devm_clk_register(&spi->dev, &st->hw); > > + if (IS_ERR(clk)) > > + return PTR_ERR(clk); > > + > > + st->clk = clk; > > + > > + ret = of_clk_add_provider(spi->dev.of_node, of_clk_src_simple_get, clk); > > + if (ret) > > + return ret; > > + > > + st->clkout = clk; > > + > > + return devm_add_action_or_reset(&spi->dev, adf4377_clk_del_provider, > > st); > > +} > > + > > static const struct adf4377_chip_info adf4377_chip_info = { > > .name = "adf4377", > > .has_gpio_enclk2 = true, > > @@ -958,8 +1078,6 @@ static int adf4377_probe(struct spi_device *spi) > > > > indio_dev->info = &adf4377_info; > > indio_dev->name = "adf4377"; > > - indio_dev->channels = adf4377_channels; > > - indio_dev->num_channels = ARRAY_SIZE(adf4377_channels); > > > > st->regmap = regmap; > > st->spi = spi; > > @@ -979,6 +1097,15 @@ static int adf4377_probe(struct spi_device *spi) > > if (ret) > > return ret; > > > > + ret = adf4377_clk_register(st); > > + if (ret) > > + return ret; > > + > > + if (!st->clkout) { > > + indio_dev->channels = adf4377_channels; > > + indio_dev->num_channels = ARRAY_SIZE(adf4377_channels); > > Why register a channel free iio device? Probably better to just not register > it at all in this path. Maybe a sneaky way of making use of the IIO debug direct access :). But I already asked myself the somehow related question if we should still allow IIO access even if the clock provider is registered. I mean, for sure we would need a more "fine" grained access but we could only forbid IIO/userspace control in case an actual consumer of the clock asks for it. Or maybe not worth the trouble :) - Nuno Sá > > > + } > > + > > return devm_iio_device_register(&spi->dev, indio_dev); > > } > > ^ permalink raw reply [flat|nested] 9+ messages in thread
* RE: [PATCH 2/2] iio: frequency: adf4377: add clk provider support 2025-11-15 17:24 ` Jonathan Cameron 2025-11-17 8:35 ` Nuno Sá @ 2025-11-17 9:09 ` Miclaus, Antoniu 1 sibling, 0 replies; 9+ messages in thread From: Miclaus, Antoniu @ 2025-11-17 9:09 UTC (permalink / raw) To: Jonathan Cameron Cc: robh@kernel.org, conor+dt@kernel.org, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, Michael Turquette, Stephen Boyd, Sa, Nuno Hi Jonathan, > -----Original Message----- > From: Jonathan Cameron <jic23@kernel.org> > Sent: Saturday, November 15, 2025 7:24 PM > To: Miclaus, Antoniu <Antoniu.Miclaus@analog.com> > Cc: robh@kernel.org; conor+dt@kernel.org; linux-iio@vger.kernel.org; linux- > kernel@vger.kernel.org; devicetree@vger.kernel.org; linux- > clk@vger.kernel.org; Michael Turquette <mturquette@baylibre.com>; Stephen > Boyd <sboyd@kernel.org> > Subject: Re: [PATCH 2/2] iio: frequency: adf4377: add clk provider support > > [External] > > On Fri, 14 Nov 2025 12:09:08 +0000 > Antoniu Miclaus <antoniu.miclaus@analog.com> wrote: > > > Add clk provider feature for the adf4377. > > > > Even though the driver was sent as an IIO driver in most cases the > > device is actually seen as a clock provider. > > > > This patch aims to cover actual usecases requested by users in order to > > completely control the output frequencies from userspace. > > > > Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com> > > Given this new code is basically a clock driver, I'd expect to see some > relevant folk +CC. > > Added Michael, Stephen and linux-clk. > > One question from me right at the end around whether it makes sense > to register an IIO device with no channels. I left the rest so it was > easy for the people added to the thread to see all the code. > > Thanks, > > Jonathan > > > > --- > > drivers/iio/frequency/adf4377.c | 131 > +++++++++++++++++++++++++++++++- > > 1 file changed, 129 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/iio/frequency/adf4377.c > b/drivers/iio/frequency/adf4377.c > > index 08833b7035e4..08dc2110cf8c 100644 > > --- a/drivers/iio/frequency/adf4377.c > > +++ b/drivers/iio/frequency/adf4377.c > > @@ -8,6 +8,7 @@ > > #include <linux/bitfield.h> > > #include <linux/bits.h> > > #include <linux/clk.h> > > +#include <linux/clk-provider.h> > > #include <linux/clkdev.h> > > #include <linux/delay.h> > > #include <linux/device.h> > > @@ -435,9 +436,14 @@ struct adf4377_state { > > struct gpio_desc *gpio_ce; > > struct gpio_desc *gpio_enclk1; > > struct gpio_desc *gpio_enclk2; > > + struct clk *clk; > > + struct clk *clkout; > > + struct clk_hw hw; > > u8 buf[2] __aligned(IIO_DMA_MINALIGN); > > }; > > > > +#define to_adf4377_state(h) container_of(h, struct adf4377_state, > hw) > > + > > static const char * const adf4377_muxout_modes[] = { > > [ADF4377_MUXOUT_HIGH_Z] = "high_z", > > [ADF4377_MUXOUT_LKDET] = "lock_detect", > > @@ -929,6 +935,120 @@ static int adf4377_freq_change(struct > notifier_block *nb, unsigned long action, > > return NOTIFY_OK; > > } > > > > +static void adf4377_clk_del_provider(void *data) > > +{ > > + struct adf4377_state *st = data; > > + > > + of_clk_del_provider(st->spi->dev.of_node); > > +} > > + > > +static unsigned long adf4377_clk_recalc_rate(struct clk_hw *hw, > > + unsigned long parent_rate) > > +{ > > + struct adf4377_state *st = to_adf4377_state(hw); > > + u64 freq; > > + int ret; > > + > > + ret = adf4377_get_freq(st, &freq); > > + if (ret) > > + return 0; > > + > > + return freq; > > +} > > + > > +static int adf4377_clk_set_rate(struct clk_hw *hw, > > + unsigned long rate, > > + unsigned long parent_rate) > > +{ > > + struct adf4377_state *st = to_adf4377_state(hw); > > + > > + return adf4377_set_freq(st, rate); > > +} > > + > > +static int adf4377_clk_prepare(struct clk_hw *hw) > > +{ > > + struct adf4377_state *st = to_adf4377_state(hw); > > + > > + return regmap_update_bits(st->regmap, 0x1a, > ADF4377_001A_PD_CLKOUT1_MSK | > > + ADF4377_001A_PD_CLKOUT2_MSK, > > + > FIELD_PREP(ADF4377_001A_PD_CLKOUT1_MSK, 0) | > > + > FIELD_PREP(ADF4377_001A_PD_CLKOUT2_MSK, 0)); > > +} > > + > > +static void adf4377_clk_unprepare(struct clk_hw *hw) > > +{ > > + struct adf4377_state *st = to_adf4377_state(hw); > > + > > + regmap_update_bits(st->regmap, 0x1a, > ADF4377_001A_PD_CLKOUT1_MSK | > > + ADF4377_001A_PD_CLKOUT2_MSK, > > + FIELD_PREP(ADF4377_001A_PD_CLKOUT1_MSK, 1) > | > > + FIELD_PREP(ADF4377_001A_PD_CLKOUT2_MSK, > 1)); > > +} > > + > > +static int adf4377_clk_is_enabled(struct clk_hw *hw) > > +{ > > + struct adf4377_state *st = to_adf4377_state(hw); > > + unsigned int readval; > > + int ret; > > + > > + ret = regmap_read(st->regmap, 0x1a, &readval); > > + if (ret) > > + return ret; > > + > > + return !(readval & (ADF4377_001A_PD_CLKOUT1_MSK | > ADF4377_001A_PD_CLKOUT2_MSK)); > > +} > > + > > +static const struct clk_ops adf4377_clk_ops = { > > + .recalc_rate = adf4377_clk_recalc_rate, > > + .set_rate = adf4377_clk_set_rate, > > + .prepare = adf4377_clk_prepare, > > + .unprepare = adf4377_clk_unprepare, > > + .is_enabled = adf4377_clk_is_enabled, > > +}; > > + > > +static int adf4377_clk_register(struct adf4377_state *st) > > +{ > > + struct spi_device *spi = st->spi; > > + struct clk_init_data init; > > + struct clk *clk; > > + const char *parent_name; > > + int ret; > > + > > + if (!device_property_present(&spi->dev, "#clock-cells")) > > + return 0; > > + > > + if (device_property_read_string(&spi->dev, "clock-output-names", > &init.name)) { > > + init.name = devm_kasprintf(&spi->dev, GFP_KERNEL, "%s-clk", > > + > fwnode_get_name(dev_fwnode(&spi->dev))); > > + if (!init.name) > > + return -ENOMEM; > > + } > > + > > + parent_name = of_clk_get_parent_name(spi->dev.of_node, 0); > > + if (!parent_name) > > + return -EINVAL; > > + > > + init.ops = &adf4377_clk_ops; > > + init.parent_names = &parent_name; > > + init.num_parents = 1; > > + init.flags = CLK_SET_RATE_PARENT; > > + > > + st->hw.init = &init; > > + clk = devm_clk_register(&spi->dev, &st->hw); > > + if (IS_ERR(clk)) > > + return PTR_ERR(clk); > > + > > + st->clk = clk; > > + > > + ret = of_clk_add_provider(spi->dev.of_node, of_clk_src_simple_get, > clk); > > + if (ret) > > + return ret; > > + > > + st->clkout = clk; > > + > > + return devm_add_action_or_reset(&spi->dev, > adf4377_clk_del_provider, st); > > +} > > + > > static const struct adf4377_chip_info adf4377_chip_info = { > > .name = "adf4377", > > .has_gpio_enclk2 = true, > > @@ -958,8 +1078,6 @@ static int adf4377_probe(struct spi_device *spi) > > > > indio_dev->info = &adf4377_info; > > indio_dev->name = "adf4377"; > > - indio_dev->channels = adf4377_channels; > > - indio_dev->num_channels = ARRAY_SIZE(adf4377_channels); > > > > st->regmap = regmap; > > st->spi = spi; > > @@ -979,6 +1097,15 @@ static int adf4377_probe(struct spi_device *spi) > > if (ret) > > return ret; > > > > + ret = adf4377_clk_register(st); > > + if (ret) > > + return ret; > > + > > + if (!st->clkout) { > > + indio_dev->channels = adf4377_channels; > > + indio_dev->num_channels = ARRAY_SIZE(adf4377_channels); > > Why register a channel free iio device? Probably better to just not register > it at all in this path. There was a similar discussion on adf4350 clock provider support and we ended up using this approach. https://github.com/torvalds/linux/commit/a1a09713b40dfc1c0b7d1f9233a7698c93a9af05 I wanted to stick to something that was accepted at some point in time. Regards, Antoniu > > + } > > + > > return devm_iio_device_register(&spi->dev, indio_dev); > > } > > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] iio: frequency: adf4377: add clk provider support 2025-11-14 12:09 ` [PATCH 2/2] iio: frequency: adf4377: add clk provider support Antoniu Miclaus 2025-11-15 17:24 ` Jonathan Cameron @ 2025-11-21 3:13 ` Stephen Boyd 1 sibling, 0 replies; 9+ messages in thread From: Stephen Boyd @ 2025-11-21 3:13 UTC (permalink / raw) To: Antoniu Miclaus, conor+dt, devicetree, jic23, linux-iio, linux-kernel, robh Cc: Antoniu Miclaus Quoting Antoniu Miclaus (2025-11-14 04:09:08) > diff --git a/drivers/iio/frequency/adf4377.c b/drivers/iio/frequency/adf4377.c > index 08833b7035e4..08dc2110cf8c 100644 > --- a/drivers/iio/frequency/adf4377.c > +++ b/drivers/iio/frequency/adf4377.c > @@ -929,6 +935,120 @@ static int adf4377_freq_change(struct notifier_block *nb, unsigned long action, > return NOTIFY_OK; > } > > +static void adf4377_clk_del_provider(void *data) > +{ > + struct adf4377_state *st = data; > + > + of_clk_del_provider(st->spi->dev.of_node); > +} > + > + > +static int adf4377_clk_is_enabled(struct clk_hw *hw) > +{ > + struct adf4377_state *st = to_adf4377_state(hw); > + unsigned int readval; > + int ret; > + > + ret = regmap_read(st->regmap, 0x1a, &readval); > + if (ret) > + return ret; > + > + return !(readval & (ADF4377_001A_PD_CLKOUT1_MSK | ADF4377_001A_PD_CLKOUT2_MSK)); > +} > + > +static const struct clk_ops adf4377_clk_ops = { > + .recalc_rate = adf4377_clk_recalc_rate, > + .set_rate = adf4377_clk_set_rate, > + .prepare = adf4377_clk_prepare, > + .unprepare = adf4377_clk_unprepare, > + .is_enabled = adf4377_clk_is_enabled, In theory .is_enabled shouldn't sleep to match the contract of .enable/.disable. Probably should change this to .is_prepared? > +}; > + > +static int adf4377_clk_register(struct adf4377_state *st) > +{ > + struct spi_device *spi = st->spi; > + struct clk_init_data init; > + struct clk *clk; > + const char *parent_name; > + int ret; > + > + if (!device_property_present(&spi->dev, "#clock-cells")) > + return 0; > + > + if (device_property_read_string(&spi->dev, "clock-output-names", &init.name)) { > + init.name = devm_kasprintf(&spi->dev, GFP_KERNEL, "%s-clk", > + fwnode_get_name(dev_fwnode(&spi->dev))); > + if (!init.name) > + return -ENOMEM; > + } > + > + parent_name = of_clk_get_parent_name(spi->dev.of_node, 0); > + if (!parent_name) > + return -EINVAL; > + > + init.ops = &adf4377_clk_ops; > + init.parent_names = &parent_name; We should be able to use clk_parent_data here instead of of_clk_get_parent_name(). It will require setting the proper DT node/device when registering the clk but it looks like you're doing that already. > + init.num_parents = 1; > + init.flags = CLK_SET_RATE_PARENT; > + > + st->hw.init = &init; > + clk = devm_clk_register(&spi->dev, &st->hw); Please use devm_clk_hw_register() > + if (IS_ERR(clk)) > + return PTR_ERR(clk); > + > + st->clk = clk; > + > + ret = of_clk_add_provider(spi->dev.of_node, of_clk_src_simple_get, clk); Please add a clk_hw provider. A clk provider isn't typically a clk consumer of the clk it provides. I think we have devm for that too? > + if (ret) > + return ret; > + > + st->clkout = clk; > + > + return devm_add_action_or_reset(&spi->dev, adf4377_clk_del_provider, st); > +} > + > static const struct adf4377_chip_info adf4377_chip_info = { > .name = "adf4377", > .has_gpio_enclk2 = true, ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 0/2] iio: frequency: adf4377: add clock provider support @ 2025-11-14 11:59 Antoniu Miclaus 2025-11-14 11:59 ` [PATCH 2/2] iio: frequency: adf4377: add clk " Antoniu Miclaus 0 siblings, 1 reply; 9+ messages in thread From: Antoniu Miclaus @ 2025-11-14 11:59 UTC (permalink / raw) To: jic23, robh, conor+dt, linux-iio, linux-kernel, devicetree Cc: Antoniu Miclaus This series adds clock provider functionality to the ADF4377 frequency synthesizer driver to address user requests for controlling output frequencies from userspace. While implemented as an IIO driver, the ADF4377 is commonly used as a clock source. This patch series enables it to function as either: - A traditional IIO device (when #clock-cells is not specified) - A clock provider (when #clock-cells is present in device tree) The implementation provides standard clock framework integration with rate control, enable/disable support, and maintains backward compatibility with existing IIO configurations. Antoniu Miclaus (2): dt-bindings: frequency: adf4377: add clk provider iio: frequency: adf4377: add clk provider support .../bindings/iio/frequency/adi,adf4377.yaml | 20 +++ drivers/iio/frequency/adf4377.c | 131 +++++++++++++++++- 2 files changed, 149 insertions(+), 2 deletions(-) -- 2.43.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/2] iio: frequency: adf4377: add clk provider support 2025-11-14 11:59 [PATCH 0/2] iio: frequency: adf4377: add clock " Antoniu Miclaus @ 2025-11-14 11:59 ` Antoniu Miclaus 0 siblings, 0 replies; 9+ messages in thread From: Antoniu Miclaus @ 2025-11-14 11:59 UTC (permalink / raw) To: jic23, robh, conor+dt, linux-iio, linux-kernel, devicetree Cc: Antoniu Miclaus Add clk provider feature for the adf4377. Even though the driver was sent as an IIO driver in most cases the device is actually seen as a clock provider. This patch aims to cover actual usecases requested by users in order to completely control the output frequencies from userspace. Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com> --- drivers/iio/frequency/adf4377.c | 131 +++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 2 deletions(-) diff --git a/drivers/iio/frequency/adf4377.c b/drivers/iio/frequency/adf4377.c index 08833b7035e4..08dc2110cf8c 100644 --- a/drivers/iio/frequency/adf4377.c +++ b/drivers/iio/frequency/adf4377.c @@ -8,6 +8,7 @@ #include <linux/bitfield.h> #include <linux/bits.h> #include <linux/clk.h> +#include <linux/clk-provider.h> #include <linux/clkdev.h> #include <linux/delay.h> #include <linux/device.h> @@ -435,9 +436,14 @@ struct adf4377_state { struct gpio_desc *gpio_ce; struct gpio_desc *gpio_enclk1; struct gpio_desc *gpio_enclk2; + struct clk *clk; + struct clk *clkout; + struct clk_hw hw; u8 buf[2] __aligned(IIO_DMA_MINALIGN); }; +#define to_adf4377_state(h) container_of(h, struct adf4377_state, hw) + static const char * const adf4377_muxout_modes[] = { [ADF4377_MUXOUT_HIGH_Z] = "high_z", [ADF4377_MUXOUT_LKDET] = "lock_detect", @@ -929,6 +935,120 @@ static int adf4377_freq_change(struct notifier_block *nb, unsigned long action, return NOTIFY_OK; } +static void adf4377_clk_del_provider(void *data) +{ + struct adf4377_state *st = data; + + of_clk_del_provider(st->spi->dev.of_node); +} + +static unsigned long adf4377_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct adf4377_state *st = to_adf4377_state(hw); + u64 freq; + int ret; + + ret = adf4377_get_freq(st, &freq); + if (ret) + return 0; + + return freq; +} + +static int adf4377_clk_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct adf4377_state *st = to_adf4377_state(hw); + + return adf4377_set_freq(st, rate); +} + +static int adf4377_clk_prepare(struct clk_hw *hw) +{ + struct adf4377_state *st = to_adf4377_state(hw); + + return regmap_update_bits(st->regmap, 0x1a, ADF4377_001A_PD_CLKOUT1_MSK | + ADF4377_001A_PD_CLKOUT2_MSK, + FIELD_PREP(ADF4377_001A_PD_CLKOUT1_MSK, 0) | + FIELD_PREP(ADF4377_001A_PD_CLKOUT2_MSK, 0)); +} + +static void adf4377_clk_unprepare(struct clk_hw *hw) +{ + struct adf4377_state *st = to_adf4377_state(hw); + + regmap_update_bits(st->regmap, 0x1a, ADF4377_001A_PD_CLKOUT1_MSK | + ADF4377_001A_PD_CLKOUT2_MSK, + FIELD_PREP(ADF4377_001A_PD_CLKOUT1_MSK, 1) | + FIELD_PREP(ADF4377_001A_PD_CLKOUT2_MSK, 1)); +} + +static int adf4377_clk_is_enabled(struct clk_hw *hw) +{ + struct adf4377_state *st = to_adf4377_state(hw); + unsigned int readval; + int ret; + + ret = regmap_read(st->regmap, 0x1a, &readval); + if (ret) + return ret; + + return !(readval & (ADF4377_001A_PD_CLKOUT1_MSK | ADF4377_001A_PD_CLKOUT2_MSK)); +} + +static const struct clk_ops adf4377_clk_ops = { + .recalc_rate = adf4377_clk_recalc_rate, + .set_rate = adf4377_clk_set_rate, + .prepare = adf4377_clk_prepare, + .unprepare = adf4377_clk_unprepare, + .is_enabled = adf4377_clk_is_enabled, +}; + +static int adf4377_clk_register(struct adf4377_state *st) +{ + struct spi_device *spi = st->spi; + struct clk_init_data init; + struct clk *clk; + const char *parent_name; + int ret; + + if (!device_property_present(&spi->dev, "#clock-cells")) + return 0; + + if (device_property_read_string(&spi->dev, "clock-output-names", &init.name)) { + init.name = devm_kasprintf(&spi->dev, GFP_KERNEL, "%s-clk", + fwnode_get_name(dev_fwnode(&spi->dev))); + if (!init.name) + return -ENOMEM; + } + + parent_name = of_clk_get_parent_name(spi->dev.of_node, 0); + if (!parent_name) + return -EINVAL; + + init.ops = &adf4377_clk_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = CLK_SET_RATE_PARENT; + + st->hw.init = &init; + clk = devm_clk_register(&spi->dev, &st->hw); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + st->clk = clk; + + ret = of_clk_add_provider(spi->dev.of_node, of_clk_src_simple_get, clk); + if (ret) + return ret; + + st->clkout = clk; + + return devm_add_action_or_reset(&spi->dev, adf4377_clk_del_provider, st); +} + static const struct adf4377_chip_info adf4377_chip_info = { .name = "adf4377", .has_gpio_enclk2 = true, @@ -958,8 +1078,6 @@ static int adf4377_probe(struct spi_device *spi) indio_dev->info = &adf4377_info; indio_dev->name = "adf4377"; - indio_dev->channels = adf4377_channels; - indio_dev->num_channels = ARRAY_SIZE(adf4377_channels); st->regmap = regmap; st->spi = spi; @@ -979,6 +1097,15 @@ static int adf4377_probe(struct spi_device *spi) if (ret) return ret; + ret = adf4377_clk_register(st); + if (ret) + return ret; + + if (!st->clkout) { + indio_dev->channels = adf4377_channels; + indio_dev->num_channels = ARRAY_SIZE(adf4377_channels); + } + return devm_iio_device_register(&spi->dev, indio_dev); } -- 2.43.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-11-21 5:20 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-11-14 12:09 [PATCH 0/2] iio: frequency: adf4377: add clock provider support Antoniu Miclaus 2025-11-14 12:09 ` [PATCH 1/2] dt-bindings: frequency: adf4377: add clk provider Antoniu Miclaus 2025-11-15 17:25 ` Jonathan Cameron 2025-11-14 12:09 ` [PATCH 2/2] iio: frequency: adf4377: add clk provider support Antoniu Miclaus 2025-11-15 17:24 ` Jonathan Cameron 2025-11-17 8:35 ` Nuno Sá 2025-11-17 9:09 ` Miclaus, Antoniu 2025-11-21 3:13 ` Stephen Boyd -- strict thread matches above, loose matches on Subject: below -- 2025-11-14 11:59 [PATCH 0/2] iio: frequency: adf4377: add clock " Antoniu Miclaus 2025-11-14 11:59 ` [PATCH 2/2] iio: frequency: adf4377: add clk " Antoniu Miclaus
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).