All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] iio: xilinx-xadc: Make IRQ optional
@ 2021-10-21 12:59 Lars-Peter Clausen
  2021-10-28 14:23 ` Jonathan Cameron
  0 siblings, 1 reply; 2+ messages in thread
From: Lars-Peter Clausen @ 2021-10-21 12:59 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Michal Simek, Anand Ashok Dumbre, linux-iio, Lars-Peter Clausen

In some setups the IRQ signal of the XADC might not be wired to the host
system. The driver currently requires that an interrupt is specified. Make
the interrupt optional so the driver can be used in such setups where the
interrupt is not connected.

Since both the internal triggers as well as events depend on the interrupt
being connected both are not available when the interrupt is not connected.

Buffered access is still supported even without an interrupt since an
external trigger can be used.

The IRQ is only optional when using the AXI interface, since the PCAP
interface needs the IRQ for reading and writing registers.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/iio/adc/xilinx-xadc-core.c | 62 +++++++++++++++++++-----------
 1 file changed, 40 insertions(+), 22 deletions(-)

diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
index 83bea5ef765d..2aa4278ecba7 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -107,6 +107,7 @@ static const unsigned int XADC_ZYNQ_UNMASK_TIMEOUT = 500;
 #define XADC_AXI_INT_ALARM_MASK		0x3c0f
 
 #define XADC_FLAGS_BUFFERED BIT(0)
+#define XADC_FLAGS_IRQ_OPTIONAL BIT(1)
 
 /*
  * The XADC hardware supports a samplerate of up to 1MSPS. Unfortunately it does
@@ -562,7 +563,7 @@ static const struct xadc_ops xadc_7s_axi_ops = {
 	.get_dclk_rate = xadc_axi_get_dclk,
 	.update_alarm = xadc_axi_update_alarm,
 	.interrupt_handler = xadc_axi_interrupt_handler,
-	.flags = XADC_FLAGS_BUFFERED,
+	.flags = XADC_FLAGS_BUFFERED | XADC_FLAGS_IRQ_OPTIONAL,
 	.type = XADC_TYPE_S7,
 };
 
@@ -573,7 +574,7 @@ static const struct xadc_ops xadc_us_axi_ops = {
 	.get_dclk_rate = xadc_axi_get_dclk,
 	.update_alarm = xadc_axi_update_alarm,
 	.interrupt_handler = xadc_axi_interrupt_handler,
-	.flags = XADC_FLAGS_BUFFERED,
+	.flags = XADC_FLAGS_BUFFERED | XADC_FLAGS_IRQ_OPTIONAL,
 	.type = XADC_TYPE_US,
 };
 
@@ -1182,7 +1183,7 @@ static const struct of_device_id xadc_of_match_table[] = {
 MODULE_DEVICE_TABLE(of, xadc_of_match_table);
 
 static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
-	unsigned int *conf)
+	unsigned int *conf, int irq)
 {
 	struct device *dev = indio_dev->dev.parent;
 	struct xadc *xadc = iio_priv(indio_dev);
@@ -1195,6 +1196,7 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
 	u32 ext_mux_chan;
 	u32 reg;
 	int ret;
+	int i;
 
 	*conf = 0;
 
@@ -1273,6 +1275,14 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
 	}
 	of_node_put(chan_node);
 
+	/* No IRQ => no events */
+	if (irq <= 0) {
+		for (i = 0; i < num_channels; i++) {
+			channels[i].event_spec = NULL;
+			channels[i].num_event_specs = 0;
+		}
+	}
+
 	indio_dev->num_channels = num_channels;
 	indio_dev->channels = devm_krealloc(dev, channels,
 					    sizeof(*channels) * num_channels,
@@ -1307,6 +1317,7 @@ static int xadc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	const struct of_device_id *id;
+	const struct xadc_ops *ops;
 	struct iio_dev *indio_dev;
 	unsigned int bipolar_mask;
 	unsigned int conf0;
@@ -1322,9 +1333,12 @@ static int xadc_probe(struct platform_device *pdev)
 	if (!id)
 		return -EINVAL;
 
-	irq = platform_get_irq(pdev, 0);
-	if (irq <= 0)
-		return -ENXIO;
+	ops = id->data;
+
+	irq = platform_get_irq_optional(pdev, 0);
+	if (irq < 0 &&
+	    (irq != -ENXIO || !(ops->flags & XADC_FLAGS_IRQ_OPTIONAL)))
+		return irq;
 
 	indio_dev = devm_iio_device_alloc(dev, sizeof(*xadc));
 	if (!indio_dev)
@@ -1345,7 +1359,7 @@ static int xadc_probe(struct platform_device *pdev)
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &xadc_info;
 
-	ret = xadc_parse_dt(indio_dev, dev->of_node, &conf0);
+	ret = xadc_parse_dt(indio_dev, dev->of_node, &conf0, irq);
 	if (ret)
 		return ret;
 
@@ -1357,14 +1371,16 @@ static int xadc_probe(struct platform_device *pdev)
 		if (ret)
 			return ret;
 
-		xadc->convst_trigger = xadc_alloc_trigger(indio_dev, "convst");
-		if (IS_ERR(xadc->convst_trigger))
-			return PTR_ERR(xadc->convst_trigger);
+		if (irq > 0) {
+			xadc->convst_trigger = xadc_alloc_trigger(indio_dev, "convst");
+			if (IS_ERR(xadc->convst_trigger))
+				return PTR_ERR(xadc->convst_trigger);
 
-		xadc->samplerate_trigger = xadc_alloc_trigger(indio_dev,
-			"samplerate");
-		if (IS_ERR(xadc->samplerate_trigger))
-			return PTR_ERR(xadc->samplerate_trigger);
+			xadc->samplerate_trigger = xadc_alloc_trigger(indio_dev,
+				"samplerate");
+			if (IS_ERR(xadc->samplerate_trigger))
+				return PTR_ERR(xadc->samplerate_trigger);
+		}
 	}
 
 	xadc->clk = devm_clk_get(dev, NULL);
@@ -1396,15 +1412,17 @@ static int xadc_probe(struct platform_device *pdev)
 		}
 	}
 
-	ret = devm_request_irq(dev, irq, xadc->ops->interrupt_handler, 0,
-			       dev_name(dev), indio_dev);
-	if (ret)
-		return ret;
+	if (irq > 0) {
+		ret = devm_request_irq(dev, irq, xadc->ops->interrupt_handler,
+				       0, dev_name(dev), indio_dev);
+		if (ret)
+			return ret;
 
-	ret = devm_add_action_or_reset(dev, xadc_cancel_delayed_work,
-				       &xadc->zynq_unmask_work);
-	if (ret)
-		return ret;
+		ret = devm_add_action_or_reset(dev, xadc_cancel_delayed_work,
+					       &xadc->zynq_unmask_work);
+		if (ret)
+			return ret;
+	}
 
 	ret = xadc->ops->setup(pdev, indio_dev, irq);
 	if (ret)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] iio: xilinx-xadc: Make IRQ optional
  2021-10-21 12:59 [PATCH] iio: xilinx-xadc: Make IRQ optional Lars-Peter Clausen
@ 2021-10-28 14:23 ` Jonathan Cameron
  0 siblings, 0 replies; 2+ messages in thread
