Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: adc: ad7124: do not require mclk

Make the "mclk" clock optional in the ad7124 driver. The MCLK is an
internal counter on the ADC, so it is not something that should be
coming from the devicetree. However, existing users may be using this
to essentially select the power mode of the ADC from the devicetree.
In order to not break those users, we have to keep the existing "mclk"
handling, but now it is optional.

Now, when the "mclk" clock is omitted from the devicetree, the driver
will default to the full power mode. Support for an external clock
and dynamic power mode switching can be added later if needed.

Signed-off-by: David Lechner <dlechner@baylibre.com>
Link: https://patch.msgid.link/20250828-iio-adc-ad7124-proper-clock-support-v3-2-0b317b4605e5@baylibre.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

David Lechner and committed by
Jonathan Cameron
aead8e4c a52bdee1

+44 -18
+44 -18
drivers/iio/adc/ad7124.c
··· 174 174 struct ad_sigma_delta sd; 175 175 struct ad7124_channel *channels; 176 176 struct regulator *vref[4]; 177 - struct clk *mclk; 178 177 unsigned int adc_control; 179 178 unsigned int num_channels; 180 179 struct mutex cfgs_lock; /* lock for configs access */ ··· 253 254 { 254 255 unsigned int fclk, odr_sel_bits; 255 256 256 - fclk = clk_get_rate(st->mclk); 257 + fclk = ad7124_master_clk_freq_hz[FIELD_GET(AD7124_ADC_CONTROL_POWER_MODE, 258 + st->adc_control)]; 259 + 257 260 /* 258 261 * FS[10:0] = fCLK / (fADC x 32) where: 259 262 * fADC is the output data rate ··· 1112 1111 static int ad7124_setup(struct ad7124_state *st) 1113 1112 { 1114 1113 struct device *dev = &st->sd.spi->dev; 1115 - unsigned int fclk, power_mode; 1114 + unsigned int power_mode; 1115 + struct clk *mclk; 1116 1116 int i, ret; 1117 1117 1118 - fclk = clk_get_rate(st->mclk); 1119 - if (!fclk) 1120 - return dev_err_probe(dev, -EINVAL, "Failed to get mclk rate\n"); 1118 + /* 1119 + * Always use full power mode for max performance. If needed, the driver 1120 + * could be adapted to use a dynamic power mode based on the requested 1121 + * output data rate. 1122 + */ 1123 + power_mode = AD7124_ADC_CONTROL_POWER_MODE_FULL; 1121 1124 1122 - /* The power mode changes the master clock frequency */ 1123 - power_mode = ad7124_find_closest_match(ad7124_master_clk_freq_hz, 1124 - ARRAY_SIZE(ad7124_master_clk_freq_hz), 1125 - fclk); 1126 - if (fclk != ad7124_master_clk_freq_hz[power_mode]) { 1127 - ret = clk_set_rate(st->mclk, fclk); 1128 - if (ret) 1129 - return dev_err_probe(dev, ret, "Failed to set mclk rate\n"); 1125 + /* 1126 + * This "mclk" business is needed for backwards compatibility with old 1127 + * devicetrees that specified a fake clock named "mclk" to select the 1128 + * power mode. 1129 + */ 1130 + mclk = devm_clk_get_optional_enabled(dev, "mclk"); 1131 + if (IS_ERR(mclk)) 1132 + return dev_err_probe(dev, PTR_ERR(mclk), "Failed to get mclk\n"); 1133 + 1134 + if (mclk) { 1135 + unsigned long mclk_hz; 1136 + 1137 + mclk_hz = clk_get_rate(mclk); 1138 + if (!mclk_hz) 1139 + return dev_err_probe(dev, -EINVAL, 1140 + "Failed to get mclk rate\n"); 1141 + 1142 + /* 1143 + * This logic is a bit backwards, which is why it is only here 1144 + * for backwards compatibility. The driver should be able to set 1145 + * the power mode as it sees fit and the f_clk/mclk rate should 1146 + * be dynamic accordingly. But here, we are selecting a fixed 1147 + * power mode based on the given "mclk" rate. 1148 + */ 1149 + power_mode = ad7124_find_closest_match(ad7124_master_clk_freq_hz, 1150 + ARRAY_SIZE(ad7124_master_clk_freq_hz), mclk_hz); 1151 + 1152 + if (mclk_hz != ad7124_master_clk_freq_hz[power_mode]) { 1153 + ret = clk_set_rate(mclk, mclk_hz); 1154 + if (ret) 1155 + return dev_err_probe(dev, ret, 1156 + "Failed to set mclk rate\n"); 1157 + } 1130 1158 } 1131 1159 1132 1160 /* Set the power mode */ ··· 1332 1302 if (ret) 1333 1303 return ret; 1334 1304 } 1335 - 1336 - st->mclk = devm_clk_get_enabled(&spi->dev, "mclk"); 1337 - if (IS_ERR(st->mclk)) 1338 - return dev_err_probe(dev, PTR_ERR(st->mclk), "Failed to get mclk\n"); 1339 1305 1340 1306 ret = ad7124_soft_reset(st); 1341 1307 if (ret < 0)