mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-22 14:51:41 +00:00
174 lines
4.3 KiB
Diff
174 lines
4.3 KiB
Diff
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 <linux/slab.h>
|
|
#include <linux/sysfs.h>
|
|
#include <linux/list.h>
|
|
+#include <linux/of.h>
|
|
+#include <linux/of_device.h>
|
|
#include <linux/spi/spi.h>
|
|
#include <linux/regulator/consumer.h>
|
|
#include <linux/err.h>
|
|
#include <linux/module.h>
|
|
#include <asm/div64.h>
|
|
+#include <linux/clk.h>
|
|
|
|
#include <linux/iio/iio.h>
|
|
#include <linux/iio/sysfs.h>
|
|
@@ -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;
|