Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c9474599 authored by Sean Nyekjaer's avatar Sean Nyekjaer Committed by Jonathan Cameron
Browse files

iio: ad5755: add support for dt bindings



Devicetree can provide platform data

Signed-off-by: default avatarSean Nyekjaer <sean.nyekjaer@prevas.dk>
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
parent 29e3e06d
Loading
Loading
Loading
Loading
+187 −1
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/platform_data/ad5755.h>
@@ -109,6 +110,51 @@ enum ad5755_type {
	ID_AD5737,
};

#ifdef CONFIG_OF
static const int ad5755_dcdc_freq_table[][2] = {
	{ 250000, AD5755_DC_DC_FREQ_250kHZ },
	{ 410000, AD5755_DC_DC_FREQ_410kHZ },
	{ 650000, AD5755_DC_DC_FREQ_650kHZ }
};

static const int ad5755_dcdc_maxv_table[][2] = {
	{ 23000000, AD5755_DC_DC_MAXV_23V },
	{ 24500000, AD5755_DC_DC_MAXV_24V5 },
	{ 27000000, AD5755_DC_DC_MAXV_27V },
	{ 29500000, AD5755_DC_DC_MAXV_29V5 },
};

static const int ad5755_slew_rate_table[][2] = {
	{ 64000, AD5755_SLEW_RATE_64k },
	{ 32000, AD5755_SLEW_RATE_32k },
	{ 16000, AD5755_SLEW_RATE_16k },
	{ 8000, AD5755_SLEW_RATE_8k },
	{ 4000, AD5755_SLEW_RATE_4k },
	{ 2000, AD5755_SLEW_RATE_2k },
	{ 1000, AD5755_SLEW_RATE_1k },
	{ 500, AD5755_SLEW_RATE_500 },
	{ 250, AD5755_SLEW_RATE_250 },
	{ 125, AD5755_SLEW_RATE_125 },
	{ 64, AD5755_SLEW_RATE_64 },
	{ 32, AD5755_SLEW_RATE_32 },
	{ 16, AD5755_SLEW_RATE_16 },
	{ 8, AD5755_SLEW_RATE_8 },
	{ 4, AD5755_SLEW_RATE_4 },
	{ 0, AD5755_SLEW_RATE_0_5 },
};

static const int ad5755_slew_step_table[][2] = {
	{ 256, AD5755_SLEW_STEP_SIZE_256 },
	{ 128, AD5755_SLEW_STEP_SIZE_128 },
	{ 64, AD5755_SLEW_STEP_SIZE_64 },
	{ 32, AD5755_SLEW_STEP_SIZE_32 },
	{ 16, AD5755_SLEW_STEP_SIZE_16 },
	{ 4, AD5755_SLEW_STEP_SIZE_4 },
	{ 2, AD5755_SLEW_STEP_SIZE_2 },
	{ 1, AD5755_SLEW_STEP_SIZE_1 },
};
#endif

static int ad5755_write_unlocked(struct iio_dev *indio_dev,
	unsigned int reg, unsigned int val)
{
@@ -556,6 +602,129 @@ static const struct ad5755_platform_data ad5755_default_pdata = {
	},
};

