Skip to content

Commit 17ba036

Browse files
machschmittjic23
authored andcommitted
iio: adc: ad4170-4: Add clock provider support
The AD4170-4 chip can use an externally supplied clock at the XTAL2 pin, or an external crystal connected to the XTAL1 and XTAL2 pins. Alternatively, the AD4170-4 can provide its 16 MHz internal clock at the XTAL2 pin. In addition, the chip has a programmable clock divider that allows dividing the external or internal clock frequency, however, control for that is not provided in this patch. Extend the AD4170-4 driver so it effectively uses the provided external clock, if any, or supplies its own clock as a clock provider. Reviewed-by: Nuno Sá <nuno.sa@analog.com> Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com> Link: https://patch.msgid.link/68697c7613b1a69d752e541caef28d08b3e59bc1.1751895245.git.marcelo.schmitt@analog.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent 1af14a9 commit 17ba036

File tree

2 files changed

+147
-1
lines changed

2 files changed

+147
-1
lines changed

drivers/iio/adc/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ config AD4170_4
9191
select REGMAP_SPI
9292
select IIO_BUFFER
9393
select IIO_TRIGGERED_BUFFER
94+
depends on COMMON_CLK
9495
help
9596
Say yes here to build support for Analog Devices AD4170-4 SPI analog
9697
to digital converters (ADC).

drivers/iio/adc/ad4170-4.c

Lines changed: 146 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include <linux/bitops.h>
1414
#include <linux/bits.h>
1515
#include <linux/cleanup.h>
16+
#include <linux/clk.h>
17+
#include <linux/clk-provider.h>
1618
#include <linux/delay.h>
1719
#include <linux/device.h>
1820
#include <linux/err.h>
@@ -55,6 +57,7 @@
5557
#define AD4170_CONFIG_A_REG 0x00
5658
#define AD4170_DATA_24B_REG 0x1E
5759
#define AD4170_PIN_MUXING_REG 0x69
60+
#define AD4170_CLOCK_CTRL_REG 0x6B
5861
#define AD4170_ADC_CTRL_REG 0x71
5962
#define AD4170_CHAN_EN_REG 0x79
6063
#define AD4170_CHAN_SETUP_REG(x) (0x81 + 4 * (x))
@@ -75,6 +78,9 @@
7578
/* AD4170_PIN_MUXING_REG */
7679
#define AD4170_PIN_MUXING_DIG_AUX1_CTRL_MSK GENMASK(5, 4)
7780

81+
/* AD4170_CLOCK_CTRL_REG */
82+
#define AD4170_CLOCK_CTRL_CLOCKSEL_MSK GENMASK(1, 0)
83+
7884
/* AD4170_ADC_CTRL_REG */
7985
#define AD4170_ADC_CTRL_MULTI_DATA_REG_SEL_MSK BIT(7)
8086
#define AD4170_ADC_CTRL_CONT_READ_MSK GENMASK(5, 4)
@@ -102,6 +108,12 @@
102108

103109
/* AD4170 register constants */
104110

111+
/* AD4170_CLOCK_CTRL_REG constants */
112+
#define AD4170_CLOCK_CTRL_CLOCKSEL_INT 0x0
113+
#define AD4170_CLOCK_CTRL_CLOCKSEL_INT_OUT 0x1
114+
#define AD4170_CLOCK_CTRL_CLOCKSEL_EXT 0x2
115+
#define AD4170_CLOCK_CTRL_CLOCKSEL_EXT_XTAL 0x3
116+
105117
/* AD4170_CHAN_MAP_REG constants */
106118
#define AD4170_CHAN_MAP_AIN(x) (x)
107119
#define AD4170_CHAN_MAP_TEMP_SENSOR 17
@@ -150,6 +162,8 @@
150162

151163
/* Internal and external clock properties */
152164
#define AD4170_INT_CLOCK_16MHZ (16 * HZ_PER_MHZ)
165+
#define AD4170_EXT_CLOCK_MHZ_MIN (1 * HZ_PER_MHZ)
166+
#define AD4170_EXT_CLOCK_MHZ_MAX (17 * HZ_PER_MHZ)
153167

