Skip to contentSkip to conversation

mxs: Implement common function to setup VDDx

PATCH New Marek Vasut 3 participants 7 messages Nov 30, 2012 – Dec 4, 2012

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/2 mxs: Implement common function to setup VDDx

Implement common function to setup the VDDIO, VDDD and VDDA voltage. Right now, there are two almost identical functions to setup VDDIO and VDDD, which is prone to breakage. Pull out the differences into constant structure and pass them as an argument to the common function.

Moreover, the function has almost identical loops for setting higher and lower VDDx voltage. Merge these two loops.

Cc Stefano Babic <[email protected]>
Cc Fabio Estevam <[email protected]>
---
 arch/arm/cpu/arm926ejs/mxs/spl_power_init.c |  253 +++++++++------------------
 1 file changed, 83 insertions(+), 170 deletions(-)
arch/arm/cpu/arm926ejs/mxs/spl_power_init.c +83 -170
index 4b917bd..0d80158 100644
@@ -766,198 +766,112 @@ int mxs_get_vddd_power_source_off(void)
 	return 0;
 }
 
-void mxs_power_set_vddio(uint32_t new_target, uint32_t new_brownout)
+struct mxs_vddx_cfg {
+	uint32_t		*reg;
+	uint8_t			step_mV;
+	uint16_t		lowest_mV;
+	int			(*powered_by_linreg)(void);
+	uint32_t		trg_mask;
+	uint32_t		bo_irq;
+	uint32_t		bo_enirq;
+	uint32_t		bo_offset_mask;
+	uint32_t		bo_offset_offset;
+};
+
+const struct mxs_vddx_cfg mxs_vddio_cfg = {
+	.reg			= &(((struct mxs_power_regs *)MXS_POWER_BASE)->
+					hw_power_vddioctrl),
+	.step_mV		= 50,
+	.lowest_mV		= 2800,
+	.powered_by_linreg	= mxs_get_vddio_power_source_off,
+	.trg_mask		= POWER_VDDIOCTRL_TRG_MASK,
+	.bo_irq			= POWER_CTRL_VDDIO_BO_IRQ,
+	.bo_enirq		= POWER_CTRL_ENIRQ_VDDIO_BO,
+	.bo_offset_mask		= POWER_VDDIOCTRL_BO_OFFSET_MASK,
+	.bo_offset_offset	= POWER_VDDIOCTRL_BO_OFFSET_OFFSET,
+};
+
+const struct mxs_vddx_cfg mxs_vddd_cfg = {
+	.reg			= &(((struct mxs_power_regs *)MXS_POWER_BASE)->
+					hw_power_vdddctrl),
+	.step_mV		= 25,
+	.lowest_mV		= 800,
+	.powered_by_linreg	= mxs_get_vddd_power_source_off,
+	.trg_mask		= POWER_VDDDCTRL_TRG_MASK,
+	.bo_irq			= POWER_CTRL_VDDD_BO_IRQ,
+	.bo_enirq		= POWER_CTRL_ENIRQ_VDDD_BO,
+	.bo_offset_mask		= POWER_VDDDCTRL_BO_OFFSET_MASK,
+	.bo_offset_offset	= POWER_VDDDCTRL_BO_OFFSET_OFFSET,
+};
+
+static void mxs_power_set_vddx(const struct mxs_vddx_cfg *cfg,
+				uint32_t new_target, uint32_t new_brownout)
 {
 	struct mxs_power_regs *power_regs =
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 	uint32_t cur_target, diff, bo_int = 0;
 	uint32_t powered_by_linreg = 0;
+	int adjust_up, tmp;
 
-	new_brownout = (new_target - new_brownout + 25) / 50;
+	new_brownout = DIV_ROUND(new_target - new_brownout, cfg->step_mV);
 
-	cur_target = readl(&power_regs->hw_power_vddioctrl);
-	cur_target &= POWER_VDDIOCTRL_TRG_MASK;
-	cur_target *= 50;	/* 50 mV step*/
-	cur_target += 2800;	/* 2800 mV lowest */
+	cur_target = readl(cfg->reg);
+	cur_target &= cfg->trg_mask;
+	cur_target *= cfg->step_mV;
+	cur_target += cfg->lowest_mV;
 
-	powered_by_linreg = mxs_get_vddio_power_source_off();
-	if (new_target > cur_target) {
+	adjust_up = new_target > cur_target;
+	powered_by_linreg = cfg->powered_by_linreg();
 
+	if (adjust_up) {
 		if (powered_by_linreg) {
-			bo_int = readl(&power_regs->hw_power_vddioctrl);
-			clrbits_le32(&power_regs->hw_power_vddioctrl,
-					POWER_CTRL_ENIRQ_VDDIO_BO);
+			bo_int = readl(cfg->reg);
+			clrbits_le32(cfg->reg, cfg->bo_enirq);
 		}
+		setbits_le32(cfg->reg, cfg->bo_offset_mask);
+	}
 
-		setbits_le32(&power_regs->hw_power_vddioctrl,
-				POWER_VDDIOCTRL_BO_OFFSET_MASK);
-		do {
-			if (new_target - cur_target > 100)
+	do {
+		if (abs(new_target - cur_target) > 100) {
+			if (adjust_up)
 				diff = cur_target + 100;
 			else
-				diff = new_target;
-
-			diff -= 2800;
-			diff /= 50;
-
-			clrsetbits_le32(&power_regs->hw_power_vddioctrl,
-				POWER_VDDIOCTRL_TRG_MASK, diff);
-
-			if (powered_by_linreg ||
-				(readl(&power_regs->hw_power_sts) &
-					POWER_STS_VDD5V_GT_VDDIO))
-				early_delay(500);
-			else {
-				while (!(readl(&power_regs->hw_power_sts) &
-					POWER_STS_DC_OK))
-					;
-
-			}
-
-			cur_target = readl(&power_regs->hw_power_vddioctrl);
-			cur_target &= POWER_VDDIOCTRL_TRG_MASK;
-			cur_target *= 50;	/* 50 mV step*/
-			cur_target += 2800;	/* 2800 mV lowest */
-		} while (new_target > cur_target);
-
-		if (powered_by_linreg) {
-			writel(POWER_CTRL_VDDIO_BO_IRQ,
-				&power_regs->hw_power_ctrl_clr);
-			if (bo_int & POWER_CTRL_ENIRQ_VDDIO_BO)
-				setbits_le32(&power_regs->hw_power_vddioctrl,
-						POWER_CTRL_ENIRQ_VDDIO_BO);
-		}
-	} else {
-		do {
-			if (cur_target - new_target > 100)
 				diff = cur_target - 100;
-			else
-				diff = new_target;
-
-			diff -= 2800;
-			diff /= 50;
-
-			clrsetbits_le32(&power_regs->hw_power_vddioctrl,
-				POWER_VDDIOCTRL_TRG_MASK, diff);
-
-			if (powered_by_linreg ||
-				(readl(&power_regs->hw_power_sts) &
-					POWER_STS_VDD5V_GT_VDDIO))
-				early_delay(500);
-			else {
-				while (!(readl(&power_regs->hw_power_sts) &
-					POWER_STS_DC_OK))
-					;
-
-			}
-
-			cur_target = readl(&power_regs->hw_power_vddioctrl);
-			cur_target &= POWER_VDDIOCTRL_TRG_MASK;
-			cur_target *= 50;	/* 50 mV step*/
-			cur_target += 2800;	/* 2800 mV lowest */
-		} while (new_target < cur_target);
-	}
-
-	clrsetbits_le32(&power_regs->hw_power_vddioctrl,
-			POWER_VDDIOCTRL_BO_OFFSET_MASK,
-			new_brownout << POWER_VDDIOCTRL_BO_OFFSET_OFFSET);
-}
-
-void mxs_power_set_vddd(uint32_t new_target, uint32_t new_brownout)
-{
-	struct mxs_power_regs *power_regs =
-		(struct mxs_power_regs *)MXS_POWER_BASE;
-	uint32_t cur_target, diff, bo_int = 0;
-	uint32_t powered_by_linreg = 0;
-
-	new_brownout = (new_target - new_brownout + 12) / 25;
-
-	cur_target = readl(&power_regs->hw_power_vdddctrl);
-	cur_target &= POWER_VDDDCTRL_TRG_MASK;
-	cur_target *= 25;	/* 25 mV step*/
-	cur_target += 800;	/* 800 mV lowest */
-
-	powered_by_linreg = mxs_get_vddd_power_source_off();
-	if (new_target > cur_target) {
-		if (powered_by_linreg) {
-			bo_int = readl(&power_regs->hw_power_vdddctrl);
-			clrbits_le32(&power_regs->hw_power_vdddctrl,
-					POWER_CTRL_ENIRQ_VDDD_BO);
+		} else {
+			diff = new_target;
 		}
 
-		setbits_le32(&power_regs->hw_power_vdddctrl,
-				POWER_VDDDCTRL_BO_OFFSET_MASK);
-
-		do {
-			if (new_target - cur_target > 100)
-				diff = cur_target + 100;
-			else
-				diff = new_target;
-
-			diff -= 800;
-			diff /= 25;
-
-			clrsetbits_le32(&power_regs->hw_power_vdddctrl,
-				POWER_VDDDCTRL_TRG_MASK, diff);
+		diff -= cfg->lowest_mV;
+		diff /= cfg->step_mV;
 
-			if (powered_by_linreg ||
-				(readl(&power_regs->hw_power_sts) &
-					POWER_STS_VDD5V_GT_VDDIO))
-				early_delay(500);
-			else {
-				while (!(readl(&power_regs->hw_power_sts) &
-					POWER_STS_DC_OK))
-					;
+		clrsetbits_le32(cfg->reg, cfg->trg_mask, diff);
 
+		if (powered_by_linreg ||
+			(readl(&power_regs->hw_power_sts) &
+				POWER_STS_VDD5V_GT_VDDIO))
+			early_delay(500);
+		else {
+			for (;;) {
+				tmp = readl(&power_regs->hw_power_sts);
+				if (tmp & POWER_STS_DC_OK)
+					break;
 			}
-
-			cur_target = readl(&power_regs->hw_power_vdddctrl);
-			cur_target &= POWER_VDDDCTRL_TRG_MASK;
-			cur_target *= 25;	/* 25 mV step*/
-			cur_target += 800;	/* 800 mV lowest */
-		} while (new_target > cur_target);
-
-		if (powered_by_linreg) {
-			writel(POWER_CTRL_VDDD_BO_IRQ,
-				&power_regs->hw_power_ctrl_clr);
-			if (bo_int & POWER_CTRL_ENIRQ_VDDD_BO)
-				setbits_le32(&power_regs->hw_power_vdddctrl,
-						POWER_CTRL_ENIRQ_VDDD_BO);
 		}
-	} else {
-		do {
-			if (cur_target - new_target > 100)
-				diff = cur_target - 100;
-			else
-				diff = new_target;
 
-			diff -= 800;
-			diff /= 25;
+		cur_target = readl(cfg->reg);
+		cur_target &= cfg->trg_mask;
+		cur_target *= cfg->step_mV;
+		cur_target += cfg->lowest_mV;
+	} while (new_target > cur_target);
 
-			clrsetbits_le32(&power_regs->hw_power_vdddctrl,
-					POWER_VDDDCTRL_TRG_MASK, diff);
-
-			if (powered_by_linreg ||
-				(readl(&power_regs->hw_power_sts) &
-					POWER_STS_VDD5V_GT_VDDIO))
-				early_delay(500);
-			else {
-				while (!(readl(&power_regs->hw_power_sts) &
-					POWER_STS_DC_OK))
-					;
-
-			}
-
-			cur_target = readl(&power_regs->hw_power_vdddctrl);
-			cur_target &= POWER_VDDDCTRL_TRG_MASK;
-			cur_target *= 25;	/* 25 mV step*/
-			cur_target += 800;	/* 800 mV lowest */
-		} while (new_target < cur_target);
+	if (adjust_up && powered_by_linreg) {
+		writel(cfg->bo_irq, &power_regs->hw_power_ctrl_clr);
+		if (bo_int & cfg->bo_enirq)
+			setbits_le32(cfg->reg, cfg->bo_enirq);
 	}
 
-	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
-			POWER_VDDDCTRL_BO_OFFSET_MASK,
-			new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
+	clrsetbits_le32(cfg->reg, cfg->bo_offset_mask,
+			new_brownout << cfg->bo_offset_offset);
 }
 
 void mxs_setup_batt_detect(void)
@@ -982,9 +896,8 @@ void mxs_power_init(void)
 	mxs_power_configure_power_source();
 	mxs_enable_output_rail_protection();
 
-	mxs_power_set_vddio(3300, 3150);
-
-	mxs_power_set_vddd(1350, 1200);
+	mxs_power_set_vddx(&mxs_vddio_cfg, 3300, 3150);
+	mxs_power_set_vddx(&mxs_vddd_cfg, 1350, 1200);
 
 	writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
 		POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
Signature · 1 line
1.7.10.4
#1 lore raw

PATCH 2/2 mxs: Properly setup VDDD in power supply setup code

The memory setup code adjusted the VDDD voltage. Remove this adjustment and configure the VDDD voltage correctly in the power supply setup code.

Cc Stefano Babic <[email protected]>
Cc Fabio Estevam <[email protected]>
---
 arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c   |   13 -------------
 arch/arm/cpu/arm926ejs/mxs/spl_power_init.c |    2 +-
 2 files changed, 1 insertion(+), 14 deletions(-)
arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c +0 -13
index e693145..8904e24 100644
@@ -171,17 +171,6 @@ void mxs_mem_setup_vdda(void)
 		&power_regs->hw_power_vddactrl);
 }
 
-void mxs_mem_setup_vddd(void)
-{
-	struct mxs_power_regs *power_regs =
-		(struct mxs_power_regs *)MXS_POWER_BASE;
-
-	writel((0x1c << POWER_VDDDCTRL_TRG_OFFSET) |
-		(0x7 << POWER_VDDDCTRL_BO_OFFSET_OFFSET) |
-		POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW,
-		&power_regs->hw_power_vdddctrl);
-}
-
 uint32_t mxs_mem_get_size(void)
 {
 	uint32_t sz, da;
@@ -241,8 +230,6 @@ void mxs_mem_init(void)
 	while (!(readl(MXS_DRAM_BASE + 0xe8) & (1 << 20)))
 		;
 
-	mxs_mem_setup_vddd();
-
 	early_delay(10000);
 
 	mxs_mem_setup_cpu_and_hbus();
arch/arm/cpu/arm926ejs/mxs/spl_power_init.c +1 -1
index 0d80158..2bc6ad1 100644
@@ -897,7 +897,7 @@ void mxs_power_init(void)
 	mxs_enable_output_rail_protection();
 
 	mxs_power_set_vddx(&mxs_vddio_cfg, 3300, 3150);
-	mxs_power_set_vddx(&mxs_vddd_cfg, 1350, 1200);
+	mxs_power_set_vddx(&mxs_vddd_cfg, 1500, 1000);
 
 	writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
 		POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
Signature · 1 line
1.7.10.4
#2 lore raw

PATCH 2/2 mxs: Properly setup VDDD in power supply setup code

Quoted 11 lines · Marek Vasut

The memory setup code adjusted the VDDD voltage. Remove this adjustment and configure the VDDD voltage correctly in the power supply setup code.

Cc Stefano Babic <[email protected]>
Cc Fabio Estevam <[email protected]>
---
 arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c   |   13 -------------
 arch/arm/cpu/arm926ejs/mxs/spl_power_init.c |    2 +-
 2 files changed, 1 insertion(+), 14 deletions(-)

Applied to u-boot-imx, thanks.

Best regards,
Stefano Babic

Signature · 5 lines
=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================
#3 lore raw

PATCH 1/2 mxs: Implement common function to setup VDDx

In reply to Marek Vasut
Quoted 5 lines · Marek Vasut

Implement common function to setup the VDDIO, VDDD and VDDA voltage. Right now, there are two almost identical functions to setup VDDIO and VDDD, which is prone to breakage. Pull out the differences into constant structure and pass them as an argument to the common function.

Quoted 7 lines

Moreover, the function has almost identical loops for setting higher and lower VDDx voltage. Merge these two loops.

Cc Stefano Babic <[email protected]>
Cc Fabio Estevam <[email protected]>

I like the code cleanup but I am curious if you have taken a look if the mx23 one is compatible.

Signature · 3 lines
Otavio Salvador                             O.S. Systems
E-mail: otavio at ossystems.com.br  http://www.ossystems.com.br
Mobile: +55 53 9981-7854              http://projetos.ossystems.com.br
#4 lore raw

PATCH 1/2 mxs: Implement common function to setup VDDx

Dear Otavio Salvador,

Quoted 9 lines · Marek Vasut
Quoted 8 lines

Implement common function to setup the VDDIO, VDDD and VDDA voltage. Right now, there are two almost identical functions to setup VDDIO and VDDD, which is prone to breakage. Pull out the differences into constant structure and pass them as an argument to the common function.

Moreover, the function has almost identical loops for setting higher and lower VDDx voltage. Merge these two loops.

Quoted 6 lines
Quoted 3 lines
Cc Stefano Babic <[email protected]>
Cc Fabio Estevam <[email protected]>

I like the code cleanup but I am curious if you have taken a look if the mx23 one is compatible.

MX23 is unsupported in the mainline u-boot.

Best regards,
Marek Vasut

#5 lore raw

PATCH 1/2 mxs: Implement common function to setup VDDx

Quoted 11 lines · Marek Vasut

Dear Otavio Salvador,

Quoted 9 lines · Marek Vasut
Quoted 8 lines

Implement common function to setup the VDDIO, VDDD and VDDA voltage. Right now, there are two almost identical functions to setup VDDIO and VDDD, which is prone to breakage. Pull out the differences into constant structure and pass them as an argument to the common function.

Moreover, the function has almost identical loops for setting higher and lower VDDx voltage. Merge these two loops.

Quoted 9 lines
Quoted 6 lines
Quoted 3 lines
Cc Stefano Babic <[email protected]>
Cc Fabio Estevam <[email protected]>

I like the code cleanup but I am curious if you have taken a look if the mx23 one is compatible.

MX23 is unsupported in the mainline u-boot.

I see ...

Signature · 3 lines
Otavio Salvador                             O.S. Systems
E-mail: otavio at ossystems.com.br  http://www.ossystems.com.br
Mobile: +55 53 9981-7854              http://projetos.ossystems.com.br
#6 lore raw

PATCH 1/2 mxs: Implement common function to setup VDDx

In reply to Marek Vasut
Quoted 5 lines · Marek Vasut

Implement common function to setup the VDDIO, VDDD and VDDA voltage. Right now, there are two almost identical functions to setup VDDIO and VDDD, which is prone to breakage. Pull out the differences into constant structure and pass them as an argument to the common function.

Quoted 7 lines

Moreover, the function has almost identical loops for setting higher and lower VDDx voltage. Merge these two loops.

Cc Stefano Babic <[email protected]>
Cc Fabio Estevam <[email protected]>

---

Applied to u-boot-imx, thanks.

Best regards,
Stefano Babic

Signature · 5 lines
=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================