]>
Commit | Line | Data |
---|---|---|
3adbf342 MB |
1 | /* |
2 | * Amlogic Meson Successive Approximation Register (SAR) A/D Converter | |
3 | * | |
4 | * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 as | |
8 | * published by the Free Software Foundation. | |
9 | * | |
10 | * You should have received a copy of the GNU General Public License | |
11 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
12 | */ | |
13 | ||
14 | #include <linux/bitfield.h> | |
15 | #include <linux/clk.h> | |
16 | #include <linux/clk-provider.h> | |
17 | #include <linux/delay.h> | |
18 | #include <linux/io.h> | |
19 | #include <linux/iio/iio.h> | |
20 | #include <linux/module.h> | |
3af10913 | 21 | #include <linux/interrupt.h> |
3adbf342 | 22 | #include <linux/of.h> |
3af10913 | 23 | #include <linux/of_irq.h> |
3adbf342 MB |
24 | #include <linux/of_device.h> |
25 | #include <linux/platform_device.h> | |
26 | #include <linux/regmap.h> | |
27 | #include <linux/regulator/consumer.h> | |
28 | ||
29 | #define MESON_SAR_ADC_REG0 0x00 | |
30 | #define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31) | |
31 | #define MESON_SAR_ADC_REG0_BUSY_MASK GENMASK(30, 28) | |
32 | #define MESON_SAR_ADC_REG0_DELTA_BUSY BIT(30) | |
33 | #define MESON_SAR_ADC_REG0_AVG_BUSY BIT(29) | |
34 | #define MESON_SAR_ADC_REG0_SAMPLE_BUSY BIT(28) | |
35 | #define MESON_SAR_ADC_REG0_FIFO_FULL BIT(27) | |
36 | #define MESON_SAR_ADC_REG0_FIFO_EMPTY BIT(26) | |
37 | #define MESON_SAR_ADC_REG0_FIFO_COUNT_MASK GENMASK(25, 21) | |
38 | #define MESON_SAR_ADC_REG0_ADC_BIAS_CTRL_MASK GENMASK(20, 19) | |
39 | #define MESON_SAR_ADC_REG0_CURR_CHAN_ID_MASK GENMASK(18, 16) | |
40 | #define MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL BIT(15) | |
41 | #define MESON_SAR_ADC_REG0_SAMPLING_STOP BIT(14) | |
42 | #define MESON_SAR_ADC_REG0_CHAN_DELTA_EN_MASK GENMASK(13, 12) | |
43 | #define MESON_SAR_ADC_REG0_DETECT_IRQ_POL BIT(10) | |
44 | #define MESON_SAR_ADC_REG0_DETECT_IRQ_EN BIT(9) | |
45 | #define MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK GENMASK(8, 4) | |
46 | #define MESON_SAR_ADC_REG0_FIFO_IRQ_EN BIT(3) | |
47 | #define MESON_SAR_ADC_REG0_SAMPLING_START BIT(2) | |
48 | #define MESON_SAR_ADC_REG0_CONTINUOUS_EN BIT(1) | |
49 | #define MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE BIT(0) | |
50 | ||
51 | #define MESON_SAR_ADC_CHAN_LIST 0x04 | |
52 | #define MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK GENMASK(26, 24) | |
53 | #define MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(_chan) \ | |
54 | (GENMASK(2, 0) << ((_chan) * 3)) | |
55 | ||
56 | #define MESON_SAR_ADC_AVG_CNTL 0x08 | |
57 | #define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(_chan) \ | |
58 | (16 + ((_chan) * 2)) | |
59 | #define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(_chan) \ | |
60 | (GENMASK(17, 16) << ((_chan) * 2)) | |
61 | #define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(_chan) \ | |
62 | (0 + ((_chan) * 2)) | |
63 | #define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(_chan) \ | |
64 | (GENMASK(1, 0) << ((_chan) * 2)) | |
65 | ||
66 | #define MESON_SAR_ADC_REG3 0x0c | |
67 | #define MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY BIT(31) | |
68 | #define MESON_SAR_ADC_REG3_CLK_EN BIT(30) | |
69 | #define MESON_SAR_ADC_REG3_BL30_INITIALIZED BIT(28) | |
70 | #define MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN BIT(27) | |
71 | #define MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE BIT(26) | |
72 | #define MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK GENMASK(25, 23) | |
73 | #define MESON_SAR_ADC_REG3_DETECT_EN BIT(22) | |
74 | #define MESON_SAR_ADC_REG3_ADC_EN BIT(21) | |
75 | #define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK GENMASK(20, 18) | |
76 | #define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK GENMASK(17, 16) | |
77 | #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT 10 | |
78 | #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 5 | |
79 | #define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK GENMASK(9, 8) | |
80 | #define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK GENMASK(7, 0) | |
81 | ||
82 | #define MESON_SAR_ADC_DELAY 0x10 | |
83 | #define MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK GENMASK(25, 24) | |
84 | #define MESON_SAR_ADC_DELAY_BL30_BUSY BIT(15) | |
85 | #define MESON_SAR_ADC_DELAY_KERNEL_BUSY BIT(14) | |
86 | #define MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK GENMASK(23, 16) | |
87 | #define MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK GENMASK(9, 8) | |
88 | #define MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK GENMASK(7, 0) | |
89 | ||
90 | #define MESON_SAR_ADC_LAST_RD 0x14 | |
91 | #define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL1_MASK GENMASK(23, 16) | |
92 | #define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL0_MASK GENMASK(9, 0) | |
93 | ||
94 | #define MESON_SAR_ADC_FIFO_RD 0x18 | |
95 | #define MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK GENMASK(14, 12) | |
96 | #define MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK GENMASK(11, 0) | |
97 | ||
98 | #define MESON_SAR_ADC_AUX_SW 0x1c | |
ab569a4c MB |
99 | #define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(_chan) \ |
100 | (8 + (((_chan) - 2) * 3)) | |
3adbf342 MB |
101 | #define MESON_SAR_ADC_AUX_SW_VREF_P_MUX BIT(6) |
102 | #define MESON_SAR_ADC_AUX_SW_VREF_N_MUX BIT(5) | |
103 | #define MESON_SAR_ADC_AUX_SW_MODE_SEL BIT(4) | |
104 | #define MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW BIT(3) | |
105 | #define MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW BIT(2) | |
106 | #define MESON_SAR_ADC_AUX_SW_YM_DRIVE_SW BIT(1) | |
107 | #define MESON_SAR_ADC_AUX_SW_XM_DRIVE_SW BIT(0) | |
108 | ||
109 | #define MESON_SAR_ADC_CHAN_10_SW 0x20 | |
110 | #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK GENMASK(25, 23) | |
111 | #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_P_MUX BIT(22) | |
112 | #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_N_MUX BIT(21) | |
113 | #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MODE_SEL BIT(20) | |
114 | #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW BIT(19) | |
115 | #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW BIT(18) | |
116 | #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YM_DRIVE_SW BIT(17) | |
117 | #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XM_DRIVE_SW BIT(16) | |
118 | #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK GENMASK(9, 7) | |
119 | #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_P_MUX BIT(6) | |
120 | #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_N_MUX BIT(5) | |
121 | #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MODE_SEL BIT(4) | |
122 | #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW BIT(3) | |
123 | #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW BIT(2) | |
124 | #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YM_DRIVE_SW BIT(1) | |
125 | #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XM_DRIVE_SW BIT(0) | |
126 | ||
127 | #define MESON_SAR_ADC_DETECT_IDLE_SW 0x24 | |
128 | #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_SW_EN BIT(26) | |
129 | #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK GENMASK(25, 23) | |
130 | #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_P_MUX BIT(22) | |
131 | #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_N_MUX BIT(21) | |
132 | #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_SEL BIT(20) | |
133 | #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YP_DRIVE_SW BIT(19) | |
134 | #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XP_DRIVE_SW BIT(18) | |
135 | #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YM_DRIVE_SW BIT(17) | |
136 | #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XM_DRIVE_SW BIT(16) | |
137 | #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK GENMASK(9, 7) | |
138 | #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_P_MUX BIT(6) | |
139 | #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_N_MUX BIT(5) | |
140 | #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_SEL BIT(4) | |
141 | #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YP_DRIVE_SW BIT(3) | |
142 | #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XP_DRIVE_SW BIT(2) | |
143 | #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YM_DRIVE_SW BIT(1) | |
144 | #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XM_DRIVE_SW BIT(0) | |
145 | ||
146 | #define MESON_SAR_ADC_DELTA_10 0x28 | |
147 | #define MESON_SAR_ADC_DELTA_10_TEMP_SEL BIT(27) | |
148 | #define MESON_SAR_ADC_DELTA_10_TS_REVE1 BIT(26) | |
149 | #define MESON_SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_MASK GENMASK(25, 16) | |
150 | #define MESON_SAR_ADC_DELTA_10_TS_REVE0 BIT(15) | |
151 | #define MESON_SAR_ADC_DELTA_10_TS_C_SHIFT 11 | |
152 | #define MESON_SAR_ADC_DELTA_10_TS_C_MASK GENMASK(14, 11) | |
153 | #define MESON_SAR_ADC_DELTA_10_TS_VBG_EN BIT(10) | |
154 | #define MESON_SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_MASK GENMASK(9, 0) | |
155 | ||
156 | /* | |
157 | * NOTE: registers from here are undocumented (the vendor Linux kernel driver | |
158 | * and u-boot source served as reference). These only seem to be relevant on | |
159 | * GXBB and newer. | |
160 | */ | |
161 | #define MESON_SAR_ADC_REG11 0x2c | |
162 | #define MESON_SAR_ADC_REG11_BANDGAP_EN BIT(13) | |
163 | ||
164 | #define MESON_SAR_ADC_REG13 0x34 | |
165 | #define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK GENMASK(13, 8) | |
166 | ||
167 | #define MESON_SAR_ADC_MAX_FIFO_SIZE 32 | |
3af10913 | 168 | #define MESON_SAR_ADC_TIMEOUT 100 /* ms */ |
48ba7c3c HK |
169 | /* for use with IIO_VAL_INT_PLUS_MICRO */ |
170 | #define MILLION 1000000 | |
3adbf342 MB |
171 | |
172 | #define MESON_SAR_ADC_CHAN(_chan) { \ | |
173 | .type = IIO_VOLTAGE, \ | |
174 | .indexed = 1, \ | |
175 | .channel = _chan, \ | |
176 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | |
177 | BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ | |
48ba7c3c HK |
178 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ |
179 | BIT(IIO_CHAN_INFO_CALIBBIAS) | \ | |
180 | BIT(IIO_CHAN_INFO_CALIBSCALE), \ | |
3adbf342 MB |
181 | .datasheet_name = "SAR_ADC_CH"#_chan, \ |
182 | } | |
183 | ||
184 | /* | |
185 | * TODO: the hardware supports IIO_TEMP for channel 6 as well which is | |
186 | * currently not supported by this driver. | |
187 | */ | |
188 | static const struct iio_chan_spec meson_sar_adc_iio_channels[] = { | |
189 | MESON_SAR_ADC_CHAN(0), | |
190 | MESON_SAR_ADC_CHAN(1), | |
191 | MESON_SAR_ADC_CHAN(2), | |
192 | MESON_SAR_ADC_CHAN(3), | |
193 | MESON_SAR_ADC_CHAN(4), | |
194 | MESON_SAR_ADC_CHAN(5), | |
195 | MESON_SAR_ADC_CHAN(6), | |
196 | MESON_SAR_ADC_CHAN(7), | |
197 | IIO_CHAN_SOFT_TIMESTAMP(8), | |
198 | }; | |
199 | ||
200 | enum meson_sar_adc_avg_mode { | |
201 | NO_AVERAGING = 0x0, | |
202 | MEAN_AVERAGING = 0x1, | |
203 | MEDIAN_AVERAGING = 0x2, | |
204 | }; | |
205 | ||
206 | enum meson_sar_adc_num_samples { | |
207 | ONE_SAMPLE = 0x0, | |
208 | TWO_SAMPLES = 0x1, | |
209 | FOUR_SAMPLES = 0x2, | |
210 | EIGHT_SAMPLES = 0x3, | |
211 | }; | |
212 | ||
213 | enum meson_sar_adc_chan7_mux_sel { | |
214 | CHAN7_MUX_VSS = 0x0, | |
215 | CHAN7_MUX_VDD_DIV4 = 0x1, | |
216 | CHAN7_MUX_VDD_DIV2 = 0x2, | |
217 | CHAN7_MUX_VDD_MUL3_DIV4 = 0x3, | |
218 | CHAN7_MUX_VDD = 0x4, | |
219 | CHAN7_MUX_CH7_INPUT = 0x7, | |
220 | }; | |
221 | ||
053ffe3c | 222 | struct meson_sar_adc_param { |
6c76ed31 | 223 | bool has_bl30_integration; |
fda29dba | 224 | unsigned long clock_rate; |
d85eed9f | 225 | u32 bandgap_reg; |
3adbf342 | 226 | unsigned int resolution; |
96748823 | 227 | const struct regmap_config *regmap_config; |
3adbf342 MB |
228 | }; |
229 | ||
053ffe3c YL |
230 | struct meson_sar_adc_data { |
231 | const struct meson_sar_adc_param *param; | |
232 | const char *name; | |
233 | }; | |
234 | ||
3adbf342 MB |
235 | struct meson_sar_adc_priv { |
236 | struct regmap *regmap; | |
237 | struct regulator *vref; | |
238 | const struct meson_sar_adc_data *data; | |
239 | struct clk *clkin; | |
240 | struct clk *core_clk; | |
3adbf342 MB |
241 | struct clk *adc_sel_clk; |
242 | struct clk *adc_clk; | |
243 | struct clk_gate clk_gate; | |
244 | struct clk *adc_div_clk; | |
245 | struct clk_divider clk_div; | |
3af10913 | 246 | struct completion done; |
48ba7c3c HK |
247 | int calibbias; |
248 | int calibscale; | |
3adbf342 MB |
249 | }; |
250 | ||
96748823 | 251 | static const struct regmap_config meson_sar_adc_regmap_config_gxbb = { |
3adbf342 MB |
252 | .reg_bits = 8, |
253 | .val_bits = 32, | |
254 | .reg_stride = 4, | |
255 | .max_register = MESON_SAR_ADC_REG13, | |
256 | }; | |
257 | ||
96748823 MB |
258 | static const struct regmap_config meson_sar_adc_regmap_config_meson8 = { |
259 | .reg_bits = 8, | |
260 | .val_bits = 32, | |
261 | .reg_stride = 4, | |
262 | .max_register = MESON_SAR_ADC_DELTA_10, | |
263 | }; | |
264 | ||
3adbf342 MB |
265 | static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev) |
266 | { | |
267 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
268 | u32 regval; | |
269 | ||
270 | regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val); | |
271 | ||
272 | return FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval); | |
273 | } | |
274 | ||
48ba7c3c HK |
275 | static int meson_sar_adc_calib_val(struct iio_dev *indio_dev, int val) |
276 | { | |
277 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
278 | int tmp; | |
279 | ||
280 | /* use val_calib = scale * val_raw + offset calibration function */ | |
281 | tmp = div_s64((s64)val * priv->calibscale, MILLION) + priv->calibbias; | |
282 | ||
053ffe3c | 283 | return clamp(tmp, 0, (1 << priv->data->param->resolution) - 1); |
48ba7c3c HK |
284 | } |
285 | ||
3adbf342 MB |
286 | static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev) |
287 | { | |
288 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
289 | int regval, timeout = 10000; | |
290 | ||
291 | /* | |
292 | * NOTE: we need a small delay before reading the status, otherwise | |
293 | * the sample engine may not have started internally (which would | |
294 | * seem to us that sampling is already finished). | |
295 | */ | |
296 | do { | |
297 | udelay(1); | |
298 | regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val); | |
299 | } while (FIELD_GET(MESON_SAR_ADC_REG0_BUSY_MASK, regval) && timeout--); | |
300 | ||
301 | if (timeout < 0) | |
302 | return -ETIMEDOUT; | |
303 | ||
304 | return 0; | |
305 | } | |
306 | ||
307 | static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev, | |
308 | const struct iio_chan_spec *chan, | |
309 | int *val) | |
310 | { | |
311 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
6a882a2c | 312 | int regval, fifo_chan, fifo_val, count; |
3adbf342 | 313 | |
3af10913 HK |
314 | if(!wait_for_completion_timeout(&priv->done, |
315 | msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT))) | |
316 | return -ETIMEDOUT; | |
3adbf342 | 317 | |
6a882a2c HK |
318 | count = meson_sar_adc_get_fifo_count(indio_dev); |
319 | if (count != 1) { | |
320 | dev_err(&indio_dev->dev, | |
321 | "ADC FIFO has %d element(s) instead of one\n", count); | |
322 | return -EINVAL; | |
3adbf342 MB |
323 | } |
324 | ||
6a882a2c HK |
325 | regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, ®val); |
326 | fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval); | |
327 | if (fifo_chan != chan->channel) { | |
328 | dev_err(&indio_dev->dev, | |
329 | "ADC FIFO entry belongs to channel %d instead of %d\n", | |
330 | fifo_chan, chan->channel); | |
331 | return -EINVAL; | |
332 | } | |
3adbf342 | 333 | |
6a882a2c | 334 | fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval); |
053ffe3c | 335 | fifo_val &= GENMASK(priv->data->param->resolution - 1, 0); |
48ba7c3c | 336 | *val = meson_sar_adc_calib_val(indio_dev, fifo_val); |
3adbf342 MB |
337 | |
338 | return 0; | |
339 | } | |
340 | ||
341 | static void meson_sar_adc_set_averaging(struct iio_dev *indio_dev, | |
342 | const struct iio_chan_spec *chan, | |
343 | enum meson_sar_adc_avg_mode mode, | |
344 | enum meson_sar_adc_num_samples samples) | |
345 | { | |
346 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
347 | int val, channel = chan->channel; | |
348 | ||
349 | val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(channel); | |
350 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, | |
351 | MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(channel), | |
352 | val); | |
353 | ||
354 | val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(channel); | |
355 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, | |
356 | MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(channel), val); | |
357 | } | |
358 | ||
359 | static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev, | |
360 | const struct iio_chan_spec *chan) | |
361 | { | |
362 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
363 | u32 regval; | |
364 | ||
365 | /* | |
366 | * the SAR ADC engine allows sampling multiple channels at the same | |
367 | * time. to keep it simple we're only working with one *internal* | |
368 | * channel, which starts counting at index 0 (which means: count = 1). | |
369 | */ | |
370 | regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, 0); | |
371 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, | |
372 | MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, regval); | |
373 | ||
374 | /* map channel index 0 to the channel which we want to read */ | |
375 | regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), | |
376 | chan->channel); | |
377 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, | |
378 | MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), regval); | |
379 | ||
380 | regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, | |
381 | chan->channel); | |
382 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, | |
383 | MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, | |
384 | regval); | |
385 | ||
386 | regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, | |
387 | chan->channel); | |
388 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, | |
389 | MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, | |
390 | regval); | |
391 | ||
392 | if (chan->channel == 6) | |
393 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, | |
394 | MESON_SAR_ADC_DELTA_10_TEMP_SEL, 0); | |
395 | } | |
396 | ||
397 | static void meson_sar_adc_set_chan7_mux(struct iio_dev *indio_dev, | |
398 | enum meson_sar_adc_chan7_mux_sel sel) | |
399 | { | |
400 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
401 | u32 regval; | |
402 | ||
403 | regval = FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, sel); | |
404 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, | |
405 | MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, regval); | |
406 | ||
407 | usleep_range(10, 20); | |
408 | } | |
409 | ||
410 | static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev) | |
411 | { | |
412 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
413 | ||
3af10913 HK |
414 | reinit_completion(&priv->done); |
415 | ||
416 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, | |
417 | MESON_SAR_ADC_REG0_FIFO_IRQ_EN, | |
418 | MESON_SAR_ADC_REG0_FIFO_IRQ_EN); | |
419 | ||
3adbf342 MB |
420 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, |
421 | MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, | |
422 | MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE); | |
423 | ||
424 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, | |
425 | MESON_SAR_ADC_REG0_SAMPLING_START, | |
426 | MESON_SAR_ADC_REG0_SAMPLING_START); | |
427 | } | |
428 | ||
429 | static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev) | |
430 | { | |
431 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
432 | ||
3af10913 HK |
433 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, |
434 | MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0); | |
435 | ||
3adbf342 MB |
436 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, |
437 | MESON_SAR_ADC_REG0_SAMPLING_STOP, | |
438 | MESON_SAR_ADC_REG0_SAMPLING_STOP); | |
439 | ||
440 | /* wait until all modules are stopped */ | |
441 | meson_sar_adc_wait_busy_clear(indio_dev); | |
442 | ||
443 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, | |
444 | MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 0); | |
445 | } | |
446 | ||
447 | static int meson_sar_adc_lock(struct iio_dev *indio_dev) | |
448 | { | |
449 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
450 | int val, timeout = 10000; | |
451 | ||
452 | mutex_lock(&indio_dev->mlock); | |
453 | ||
053ffe3c | 454 | if (priv->data->param->has_bl30_integration) { |
6c76ed31 MB |
455 | /* prevent BL30 from using the SAR ADC while we are using it */ |
456 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, | |
457 | MESON_SAR_ADC_DELAY_KERNEL_BUSY, | |
458 | MESON_SAR_ADC_DELAY_KERNEL_BUSY); | |
459 | ||
460 | /* | |
461 | * wait until BL30 releases it's lock (so we can use the SAR | |
462 | * ADC) | |
463 | */ | |
464 | do { | |
465 | udelay(1); | |
466 | regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val); | |
467 | } while (val & MESON_SAR_ADC_DELAY_BL30_BUSY && timeout--); | |
468 | ||
3c3e4b3a DC |
469 | if (timeout < 0) { |
470 | mutex_unlock(&indio_dev->mlock); | |
6c76ed31 | 471 | return -ETIMEDOUT; |
3c3e4b3a | 472 | } |
6c76ed31 | 473 | } |
3adbf342 MB |
474 | |
475 | return 0; | |
476 | } | |
477 | ||
478 | static void meson_sar_adc_unlock(struct iio_dev *indio_dev) | |
479 | { | |
480 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
481 | ||
053ffe3c | 482 | if (priv->data->param->has_bl30_integration) |
6c76ed31 MB |
483 | /* allow BL30 to use the SAR ADC again */ |
484 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, | |
485 | MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); | |
3adbf342 MB |
486 | |
487 | mutex_unlock(&indio_dev->mlock); | |
488 | } | |
489 | ||
490 | static void meson_sar_adc_clear_fifo(struct iio_dev *indio_dev) | |
491 | { | |
492 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
103a07d4 | 493 | unsigned int count, tmp; |
3adbf342 MB |
494 | |
495 | for (count = 0; count < MESON_SAR_ADC_MAX_FIFO_SIZE; count++) { | |
496 | if (!meson_sar_adc_get_fifo_count(indio_dev)) | |
497 | break; | |
498 | ||
103a07d4 | 499 | regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &tmp); |
3adbf342 MB |
500 | } |
501 | } | |
502 | ||
503 | static int meson_sar_adc_get_sample(struct iio_dev *indio_dev, | |
504 | const struct iio_chan_spec *chan, | |
505 | enum meson_sar_adc_avg_mode avg_mode, | |
506 | enum meson_sar_adc_num_samples avg_samples, | |
507 | int *val) | |
508 | { | |
509 | int ret; | |
510 | ||
511 | ret = meson_sar_adc_lock(indio_dev); | |
512 | if (ret) | |
513 | return ret; | |
514 | ||
515 | /* clear the FIFO to make sure we're not reading old values */ | |
516 | meson_sar_adc_clear_fifo(indio_dev); | |
517 | ||
518 | meson_sar_adc_set_averaging(indio_dev, chan, avg_mode, avg_samples); | |
519 | ||
520 | meson_sar_adc_enable_channel(indio_dev, chan); | |
521 | ||
522 | meson_sar_adc_start_sample_engine(indio_dev); | |
523 | ret = meson_sar_adc_read_raw_sample(indio_dev, chan, val); | |
524 | meson_sar_adc_stop_sample_engine(indio_dev); | |
525 | ||
526 | meson_sar_adc_unlock(indio_dev); | |
527 | ||
528 | if (ret) { | |
529 | dev_warn(indio_dev->dev.parent, | |
530 | "failed to read sample for channel %d: %d\n", | |
531 | chan->channel, ret); | |
532 | return ret; | |
533 | } | |
534 | ||
535 | return IIO_VAL_INT; | |
536 | } | |
537 | ||
538 | static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev, | |
539 | const struct iio_chan_spec *chan, | |
540 | int *val, int *val2, long mask) | |
541 | { | |
542 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
543 | int ret; | |
544 | ||
545 | switch (mask) { | |
546 | case IIO_CHAN_INFO_RAW: | |
547 | return meson_sar_adc_get_sample(indio_dev, chan, NO_AVERAGING, | |
548 | ONE_SAMPLE, val); | |
549 | break; | |
550 | ||
551 | case IIO_CHAN_INFO_AVERAGE_RAW: | |
552 | return meson_sar_adc_get_sample(indio_dev, chan, | |
553 | MEAN_AVERAGING, EIGHT_SAMPLES, | |
554 | val); | |
555 | break; | |
556 | ||
557 | case IIO_CHAN_INFO_SCALE: | |
558 | ret = regulator_get_voltage(priv->vref); | |
559 | if (ret < 0) { | |
560 | dev_err(indio_dev->dev.parent, | |
561 | "failed to get vref voltage: %d\n", ret); | |
562 | return ret; | |
563 | } | |
564 | ||
565 | *val = ret / 1000; | |
053ffe3c | 566 | *val2 = priv->data->param->resolution; |
3adbf342 MB |
567 | return IIO_VAL_FRACTIONAL_LOG2; |
568 | ||
48ba7c3c HK |
569 | case IIO_CHAN_INFO_CALIBBIAS: |
570 | *val = priv->calibbias; | |
571 | return IIO_VAL_INT; | |
572 | ||
573 | case IIO_CHAN_INFO_CALIBSCALE: | |
574 | *val = priv->calibscale / MILLION; | |
575 | *val2 = priv->calibscale % MILLION; | |
576 | return IIO_VAL_INT_PLUS_MICRO; | |
577 | ||
3adbf342 MB |
578 | default: |
579 | return -EINVAL; | |
580 | } | |
581 | } | |
582 | ||
583 | static int meson_sar_adc_clk_init(struct iio_dev *indio_dev, | |
584 | void __iomem *base) | |
585 | { | |
586 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
587 | struct clk_init_data init; | |
588 | const char *clk_parents[1]; | |
589 | ||
3921db46 RH |
590 | init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%pOF#adc_div", |
591 | indio_dev->dev.of_node); | |
3adbf342 MB |
592 | init.flags = 0; |
593 | init.ops = &clk_divider_ops; | |
594 | clk_parents[0] = __clk_get_name(priv->clkin); | |
595 | init.parent_names = clk_parents; | |
596 | init.num_parents = 1; | |
597 | ||
598 | priv->clk_div.reg = base + MESON_SAR_ADC_REG3; | |
599 | priv->clk_div.shift = MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT; | |
600 | priv->clk_div.width = MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH; | |
601 | priv->clk_div.hw.init = &init; | |
602 | priv->clk_div.flags = 0; | |
603 | ||
604 | priv->adc_div_clk = devm_clk_register(&indio_dev->dev, | |
605 | &priv->clk_div.hw); | |
606 | if (WARN_ON(IS_ERR(priv->adc_div_clk))) | |
607 | return PTR_ERR(priv->adc_div_clk); | |
608 | ||
3921db46 RH |
609 | init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%pOF#adc_en", |
610 | indio_dev->dev.of_node); | |
3adbf342 MB |
611 | init.flags = CLK_SET_RATE_PARENT; |
612 | init.ops = &clk_gate_ops; | |
613 | clk_parents[0] = __clk_get_name(priv->adc_div_clk); | |
614 | init.parent_names = clk_parents; | |
615 | init.num_parents = 1; | |
616 | ||
617 | priv->clk_gate.reg = base + MESON_SAR_ADC_REG3; | |
7a6b0420 | 618 | priv->clk_gate.bit_idx = __ffs(MESON_SAR_ADC_REG3_CLK_EN); |
3adbf342 MB |
619 | priv->clk_gate.hw.init = &init; |
620 | ||
621 | priv->adc_clk = devm_clk_register(&indio_dev->dev, &priv->clk_gate.hw); | |
622 | if (WARN_ON(IS_ERR(priv->adc_clk))) | |
623 | return PTR_ERR(priv->adc_clk); | |
624 | ||
625 | return 0; | |
626 | } | |
627 | ||
628 | static int meson_sar_adc_init(struct iio_dev *indio_dev) | |
629 | { | |
630 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
ab569a4c | 631 | int regval, i, ret; |
3adbf342 MB |
632 | |
633 | /* | |
634 | * make sure we start at CH7 input since the other muxes are only used | |
635 | * for internal calibration. | |
636 | */ | |
637 | meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); | |
638 | ||
053ffe3c | 639 | if (priv->data->param->has_bl30_integration) { |
6c76ed31 MB |
640 | /* |
641 | * leave sampling delay and the input clocks as configured by | |
642 | * BL30 to make sure BL30 gets the values it expects when | |
643 | * reading the temperature sensor. | |
644 | */ | |
645 | regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ®val); | |
646 | if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED) | |
647 | return 0; | |
648 | } | |
3adbf342 MB |
649 | |
650 | meson_sar_adc_stop_sample_engine(indio_dev); | |
651 | ||
652 | /* update the channel 6 MUX to select the temperature sensor */ | |
653 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, | |
654 | MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL, | |
655 | MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL); | |
656 | ||
657 | /* disable all channels by default */ | |
658 | regmap_write(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 0x0); | |
659 | ||
660 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, | |
661 | MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE, 0); | |
662 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, | |
663 | MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY, | |
664 | MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY); | |
665 | ||
666 | /* delay between two samples = (10+1) * 1uS */ | |
667 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, | |
668 | MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, | |
669 | FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK, | |
670 | 10)); | |
671 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, | |
672 | MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK, | |
673 | FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK, | |
674 | 0)); | |
675 | ||
676 | /* delay between two samples = (10+1) * 1uS */ | |
677 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, | |
678 | MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, | |
679 | FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, | |
680 | 10)); | |
681 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, | |
682 | MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK, | |
683 | FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK, | |
684 | 1)); | |
685 | ||
ab569a4c MB |
686 | /* |
687 | * set up the input channel muxes in MESON_SAR_ADC_CHAN_10_SW | |
688 | * (0 = SAR_ADC_CH0, 1 = SAR_ADC_CH1) | |
689 | */ | |
690 | regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 0); | |
691 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, | |
692 | MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, | |
693 | regval); | |
694 | regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 1); | |
695 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, | |
696 | MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, | |
697 | regval); | |
698 | ||
699 | /* | |
700 | * set up the input channel muxes in MESON_SAR_ADC_AUX_SW | |
701 | * (2 = SAR_ADC_CH2, 3 = SAR_ADC_CH3, ...) and enable | |
702 | * MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW and | |
703 | * MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW like the vendor driver. | |
704 | */ | |
705 | regval = 0; | |
706 | for (i = 2; i <= 7; i++) | |
707 | regval |= i << MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(i); | |
708 | regval |= MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW; | |
709 | regval |= MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW; | |
710 | regmap_write(priv->regmap, MESON_SAR_ADC_AUX_SW, regval); | |
711 | ||
3adbf342 MB |
712 | ret = clk_set_parent(priv->adc_sel_clk, priv->clkin); |
713 | if (ret) { | |
714 | dev_err(indio_dev->dev.parent, | |
715 | "failed to set adc parent to clkin\n"); | |
716 | return ret; | |
717 | } | |
718 | ||
053ffe3c | 719 | ret = clk_set_rate(priv->adc_clk, priv->data->param->clock_rate); |
3adbf342 MB |
720 | if (ret) { |
721 | dev_err(indio_dev->dev.parent, | |
722 | "failed to set adc clock rate\n"); | |
723 | return ret; | |
724 | } | |
725 | ||
726 | return 0; | |
727 | } | |
728 | ||
d85eed9f MB |
729 | static void meson_sar_adc_set_bandgap(struct iio_dev *indio_dev, bool on_off) |
730 | { | |
731 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
053ffe3c | 732 | const struct meson_sar_adc_param *param = priv->data->param; |
d85eed9f MB |
733 | u32 enable_mask; |
734 | ||
053ffe3c | 735 | if (param->bandgap_reg == MESON_SAR_ADC_REG11) |
d85eed9f MB |
736 | enable_mask = MESON_SAR_ADC_REG11_BANDGAP_EN; |
737 | else | |
738 | enable_mask = MESON_SAR_ADC_DELTA_10_TS_VBG_EN; | |
739 | ||
053ffe3c | 740 | regmap_update_bits(priv->regmap, param->bandgap_reg, enable_mask, |
d85eed9f MB |
741 | on_off ? enable_mask : 0); |
742 | } | |
743 | ||
3adbf342 MB |
744 | static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev) |
745 | { | |
746 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
747 | int ret; | |
3af10913 | 748 | u32 regval; |
3adbf342 MB |
749 | |
750 | ret = meson_sar_adc_lock(indio_dev); | |
751 | if (ret) | |
752 | goto err_lock; | |
753 | ||
754 | ret = regulator_enable(priv->vref); | |
755 | if (ret < 0) { | |
756 | dev_err(indio_dev->dev.parent, | |
757 | "failed to enable vref regulator\n"); | |
758 | goto err_vref; | |
759 | } | |
760 | ||
761 | ret = clk_prepare_enable(priv->core_clk); | |
762 | if (ret) { | |
763 | dev_err(indio_dev->dev.parent, "failed to enable core clk\n"); | |
764 | goto err_core_clk; | |
765 | } | |
766 | ||
3af10913 HK |
767 | regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1); |
768 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, | |
769 | MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); | |
d85eed9f MB |
770 | |
771 | meson_sar_adc_set_bandgap(indio_dev, true); | |
772 | ||
3adbf342 MB |
773 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, |
774 | MESON_SAR_ADC_REG3_ADC_EN, | |
775 | MESON_SAR_ADC_REG3_ADC_EN); | |
776 | ||
777 | udelay(5); | |
778 | ||
779 | ret = clk_prepare_enable(priv->adc_clk); | |
780 | if (ret) { | |
781 | dev_err(indio_dev->dev.parent, "failed to enable adc clk\n"); | |
782 | goto err_adc_clk; | |
783 | } | |
784 | ||
785 | meson_sar_adc_unlock(indio_dev); | |
786 | ||
787 | return 0; | |
788 | ||
789 | err_adc_clk: | |
790 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, | |
791 | MESON_SAR_ADC_REG3_ADC_EN, 0); | |
d85eed9f | 792 | meson_sar_adc_set_bandgap(indio_dev, false); |
3adbf342 MB |
793 | clk_disable_unprepare(priv->core_clk); |
794 | err_core_clk: | |
795 | regulator_disable(priv->vref); | |
796 | err_vref: | |
797 | meson_sar_adc_unlock(indio_dev); | |
798 | err_lock: | |
799 | return ret; | |
800 | } | |
801 | ||
802 | static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev) | |
803 | { | |
804 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
805 | int ret; | |
806 | ||
807 | ret = meson_sar_adc_lock(indio_dev); | |
808 | if (ret) | |
809 | return ret; | |
810 | ||
811 | clk_disable_unprepare(priv->adc_clk); | |
812 | ||
813 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, | |
814 | MESON_SAR_ADC_REG3_ADC_EN, 0); | |
d85eed9f MB |
815 | |
816 | meson_sar_adc_set_bandgap(indio_dev, false); | |
3adbf342 | 817 | |
3adbf342 MB |
818 | clk_disable_unprepare(priv->core_clk); |
819 | ||
820 | regulator_disable(priv->vref); | |
821 | ||
822 | meson_sar_adc_unlock(indio_dev); | |
823 | ||
824 | return 0; | |
825 | } | |
826 | ||
3af10913 HK |
827 | static irqreturn_t meson_sar_adc_irq(int irq, void *data) |
828 | { | |
829 | struct iio_dev *indio_dev = data; | |
830 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
831 | unsigned int cnt, threshold; | |
832 | u32 regval; | |
833 | ||
834 | regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val); | |
835 | cnt = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval); | |
836 | threshold = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); | |
837 | ||
838 | if (cnt < threshold) | |
839 | return IRQ_NONE; | |
840 | ||
841 | complete(&priv->done); | |
842 | ||
843 | return IRQ_HANDLED; | |
844 | } | |
845 | ||
48ba7c3c HK |
846 | static int meson_sar_adc_calib(struct iio_dev *indio_dev) |
847 | { | |
848 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
849 | int ret, nominal0, nominal1, value0, value1; | |
850 | ||
851 | /* use points 25% and 75% for calibration */ | |
053ffe3c YL |
852 | nominal0 = (1 << priv->data->param->resolution) / 4; |
853 | nominal1 = (1 << priv->data->param->resolution) * 3 / 4; | |
48ba7c3c HK |
854 | |
855 | meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4); | |
856 | usleep_range(10, 20); | |
857 | ret = meson_sar_adc_get_sample(indio_dev, | |
858 | &meson_sar_adc_iio_channels[7], | |
859 | MEAN_AVERAGING, EIGHT_SAMPLES, &value0); | |
860 | if (ret < 0) | |
861 | goto out; | |
862 | ||
863 | meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_MUL3_DIV4); | |
864 | usleep_range(10, 20); | |
865 | ret = meson_sar_adc_get_sample(indio_dev, | |
866 | &meson_sar_adc_iio_channels[7], | |
867 | MEAN_AVERAGING, EIGHT_SAMPLES, &value1); | |
868 | if (ret < 0) | |
869 | goto out; | |
870 | ||
871 | if (value1 <= value0) { | |
872 | ret = -EINVAL; | |
873 | goto out; | |
874 | } | |
875 | ||
876 | priv->calibscale = div_s64((nominal1 - nominal0) * (s64)MILLION, | |
877 | value1 - value0); | |
878 | priv->calibbias = nominal0 - div_s64((s64)value0 * priv->calibscale, | |
879 | MILLION); | |
880 | ret = 0; | |
881 | out: | |
882 | meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); | |
883 | ||
884 | return ret; | |
885 | } | |
886 | ||
3adbf342 MB |
887 | static const struct iio_info meson_sar_adc_iio_info = { |
888 | .read_raw = meson_sar_adc_iio_info_read_raw, | |
3adbf342 MB |
889 | }; |
890 | ||
053ffe3c | 891 | static const struct meson_sar_adc_param meson_sar_adc_meson8_param = { |
6c76ed31 | 892 | .has_bl30_integration = false, |
fda29dba | 893 | .clock_rate = 1150000, |
d85eed9f | 894 | .bandgap_reg = MESON_SAR_ADC_DELTA_10, |
96748823 | 895 | .regmap_config = &meson_sar_adc_regmap_config_meson8, |
6c76ed31 | 896 | .resolution = 10, |
6c76ed31 MB |
897 | }; |
898 | ||
053ffe3c | 899 | static const struct meson_sar_adc_param meson_sar_adc_gxbb_param = { |
6c76ed31 | 900 | .has_bl30_integration = true, |
fda29dba | 901 | .clock_rate = 1200000, |
d85eed9f | 902 | .bandgap_reg = MESON_SAR_ADC_REG11, |
96748823 | 903 | .regmap_config = &meson_sar_adc_regmap_config_gxbb, |
3adbf342 | 904 | .resolution = 10, |
3adbf342 MB |
905 | }; |
906 | ||
053ffe3c | 907 | static const struct meson_sar_adc_param meson_sar_adc_gxl_param = { |
6c76ed31 | 908 | .has_bl30_integration = true, |
fda29dba | 909 | .clock_rate = 1200000, |
d85eed9f | 910 | .bandgap_reg = MESON_SAR_ADC_REG11, |
96748823 | 911 | .regmap_config = &meson_sar_adc_regmap_config_gxbb, |
3adbf342 | 912 | .resolution = 12, |
053ffe3c YL |
913 | }; |
914 | ||
915 | static const struct meson_sar_adc_data meson_sar_adc_meson8_data = { | |
916 | .param = &meson_sar_adc_meson8_param, | |
917 | .name = "meson-meson8-saradc", | |
918 | }; | |
919 | ||
920 | static const struct meson_sar_adc_data meson_sar_adc_meson8b_data = { | |
921 | .param = &meson_sar_adc_meson8_param, | |
922 | .name = "meson-meson8b-saradc", | |
923 | }; | |
924 | ||
925 | static const struct meson_sar_adc_data meson_sar_adc_gxbb_data = { | |
926 | .param = &meson_sar_adc_gxbb_param, | |
927 | .name = "meson-gxbb-saradc", | |
928 | }; | |
929 | ||
930 | static const struct meson_sar_adc_data meson_sar_adc_gxl_data = { | |
931 | .param = &meson_sar_adc_gxl_param, | |
3adbf342 MB |
932 | .name = "meson-gxl-saradc", |
933 | }; | |
934 | ||
c1c2de37 | 935 | static const struct meson_sar_adc_data meson_sar_adc_gxm_data = { |
053ffe3c | 936 | .param = &meson_sar_adc_gxl_param, |
3adbf342 MB |
937 | .name = "meson-gxm-saradc", |
938 | }; | |
939 | ||
ff632dda XC |
940 | static const struct meson_sar_adc_data meson_sar_adc_axg_data = { |
941 | .param = &meson_sar_adc_gxl_param, | |
942 | .name = "meson-axg-saradc", | |
943 | }; | |
944 | ||
3adbf342 | 945 | static const struct of_device_id meson_sar_adc_of_match[] = { |
6c76ed31 MB |
946 | { |
947 | .compatible = "amlogic,meson8-saradc", | |
948 | .data = &meson_sar_adc_meson8_data, | |
949 | }, | |
950 | { | |
951 | .compatible = "amlogic,meson8b-saradc", | |
952 | .data = &meson_sar_adc_meson8b_data, | |
953 | }, | |
3adbf342 MB |
954 | { |
955 | .compatible = "amlogic,meson-gxbb-saradc", | |
956 | .data = &meson_sar_adc_gxbb_data, | |
957 | }, { | |
958 | .compatible = "amlogic,meson-gxl-saradc", | |
959 | .data = &meson_sar_adc_gxl_data, | |
960 | }, { | |
961 | .compatible = "amlogic,meson-gxm-saradc", | |
962 | .data = &meson_sar_adc_gxm_data, | |
ff632dda XC |
963 | }, { |
964 | .compatible = "amlogic,meson-axg-saradc", | |
965 | .data = &meson_sar_adc_axg_data, | |
3adbf342 MB |
966 | }, |
967 | {}, | |
968 | }; | |
969 | MODULE_DEVICE_TABLE(of, meson_sar_adc_of_match); | |
970 | ||
971 | static int meson_sar_adc_probe(struct platform_device *pdev) | |
972 | { | |
973 | struct meson_sar_adc_priv *priv; | |
974 | struct iio_dev *indio_dev; | |
975 | struct resource *res; | |
976 | void __iomem *base; | |
977 | const struct of_device_id *match; | |
3af10913 | 978 | int irq, ret; |
3adbf342 MB |
979 | |
980 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); | |
981 | if (!indio_dev) { | |
982 | dev_err(&pdev->dev, "failed allocating iio device\n"); | |
983 | return -ENOMEM; | |
984 | } | |
985 | ||
986 | priv = iio_priv(indio_dev); | |
3af10913 | 987 | init_completion(&priv->done); |
3adbf342 MB |
988 | |
989 | match = of_match_device(meson_sar_adc_of_match, &pdev->dev); | |
2f9aeeed GS |
990 | if (!match) { |
991 | dev_err(&pdev->dev, "failed to match device\n"); | |
992 | return -ENODEV; | |
993 | } | |
994 | ||
3adbf342 MB |
995 | priv->data = match->data; |
996 | ||
997 | indio_dev->name = priv->data->name; | |
998 | indio_dev->dev.parent = &pdev->dev; | |
999 | indio_dev->dev.of_node = pdev->dev.of_node; | |
1000 | indio_dev->modes = INDIO_DIRECT_MODE; | |
1001 | indio_dev->info = &meson_sar_adc_iio_info; | |
1002 | ||
1003 | indio_dev->channels = meson_sar_adc_iio_channels; | |
1004 | indio_dev->num_channels = ARRAY_SIZE(meson_sar_adc_iio_channels); | |
1005 | ||
1006 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
1007 | base = devm_ioremap_resource(&pdev->dev, res); | |
1008 | if (IS_ERR(base)) | |
1009 | return PTR_ERR(base); | |
1010 | ||
3af10913 HK |
1011 | irq = irq_of_parse_and_map(pdev->dev.of_node, 0); |
1012 | if (!irq) | |
1013 | return -EINVAL; | |
1014 | ||
1015 | ret = devm_request_irq(&pdev->dev, irq, meson_sar_adc_irq, IRQF_SHARED, | |
1016 | dev_name(&pdev->dev), indio_dev); | |
1017 | if (ret) | |
1018 | return ret; | |
1019 | ||
3adbf342 | 1020 | priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, |
053ffe3c | 1021 | priv->data->param->regmap_config); |
3adbf342 MB |
1022 | if (IS_ERR(priv->regmap)) |
1023 | return PTR_ERR(priv->regmap); | |
1024 | ||
1025 | priv->clkin = devm_clk_get(&pdev->dev, "clkin"); | |
1026 | if (IS_ERR(priv->clkin)) { | |
1027 | dev_err(&pdev->dev, "failed to get clkin\n"); | |
1028 | return PTR_ERR(priv->clkin); | |
1029 | } | |
1030 | ||
1031 | priv->core_clk = devm_clk_get(&pdev->dev, "core"); | |
1032 | if (IS_ERR(priv->core_clk)) { | |
1033 | dev_err(&pdev->dev, "failed to get core clk\n"); | |
1034 | return PTR_ERR(priv->core_clk); | |
1035 | } | |
1036 | ||
3adbf342 MB |
1037 | priv->adc_clk = devm_clk_get(&pdev->dev, "adc_clk"); |
1038 | if (IS_ERR(priv->adc_clk)) { | |
1039 | if (PTR_ERR(priv->adc_clk) == -ENOENT) { | |
1040 | priv->adc_clk = NULL; | |
1041 | } else { | |
1042 | dev_err(&pdev->dev, "failed to get adc clk\n"); | |
1043 | return PTR_ERR(priv->adc_clk); | |
1044 | } | |
1045 | } | |
1046 | ||
1047 | priv->adc_sel_clk = devm_clk_get(&pdev->dev, "adc_sel"); | |
1048 | if (IS_ERR(priv->adc_sel_clk)) { | |
1049 | if (PTR_ERR(priv->adc_sel_clk) == -ENOENT) { | |
1050 | priv->adc_sel_clk = NULL; | |
1051 | } else { | |
1052 | dev_err(&pdev->dev, "failed to get adc_sel clk\n"); | |
1053 | return PTR_ERR(priv->adc_sel_clk); | |
1054 | } | |
1055 | } | |
1056 | ||
1057 | /* on pre-GXBB SoCs the SAR ADC itself provides the ADC clock: */ | |
1058 | if (!priv->adc_clk) { | |
1059 | ret = meson_sar_adc_clk_init(indio_dev, base); | |
1060 | if (ret) | |
1061 | return ret; | |
1062 | } | |
1063 | ||
1064 | priv->vref = devm_regulator_get(&pdev->dev, "vref"); | |
1065 | if (IS_ERR(priv->vref)) { | |
1066 | dev_err(&pdev->dev, "failed to get vref regulator\n"); | |
1067 | return PTR_ERR(priv->vref); | |
1068 | } | |
1069 | ||
48ba7c3c HK |
1070 | priv->calibscale = MILLION; |
1071 | ||
3adbf342 MB |
1072 | ret = meson_sar_adc_init(indio_dev); |
1073 | if (ret) | |
1074 | goto err; | |
1075 | ||
1076 | ret = meson_sar_adc_hw_enable(indio_dev); | |
1077 | if (ret) | |
1078 | goto err; | |
1079 | ||
48ba7c3c HK |
1080 | ret = meson_sar_adc_calib(indio_dev); |
1081 | if (ret) | |
1082 | dev_warn(&pdev->dev, "calibration failed\n"); | |
1083 | ||
3adbf342 MB |
1084 | platform_set_drvdata(pdev, indio_dev); |
1085 | ||
1086 | ret = iio_device_register(indio_dev); | |
1087 | if (ret) | |
1088 | goto err_hw; | |
1089 | ||
1090 | return 0; | |
1091 | ||
1092 | err_hw: | |
1093 | meson_sar_adc_hw_disable(indio_dev); | |
1094 | err: | |
1095 | return ret; | |
1096 | } | |
1097 | ||
1098 | static int meson_sar_adc_remove(struct platform_device *pdev) | |
1099 | { | |
1100 | struct iio_dev *indio_dev = platform_get_drvdata(pdev); | |
1101 | ||
1102 | iio_device_unregister(indio_dev); | |
1103 | ||
1104 | return meson_sar_adc_hw_disable(indio_dev); | |
1105 | } | |
1106 | ||
1107 | static int __maybe_unused meson_sar_adc_suspend(struct device *dev) | |
1108 | { | |
1109 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
1110 | ||
1111 | return meson_sar_adc_hw_disable(indio_dev); | |
1112 | } | |
1113 | ||
1114 | static int __maybe_unused meson_sar_adc_resume(struct device *dev) | |
1115 | { | |
1116 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
1117 | ||
1118 | return meson_sar_adc_hw_enable(indio_dev); | |
1119 | } | |
1120 | ||
1121 | static SIMPLE_DEV_PM_OPS(meson_sar_adc_pm_ops, | |
1122 | meson_sar_adc_suspend, meson_sar_adc_resume); | |
1123 | ||
1124 | static struct platform_driver meson_sar_adc_driver = { | |
1125 | .probe = meson_sar_adc_probe, | |
1126 | .remove = meson_sar_adc_remove, | |
1127 | .driver = { | |
1128 | .name = "meson-saradc", | |
1129 | .of_match_table = meson_sar_adc_of_match, | |
1130 | .pm = &meson_sar_adc_pm_ops, | |
1131 | }, | |
1132 | }; | |
1133 | ||
1134 | module_platform_driver(meson_sar_adc_driver); | |
1135 | ||
1136 | MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>"); | |
1137 | MODULE_DESCRIPTION("Amlogic Meson SAR ADC driver"); | |
1138 | MODULE_LICENSE("GPL v2"); |