diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c index 19216af1..e839d23a 100644 --- a/drivers/staging/iio/frequency/ad9834.c +++ b/drivers/staging/iio/frequency/ad9834.c @@ -13,11 +13,14 @@ #include #include #include +#include +#include #include #include #include #include #include +#include #include #include @@ -316,14 +319,81 @@ static const struct iio_info ad9833_info = { .driver_module = THIS_MODULE, }; +#if defined(CONFIG_OF) +static struct ad9834_platform_data *ad9834_parse_dt(struct spi_device *spi) +{ + struct ad9834_platform_data *pdata; + struct device_node *np = spi->dev.of_node; + + pdata = devm_kzalloc(&spi->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + pdata->freq0 = 134000; + of_property_read_u32(np, "freq0", &pdata->freq0); + + pdata->freq1 = 134000; + of_property_read_u32(np, "freq1", &pdata->freq1); + + pdata->phase0 = 0; + of_property_read_u16(np, "phase0", &pdata->phase0); + + pdata->phase1 = 0; + of_property_read_u16(np, "phase1", &pdata->phase1); + + pdata->en_div2 = of_property_read_bool(np, "en_div2"); + pdata->en_signbit_msb_out = of_property_read_bool(np, + "en_signbit_msb_out"); + + return pdata; +} +#else +static struct ad9834_platform_data *ad9834_parse_dt(struct spi_device *spi) +{ + return NULL; +} +#endif + +static const struct of_device_id ad9834_of_match[] = { + { + .compatible = "adi,ad9833", + .data = (void *)ID_AD9833, + }, + { + .compatible = "adi,ad9834", + .data = (void *)ID_AD9834, + }, + { + .compatible = "adi,ad9837", + .data = (void *)ID_AD9837, + }, + { + .compatible = "adi,ad9838", + .data = (void *)ID_AD9838, + }, + { } +}; +MODULE_DEVICE_TABLE(of, ad9834_of_match); + static int ad9834_probe(struct spi_device *spi) { - struct ad9834_platform_data *pdata = dev_get_platdata(&spi->dev); + const struct of_device_id *of_id = of_match_device(ad9834_of_match, + &spi->dev); + struct ad9834_platform_data *pdata; struct ad9834_state *st; struct iio_dev *indio_dev; struct regulator *reg; + struct clk *clk = NULL; int ret; + if (!pdata && spi->dev.of_node) { + pdata = ad9834_parse_dt(spi); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + } else { + pdata = spi->dev.platform_data; + } + if (!pdata) { dev_dbg(&spi->dev, "no platform data?\n"); return -ENODEV; @@ -346,9 +416,30 @@ static int ad9834_probe(struct spi_device *spi) } spi_set_drvdata(spi, indio_dev); st = iio_priv(indio_dev); - st->mclk = pdata->mclk; + + if (!pdata->mclk) { + clk = devm_clk_get(&spi->dev, NULL); + if (IS_ERR(clk)) + return -EPROBE_DEFER; + + ret = clk_prepare_enable(clk); + if (ret < 0) + return ret; + } + + if (clk) { + st->clk = clk; + st->mclk = clk_get_rate(clk); + } else { + st->mclk = pdata->mclk; + } + + if (of_id) + st->devid = (enum ad9834_supported_device_ids)of_id->data; + else + st->devid = spi_get_device_id(spi)->driver_data; + st->spi = spi; - st->devid = spi_get_device_id(spi)->driver_data; st->reg = reg; indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; @@ -421,6 +512,9 @@ static int ad9834_probe(struct spi_device *spi) error_disable_reg: regulator_disable(reg); +if (clk) + clk_disable_unprepare(clk); + return ret; } @@ -431,6 +525,8 @@ static int ad9834_remove(struct spi_device *spi) iio_device_unregister(indio_dev); regulator_disable(st->reg); +if (st->clk) + clk_disable_unprepare(st->clk); return 0; } @@ -447,6 +543,7 @@ MODULE_DEVICE_TABLE(spi, ad9834_id); static struct spi_driver ad9834_driver = { .driver = { .name = "ad9834", + .of_match_table = of_match_ptr(ad9834_of_match), }, .probe = ad9834_probe, .remove = ad9834_remove, diff --git a/drivers/staging/iio/frequency/ad9834.h b/drivers/staging/iio/frequency/ad9834.h index 40fdd5da..fd9cccf3 100644 --- a/drivers/staging/iio/frequency/ad9834.h +++ b/drivers/staging/iio/frequency/ad9834.h @@ -53,6 +53,7 @@ struct ad9834_state { struct spi_device *spi; struct regulator *reg; + struct clk *clk; unsigned int mclk; unsigned short control; unsigned short devid;