ad9834 driver needs some default properties. Currently these parameters are
provided through platform_data.
This patch adds a function to create this pdata based on device-tree node.
Signed-off-by: Gwenhael Goavec-Merou
---
Changes v1 -> v2:
- use clock bindings for input clock (Lars-Peter Clausen)
- provides a default value for freq0/1 and phase0/1 (Lars-Peter Clausen)
---
drivers/staging/iio/frequency/ad9834.c | 71 +-
drivers/staging/iio/frequency/ad9834.h | 1 +
2 files changed, 70 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/iio/frequency/ad9834.c
b/drivers/staging/iio/frequency/ad9834.c
index 6366216..24a3e84 100644
--- a/drivers/staging/iio/frequency/ad9834.c
+++ b/drivers/staging/iio/frequency/ad9834.c
@@ -18,6 +18,7 @@
#include
#include
#include
+#include
#include
#include
@@ -316,24 +317,76 @@ 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(>dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ pdata->freq0 = 134000;
+ of_property_read_u32(np, "freq0", >freq0);
+
+ pdata->freq1 = 134000;
+ of_property_read_u32(np, "freq1", >freq1);
+
+ pdata->phase0 = 0;
+ of_property_read_u16(np, "phase0", >phase0);
+
+ pdata->phase1 = 0;
+ of_property_read_u16(np, "phase1", >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 int ad9834_probe(struct spi_device *spi)
{
struct ad9834_platform_data *pdata = dev_get_platdata(>dev);
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);
+ }
+
if (!pdata) {
dev_dbg(>dev, "no platform data?\n");
return -ENODEV;
}
+ if (!pdata->mclk) {
+ clk = devm_clk_get(>dev, NULL);
+ if (IS_ERR(clk))
+ return -EPROBE_DEFER;
+
+ ret = clk_prepare_enable(clk);
+ if (ret < 0)
+ return ret;
+ }
+
reg = devm_regulator_get(>dev, "vcc");
if (!IS_ERR(reg)) {
ret = regulator_enable(reg);
if (ret)
- return ret;
+ goto error_disable_clk;
}
indio_dev = devm_iio_device_alloc(>dev, sizeof(*st));
@@ -343,7 +396,14 @@ static int ad9834_probe(struct spi_device *spi)
}
spi_set_drvdata(spi, indio_dev);
st = iio_priv(indio_dev);
- st->mclk = pdata->mclk;
+
+ if (clk) {
+ st->clk = clk;
+ st->mclk = clk_get_rate(clk);
+ } else {
+ st->mclk = pdata->mclk;
+ }
+
st->spi = spi;
st->devid = spi_get_device_id(spi)->driver_data;
st->reg = reg;
@@ -418,6 +478,9 @@ static int ad9834_probe(struct spi_device *spi)
error_disable_reg:
if (!IS_ERR(reg))
regulator_disable(reg);
+error_disable_clk:
+ if (clk)
+ clk_disable_unprepare(clk);
return ret;
}
@@ -428,6 +491,10 @@ static int ad9834_remove(struct spi_device *spi)
struct ad9834_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
+
+ if (st->clk)
+ clk_disable_unprepare(st->clk);
+
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
diff --git a/drivers/staging/iio/frequency/ad9834.h
b/drivers/staging/iio/frequency/ad9834.h
index 40fdd5d..fd9cccf 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 intmclk;
unsigned short control;
unsigned short devid;
--
2.9.3
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel