blob: 607d10b5b709585ee2adcdec3490ba721a62b494 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
David Wuae3ed042017-09-20 14:28:16 +08002/*
3 * (C) Copyright 2017, Fuzhou Rockchip Electronics Co., Ltd
4 *
David Wuae3ed042017-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>
13#include <asm/io.h>
Simon Glasscd93d622020-05-10 11:40:13 -060014#include <linux/bitops.h>
Simon Glass61b29b82020-02-03 07:36:15 -070015#include <linux/err.h>
Simon Glass1e94b462023-09-14 18:21:46 -060016#include <linux/printk.h>
Peter Caie9632282022-02-04 15:16:06 -050017#include <power/regulator.h>
David Wuae3ed042017-09-20 14:28:16 +080018
19#define SARADC_CTRL_CHN_MASK GENMASK(2, 0)
20#define SARADC_CTRL_POWER_CTRL BIT(3)
21#define SARADC_CTRL_IRQ_ENABLE BIT(5)
22#define SARADC_CTRL_IRQ_STATUS BIT(6)
23
24#define SARADC_TIMEOUT (100 * 1000)
25
Quentin Schulz0707bfd2024-03-14 10:36:20 +010026struct rockchip_saradc_regs_v1 {
David Wuae3ed042017-09-20 14:28:16 +080027 unsigned int data;
28 unsigned int stas;
29 unsigned int ctrl;
30 unsigned int dly_pu_soc;
31};
32
Quentin Schulz0707bfd2024-03-14 10:36:20 +010033union rockchip_saradc_regs {
34 struct rockchip_saradc_regs_v1 *v1;
35};
David Wuae3ed042017-09-20 14:28:16 +080036struct rockchip_saradc_data {
37 int num_bits;
38 int num_channels;
39 unsigned long clk_rate;
Quentin Schulz7da30652024-03-14 10:36:21 +010040 int (*channel_data)(struct udevice *dev, int channel, unsigned int *data);
Quentin Schulz25775252024-03-14 10:36:22 +010041 int (*start_channel)(struct udevice *dev, int channel);
David Wuae3ed042017-09-20 14:28:16 +080042};
43
44struct rockchip_saradc_priv {
Quentin Schulz0707bfd2024-03-14 10:36:20 +010045 union rockchip_saradc_regs regs;
David Wuae3ed042017-09-20 14:28:16 +080046 int active_channel;
47 const struct rockchip_saradc_data *data;
48};
49
Quentin Schulz7da30652024-03-14 10:36:21 +010050int rockchip_saradc_channel_data_v1(struct udevice *dev, int channel,
51 unsigned int *data)
David Wuae3ed042017-09-20 14:28:16 +080052{
53 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
David Wuae3ed042017-09-20 14:28:16 +080054
Quentin Schulz0707bfd2024-03-14 10:36:20 +010055 if ((readl(&priv->regs.v1->ctrl) & SARADC_CTRL_IRQ_STATUS) !=
David Wuae3ed042017-09-20 14:28:16 +080056 SARADC_CTRL_IRQ_STATUS)
57 return -EBUSY;
58
59 /* Read value */
Quentin Schulz0707bfd2024-03-14 10:36:20 +010060 *data = readl(&priv->regs.v1->data);
David Wuae3ed042017-09-20 14:28:16 +080061
62 /* Power down adc */
Quentin Schulz0707bfd2024-03-14 10:36:20 +010063 writel(0, &priv->regs.v1->ctrl);
David Wuae3ed042017-09-20 14:28:16 +080064
65 return 0;
66}
67
Quentin Schulz7da30652024-03-14 10:36:21 +010068int rockchip_saradc_channel_data(struct udevice *dev, int channel,
69 unsigned int *data)
70{
71 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
72 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
73 int ret;
74
75 if (channel != priv->active_channel) {
76 pr_err("Requested channel is not active!");
77 return -EINVAL;
78 }
79
80 ret = priv->data->channel_data(dev, channel, data);
81 if (ret) {
82 if (ret != -EBUSY)
83 pr_err("Error reading channel data, %d!", ret);
84 return ret;
85 }
86
87 *data &= uc_pdata->data_mask;
88
89 return 0;
90}
91
Quentin Schulz25775252024-03-14 10:36:22 +010092int rockchip_saradc_start_channel_v1(struct udevice *dev, int channel)
David Wuae3ed042017-09-20 14:28:16 +080093{
94 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
95
David Wuae3ed042017-09-20 14:28:16 +080096 /* 8 clock periods as delay between power up and start cmd */
Quentin Schulz0707bfd2024-03-14 10:36:20 +010097 writel(8, &priv->regs.v1->dly_pu_soc);
David Wuae3ed042017-09-20 14:28:16 +080098
99 /* Select the channel to be used and trigger conversion */
100 writel(SARADC_CTRL_POWER_CTRL | (channel & SARADC_CTRL_CHN_MASK) |
Quentin Schulz0707bfd2024-03-14 10:36:20 +0100101 SARADC_CTRL_IRQ_ENABLE, &priv->regs.v1->ctrl);
David Wuae3ed042017-09-20 14:28:16 +0800102
Quentin Schulz25775252024-03-14 10:36:22 +0100103 return 0;
104}
105
106int rockchip_saradc_start_channel(struct udevice *dev, int channel)
107{
108 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
109 int ret;
110
111 if (channel < 0 || channel >= priv->data->num_channels) {
112 pr_err("Requested channel is invalid!");
113 return -EINVAL;
114 }
115
116 ret = priv->data->start_channel(dev, channel);
117 if (ret) {
118 pr_err("Error starting channel, %d!", ret);
119 return ret;
120 }
121
David Wuae3ed042017-09-20 14:28:16 +0800122 priv->active_channel = channel;
123
124 return 0;
125}
126
127int rockchip_saradc_stop(struct udevice *dev)
128{
129 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
130
131 /* Power down adc */
Quentin Schulz0707bfd2024-03-14 10:36:20 +0100132 writel(0, &priv->regs.v1->ctrl);
David Wuae3ed042017-09-20 14:28:16 +0800133
134 priv->active_channel = -1;
135
136 return 0;
137}
138
139int rockchip_saradc_probe(struct udevice *dev)
140{
Peter Caie9632282022-02-04 15:16:06 -0500141 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
David Wuae3ed042017-09-20 14:28:16 +0800142 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
Peter Caie9632282022-02-04 15:16:06 -0500143 struct udevice *vref;
David Wuae3ed042017-09-20 14:28:16 +0800144 struct clk clk;
Peter Caie9632282022-02-04 15:16:06 -0500145 int vref_uv;
David Wuae3ed042017-09-20 14:28:16 +0800146 int ret;
147
148 ret = clk_get_by_index(dev, 0, &clk);
149 if (ret)
150 return ret;
151
152 ret = clk_set_rate(&clk, priv->data->clk_rate);
153 if (IS_ERR_VALUE(ret))
154 return ret;
155
156 priv->active_channel = -1;
157
Peter Caie9632282022-02-04 15:16:06 -0500158 ret = device_get_supply_regulator(dev, "vref-supply", &vref);
159 if (ret) {
160 printf("can't get vref-supply: %d\n", ret);
161 return ret;
162 }
163
164 vref_uv = regulator_get_value(vref);
165 if (vref_uv < 0) {
166 printf("can't get vref-supply value: %d\n", vref_uv);
167 return vref_uv;
168 }
169
170 /* VDD supplied by common vref pin */
171 uc_pdata->vdd_supply = vref;
172 uc_pdata->vdd_microvolts = vref_uv;
173 uc_pdata->vss_microvolts = 0;
174
David Wuae3ed042017-09-20 14:28:16 +0800175 return 0;
176}
177
Simon Glassd1998a92020-12-03 16:55:21 -0700178int rockchip_saradc_of_to_plat(struct udevice *dev)
David Wuae3ed042017-09-20 14:28:16 +0800179{
Simon Glasscaa4daa2020-12-03 16:55:18 -0700180 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
David Wuae3ed042017-09-20 14:28:16 +0800181 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
182 struct rockchip_saradc_data *data;
183
184 data = (struct rockchip_saradc_data *)dev_get_driver_data(dev);
Quentin Schulz0707bfd2024-03-14 10:36:20 +0100185 priv->regs.v1 = dev_read_addr_ptr(dev);
186 if (!priv->regs.v1) {
Masahiro Yamada9b643e32017-09-16 14:10:41 +0900187 pr_err("Dev: %s - can't get address!", dev->name);
Johan Jonkerac9198d2023-03-13 01:29:35 +0100188 return -EINVAL;
David Wuae3ed042017-09-20 14:28:16 +0800189 }
190
191 priv->data = data;
Giulio Benetti9acae542022-03-14 10:09:43 +0100192 uc_pdata->data_mask = (1 << priv->data->num_bits) - 1;
David Wuae3ed042017-09-20 14:28:16 +0800193 uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
194 uc_pdata->data_timeout_us = SARADC_TIMEOUT / 5;
195 uc_pdata->channel_mask = (1 << priv->data->num_channels) - 1;
196
197 return 0;
198}
199
200static const struct adc_ops rockchip_saradc_ops = {
201 .start_channel = rockchip_saradc_start_channel,
202 .channel_data = rockchip_saradc_channel_data,
203 .stop = rockchip_saradc_stop,
204};
205
206static const struct rockchip_saradc_data saradc_data = {
207 .num_bits = 10,
208 .num_channels = 3,
209 .clk_rate = 1000000,
Quentin Schulz7da30652024-03-14 10:36:21 +0100210 .channel_data = rockchip_saradc_channel_data_v1,
Quentin Schulz25775252024-03-14 10:36:22 +0100211 .start_channel = rockchip_saradc_start_channel_v1,
David Wuae3ed042017-09-20 14:28:16 +0800212};
213
214static const struct rockchip_saradc_data rk3066_tsadc_data = {
215 .num_bits = 12,
216 .num_channels = 2,
217 .clk_rate = 50000,
Quentin Schulz7da30652024-03-14 10:36:21 +0100218 .channel_data = rockchip_saradc_channel_data_v1,
Quentin Schulz25775252024-03-14 10:36:22 +0100219 .start_channel = rockchip_saradc_start_channel_v1,
David Wuae3ed042017-09-20 14:28:16 +0800220};
221
222static const struct rockchip_saradc_data rk3399_saradc_data = {
223 .num_bits = 10,
224 .num_channels = 6,
225 .clk_rate = 1000000,
Quentin Schulz7da30652024-03-14 10:36:21 +0100226 .channel_data = rockchip_saradc_channel_data_v1,
Quentin Schulz25775252024-03-14 10:36:22 +0100227 .start_channel = rockchip_saradc_start_channel_v1,
David Wuae3ed042017-09-20 14:28:16 +0800228};
229
230static const struct udevice_id rockchip_saradc_ids[] = {
231 { .compatible = "rockchip,saradc",
232 .data = (ulong)&saradc_data },
233 { .compatible = "rockchip,rk3066-tsadc",
234 .data = (ulong)&rk3066_tsadc_data },
235 { .compatible = "rockchip,rk3399-saradc",
236 .data = (ulong)&rk3399_saradc_data },
237 { }
238};
239
240U_BOOT_DRIVER(rockchip_saradc) = {
241 .name = "rockchip_saradc",
242 .id = UCLASS_ADC,
243 .of_match = rockchip_saradc_ids,
244 .ops = &rockchip_saradc_ops,
245 .probe = rockchip_saradc_probe,
Simon Glassd1998a92020-12-03 16:55:21 -0700246 .of_to_plat = rockchip_saradc_of_to_plat,
Simon Glass41575d82020-12-03 16:55:17 -0700247 .priv_auto = sizeof(struct rockchip_saradc_priv),
David Wuae3ed042017-09-20 14:28:16 +0800248};