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