adc: meson-saradc: add AXG variant
[platform/kernel/u-boot.git] / drivers / adc / rockchip-saradc.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2017, Fuzhou Rockchip Electronics Co., Ltd
4  *
5  * 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>
14 #include <linux/bitops.h>
15 #include <linux/err.h>
16 #include <power/regulator.h>
17
18 #define SARADC_CTRL_CHN_MASK            GENMASK(2, 0)
19 #define SARADC_CTRL_POWER_CTRL          BIT(3)
20 #define SARADC_CTRL_IRQ_ENABLE          BIT(5)
21 #define SARADC_CTRL_IRQ_STATUS          BIT(6)
22
23 #define SARADC_TIMEOUT                  (100 * 1000)
24
25 struct rockchip_saradc_regs {
26         unsigned int data;
27         unsigned int stas;
28         unsigned int ctrl;
29         unsigned int dly_pu_soc;
30 };
31
32 struct rockchip_saradc_data {
33         int                             num_bits;
34         int                             num_channels;
35         unsigned long                   clk_rate;
36 };
37
38 struct rockchip_saradc_priv {
39         struct rockchip_saradc_regs             *regs;
40         int                                     active_channel;
41         const struct rockchip_saradc_data       *data;
42 };
43
44 int rockchip_saradc_channel_data(struct udevice *dev, int channel,
45                                  unsigned int *data)
46 {
47         struct rockchip_saradc_priv *priv = dev_get_priv(dev);
48         struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
49
50         if (channel != priv->active_channel) {
51                 pr_err("Requested channel is not active!");
52                 return -EINVAL;
53         }
54
55         if ((readl(&priv->regs->ctrl) & SARADC_CTRL_IRQ_STATUS) !=
56             SARADC_CTRL_IRQ_STATUS)
57                 return -EBUSY;
58
59         /* Read value */
60         *data = readl(&priv->regs->data);
61         *data &= uc_pdata->data_mask;
62
63         /* Power down adc */
64         writel(0, &priv->regs->ctrl);
65
66         return 0;
67 }
68
69 int rockchip_saradc_start_channel(struct udevice *dev, int channel)
70 {
71         struct rockchip_saradc_priv *priv = dev_get_priv(dev);
72
73         if (channel < 0 || channel >= priv->data->num_channels) {
74                 pr_err("Requested channel is invalid!");
75                 return -EINVAL;
76         }
77
78         /* 8 clock periods as delay between power up and start cmd */
79         writel(8, &priv->regs->dly_pu_soc);
80
81         /* Select the channel to be used and trigger conversion */
82         writel(SARADC_CTRL_POWER_CTRL | (channel & SARADC_CTRL_CHN_MASK) |
83                SARADC_CTRL_IRQ_ENABLE, &priv->regs->ctrl);
84
85         priv->active_channel = channel;
86
87         return 0;
88 }
89
90 int rockchip_saradc_stop(struct udevice *dev)
91 {
92         struct rockchip_saradc_priv *priv = dev_get_priv(dev);
93
94         /* Power down adc */
95         writel(0, &priv->regs->ctrl);
96
97         priv->active_channel = -1;
98
99         return 0;
100 }
101
102 int rockchip_saradc_probe(struct udevice *dev)
103 {
104         struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
105         struct rockchip_saradc_priv *priv = dev_get_priv(dev);
106         struct udevice *vref;
107         struct clk clk;
108         int vref_uv;
109         int ret;
110
111         ret = clk_get_by_index(dev, 0, &clk);
112         if (ret)
113                 return ret;
114
115         ret = clk_set_rate(&clk, priv->data->clk_rate);
116         if (IS_ERR_VALUE(ret))
117                 return ret;
118
119         priv->active_channel = -1;
120
121         ret = device_get_supply_regulator(dev, "vref-supply", &vref);
122         if (ret) {
123                 printf("can't get vref-supply: %d\n", ret);
124                 return ret;
125         }
126
127         vref_uv = regulator_get_value(vref);
128         if (vref_uv < 0) {
129                 printf("can't get vref-supply value: %d\n", vref_uv);
130                 return vref_uv;
131         }
132
133         /* VDD supplied by common vref pin */
134         uc_pdata->vdd_supply = vref;
135         uc_pdata->vdd_microvolts = vref_uv;
136         uc_pdata->vss_microvolts = 0;
137
138         return 0;
139 }
140
141 int rockchip_saradc_of_to_plat(struct udevice *dev)
142 {
143         struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
144         struct rockchip_saradc_priv *priv = dev_get_priv(dev);
145         struct rockchip_saradc_data *data;
146
147         data = (struct rockchip_saradc_data *)dev_get_driver_data(dev);
148         priv->regs = (struct rockchip_saradc_regs *)dev_read_addr(dev);
149         if (priv->regs == (struct rockchip_saradc_regs *)FDT_ADDR_T_NONE) {
150                 pr_err("Dev: %s - can't get address!", dev->name);
151                 return -ENODATA;
152         }
153
154         priv->data = data;
155         uc_pdata->data_mask = (1 << priv->data->num_bits) - 1;
156         uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
157         uc_pdata->data_timeout_us = SARADC_TIMEOUT / 5;
158         uc_pdata->channel_mask = (1 << priv->data->num_channels) - 1;
159
160         return 0;
161 }
162
163 static const struct adc_ops rockchip_saradc_ops = {
164         .start_channel = rockchip_saradc_start_channel,
165         .channel_data = rockchip_saradc_channel_data,
166         .stop = rockchip_saradc_stop,
167 };
168
169 static const struct rockchip_saradc_data saradc_data = {
170         .num_bits = 10,
171         .num_channels = 3,
172         .clk_rate = 1000000,
173 };
174
175 static const struct rockchip_saradc_data rk3066_tsadc_data = {
176         .num_bits = 12,
177         .num_channels = 2,
178         .clk_rate = 50000,
179 };
180
181 static const struct rockchip_saradc_data rk3399_saradc_data = {
182         .num_bits = 10,
183         .num_channels = 6,
184         .clk_rate = 1000000,
185 };
186
187 static const struct udevice_id rockchip_saradc_ids[] = {
188         { .compatible = "rockchip,saradc",
189           .data = (ulong)&saradc_data },
190         { .compatible = "rockchip,rk3066-tsadc",
191           .data = (ulong)&rk3066_tsadc_data },
192         { .compatible = "rockchip,rk3399-saradc",
193           .data = (ulong)&rk3399_saradc_data },
194         { }
195 };
196
197 U_BOOT_DRIVER(rockchip_saradc) = {
198         .name           = "rockchip_saradc",
199         .id             = UCLASS_ADC,
200         .of_match       = rockchip_saradc_ids,
201         .ops            = &rockchip_saradc_ops,
202         .probe          = rockchip_saradc_probe,
203         .of_to_plat = rockchip_saradc_of_to_plat,
204         .priv_auto      = sizeof(struct rockchip_saradc_priv),
205 };