From: Jonathan Cameron @ 2021-10-28 14:23 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: Michal Simek, Anand Ashok Dumbre, linux-iio

On Thu, 21 Oct 2021 14:59:50 +0200
Lars-Peter Clausen <lars@metafoo.de> wrote:

> In some setups the IRQ signal of the XADC might not be wired to the host
> system. The driver currently requires that an interrupt is specified. Make
> the interrupt optional so the driver can be used in such setups where the
> interrupt is not connected.
> 
> Since both the internal triggers as well as events depend on the interrupt
> being connected both are not available when the interrupt is not connected.
> 
> Buffered access is still supported even without an interrupt since an
> external trigger can be used.
> 
> The IRQ is only optional when using the AXI interface, since the PCAP
> interface needs the IRQ for reading and writing registers.
> 
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>

Applied to the togreg branch of iio.git and pushed out as testing.

Thanks,

Jonathan

> ---
>  drivers/iio/adc/xilinx-xadc-core.c | 62 +++++++++++++++++++-----------
>  1 file changed, 40 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
> index 83bea5ef765d..2aa4278ecba7 100644
> --- a/drivers/iio/adc/xilinx-xadc-core.c
> +++ b/drivers/iio/adc/xilinx-xadc-core.c
> @@ -107,6 +107,7 @@ static const unsigned int XADC_ZYNQ_UNMASK_TIMEOUT = 500;
>  #define XADC_AXI_INT_ALARM_MASK		0x3c0f
>  
>  #define XADC_FLAGS_BUFFERED BIT(0)
> +#define XADC_FLAGS_IRQ_OPTIONAL BIT(1)
>  
>  /*
>   * The XADC hardware supports a samplerate of up to 1MSPS. Unfortunately it does
> @@ -562,7 +563,7 @@ static const struct xadc_ops xadc_7s_axi_ops = {
>  	.get_dclk_rate = xadc_axi_get_dclk,
>  	.update_alarm = xadc_axi_update_alarm,
>  	.interrupt_handler = xadc_axi_interrupt_handler,
> -	.flags = XADC_FLAGS_BUFFERED,
> +	.flags = XADC_FLAGS_BUFFERED | XADC_FLAGS_IRQ_OPTIONAL,
>  	.type = XADC_TYPE_S7,
>  };
>  
> @@ -573,7 +574,7 @@ static const struct xadc_ops xadc_us_axi_ops = {
>  	.get_dclk_rate = xadc_axi_get_dclk,
>  	.update_alarm = xadc_axi_update_alarm,
>  	.interrupt_handler = xadc_axi_interrupt_handler,
> -	.flags = XADC_FLAGS_BUFFERED,
> +	.flags = XADC_FLAGS_BUFFERED | XADC_FLAGS_IRQ_OPTIONAL,
>  	.type = XADC_TYPE_US,
>  };
>  
> @@ -1182,7 +1183,7 @@ static const struct of_device_id xadc_of_match_table[] = {
>  MODULE_DEVICE_TABLE(of, xadc_of_match_table);
>  
>  static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
> -	unsigned int *conf)
> +	unsigned int *conf, int irq)
>  {
>  	struct device *dev = indio_dev->dev.parent;
>  	struct xadc *xadc = iio_priv(indio_dev);
> @@ -1195,6 +1196,7 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
>  	u32 ext_mux_chan;
>  	u32 reg;
>  	int ret;
> +	int i;
>  
>  	*conf = 0;
>  
> @@ -1273,6 +1275,14 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
>  	}
>  	of_node_put(chan_node);
>  
> +	/* No IRQ => no events */
> +	if (irq <= 0) {
> +		for (i = 0; i < num_channels; i++) {
> +			channels[i].event_spec = NULL;
> +			channels[i].num_event_specs = 0;
> +		}
> +	}
> +
>  	indio_dev->num_channels = num_channels;
>  	indio_dev->channels = devm_krealloc(dev, channels,
>  					    sizeof(*channels) * num_channels,
> @@ -1307,6 +1317,7 @@ static int xadc_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
>  	const struct of_device_id *id;
> +	const struct xadc_ops *ops;
>  	struct iio_dev *indio_dev;
>  	unsigned int bipolar_mask;
>  	unsigned int conf0;
> @@ -1322,9 +1333,12 @@ static int xadc_probe(struct platform_device *pdev)
>  	if (!id)
>  		return -EINVAL;
>  
> -	irq = platform_get_irq(pdev, 0);
> -	if (irq <= 0)
> -		return -ENXIO;
> +	ops = id->data;
> +
> +	irq = platform_get_irq_optional(pdev, 0);
> +	if (irq < 0 &&
> +	    (irq != -ENXIO || !(ops->flags & XADC_FLAGS_IRQ_OPTIONAL)))
> +		return irq;
>  
>  	indio_dev = devm_iio_device_alloc(dev, sizeof(*xadc));
>  	if (!indio_dev)
> @@ -1345,7 +1359,7 @@ static int xadc_probe(struct platform_device *pdev)
>  	indio_dev->modes = INDIO_DIRECT_MODE;
>  	indio_dev->info = &xadc_info;
>  
> -	ret = xadc_parse_dt(indio_dev, dev->of_node, &conf0);
> +	ret = xadc_parse_dt(indio_dev, dev->of_node, &conf0, irq);
>  	if (ret)
>  		return ret;
>  
> @@ -1357,14 +1371,16 @@ static int xadc_probe(struct platform_device *pdev)
>  		if (ret)
>  			return ret;
>  
> -		xadc->convst_trigger = xadc_alloc_trigger(indio_dev, "convst");
> -		if (IS_ERR(xadc->convst_trigger))
> -			return PTR_ERR(xadc->convst_trigger);
> +		if (irq > 0) {
> +			xadc->convst_trigger = xadc_alloc_trigger(indio_dev, "convst");
> +			if (IS_ERR(xadc->convst_trigger))
> +				return PTR_ERR(xadc->convst_trigger);
>  
> -		xadc->samplerate_trigger = xadc_alloc_trigger(indio_dev,
> -			"samplerate");
> -		if (IS_ERR(xadc->samplerate_trigger))
> -			return PTR_ERR(xadc->samplerate_trigger);
> +			xadc->samplerate_trigger = xadc_alloc_trigger(indio_dev,
> +				"samplerate");
> +			if (IS_ERR(xadc->samplerate_trigger))
> +				return PTR_ERR(xadc->samplerate_trigger);
> +		}
>  	}
>  
>  	xadc->clk = devm_clk_get(dev, NULL);
> @@ -1396,15 +1412,17 @@ static int xadc_probe(struct platform_device *pdev)
>  		}
>  	}
>  
> -	ret = devm_request_irq(dev, irq, xadc->ops->interrupt_handler, 0,
> -			       dev_name(dev), indio_dev);
> -	if (ret)
> -		return ret;
> +	if (irq > 0) {
> +		ret = devm_request_irq(dev, irq, xadc->ops->interrupt_handler,
> +				       0, dev_name(dev), indio_dev);
> +		if (ret)
> +			return ret;
>  
> -	ret = devm_add_action_or_reset(dev, xadc_cancel_delayed_work,
> -				       &xadc->zynq_unmask_work);
> -	if (ret)
> -		return ret;
> +		ret = devm_add_action_or_reset(dev, xadc_cancel_delayed_work,
> +					       &xadc->zynq_unmask_work);
> +		if (ret)
> +			return ret;
> +	}
>  
>  	ret = xadc->ops->setup(pdev, indio_dev, irq);
>  	if (ret)


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-10-28 14:19 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-21 12:59 [PATCH] iio: xilinx-xadc: Make IRQ optional Lars-Peter Clausen
2021-10-28 14:23 ` Jonathan Cameron

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.