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 
rockchip_saradc_channel_data(struct udevice * dev,int channel,unsigned int * data)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 
rockchip_saradc_start_channel(struct udevice * dev,int channel)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 
rockchip_saradc_stop(struct udevice * dev)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 
rockchip_saradc_probe(struct udevice * dev)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 
rockchip_saradc_of_to_plat(struct udevice * dev)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 = dev_read_addr_ptr(dev);
149 	if (!priv->regs) {
150 		pr_err("Dev: %s - can't get address!", dev->name);
151 		return -EINVAL;
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 };
206