Home | History | Annotate | Line # | Download | only in bootimx23
power_prep.c revision 1.3
      1 /* $Id: power_prep.c,v 1.3 2012/12/16 19:08:45 jkunz Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2012 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Petri Laakso.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/param.h>
     33 #include <sys/types.h>
     34 #include <sys/cdefs.h>
     35 
     36 #include <arm/imx/imx23_powerreg.h>
     37 
     38 #include <lib/libsa/stand.h>
     39 
     40 #include "common.h"
     41 
     42 static void set_vddd_target(uint8_t);
     43 static void set_vdda_target(uint8_t);
     44 static void set_vddio_target(uint8_t);
     45 static void set_vddmem_target(uint8_t);
     46 #ifdef DEBUG
     47 static void print_regs(void);
     48 #endif
     49 
     50 #define VDDD_TARGET	0x1e	/* 1550 mV */
     51 #define VDDA_TARGET	0x0a	/* 1750 mV */
     52 #define VDDIO_TARGET	0x0c	/* 3100 mV */
     53 #define VDDMEM_TARGET	0x10	/* 2500 mV */
     54 
     55 static int five_volts = 0;
     56 
     57 /*
     58  * If 5V is present, all power rails are powered from the LinRegs.
     59  *
     60  * If powered from the battery, the DC-DC converter starts when battery power
     61  * is detected and the PSWITCH button is pressed. In this state, the VDDA and
     62  * VDDIO rails are powered on from DC-DC, but the VDDD rail is powered from its
     63  * LinReg.
     64  */
     65 int
     66 power_prep(void)
     67 {
     68 	if (REG_RD(HW_POWER_BASE + HW_POWER_STS) & HW_POWER_STS_VDD5V_GT_VDDIO)
     69 		five_volts = 1;
     70 #ifdef DEBUG
     71 	if (five_volts)
     72 		printf("Powered from 5V\n\r");
     73 	else
     74 		printf("Powered from the battery.\n\r");
     75 	print_regs();
     76 #endif
     77 	set_vddd_target(VDDD_TARGET);
     78 	set_vdda_target(VDDA_TARGET);
     79 	set_vddio_target(VDDIO_TARGET);
     80 	set_vddmem_target(VDDMEM_TARGET);
     81 #ifdef DEBUG
     82 	print_regs();
     83 #endif
     84 	return 0;
     85 }
     86 
     87 /*
     88  * Set VDDD target voltage.
     89  */
     90 static void
     91 set_vddd_target(uint8_t target)
     92 {
     93 	uint32_t vddd;
     94 	uint8_t curtrg;
     95 
     96 	vddd = REG_RD(HW_POWER_BASE + HW_POWER_VDDDCTRL);
     97 
     98 	/*
     99 	 * VDDD is always powered from the linear regulator.
    100 	 *
    101 	 * Setting LINREG_OFFSET to 0 is recommended when powering VDDD from
    102 	 * the linear regulator. It is also recommended to set DISABLE_STEPPING
    103 	 * when powering VDDD from the linear regulators.
    104 	 */
    105 	vddd &= ~(HW_POWER_VDDDCTRL_LINREG_OFFSET);
    106 	vddd |= HW_POWER_VDDDCTRL_DISABLE_STEPPING;
    107 
    108 	REG_WR(HW_POWER_BASE + HW_POWER_VDDDCTRL, vddd);
    109 	delay(1000);
    110 
    111 	curtrg = __SHIFTOUT(vddd, HW_POWER_VDDDCTRL_TRG);
    112 
    113 	/* Because HW stepping is disabled, raise voltage to target slowly. */
    114 	for (curtrg++; curtrg <= target; curtrg++) {
    115 		vddd = REG_RD(HW_POWER_BASE + HW_POWER_VDDDCTRL);
    116 		vddd &= ~(HW_POWER_VDDDCTRL_TRG);
    117 		vddd |= __SHIFTIN(curtrg, HW_POWER_VDDDCTRL_TRG);
    118 		REG_WR(HW_POWER_BASE + HW_POWER_VDDDCTRL, vddd);
    119 		delay(1000);
    120 	}
    121 
    122 	return;
    123 }
    124 
    125 static void
    126 set_vdda_target(uint8_t target)
    127 {
    128 	uint32_t vdda;
    129 	uint8_t curtrg;
    130 
    131 	vdda = REG_RD(HW_POWER_BASE + HW_POWER_VDDACTRL);
    132 
    133 	/*
    134 	 * Setting LINREG_OFFSET to 0 is recommended when powering VDDA from
    135 	 * the linear regulator. It is also recommended to set DISABLE_STEPPING
    136 	 * when powering VDDA from the linear regulators.
    137 	 */
    138 	if (five_volts) {
    139 		vdda &= ~(HW_POWER_VDDACTRL_LINREG_OFFSET);
    140 		vdda |= HW_POWER_VDDACTRL_DISABLE_STEPPING;
    141 		REG_WR(HW_POWER_BASE + HW_POWER_VDDACTRL, vdda);
    142 		delay(1000);
    143 
    144 		curtrg = __SHIFTOUT(vdda, HW_POWER_VDDACTRL_TRG);
    145 
    146 		/*
    147 		 * Because HW stepping is disabled, raise voltage to target
    148 		 * slowly.
    149 		 */
    150 		for (curtrg++; curtrg <= target; curtrg++) {
    151 			vdda = REG_RD(HW_POWER_BASE + HW_POWER_VDDACTRL);
    152 			vdda &= ~(HW_POWER_VDDACTRL_TRG);
    153 			vdda |= __SHIFTIN(curtrg, HW_POWER_VDDACTRL_TRG);
    154 			REG_WR(HW_POWER_BASE + HW_POWER_VDDACTRL, vdda);
    155 			delay(1000);
    156 		}
    157 	} else {
    158 		vdda |= __SHIFTIN(target, HW_POWER_VDDACTRL_TRG);
    159 		REG_WR(HW_POWER_BASE + HW_POWER_VDDACTRL, vdda);
    160 	}
    161 
    162 	return;
    163 }
    164 
    165 static void
    166 set_vddio_target(uint8_t target)
    167 {
    168 	uint32_t vddio;
    169 	uint8_t curtrg;
    170 
    171 	vddio = REG_RD(HW_POWER_BASE + HW_POWER_VDDIOCTRL);
    172 
    173 	/*
    174 	 * Setting LINREG_OFFSET to 0 is recommended when powering VDDIO from
    175 	 * the linear regulator. It is also recommended to set DISABLE_STEPPING
    176 	 * when powering VDDIO from the linear regulators.
    177 	 */
    178 	if (five_volts) {
    179 		vddio &= ~(HW_POWER_VDDIOCTRL_LINREG_OFFSET);
    180 		vddio |= HW_POWER_VDDIOCTRL_DISABLE_STEPPING;
    181 		REG_WR(HW_POWER_BASE + HW_POWER_VDDIOCTRL, vddio);
    182 		delay(1000);
    183 
    184 		curtrg = __SHIFTOUT(vddio, HW_POWER_VDDIOCTRL_TRG);
    185 
    186 		/*
    187 		 * Because HW stepping is disabled, raise voltage to target
    188 		 * slowly.
    189 		 */
    190 		for (curtrg++; curtrg <= target; curtrg++) {
    191 			vddio = REG_RD(HW_POWER_BASE + HW_POWER_VDDIOCTRL);
    192 			vddio &= ~(HW_POWER_VDDIOCTRL_TRG);
    193 			vddio |= __SHIFTIN(curtrg, HW_POWER_VDDIOCTRL_TRG);
    194 			REG_WR(HW_POWER_BASE + HW_POWER_VDDIOCTRL, vddio);
    195 			delay(1000);
    196 		}
    197 	} else {
    198 		vddio |= __SHIFTIN(target, HW_POWER_VDDIOCTRL_TRG);
    199 		REG_WR(HW_POWER_BASE + HW_POWER_VDDIOCTRL, vddio);
    200 	}
    201 
    202 	return;
    203 }
    204 
    205 static void
    206 set_vddmem_target(uint8_t target)
    207 {
    208 	uint32_t vddmem;
    209 
    210 	/* Set target. */
    211 	vddmem = REG_RD(HW_POWER_BASE + HW_POWER_VDDMEMCTRL);
    212 	vddmem &= ~(HW_POWER_VDDMEMCTRL_TRG);
    213 	vddmem |= __SHIFTIN(target, HW_POWER_VDDMEMCTRL_TRG);
    214 	REG_WR(HW_POWER_BASE + HW_POWER_VDDMEMCTRL, vddmem);
    215 	delay(1000);
    216 
    217 	/* Enable VDDMEM */
    218 	vddmem = REG_RD(HW_POWER_BASE + HW_POWER_VDDMEMCTRL);
    219 	vddmem |= (HW_POWER_VDDMEMCTRL_PULLDOWN_ACTIVE |
    220 	    HW_POWER_VDDMEMCTRL_ENABLE_ILIMIT |
    221 	    HW_POWER_VDDMEMCTRL_ENABLE_LINREG);
    222 	REG_WR(HW_POWER_BASE + HW_POWER_VDDMEMCTRL, vddmem);
    223 	delay(500);
    224 	vddmem &= ~(HW_POWER_VDDMEMCTRL_PULLDOWN_ACTIVE |
    225 	    HW_POWER_VDDMEMCTRL_ENABLE_ILIMIT);
    226 	REG_WR(HW_POWER_BASE + HW_POWER_VDDMEMCTRL, vddmem);
    227 
    228 	return;
    229 }
    230 #ifdef DEBUG
    231 #define PRINT_REG(REG)							\
    232 	printf(#REG "\t%x\n\r", REG_RD(HW_POWER_BASE + REG));
    233 
    234 static void
    235 print_regs(void)
    236 {
    237 	PRINT_REG(HW_POWER_CTRL);
    238 	PRINT_REG(HW_POWER_5VCTRL);
    239 	PRINT_REG(HW_POWER_MINPWR);
    240 	PRINT_REG(HW_POWER_CHARGE);
    241 	PRINT_REG(HW_POWER_VDDDCTRL);
    242 	PRINT_REG(HW_POWER_VDDACTRL);
    243 	PRINT_REG(HW_POWER_VDDIOCTRL);
    244 	PRINT_REG(HW_POWER_VDDMEMCTRL);
    245 	PRINT_REG(HW_POWER_DCDC4P2);
    246 	PRINT_REG(HW_POWER_MISC);
    247 	PRINT_REG(HW_POWER_DCLIMITS);
    248 	PRINT_REG(HW_POWER_LOOPCTRL);
    249 	PRINT_REG(HW_POWER_STS);
    250 	PRINT_REG(HW_POWER_SPEED);
    251 	PRINT_REG(HW_POWER_BATTMONITOR);
    252 	PRINT_REG(HW_POWER_RESET);
    253 	PRINT_REG(HW_POWER_DEBUG);
    254 	PRINT_REG(HW_POWER_SPECIAL);
    255 	PRINT_REG(HW_POWER_VERSION);
    256 
    257 	return;
    258 }
    259 #endif
    260