xref: /rk3399_rockchip-uboot/drivers/adc/rockchip-saradc-v2.c (revision 9244b456d2f8eff40a98343b90954cf2ff818792)
148111c22SSimon Xue // SPDX-License-Identifier:     GPL-2.0+
248111c22SSimon Xue /*
348111c22SSimon Xue  * (C) Copyright 2021, Rockchip Electronics Co., Ltd
448111c22SSimon Xue  *
548111c22SSimon Xue  * Rockchip SARADC driver for U-Boot
648111c22SSimon Xue  */
748111c22SSimon Xue 
848111c22SSimon Xue #include <common.h>
948111c22SSimon Xue #include <adc.h>
1048111c22SSimon Xue #include <clk.h>
1148111c22SSimon Xue #include <dm.h>
123c7e7319SXuhui Lin #include <linux/iopoll.h>
1348111c22SSimon Xue #include <errno.h>
1448111c22SSimon Xue #include <asm/io.h>
157777fe4eSJoseph Chen #include <reset.h>
1648111c22SSimon Xue 
1748111c22SSimon Xue #define SARADC2_EN_END_INT		BIT(0)
1848111c22SSimon Xue #define SARADC2_START			BIT(4)
1948111c22SSimon Xue #define SARADC2_SINGLE_MODE		BIT(5)
2048111c22SSimon Xue 
2148111c22SSimon Xue #define SARADC_TIMEOUT			(100 * 1000)
2248111c22SSimon Xue 
2348111c22SSimon Xue struct rockchip_saradc_regs {
2448111c22SSimon Xue 	u32 conv_con;
2548111c22SSimon Xue 	u32 t_pd_soc;
2648111c22SSimon Xue 	u32 t_as_soc;
2748111c22SSimon Xue 	u32 t_das_soc;
2848111c22SSimon Xue 	u32 t_sel_soc;
2948111c22SSimon Xue 	u32 high_comp0;
3048111c22SSimon Xue 	u32 high_comp1;
3148111c22SSimon Xue 	u32 high_comp2;
3248111c22SSimon Xue 	u32 high_comp3;
3348111c22SSimon Xue 	u32 high_comp4;
3448111c22SSimon Xue 	u32 high_comp5;
3548111c22SSimon Xue 	u32 reserved0044;
3648111c22SSimon Xue 	u32 high_comp7;
3748111c22SSimon Xue 	u32 high_comp8;
3848111c22SSimon Xue 	u32 high_comp9;
3948111c22SSimon Xue 	u32 high_comp10;
4048111c22SSimon Xue 	u32 high_comp11;
4148111c22SSimon Xue 	u32 high_comp12;
4248111c22SSimon Xue 	u32 high_comp13;
4348111c22SSimon Xue 	u32 high_comp14;
4448111c22SSimon Xue 	u32 high_comp15;
4548111c22SSimon Xue 	u32 low_comp0;
4648111c22SSimon Xue 	u32 low_comp1;
4748111c22SSimon Xue 	u32 low_comp2;
4848111c22SSimon Xue 	u32 low_comp3;
4948111c22SSimon Xue 	u32 low_comp4;
5048111c22SSimon Xue 	u32 low_comp5;
5148111c22SSimon Xue 	u32 low_comp6;
5248111c22SSimon Xue 	u32 low_comp7;
5348111c22SSimon Xue 	u32 low_comp8;
5448111c22SSimon Xue 	u32 low_comp9;
5548111c22SSimon Xue 	u32 low_comp10;
5648111c22SSimon Xue 	u32 low_comp11;
5748111c22SSimon Xue 	u32 low_comp12;
5848111c22SSimon Xue 	u32 low_comp13;
5948111c22SSimon Xue 	u32 low_comp14;
6048111c22SSimon Xue 	u32 low_comp15;
6148111c22SSimon Xue 	u32 debounce;
6248111c22SSimon Xue 	u32 ht_int_en;
6348111c22SSimon Xue 	u32 lt_int_en;
6448111c22SSimon Xue 	u32 reserved0160[24];
6548111c22SSimon Xue 	u32 mt_int_en;
6648111c22SSimon Xue 	u32 end_int_en;
6748111c22SSimon Xue 	u32 st_con;
6848111c22SSimon Xue 	u32 status;
6948111c22SSimon Xue 	u32 end_int_st;
7048111c22SSimon Xue 	u32 ht_int_st;
7148111c22SSimon Xue 	u32 lt_int_st;
7248111c22SSimon Xue 	u32 mt_int_st;
7348111c22SSimon Xue 	u32 data0;
7448111c22SSimon Xue 	u32 data1;
7548111c22SSimon Xue 	u32 data2;
7648111c22SSimon Xue 	u32 data3;
7748111c22SSimon Xue 	u32 data4;
7848111c22SSimon Xue 	u32 data5;
7948111c22SSimon Xue 	u32 data6;
8048111c22SSimon Xue 	u32 data7;
8148111c22SSimon Xue 	u32 data8;
8248111c22SSimon Xue 	u32 data9;
8348111c22SSimon Xue 	u32 data10;
8448111c22SSimon Xue 	u32 data11;
8548111c22SSimon Xue 	u32 data12;
8648111c22SSimon Xue 	u32 data13;
8748111c22SSimon Xue 	u32 data14;
8848111c22SSimon Xue 	u32 data15;
8948111c22SSimon Xue 	u32 auto_ch_en;
9048111c22SSimon Xue };
9148111c22SSimon Xue 
9248111c22SSimon Xue struct rockchip_saradc_data {
9348111c22SSimon Xue 	int				num_bits;
9448111c22SSimon Xue 	int				num_channels;
9548111c22SSimon Xue 	unsigned long			clk_rate;
96*9244b456SSimon Xue 	int				das_soc_data;
9748111c22SSimon Xue };
9848111c22SSimon Xue 
9948111c22SSimon Xue struct rockchip_saradc_priv {
10048111c22SSimon Xue 	struct rockchip_saradc_regs		*regs;
10148111c22SSimon Xue 	int					active_channel;
10248111c22SSimon Xue 	const struct rockchip_saradc_data	*data;
1037777fe4eSJoseph Chen 	struct reset_ctl			rst;
10448111c22SSimon Xue };
10548111c22SSimon Xue 
rockchip_saradc_channel_data(struct udevice * dev,int channel,unsigned int * data)10648111c22SSimon Xue static int rockchip_saradc_channel_data(struct udevice *dev, int channel,
10748111c22SSimon Xue 					unsigned int *data)
10848111c22SSimon Xue {
10948111c22SSimon Xue 	struct rockchip_saradc_priv *priv = dev_get_priv(dev);
11048111c22SSimon Xue 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
1113c7e7319SXuhui Lin 	u32 status;
11248111c22SSimon Xue 
11348111c22SSimon Xue 	if (channel != priv->active_channel) {
11448111c22SSimon Xue 		pr_err("Requested channel is not active!");
11548111c22SSimon Xue 		return -EINVAL;
11648111c22SSimon Xue 	}
11748111c22SSimon Xue 
1183c7e7319SXuhui Lin 	/* Wait for end conversion interrupt status. */
1193c7e7319SXuhui Lin 	if (readl_poll_timeout(&priv->regs->end_int_st, status,
1203c7e7319SXuhui Lin 			       status & SARADC2_EN_END_INT, SARADC_TIMEOUT)) {
1213c7e7319SXuhui Lin 		pr_err("Wait for end conversion interrupt status timeout!\n");
1223c7e7319SXuhui Lin 		return -ETIMEDOUT;
1233c7e7319SXuhui Lin 	}
1243c7e7319SXuhui Lin 
1253c7e7319SXuhui Lin 	/* Clear irq. */
1267777fe4eSJoseph Chen 	writel(0x1, &priv->regs->end_int_st);
12748111c22SSimon Xue 
1287777fe4eSJoseph Chen 	*data = readl(&priv->regs->data0 + priv->active_channel);
12948111c22SSimon Xue 	*data &= uc_pdata->data_mask;
13048111c22SSimon Xue 
13148111c22SSimon Xue 	return 0;
13248111c22SSimon Xue }
13348111c22SSimon Xue 
rockchip_saradc_start_channel(struct udevice * dev,int channel)13448111c22SSimon Xue static int rockchip_saradc_start_channel(struct udevice *dev, int channel)
13548111c22SSimon Xue {
13648111c22SSimon Xue 	struct rockchip_saradc_priv *priv = dev_get_priv(dev);
13748111c22SSimon Xue 	int val;
13848111c22SSimon Xue 
13948111c22SSimon Xue 	if (channel < 0 || channel >= priv->data->num_channels) {
14048111c22SSimon Xue 		pr_err("Requested channel is invalid!");
14148111c22SSimon Xue 		return -EINVAL;
14248111c22SSimon Xue 	}
14348111c22SSimon Xue 
1447777fe4eSJoseph Chen #if CONFIG_IS_ENABLED(DM_RESET)
1457777fe4eSJoseph Chen 	reset_assert(&priv->rst);
1467777fe4eSJoseph Chen 	udelay(10);
1477777fe4eSJoseph Chen 	reset_deassert(&priv->rst);
1487777fe4eSJoseph Chen #endif
1497777fe4eSJoseph Chen 	writel(0x20, &priv->regs->t_pd_soc);
150*9244b456SSimon Xue 	if (priv->data->das_soc_data)
151*9244b456SSimon Xue 		writel(priv->data->das_soc_data, &priv->regs->t_das_soc);
152*9244b456SSimon Xue 	else
1537777fe4eSJoseph Chen 		writel(0xc, &priv->regs->t_das_soc);
15448111c22SSimon Xue 	val = SARADC2_EN_END_INT << 16 | SARADC2_EN_END_INT;
1557777fe4eSJoseph Chen 	writel(val, &priv->regs->end_int_en);
15648111c22SSimon Xue 	val = SARADC2_START | SARADC2_SINGLE_MODE | channel;
1577777fe4eSJoseph Chen 	writel(val << 16 | val, &priv->regs->conv_con);
1587777fe4eSJoseph Chen 
1597777fe4eSJoseph Chen 	udelay(100);
16048111c22SSimon Xue 
16148111c22SSimon Xue 	priv->active_channel = channel;
16248111c22SSimon Xue 
16348111c22SSimon Xue 	return 0;
16448111c22SSimon Xue }
16548111c22SSimon Xue 
rockchip_saradc_stop(struct udevice * dev)16648111c22SSimon Xue static int rockchip_saradc_stop(struct udevice *dev)
16748111c22SSimon Xue {
16848111c22SSimon Xue 	struct rockchip_saradc_priv *priv = dev_get_priv(dev);
16948111c22SSimon Xue 
17048111c22SSimon Xue 	priv->active_channel = -1;
17148111c22SSimon Xue 
17248111c22SSimon Xue 	return 0;
17348111c22SSimon Xue }
17448111c22SSimon Xue 
rockchip_saradc_probe(struct udevice * dev)17548111c22SSimon Xue static int rockchip_saradc_probe(struct udevice *dev)
17648111c22SSimon Xue {
17748111c22SSimon Xue 	struct rockchip_saradc_priv *priv = dev_get_priv(dev);
17848111c22SSimon Xue 	struct clk clk;
17948111c22SSimon Xue 	int ret;
18048111c22SSimon Xue 
1817777fe4eSJoseph Chen #if CONFIG_IS_ENABLED(DM_RESET)
1827777fe4eSJoseph Chen 	ret = reset_get_by_name(dev, "saradc-apb", &priv->rst);
1837777fe4eSJoseph Chen 	if (ret) {
1847777fe4eSJoseph Chen 		debug("reset_get_by_name() failed: %d\n", ret);
1857777fe4eSJoseph Chen 		return ret;
1867777fe4eSJoseph Chen 	}
1877777fe4eSJoseph Chen #endif
1887777fe4eSJoseph Chen 
18948111c22SSimon Xue 	ret = clk_get_by_index(dev, 0, &clk);
19048111c22SSimon Xue 	if (ret)
19148111c22SSimon Xue 		return ret;
19248111c22SSimon Xue 
19348111c22SSimon Xue 	ret = clk_set_rate(&clk, priv->data->clk_rate);
19448111c22SSimon Xue 	if (IS_ERR_VALUE(ret))
19548111c22SSimon Xue 		return ret;
19648111c22SSimon Xue 
197ec5f0a7cSSimon Xue 	/* Wait until pll stable */
198ec5f0a7cSSimon Xue 	mdelay(5);
199ec5f0a7cSSimon Xue 
20048111c22SSimon Xue 	priv->active_channel = -1;
20148111c22SSimon Xue 
20248111c22SSimon Xue 	return 0;
20348111c22SSimon Xue }
20448111c22SSimon Xue 
rockchip_saradc_ofdata_to_platdata(struct udevice * dev)20548111c22SSimon Xue static int rockchip_saradc_ofdata_to_platdata(struct udevice *dev)
20648111c22SSimon Xue {
20748111c22SSimon Xue 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
20848111c22SSimon Xue 	struct rockchip_saradc_priv *priv = dev_get_priv(dev);
20948111c22SSimon Xue 	struct rockchip_saradc_data *data;
21048111c22SSimon Xue 
21148111c22SSimon Xue 	data = (struct rockchip_saradc_data *)dev_get_driver_data(dev);
21248111c22SSimon Xue 	priv->regs = (struct rockchip_saradc_regs *)dev_read_addr(dev);
21348111c22SSimon Xue 	if (priv->regs == (struct rockchip_saradc_regs *)FDT_ADDR_T_NONE) {
21448111c22SSimon Xue 		pr_err("Dev: %s - can't get address!", dev->name);
21548111c22SSimon Xue 		return -ENODATA;
21648111c22SSimon Xue 	}
21748111c22SSimon Xue 
21848111c22SSimon Xue 	priv->data = data;
21948111c22SSimon Xue 	uc_pdata->data_mask = (1 << priv->data->num_bits) - 1;
22048111c22SSimon Xue 	uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
22148111c22SSimon Xue 	uc_pdata->data_timeout_us = SARADC_TIMEOUT / 5;
22248111c22SSimon Xue 	uc_pdata->channel_mask = (1 << priv->data->num_channels) - 1;
22348111c22SSimon Xue 
22448111c22SSimon Xue 	return 0;
22548111c22SSimon Xue }
22648111c22SSimon Xue 
22748111c22SSimon Xue static const struct adc_ops rockchip_saradc_ops = {
22848111c22SSimon Xue 	.start_channel = rockchip_saradc_start_channel,
22948111c22SSimon Xue 	.channel_data = rockchip_saradc_channel_data,
23048111c22SSimon Xue 	.stop = rockchip_saradc_stop,
23148111c22SSimon Xue };
23248111c22SSimon Xue 
23348111c22SSimon Xue static const struct rockchip_saradc_data rk3588_saradc_data = {
23448111c22SSimon Xue 	.num_bits = 12,
23548111c22SSimon Xue 	.num_channels = 8,
23648111c22SSimon Xue 	.clk_rate = 1000000,
23748111c22SSimon Xue };
23848111c22SSimon Xue 
2397cd4e41dSSimon Xue static const struct rockchip_saradc_data rk3562_saradc_data = {
2407cd4e41dSSimon Xue 	.num_bits = 10,
2417cd4e41dSSimon Xue 	.num_channels = 8,
2427cd4e41dSSimon Xue 	.clk_rate = 1000000,
2437cd4e41dSSimon Xue };
2447cd4e41dSSimon Xue 
24541096139SXuhui Lin static const struct rockchip_saradc_data rv1106_saradc_data = {
246170e4649SSimon Xue 	.num_bits = 10,
247170e4649SSimon Xue 	.num_channels = 2,
248170e4649SSimon Xue 	.clk_rate = 1000000,
249170e4649SSimon Xue };
250170e4649SSimon Xue 
25141096139SXuhui Lin static const struct rockchip_saradc_data rv1103b_saradc_data = {
25241096139SXuhui Lin 	.num_bits = 10,
25341096139SXuhui Lin 	.num_channels = 1,
25441096139SXuhui Lin 	.clk_rate = 1000000,
25541096139SXuhui Lin };
25641096139SXuhui Lin 
257*9244b456SSimon Xue static const struct rockchip_saradc_data rv1126b_saradc_data = {
258*9244b456SSimon Xue 	.num_bits = 13,
259*9244b456SSimon Xue 	.num_channels = 8,
260*9244b456SSimon Xue 	.clk_rate = 24000000,
261*9244b456SSimon Xue 	.das_soc_data = 0x14,
262*9244b456SSimon Xue };
263*9244b456SSimon Xue 
26448111c22SSimon Xue static const struct udevice_id rockchip_saradc_ids[] = {
26527354a5cSJoseph Chen 	{
26627354a5cSJoseph Chen 		.compatible = "rockchip,rk3588-saradc",
26727354a5cSJoseph Chen 		.data = (ulong)&rk3588_saradc_data
26827354a5cSJoseph Chen 	},
26927354a5cSJoseph Chen 	{
27027354a5cSJoseph Chen 		.compatible = "rockchip,rk3528-saradc",
27127354a5cSJoseph Chen 		.data = (ulong)&rk3588_saradc_data
27227354a5cSJoseph Chen 	},
2737cd4e41dSSimon Xue 	{
2747cd4e41dSSimon Xue 		.compatible = "rockchip,rk3562-saradc",
2757cd4e41dSSimon Xue 		.data = (ulong)&rk3562_saradc_data
2767cd4e41dSSimon Xue 	},
277170e4649SSimon Xue 	{
278170e4649SSimon Xue 		.compatible = "rockchip,rv1106-saradc",
27941096139SXuhui Lin 		.data = (ulong)&rv1106_saradc_data
28041096139SXuhui Lin 	},
28141096139SXuhui Lin 	{
28241096139SXuhui Lin 		.compatible = "rockchip,rv1103b-saradc",
28341096139SXuhui Lin 		.data = (ulong)&rv1103b_saradc_data
284170e4649SSimon Xue 	},
285*9244b456SSimon Xue 	{
286*9244b456SSimon Xue 		.compatible = "rockchip,rv1126b-saradc",
287*9244b456SSimon Xue 		.data = (ulong)&rv1126b_saradc_data
288*9244b456SSimon Xue 	},
28948111c22SSimon Xue 	{ }
29048111c22SSimon Xue };
29148111c22SSimon Xue 
29248111c22SSimon Xue U_BOOT_DRIVER(rockchip_saradc_v2) = {
29348111c22SSimon Xue 	.name		= "rockchip_saradc_v2",
29448111c22SSimon Xue 	.id		= UCLASS_ADC,
29548111c22SSimon Xue 	.of_match	= rockchip_saradc_ids,
29648111c22SSimon Xue 	.ops		= &rockchip_saradc_ops,
29748111c22SSimon Xue 	.probe		= rockchip_saradc_probe,
29848111c22SSimon Xue 	.ofdata_to_platdata = rockchip_saradc_ofdata_to_platdata,
29948111c22SSimon Xue 	.priv_auto_alloc_size = sizeof(struct rockchip_saradc_priv),
30048111c22SSimon Xue };
301