#ifdef CONFIG_OF
static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
{
	struct device_node *np = dev->of_node;
	struct device_node *pp;
	struct ad5755_platform_data *pdata;
	unsigned int tmp;
	unsigned int tmparray[3];
	int devnr, i;

	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
	if (!pdata)
		return NULL;

	pdata->ext_dc_dc_compenstation_resistor =
	    of_property_read_bool(np, "adi,ext-dc-dc-compenstation-resistor");

	if (!of_property_read_u32(np, "adi,dc-dc-phase", &tmp))
		pdata->dc_dc_phase = tmp;
	else
		pdata->dc_dc_phase = AD5755_DC_DC_PHASE_ALL_SAME_EDGE;

	pdata->dc_dc_freq = AD5755_DC_DC_FREQ_410kHZ;
	if (!of_property_read_u32(np, "adi,dc-dc-freq-hz", &tmp)) {
		for (i = 0; i < ARRAY_SIZE(ad5755_dcdc_freq_table); i++) {
			if (tmp == ad5755_dcdc_freq_table[i][0]) {
				pdata->dc_dc_freq = ad5755_dcdc_freq_table[i][1];
				break;
			}
		}

		if (i == ARRAY_SIZE(ad5755_dcdc_freq_table)) {
			dev_err(dev,
				"adi,dc-dc-freq out of range selecting 410kHz");
		}
	}

	pdata->dc_dc_maxv = AD5755_DC_DC_MAXV_23V;
	if (!of_property_read_u32(np, "adi,dc-dc-max-microvolt", &tmp)) {
		for (i = 0; i < ARRAY_SIZE(ad5755_dcdc_maxv_table); i++) {
			if (tmp == ad5755_dcdc_maxv_table[i][0]) {
				pdata->dc_dc_maxv = ad5755_dcdc_maxv_table[i][1];
				break;
			}
		}
		if (i == ARRAY_SIZE(ad5755_dcdc_maxv_table)) {
				dev_err(dev,
					"adi,dc-dc-maxv out of range selecting 23V");
		}
	}

	devnr = 0;
	for_each_child_of_node(np, pp) {
		if (devnr > AD5755_NUM_CHANNELS) {
			dev_err(dev,
				"There is to many channels defined in DT\n");
			goto error_out;
		}

		if (!of_property_read_u32(pp, "adi,mode", &tmp))
			pdata->dac[devnr].mode = tmp;
		else
			pdata->dac[devnr].mode = AD5755_MODE_CURRENT_4mA_20mA;

		pdata->dac[devnr].ext_current_sense_resistor =
		    of_property_read_bool(pp, "adi,ext-current-sense-resistor");

		pdata->dac[devnr].enable_voltage_overrange =
		    of_property_read_bool(pp, "adi,enable-voltage-overrange");

		if (!of_property_read_u32_array(pp, "adi,slew", tmparray, 3)) {
			pdata->dac[devnr].slew.enable = tmparray[0];

			pdata->dac[devnr].slew.rate = AD5755_SLEW_RATE_64k;
			for (i = 0; i < ARRAY_SIZE(ad5755_slew_rate_table); i++) {
				if (tmparray[1] == ad5755_slew_rate_table[i][0]) {
					pdata->dac[devnr].slew.rate =
						ad5755_slew_rate_table[i][1];
					break;
				}
			}
			if (i == ARRAY_SIZE(ad5755_slew_rate_table)) {
				dev_err(dev,
					"channel %d slew rate out of range selecting 64kHz",
					devnr);
			}

			pdata->dac[devnr].slew.step_size = AD5755_SLEW_STEP_SIZE_1;
			for (i = 0; i < ARRAY_SIZE(ad5755_slew_step_table); i++) {
				if (tmparray[2] == ad5755_slew_step_table[i][0]) {
					pdata->dac[devnr].slew.step_size =
						ad5755_slew_step_table[i][1];
					break;
				}
			}
			if (i == ARRAY_SIZE(ad5755_slew_step_table)) {
				dev_err(dev,
					"channel %d slew step size out of range selecting 1 LSB",
					devnr);
			}
		} else {
			pdata->dac[devnr].slew.enable = false;
			pdata->dac[devnr].slew.rate = AD5755_SLEW_RATE_64k;
			pdata->dac[devnr].slew.step_size =
			    AD5755_SLEW_STEP_SIZE_1;
		}
		devnr++;
	}

	return pdata;

 error_out:
	devm_kfree(dev, pdata);
	return NULL;
}
#else
static
struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
{
	return NULL;
}
#endif

static int ad5755_probe(struct spi_device *spi)
{
	enum ad5755_type type = spi_get_device_id(spi)->driver_data;
@@ -583,8 +752,15 @@ static int ad5755_probe(struct spi_device *spi)
	indio_dev->modes = INDIO_DIRECT_MODE;
	indio_dev->num_channels = AD5755_NUM_CHANNELS;

	if (!pdata)
	if (spi->dev.of_node)
		pdata = ad5755_parse_dt(&spi->dev);
	else
		pdata = spi->dev.platform_data;

	if (!pdata) {
		dev_warn(&spi->dev, "no platform data? using default\n");
		pdata = &ad5755_default_pdata;
	}

	ret = ad5755_init_channels(indio_dev, pdata);
	if (ret)
@@ -607,6 +783,16 @@ static const struct spi_device_id ad5755_id[] = {
};
MODULE_DEVICE_TABLE(spi, ad5755_id);

static const struct of_device_id ad5755_of_match[] = {
	{ .compatible = "adi,ad5755" },
	{ .compatible = "adi,ad5755-1" },
	{ .compatible = "adi,ad5757" },
	{ .compatible = "adi,ad5735" },
	{ .compatible = "adi,ad5737" },
	{ }
};
MODULE_DEVICE_TABLE(of, ad5755_of_match);

static struct spi_driver ad5755_driver = {
	.driver = {
		.name = "ad5755",