Message ID | 20240221-rk3588-saradc-v1-11-c39a5601d1cc@theobroma-systems.com |
---|---|
State | Superseded |
Delegated to: | Kever Yang |
Headers | show |
Series | rockchip: add support for SARADCv2 and RK806 PMIC and regulators | expand |
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
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)); + + return 0; +} + int rockchip_saradc_start_channel(struct udevice *dev, int channel) { struct rockchip_saradc_priv *priv = dev_get_priv(dev); @@ -247,6 +311,14 @@ static const struct rockchip_saradc_data rk3399_saradc_data = { .stop = rockchip_saradc_stop_v1, }; +static const struct rockchip_saradc_data rk3588_saradc_data = { + .num_bits = 12, + .num_channels = 8, + .clk_rate = 1000000, + .channel_data = rockchip_saradc_channel_data_v2, + .start_channel = rockchip_saradc_start_channel_v2, +}; + static const struct udevice_id rockchip_saradc_ids[] = { { .compatible = "rockchip,saradc", .data = (ulong)&saradc_data }, @@ -254,6 +326,8 @@ static const struct udevice_id rockchip_saradc_ids[] = { .data = (ulong)&rk3066_tsadc_data }, { .compatible = "rockchip,rk3399-saradc", .data = (ulong)&rk3399_saradc_data }, + { .compatible = "rockchip,rk3588-saradc", + .data = (ulong)&rk3588_saradc_data }, { } };