RE: [PATCH v5 2/2] mmc: renesas_sdhi: Add support for RZ/G3E SoC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux