blob: f6832ab30731463546917204863b791c54136a92 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
David Wuf8d5bc72017-09-20 14:28:16 +08002/*
3 * (C) Copyright 2017, Fuzhou Rockchip Electronics Co., Ltd
4 *
David Wuf8d5bc72017-09-20 14:28:16 +08005 * Rockchip SARADC driver for U-Boot
6 */
7
David Wuf8d5bc72017-09-20 14:28:16 +08008#include <adc.h>
9#include <clk.h>
10#include <dm.h>
11#include <errno.h>
Quentin Schulz5df8ac42024-03-14 10:36:24 +010012#include <reset.h>
13#include <asm/arch-rockchip/hardware.h>
14#include <linux/bitfield.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060015#include <linux/bitops.h>
Quentin Schulz5df8ac42024-03-14 10:36:24 +010016#include <linux/delay.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070017#include <linux/err.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060018#include <linux/printk.h>
Peter Cai14f3e382022-02-04 15:16:06 -050019#include <power/regulator.h>
David Wuf8d5bc72017-09-20 14:28:16 +080020
Quentin Schulz5df8ac42024-03-14 10:36:24 +010021#define usleep_range(a, b) udelay((b))
22
David Wuf8d5bc72017-09-20 14:28:16 +080023#define SARADC_CTRL_CHN_MASK GENMASK(2, 0)
24#define SARADC_CTRL_POWER_CTRL BIT(3)
25#define SARADC_CTRL_IRQ_ENABLE BIT(5)
26#define SARADC_CTRL_IRQ_STATUS BIT(6)
27
28#define SARADC_TIMEOUT (100 * 1000)
29
Quentin Schulzf1209562024-03-14 10:36:20 +010030struct rockchip_saradc_regs_v1 {
David Wuf8d5bc72017-09-20 14:28:16 +080031 unsigned int data;
32 unsigned int stas;
33 unsigned int ctrl;
34 unsigned int dly_pu_soc;
35};
36
Quentin Schulz5df8ac42024-03-14 10:36:24 +010037struct rockchip_saradc_regs_v2 {
38 unsigned int conv_con;
39#define SARADC2_SINGLE_MODE BIT(5)
40#define SARADC2_START BIT(4)
41#define SARADC2_CONV_CHANNELS GENMASK(3, 0)
42 unsigned int t_pd_soc;
43 unsigned int t_as_soc;
44 unsigned int t_das_soc;
45 unsigned int t_sel_soc;
46 unsigned int high_comp[16];
47 unsigned int low_comp[16];
48 unsigned int debounce;
49 unsigned int ht_int_en;
50 unsigned int lt_int_en;
51 unsigned int reserved[24];
52 unsigned int mt_int_en;
53 unsigned int end_int_en;
54#define SARADC2_EN_END_INT BIT(0)
55 unsigned int st_con;
56 unsigned int status;
57 unsigned int end_int_st;
58 unsigned int ht_int_st;
59 unsigned int lt_int_st;
60 unsigned int mt_int_st;
61 unsigned int data[16];
62 unsigned int auto_ch_en;
63};
64
Quentin Schulzf1209562024-03-14 10:36:20 +010065union rockchip_saradc_regs {
66 struct rockchip_saradc_regs_v1 *v1;
Quentin Schulz5df8ac42024-03-14 10:36:24 +010067 struct rockchip_saradc_regs_v2 *v2;
Quentin Schulzf1209562024-03-14 10:36:20 +010068};
David Wuf8d5bc72017-09-20 14:28:16 +080069struct rockchip_saradc_data {
70 int num_bits;
71 int num_channels;
72 unsigned long clk_rate;
Quentin Schulza07eeca2024-03-14 10:36:21 +010073 int (*channel_data)(struct udevice *dev, int channel, unsigned int *data);
Quentin Schulzd0aaaae2024-03-14 10:36:22 +010074 int (*start_channel)(struct udevice *dev, int channel);
Quentin Schulze8e0aae2024-03-14 10:36:23 +010075 int (*stop)(struct udevice *dev);
David Wuf8d5bc72017-09-20 14:28:16 +080076};
77
78struct rockchip_saradc_priv {
Quentin Schulzf1209562024-03-14 10:36:20 +010079 union rockchip_saradc_regs regs;
David Wuf8d5bc72017-09-20 14:28:16 +080080 int active_channel;
81 const struct rockchip_saradc_data *data;
Quentin Schulz5df8ac42024-03-14 10:36:24 +010082 struct reset_ctl *reset;
David Wuf8d5bc72017-09-20 14:28:16 +080083};
84
Quentin Schulza07eeca2024-03-14 10:36:21 +010085int rockchip_saradc_channel_data_v1(struct udevice *dev, int channel,
86 unsigned int *data)
87{
88 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
89
90 if ((readl(&priv->regs.v1->ctrl) & SARADC_CTRL_IRQ_STATUS) !=
91 SARADC_CTRL_IRQ_STATUS)
92 return -EBUSY;
93
94 /* Read value */
95 *data = readl(&priv->regs.v1->data);
96
97 /* Power down adc */
98 writel(0, &priv->regs.v1->ctrl);
99
100 return 0;
101}
102
Quentin Schulz5df8ac42024-03-14 10:36:24 +0100103int rockchip_saradc_channel_data_v2(struct udevice *dev, int channel,
104 unsigned int *data)
105{
106 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
107
108 if (!(readl(&priv->regs.v2->end_int_st) & SARADC2_EN_END_INT))
109 return -EBUSY;
110
111 /* Read value */
112 *data = readl(&priv->regs.v2->data[channel]);
113
114 /* Acknowledge the interrupt */
115 writel(SARADC2_EN_END_INT, &priv->regs.v2->end_int_st);
116
117 return 0;
118}
David Wuf8d5bc72017-09-20 14:28:16 +0800119int rockchip_saradc_channel_data(struct udevice *dev, int channel,
120 unsigned int *data)
121{
122 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
Simon Glass71fa5b42020-12-03 16:55:18 -0700123 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
Quentin Schulza07eeca2024-03-14 10:36:21 +0100124 int ret;
David Wuf8d5bc72017-09-20 14:28:16 +0800125
126 if (channel != priv->active_channel) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900127 pr_err("Requested channel is not active!");
David Wuf8d5bc72017-09-20 14:28:16 +0800128 return -EINVAL;
129 }
130
Quentin Schulza07eeca2024-03-14 10:36:21 +0100131 ret = priv->data->channel_data(dev, channel, data);
132 if (ret) {
133 if (ret != -EBUSY)
134 pr_err("Error reading channel data, %d!", ret);
135 return ret;
136 }
David Wuf8d5bc72017-09-20 14:28:16 +0800137
David Wuf8d5bc72017-09-20 14:28:16 +0800138 *data &= uc_pdata->data_mask;
139
David Wuf8d5bc72017-09-20 14:28:16 +0800140 return 0;
141}
142
Quentin Schulzd0aaaae2024-03-14 10:36:22 +0100143int rockchip_saradc_start_channel_v1(struct udevice *dev, int channel)
David Wuf8d5bc72017-09-20 14:28:16 +0800144{
145 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
146
David Wuf8d5bc72017-09-20 14:28:16 +0800147 /* 8 clock periods as delay between power up and start cmd */
Quentin Schulzf1209562024-03-14 10:36:20 +0100148 writel(8, &priv->regs.v1->dly_pu_soc);
David Wuf8d5bc72017-09-20 14:28:16 +0800149
150 /* Select the channel to be used and trigger conversion */
151 writel(SARADC_CTRL_POWER_CTRL | (channel & SARADC_CTRL_CHN_MASK) |
Quentin Schulzf1209562024-03-14 10:36:20 +0100152 SARADC_CTRL_IRQ_ENABLE, &priv->regs.v1->ctrl);
David Wuf8d5bc72017-09-20 14:28:16 +0800153
Quentin Schulzd0aaaae2024-03-14 10:36:22 +0100154 return 0;
155}
156
Quentin Schulz5df8ac42024-03-14 10:36:24 +0100157static void rockchip_saradc_reset_controller(struct reset_ctl *reset)
158{
159 reset_assert(reset);
160 usleep_range(10, 20);
161 reset_deassert(reset);
162}
163
164int rockchip_saradc_start_channel_v2(struct udevice *dev, int channel)
165{
166 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
167
168 /*
169 * Downstream says
170 * """If read other chn at anytime, then chn1 will error, assert
171 * controller as a workaround."""
172 */
173 if (priv->reset)
174 rockchip_saradc_reset_controller(priv->reset);
175
176 writel(0xc, &priv->regs.v2->t_das_soc);
177 writel(0x20, &priv->regs.v2->t_pd_soc);
178
179 /* Acknowledge any previous interrupt */
180 writel(SARADC2_EN_END_INT, &priv->regs.v2->end_int_st);
181
182 rk_clrsetreg(&priv->regs.v2->conv_con,
183 SARADC2_CONV_CHANNELS | SARADC2_START | SARADC2_SINGLE_MODE,
184 FIELD_PREP(SARADC2_CONV_CHANNELS, channel) |
185 FIELD_PREP(SARADC2_START, 1) |
186 FIELD_PREP(SARADC2_SINGLE_MODE, 1));
187
188 return 0;
189}
190
Quentin Schulzd0aaaae2024-03-14 10:36:22 +0100191int rockchip_saradc_start_channel(struct udevice *dev, int channel)
192{
193 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
194 int ret;
195
196 if (channel < 0 || channel >= priv->data->num_channels) {
197 pr_err("Requested channel is invalid!");
198 return -EINVAL;
199 }
200
201 ret = priv->data->start_channel(dev, channel);
202 if (ret) {
203 pr_err("Error starting channel, %d!", ret);
204 return ret;
205 }
206
David Wuf8d5bc72017-09-20 14:28:16 +0800207 priv->active_channel = channel;
208
209 return 0;
210}
211
Quentin Schulze8e0aae2024-03-14 10:36:23 +0100212int rockchip_saradc_stop_v1(struct udevice *dev)
David Wuf8d5bc72017-09-20 14:28:16 +0800213{
214 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
215
216 /* Power down adc */
Quentin Schulzf1209562024-03-14 10:36:20 +0100217 writel(0, &priv->regs.v1->ctrl);
David Wuf8d5bc72017-09-20 14:28:16 +0800218
Quentin Schulze8e0aae2024-03-14 10:36:23 +0100219 return 0;
220}
221
222int rockchip_saradc_stop(struct udevice *dev)
223{
224 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
225
226 if (priv->data->stop) {
227 int ret = priv->data->stop(dev);
228
229 if (ret) {
230 pr_err("Error stopping channel, %d!", ret);
231 return ret;
232 }
233 }
234
David Wuf8d5bc72017-09-20 14:28:16 +0800235 priv->active_channel = -1;
236
237 return 0;
238}
239
240int rockchip_saradc_probe(struct udevice *dev)
241{
Peter Cai14f3e382022-02-04 15:16:06 -0500242 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
David Wuf8d5bc72017-09-20 14:28:16 +0800243 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
Peter Cai14f3e382022-02-04 15:16:06 -0500244 struct udevice *vref;
David Wuf8d5bc72017-09-20 14:28:16 +0800245 struct clk clk;
Peter Cai14f3e382022-02-04 15:16:06 -0500246 int vref_uv;
David Wuf8d5bc72017-09-20 14:28:16 +0800247 int ret;
248
Quentin Schulz5df8ac42024-03-14 10:36:24 +0100249 priv->reset = devm_reset_control_get_optional(dev, "saradc-apb");
250
David Wuf8d5bc72017-09-20 14:28:16 +0800251 ret = clk_get_by_index(dev, 0, &clk);
252 if (ret)
253 return ret;
254
255 ret = clk_set_rate(&clk, priv->data->clk_rate);
256 if (IS_ERR_VALUE(ret))
257 return ret;
258
259 priv->active_channel = -1;
260
Peter Cai14f3e382022-02-04 15:16:06 -0500261 ret = device_get_supply_regulator(dev, "vref-supply", &vref);
262 if (ret) {
263 printf("can't get vref-supply: %d\n", ret);
264 return ret;
265 }
266
Quentin Schulz5df8ac42024-03-14 10:36:24 +0100267 if (priv->reset)
268 rockchip_saradc_reset_controller(priv->reset);
269
Peter Cai14f3e382022-02-04 15:16:06 -0500270 vref_uv = regulator_get_value(vref);
271 if (vref_uv < 0) {
272 printf("can't get vref-supply value: %d\n", vref_uv);
273 return vref_uv;
274 }
275
276 /* VDD supplied by common vref pin */
277 uc_pdata->vdd_supply = vref;
278 uc_pdata->vdd_microvolts = vref_uv;
279 uc_pdata->vss_microvolts = 0;
280
David Wuf8d5bc72017-09-20 14:28:16 +0800281 return 0;
282}
283
Simon Glassaad29ae2020-12-03 16:55:21 -0700284int rockchip_saradc_of_to_plat(struct udevice *dev)
David Wuf8d5bc72017-09-20 14:28:16 +0800285{
Simon Glass71fa5b42020-12-03 16:55:18 -0700286 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
David Wuf8d5bc72017-09-20 14:28:16 +0800287 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
288 struct rockchip_saradc_data *data;
289
290 data = (struct rockchip_saradc_data *)dev_get_driver_data(dev);
Quentin Schulzf1209562024-03-14 10:36:20 +0100291 priv->regs.v1 = dev_read_addr_ptr(dev);
292 if (!priv->regs.v1) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900293 pr_err("Dev: %s - can't get address!", dev->name);
Johan Jonkerb415d0e2023-03-13 01:29:35 +0100294 return -EINVAL;
David Wuf8d5bc72017-09-20 14:28:16 +0800295 }
296
297 priv->data = data;
Giulio Benetti33ecda02022-03-14 10:09:43 +0100298 uc_pdata->data_mask = (1 << priv->data->num_bits) - 1;
David Wuf8d5bc72017-09-20 14:28:16 +0800299 uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
300 uc_pdata->data_timeout_us = SARADC_TIMEOUT / 5;
301 uc_pdata->channel_mask = (1 << priv->data->num_channels) - 1;
302
303 return 0;
304}
305
306static const struct adc_ops rockchip_saradc_ops = {
307 .start_channel = rockchip_saradc_start_channel,
308 .channel_data = rockchip_saradc_channel_data,
309 .stop = rockchip_saradc_stop,
310};
311
312static const struct rockchip_saradc_data saradc_data = {
313 .num_bits = 10,
314 .num_channels = 3,
315 .clk_rate = 1000000,
Quentin Schulza07eeca2024-03-14 10:36:21 +0100316 .channel_data = rockchip_saradc_channel_data_v1,
Quentin Schulzd0aaaae2024-03-14 10:36:22 +0100317 .start_channel = rockchip_saradc_start_channel_v1,
Quentin Schulze8e0aae2024-03-14 10:36:23 +0100318 .stop = rockchip_saradc_stop_v1,
David Wuf8d5bc72017-09-20 14:28:16 +0800319};
320
321static const struct rockchip_saradc_data rk3066_tsadc_data = {
322 .num_bits = 12,
323 .num_channels = 2,
324 .clk_rate = 50000,
Quentin Schulza07eeca2024-03-14 10:36:21 +0100325 .channel_data = rockchip_saradc_channel_data_v1,
Quentin Schulzd0aaaae2024-03-14 10:36:22 +0100326 .start_channel = rockchip_saradc_start_channel_v1,
Quentin Schulze8e0aae2024-03-14 10:36:23 +0100327 .stop = rockchip_saradc_stop_v1,
David Wuf8d5bc72017-09-20 14:28:16 +0800328};
329
330static const struct rockchip_saradc_data rk3399_saradc_data = {
331 .num_bits = 10,
332 .num_channels = 6,
333 .clk_rate = 1000000,
Quentin Schulza07eeca2024-03-14 10:36:21 +0100334 .channel_data = rockchip_saradc_channel_data_v1,
Quentin Schulzd0aaaae2024-03-14 10:36:22 +0100335 .start_channel = rockchip_saradc_start_channel_v1,
Quentin Schulze8e0aae2024-03-14 10:36:23 +0100336 .stop = rockchip_saradc_stop_v1,
David Wuf8d5bc72017-09-20 14:28:16 +0800337};
338
Quentin Schulz5df8ac42024-03-14 10:36:24 +0100339static const struct rockchip_saradc_data rk3588_saradc_data = {
340 .num_bits = 12,
341 .num_channels = 8,
342 .clk_rate = 1000000,
343 .channel_data = rockchip_saradc_channel_data_v2,
344 .start_channel = rockchip_saradc_start_channel_v2,
345};
346
David Wuf8d5bc72017-09-20 14:28:16 +0800347static const struct udevice_id rockchip_saradc_ids[] = {
348 { .compatible = "rockchip,saradc",
349 .data = (ulong)&saradc_data },
350 { .compatible = "rockchip,rk3066-tsadc",
351 .data = (ulong)&rk3066_tsadc_data },
352 { .compatible = "rockchip,rk3399-saradc",
353 .data = (ulong)&rk3399_saradc_data },
Quentin Schulz5df8ac42024-03-14 10:36:24 +0100354 { .compatible = "rockchip,rk3588-saradc",
355 .data = (ulong)&rk3588_saradc_data },
David Wuf8d5bc72017-09-20 14:28:16 +0800356 { }
357};
358
359U_BOOT_DRIVER(rockchip_saradc) = {
360 .name = "rockchip_saradc",
361 .id = UCLASS_ADC,
362 .of_match = rockchip_saradc_ids,
363 .ops = &rockchip_saradc_ops,
364 .probe = rockchip_saradc_probe,
Simon Glassaad29ae2020-12-03 16:55:21 -0700365 .of_to_plat = rockchip_saradc_of_to_plat,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700366 .priv_auto = sizeof(struct rockchip_saradc_priv),
David Wuf8d5bc72017-09-20 14:28:16 +0800367};