Skip to content

Commit 3b7f9db

Browse files
larsclausenjic23
authored andcommitted
iio: xilinx-xadc: Make sure not exceed maximum samplerate
The XADC supports a samplerate of up to 1MSPS. Unfortunately the hardware does not have a FIFO, which means it generates an interrupt for each conversion sequence. At one 1MSPS this creates an interrupt storm that causes the system to soft-lock. For this reason the driver limits the maximum samplerate to 150kSPS. Currently this check is only done when setting a new samplerate. But it is also possible that the initial samplerate configured in the FPGA bitstream exceeds the limit. In this case when starting to capture data without first changing the samplerate the system can overload. To prevent this check the currently configured samplerate in the probe function and reduce it to the maximum if necessary. Signed-off-by: Lars-Peter Clausen <[email protected]> Fixes: bdc8cda ("iio:adc: Add Xilinx XADC driver") Cc: <[email protected]> Signed-off-by: Jonathan Cameron <[email protected]>
1 parent 8bef455 commit 3b7f9db

File tree

1 file changed

+60
-18
lines changed

1 file changed

+60
-18
lines changed

drivers/iio/adc/xilinx-xadc-core.c

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,16 @@ static const unsigned int XADC_ZYNQ_UNMASK_TIMEOUT = 500;
102102

103103
#define XADC_FLAGS_BUFFERED BIT(0)
104104

105+
/*
106+
* The XADC hardware supports a samplerate of up to 1MSPS. Unfortunately it does
107+
* not have a hardware FIFO. Which means an interrupt is generated for each
108+
* conversion sequence. At 1MSPS sample rate the CPU in ZYNQ7000 is completely
109+
* overloaded by the interrupts that it soft-lockups. For this reason the driver
110+
* limits the maximum samplerate 150kSPS. At this rate the CPU is fairly busy,
111+
* but still responsive.
112+
*/
113+
#define XADC_MAX_SAMPLERATE 150000
114+
105115
static void xadc_write_reg(struct xadc *xadc, unsigned int reg,
106116
uint32_t val)
107117
{
@@ -834,11 +844,27 @@ static const struct iio_buffer_setup_ops xadc_buffer_ops = {
834844
.postdisable = &xadc_postdisable,
835845
};
836846

847+
static int xadc_read_samplerate(struct xadc *xadc)
848+
{
849+
unsigned int div;
850+
uint16_t val16;
851+
int ret;
852+
853+
ret = xadc_read_adc_reg(xadc, XADC_REG_CONF2, &val16);
854+
if (ret)
855+
return ret;
856+
857+
div = (val16 & XADC_CONF2_DIV_MASK) >> XADC_CONF2_DIV_OFFSET;
858+
if (div < 2)
859+
div = 2;
860+
861+
return xadc_get_dclk_rate(xadc) / div / 26;
862+
}
863+
837864
static int xadc_read_raw(struct iio_dev *indio_dev,
838865
struct iio_chan_spec const *chan, int *val, int *val2, long info)
839866
{
840867
struct xadc *xadc = iio_priv(indio_dev);
841-
unsigned int div;
842868
uint16_t val16;
843869
int ret;
844870

@@ -891,41 +917,31 @@ static int xadc_read_raw(struct iio_dev *indio_dev,
891917
*val = -((273150 << 12) / 503975);
892918
return IIO_VAL_INT;
893919
case IIO_CHAN_INFO_SAMP_FREQ:
894-
ret = xadc_read_adc_reg(xadc, XADC_REG_CONF2, &val16);
895-
if (ret)
920+
ret = xadc_read_samplerate(xadc);
921+
if (ret < 0)
896922
return ret;
897923

898-
div = (val16 & XADC_CONF2_DIV_MASK) >> XADC_CONF2_DIV_OFFSET;
899-
if (div < 2)
900-
div = 2;
901-
902-
*val = xadc_get_dclk_rate(xadc) / div / 26;
903-
924+
*val = ret;
904925
return IIO_VAL_INT;
905926
default:
906927
return -EINVAL;
907928
}
908929
}
909930

910-
static int xadc_write_raw(struct iio_dev *indio_dev,
911-
struct iio_chan_spec const *chan, int val, int val2, long info)
931+
static int xadc_write_samplerate(struct xadc *xadc, int val)
912932
{
913-
struct xadc *xadc = iio_priv(indio_dev);
914933
unsigned long clk_rate = xadc_get_dclk_rate(xadc);
915934
unsigned int div;
916935

917936
if (!clk_rate)
918937
return -EINVAL;
919938

920-
if (info != IIO_CHAN_INFO_SAMP_FREQ)
921-
return -EINVAL;
922-
923939
if (val <= 0)
924940
return -EINVAL;
925941

926942
/* Max. 150 kSPS */
927-
if (val > 150000)
928-
val = 150000;
943+
if (val > XADC_MAX_SAMPLERATE)
944+
val = XADC_MAX_SAMPLERATE;
929945

930946
val *= 26;
931947

@@ -938,7 +954,7 @@ static int xadc_write_raw(struct iio_dev *indio_dev,
938954
* limit.
939955
*/
940956
div = clk_rate / val;
941-
if (clk_rate / div / 26 > 150000)
957+
if (clk_rate / div / 26 > XADC_MAX_SAMPLERATE)
942958
div++;
943959
if (div < 2)
944960
div = 2;
@@ -949,6 +965,17 @@ static int xadc_write_raw(struct iio_dev *indio_dev,
949965
div << XADC_CONF2_DIV_OFFSET);
950966
}
951967

968+
static int xadc_write_raw(struct iio_dev *indio_dev,
969+
struct iio_chan_spec const *chan, int val, int val2, long info)
970+
{
971+
struct xadc *xadc = iio_priv(indio_dev);
972+
973+
if (info != IIO_CHAN_INFO_SAMP_FREQ)
974+
return -EINVAL;
975+
976+
return xadc_write_samplerate(xadc, val);
977+
}
978+
952979
static const struct iio_event_spec xadc_temp_events[] = {
953980
{
954981
.type = IIO_EV_TYPE_THRESH,
@@ -1234,6 +1261,21 @@ static int xadc_probe(struct platform_device *pdev)
12341261
if (ret)
12351262
goto err_free_samplerate_trigger;
12361263

1264+
/*
1265+
* Make sure not to exceed the maximum samplerate since otherwise the
1266+
* resulting interrupt storm will soft-lock the system.
1267+
*/
1268+
if (xadc->ops->flags & XADC_FLAGS_BUFFERED) {
1269+
ret = xadc_read_samplerate(xadc);
1270+
if (ret < 0)
1271+
goto err_free_samplerate_trigger;
1272+
if (ret > XADC_MAX_SAMPLERATE) {
1273+
ret = xadc_write_samplerate(xadc, XADC_MAX_SAMPLERATE);
1274+
if (ret < 0)
1275+
goto err_free_samplerate_trigger;
1276+
}
1277+
}
1278+
12371279
ret = request_irq(xadc->irq, xadc->ops->interrupt_handler, 0,
12381280
dev_name(&pdev->dev), indio_dev);
12391281
if (ret)

0 commit comments

Comments
 (0)