Skip to content

Commit 67c2c12

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/3373d02579fb3f2c45f845984b2cf9b979221fb8.1751289747.git.marcelo.schmitt@analog.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent 5cbe083 commit 67c2c12

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
@@ -149,6 +161,8 @@
149161

150162
/* Internal and external clock properties */
151163
#define AD4170_INT_CLOCK_16MHZ (16 * HZ_PER_MHZ)
164+
#define AD4170_EXT_CLOCK_MHZ_MIN (1 * HZ_PER_MHZ)
165+
#define AD4170_EXT_CLOCK_MHZ_MAX (17 * HZ_PER_MHZ)
152166

153167
#define AD4170_NUM_PGA_OPTIONS 10
154168

@@ -166,6 +180,7 @@ static const unsigned int ad4170_reg_size[] = {
166180
[AD4170_CONFIG_A_REG] = 1,
167181
[AD4170_DATA_24B_REG] = 3,
168182
[AD4170_PIN_MUXING_REG] = 2,
183+
[AD4170_CLOCK_CTRL_REG] = 2,
169184
[AD4170_ADC_CTRL_REG] = 2,
170185
[AD4170_CHAN_EN_REG] = 2,
171186
/*
@@ -238,6 +253,10 @@ enum ad4170_regulator {
238253
AD4170_MAX_SUP,
239254
};
240255

256+
static const char *const ad4170_clk_sel[] = {
257+
"ext-clk", "xtal",
258+
};
259+
241260
enum ad4170_int_pin_sel {
242261
AD4170_INT_PIN_SDO,
243262
AD4170_INT_PIN_DIG_AUX1,
@@ -340,6 +359,8 @@ struct ad4170_state {
340359
struct completion completion;
341360
unsigned int pins_fn[AD4170_NUM_ANALOG_PINS];
342361
u32 int_pin_sel;
362+
struct clk_hw int_clk_hw;
363+
unsigned int clock_ctrl;
343364
/*
344365
* DMA (thus cache coherency maintenance) requires the transfer buffers
345366
* to live in their own cache lines.
@@ -1623,13 +1644,137 @@ static int ad4170_parse_channels(struct iio_dev *indio_dev)
16231644
return 0;
16241645
}
16251646

1647+
static struct ad4170_state *clk_hw_to_ad4170(struct clk_hw *hw)
1648+
{
1649+
return container_of(hw, struct ad4170_state, int_clk_hw);
1650+
}
1651+
1652+
static unsigned long ad4170_sel_clk(struct ad4170_state *st,
1653+
unsigned int clk_sel)
1654+
{
1655+
st->clock_ctrl &= ~AD4170_CLOCK_CTRL_CLOCKSEL_MSK;
1656+
st->clock_ctrl |= FIELD_PREP(AD4170_CLOCK_CTRL_CLOCKSEL_MSK, clk_sel);
1657+
return regmap_write(st->regmap, AD4170_CLOCK_CTRL_REG, st->clock_ctrl);
1658+
}
1659+
1660+
static unsigned long ad4170_clk_recalc_rate(struct clk_hw *hw,
1661+
unsigned long parent_rate)
1662+
{
1663+
return AD4170_INT_CLOCK_16MHZ;
1664+
}
1665+
1666+
static int ad4170_clk_output_is_enabled(struct clk_hw *hw)
1667+
{
1668+
struct ad4170_state *st = clk_hw_to_ad4170(hw);
1669+
u32 clk_sel;
1670+
1671+
clk_sel = FIELD_GET(AD4170_CLOCK_CTRL_CLOCKSEL_MSK, st->clock_ctrl);
1672+
return clk_sel == AD4170_CLOCK_CTRL_CLOCKSEL_INT_OUT;
1673+
}
1674+
1675+
static int ad4170_clk_output_prepare(struct clk_hw *hw)
1676+
{
1677+
struct ad4170_state *st = clk_hw_to_ad4170(hw);
1678+
1679+
return ad4170_sel_clk(st, AD4170_CLOCK_CTRL_CLOCKSEL_INT_OUT);
1680+
}
1681+
1682+
static void ad4170_clk_output_unprepare(struct clk_hw *hw)
1683+
{
1684+
struct ad4170_state *st = clk_hw_to_ad4170(hw);
1685+
1686+
ad4170_sel_clk(st, AD4170_CLOCK_CTRL_CLOCKSEL_INT);
1687+
}
1688+
1689+
static const struct clk_ops ad4170_int_clk_ops = {
1690+
.recalc_rate = ad4170_clk_recalc_rate,
1691+
.is_enabled = ad4170_clk_output_is_enabled,
1692+
.prepare = ad4170_clk_output_prepare,
1693+
.unprepare = ad4170_clk_output_unprepare,
1694+
};
1695+
1696+
static int ad4170_register_clk_provider(struct iio_dev *indio_dev)
1697+
{
1698+
struct ad4170_state *st = iio_priv(indio_dev);
1699+
struct device *dev = indio_dev->dev.parent;
1700+
struct clk_init_data init = {};
1701+
int ret;
1702+
1703+
if (device_property_read_string(dev, "clock-output-names", &init.name)) {
1704+
init.name = devm_kasprintf(dev, GFP_KERNEL, "%pfw",
1705+
dev_fwnode(dev));
1706+
if (!init.name)
1707+
return -ENOMEM;
1708+
}
1709+
1710+
init.ops = &ad4170_int_clk_ops;
1711+
1712+
st->int_clk_hw.init = &init;
1713+
ret = devm_clk_hw_register(dev, &st->int_clk_hw);
1714+
if (ret)
1715+
return ret;
1716+
1717+
return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
1718+
&st->int_clk_hw);
1719+
}
1720+
1721+
static int ad4170_clock_select(struct iio_dev *indio_dev)
1722+
{
1723+
struct ad4170_state *st = iio_priv(indio_dev);
1724+
struct device *dev = &st->spi->dev;
1725+
struct clk *ext_clk;
1726+
int ret;
1727+
1728+
ext_clk = devm_clk_get_optional_enabled(dev, NULL);
1729+
if (IS_ERR(ext_clk))
1730+
return dev_err_probe(dev, PTR_ERR(ext_clk),
1731+
"Failed to get external clock\n");
1732+
1733+
if (!ext_clk) {
1734+
/* Use internal clock reference */
1735+
st->mclk_hz = AD4170_INT_CLOCK_16MHZ;
1736+
st->clock_ctrl |= FIELD_PREP(AD4170_CLOCK_CTRL_CLOCKSEL_MSK,
1737+
AD4170_CLOCK_CTRL_CLOCKSEL_INT_OUT);
1738+
1739+
if (!device_property_present(&st->spi->dev, "#clock-cells"))
1740+
return 0;
1741+
1742+
return ad4170_register_clk_provider(indio_dev);
1743+
}
1744+
1745+
/* Read optional clock-names prop to specify the external clock type */
1746+
ret = device_property_match_property_string(dev, "clock-names",
1747+
ad4170_clk_sel,
1748+
ARRAY_SIZE(ad4170_clk_sel));
1749+
1750+
ret = ret < 0 ? 0 : ret; /* Default to external clock if no clock-names */
1751+
st->clock_ctrl |= FIELD_PREP(AD4170_CLOCK_CTRL_CLOCKSEL_MSK,
1752+
AD4170_CLOCK_CTRL_CLOCKSEL_EXT + ret);
1753+
1754+
st->mclk_hz = clk_get_rate(ext_clk);
1755+
if (st->mclk_hz < AD4170_EXT_CLOCK_MHZ_MIN ||
1756+
st->mclk_hz > AD4170_EXT_CLOCK_MHZ_MAX) {
1757+
return dev_err_probe(dev, -EINVAL,
1758+
"Invalid external clock frequency %u\n",
1759+
st->mclk_hz);
1760+
}
1761+
1762+
return 0;
1763+
}
1764+
16261765
static int ad4170_parse_firmware(struct iio_dev *indio_dev)
16271766
{
16281767
struct ad4170_state *st = iio_priv(indio_dev);
16291768
struct device *dev = &st->spi->dev;
16301769
int reg_data, ret;
16311770

1632-
st->mclk_hz = AD4170_INT_CLOCK_16MHZ;
1771+
ret = ad4170_clock_select(indio_dev);
1772+
if (ret)
1773+
return dev_err_probe(dev, ret, "Failed to setup device clock\n");
1774+
1775+
ret = regmap_write(st->regmap, AD4170_CLOCK_CTRL_REG, st->clock_ctrl);
1776+
if (ret)
1777+
return ret;
16331778

16341779
/* On power on, device defaults to using SDO pin for data ready signal */
16351780
st->int_pin_sel = AD4170_INT_PIN_SDO;

0 commit comments

Comments
 (0)