
Hi all,
On 2/21/24 18:07, Quentin Schulz wrote:
From: Quentin Schulz quentin.schulz@theobroma-systems.com
This adds support for the SARADCv2 found on RK3588.
There is no stop callback as it is currently configured in single conversion mode, where the ADC is powered down after a single conversion has been made.
Cc: Quentin Schulz foss+uboot@0leil.net Signed-off-by: Quentin Schulz quentin.schulz@theobroma-systems.com
drivers/adc/rockchip-saradc.c | 76 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-)
diff --git a/drivers/adc/rockchip-saradc.c b/drivers/adc/rockchip-saradc.c index b5df58fe3eb..05c93cedcf1 100644 --- a/drivers/adc/rockchip-saradc.c +++ b/drivers/adc/rockchip-saradc.c @@ -10,7 +10,8 @@ #include <clk.h> #include <dm.h> #include <errno.h> -#include <asm/io.h> +#include <asm/arch-rockchip/hardware.h> +#include <linux/bitfield.h> #include <linux/bitops.h> #include <linux/err.h> #include <linux/printk.h> @@ -30,8 +31,37 @@ struct rockchip_saradc_regs_v1 { unsigned int dly_pu_soc; };
+struct rockchip_saradc_regs_v2 {
- unsigned int conv_con;
+#define SARADC2_SINGLE_MODE BIT(5) +#define SARADC2_START BIT(4) +#define SARADC2_CONV_CHANNELS GENMASK(3, 0)
- unsigned int t_pd_soc;
- unsigned int t_as_soc;
- unsigned int t_das_soc;
- unsigned int t_sel_soc;
- unsigned int high_comp[16];
- unsigned int low_comp[16];
- unsigned int debounce;
- unsigned int ht_int_en;
- unsigned int lt_int_en;
- unsigned int reserved[24];
- unsigned int mt_int_en;
- unsigned int end_int_en;
+#define SARADC2_EN_END_INT BIT(0)
- unsigned int st_con;
- unsigned int status;
- unsigned int end_int_st;
- unsigned int ht_int_st;
- unsigned int lt_int_st;
- unsigned int mt_int_st;
- unsigned int data[16];
- unsigned int auto_ch_en;
+};
- union rockchip_saradc_regs { struct rockchip_saradc_regs_v1 *v1;
- struct rockchip_saradc_regs_v2 *v2; }; struct rockchip_saradc_data { int num_bits;
@@ -66,6 +96,22 @@ int rockchip_saradc_channel_data_v1(struct udevice *dev, int channel, return 0; }
+int rockchip_saradc_channel_data_v2(struct udevice *dev, int channel,
unsigned int *data)
+{
- struct rockchip_saradc_priv *priv = dev_get_priv(dev);
- if (!(readl(&priv->regs.v2->end_int_st) & SARADC2_EN_END_INT))
return -EBUSY;
- /* Read value */
- *data = readl(&priv->regs.v2->data[channel]);
- /* Acknowledge the interrupt */
- writel(SARADC2_EN_END_INT, &priv->regs.v2->end_int_st);
- return 0;
+} int rockchip_saradc_channel_data(struct udevice *dev, int channel, unsigned int *data) { @@ -104,6 +150,24 @@ int rockchip_saradc_start_channel_v1(struct udevice *dev, int channel) return 0; }
+int rockchip_saradc_start_channel_v2(struct udevice *dev, int channel) +{
- struct rockchip_saradc_priv *priv = dev_get_priv(dev);
- writel(0xc, &priv->regs.v2->t_das_soc);
- writel(0x20, &priv->regs.v2->t_pd_soc);
- /* Acknowledge any previous interrupt */
- writel(SARADC2_EN_END_INT, &priv->regs.v2->end_int_st);
- rk_setreg(&priv->regs.v2->conv_con,
FIELD_PREP(SARADC2_CONV_CHANNELS, channel) |
FIELD_PREP(SARADC2_START, 1) |
FIELD_PREP(SARADC2_SINGLE_MODE, 1));
This is incorrect because we need to also write zeroes in the SARADC2_CONV_CHANNELS bitfield and rk_setreg takes the argument and shifts it by 16 for the write_enable mask, not taking into account the mask in which those bits are set. Will send a v2 soon, trying to figure out why this isn't an issue in Linux kernel which is using the same logic....
Cheers, Quentin