Home | History | Annotate | Line # | Download | only in bootimx23
power_prep.c revision 1.1
      1  1.1  jkunz /* $Id: power_prep.c,v 1.1 2012/11/20 19:08:46 jkunz Exp $ */
      2  1.1  jkunz 
      3  1.1  jkunz /*
      4  1.1  jkunz  * Copyright (c) 2012 The NetBSD Foundation, Inc.
      5  1.1  jkunz  * All rights reserved.
      6  1.1  jkunz  *
      7  1.1  jkunz  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1  jkunz  * by Petri Laakso.
      9  1.1  jkunz  *
     10  1.1  jkunz  * Redistribution and use in source and binary forms, with or without
     11  1.1  jkunz  * modification, are permitted provided that the following conditions
     12  1.1  jkunz  * are met:
     13  1.1  jkunz  * 1. Redistributions of source code must retain the above copyright
     14  1.1  jkunz  *    notice, this list of conditions and the following disclaimer.
     15  1.1  jkunz  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1  jkunz  *    notice, this list of conditions and the following disclaimer in the
     17  1.1  jkunz  *    documentation and/or other materials provided with the distribution.
     18  1.1  jkunz  *
     19  1.1  jkunz  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  1.1  jkunz  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  1.1  jkunz  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  1.1  jkunz  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  1.1  jkunz  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  1.1  jkunz  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  1.1  jkunz  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  1.1  jkunz  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  1.1  jkunz  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  1.1  jkunz  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  1.1  jkunz  * POSSIBILITY OF SUCH DAMAGE.
     30  1.1  jkunz  */
     31  1.1  jkunz 
     32  1.1  jkunz #include <sys/param.h>
     33  1.1  jkunz #include <sys/cdefs.h>
     34  1.1  jkunz #include <sys/types.h>
     35  1.1  jkunz 
     36  1.1  jkunz #include <arm/imx/imx23_powerreg.h>
     37  1.1  jkunz 
     38  1.1  jkunz #include <lib/libsa/stand.h>
     39  1.1  jkunz 
     40  1.1  jkunz #include "common.h"
     41  1.1  jkunz 
     42  1.1  jkunz void charge_4p2_capacitance(void);
     43  1.1  jkunz void enable_4p2_linreg(void);
     44  1.1  jkunz void enable_dcdc(void);
     45  1.1  jkunz void enable_vbusvalid_comparator(void);
     46  1.1  jkunz void set_targets(void);
     47  1.1  jkunz void dcdc4p2_enable_dcdc(void);
     48  1.1  jkunz void p5vctrl_enable_dcdc(void);
     49  1.1  jkunz void enable_vddmem(void);
     50  1.1  jkunz 
     51  1.1  jkunz /*
     52  1.1  jkunz  * Power rail voltage targets, brownout levels and linear regulator
     53  1.1  jkunz  * offsets from the target.
     54  1.1  jkunz  *
     55  1.1  jkunz  * Supply	Target	BO	LinReg offset
     56  1.1  jkunz  * ------------------------------------------
     57  1.1  jkunz  * VDDD		1.550 V	1.450 V	-25 mV
     58  1.1  jkunz  * VDDA		1.750 V	1.575 V	-25 mV
     59  1.1  jkunz  * VDDIO	3.100 V	2.925 V	-25 mV
     60  1.1  jkunz  * VDDMEM	2.500 V <na>	<na>
     61  1.1  jkunz  *
     62  1.1  jkunz  * BO = Brownout level below target.
     63  1.1  jkunz  */
     64  1.1  jkunz #define VDDD_TARGET 0x1e
     65  1.1  jkunz #define VDDD_BO_OFFSET 0x4
     66  1.1  jkunz #define VDDD_LINREG_OFFSET 0x02
     67  1.1  jkunz 
     68  1.1  jkunz #define VDDA_TARGET 0x0A
     69  1.1  jkunz #define VDDA_BO_OFFSET 0x07
     70  1.1  jkunz #define VDDA_LINREG_OFFSET 0x02
     71  1.1  jkunz 
     72  1.1  jkunz #define VDDIO_TARGET 0x0C
     73  1.1  jkunz #define VDDIO_BO_OFFSET 0x07
     74  1.1  jkunz #define VDDIO_LINREG_OFFSET 0x02
     75  1.1  jkunz 
     76  1.1  jkunz #define VDDMEM_TARGET 0x10
     77  1.1  jkunz 
     78  1.1  jkunz /*
     79  1.1  jkunz  * Threshold voltage for the VBUSVALID comparator.
     80  1.1  jkunz  * Always make sure that the VDD5V voltage level is higher.
     81  1.1  jkunz  */
     82  1.1  jkunz #define VBUSVALID_TRSH 0x02	/* 4.1 V */
     83  1.1  jkunz 
     84  1.1  jkunz /* Limits for BATT charger + 4P2 current */
     85  1.1  jkunz #define P4P2_ILIMIT_MIN 0x01	/* 10 mA */
     86  1.1  jkunz #define P4P2_ILIMIT_MAX 0x3f	/* 780 mA */
     87  1.1  jkunz 
     88  1.1  jkunz /*
     89  1.1  jkunz  * Trip point for the comparison between the DCDC_4P2 and BATTERY pin.
     90  1.1  jkunz  * If this voltage comparation is true then 5 V originated power will supply
     91  1.1  jkunz  * the DCDC. Otherwise battery will be used.
     92  1.1  jkunz  */
     93  1.1  jkunz #define DCDC4P2_CMPTRIP 0x00	/* DCDC_4P2 pin > 0.85 * BATTERY pin */
     94  1.1  jkunz 
     95  1.1  jkunz /*
     96  1.1  jkunz  * Adjust the behavior of the DCDC and 4.2 V circuit.
     97  1.1  jkunz  * Two MSBs control the VDD4P2 brownout below the DCDC4P2_TRG before the
     98  1.1  jkunz  * regulation circuit steals battery charge. Two LSBs control which power
     99  1.1  jkunz  * source is selected by the DCDC.
    100  1.1  jkunz  */
    101  1.1  jkunz #define DCDC4P2_DROPOUT_CTRL_BO_200 0x0C
    102  1.1  jkunz #define DCDC4P2_DROPOUT_CTRL_BO_100 0x08
    103  1.1  jkunz #define DCDC4P2_DROPOUT_CTRL_BO_050 0x04
    104  1.1  jkunz #define DCDC4P2_DROPOUT_CTRL_BO_025 0x00
    105  1.1  jkunz 
    106  1.1  jkunz #define DCDC4P2_DROPOUT_CTRL_SEL_4P2 0x00	/* Don't use battery at all. */
    107  1.1  jkunz #define DCDC4P2_DROPOUT_CTRL_SEL_BATT_IF_GT_4P2 0x01	/* BATT if 4P2 < BATT */
    108  1.1  jkunz #define DCDC4P2_DROPOUT_CTRL_SEL_HIGHER 0x02	/* Selects which ever is
    109  1.1  jkunz 						 * higher. */
    110  1.1  jkunz 
    111  1.1  jkunz #define DCDC4P2_DROPOUT_CTRL (DCDC4P2_DROPOUT_CTRL_BO_200 |\
    112  1.1  jkunz 	    DCDC4P2_DROPOUT_CTRL_SEL_4P2)
    113  1.1  jkunz 
    114  1.1  jkunz /*
    115  1.1  jkunz  * Prepare system for a 5 V operation.
    116  1.1  jkunz  *
    117  1.1  jkunz  * The system uses inefficient linear regulators as a power source after boot.
    118  1.1  jkunz  * This code enables the use of more energy efficient DC-DC converter as a
    119  1.1  jkunz  * power source.
    120  1.1  jkunz  */
    121  1.1  jkunz int
    122  1.1  jkunz power_prep(void)
    123  1.1  jkunz {
    124  1.1  jkunz 
    125  1.1  jkunz 	/* Enable clocks to the power block */
    126  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR, HW_POWER_CTRL_CLKGATE);
    127  1.1  jkunz 
    128  1.1  jkunz 	set_targets();
    129  1.1  jkunz 	enable_vbusvalid_comparator();
    130  1.1  jkunz 	enable_4p2_linreg();
    131  1.1  jkunz 	charge_4p2_capacitance();
    132  1.1  jkunz 	enable_dcdc();
    133  1.1  jkunz 	enable_vddmem();
    134  1.1  jkunz 
    135  1.1  jkunz 	return 0;
    136  1.1  jkunz }
    137  1.1  jkunz 
    138  1.1  jkunz /*
    139  1.1  jkunz  * Set switching converter voltage targets, brownout levels and linear
    140  1.1  jkunz  * regulator output offsets.
    141  1.1  jkunz  */
    142  1.1  jkunz void
    143  1.1  jkunz set_targets(void)
    144  1.1  jkunz {
    145  1.1  jkunz 	uint32_t vddctrl;
    146  1.1  jkunz 
    147  1.1  jkunz 	/* VDDD */
    148  1.1  jkunz 	vddctrl = REG_READ(HW_POWER_BASE + HW_POWER_VDDDCTRL);
    149  1.1  jkunz 
    150  1.1  jkunz 	vddctrl &= ~(HW_POWER_VDDDCTRL_LINREG_OFFSET |
    151  1.1  jkunz 	    HW_POWER_VDDDCTRL_BO_OFFSET |
    152  1.1  jkunz 	    HW_POWER_VDDDCTRL_TRG);
    153  1.1  jkunz 	vddctrl |=
    154  1.1  jkunz 	    __SHIFTIN(VDDD_LINREG_OFFSET, HW_POWER_VDDDCTRL_LINREG_OFFSET) |
    155  1.1  jkunz 	    __SHIFTIN(VDDD_BO_OFFSET, HW_POWER_VDDDCTRL_BO_OFFSET) |
    156  1.1  jkunz 	    __SHIFTIN(VDDD_TARGET, HW_POWER_VDDDCTRL_TRG);
    157  1.1  jkunz 
    158  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_VDDDCTRL, vddctrl);
    159  1.1  jkunz 
    160  1.1  jkunz 	/* VDDA */
    161  1.1  jkunz 	vddctrl = REG_READ(HW_POWER_BASE + HW_POWER_VDDACTRL);
    162  1.1  jkunz 
    163  1.1  jkunz 	vddctrl &= ~(HW_POWER_VDDACTRL_LINREG_OFFSET |
    164  1.1  jkunz 	    HW_POWER_VDDACTRL_BO_OFFSET |
    165  1.1  jkunz 	    HW_POWER_VDDACTRL_TRG);
    166  1.1  jkunz 	vddctrl |=
    167  1.1  jkunz 	    __SHIFTIN(VDDA_LINREG_OFFSET, HW_POWER_VDDACTRL_LINREG_OFFSET) |
    168  1.1  jkunz 	    __SHIFTIN(VDDA_BO_OFFSET, HW_POWER_VDDACTRL_BO_OFFSET) |
    169  1.1  jkunz 	    __SHIFTIN(VDDA_TARGET, HW_POWER_VDDACTRL_TRG);
    170  1.1  jkunz 
    171  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_VDDACTRL, vddctrl);
    172  1.1  jkunz 
    173  1.1  jkunz 	/* VDDIO */
    174  1.1  jkunz 	vddctrl = REG_READ(HW_POWER_BASE + HW_POWER_VDDIOCTRL);
    175  1.1  jkunz 
    176  1.1  jkunz 	vddctrl &= ~(HW_POWER_VDDIOCTRL_LINREG_OFFSET |
    177  1.1  jkunz 	    HW_POWER_VDDIOCTRL_BO_OFFSET |
    178  1.1  jkunz 	    HW_POWER_VDDIOCTRL_TRG);
    179  1.1  jkunz 	vddctrl |=
    180  1.1  jkunz 	    __SHIFTIN(VDDIO_LINREG_OFFSET, HW_POWER_VDDACTRL_LINREG_OFFSET) |
    181  1.1  jkunz 	    __SHIFTIN(VDDIO_BO_OFFSET, HW_POWER_VDDACTRL_BO_OFFSET) |
    182  1.1  jkunz 	    __SHIFTIN(VDDIO_TARGET, HW_POWER_VDDACTRL_TRG);
    183  1.1  jkunz 
    184  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_VDDIOCTRL, vddctrl);
    185  1.1  jkunz 
    186  1.1  jkunz 	/* VDDMEM */
    187  1.1  jkunz 	vddctrl = REG_READ(HW_POWER_BASE + HW_POWER_VDDMEMCTRL);
    188  1.1  jkunz 	vddctrl &= ~(HW_POWER_VDDMEMCTRL_TRG);
    189  1.1  jkunz 	vddctrl |= __SHIFTIN(VDDMEM_TARGET, HW_POWER_VDDMEMCTRL_TRG);
    190  1.1  jkunz 
    191  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_VDDMEMCTRL, vddctrl);
    192  1.1  jkunz 
    193  1.1  jkunz 	return;
    194  1.1  jkunz }
    195  1.1  jkunz 
    196  1.1  jkunz /*
    197  1.1  jkunz  * VBUSVALID comparator is accurate method to determine the presence of 5 V.
    198  1.1  jkunz  * Turn on the comparator, set its voltage treshold and instruct DC-DC to
    199  1.1  jkunz  * use it.
    200  1.1  jkunz  */
    201  1.1  jkunz void
    202  1.1  jkunz enable_vbusvalid_comparator()
    203  1.1  jkunz {
    204  1.1  jkunz 	uint32_t p5vctrl;
    205  1.1  jkunz 
    206  1.1  jkunz 	/*
    207  1.1  jkunz 	 * Disable 5 V brownout detection temporarily because setting
    208  1.1  jkunz 	 * VBUSVALID_5VDETECT can cause false brownout.
    209  1.1  jkunz 	 */
    210  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_CLR,
    211  1.1  jkunz 	    HW_POWER_5VCTRL_PWDN_5VBRNOUT);
    212  1.1  jkunz 
    213  1.1  jkunz 	p5vctrl = REG_READ(HW_POWER_BASE + HW_POWER_5VCTRL);
    214  1.1  jkunz 
    215  1.1  jkunz 	p5vctrl &= ~HW_POWER_5VCTRL_VBUSVALID_TRSH;
    216  1.1  jkunz 	p5vctrl |=
    217  1.1  jkunz 	    /* Turn on VBUS comparators. */
    218  1.1  jkunz 	    (HW_POWER_5VCTRL_PWRUP_VBUS_CMPS |
    219  1.1  jkunz 	    /* Set treshold for VBUSVALID comparator. */
    220  1.1  jkunz 	    __SHIFTIN(VBUSVALID_TRSH, HW_POWER_5VCTRL_VBUSVALID_TRSH) |
    221  1.1  jkunz 	    /* Set DC-DC to use VBUSVALID comparator. */
    222  1.1  jkunz 	    HW_POWER_5VCTRL_VBUSVALID_5VDETECT);
    223  1.1  jkunz 
    224  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL, p5vctrl);
    225  1.1  jkunz 
    226  1.1  jkunz 	/* Enable temporarily disabled 5 V brownout detection. */
    227  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_SET,
    228  1.1  jkunz 	    HW_POWER_5VCTRL_PWDN_5VBRNOUT);
    229  1.1  jkunz 
    230  1.1  jkunz 	return;
    231  1.1  jkunz }
    232  1.1  jkunz 
    233  1.1  jkunz /*
    234  1.1  jkunz  * Enable 4P2 linear regulator.
    235  1.1  jkunz  */
    236  1.1  jkunz void
    237  1.1  jkunz enable_4p2_linreg(void)
    238  1.1  jkunz {
    239  1.1  jkunz 	uint32_t dcdc4p2;
    240  1.1  jkunz 	uint32_t p5vctrl;
    241  1.1  jkunz 
    242  1.1  jkunz 	dcdc4p2 = REG_READ(HW_POWER_BASE + HW_POWER_DCDC4P2);
    243  1.1  jkunz 	/* Set the 4P2 target to 4.2 V and BO to 3.6V by clearing TRG and BO
    244  1.1  jkunz 	 * field. */
    245  1.1  jkunz 	dcdc4p2 &= ~(HW_POWER_DCDC4P2_TRG | HW_POWER_DCDC4P2_BO);
    246  1.1  jkunz 	/* Enable the 4P2 circuitry to control the LinReg. */
    247  1.1  jkunz 	dcdc4p2 |= HW_POWER_DCDC4P2_ENABLE_4P2;
    248  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_DCDC4P2, dcdc4p2);
    249  1.1  jkunz 
    250  1.1  jkunz 	/* The 4P2 LinReg needs a static load to operate correctly. Since the
    251  1.1  jkunz 	 * DC-DC is not yet loading the LinReg, another load must be used. */
    252  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_CHARGE_SET,
    253  1.1  jkunz 	    HW_POWER_CHARGE_ENABLE_LOAD);
    254  1.1  jkunz 
    255  1.1  jkunz 	p5vctrl = REG_READ(HW_POWER_BASE + HW_POWER_5VCTRL);
    256  1.1  jkunz 	p5vctrl &= ~(HW_POWER_5VCTRL_CHARGE_4P2_ILIMIT |
    257  1.1  jkunz 	    /* Power on the 4P2 LinReg. ON = 0x0, OFF = 0x1 */
    258  1.1  jkunz 	    HW_POWER_5VCTRL_PWD_CHARGE_4P2);
    259  1.1  jkunz 	p5vctrl |=
    260  1.1  jkunz 	    /* Provide an initial current limit for the 4P2 LinReg with the
    261  1.1  jkunz 	     * smallest value possible. */
    262  1.1  jkunz 	    __SHIFTIN(P4P2_ILIMIT_MIN, HW_POWER_5VCTRL_CHARGE_4P2_ILIMIT);
    263  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL, p5vctrl);
    264  1.1  jkunz 
    265  1.1  jkunz 	/* Ungate the path from 4P2 LinReg to DC-DC. */
    266  1.1  jkunz 	dcdc4p2_enable_dcdc();
    267  1.1  jkunz 
    268  1.1  jkunz 	return;
    269  1.1  jkunz }
    270  1.1  jkunz 
    271  1.1  jkunz /*
    272  1.1  jkunz  * There is capacitor on the 4P2 output which must be charged before powering
    273  1.1  jkunz  * on the 4P2 linear regulator to avoid brownouts on the 5 V source.
    274  1.1  jkunz  * Charging is done by slowly increasing current limit until it reaches
    275  1.1  jkunz  * P4P2_ILIMIT_MAX.
    276  1.1  jkunz  */
    277  1.1  jkunz void
    278  1.1  jkunz charge_4p2_capacitance(void)
    279  1.1  jkunz {
    280  1.1  jkunz 	uint32_t ilimit;
    281  1.1  jkunz 	uint32_t p5vctrl;
    282  1.1  jkunz 
    283  1.1  jkunz 	p5vctrl = REG_READ(HW_POWER_BASE + HW_POWER_5VCTRL);
    284  1.1  jkunz 	ilimit = __SHIFTOUT(p5vctrl, HW_POWER_5VCTRL_CHARGE_4P2_ILIMIT);
    285  1.1  jkunz 
    286  1.1  jkunz 	/* Increment current limit slowly. */
    287  1.1  jkunz 	while (ilimit < P4P2_ILIMIT_MAX) {
    288  1.1  jkunz 		ilimit++;
    289  1.1  jkunz 		p5vctrl &= ~(HW_POWER_5VCTRL_CHARGE_4P2_ILIMIT);
    290  1.1  jkunz 		p5vctrl |= __SHIFTIN(ilimit, HW_POWER_5VCTRL_CHARGE_4P2_ILIMIT);
    291  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL, p5vctrl);
    292  1.1  jkunz 		delay_us(10000);
    293  1.1  jkunz 	}
    294  1.1  jkunz 
    295  1.1  jkunz 	return;
    296  1.1  jkunz }
    297  1.1  jkunz 
    298  1.1  jkunz /*
    299  1.1  jkunz  * Enable DCDC to use 4P2 regulator and set its power source selection logic.
    300  1.1  jkunz  */
    301  1.1  jkunz void
    302  1.1  jkunz enable_dcdc(void)
    303  1.1  jkunz {
    304  1.1  jkunz 	uint32_t dcdc4p2;
    305  1.1  jkunz 	uint32_t vddctrl;
    306  1.1  jkunz 
    307  1.1  jkunz 	dcdc4p2 = REG_READ(HW_POWER_BASE + HW_POWER_DCDC4P2);
    308  1.1  jkunz 	dcdc4p2 &= ~(HW_POWER_DCDC4P2_CMPTRIP | HW_POWER_DCDC4P2_DROPOUT_CTRL);
    309  1.1  jkunz 	/* Comparison between the DCDC_4P2 pin and BATTERY pin to choose which
    310  1.1  jkunz 	 * will supply the DCDC. */
    311  1.1  jkunz 	dcdc4p2 |= __SHIFTIN(DCDC4P2_CMPTRIP, HW_POWER_DCDC4P2_CMPTRIP);
    312  1.1  jkunz 	/* DC-DC brownout and select logic. */
    313  1.1  jkunz 	dcdc4p2 |= __SHIFTIN(DCDC4P2_DROPOUT_CTRL,
    314  1.1  jkunz 	    HW_POWER_DCDC4P2_DROPOUT_CTRL);
    315  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_DCDC4P2, dcdc4p2);
    316  1.1  jkunz 
    317  1.1  jkunz 	/* Disable the automatic DC-DC startup when 5 V is lost (it is on
    318  1.1  jkunz 	 * already) */
    319  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_CLR,
    320  1.1  jkunz 	    HW_POWER_5VCTRL_DCDC_XFER);
    321  1.1  jkunz 
    322  1.1  jkunz 	p5vctrl_enable_dcdc();
    323  1.1  jkunz 
    324  1.1  jkunz 	/* Enable switching converter outputs and disable linear regulators
    325  1.1  jkunz 	 * for VDDD, VDDIO and VDDA. */
    326  1.1  jkunz 	vddctrl = REG_READ(HW_POWER_BASE + HW_POWER_VDDDCTRL);
    327  1.1  jkunz 	vddctrl &= ~(HW_POWER_VDDDCTRL_DISABLE_FET |
    328  1.1  jkunz 	    HW_POWER_VDDDCTRL_ENABLE_LINREG);
    329  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_VDDDCTRL, vddctrl);
    330  1.1  jkunz 
    331  1.1  jkunz 	vddctrl = REG_READ(HW_POWER_BASE + HW_POWER_VDDIOCTRL);
    332  1.1  jkunz 	vddctrl &= ~HW_POWER_VDDIOCTRL_DISABLE_FET;
    333  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_VDDIOCTRL, vddctrl);
    334  1.1  jkunz 
    335  1.1  jkunz 	vddctrl = REG_READ(HW_POWER_BASE + HW_POWER_VDDACTRL);
    336  1.1  jkunz 	vddctrl &= ~(HW_POWER_VDDACTRL_DISABLE_FET |
    337  1.1  jkunz 	    HW_POWER_VDDACTRL_ENABLE_LINREG);
    338  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_VDDACTRL, vddctrl);
    339  1.1  jkunz 
    340  1.1  jkunz 	/* The 4P2 LinReg needs a static load to operate correctly. Since the
    341  1.1  jkunz 	 * DC-DC is already running we can remove extra 100 ohm load enabled
    342  1.1  jkunz 	 * before. */
    343  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_CHARGE_CLR,
    344  1.1  jkunz 	    HW_POWER_CHARGE_ENABLE_LOAD);
    345  1.1  jkunz 
    346  1.1  jkunz 	return;
    347  1.1  jkunz }
    348  1.1  jkunz 
    349  1.1  jkunz /*
    350  1.1  jkunz  * DCDC4P2 DCDC enable sequence according to errata #5837
    351  1.1  jkunz  */
    352  1.1  jkunz void
    353  1.1  jkunz dcdc4p2_enable_dcdc(void)
    354  1.1  jkunz {
    355  1.1  jkunz 	uint32_t dcdc4p2;
    356  1.1  jkunz 	uint32_t p5vctrl;
    357  1.1  jkunz 	uint32_t p5vctrl_saved;
    358  1.1  jkunz 	uint32_t pctrl;
    359  1.1  jkunz 	uint32_t pctrl_saved;
    360  1.1  jkunz 
    361  1.1  jkunz 	pctrl_saved = REG_READ(HW_POWER_BASE + HW_POWER_CTRL);
    362  1.1  jkunz 	p5vctrl_saved = REG_READ(HW_POWER_BASE + HW_POWER_5VCTRL);
    363  1.1  jkunz 
    364  1.1  jkunz 	/* Disable the power rail brownout interrupts. */
    365  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
    366  1.1  jkunz 	    (HW_POWER_CTRL_ENIRQ_VDDA_BO |
    367  1.1  jkunz 	    HW_POWER_CTRL_ENIRQ_VDDD_BO |
    368  1.1  jkunz 	    HW_POWER_CTRL_ENIRQ_VDDIO_BO));
    369  1.1  jkunz 
    370  1.1  jkunz 	/* Set the HW_POWER_5VCTRL PWRUP_VBUS_CMPS bit (may already be set) */
    371  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_SET,
    372  1.1  jkunz 	    HW_POWER_5VCTRL_PWRUP_VBUS_CMPS);
    373  1.1  jkunz 
    374  1.1  jkunz 	/* Set the HW_POWER_5VCTRL VBUSVALID_5VDETECT bit to 0 */
    375  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_CLR,
    376  1.1  jkunz 	    HW_POWER_5VCTRL_VBUSVALID_5VDETECT);
    377  1.1  jkunz 
    378  1.1  jkunz 	/* Set the HW_POWER_5VCTRL VBUSVALID_TRSH to 0x0 (2.9 V) */
    379  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_CLR,
    380  1.1  jkunz 	    HW_POWER_5VCTRL_VBUSVALID_TRSH);
    381  1.1  jkunz 
    382  1.1  jkunz 	/* Disable VBUSDROOP status and interrupt. */
    383  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
    384  1.1  jkunz 	    (HW_POWER_CTRL_VDD5V_DROOP_IRQ | HW_POWER_CTRL_ENIRQ_VDD5V_DROOP));
    385  1.1  jkunz 
    386  1.1  jkunz 	/* Set the ENABLE_DCDC bit in HW_POWER_DCDC4P2. */
    387  1.1  jkunz 	dcdc4p2 = REG_READ(HW_POWER_BASE + HW_POWER_DCDC4P2);
    388  1.1  jkunz 	dcdc4p2 |= HW_POWER_DCDC4P2_ENABLE_DCDC;
    389  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_DCDC4P2, dcdc4p2);
    390  1.1  jkunz 
    391  1.1  jkunz 	delay_us(100);
    392  1.1  jkunz 
    393  1.1  jkunz 	pctrl = REG_READ(HW_POWER_BASE + HW_POWER_CTRL);
    394  1.1  jkunz 	/* VBUSVALID_IRQ is set. */
    395  1.1  jkunz 	if (__SHIFTOUT(pctrl, HW_POWER_CTRL_VBUSVALID_IRQ)) {
    396  1.1  jkunz 		/* Set and clear the PWD_CHARGE_4P2 bit to repower on the 4P2
    397  1.1  jkunz 		 * regulator because it is automatically shut off on a
    398  1.1  jkunz 		 * VBUSVALID false condition. */
    399  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_SET,
    400  1.1  jkunz 		    HW_POWER_5VCTRL_PWD_CHARGE_4P2);
    401  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_CLR,
    402  1.1  jkunz 		    HW_POWER_5VCTRL_PWD_CHARGE_4P2);
    403  1.1  jkunz 		/* Ramp up the CHARGE_4P2_ILIMIT value at this point. */
    404  1.1  jkunz 		charge_4p2_capacitance();
    405  1.1  jkunz 	}
    406  1.1  jkunz 
    407  1.1  jkunz 	/* Restore modified bits back to HW_POWER_CTRL. */
    408  1.1  jkunz 	if (pctrl_saved & HW_POWER_CTRL_ENIRQ_VDDA_BO)
    409  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
    410  1.1  jkunz 		    HW_POWER_CTRL_ENIRQ_VDDA_BO);
    411  1.1  jkunz 	else
    412  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
    413  1.1  jkunz 		    HW_POWER_CTRL_ENIRQ_VDDA_BO);
    414  1.1  jkunz 
    415  1.1  jkunz 	if (pctrl_saved & HW_POWER_CTRL_ENIRQ_VDDD_BO)
    416  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
    417  1.1  jkunz 		    HW_POWER_CTRL_ENIRQ_VDDD_BO);
    418  1.1  jkunz 	else
    419  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
    420  1.1  jkunz 		    HW_POWER_CTRL_ENIRQ_VDDD_BO);
    421  1.1  jkunz 
    422  1.1  jkunz 	if (pctrl_saved & HW_POWER_CTRL_ENIRQ_VDDIO_BO)
    423  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
    424  1.1  jkunz 		    HW_POWER_CTRL_ENIRQ_VDDIO_BO);
    425  1.1  jkunz 	else
    426  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
    427  1.1  jkunz 		    HW_POWER_CTRL_ENIRQ_VDDIO_BO);
    428  1.1  jkunz 
    429  1.1  jkunz 	if (pctrl_saved & HW_POWER_CTRL_VDD5V_DROOP_IRQ)
    430  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
    431  1.1  jkunz 		    HW_POWER_CTRL_VDD5V_DROOP_IRQ);
    432  1.1  jkunz 	else
    433  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
    434  1.1  jkunz 		    HW_POWER_CTRL_VDD5V_DROOP_IRQ);
    435  1.1  jkunz 
    436  1.1  jkunz 	if (pctrl_saved & HW_POWER_CTRL_ENIRQ_VDD5V_DROOP)
    437  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
    438  1.1  jkunz 		    HW_POWER_CTRL_ENIRQ_VDD5V_DROOP);
    439  1.1  jkunz 	else
    440  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
    441  1.1  jkunz 		    HW_POWER_CTRL_ENIRQ_VDD5V_DROOP);
    442  1.1  jkunz 
    443  1.1  jkunz 	/* Restore modified bits back to HW_POWER_5VCTRL. */
    444  1.1  jkunz 	p5vctrl = REG_READ(HW_POWER_BASE + HW_POWER_5VCTRL);
    445  1.1  jkunz 	p5vctrl &= ~(HW_POWER_5VCTRL_PWRUP_VBUS_CMPS |
    446  1.1  jkunz 	    HW_POWER_5VCTRL_VBUSVALID_5VDETECT |
    447  1.1  jkunz 	    HW_POWER_5VCTRL_VBUSVALID_TRSH);
    448  1.1  jkunz 	p5vctrl |= __SHIFTOUT(p5vctrl_saved, HW_POWER_5VCTRL_VBUSVALID_TRSH) |
    449  1.1  jkunz 	    (p5vctrl_saved & HW_POWER_5VCTRL_PWRUP_VBUS_CMPS) |
    450  1.1  jkunz 	    (p5vctrl_saved & HW_POWER_5VCTRL_VBUSVALID_5VDETECT);
    451  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL, p5vctrl);
    452  1.1  jkunz 
    453  1.1  jkunz 	return;
    454  1.1  jkunz }
    455  1.1  jkunz 
    456  1.1  jkunz /*
    457  1.1  jkunz  * 5VCTRL DCDC enable sequence according to errata #5837
    458  1.1  jkunz  */
    459  1.1  jkunz void
    460  1.1  jkunz p5vctrl_enable_dcdc(void)
    461  1.1  jkunz {
    462  1.1  jkunz 	uint32_t p5vctrl;
    463  1.1  jkunz 	uint32_t p5vctrl_saved;
    464  1.1  jkunz 	uint32_t pctrl;
    465  1.1  jkunz 	uint32_t pctrl_saved;
    466  1.1  jkunz 
    467  1.1  jkunz 	pctrl_saved = REG_READ(HW_POWER_BASE + HW_POWER_CTRL);
    468  1.1  jkunz 	p5vctrl_saved = REG_READ(HW_POWER_BASE + HW_POWER_5VCTRL);
    469  1.1  jkunz 
    470  1.1  jkunz 	/* Disable the power rail brownout interrupts. */
    471  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
    472  1.1  jkunz 	    HW_POWER_CTRL_ENIRQ_VDDA_BO |
    473  1.1  jkunz 	    HW_POWER_CTRL_ENIRQ_VDDD_BO |
    474  1.1  jkunz 	    HW_POWER_CTRL_ENIRQ_VDDIO_BO);
    475  1.1  jkunz 
    476  1.1  jkunz 	/* Set the HW_POWER_5VCTRL PWRUP_VBUS_CMPS bit (may already be set) */
    477  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_SET,
    478  1.1  jkunz 	    HW_POWER_5VCTRL_PWRUP_VBUS_CMPS);
    479  1.1  jkunz 
    480  1.1  jkunz 	/* Set the HW_POWER_5VCTRL VBUSVALID_5VDETECT bit to 1 */
    481  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_SET,
    482  1.1  jkunz 	    HW_POWER_5VCTRL_VBUSVALID_5VDETECT);
    483  1.1  jkunz 
    484  1.1  jkunz 	/* Set the HW_POWER_5VCTRL VBUSVALID_TRSH to 0x0 (2.9 V) */
    485  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_CLR,
    486  1.1  jkunz 	    HW_POWER_5VCTRL_VBUSVALID_TRSH);
    487  1.1  jkunz 
    488  1.1  jkunz 	/* Disable VBUSDROOP status and interrupt. */
    489  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
    490  1.1  jkunz 	    (HW_POWER_CTRL_VDD5V_DROOP_IRQ | HW_POWER_CTRL_ENIRQ_VDD5V_DROOP));
    491  1.1  jkunz 
    492  1.1  jkunz 	/* Work over errata #2816 by disabling 5 V brownout while modifying
    493  1.1  jkunz 	 * ENABLE_DCDC. */
    494  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_CLR,
    495  1.1  jkunz 	    HW_POWER_5VCTRL_PWDN_5VBRNOUT);
    496  1.1  jkunz 
    497  1.1  jkunz 	/* Set the ENABLE_DCDC bit in HW_POWER_5VCTRL. */
    498  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_SET,
    499  1.1  jkunz 	    HW_POWER_5VCTRL_ENABLE_DCDC);
    500  1.1  jkunz 
    501  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_SET,
    502  1.1  jkunz 	    HW_POWER_5VCTRL_PWDN_5VBRNOUT);
    503  1.1  jkunz 
    504  1.1  jkunz 	delay_us(100);
    505  1.1  jkunz 
    506  1.1  jkunz 	pctrl = REG_READ(HW_POWER_BASE + HW_POWER_CTRL);
    507  1.1  jkunz 	/* VBUSVALID_IRQ is set. */
    508  1.1  jkunz 	if (__SHIFTOUT(pctrl, HW_POWER_CTRL_VBUSVALID_IRQ)) {
    509  1.1  jkunz 		/* repeat the sequence for enabling the 4P2 regulator and DCDC
    510  1.1  jkunz 		 * from 4P2. */
    511  1.1  jkunz 		enable_4p2_linreg();
    512  1.1  jkunz 	}
    513  1.1  jkunz 	/* Restore modified bits back to HW_POWER_CTRL. */
    514  1.1  jkunz 	if (pctrl_saved & HW_POWER_CTRL_ENIRQ_VDDA_BO)
    515  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
    516  1.1  jkunz 		    HW_POWER_CTRL_ENIRQ_VDDA_BO);
    517  1.1  jkunz 	else
    518  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
    519  1.1  jkunz 		    HW_POWER_CTRL_ENIRQ_VDDA_BO);
    520  1.1  jkunz 
    521  1.1  jkunz 	if (pctrl_saved & HW_POWER_CTRL_ENIRQ_VDDD_BO)
    522  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
    523  1.1  jkunz 		    HW_POWER_CTRL_ENIRQ_VDDD_BO);
    524  1.1  jkunz 	else
    525  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
    526  1.1  jkunz 		    HW_POWER_CTRL_ENIRQ_VDDD_BO);
    527  1.1  jkunz 
    528  1.1  jkunz 	if (pctrl_saved & HW_POWER_CTRL_ENIRQ_VDDIO_BO)
    529  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
    530  1.1  jkunz 		    HW_POWER_CTRL_ENIRQ_VDDIO_BO);
    531  1.1  jkunz 	else
    532  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
    533  1.1  jkunz 		    HW_POWER_CTRL_ENIRQ_VDDIO_BO);
    534  1.1  jkunz 
    535  1.1  jkunz 	if (pctrl_saved & HW_POWER_CTRL_VDD5V_DROOP_IRQ)
    536  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
    537  1.1  jkunz 		    HW_POWER_CTRL_VDD5V_DROOP_IRQ);
    538  1.1  jkunz 	else
    539  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
    540  1.1  jkunz 		    HW_POWER_CTRL_VDD5V_DROOP_IRQ);
    541  1.1  jkunz 
    542  1.1  jkunz 	if (pctrl_saved & HW_POWER_CTRL_ENIRQ_VDD5V_DROOP)
    543  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
    544  1.1  jkunz 		    HW_POWER_CTRL_ENIRQ_VDD5V_DROOP);
    545  1.1  jkunz 	else
    546  1.1  jkunz 		REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
    547  1.1  jkunz 		    HW_POWER_CTRL_ENIRQ_VDD5V_DROOP);
    548  1.1  jkunz 
    549  1.1  jkunz 	/* Restore modified bits back to HW_POWER_5VCTRL. */
    550  1.1  jkunz 	p5vctrl = REG_READ(HW_POWER_BASE + HW_POWER_5VCTRL);
    551  1.1  jkunz 	p5vctrl &= ~(HW_POWER_5VCTRL_PWRUP_VBUS_CMPS |
    552  1.1  jkunz 	    HW_POWER_5VCTRL_VBUSVALID_5VDETECT |
    553  1.1  jkunz 	    HW_POWER_5VCTRL_VBUSVALID_TRSH);
    554  1.1  jkunz 	p5vctrl |= __SHIFTOUT(p5vctrl_saved, HW_POWER_5VCTRL_VBUSVALID_TRSH) |
    555  1.1  jkunz 	    (p5vctrl_saved & HW_POWER_5VCTRL_PWRUP_VBUS_CMPS) |
    556  1.1  jkunz 	    (p5vctrl_saved & HW_POWER_5VCTRL_VBUSVALID_5VDETECT);
    557  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL, p5vctrl);
    558  1.1  jkunz 
    559  1.1  jkunz 	return;
    560  1.1  jkunz }
    561  1.1  jkunz 
    562  1.1  jkunz void
    563  1.1  jkunz enable_vddmem(void)
    564  1.1  jkunz {
    565  1.1  jkunz 	uint32_t vddctrl;
    566  1.1  jkunz 
    567  1.1  jkunz 	/* VDDMEM */
    568  1.1  jkunz 	vddctrl = REG_READ(HW_POWER_BASE + HW_POWER_VDDMEMCTRL);
    569  1.1  jkunz 	vddctrl |= (HW_POWER_VDDMEMCTRL_PULLDOWN_ACTIVE |
    570  1.1  jkunz 	    HW_POWER_VDDMEMCTRL_ENABLE_ILIMIT |
    571  1.1  jkunz 	    HW_POWER_VDDMEMCTRL_ENABLE_LINREG);
    572  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_VDDMEMCTRL, vddctrl);
    573  1.1  jkunz 	delay_us(500);
    574  1.1  jkunz 	vddctrl &= ~(HW_POWER_VDDMEMCTRL_PULLDOWN_ACTIVE |
    575  1.1  jkunz 	    HW_POWER_VDDMEMCTRL_ENABLE_ILIMIT);
    576  1.1  jkunz 	REG_WRITE(HW_POWER_BASE + HW_POWER_VDDMEMCTRL, vddctrl);
    577  1.1  jkunz 
    578  1.1  jkunz 	return;
    579  1.1  jkunz }
    580