diff options
Diffstat (limited to 'drivers/iio/adc/xilinx-xadc-core.c')
| -rw-r--r-- | drivers/iio/adc/xilinx-xadc-core.c | 44 | 
1 files changed, 32 insertions, 12 deletions
| diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c index d4f21d1be6c8..3f6be5ac049a 100644 --- a/drivers/iio/adc/xilinx-xadc-core.c +++ b/drivers/iio/adc/xilinx-xadc-core.c @@ -322,6 +322,7 @@ static irqreturn_t xadc_zynq_interrupt_handler(int irq, void *devid)  #define XADC_ZYNQ_TCK_RATE_MAX 50000000  #define XADC_ZYNQ_IGAP_DEFAULT 20 +#define XADC_ZYNQ_PCAP_RATE_MAX 200000000  static int xadc_zynq_setup(struct platform_device *pdev,  	struct iio_dev *indio_dev, int irq) @@ -332,6 +333,7 @@ static int xadc_zynq_setup(struct platform_device *pdev,  	unsigned int div;  	unsigned int igap;  	unsigned int tck_rate; +	int ret;  	/* TODO: Figure out how to make igap and tck_rate configurable */  	igap = XADC_ZYNQ_IGAP_DEFAULT; @@ -340,9 +342,16 @@ static int xadc_zynq_setup(struct platform_device *pdev,  	xadc->zynq_intmask = ~0;  	pcap_rate = clk_get_rate(xadc->clk); +	if (!pcap_rate) +		return -EINVAL; + +	if (pcap_rate > XADC_ZYNQ_PCAP_RATE_MAX) { +		ret = clk_set_rate(xadc->clk, +				   (unsigned long)XADC_ZYNQ_PCAP_RATE_MAX); +		if (ret) +			return ret; +	} -	if (tck_rate > XADC_ZYNQ_TCK_RATE_MAX) -		tck_rate = XADC_ZYNQ_TCK_RATE_MAX;  	if (tck_rate > pcap_rate / 2) {  		div = 2;  	} else { @@ -368,6 +377,12 @@ static int xadc_zynq_setup(struct platform_device *pdev,  			XADC_ZYNQ_CFG_REDGE | XADC_ZYNQ_CFG_WEDGE |  			tck_div | XADC_ZYNQ_CFG_IGAP(igap)); +	if (pcap_rate > XADC_ZYNQ_PCAP_RATE_MAX) { +		ret = clk_set_rate(xadc->clk, pcap_rate); +		if (ret) +			return ret; +	} +  	return 0;  } @@ -889,6 +904,9 @@ static int xadc_write_raw(struct iio_dev *indio_dev,  	unsigned long clk_rate = xadc_get_dclk_rate(xadc);  	unsigned int div; +	if (!clk_rate) +		return -EINVAL; +  	if (info != IIO_CHAN_INFO_SAMP_FREQ)  		return -EINVAL; @@ -1045,7 +1063,7 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,  	unsigned int num_channels;  	const char *external_mux;  	u32 ext_mux_chan; -	int reg; +	u32 reg;  	int ret;  	*conf = 0; @@ -1157,6 +1175,7 @@ static int xadc_probe(struct platform_device *pdev)  	xadc = iio_priv(indio_dev);  	xadc->ops = id->data; +	xadc->irq = irq;  	init_completion(&xadc->completion);  	mutex_init(&xadc->mutex);  	spin_lock_init(&xadc->lock); @@ -1207,14 +1226,14 @@ static int xadc_probe(struct platform_device *pdev)  	if (ret)  		goto err_free_samplerate_trigger; -	ret = xadc->ops->setup(pdev, indio_dev, irq); +	ret = request_irq(xadc->irq, xadc->ops->interrupt_handler, 0, +			dev_name(&pdev->dev), indio_dev);  	if (ret)  		goto err_clk_disable_unprepare; -	ret = request_irq(irq, xadc->ops->interrupt_handler, 0, -			dev_name(&pdev->dev), indio_dev); +	ret = xadc->ops->setup(pdev, indio_dev, xadc->irq);  	if (ret) -		goto err_clk_disable_unprepare; +		goto err_free_irq;  	for (i = 0; i < 16; i++)  		xadc_read_adc_reg(xadc, XADC_REG_THRESHOLD(i), @@ -1239,8 +1258,10 @@ static int xadc_probe(struct platform_device *pdev)  		goto err_free_irq;  	/* Disable all alarms */ -	xadc_update_adc_reg(xadc, XADC_REG_CONF1, XADC_CONF1_ALARM_MASK, -		XADC_CONF1_ALARM_MASK); +	ret = xadc_update_adc_reg(xadc, XADC_REG_CONF1, XADC_CONF1_ALARM_MASK, +				  XADC_CONF1_ALARM_MASK); +	if (ret) +		goto err_free_irq;  	/* Set thresholds to min/max */  	for (i = 0; i < 16; i++) { @@ -1268,7 +1289,7 @@ static int xadc_probe(struct platform_device *pdev)  	return 0;  err_free_irq: -	free_irq(irq, indio_dev); +	free_irq(xadc->irq, indio_dev);  err_clk_disable_unprepare:  	clk_disable_unprepare(xadc->clk);  err_free_samplerate_trigger: @@ -1290,7 +1311,6 @@ static int xadc_remove(struct platform_device *pdev)  {  	struct iio_dev *indio_dev = platform_get_drvdata(pdev);  	struct xadc *xadc = iio_priv(indio_dev); -	int irq = platform_get_irq(pdev, 0);  	iio_device_unregister(indio_dev);  	if (xadc->ops->flags & XADC_FLAGS_BUFFERED) { @@ -1298,7 +1318,7 @@ static int xadc_remove(struct platform_device *pdev)  		iio_trigger_free(xadc->convst_trigger);  		iio_triggered_buffer_cleanup(indio_dev);  	} -	free_irq(irq, indio_dev); +	free_irq(xadc->irq, indio_dev);  	clk_disable_unprepare(xadc->clk);  	cancel_delayed_work(&xadc->zynq_unmask_work);  	kfree(xadc->data); |