Hi All, > -----Original Message----- > From: Biju Das <biju.das.jz@xxxxxxxxxxxxxx> > Sent: 03 March 2025 11:38 > Subject: [PATCH v5 2/2] mmc: renesas_sdhi: Add support for RZ/G3E SoC > > The SDHI/eMMC IPs in the RZ/G3E SoC are similar to those in R-Car Gen3. > However, the RZ/G3E SD0 channel has Voltage level control and PWEN pin support via SD_STATUS register. > > internal regulator support is added to control the voltage levels of the SD pins via sd_iovs/sd_pwen > bits in SD_STATUS register by populating vqmmc-regulator child node. > > SD1 and SD2 channels have gpio regulator support and internal regulator support. Selection of the > regulator is based on the regulator phandle. > Similar case for SD0 fixed voltage (eMMC) that uses fixed regulator and > SD0 non-fixed voltage (SD0) that uses internal regulator. > > Signed-off-by: Biju Das <biju.das.jz@xxxxxxxxxxxxxx> > --- > v4->v5: > * Dropped redundant struct renesas_sdhi_vqmmc_regulator initialization. > * Added one space before '=' in the struct initializer. > v3->v4: > * Added sd_ctrl_read32() > * Replaced sd_ctrl_read32_rep()->sd_ctrl_read32(). > * Arranged variables of same types close to each other in probe(). > v2->v3: > * No change. > v1->v2: > * Updated commit description for regulator used in SD0 fixed and > non-fixed voltage case. > * As the node enabling of internal regulator is controlled through status, > added a check for device availability. > --- > drivers/mmc/host/renesas_sdhi.h | 1 + > drivers/mmc/host/renesas_sdhi_core.c | 130 +++++++++++++++++++++++++++ > drivers/mmc/host/tmio_mmc.h | 10 +++ > 3 files changed, 141 insertions(+) > > diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h index > f12a87442338..291ddb4ad9be 100644 > --- a/drivers/mmc/host/renesas_sdhi.h > +++ b/drivers/mmc/host/renesas_sdhi.h > @@ -95,6 +95,7 @@ struct renesas_sdhi { > > struct reset_control *rstc; > struct tmio_mmc_host *host; > + struct regulator_dev *rdev; > }; > > #define host_to_priv(host) \ > diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c > index f73b84bae0c4..3a3c6a7aba89 100644 > --- a/drivers/mmc/host/renesas_sdhi_core.c > +++ b/drivers/mmc/host/renesas_sdhi_core.c > @@ -32,6 +32,8 @@ > #include <linux/platform_device.h> > #include <linux/pm_domain.h> > #include <linux/regulator/consumer.h> > +#include <linux/regulator/driver.h> > +#include <linux/regulator/of_regulator.h> > #include <linux/reset.h> > #include <linux/sh_dma.h> > #include <linux/slab.h> > @@ -581,12 +583,24 @@ static void renesas_sdhi_reset(struct tmio_mmc_host *host, bool preserve) > > if (!preserve) { > if (priv->rstc) { > + u32 sd_status; > + /* > + * HW reset might have toggled the regulator state in > + * HW which regulator core might be unaware of so save > + * and restore the regulator state during HW reset. > + */ > + if (priv->rdev) > + sd_status = sd_ctrl_read32(host, CTL_SD_STATUS); > + > reset_control_reset(priv->rstc); > /* Unknown why but without polling reset status, it will hang */ > read_poll_timeout(reset_control_status, ret, ret == 0, 1, 100, > false, priv->rstc); > /* At least SDHI_VER_GEN2_SDR50 needs manual release of reset */ > sd_ctrl_write16(host, CTL_RESET_SD, 0x0001); > + if (priv->rdev) > + sd_ctrl_write32(host, CTL_SD_STATUS, sd_status); > + > priv->needs_adjust_hs400 = false; > renesas_sdhi_set_clock(host, host->clk_cache); > > @@ -904,6 +918,102 @@ static void renesas_sdhi_enable_dma(struct tmio_mmc_host *host, bool enable) > renesas_sdhi_sdbuf_width(host, enable ? width : 16); } > > +static const unsigned int renesas_sdhi_vqmmc_voltages[] = { > + 3300000, 1800000 > +}; > + > +static int renesas_sdhi_regulator_disable(struct regulator_dev *rdev) { > + struct tmio_mmc_host *host = rdev_get_drvdata(rdev); > + u32 sd_status; > + > + sd_status = sd_ctrl_read32(host, CTL_SD_STATUS); > + sd_status &= ~SD_STATUS_PWEN; > + sd_ctrl_write32(host, CTL_SD_STATUS, sd_status); > + > + return 0; > +} > + > +static int renesas_sdhi_regulator_enable(struct regulator_dev *rdev) { > + struct tmio_mmc_host *host = rdev_get_drvdata(rdev); > + u32 sd_status; > + > + sd_status = sd_ctrl_read32(host, CTL_SD_STATUS); > + sd_status |= SD_STATUS_PWEN; > + sd_ctrl_write32(host, CTL_SD_STATUS, sd_status); > + > + return 0; > +} > + > +static int renesas_sdhi_regulator_is_enabled(struct regulator_dev > +*rdev) { > + struct tmio_mmc_host *host = rdev_get_drvdata(rdev); > + u32 sd_status; > + > + sd_status = sd_ctrl_read32(host, CTL_SD_STATUS); > + > + return (sd_status & SD_STATUS_PWEN) ? 1 : 0; } > + > +static int renesas_sdhi_regulator_get_voltage(struct regulator_dev > +*rdev) { > + struct tmio_mmc_host *host = rdev_get_drvdata(rdev); > + u32 sd_status; > + > + sd_status = sd_ctrl_read32(host, CTL_SD_STATUS); > + > + return (sd_status & SD_STATUS_IOVS) ? 1800000 : 3300000; } > + > +static int renesas_sdhi_regulator_set_voltage(struct regulator_dev *rdev, > + int min_uV, int max_uV, > + unsigned int *selector) > +{ > + struct tmio_mmc_host *host = rdev_get_drvdata(rdev); > + u32 sd_status; > + > + sd_status = sd_ctrl_read32(host, CTL_SD_STATUS); > + if (min_uV >= 1700000 && max_uV <= 1950000) { > + sd_status |= SD_STATUS_IOVS; > + *selector = 1; > + } else { > + sd_status &= ~SD_STATUS_IOVS; > + *selector = 0; > + } > + sd_ctrl_write32(host, CTL_SD_STATUS, sd_status); > + > + return 0; > +} > + > +static int renesas_sdhi_regulator_list_voltage(struct regulator_dev *rdev, > + unsigned int selector) > +{ > + if (selector >= ARRAY_SIZE(renesas_sdhi_vqmmc_voltages)) > + return -EINVAL; > + > + return renesas_sdhi_vqmmc_voltages[selector]; > +} > + > +static const struct regulator_ops renesas_sdhi_regulator_voltage_ops = { > + .enable = renesas_sdhi_regulator_enable, > + .disable = renesas_sdhi_regulator_disable, > + .is_enabled = renesas_sdhi_regulator_is_enabled, > + .list_voltage = renesas_sdhi_regulator_list_voltage, > + .get_voltage = renesas_sdhi_regulator_get_voltage, > + .set_voltage = renesas_sdhi_regulator_set_voltage, > +}; > + > +static struct regulator_desc renesas_sdhi_vqmmc_regulator = { I missed adding const here. Will be fixing this in next version along with other review comments for this patch, if any. Cheers, Biu