xref: /netbsd-src/sys/arch/evbarm/stand/bootimx23/power_prep.c (revision 4db03d42c9db855752ae131e52df3637db5afb32)
1*4db03d42Sskrll /* $Id: power_prep.c,v 1.5 2016/08/17 22:04:51 skrll Exp $ */
2da8587eaSjkunz 
3da8587eaSjkunz /*
4da8587eaSjkunz  * Copyright (c) 2012 The NetBSD Foundation, Inc.
5da8587eaSjkunz  * All rights reserved.
6da8587eaSjkunz  *
7da8587eaSjkunz  * This code is derived from software contributed to The NetBSD Foundation
8da8587eaSjkunz  * by Petri Laakso.
9da8587eaSjkunz  *
10da8587eaSjkunz  * Redistribution and use in source and binary forms, with or without
11da8587eaSjkunz  * modification, are permitted provided that the following conditions
12da8587eaSjkunz  * are met:
13da8587eaSjkunz  * 1. Redistributions of source code must retain the above copyright
14da8587eaSjkunz  *    notice, this list of conditions and the following disclaimer.
15da8587eaSjkunz  * 2. Redistributions in binary form must reproduce the above copyright
16da8587eaSjkunz  *    notice, this list of conditions and the following disclaimer in the
17da8587eaSjkunz  *    documentation and/or other materials provided with the distribution.
18da8587eaSjkunz  *
19da8587eaSjkunz  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20da8587eaSjkunz  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21da8587eaSjkunz  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22da8587eaSjkunz  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23da8587eaSjkunz  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24da8587eaSjkunz  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25da8587eaSjkunz  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26da8587eaSjkunz  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27da8587eaSjkunz  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28da8587eaSjkunz  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29da8587eaSjkunz  * POSSIBILITY OF SUCH DAMAGE.
30da8587eaSjkunz  */
31da8587eaSjkunz 
3294de0730Smatt #include <sys/cdefs.h>
33da8587eaSjkunz #include <sys/param.h>
34da8587eaSjkunz #include <sys/types.h>
35da8587eaSjkunz 
36da8587eaSjkunz #include <arm/imx/imx23_powerreg.h>
37da8587eaSjkunz 
3894de0730Smatt #include <lib/libkern/libkern.h>
39da8587eaSjkunz #include <lib/libsa/stand.h>
40da8587eaSjkunz 
41da8587eaSjkunz #include "common.h"
42da8587eaSjkunz 
4394de0730Smatt #define PWR_CTRL	(HW_POWER_BASE + HW_POWER_CTRL)
4494de0730Smatt #define PWR_CTRL_S	(HW_POWER_BASE + HW_POWER_CTRL_SET)
4594de0730Smatt #define PWR_CTRL_C	(HW_POWER_BASE + HW_POWER_CTRL_CLR)
4694de0730Smatt #define PWR_5VCTRL	(HW_POWER_BASE + HW_POWER_5VCTRL)
4794de0730Smatt #define PWR_5VCTRL_S	(HW_POWER_BASE + HW_POWER_5VCTRL_SET)
4894de0730Smatt #define PWR_5VCTRL_C	(HW_POWER_BASE + HW_POWER_5VCTRL_CLR)
4994de0730Smatt #define PWR_MINPWR	(HW_POWER_BASE + HW_POWER_MINPWR)
5094de0730Smatt #define PWR_MINPWR_S	(HW_POWER_BASE + HW_POWER_MINPWR_SET)
5194de0730Smatt #define PWR_MINPWR_C	(HW_POWER_BASE + HW_POWER_MINPWR_CLR)
5294de0730Smatt #define PWR_CHARGE	(HW_POWER_BASE + HW_POWER_CHARGE)
5394de0730Smatt #define PWR_CHARGE_S	(HW_POWER_BASE + HW_POWER_CHARGE_SET)
5494de0730Smatt #define PWR_CHARGE_C	(HW_POWER_BASE + HW_POWER_CHARGE_CLR)
5594de0730Smatt #define PWR_VDDDCTRL	(HW_POWER_BASE + HW_POWER_VDDDCTRL)
5694de0730Smatt #define PWR_VDDACTRL	(HW_POWER_BASE + HW_POWER_VDDACTRL)
5794de0730Smatt #define PWR_VDDIOCTRL	(HW_POWER_BASE + HW_POWER_VDDIOCTRL)
5894de0730Smatt #define PWR_VDDMEMCTRL	(HW_POWER_BASE + HW_POWER_VDDMEMCTRL)
5994de0730Smatt #define PWR_DCDC4P2	(HW_POWER_BASE + HW_POWER_DCDC4P2)
6094de0730Smatt #define PWR_MISC	(HW_POWER_BASE + HW_POWER_MISC)
6194de0730Smatt #define PWR_DCLIMITS	(HW_POWER_BASE + HW_POWER_DCLIMITS)
6294de0730Smatt #define PWR_LOOPCTRL 	(HW_POWER_BASE + HW_POWER_LOOPCTRL)
6394de0730Smatt #define PWR_LOOPCTRL_S	(HW_POWER_BASE + HW_POWER_LOOPCTRL_SET)
6494de0730Smatt #define PWR_LOOPCTRL_C	(HW_POWER_BASE + HW_POWER_LOOPCTRL_CLR)
6594de0730Smatt #define PWR_STATUS	(HW_POWER_BASE + HW_POWER_STS)
6694de0730Smatt #define PWR_SPEED	(HW_POWER_BASE + HW_POWER_SPEED)
6794de0730Smatt #define PWR_BATTMONITOR	(HW_POWER_BASE + HW_POWER_BATTMONITOR)
6894de0730Smatt #define PWR_RESET	(HW_POWER_BASE + HW_POWER_RESET)
6994de0730Smatt #define PWR_DEBUG	(HW_POWER_BASE + HW_POWER_DEBUG)
7094de0730Smatt #define PWR_SPECIAL	(HW_POWER_BASE + HW_POWER_SPECIAL)
7194de0730Smatt #define PWR_VERSION	(HW_POWER_BASE + HW_POWER_VERSION)
725379dc38Sjkunz 
7394de0730Smatt #define VBUSVALID_TRSH 5	/* 4.4V */
7494de0730Smatt #define CHARGE_4P2_ILIMIT_MAX 0x3f
7594de0730Smatt #define CMPTRIP 0x1f	/* DCDC_4P2 pin >= 1.05 * BATTERY pin. */
7694de0730Smatt #define DROPOUT_CTRL 0xa /* BO 100mV, DCDC selects higher. */
775379dc38Sjkunz 
7894de0730Smatt void en_vbusvalid(void);
7994de0730Smatt int vbusvalid(void);
8094de0730Smatt void power_tune(void);
8194de0730Smatt void en_4p2_reg(void);
8294de0730Smatt void en_4p2_to_dcdc(void);
8394de0730Smatt void power_vddd_from_dcdc(int, int);
8494de0730Smatt void power_vdda_from_dcdc(int, int);
8594de0730Smatt void power_vddio_from_dcdc(int, int);
8694de0730Smatt void power_vddmem(int);
87da8587eaSjkunz 
88da8587eaSjkunz /*
8994de0730Smatt  * Configure the DCDC control logic 5V detection to use VBUSVALID.
9094de0730Smatt  */
9194de0730Smatt void
en_vbusvalid(void)9294de0730Smatt en_vbusvalid(void)
9394de0730Smatt {
9494de0730Smatt 	uint32_t tmp_r;
9594de0730Smatt 
9694de0730Smatt 	tmp_r = REG_RD(PWR_5VCTRL);
9794de0730Smatt 	tmp_r &= ~HW_POWER_5VCTRL_VBUSVALID_TRSH;
9894de0730Smatt 	tmp_r |= __SHIFTIN(VBUSVALID_TRSH, HW_POWER_5VCTRL_VBUSVALID_TRSH);
9994de0730Smatt 	REG_WR(PWR_5VCTRL, tmp_r);
10094de0730Smatt 
10194de0730Smatt 	REG_WR(PWR_5VCTRL_S, HW_POWER_5VCTRL_PWRUP_VBUS_CMPS);
10294de0730Smatt 	delay(1000);
10394de0730Smatt 
10494de0730Smatt 	REG_WR(PWR_5VCTRL_S, HW_POWER_5VCTRL_VBUSVALID_5VDETECT);
10594de0730Smatt 
10694de0730Smatt 	return;
10794de0730Smatt }
10894de0730Smatt /*
10994de0730Smatt  * Test VBUSVALID.
110da8587eaSjkunz  */
111da8587eaSjkunz int
vbusvalid(void)11294de0730Smatt vbusvalid(void)
113da8587eaSjkunz {
11494de0730Smatt 	if (REG_RD(PWR_STATUS) & HW_POWER_STS_VBUSVALID)
11594de0730Smatt 		return 1;
1165379dc38Sjkunz 	else
117da8587eaSjkunz 		return 0;
118da8587eaSjkunz }
119da8587eaSjkunz /*
12094de0730Smatt  * Set various registers.
121da8587eaSjkunz  */
12294de0730Smatt void
power_tune(void)12394de0730Smatt power_tune(void)
124da8587eaSjkunz {
12594de0730Smatt 	uint32_t tmp_r;
126da8587eaSjkunz 
12794de0730Smatt 	REG_WR(PWR_LOOPCTRL_S, HW_POWER_LOOPCTRL_TOGGLE_DIF |
12894de0730Smatt 		HW_POWER_LOOPCTRL_EN_CM_HYST |
12994de0730Smatt 		HW_POWER_LOOPCTRL_EN_DF_HYST |
13094de0730Smatt 		HW_POWER_LOOPCTRL_RCSCALE_THRESH |
13194de0730Smatt 		__SHIFTIN(3, HW_POWER_LOOPCTRL_EN_RCSCALE));
132da8587eaSjkunz 
13394de0730Smatt 	REG_WR(PWR_MINPWR_S, HW_POWER_MINPWR_DOUBLE_FETS);
13494de0730Smatt 
13594de0730Smatt 	REG_WR(PWR_5VCTRL_S, __SHIFTIN(4, HW_POWER_5VCTRL_HEADROOM_ADJ));
13694de0730Smatt 
13794de0730Smatt 	tmp_r = REG_RD(PWR_DCLIMITS);
13894de0730Smatt 	tmp_r &= ~HW_POWER_DCLIMITS_POSLIMIT_BUCK;
13994de0730Smatt 	tmp_r |= __SHIFTIN(0x30, HW_POWER_DCLIMITS_POSLIMIT_BUCK);
14094de0730Smatt 	REG_WR(PWR_DCLIMITS, tmp_r);
14194de0730Smatt 
14294de0730Smatt 	return;
14394de0730Smatt }
144da8587eaSjkunz /*
14594de0730Smatt  * AN3883.pdf 2.1.3.1 Enabling the 4P2 LinReg
146da8587eaSjkunz  */
14794de0730Smatt void
en_4p2_reg(void)14894de0730Smatt en_4p2_reg(void)
14994de0730Smatt {
15094de0730Smatt 	uint32_t tmp_r;
15194de0730Smatt 	int ilimit;
152da8587eaSjkunz 
15394de0730Smatt 	/* TRG is 4.2V by default. */
15494de0730Smatt 	tmp_r = REG_RD(PWR_DCDC4P2);
15594de0730Smatt 	tmp_r |= HW_POWER_DCDC4P2_ENABLE_4P2;
15694de0730Smatt 	REG_WR(PWR_DCDC4P2, tmp_r);
157da8587eaSjkunz 
15894de0730Smatt 	REG_WR(PWR_CHARGE_S, HW_POWER_CHARGE_ENABLE_LOAD);
159da8587eaSjkunz 
16094de0730Smatt 	/* Set CHARGE_4P2_ILIMIT to minimum. */
16194de0730Smatt 	REG_WR(PWR_5VCTRL_C, HW_POWER_5VCTRL_CHARGE_4P2_ILIMIT);
16294de0730Smatt 	REG_WR(PWR_5VCTRL_S, __SHIFTIN(1, HW_POWER_5VCTRL_CHARGE_4P2_ILIMIT));
16394de0730Smatt 
16494de0730Smatt 	/* Power up 4.2V regulation circuit. */
16594de0730Smatt 	REG_WR(PWR_5VCTRL_C, HW_POWER_5VCTRL_PWD_CHARGE_4P2);
16694de0730Smatt 
16794de0730Smatt 	/* Ungate path from 4P2 reg to DCDC. */
16894de0730Smatt 	tmp_r = REG_RD(PWR_DCDC4P2);
16994de0730Smatt 	tmp_r |= HW_POWER_DCDC4P2_ENABLE_DCDC;
17094de0730Smatt 	REG_WR(PWR_DCDC4P2, tmp_r);
17194de0730Smatt 
17294de0730Smatt 	delay(10000);
17394de0730Smatt 
17494de0730Smatt 	/* Charge 4P2 capacitance. */
17594de0730Smatt 	tmp_r = REG_RD(PWR_5VCTRL);
17694de0730Smatt 	for (ilimit = 2; ilimit <= CHARGE_4P2_ILIMIT_MAX; ilimit++) {
17794de0730Smatt 		tmp_r &= ~HW_POWER_5VCTRL_CHARGE_4P2_ILIMIT;
17894de0730Smatt 		tmp_r |= __SHIFTIN(ilimit, HW_POWER_5VCTRL_CHARGE_4P2_ILIMIT);
17994de0730Smatt 		REG_WR(PWR_5VCTRL, tmp_r);
18094de0730Smatt 		delay(10000);
181da8587eaSjkunz 	}
182da8587eaSjkunz 
183da8587eaSjkunz 	return;
184da8587eaSjkunz }
185da8587eaSjkunz 
18694de0730Smatt /*
18794de0730Smatt  * AN3883.pdf 2.1.3.3 Enabling 4P2 Input to DC-DC
18894de0730Smatt  */
en_4p2_to_dcdc(void)18994de0730Smatt void en_4p2_to_dcdc(void)
190da8587eaSjkunz {
19194de0730Smatt 	uint32_t tmp_r;
192da8587eaSjkunz 
19394de0730Smatt 	tmp_r = REG_RD(PWR_DCDC4P2);
194da8587eaSjkunz 
19594de0730Smatt 	tmp_r &= ~HW_POWER_DCDC4P2_CMPTRIP;
19694de0730Smatt 	tmp_r |= __SHIFTIN(CMPTRIP, HW_POWER_DCDC4P2_CMPTRIP);
197da8587eaSjkunz 
19894de0730Smatt 	tmp_r &= ~HW_POWER_DCDC4P2_DROPOUT_CTRL;
19994de0730Smatt 	tmp_r |= __SHIFTIN(DROPOUT_CTRL, HW_POWER_DCDC4P2_DROPOUT_CTRL);
200da8587eaSjkunz 
20194de0730Smatt 	REG_WR(PWR_DCDC4P2, tmp_r);
20294de0730Smatt 
20394de0730Smatt 	REG_WR(PWR_5VCTRL_C, HW_POWER_5VCTRL_DCDC_XFER);
20494de0730Smatt 
20594de0730Smatt 	/* Enabling DCDC triggers 5V brownout. */
20694de0730Smatt 	REG_WR(PWR_5VCTRL_C, HW_POWER_5VCTRL_PWDN_5VBRNOUT);
20794de0730Smatt 	REG_WR(PWR_5VCTRL_S, HW_POWER_5VCTRL_ENABLE_DCDC);
20894de0730Smatt 	delay(10000);
20994de0730Smatt 	REG_WR(PWR_5VCTRL_S, HW_POWER_5VCTRL_PWDN_5VBRNOUT);
21094de0730Smatt 
21194de0730Smatt 	/* Now DCDC is using 4P2 so I can remove extra temporary load. */
21294de0730Smatt 	REG_WR(PWR_CHARGE_C, HW_POWER_CHARGE_ENABLE_LOAD);
213da8587eaSjkunz 
214da8587eaSjkunz 	return;
215da8587eaSjkunz }
216da8587eaSjkunz 
21794de0730Smatt /*
21894de0730Smatt  * Configure VDDD to source power from DCDC.
21994de0730Smatt  */
22094de0730Smatt void
power_vddd_from_dcdc(int target,int brownout)22194de0730Smatt power_vddd_from_dcdc(int target, int brownout)
222da8587eaSjkunz {
22394de0730Smatt 	uint32_t tmp_r;
224da8587eaSjkunz 
225*4db03d42Sskrll 	/* BO_OFFSET must be within 800mV - 1475mV */
22694de0730Smatt 	if (brownout > 1475)
22794de0730Smatt 		brownout = 1475;
22894de0730Smatt 	else if (brownout < 800)
22994de0730Smatt 		brownout = 800;
230da8587eaSjkunz 
231da8587eaSjkunz 
23294de0730Smatt 	/* Set LINREG_OFFSET one step below TRG. */
23394de0730Smatt 	tmp_r = REG_RD(PWR_VDDDCTRL);
23494de0730Smatt 	tmp_r &= ~HW_POWER_VDDDCTRL_LINREG_OFFSET;
23594de0730Smatt 	tmp_r |= __SHIFTIN(2, HW_POWER_VDDDCTRL_LINREG_OFFSET);
23694de0730Smatt 	REG_WR(PWR_VDDDCTRL, tmp_r);
23794de0730Smatt 	delay(10000);
238da8587eaSjkunz 
23994de0730Smatt 	/* Enable VDDD switching converter output. */
24094de0730Smatt 	tmp_r = REG_RD(PWR_VDDDCTRL);
24194de0730Smatt 	tmp_r &= ~HW_POWER_VDDDCTRL_DISABLE_FET;
24294de0730Smatt 	REG_WR(PWR_VDDDCTRL, tmp_r);
24394de0730Smatt 	delay(10000);
24494de0730Smatt 
24594de0730Smatt 	/* Disable linear regulator output. */
24694de0730Smatt 	tmp_r = REG_RD(PWR_VDDDCTRL);
24794de0730Smatt 	tmp_r &= ~HW_POWER_VDDDCTRL_ENABLE_LINREG;
24894de0730Smatt 	REG_WR(PWR_VDDDCTRL, tmp_r);
24994de0730Smatt 	delay(10000);
25094de0730Smatt 
25194de0730Smatt 	/* Set target voltage and brownout level. */
25294de0730Smatt 	tmp_r = REG_RD(PWR_VDDDCTRL);
25394de0730Smatt 	tmp_r &= ~(HW_POWER_VDDDCTRL_BO_OFFSET | HW_POWER_VDDDCTRL_TRG);
25494de0730Smatt 	tmp_r |= __SHIFTIN(((target - brownout) / 25),
25594de0730Smatt 		HW_POWER_VDDDCTRL_BO_OFFSET);
25694de0730Smatt 	tmp_r |= __SHIFTIN(((target - 800) / 25), HW_POWER_VDDDCTRL_TRG);
25794de0730Smatt 	REG_WR(PWR_VDDDCTRL, tmp_r);
25894de0730Smatt 	delay(10000);
25994de0730Smatt 
26094de0730Smatt 	/* Enable PWDN_BRNOUT. */
26194de0730Smatt 	REG_WR(PWR_CTRL_C, HW_POWER_CTRL_VDDD_BO_IRQ);
26294de0730Smatt 
26394de0730Smatt 	tmp_r = REG_RD(PWR_VDDDCTRL);
26494de0730Smatt 	tmp_r |= HW_POWER_VDDDCTRL_PWDN_BRNOUT;
26594de0730Smatt 	REG_WR(PWR_VDDDCTRL, tmp_r);
266da8587eaSjkunz 
267da8587eaSjkunz 	return;
268da8587eaSjkunz }
26994de0730Smatt /*
27094de0730Smatt  * Configure VDDA to source power from DCDC.
27194de0730Smatt  */
27294de0730Smatt void
power_vdda_from_dcdc(int target,int brownout)27394de0730Smatt power_vdda_from_dcdc(int target, int brownout)
274da8587eaSjkunz {
27594de0730Smatt 	uint32_t tmp_r;
276da8587eaSjkunz 
277*4db03d42Sskrll 	/* BO_OFFSET must be within 1400mV - 2175mV */
27894de0730Smatt 	if (brownout > 2275)
27994de0730Smatt 		brownout = 2275;
28094de0730Smatt 	else if (brownout < 1400)
28194de0730Smatt 		brownout = 1400;
282da8587eaSjkunz 
28394de0730Smatt 
28494de0730Smatt 	/* Set LINREG_OFFSET one step below TRG. */
28594de0730Smatt 	tmp_r = REG_RD(PWR_VDDACTRL);
28694de0730Smatt 	tmp_r &= ~HW_POWER_VDDACTRL_LINREG_OFFSET;
28794de0730Smatt 	tmp_r |= __SHIFTIN(2, HW_POWER_VDDACTRL_LINREG_OFFSET);
28894de0730Smatt 	REG_WR(PWR_VDDACTRL, tmp_r);
28994de0730Smatt 	delay(10000);
29094de0730Smatt 
29194de0730Smatt 	/* Enable VDDA switching converter output. */
29294de0730Smatt 	tmp_r = REG_RD(PWR_VDDACTRL);
29394de0730Smatt 	tmp_r &= ~HW_POWER_VDDACTRL_DISABLE_FET;
29494de0730Smatt 	REG_WR(PWR_VDDACTRL, tmp_r);
29594de0730Smatt 	delay(10000);
29694de0730Smatt 
29794de0730Smatt 	/* Disable linear regulator output. */
29894de0730Smatt 	tmp_r = REG_RD(PWR_VDDACTRL);
29994de0730Smatt 	tmp_r &= ~HW_POWER_VDDACTRL_ENABLE_LINREG;
30094de0730Smatt 	REG_WR(PWR_VDDACTRL, tmp_r);
30194de0730Smatt 	delay(10000);
30294de0730Smatt 
30394de0730Smatt 	/* Set target voltage and brownout level. */
30494de0730Smatt 	tmp_r = REG_RD(PWR_VDDACTRL);
30594de0730Smatt 	tmp_r &= ~(HW_POWER_VDDACTRL_BO_OFFSET | HW_POWER_VDDACTRL_TRG);
30694de0730Smatt 	tmp_r |= __SHIFTIN(((target - brownout) / 25),
30794de0730Smatt 		HW_POWER_VDDACTRL_BO_OFFSET);
30894de0730Smatt 	tmp_r |= __SHIFTIN(((target - 1500) / 25), HW_POWER_VDDACTRL_TRG);
30994de0730Smatt 	REG_WR(PWR_VDDACTRL, tmp_r);
31094de0730Smatt 	delay(10000);
31194de0730Smatt 
31294de0730Smatt 	/* Enable PWDN_BRNOUT. */
31394de0730Smatt 	REG_WR(PWR_CTRL_C, HW_POWER_CTRL_VDDA_BO_IRQ);
31494de0730Smatt 
31594de0730Smatt 	tmp_r = REG_RD(PWR_VDDACTRL);
31694de0730Smatt 	tmp_r |= HW_POWER_VDDACTRL_PWDN_BRNOUT;
31794de0730Smatt 	REG_WR(PWR_VDDACTRL, tmp_r);
31894de0730Smatt 
31994de0730Smatt 	return;
32094de0730Smatt }
32194de0730Smatt /*
32294de0730Smatt  * Configure VDDIO to source power from DCDC.
32394de0730Smatt  */
32494de0730Smatt void
power_vddio_from_dcdc(int target,int brownout)32594de0730Smatt power_vddio_from_dcdc(int target, int brownout)
32694de0730Smatt {
32794de0730Smatt 	uint32_t tmp_r;
32894de0730Smatt 
329*4db03d42Sskrll 	/* BO_OFFSET must be within 2700mV - 3475mV */
33094de0730Smatt 	if (brownout > 3475)
33194de0730Smatt 		brownout = 3475;
33294de0730Smatt 	else if (brownout < 2700)
33394de0730Smatt 		brownout = 2700;
33494de0730Smatt 
33594de0730Smatt 
33694de0730Smatt 	/* Set LINREG_OFFSET one step below TRG. */
33794de0730Smatt 	tmp_r = REG_RD(PWR_VDDIOCTRL);
33894de0730Smatt 	tmp_r &= ~HW_POWER_VDDIOCTRL_LINREG_OFFSET;
33994de0730Smatt 	tmp_r |= __SHIFTIN(2, HW_POWER_VDDIOCTRL_LINREG_OFFSET);
34094de0730Smatt 	REG_WR(PWR_VDDIOCTRL, tmp_r);
34194de0730Smatt 	delay(10000);
34294de0730Smatt 
34394de0730Smatt 	/* Enable VDDIO switching converter output. */
34494de0730Smatt 	tmp_r = REG_RD(PWR_VDDIOCTRL);
34594de0730Smatt 	tmp_r &= ~HW_POWER_VDDIOCTRL_DISABLE_FET;
34694de0730Smatt 	REG_WR(PWR_VDDIOCTRL, tmp_r);
34794de0730Smatt 	delay(10000);
34894de0730Smatt 
34994de0730Smatt 	/* Set target voltage and brownout level. */
35094de0730Smatt 	tmp_r = REG_RD(PWR_VDDIOCTRL);
35194de0730Smatt 	tmp_r &= ~(HW_POWER_VDDIOCTRL_BO_OFFSET | HW_POWER_VDDIOCTRL_TRG);
35294de0730Smatt 	tmp_r |= __SHIFTIN(((target - brownout) / 25),
35394de0730Smatt 		HW_POWER_VDDIOCTRL_BO_OFFSET);
35494de0730Smatt 	tmp_r |= __SHIFTIN(((target - 2800) / 25), HW_POWER_VDDIOCTRL_TRG);
35594de0730Smatt 	REG_WR(PWR_VDDIOCTRL, tmp_r);
35694de0730Smatt 	delay(10000);
35794de0730Smatt 
35894de0730Smatt 	/* Enable PWDN_BRNOUT. */
35994de0730Smatt 	REG_WR(PWR_CTRL_C, HW_POWER_CTRL_VDDIO_BO_IRQ);
36094de0730Smatt 
36194de0730Smatt 	tmp_r = REG_RD(PWR_VDDIOCTRL);
36294de0730Smatt 	tmp_r |= HW_POWER_VDDIOCTRL_PWDN_BRNOUT;
36394de0730Smatt 	REG_WR(PWR_VDDIOCTRL, tmp_r);
36494de0730Smatt 
36594de0730Smatt 	return;
36694de0730Smatt }
36794de0730Smatt /*
36894de0730Smatt  * AN3883.pdf 2.3.1.2 Setting VDDMEM Target Voltage
36994de0730Smatt  */
37094de0730Smatt void
power_vddmem(int target)37194de0730Smatt power_vddmem(int target)
37294de0730Smatt {
37394de0730Smatt 	uint32_t tmp_r;
37494de0730Smatt 
37594de0730Smatt 	/* Set target voltage. */
37694de0730Smatt 	tmp_r = REG_RD(PWR_VDDMEMCTRL);
37794de0730Smatt 	tmp_r &= ~(HW_POWER_VDDMEMCTRL_TRG);
37894de0730Smatt 	tmp_r |= __SHIFTIN(((target - 1700) / 50), HW_POWER_VDDMEMCTRL_TRG);
37994de0730Smatt 	REG_WR(PWR_VDDMEMCTRL, tmp_r);
38094de0730Smatt 	delay(10000);
38194de0730Smatt 
38294de0730Smatt 	tmp_r = REG_RD(PWR_VDDMEMCTRL);
38394de0730Smatt 	tmp_r |= (HW_POWER_VDDMEMCTRL_PULLDOWN_ACTIVE |
384da8587eaSjkunz 		HW_POWER_VDDMEMCTRL_ENABLE_ILIMIT |
385da8587eaSjkunz 		HW_POWER_VDDMEMCTRL_ENABLE_LINREG);
38694de0730Smatt 	REG_WR(PWR_VDDMEMCTRL, tmp_r);
38794de0730Smatt 
38894de0730Smatt 	delay(1000);
38994de0730Smatt 
39094de0730Smatt 	tmp_r = REG_RD(PWR_VDDMEMCTRL);
39194de0730Smatt 	tmp_r &= ~(HW_POWER_VDDMEMCTRL_PULLDOWN_ACTIVE |
392da8587eaSjkunz 		HW_POWER_VDDMEMCTRL_ENABLE_ILIMIT);
39394de0730Smatt 	REG_WR(PWR_VDDMEMCTRL, tmp_r);
394da8587eaSjkunz 
395da8587eaSjkunz 	return;
396da8587eaSjkunz }
397