154168
#define AD4170_NUM_PGA_OPTIONS 10
155169

@@ -167,6 +181,7 @@ static const unsigned int ad4170_reg_size[] = {
167181
[AD4170_CONFIG_A_REG] = 1,
168182
[AD4170_DATA_24B_REG] = 3,
169183
[AD4170_PIN_MUXING_REG] = 2,
184+
[AD4170_CLOCK_CTRL_REG] = 2,
170185
[AD4170_ADC_CTRL_REG] = 2,
171186
[AD4170_CHAN_EN_REG] = 2,
172187
/*
@@ -239,6 +254,10 @@ enum ad4170_regulator {
239254
AD4170_MAX_SUP,
240255
};
241256

257+
static const char *const ad4170_clk_sel[] = {
258+
"ext-clk", "xtal",
259+
};
260+
242261
enum ad4170_int_pin_sel {
243262
AD4170_INT_PIN_SDO,
244263
AD4170_INT_PIN_DIG_AUX1,
@@ -343,6 +362,8 @@ struct ad4170_state {
343362
struct spi_message msg;
344363
struct spi_transfer xfer;
345364
struct iio_trigger *trig;
365+
struct clk_hw int_clk_hw;
366+
unsigned int clock_ctrl;
346367
unsigned int pins_fn[AD4170_NUM_ANALOG_PINS];
347368
/*
348369
* DMA (thus cache coherency maintenance) requires the transfer buffers
@@ -1646,14 +1667,138 @@ static int ad4170_parse_channels(struct iio_dev *indio_dev)
16461667
return 0;
16471668
}
16481669

1670+
static struct ad4170_state *clk_hw_to_ad4170(struct clk_hw *hw)
1671+
{
1672+
return container_of(hw, struct ad4170_state, int_clk_hw);
1673+
}
1674+
1675+
static unsigned long ad4170_sel_clk(struct ad4170_state *st,
1676+
unsigned int clk_sel)
1677+
{
1678+
st->clock_ctrl &= ~AD4170_CLOCK_CTRL_CLOCKSEL_MSK;
1679+
st->clock_ctrl |= FIELD_PREP(AD4170_CLOCK_CTRL_CLOCKSEL_MSK, clk_sel);
1680+
return regmap_write(st->regmap, AD4170_CLOCK_CTRL_REG, st->clock_ctrl);
1681+
}
1682+
1683+
static unsigned long ad4170_clk_recalc_rate(struct clk_hw *hw,
1684+
unsigned long parent_rate)
1685+
{
1686+
return AD4170_INT_CLOCK_16MHZ;
1687+
}
1688+
1689+
static int ad4170_clk_output_is_enabled(struct clk_hw *hw)
1690+
{
1691+
struct ad4170_state *st = clk_hw_to_ad4170(hw);
1692+
u32 clk_sel;
1693+
1694+
clk_sel = FIELD_GET(AD4170_CLOCK_CTRL_CLOCKSEL_MSK, st->clock_ctrl);
1695+
return clk_sel == AD4170_CLOCK_CTRL_CLOCKSEL_INT_OUT;
1696+
}
1697+
1698+
static int ad4170_clk_output_prepare(struct clk_hw *hw)
1699+
{
1700+
struct ad4170_state *st = clk_hw_to_ad4170(hw);
1701+
1702+
return ad4170_sel_clk(st, AD4170_CLOCK_CTRL_CLOCKSEL_INT_OUT);
1703+
}
1704+
1705+
static void ad4170_clk_output_unprepare(struct clk_hw *hw)
1706+
{
1707+
struct ad4170_state *st = clk_hw_to_ad4170(hw);
1708+
1709+
ad4170_sel_clk(st, AD4170_CLOCK_CTRL_CLOCKSEL_INT);
1710+
}
1711+
1712+
static const struct clk_ops ad4170_int_clk_ops = {
1713+
.recalc_rate = ad4170_clk_recalc_rate,
1714+
.is_enabled = ad4170_clk_output_is_enabled,
1715+
.prepare = ad4170_clk_output_prepare,
1716+
.unprepare = ad4170_clk_output_unprepare,
1717+
};
1718+
1719+
static int ad4170_register_clk_provider(struct iio_dev *indio_dev)
1720+
{
1721+
struct ad4170_state *st = iio_priv(indio_dev);
1722+
struct device *dev = indio_dev->dev.parent;
1723+
struct clk_init_data init = {};
1724+
int ret;
1725+
1726+
if (device_property_read_string(dev, "clock-output-names", &init.name)) {
1727+
init.name = devm_kasprintf(dev, GFP_KERNEL, "%pfw",
1728+
dev_fwnode(dev));
1729+
if (!init.name)
1730+
return -ENOMEM;
1731+
}
1732+
1733+
init.ops = &ad4170_int_clk_ops;
1734+
1735+
st->int_clk_hw.init = &init;
1736+
ret = devm_clk_hw_register(dev, &st->int_clk_hw);
1737+
if (ret)
1738+
return ret;
1739+
1740+
return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
1741+
&st->int_clk_hw);
1742+
}
1743+
1744+
static int ad4170_clock_select(struct iio_dev *indio_dev)
1745+
{
1746+
struct ad4170_state *st = iio_priv(indio_dev);
1747+
struct device *dev = &st->spi->dev;
1748+
struct clk *ext_clk;
1749+
int ret;
1750+
1751+
ext_clk = devm_clk_get_optional_enabled(dev, NULL);
1752+
if (IS_ERR(ext_clk))
1753+
return dev_err_probe(dev, PTR_ERR(ext_clk),
1754+
"Failed to get external clock\n");
1755+
1756+
if (!ext_clk) {
1757+
/* Use internal clock reference */
1758+
st->mclk_hz = AD4170_INT_CLOCK_16MHZ;
1759+
st->clock_ctrl |= FIELD_PREP(AD4170_CLOCK_CTRL_CLOCKSEL_MSK,
1760+
AD4170_CLOCK_CTRL_CLOCKSEL_INT_OUT);
1761+
1762+
if (!device_property_present(&st->spi->dev, "#clock-cells"))
1763+
return 0;
1764+
1765+
return ad4170_register_clk_provider(indio_dev);
1766+
}
1767+
1768+
/* Read optional clock-names prop to specify the external clock type */
1769+
ret = device_property_match_property_string(dev, "clock-names",
1770+
ad4170_clk_sel,
1771+
ARRAY_SIZE(ad4170_clk_sel));
1772+
1773+
ret = ret < 0 ? 0 : ret; /* Default to external clock if no clock-names */
1774+
st->clock_ctrl |= FIELD_PREP(AD4170_CLOCK_CTRL_CLOCKSEL_MSK,
1775+
AD4170_CLOCK_CTRL_CLOCKSEL_EXT + ret);
1776+
1777+
st->mclk_hz = clk_get_rate(ext_clk);
1778+
if (st->mclk_hz < AD4170_EXT_CLOCK_MHZ_MIN ||
1779+
st->mclk_hz > AD4170_EXT_CLOCK_MHZ_MAX) {
1780+
return dev_err_probe(dev, -EINVAL,
1781+
"Invalid external clock frequency %u\n",
1782+
st->mclk_hz);
1783+
}
1784+
1785+
return 0;
1786+
}
1787+
16491788
static int ad4170_parse_firmware(struct iio_dev *indio_dev)
16501789
{
16511790
struct ad4170_state *st = iio_priv(indio_dev);
16521791
struct device *dev = &st->spi->dev;
16531792
int reg_data, ret;
16541793
u32 int_pin_sel;
16551794

1656-
st->mclk_hz = AD4170_INT_CLOCK_16MHZ;
1795+
ret = ad4170_clock_select(indio_dev);
1796+
if (ret)
1797+
return dev_err_probe(dev, ret, "Failed to setup device clock\n");
1798+
1799+
ret = regmap_write(st->regmap, AD4170_CLOCK_CTRL_REG, st->clock_ctrl);
1800+
if (ret)
1801+
return ret;
16571802

16581803
/* On power on, device defaults to using SDO pin for data ready signal */
16591804
int_pin_sel = AD4170_INT_PIN_SDO;

0 commit comments

Comments
 (0)