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> 1248111c22SSimon Xue #include <errno.h> 1348111c22SSimon Xue #include <asm/io.h> 147777fe4eSJoseph Chen #include <reset.h> 1548111c22SSimon Xue 1648111c22SSimon Xue #define SARADC2_EN_END_INT BIT(0) 1748111c22SSimon Xue #define SARADC2_START BIT(4) 1848111c22SSimon Xue #define SARADC2_SINGLE_MODE BIT(5) 1948111c22SSimon Xue 2048111c22SSimon Xue #define SARADC_TIMEOUT (100 * 1000) 2148111c22SSimon Xue 2248111c22SSimon Xue struct rockchip_saradc_regs { 2348111c22SSimon Xue u32 conv_con; 2448111c22SSimon Xue u32 t_pd_soc; 2548111c22SSimon Xue u32 t_as_soc; 2648111c22SSimon Xue u32 t_das_soc; 2748111c22SSimon Xue u32 t_sel_soc; 2848111c22SSimon Xue u32 high_comp0; 2948111c22SSimon Xue u32 high_comp1; 3048111c22SSimon Xue u32 high_comp2; 3148111c22SSimon Xue u32 high_comp3; 3248111c22SSimon Xue u32 high_comp4; 3348111c22SSimon Xue u32 high_comp5; 3448111c22SSimon Xue u32 reserved0044; 3548111c22SSimon Xue u32 high_comp7; 3648111c22SSimon Xue u32 high_comp8; 3748111c22SSimon Xue u32 high_comp9; 3848111c22SSimon Xue u32 high_comp10; 3948111c22SSimon Xue u32 high_comp11; 4048111c22SSimon Xue u32 high_comp12; 4148111c22SSimon Xue u32 high_comp13; 4248111c22SSimon Xue u32 high_comp14; 4348111c22SSimon Xue u32 high_comp15; 4448111c22SSimon Xue u32 low_comp0; 4548111c22SSimon Xue u32 low_comp1; 4648111c22SSimon Xue u32 low_comp2; 4748111c22SSimon Xue u32 low_comp3; 4848111c22SSimon Xue u32 low_comp4; 4948111c22SSimon Xue u32 low_comp5; 5048111c22SSimon Xue u32 low_comp6; 5148111c22SSimon Xue u32 low_comp7; 5248111c22SSimon Xue u32 low_comp8; 5348111c22SSimon Xue u32 low_comp9; 5448111c22SSimon Xue u32 low_comp10; 5548111c22SSimon Xue u32 low_comp11; 5648111c22SSimon Xue u32 low_comp12; 5748111c22SSimon Xue u32 low_comp13; 5848111c22SSimon Xue u32 low_comp14; 5948111c22SSimon Xue u32 low_comp15; 6048111c22SSimon Xue u32 debounce; 6148111c22SSimon Xue u32 ht_int_en; 6248111c22SSimon Xue u32 lt_int_en; 6348111c22SSimon Xue u32 reserved0160[24]; 6448111c22SSimon Xue u32 mt_int_en; 6548111c22SSimon Xue u32 end_int_en; 6648111c22SSimon Xue u32 st_con; 6748111c22SSimon Xue u32 status; 6848111c22SSimon Xue u32 end_int_st; 6948111c22SSimon Xue u32 ht_int_st; 7048111c22SSimon Xue u32 lt_int_st; 7148111c22SSimon Xue u32 mt_int_st; 7248111c22SSimon Xue u32 data0; 7348111c22SSimon Xue u32 data1; 7448111c22SSimon Xue u32 data2; 7548111c22SSimon Xue u32 data3; 7648111c22SSimon Xue u32 data4; 7748111c22SSimon Xue u32 data5; 7848111c22SSimon Xue u32 data6; 7948111c22SSimon Xue u32 data7; 8048111c22SSimon Xue u32 data8; 8148111c22SSimon Xue u32 data9; 8248111c22SSimon Xue u32 data10; 8348111c22SSimon Xue u32 data11; 8448111c22SSimon Xue u32 data12; 8548111c22SSimon Xue u32 data13; 8648111c22SSimon Xue u32 data14; 8748111c22SSimon Xue u32 data15; 8848111c22SSimon Xue u32 auto_ch_en; 8948111c22SSimon Xue }; 9048111c22SSimon Xue 9148111c22SSimon Xue struct rockchip_saradc_data { 9248111c22SSimon Xue int num_bits; 9348111c22SSimon Xue int num_channels; 9448111c22SSimon Xue unsigned long clk_rate; 9548111c22SSimon Xue }; 9648111c22SSimon Xue 9748111c22SSimon Xue struct rockchip_saradc_priv { 9848111c22SSimon Xue struct rockchip_saradc_regs *regs; 9948111c22SSimon Xue int active_channel; 10048111c22SSimon Xue const struct rockchip_saradc_data *data; 1017777fe4eSJoseph Chen struct reset_ctl rst; 10248111c22SSimon Xue }; 10348111c22SSimon Xue 10448111c22SSimon Xue static int rockchip_saradc_channel_data(struct udevice *dev, int channel, 10548111c22SSimon Xue unsigned int *data) 10648111c22SSimon Xue { 10748111c22SSimon Xue struct rockchip_saradc_priv *priv = dev_get_priv(dev); 10848111c22SSimon Xue struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev); 10948111c22SSimon Xue 11048111c22SSimon Xue if (channel != priv->active_channel) { 11148111c22SSimon Xue pr_err("Requested channel is not active!"); 11248111c22SSimon Xue return -EINVAL; 11348111c22SSimon Xue } 11448111c22SSimon Xue 11548111c22SSimon Xue /* Clear irq */ 1167777fe4eSJoseph Chen writel(0x1, &priv->regs->end_int_st); 11748111c22SSimon Xue 1187777fe4eSJoseph Chen *data = readl(&priv->regs->data0 + priv->active_channel); 11948111c22SSimon Xue *data &= uc_pdata->data_mask; 12048111c22SSimon Xue 12148111c22SSimon Xue return 0; 12248111c22SSimon Xue } 12348111c22SSimon Xue 12448111c22SSimon Xue static int rockchip_saradc_start_channel(struct udevice *dev, int channel) 12548111c22SSimon Xue { 12648111c22SSimon Xue struct rockchip_saradc_priv *priv = dev_get_priv(dev); 12748111c22SSimon Xue int val; 12848111c22SSimon Xue 12948111c22SSimon Xue if (channel < 0 || channel >= priv->data->num_channels) { 13048111c22SSimon Xue pr_err("Requested channel is invalid!"); 13148111c22SSimon Xue return -EINVAL; 13248111c22SSimon Xue } 13348111c22SSimon Xue 1347777fe4eSJoseph Chen #if CONFIG_IS_ENABLED(DM_RESET) 1357777fe4eSJoseph Chen reset_assert(&priv->rst); 1367777fe4eSJoseph Chen udelay(10); 1377777fe4eSJoseph Chen reset_deassert(&priv->rst); 1387777fe4eSJoseph Chen #endif 1397777fe4eSJoseph Chen writel(0x20, &priv->regs->t_pd_soc); 1407777fe4eSJoseph Chen writel(0xc, &priv->regs->t_das_soc); 14148111c22SSimon Xue val = SARADC2_EN_END_INT << 16 | SARADC2_EN_END_INT; 1427777fe4eSJoseph Chen writel(val, &priv->regs->end_int_en); 14348111c22SSimon Xue val = SARADC2_START | SARADC2_SINGLE_MODE | channel; 1447777fe4eSJoseph Chen writel(val << 16 | val, &priv->regs->conv_con); 1457777fe4eSJoseph Chen 1467777fe4eSJoseph Chen udelay(100); 14748111c22SSimon Xue 14848111c22SSimon Xue priv->active_channel = channel; 14948111c22SSimon Xue 15048111c22SSimon Xue return 0; 15148111c22SSimon Xue } 15248111c22SSimon Xue 15348111c22SSimon Xue static int rockchip_saradc_stop(struct udevice *dev) 15448111c22SSimon Xue { 15548111c22SSimon Xue struct rockchip_saradc_priv *priv = dev_get_priv(dev); 15648111c22SSimon Xue 15748111c22SSimon Xue priv->active_channel = -1; 15848111c22SSimon Xue 15948111c22SSimon Xue return 0; 16048111c22SSimon Xue } 16148111c22SSimon Xue 16248111c22SSimon Xue static int rockchip_saradc_probe(struct udevice *dev) 16348111c22SSimon Xue { 16448111c22SSimon Xue struct rockchip_saradc_priv *priv = dev_get_priv(dev); 16548111c22SSimon Xue struct clk clk; 16648111c22SSimon Xue int ret; 16748111c22SSimon Xue 1687777fe4eSJoseph Chen #if CONFIG_IS_ENABLED(DM_RESET) 1697777fe4eSJoseph Chen ret = reset_get_by_name(dev, "saradc-apb", &priv->rst); 1707777fe4eSJoseph Chen if (ret) { 1717777fe4eSJoseph Chen debug("reset_get_by_name() failed: %d\n", ret); 1727777fe4eSJoseph Chen return ret; 1737777fe4eSJoseph Chen } 1747777fe4eSJoseph Chen #endif 1757777fe4eSJoseph Chen 17648111c22SSimon Xue ret = clk_get_by_index(dev, 0, &clk); 17748111c22SSimon Xue if (ret) 17848111c22SSimon Xue return ret; 17948111c22SSimon Xue 18048111c22SSimon Xue ret = clk_set_rate(&clk, priv->data->clk_rate); 18148111c22SSimon Xue if (IS_ERR_VALUE(ret)) 18248111c22SSimon Xue return ret; 18348111c22SSimon Xue 18448111c22SSimon Xue priv->active_channel = -1; 18548111c22SSimon Xue 18648111c22SSimon Xue return 0; 18748111c22SSimon Xue } 18848111c22SSimon Xue 18948111c22SSimon Xue static int rockchip_saradc_ofdata_to_platdata(struct udevice *dev) 19048111c22SSimon Xue { 19148111c22SSimon Xue struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev); 19248111c22SSimon Xue struct rockchip_saradc_priv *priv = dev_get_priv(dev); 19348111c22SSimon Xue struct rockchip_saradc_data *data; 19448111c22SSimon Xue 19548111c22SSimon Xue data = (struct rockchip_saradc_data *)dev_get_driver_data(dev); 19648111c22SSimon Xue priv->regs = (struct rockchip_saradc_regs *)dev_read_addr(dev); 19748111c22SSimon Xue if (priv->regs == (struct rockchip_saradc_regs *)FDT_ADDR_T_NONE) { 19848111c22SSimon Xue pr_err("Dev: %s - can't get address!", dev->name); 19948111c22SSimon Xue return -ENODATA; 20048111c22SSimon Xue } 20148111c22SSimon Xue 20248111c22SSimon Xue priv->data = data; 20348111c22SSimon Xue uc_pdata->data_mask = (1 << priv->data->num_bits) - 1; 20448111c22SSimon Xue uc_pdata->data_format = ADC_DATA_FORMAT_BIN; 20548111c22SSimon Xue uc_pdata->data_timeout_us = SARADC_TIMEOUT / 5; 20648111c22SSimon Xue uc_pdata->channel_mask = (1 << priv->data->num_channels) - 1; 20748111c22SSimon Xue 20848111c22SSimon Xue return 0; 20948111c22SSimon Xue } 21048111c22SSimon Xue 21148111c22SSimon Xue static const struct adc_ops rockchip_saradc_ops = { 21248111c22SSimon Xue .start_channel = rockchip_saradc_start_channel, 21348111c22SSimon Xue .channel_data = rockchip_saradc_channel_data, 21448111c22SSimon Xue .stop = rockchip_saradc_stop, 21548111c22SSimon Xue }; 21648111c22SSimon Xue 21748111c22SSimon Xue static const struct rockchip_saradc_data rk3588_saradc_data = { 21848111c22SSimon Xue .num_bits = 12, 21948111c22SSimon Xue .num_channels = 8, 22048111c22SSimon Xue .clk_rate = 1000000, 22148111c22SSimon Xue }; 22248111c22SSimon Xue 223*7cd4e41dSSimon Xue static const struct rockchip_saradc_data rk3562_saradc_data = { 224*7cd4e41dSSimon Xue .num_bits = 10, 225*7cd4e41dSSimon Xue .num_channels = 8, 226*7cd4e41dSSimon Xue .clk_rate = 1000000, 227*7cd4e41dSSimon Xue }; 228*7cd4e41dSSimon Xue 22948111c22SSimon Xue static const struct udevice_id rockchip_saradc_ids[] = { 23027354a5cSJoseph Chen { 23127354a5cSJoseph Chen .compatible = "rockchip,rk3588-saradc", 23227354a5cSJoseph Chen .data = (ulong)&rk3588_saradc_data 23327354a5cSJoseph Chen }, 23427354a5cSJoseph Chen { 23527354a5cSJoseph Chen .compatible = "rockchip,rk3528-saradc", 23627354a5cSJoseph Chen .data = (ulong)&rk3588_saradc_data 23727354a5cSJoseph Chen }, 238*7cd4e41dSSimon Xue { 239*7cd4e41dSSimon Xue .compatible = "rockchip,rk3562-saradc", 240*7cd4e41dSSimon Xue .data = (ulong)&rk3562_saradc_data 241*7cd4e41dSSimon Xue }, 24248111c22SSimon Xue { } 24348111c22SSimon Xue }; 24448111c22SSimon Xue 24548111c22SSimon Xue U_BOOT_DRIVER(rockchip_saradc_v2) = { 24648111c22SSimon Xue .name = "rockchip_saradc_v2", 24748111c22SSimon Xue .id = UCLASS_ADC, 24848111c22SSimon Xue .of_match = rockchip_saradc_ids, 24948111c22SSimon Xue .ops = &rockchip_saradc_ops, 25048111c22SSimon Xue .probe = rockchip_saradc_probe, 25148111c22SSimon Xue .ofdata_to_platdata = rockchip_saradc_ofdata_to_platdata, 25248111c22SSimon Xue .priv_auto_alloc_size = sizeof(struct rockchip_saradc_priv), 25348111c22SSimon Xue }; 254