blob: 03caca78b5f2fb3b09138b40cec9d91c2a063537 [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>
13#include <asm/io.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060014#include <linux/bitops.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070015#include <linux/err.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060016#include <linux/printk.h>
Peter Cai14f3e382022-02-04 15:16:06 -050017#include <power/regulator.h>
David Wuf8d5bc72017-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
26struct rockchip_saradc_regs {
27 unsigned int data;
28 unsigned int stas;
29 unsigned int ctrl;
30 unsigned int dly_pu_soc;
31};
32
33struct rockchip_saradc_data {
34 int num_bits;
35 int num_channels;
36 unsigned long clk_rate;
37};
38
39struct rockchip_saradc_priv {
40 struct rockchip_saradc_regs *regs;
41 int active_channel;
42 const struct rockchip_saradc_data *data;
43};
44
45int rockchip_saradc_channel_data(struct udevice *dev, int channel,
46 unsigned int *data)
47{
48 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
Simon Glass71fa5b42020-12-03 16:55:18 -070049 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
David Wuf8d5bc72017-09-20 14:28:16 +080050
51 if (channel != priv->active_channel) {
Masahiro Yamada81e10422017-09-16 14:10:41 +090052 pr_err("Requested channel is not active!");
David Wuf8d5bc72017-09-20 14:28:16 +080053 return -EINVAL;
54 }
55
56 if ((readl(&priv->regs->ctrl) & SARADC_CTRL_IRQ_STATUS) !=
57 SARADC_CTRL_IRQ_STATUS)
58 return -EBUSY;
59
60 /* Read value */
61 *data = readl(&priv->regs->data);
62 *data &= uc_pdata->data_mask;
63
64 /* Power down adc */
65 writel(0, &priv->regs->ctrl);
66
67 return 0;
68}
69
70int rockchip_saradc_start_channel(struct udevice *dev, int channel)
71{
72 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
73
74 if (channel < 0 || channel >= priv->data->num_channels) {
Masahiro Yamada81e10422017-09-16 14:10:41 +090075 pr_err("Requested channel is invalid!");
David Wuf8d5bc72017-09-20 14:28:16 +080076 return -EINVAL;
77 }
78
79 /* 8 clock periods as delay between power up and start cmd */
80 writel(8, &priv->regs->dly_pu_soc);
81
82 /* Select the channel to be used and trigger conversion */
83 writel(SARADC_CTRL_POWER_CTRL | (channel & SARADC_CTRL_CHN_MASK) |
84 SARADC_CTRL_IRQ_ENABLE, &priv->regs->ctrl);
85
86 priv->active_channel = channel;
87
88 return 0;
89}
90
91int rockchip_saradc_stop(struct udevice *dev)
92{
93 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
94
95 /* Power down adc */
96 writel(0, &priv->regs->ctrl);
97
98 priv->active_channel = -1;
99
100 return 0;
101}
102
103int rockchip_saradc_probe(struct udevice *dev)
104{
Peter Cai14f3e382022-02-04 15:16:06 -0500105 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
David Wuf8d5bc72017-09-20 14:28:16 +0800106 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
Peter Cai14f3e382022-02-04 15:16:06 -0500107 struct udevice *vref;
David Wuf8d5bc72017-09-20 14:28:16 +0800108 struct clk clk;
Peter Cai14f3e382022-02-04 15:16:06 -0500109 int vref_uv;
David Wuf8d5bc72017-09-20 14:28:16 +0800110 int ret;
111
112 ret = clk_get_by_index(dev, 0, &clk);
113 if (ret)
114 return ret;
115
116 ret = clk_set_rate(&clk, priv->data->clk_rate);
117 if (IS_ERR_VALUE(ret))
118 return ret;
119
120 priv->active_channel = -1;
121
Peter Cai14f3e382022-02-04 15:16:06 -0500122 ret = device_get_supply_regulator(dev, "vref-supply", &vref);
123 if (ret) {
124 printf("can't get vref-supply: %d\n", ret);
125 return ret;
126 }
127
128 vref_uv = regulator_get_value(vref);
129 if (vref_uv < 0) {
130 printf("can't get vref-supply value: %d\n", vref_uv);
131 return vref_uv;
132 }
133
134 /* VDD supplied by common vref pin */
135 uc_pdata->vdd_supply = vref;
136 uc_pdata->vdd_microvolts = vref_uv;
137 uc_pdata->vss_microvolts = 0;
138
David Wuf8d5bc72017-09-20 14:28:16 +0800139 return 0;
140}
141
Simon Glassaad29ae2020-12-03 16:55:21 -0700142int rockchip_saradc_of_to_plat(struct udevice *dev)
David Wuf8d5bc72017-09-20 14:28:16 +0800143{
Simon Glass71fa5b42020-12-03 16:55:18 -0700144 struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
David Wuf8d5bc72017-09-20 14:28:16 +0800145 struct rockchip_saradc_priv *priv = dev_get_priv(dev);
146 struct rockchip_saradc_data *data;
147
148 data = (struct rockchip_saradc_data *)dev_get_driver_data(dev);
Johan Jonkerb415d0e2023-03-13 01:29:35 +0100149 priv->regs = dev_read_addr_ptr(dev);
150 if (!priv->regs) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900151 pr_err("Dev: %s - can't get address!", dev->name);
Johan Jonkerb415d0e2023-03-13 01:29:35 +0100152 return -EINVAL;
David Wuf8d5bc72017-09-20 14:28:16 +0800153 }
154
155 priv->data = data;
Giulio Benetti33ecda02022-03-14 10:09:43 +0100156 uc_pdata->data_mask = (1 << priv->data->num_bits) - 1;
David Wuf8d5bc72017-09-20 14:28:16 +0800157 uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
158 uc_pdata->data_timeout_us = SARADC_TIMEOUT / 5;
159 uc_pdata->channel_mask = (1 << priv->data->num_channels) - 1;
160
161 return 0;
162}
163
164static const struct adc_ops rockchip_saradc_ops = {
165 .start_channel = rockchip_saradc_start_channel,
166 .channel_data = rockchip_saradc_channel_data,
167 .stop = rockchip_saradc_stop,
168};
169
170static const struct rockchip_saradc_data saradc_data = {
171 .num_bits = 10,
172 .num_channels = 3,
173 .clk_rate = 1000000,
174};
175
176static const struct rockchip_saradc_data rk3066_tsadc_data = {
177 .num_bits = 12,
178 .num_channels = 2,
179 .clk_rate = 50000,
180};
181
182static const struct rockchip_saradc_data rk3399_saradc_data = {
183 .num_bits = 10,
184 .num_channels = 6,
185 .clk_rate = 1000000,
186};
187
188static const struct udevice_id rockchip_saradc_ids[] = {
189 { .compatible = "rockchip,saradc",
190 .data = (ulong)&saradc_data },
191 { .compatible = "rockchip,rk3066-tsadc",
192 .data = (ulong)&rk3066_tsadc_data },
193 { .compatible = "rockchip,rk3399-saradc",
194 .data = (ulong)&rk3399_saradc_data },
195 { }
196};
197
198U_BOOT_DRIVER(rockchip_saradc) = {
199 .name = "rockchip_saradc",
200 .id = UCLASS_ADC,
201 .of_match = rockchip_saradc_ids,
202 .ops = &rockchip_saradc_ops,
203 .probe = rockchip_saradc_probe,
Simon Glassaad29ae2020-12-03 16:55:21 -0700204 .of_to_plat = rockchip_saradc_of_to_plat,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700205 .priv_auto = sizeof(struct rockchip_saradc_priv),
David Wuf8d5bc72017-09-20 14:28:16 +0800206};