blob: 10ded1b088f380265c5b8100f7ed6ff90b60f738 [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
8#include <common.h>
9#include <adc.h>
10#include <clk.h>
11#include <dm.h>
12#include <errno.h>
Quentin Schulz5df8ac42024-03-14 10:36:24 +010013#include <reset.h>
14#include <asm/arch-rockchip/hardware.h>
15#include <linux/bitfield.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060016#include <linux/bitops.h>
Quentin Schulz5df8ac42024-03-14 10:36:24 +010017#include <linux/delay.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070018#include <linux/err.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060019#include <linux/printk.h>
Peter Cai14f3e382022-02-04 15:16:06 -050020#include <power/regulator.h>
David Wuf8d5bc72017-09-20 14:28:16 +080021
Quentin Schulz5df8ac42024-03-14 10:36:24 +010022#define usleep_range(a, b) udelay((b))
23
David Wuf8d5bc72017-09-20 14:28:16 +080024#define SARADC_CTRL_CHN_MASK GENMASK(2, 0)
25#define SARADC_CTRL_POWER_CTRL BIT(3)
26#define SARADC_CTRL_IRQ_ENABLE BIT(5)
27#define SARADC_CTRL_IRQ_STATUS BIT(6)
28
29#define SARADC_TIMEOUT (100 * 1000)
30
Quentin Schulzf1209562024-03-14 10:36:20 +010031struct rockchip_saradc_regs_v1 {
David Wuf8d5bc72017-09-20 14:28:16 +080032 unsigned int data;
33 unsigned int stas;
34 unsigned int ctrl;
35 unsigned int dly_pu_soc;
36};
37
Quentin Schulz5df8ac42024-03-14 10:36:24 +010038struct rockchip_saradc_regs_v2 {
39 unsigned int conv_con;
40#define SARADC2_SINGLE_MODE BIT(5)
41#define SARADC2_START BIT(4)
42#define SARADC2_CONV_CHANNELS GENMASK(3, 0)
43 unsigned int t_pd_soc;
44 unsigned int t_as_soc;
45 unsigned int t_das_soc;
46 unsigned int t_sel_soc;
47 unsigned int high_comp[16];
48 unsigned int low_comp[16];
49 unsigned int debounce;
50 unsigned int ht_int_en;
51 unsigned int lt_int_en;
52 unsigned int reserved[24];
53 unsigned int mt_int_en;
54 unsigned int end_int_en;
55#define SARADC2_EN_END_INT BIT(0)
56 unsigned int st_con;
57 unsigned int status;
58 unsigned int end_int_st;
59 unsigned int ht_int_st;
60 unsigned int lt_int_st;
61 unsigned int mt_int_st;
62 unsigned int data[16];
63 unsigned int auto_ch_en;
64};
65
Quentin Schulzf1209562024-03-14 10:36:20 +010066union rockchip_saradc_regs {
67 struct rockchip_saradc_regs_v1 *v1;
Quentin Schulz5df8ac42024-03-14 10:36:24 +010068 struct rockchip_saradc_regs_v2 *v2;
Quentin Schulzf1209562024-03-14 10:36:20 +010069};
David Wuf8d5bc72017-09-20 14:28:16 +080070struct rockchip_saradc_data {
71 int num_bits;
72 int num_channels;
73 unsigned long clk_rate;
Quentin Schulza07eeca2024-03-14 10:36:21 +010074 int (*channel_data)(struct udevice *dev, int channel, unsigned int *data);
Quentin Schulzd0aaaae2024-03-14 10:36:22 +010075 int (*start_channel)(struct udevice *dev, int channel);
Quentin Schulze8e0aae2024-03-14 10:36:23 +010076 int (*stop)(struct udevice *dev);
David Wuf8d5bc72017-09-20 14:28:16 +080077};
78
79struct rockchip_saradc_priv {
Quentin Schulzf1209562024-03-14 10:36:20 +010080 union rockchip_saradc_regs regs;
David Wuf8d5bc72017-09-20 14:28:16 +080081 int active_channel;
82 const struct rockchip_saradc_data *data;
Quentin Schulz5df8ac42024-03-14 10:36:24 +010083 struct reset_ctl *reset;
David Wuf8d5bc72017-09-20 14:28:16 +080084};
85
Quentin Schulza07eeca2024-03-14 10:36:21 +010086int rockchip_saradc_channel_data_v1(struct udevice *dev, int channel,
87 unsigned int *data)
88{
89 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
90
91 if ((readl(&priv->regs.v1->ctrl) & SARADC_CTRL_IRQ_STATUS) !=
92 SARADC_CTRL_IRQ_STATUS)
93 return -EBUSY;
94
95 /* Read value */
96 *data = readl(&priv->regs.v1->data);
97
98 /* Power down adc */
99 writel(0, &priv->regs.v1->ctrl);
100
101 return 0;
102}
103
Quentin Schulz5df8ac42024-03-14 10:36:24 +0100104int rockchip_saradc_channel_data_v2(struct udevice *dev, int channel,
105 unsigned int *data)
106{
107 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
108
109 if (!(readl(&priv->regs.v2->end_int_st) & SARADC2_EN_END_INT))
110 return -EBUSY;
111
112 /* Read value */
113 *data = readl(&priv->regs.v2->data[channel]);
114
115 /* Acknowledge the interrupt */
116 writel(SARADC2_EN_END_INT, &priv->regs.v2->end_int_st);
117
118 return 0;
119}
David Wuf8d5bc72017-09-20 14:28:16 +0800120int rockchip_saradc_channel_data(struct udevice *dev, int channel,
121 unsigned int *data)
122{
123 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
Simon Glass71fa5b42020-12-03 16:55:18 -0700124 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
Quentin Schulza07eeca2024-03-14 10:36:21 +0100125 int ret;
David Wuf8d5bc72017-09-20 14:28:16 +0800126
127 if (channel != priv->active_channel) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900128 pr_err("Requested channel is not active!");
David Wuf8d5bc72017-09-20 14:28:16 +0800129 return -EINVAL;
130 }
131
Quentin Schulza07eeca2024-03-14 10:36:21 +0100132 ret = priv->data->channel_data(dev, channel, data);
133 if (ret) {
134 if (ret != -EBUSY)
135 pr_err("Error reading channel data, %d!", ret);
136 return ret;
137 }
David Wuf8d5bc72017-09-20 14:28:16 +0800138
David Wuf8d5bc72017-09-20 14:28:16 +0800139 *data &= uc_pdata->data_mask;
140
David Wuf8d5bc72017-09-20 14:28:16 +0800141 return 0;
142}
143
Quentin Schulzd0aaaae2024-03-14 10:36:22 +0100144int rockchip_saradc_start_channel_v1(struct udevice *dev, int channel)
David Wuf8d5bc72017-09-20 14:28:16 +0800145{
146 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
147
David Wuf8d5bc72017-09-20 14:28:16 +0800148 /* 8 clock periods as delay between power up and start cmd */
Quentin Schulzf1209562024-03-14 10:36:20 +0100149 writel(8, &priv->regs.v1->dly_pu_soc);
David Wuf8d5bc72017-09-20 14:28:16 +0800150
151 /* Select the channel to be used and trigger conversion */
152 writel(SARADC_CTRL_POWER_CTRL | (channel & SARADC_CTRL_CHN_MASK) |
Quentin Schulzf1209562024-03-14 10:36:20 +0100153 SARADC_CTRL_IRQ_ENABLE, &priv->regs.v1->ctrl);
David Wuf8d5bc72017-09-20 14:28:16 +0800154
Quentin Schulzd0aaaae2024-03-14 10:36:22 +0100155 return 0;
156}
157
Quentin Schulz5df8ac42024-03-14 10:36:24 +0100158static void rockchip_saradc_reset_controller(struct reset_ctl *reset)
159{
160 reset_assert(reset);
161 usleep_range(10, 20);
162 reset_deassert(reset);
163}
164
165int rockchip_saradc_start_channel_v2(struct udevice *dev, int channel)
166{
167 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
168
169 /*
170 * Downstream says
171 * """If read other chn at anytime, then chn1 will error, assert
172 * controller as a workaround."""
173 */
174 if (priv->reset)
175 rockchip_saradc_reset_controller(priv->reset);
176
177 writel(0xc, &priv->regs.v2->t_das_soc);
178 writel(0x20, &priv->regs.v2->t_pd_soc);
179
180 /* Acknowledge any previous interrupt */
181 writel(SARADC2_EN_END_INT, &priv->regs.v2->end_int_st);
182
183 rk_clrsetreg(&priv->regs.v2->conv_con,
184 SARADC2_CONV_CHANNELS | SARADC2_START | SARADC2_SINGLE_MODE,
185 FIELD_PREP(SARADC2_CONV_CHANNELS, channel) |
186 FIELD_PREP(SARADC2_START, 1) |
187 FIELD_PREP(SARADC2_SINGLE_MODE, 1));
188
189 return 0;
190}
191
Quentin Schulzd0aaaae2024-03-14 10:36:22 +0100192int rockchip_saradc_start_channel(struct udevice *dev, int channel)
193{
194 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
195 int ret;
196
197 if (channel < 0 || channel >= priv->data->num_channels) {
198 pr_err("Requested channel is invalid!");
199 return -EINVAL;
200 }
201
202 ret = priv->data->start_channel(dev, channel);
203 if (ret) {
204 pr_err("Error starting channel, %d!", ret);
205 return ret;
206 }
207
David Wuf8d5bc72017-09-20 14:28:16 +0800208 priv->active_channel = channel;
209
210 return 0;
211}
212
Quentin Schulze8e0aae2024-03-14 10:36:23 +0100213int rockchip_saradc_stop_v1(struct udevice *dev)
David Wuf8d5bc72017-09-20 14:28:16 +0800214{
215 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
216
217 /* Power down adc */
Quentin Schulzf1209562024-03-14 10:36:20 +0100218 writel(0, &priv->regs.v1->ctrl);
David Wuf8d5bc72017-09-20 14:28:16 +0800219
Quentin Schulze8e0aae2024-03-14 10:36:23 +0100220 return 0;
221}
222
223int rockchip_saradc_stop(struct udevice *dev)
224{
225 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
226
227 if (priv->data->stop) {
228 int ret = priv->data->stop(dev);
229
230 if (ret) {
231 pr_err("Error stopping channel, %d!", ret);
232 return ret;
233 }
234 }
235
David Wuf8d5bc72017-09-20 14:28:16 +0800236 priv->active_channel = -1;
237
238 return 0;
239}
240
241int rockchip_saradc_probe(struct udevice *dev)
242{
Peter Cai14f3e382022-02-04 15:16:06 -0500243 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
David Wuf8d5bc72017-09-20 14:28:16 +0800244 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
Peter Cai14f3e382022-02-04 15:16:06 -0500245 struct udevice *vref;
David Wuf8d5bc72017-09-20 14:28:16 +0800246 struct clk clk;
Peter Cai14f3e382022-02-04 15:16:06 -0500247 int vref_uv;
David Wuf8d5bc72017-09-20 14:28:16 +0800248 int ret;
249
Quentin Schulz5df8ac42024-03-14 10:36:24 +0100250 priv->reset = devm_reset_control_get_optional(dev, "saradc-apb");
251
David Wuf8d5bc72017-09-20 14:28:16 +0800252 ret = clk_get_by_index(dev, 0, &clk);
253 if (ret)
254 return ret;
255
256 ret = clk_set_rate(&clk, priv->data->clk_rate);
257 if (IS_ERR_VALUE(ret))
258 return ret;
259
260 priv->active_channel = -1;
261
Peter Cai14f3e382022-02-04 15:16:06 -0500262 ret = device_get_supply_regulator(dev, "vref-supply", &vref);
263 if (ret) {
264 printf("can't get vref-supply: %d\n", ret);
265 return ret;
266 }
267
Quentin Schulz5df8ac42024-03-14 10:36:24 +0100268 if (priv->reset)
269 rockchip_saradc_reset_controller(priv->reset);
270
Peter Cai14f3e382022-02-04 15:16:06 -0500271 vref_uv = regulator_get_value(vref);
272 if (vref_uv < 0) {
273 printf("can't get vref-supply value: %d\n", vref_uv);
274 return vref_uv;
275 }
276
277 /* VDD supplied by common vref pin */
278 uc_pdata->vdd_supply = vref;
279 uc_pdata->vdd_microvolts = vref_uv;
280 uc_pdata->vss_microvolts = 0;
281
David Wuf8d5bc72017-09-20 14:28:16 +0800282 return 0;
283}
284
Simon Glassaad29ae2020-12-03 16:55:21 -0700285int rockchip_saradc_of_to_plat(struct udevice *dev)
David Wuf8d5bc72017-09-20 14:28:16 +0800286{
Simon Glass71fa5b42020-12-03 16:55:18 -0700287 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
David Wuf8d5bc72017-09-20 14:28:16 +0800288 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
289 struct rockchip_saradc_data *data;
290
291 data = (struct rockchip_saradc_data *)dev_get_driver_data(dev);
Quentin Schulzf1209562024-03-14 10:36:20 +0100292 priv->regs.v1 = dev_read_addr_ptr(dev);
293 if (!priv->regs.v1) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900294 pr_err("Dev: %s - can't get address!", dev->name);
Johan Jonkerb415d0e2023-03-13 01:29:35 +0100295 return -EINVAL;
David Wuf8d5bc72017-09-20 14:28:16 +0800296 }
297
298 priv->data = data;
Giulio Benetti33ecda02022-03-14 10:09:43 +0100299 uc_pdata->data_mask = (1 << priv->data->num_bits) - 1;
David Wuf8d5bc72017-09-20 14:28:16 +0800300 uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
301 uc_pdata->data_timeout_us = SARADC_TIMEOUT / 5;
302 uc_pdata->channel_mask = (1 << priv->data->num_channels) - 1;
303
304 return 0;
305}
306
307static const struct adc_ops rockchip_saradc_ops = {
308 .start_channel = rockchip_saradc_start_channel,
309 .channel_data = rockchip_saradc_channel_data,
310 .stop = rockchip_saradc_stop,
311};
312
313static const struct rockchip_saradc_data saradc_data = {
314 .num_bits = 10,
315 .num_channels = 3,
316 .clk_rate = 1000000,
Quentin Schulza07eeca2024-03-14 10:36:21 +0100317 .channel_data = rockchip_saradc_channel_data_v1,
Quentin Schulzd0aaaae2024-03-14 10:36:22 +0100318 .start_channel = rockchip_saradc_start_channel_v1,
Quentin Schulze8e0aae2024-03-14 10:36:23 +0100319 .stop = rockchip_saradc_stop_v1,
David Wuf8d5bc72017-09-20 14:28:16 +0800320};
321
322static const struct rockchip_saradc_data rk3066_tsadc_data = {
323 .num_bits = 12,
324 .num_channels = 2,
325 .clk_rate = 50000,
Quentin Schulza07eeca2024-03-14 10:36:21 +0100326 .channel_data = rockchip_saradc_channel_data_v1,
Quentin Schulzd0aaaae2024-03-14 10:36:22 +0100327 .start_channel = rockchip_saradc_start_channel_v1,
Quentin Schulze8e0aae2024-03-14 10:36:23 +0100328 .stop = rockchip_saradc_stop_v1,
David Wuf8d5bc72017-09-20 14:28:16 +0800329};
330
331static const struct rockchip_saradc_data rk3399_saradc_data = {
332 .num_bits = 10,
333 .num_channels = 6,
334 .clk_rate = 1000000,
Quentin Schulza07eeca2024-03-14 10:36:21 +0100335 .channel_data = rockchip_saradc_channel_data_v1,
Quentin Schulzd0aaaae2024-03-14 10:36:22 +0100336 .start_channel = rockchip_saradc_start_channel_v1,
Quentin Schulze8e0aae2024-03-14 10:36:23 +0100337 .stop = rockchip_saradc_stop_v1,
David Wuf8d5bc72017-09-20 14:28:16 +0800338};
339
Quentin Schulz5df8ac42024-03-14 10:36:24 +0100340static const struct rockchip_saradc_data rk3588_saradc_data = {
341 .num_bits = 12,
342 .num_channels = 8,
343 .clk_rate = 1000000,
344 .channel_data = rockchip_saradc_channel_data_v2,
345 .start_channel = rockchip_saradc_start_channel_v2,
346};
347
David Wuf8d5bc72017-09-20 14:28:16 +0800348static const struct udevice_id rockchip_saradc_ids[] = {
349 { .compatible = "rockchip,saradc",
350 .data = (ulong)&saradc_data },
351 { .compatible = "rockchip,rk3066-tsadc",
352 .data = (ulong)&rk3066_tsadc_data },
353 { .compatible = "rockchip,rk3399-saradc",
354 .data = (ulong)&rk3399_saradc_data },
Quentin Schulz5df8ac42024-03-14 10:36:24 +0100355 { .compatible = "rockchip,rk3588-saradc",
356 .data = (ulong)&rk3588_saradc_data },
David Wuf8d5bc72017-09-20 14:28:16 +0800357 { }
358};
359
360U_BOOT_DRIVER(rockchip_saradc) = {
361 .name = "rockchip_saradc",
362 .id = UCLASS_ADC,
363 .of_match = rockchip_saradc_ids,
364 .ops = &rockchip_saradc_ops,
365 .probe = rockchip_saradc_probe,
Simon Glassaad29ae2020-12-03 16:55:21 -0700366 .of_to_plat = rockchip_saradc_of_to_plat,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700367 .priv_auto = sizeof(struct rockchip_saradc_priv),
David Wuf8d5bc72017-09-20 14:28:16 +0800368};