diff mbox series

[v2] soc/tegra: pmc: Add IO Pad table for tegra234

Message ID 20220808201420.3451111-1-petlozup@nvidia.com
State Changes Requested
Headers show
Series [v2] soc/tegra: pmc: Add IO Pad table for tegra234 | expand

Commit Message

Petlozu Pravareshwar Aug. 8, 2022, 8:14 p.m. UTC
Add IO PAD table for tegra234 to allow configuring dpd mode
and switching the pins to 1.8V or 3.3V as needed.

In tegra234, DPD registers are reorganized such that there is
a DPD_REQ register and a DPD_STATUS register per pad group.
This change accordingly updates the PMC driver.

Signed-off-by: Petlozu Pravareshwar <petlozup@nvidia.com>
---
 drivers/soc/tegra/pmc.c | 109 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 105 insertions(+), 4 deletions(-)

Comments

Thierry Reding Aug. 18, 2022, 3:13 p.m. UTC | #1
On Mon, Aug 08, 2022 at 08:14:20PM +0000, Petlozu Pravareshwar wrote:
> Add IO PAD table for tegra234 to allow configuring dpd mode
> and switching the pins to 1.8V or 3.3V as needed.
> 
> In tegra234, DPD registers are reorganized such that there is
> a DPD_REQ register and a DPD_STATUS register per pad group.
> This change accordingly updates the PMC driver.
> 
> Signed-off-by: Petlozu Pravareshwar <petlozup@nvidia.com>
> ---
>  drivers/soc/tegra/pmc.c | 109 ++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 105 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
> index 5611d14d3ba2..34d36a28f7d6 100644
> --- a/drivers/soc/tegra/pmc.c
> +++ b/drivers/soc/tegra/pmc.c
> @@ -266,11 +266,22 @@ struct tegra_powergate {
>  	struct reset_control *reset;
>  };
>  
> +enum tegra_dpd_reg {
> +	TEGRA_PMC_IO_INVALID_DPD,
> +	TEGRA_PMC_IO_CSI_DPD,
> +	TEGRA_PMC_IO_DISP_DPD,
> +	TEGRA_PMC_IO_QSPI_DPD,
> +	TEGRA_PMC_IO_UFS_DPD,
> +	TEGRA_PMC_IO_EDP_DPD,
> +	TEGRA_PMC_IO_SDMMC1_HV_DPD,
> +};
> +
>  struct tegra_io_pad_soc {
>  	enum tegra_io_pad id;
>  	unsigned int dpd;
>  	unsigned int voltage;
>  	const char *name;
> +	enum tegra_dpd_reg reg_index;
>  };
>  
>  struct tegra_pmc_regs {
> @@ -284,6 +295,8 @@ struct tegra_pmc_regs {
>  	unsigned int rst_source_mask;
>  	unsigned int rst_level_shift;
>  	unsigned int rst_level_mask;
> +	const unsigned int *reorg_dpd_req;
> +	const unsigned int *reorg_dpd_status;
>  };
>  
>  struct tegra_wake_event {
> @@ -364,6 +377,7 @@ struct tegra_pmc_soc {
>  	bool has_blink_output;
>  	bool has_usb_sleepwalk;
>  	bool supports_core_domain;
> +	bool has_reorg_hw_dpd_reg_impl;
>  };
>  
>  /**
> @@ -1546,6 +1560,14 @@ static int tegra_io_pad_get_dpd_register_bit(struct tegra_pmc *pmc,
>  	if (pad->dpd == UINT_MAX)
>  		return -ENOTSUPP;
>  
> +	if (pmc->soc->has_reorg_hw_dpd_reg_impl) {
> +		*mask = BIT(pad->dpd);
> +		*status = pmc->soc->regs->reorg_dpd_status[pad->reg_index];
> +		*request = pmc->soc->regs->reorg_dpd_req[pad->reg_index];
> +
> +		goto done;
> +	}
> +
>  	*mask = BIT(pad->dpd % 32);
>  
>  	if (pad->dpd < 32) {
> @@ -1556,6 +1578,7 @@ static int tegra_io_pad_get_dpd_register_bit(struct tegra_pmc *pmc,
>  		*request = pmc->soc->regs->dpd2_req;
>  	}
>  
> +done:
>  	return 0;
>  }
>  

All of this looks "bolted on". Can we not instead rework the existing
register definitions to work with the new dpd_status and dpd_request
arrays? It means that we'd probably need a bit of duplication of data
since we would no longer programmatically determine the register offsets
like we used to, but it would save the extra flag and make the code much
more readable, in my opinion.

Thierry
Petlozu Pravareshwar Aug. 24, 2022, 6:21 p.m. UTC | #2
> 
> On Mon, Aug 08, 2022 at 08:14:20PM +0000, Petlozu Pravareshwar wrote:
> > Add IO PAD table for tegra234 to allow configuring dpd mode and
> > switching the pins to 1.8V or 3.3V as needed.
> >
> > In tegra234, DPD registers are reorganized such that there is a
> > DPD_REQ register and a DPD_STATUS register per pad group.
> > This change accordingly updates the PMC driver.
> >
> > Signed-off-by: Petlozu Pravareshwar <petlozup@nvidia.com>
> > ---
> >  drivers/soc/tegra/pmc.c | 109
> > ++++++++++++++++++++++++++++++++++++++--
> >  1 file changed, 105 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index
> > 5611d14d3ba2..34d36a28f7d6 100644
> > --- a/drivers/soc/tegra/pmc.c
> > +++ b/drivers/soc/tegra/pmc.c
> > @@ -266,11 +266,22 @@ struct tegra_powergate {
> >  	struct reset_control *reset;
> >  };
> >
> > +enum tegra_dpd_reg {
> > +	TEGRA_PMC_IO_INVALID_DPD,
> > +	TEGRA_PMC_IO_CSI_DPD,
> > +	TEGRA_PMC_IO_DISP_DPD,
> > +	TEGRA_PMC_IO_QSPI_DPD,
> > +	TEGRA_PMC_IO_UFS_DPD,
> > +	TEGRA_PMC_IO_EDP_DPD,
> > +	TEGRA_PMC_IO_SDMMC1_HV_DPD,
> > +};
> > +
> >  struct tegra_io_pad_soc {
> >  	enum tegra_io_pad id;
> >  	unsigned int dpd;
> >  	unsigned int voltage;
> >  	const char *name;
> > +	enum tegra_dpd_reg reg_index;
> >  };
> >
> >  struct tegra_pmc_regs {
> > @@ -284,6 +295,8 @@ struct tegra_pmc_regs {
> >  	unsigned int rst_source_mask;
> >  	unsigned int rst_level_shift;
> >  	unsigned int rst_level_mask;
> > +	const unsigned int *reorg_dpd_req;
> > +	const unsigned int *reorg_dpd_status;
> >  };
> >
> >  struct tegra_wake_event {
> > @@ -364,6 +377,7 @@ struct tegra_pmc_soc {
> >  	bool has_blink_output;
> >  	bool has_usb_sleepwalk;
> >  	bool supports_core_domain;
> > +	bool has_reorg_hw_dpd_reg_impl;
> >  };
> >
> >  /**
> > @@ -1546,6 +1560,14 @@ static int
> tegra_io_pad_get_dpd_register_bit(struct tegra_pmc *pmc,
> >  	if (pad->dpd == UINT_MAX)
> >  		return -ENOTSUPP;
> >
> > +	if (pmc->soc->has_reorg_hw_dpd_reg_impl) {
> > +		*mask = BIT(pad->dpd);
> > +		*status = pmc->soc->regs->reorg_dpd_status[pad-
> >reg_index];
> > +		*request = pmc->soc->regs->reorg_dpd_req[pad-
> >reg_index];
> > +
> > +		goto done;
> > +	}
> > +
> >  	*mask = BIT(pad->dpd % 32);
> >
> >  	if (pad->dpd < 32) {
> > @@ -1556,6 +1578,7 @@ static int
> tegra_io_pad_get_dpd_register_bit(struct tegra_pmc *pmc,
> >  		*request = pmc->soc->regs->dpd2_req;
> >  	}
> >
> > +done:
> >  	return 0;
> >  }
> >
> 
> All of this looks "bolted on". Can we not instead rework the existing register
> definitions to work with the new dpd_status and dpd_request arrays? It
> means that we'd probably need a bit of duplication of data since we would
> no longer programmatically determine the register offsets like we used to,
> but it would save the extra flag and make the code much more readable, in
> my opinion.
> 
> Thierry
Yes. Agree that we can rework the patch to make the code more readable and
to save the extra flags. Will update the patch.

Thanks.
diff mbox series

Patch

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 5611d14d3ba2..34d36a28f7d6 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -266,11 +266,22 @@  struct tegra_powergate {
 	struct reset_control *reset;
 };
 
+enum tegra_dpd_reg {
+	TEGRA_PMC_IO_INVALID_DPD,
+	TEGRA_PMC_IO_CSI_DPD,
+	TEGRA_PMC_IO_DISP_DPD,
+	TEGRA_PMC_IO_QSPI_DPD,
+	TEGRA_PMC_IO_UFS_DPD,
+	TEGRA_PMC_IO_EDP_DPD,
+	TEGRA_PMC_IO_SDMMC1_HV_DPD,
+};
+
 struct tegra_io_pad_soc {
 	enum tegra_io_pad id;
 	unsigned int dpd;
 	unsigned int voltage;
 	const char *name;
+	enum tegra_dpd_reg reg_index;
 };
 
 struct tegra_pmc_regs {
@@ -284,6 +295,8 @@  struct tegra_pmc_regs {
 	unsigned int rst_source_mask;
 	unsigned int rst_level_shift;
 	unsigned int rst_level_mask;
+	const unsigned int *reorg_dpd_req;
+	const unsigned int *reorg_dpd_status;
 };
 
 struct tegra_wake_event {
@@ -364,6 +377,7 @@  struct tegra_pmc_soc {
 	bool has_blink_output;
 	bool has_usb_sleepwalk;
 	bool supports_core_domain;
+	bool has_reorg_hw_dpd_reg_impl;
 };
 
 /**
@@ -1546,6 +1560,14 @@  static int tegra_io_pad_get_dpd_register_bit(struct tegra_pmc *pmc,
 	if (pad->dpd == UINT_MAX)
 		return -ENOTSUPP;
 
+	if (pmc->soc->has_reorg_hw_dpd_reg_impl) {
+		*mask = BIT(pad->dpd);
+		*status = pmc->soc->regs->reorg_dpd_status[pad->reg_index];
+		*request = pmc->soc->regs->reorg_dpd_req[pad->reg_index];
+
+		goto done;
+	}
+
 	*mask = BIT(pad->dpd % 32);
 
 	if (pad->dpd < 32) {
@@ -1556,6 +1578,7 @@  static int tegra_io_pad_get_dpd_register_bit(struct tegra_pmc *pmc,
 		*request = pmc->soc->regs->dpd2_req;
 	}
 
+done:
 	return 0;
 }
 
@@ -3791,6 +3814,81 @@  static const struct tegra_pmc_soc tegra194_pmc_soc = {
 	.has_usb_sleepwalk = false,
 };
 
+#define TEGRA234_IO_PAD(_id, _dpd, _voltage, _name, _dpd_reg_index)	\
+	((struct tegra_io_pad_soc) {					\
+		.id		= (_id),				\
+		.dpd		= (_dpd),				\
+		.voltage	= (_voltage),				\
+		.name		= (_name),				\
+		.reg_index	= (_dpd_reg_index),			\
+	})
+
+#define TEGRA234_IO_PIN_DESC(_id, _dpd, _voltage, _name, _dpd_reg_index) \
+	((struct pinctrl_pin_desc) {					\
+		.number = (_id),					\
+		.name	= (_name)					\
+	})
+
+#define TEGRA234_IO_PAD_TABLE(_pad) {                                          \
+	/* (id, dpd, voltage, name, dpd_reg_index) */                          \
+	_pad(TEGRA_IO_PAD_CSIA,           0,         UINT_MAX,	"csia",        \
+		TEGRA_PMC_IO_CSI_DPD),                                         \
+	_pad(TEGRA_IO_PAD_CSIB,           1,         UINT_MAX,  "csib",        \
+		TEGRA_PMC_IO_CSI_DPD),                                         \
+	_pad(TEGRA_IO_PAD_HDMI_DP0,       0,         UINT_MAX,  "hdmi-dp0",    \
+		TEGRA_PMC_IO_DISP_DPD),                                        \
+	_pad(TEGRA_IO_PAD_CSIC,           2,         UINT_MAX,  "csic",        \
+		TEGRA_PMC_IO_CSI_DPD),                                         \
+	_pad(TEGRA_IO_PAD_CSID,           3,         UINT_MAX,  "csid",        \
+		TEGRA_PMC_IO_CSI_DPD),                                         \
+	_pad(TEGRA_IO_PAD_CSIE,           4,         UINT_MAX,  "csie",        \
+		TEGRA_PMC_IO_CSI_DPD),                                         \
+	_pad(TEGRA_IO_PAD_CSIF,           5,         UINT_MAX,  "csif",        \
+		TEGRA_PMC_IO_CSI_DPD),                                         \
+	_pad(TEGRA_IO_PAD_UFS,            0,         UINT_MAX,  "ufs",         \
+		TEGRA_PMC_IO_UFS_DPD),                                         \
+	_pad(TEGRA_IO_PAD_EDP,            1,         UINT_MAX,  "edp",         \
+		TEGRA_PMC_IO_EDP_DPD),                                         \
+	_pad(TEGRA_IO_PAD_SDMMC1_HV,      0,         4,         "sdmmc1-hv",   \
+		TEGRA_PMC_IO_SDMMC1_HV_DPD),                                   \
+	_pad(TEGRA_IO_PAD_SDMMC3_HV,      UINT_MAX,  6,         "sdmmc3-hv",   \
+		TEGRA_PMC_IO_INVALID_DPD),                                     \
+	_pad(TEGRA_IO_PAD_AUDIO_HV,       UINT_MAX,  1,         "audio-hv",    \
+		TEGRA_PMC_IO_INVALID_DPD),                                     \
+	_pad(TEGRA_IO_PAD_AO_HV,          UINT_MAX,  0,         "ao-hv",       \
+		TEGRA_PMC_IO_INVALID_DPD),                                     \
+	_pad(TEGRA_IO_PAD_CSIG,           6,         UINT_MAX,  "csig",        \
+		TEGRA_PMC_IO_CSI_DPD),                                         \
+	_pad(TEGRA_IO_PAD_CSIH,           7,         UINT_MAX,  "csih",        \
+		TEGRA_PMC_IO_CSI_DPD)                                          \
+	}
+
+static const struct tegra_io_pad_soc tegra234_io_pads[] =
+	TEGRA234_IO_PAD_TABLE(TEGRA234_IO_PAD);
+
+static const struct pinctrl_pin_desc tegra234_pin_descs[] =
+	TEGRA234_IO_PAD_TABLE(TEGRA234_IO_PIN_DESC);
+
+/* Reorganized HW DPD REQ registers */
+static const unsigned int tegra234_dpd_req_regs[] = {
+	[TEGRA_PMC_IO_CSI_DPD] = 0xe0c0,
+	[TEGRA_PMC_IO_DISP_DPD] = 0xe0d0,
+	[TEGRA_PMC_IO_QSPI_DPD] = 0xe074,
+	[TEGRA_PMC_IO_UFS_DPD] = 0xe064,
+	[TEGRA_PMC_IO_EDP_DPD] = 0xe05c,
+	[TEGRA_PMC_IO_SDMMC1_HV_DPD] = 0xe054,
+};
+
+/* Reorganized HW DPD STATUS registers */
+static const unsigned int tegra234_dpd_status_regs[] = {
+	[TEGRA_PMC_IO_CSI_DPD] = 0xe0c4,
+	[TEGRA_PMC_IO_DISP_DPD] = 0xe0d4,
+	[TEGRA_PMC_IO_QSPI_DPD] = 0xe078,
+	[TEGRA_PMC_IO_UFS_DPD] = 0xe068,
+	[TEGRA_PMC_IO_EDP_DPD] = 0xe060,
+	[TEGRA_PMC_IO_SDMMC1_HV_DPD] = 0xe058,
+};
+
 static const struct tegra_pmc_regs tegra234_pmc_regs = {
 	.scratch0 = 0x2000,
 	.dpd_req = 0,
@@ -3802,6 +3900,8 @@  static const struct tegra_pmc_regs tegra234_pmc_regs = {
 	.rst_source_mask = 0xfc,
 	.rst_level_shift = 0x0,
 	.rst_level_mask = 0x3,
+	.reorg_dpd_req = tegra234_dpd_req_regs,
+	.reorg_dpd_status = tegra234_dpd_status_regs,
 };
 
 static const char * const tegra234_reset_sources[] = {
@@ -3861,10 +3961,10 @@  static const struct tegra_pmc_soc tegra234_pmc_soc = {
 	.needs_mbist_war = false,
 	.has_impl_33v_pwr = true,
 	.maybe_tz_only = false,
-	.num_io_pads = 0,
-	.io_pads = NULL,
-	.num_pin_descs = 0,
-	.pin_descs = NULL,
+	.num_io_pads = ARRAY_SIZE(tegra234_io_pads),
+	.io_pads = tegra234_io_pads,
+	.num_pin_descs = ARRAY_SIZE(tegra234_pin_descs),
+	.pin_descs = tegra234_pin_descs,
 	.regs = &tegra234_pmc_regs,
 	.init = NULL,
 	.setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
@@ -3879,6 +3979,7 @@  static const struct tegra_pmc_soc tegra234_pmc_soc = {
 	.pmc_clks_data = NULL,
 	.num_pmc_clks = 0,
 	.has_blink_output = false,
+	.has_reorg_hw_dpd_reg_impl = true,
 };
 
 static const struct of_device_id tegra_pmc_match[] = {