From: Lothar Waßmann Date: Wed, 14 Mar 2012 18:27:47 +0000 (+0100) Subject: FIXED_BATT_SUPPLY working!? X-Git-Tag: v1.2.2~19 X-Git-Url: https://git.kernelconcepts.de/?a=commitdiff_plain;h=d3860199ce11d91a1fe69211bba45ab5630d24a7;p=karo-tx-uboot.git FIXED_BATT_SUPPLY working!? --- diff --git a/arch/arm/cpu/arm926ejs/mx28/Makefile b/arch/arm/cpu/arm926ejs/mx28/Makefile index a2e3f771c2..cb671837e4 100644 --- a/arch/arm/cpu/arm926ejs/mx28/Makefile +++ b/arch/arm/cpu/arm926ejs/mx28/Makefile @@ -28,7 +28,7 @@ LIB = $(obj)lib$(SOC).o COBJS = clock.o mx28.o iomux.o timer.o ifdef CONFIG_SPL_BUILD -COBJS += spl_boot.o spl_mem_init.o spl_power_init.o +COBJS += spl_boot.o spl_mem_init.o spl_power_init.o debug.o endif SRCS := $(START:.o=.S) $(COBJS:.o=.c) diff --git a/arch/arm/cpu/arm926ejs/mx28/debug.c b/arch/arm/cpu/arm926ejs/mx28/debug.c new file mode 100644 index 0000000000..a88f1af451 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mx28/debug.c @@ -0,0 +1,114 @@ +/* + * Boot Prep common file + * + * Copyright 2008-2009 Freescale Semiconductor + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +//#include + +#include + +void printhex(int data) +{ + int i; + char c; + + for (i = sizeof(int) * 2 - 1; i >= 0; i--) { + c = data >> (i * 4); + c &= 0xf; + if (c > 9) + serial_putc(c - 10 + 'A'); + else + serial_putc(c + '0'); + } +} + +void printdec(int data) +{ + unsigned int m; + char str[10] = { 0, }; + int i; + + if (data == 0) { + serial_putc('0'); + return; + } else if (data < 0) { + serial_putc('-'); + data = -data; + } + m = data; + for (i = 0; m > 0; i++) { + str[i] = m % 10 + '0'; + m /= 10; + } + for (i--; i >= 0; i--) { + serial_putc(str[i]); + } +} + +void dprintf(const char *fmt, ...) +{ + va_list args; + const char *fp = fmt; + + if (!fmt) + return; + + va_start(args, fmt); + while (*fp) { + if (*fp == '%') { + fp++; + switch (*fp) { + case 'c': + serial_putc(va_arg(args, int)); + break; + + case 's': + serial_puts(va_arg(args, const char *)); + break; + + case 'd': + case 'u': + case 'i': + printdec(va_arg(args, int)); + break; + + case 'p': + serial_puts("0x"); + case 'x': + case 'X': + printhex(va_arg(args, int)); + break; + + case '%': + serial_putc('%'); + break; + + default: + dprintf("\nUnsupported format string token '%c'(%x) in '%s'\n", + *fp, *fp, fmt); + } + } else { + if (*fp == '\n') + serial_putc('\r'); + serial_putc(*fp); + } + fp++; + } + va_end(args); +} diff --git a/arch/arm/cpu/arm926ejs/mx28/debug.h b/arch/arm/cpu/arm926ejs/mx28/debug.h new file mode 100644 index 0000000000..8299142006 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mx28/debug.h @@ -0,0 +1,3 @@ +extern void printhex(int data); +extern void printdec(int data); +extern void dprintf(const char *fmt, ...); diff --git a/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c b/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c index 380b120dc9..95a79a749b 100644 --- a/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c +++ b/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c @@ -30,21 +30,97 @@ #include "mx28_init.h" -void mx28_power_clock2xtal(void) +extern void dprintf(const char *fmt, ...); + +#undef __arch_getl +#undef __arch_putl + +#define __arch_getl(a) arch_getl(a, __func__, __LINE__) +static inline unsigned int arch_getl(volatile void *addr, + const char *fn, unsigned int ln) +{ + volatile unsigned int *a = addr; + unsigned int val = *a; + dprintf("%s@%d: Read %x from %p\n", fn, ln, val, addr); + return val; +} + +#define __arch_putl(v, a) arch_putl(v, a, __func__, __LINE__) +static inline void arch_putl(unsigned int val, volatile void *addr, + const char *fn, unsigned int ln) +{ + volatile unsigned int *a = addr; + + dprintf("%s@%d: Writing %x to %p\n", fn, ln, val, addr); + *a = val; +} + +#define __static + +__static int mx28_power_vdd5v_gt_vddio(void) +{ +#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY + struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE; + int power_sts = readl(&power_regs->hw_power_sts); + + dprintf("%s@%d: 0\n", __func__, __LINE__, + !!(power_sts & POWER_STS_VDD5V_GT_VDDIO)); + return power_sts & POWER_STS_VDD5V_GT_VDDIO; +#else + dprintf("%s@%d: 0\n", __func__, __LINE__); + return 0; +#endif +} + +__static int mx28_power_vbus_valid(void) +{ +#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY + struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE; + int power_5vctrl = readl(&power_regs->hw_power_5vctrl); + + dprintf("%s@%d: 0\n", __func__, __LINE__, + !!(power_5vctrl & POWER_5VCTRL_VBUSVALID_5VDETECT)); + return power_5vctrl & POWER_5VCTRL_VBUSVALID_5VDETECT; +#else + dprintf("%s@%d: 0\n", __func__, __LINE__); + return 0; +#endif +} + +static void memdump(unsigned long addr, unsigned long len) +{ + int i; + uint32_t *ptr = (void *)addr; + + for (i = 0; i < len; i++) { + if (i % 4 == 0) + dprintf("\n%p:", &ptr[i]); + dprintf(" %x", ptr[i]); + } + dprintf("\n"); +} + +//#undef CONFIG_SPL_FIXED_BATT_SUPPLY + +__static void mx28_power_clock2xtal(void) { struct mx28_clkctrl_regs *clkctrl_regs = (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE; + dprintf("%s@%d: \n", __func__, __LINE__); /* Set XTAL as CPU reference clock */ writel(CLKCTRL_CLKSEQ_BYPASS_CPU, &clkctrl_regs->hw_clkctrl_clkseq_set); } -void mx28_power_clock2pll(void) +__static void mx28_power_clock2pll(void) { struct mx28_clkctrl_regs *clkctrl_regs = (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE; + dprintf("%s@%d: \n", __func__, __LINE__); writel(CLKCTRL_PLL0CTRL0_POWER, &clkctrl_regs->hw_clkctrl_pll0ctrl0_set); early_delay(100); @@ -52,11 +128,12 @@ void mx28_power_clock2pll(void) &clkctrl_regs->hw_clkctrl_clkseq_clr); } -void mx28_power_clear_auto_restart(void) +__static void mx28_power_clear_auto_restart(void) { struct mx28_rtc_regs *rtc_regs = (struct mx28_rtc_regs *)MXS_RTC_BASE; + dprintf("%s@%d: \n", __func__, __LINE__); writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr); while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST) ; @@ -64,7 +141,7 @@ void mx28_power_clear_auto_restart(void) writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr); while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE) ; - +#ifdef CONFIG_MACH_MX28EVK /* * Due to the hardware design bug of mx28 EVK-A * we need to set the AUTO_RESTART bit. @@ -83,17 +160,19 @@ void mx28_power_clear_auto_restart(void) ; while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK) ; +#endif } -void mx28_power_set_linreg(void) +__static void mx28_power_set_linreg(void) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; + dprintf("%s@%d: \n", __func__, __LINE__); /* Set linear regulator 25mV below switching converter */ clrsetbits_le32(&power_regs->hw_power_vdddctrl, POWER_VDDDCTRL_LINREG_OFFSET_MASK, - POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW); + POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_ABOVE); clrsetbits_le32(&power_regs->hw_power_vddactrl, POWER_VDDACTRL_LINREG_OFFSET_MASK, @@ -102,13 +181,15 @@ void mx28_power_set_linreg(void) clrsetbits_le32(&power_regs->hw_power_vddioctrl, POWER_VDDIOCTRL_LINREG_OFFSET_MASK, POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW); + dprintf("vddioctrl=%x\n", readl(&power_regs->hw_power_vddioctrl)); } -void mx28_power_setup_5v_detect(void) +__static void mx28_power_setup_5v_detect(void) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; + dprintf("%s@%d: \n", __func__, __LINE__); /* Start 5V detection */ clrsetbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_VBUSVALID_TRSH_MASK, @@ -116,11 +197,12 @@ void mx28_power_setup_5v_detect(void) POWER_5VCTRL_PWRUP_VBUS_CMPS); } -void mx28_src_power_init(void) +__static void mx28_src_power_init(void) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; + dprintf("%s@%d: \n", __func__, __LINE__); /* Improve efficieny and reduce transient ripple */ writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST | POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set); @@ -140,18 +222,20 @@ void mx28_src_power_init(void) clrsetbits_le32(&power_regs->hw_power_minpwr, POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS); - +#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY /* 5V to battery handoff ... FIXME */ setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER); early_delay(30); clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER); +#endif } -void mx28_power_init_4p2_params(void) +__static void mx28_power_init_4p2_params(void) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; + dprintf("%s@%d: \n", __func__, __LINE__); /* Setup 4P2 parameters */ clrsetbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK, @@ -169,15 +253,18 @@ void mx28_power_init_4p2_params(void) clrsetbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK, 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET); + dprintf("5vctrl=%x\n", readl(&power_regs->hw_power_5vctrl)); + dprintf("dcdc4p2=%x\n", readl(&power_regs->hw_power_dcdc4p2)); } -void mx28_enable_4p2_dcdc_input(int xfer) +__static void mx28_enable_4p2_dcdc_input(int xfer) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo; uint32_t prev_5v_brnout, prev_5v_droop; + dprintf("%s@%d: %d\n", __func__, __LINE__, xfer); prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) & POWER_5VCTRL_PWDN_5VBRNOUT; prev_5v_droop = readl(&power_regs->hw_power_ctrl) & @@ -200,7 +287,7 @@ void mx28_enable_4p2_dcdc_input(int xfer) */ tmp = readl(&power_regs->hw_power_5vctrl); vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK; - vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT; + vbus_5vdetect = mx28_power_vbus_valid(); pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO; @@ -260,19 +347,20 @@ void mx28_enable_4p2_dcdc_input(int xfer) &power_regs->hw_power_ctrl_clr); if (prev_5v_droop) - clrbits_le32(&power_regs->hw_power_ctrl, + setbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP); else - setbits_le32(&power_regs->hw_power_ctrl, + clrbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP); } -void mx28_power_init_4p2_regulator(void) +__static void mx28_power_init_4p2_regulator(void) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; uint32_t tmp, tmp2; + dprintf("%s@%d: \n", __func__, __LINE__); setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2); writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set); @@ -351,11 +439,13 @@ void mx28_power_init_4p2_regulator(void) writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr); } -void mx28_power_init_dcdc_4p2_source(void) +__static void mx28_power_init_dcdc_4p2_source(void) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; + dprintf("%s@%d: \n", __func__, __LINE__); +#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY if (!(readl(&power_regs->hw_power_dcdc4p2) & POWER_DCDC4P2_ENABLE_DCDC)) { hang(); @@ -371,15 +461,20 @@ void mx28_power_init_dcdc_4p2_source(void) writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK, &power_regs->hw_power_5vctrl_set); } +#else + clrbits_le32(&power_regs->hw_power_dcdc4p2, + POWER_DCDC4P2_ENABLE_4P2 | POWER_DCDC4P2_ENABLE_DCDC); +#endif } -void mx28_power_enable_4p2(void) +__static void mx28_power_enable_4p2(void) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; uint32_t vdddctrl, vddactrl, vddioctrl; uint32_t tmp; + dprintf("%s@%d: \n", __func__, __LINE__); vdddctrl = readl(&power_regs->hw_power_vdddctrl); vddactrl = readl(&power_regs->hw_power_vddactrl); vddioctrl = readl(&power_regs->hw_power_vddioctrl); @@ -405,8 +500,12 @@ void mx28_power_enable_4p2(void) mx28_power_init_dcdc_4p2_source(); + readl(&power_regs->hw_power_vdddctrl); + readl(&power_regs->hw_power_vddactrl); + readl(&power_regs->hw_power_vddioctrl); writel(vdddctrl, &power_regs->hw_power_vdddctrl); early_delay(20); + memdump(0x80044000, 0x60); writel(vddactrl, &power_regs->hw_power_vddactrl); early_delay(20); writel(vddioctrl, &power_regs->hw_power_vddioctrl); @@ -427,11 +526,12 @@ void mx28_power_enable_4p2(void) &power_regs->hw_power_charge_clr); } -void mx28_boot_valid_5v(void) +__static void mx28_boot_valid_5v(void) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; + dprintf("%s@%d: \n", __func__, __LINE__); /* * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V * disconnect event. FIXME @@ -454,17 +554,20 @@ void mx28_powerdown(void) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; + + dprintf("%s@%d: \n", __func__, __LINE__); writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset); writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF, &power_regs->hw_power_reset); } -void mx28_handle_5v_conflict(void) +__static inline void mx28_handle_5v_conflict(void) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; uint32_t tmp; + dprintf("%s@%d: \n", __func__, __LINE__); setbits_le32(&power_regs->hw_power_vddioctrl, POWER_VDDIOCTRL_BO_OFFSET_MASK); @@ -486,50 +589,75 @@ void mx28_handle_5v_conflict(void) } } -int mx28_get_batt_volt(void) +__static int mx28_get_batt_volt(void) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; uint32_t volt = readl(&power_regs->hw_power_battmonitor); + + dprintf("%s@%d: \n", __func__, __LINE__); volt &= POWER_BATTMONITOR_BATT_VAL_MASK; volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET; volt *= 8; return volt; } -int mx28_is_batt_ready(void) +#define __maybe_unused __attribute__((unused)) + +__static int __maybe_unused mx28_is_batt_ready(void) { + dprintf("%s@%d: \n", __func__, __LINE__); return (mx28_get_batt_volt() >= 3600); } -void mx28_5v_boot(void) +__static void mx28_5v_boot(void) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; + dprintf("%s@%d: \n", __func__, __LINE__); +#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY /* * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID, * but their implementation always returns 1 so we omit it here. */ - if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { + if (mx28_power_vdd5v_gt_vddio()) { mx28_boot_valid_5v(); return; } early_delay(1000); - if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { + if (mx28_power_vdd5v_gt_vddio()) { mx28_boot_valid_5v(); return; } mx28_handle_5v_conflict(); +#else + writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set); + writel(1 << POWER_5VCTRL_PWD_CHARGE_4P2_OFFSET, &power_regs->hw_power_5vctrl_set); + + clrsetbits_le32(&power_regs->hw_power_vdddctrl, + POWER_VDDDCTRL_DISABLE_FET, + POWER_VDDDCTRL_ENABLE_LINREG | + POWER_VDDDCTRL_DISABLE_STEPPING); +#endif } -void mx28_init_batt_bo(void) +#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY +#define BATT_BO_VALUE 15 +#else +/* Brownout at 3.08V */ +#define BATT_BO_VALUE 17 +#endif + +__static void mx28_init_batt_bo(void) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; + dprintf("%s@%d: \n", __func__, __LINE__); +#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY /* Brownout at 3V */ clrsetbits_le32(&power_regs->hw_power_battmonitor, POWER_BATTMONITOR_BRWNOUT_LVL_MASK, @@ -537,13 +665,19 @@ void mx28_init_batt_bo(void) writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr); writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr); +#else + clrbits_le32(&power_regs->hw_power_battmonitor, + POWER_BATTMONITOR_PWDN_BATTBRNOUT); + writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr); +#endif } -void mx28_switch_vddd_to_dcdc_source(void) +__static void mx28_switch_vddd_to_dcdc_source(void) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; + dprintf("%s@%d: \n", __func__, __LINE__); clrsetbits_le32(&power_regs->hw_power_vdddctrl, POWER_VDDDCTRL_LINREG_OFFSET_MASK, POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW); @@ -553,12 +687,13 @@ void mx28_switch_vddd_to_dcdc_source(void) POWER_VDDDCTRL_DISABLE_STEPPING); } -int mx28_is_batt_good(void) +__static int __maybe_unused mx28_is_batt_good(void) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; uint32_t volt; + dprintf("%s@%d: \n", __func__, __LINE__); volt = readl(&power_regs->hw_power_battmonitor); volt &= POWER_BATTMONITOR_BATT_VAL_MASK; volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET; @@ -601,46 +736,54 @@ int mx28_is_batt_good(void) return 0; } -void mx28_power_configure_power_source(void) +__static void mx28_power_configure_power_source(void) { - mx28_src_power_init(); + dprintf("%s@%d: \n", __func__, __LINE__); + mx28_src_power_init(); mx28_5v_boot(); + mx28_power_clock2pll(); mx28_init_batt_bo(); + +#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY_ mx28_switch_vddd_to_dcdc_source(); +#endif } -void mx28_enable_output_rail_protection(void) +__static void mx28_enable_output_rail_protection(void) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ | POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr); - +#if 0 setbits_le32(&power_regs->hw_power_vdddctrl, POWER_VDDDCTRL_PWDN_BRNOUT); setbits_le32(&power_regs->hw_power_vddactrl, POWER_VDDACTRL_PWDN_BRNOUT); - +#endif setbits_le32(&power_regs->hw_power_vddioctrl, POWER_VDDIOCTRL_PWDN_BRNOUT); } -int mx28_get_vddio_power_source_off(void) +__static int mx28_get_vddio_power_source_off(void) { +#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY_ struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; uint32_t tmp; - if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { + dprintf("%s@%d: \n", __func__, __LINE__); + if (mx28_power_vdd5v_gt_vddio()) { tmp = readl(&power_regs->hw_power_vddioctrl); if (tmp & POWER_VDDIOCTRL_DISABLE_FET) { if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) == POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) { + dprintf("%s@%d: 1\n", __func__, __LINE__); return 1; } } @@ -649,25 +792,32 @@ int mx28_get_vddio_power_source_off(void) POWER_5VCTRL_ENABLE_DCDC)) { if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) == POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) { + dprintf("%s@%d: 1\n", __func__, __LINE__); return 1; } } } - + dprintf("%s@%d: 0\n", __func__, __LINE__); return 0; - +#else + dprintf("%s@%d: 1\n", __func__, __LINE__); + return 1; +#endif } -int mx28_get_vddd_power_source_off(void) +__static int mx28_get_vddd_power_source_off(void) { +#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY_ struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; uint32_t tmp; + dprintf("%s@%d: \n", __func__, __LINE__); tmp = readl(&power_regs->hw_power_vdddctrl); if (tmp & POWER_VDDDCTRL_DISABLE_FET) { if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) == POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) { + dprintf("%s@%d: 1\n", __func__, __LINE__); return 1; } } @@ -675,6 +825,7 @@ int mx28_get_vddd_power_source_off(void) if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { if (!(readl(&power_regs->hw_power_5vctrl) & POWER_5VCTRL_ENABLE_DCDC)) { + dprintf("%s@%d: 1\n", __func__, __LINE__); return 1; } } @@ -682,21 +833,31 @@ int mx28_get_vddd_power_source_off(void) if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) { if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) == POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) { + dprintf("%s@%d: 1\n", __func__, __LINE__); return 1; } } - + dprintf("%s@%d: 0\n", __func__, __LINE__); return 0; +#else + dprintf("%s@%d: 1\n", __func__, __LINE__); + return 1; +#endif } -void mx28_power_set_vddio(uint32_t new_target, uint32_t new_brownout) +__static void mx28_power_set_vddio(uint32_t new_target, uint32_t new_brownout) { struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; uint32_t cur_target, diff, bo_int = 0; - uint32_t powered_by_linreg = 0; + uint32_t powered_by_linreg; - new_brownout = new_target - new_brownout; + dprintf("%s@%d: \n", __func__, __LINE__); + new_brownout = (new_target - new_brownout) / 25; + if (new_brownout > 7) { + dprintf("Bad VDDD brownout offset\n"); + new_brownout = 7; + } cur_target = readl(&power_regs->hw_power_vddioctrl); cur_target &= POWER_VDDIOCTRL_TRG_MASK; @@ -704,6 +865,12 @@ void mx28_power_set_vddio(uint32_t new_target, uint32_t new_brownout) cur_target += 2800; /* 2800 mV lowest */ powered_by_linreg = mx28_get_vddio_power_source_off(); + if (new_target != cur_target) + dprintf("%s@%d: stepping VDDIO from %u to %u\n", __func__, __LINE__, + cur_target, new_target); + else + dprintf("%s@%d: VDDIO is at %u\n", __func__, __LINE__, + cur_target, new_target); if (new_target > cur_target) { if (powered_by_linreg) { @@ -725,6 +892,7 @@ void mx28_power_set_vddio(uint32_t new_target, uint32_t new_brownout) clrsetbits_le32(&power_regs->hw_power_vddioctrl, POWER_VDDIOCTRL_TRG_MASK, diff); + dprintf("vddioctrl=%x\n", readl(&power_regs->hw_power_vddioctrl)); if (powered_by_linreg) early_delay(1500); @@ -747,7 +915,9 @@ void mx28_power_set_vddio(uint32_t new_target, uint32_t new_brownout) if (bo_int & POWER_CTRL_ENIRQ_VDDIO_BO) setbits_le32(&power_regs->hw_power_vddioctrl, POWER_CTRL_ENIRQ_VDDIO_BO); + dprintf("vddioctrl=%x\n", readl(&power_regs->hw_power_vddioctrl)); } + dprintf("%s@%d: Done\n", __func__, __LINE__); } else { do { if (cur_target - new_target > 100) @@ -775,28 +945,40 @@ void mx28_power_set_vddio(uint32_t new_target, uint32_t new_brownout) cur_target *= 50; /* 50 mV step*/ cur_target += 2800; /* 2800 mV lowest */ } while (new_target < cur_target); + dprintf("%s@%d: Done\n", __func__, __LINE__); } clrsetbits_le32(&power_regs->hw_power_vddioctrl, POWER_VDDDCTRL_BO_OFFSET_MASK, new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET); + dprintf("vddioctrl=%x\n", readl(&power_regs->hw_power_vddioctrl)); } -void mx28_power_set_vddd(uint32_t new_target, uint32_t new_brownout) +__static void mx28_power_set_vddd(uint32_t new_target, uint32_t new_brownout) { struct mx28_power_regs *power_regs = (struct mx28_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; + uint32_t powered_by_linreg; + dprintf("%s@%d: \n", __func__, __LINE__); + new_brownout = (new_target - new_brownout) / 25; + if (new_brownout > 7) { + dprintf("Bad VDDD brownout offset\n"); + new_brownout = 7; + } 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 = mx28_get_vddd_power_source_off(); + if (new_target != cur_target) + dprintf("%s@%d: stepping VDDD from %u to %u\n", __func__, __LINE__, + cur_target, new_target); + else + dprintf("%s@%d: VDDD is at %u\n", __func__, __LINE__, + cur_target, new_target); if (new_target > cur_target) { if (powered_by_linreg) { bo_int = readl(&power_regs->hw_power_vdddctrl); @@ -841,6 +1023,7 @@ void mx28_power_set_vddd(uint32_t new_target, uint32_t new_brownout) setbits_le32(&power_regs->hw_power_vdddctrl, POWER_CTRL_ENIRQ_VDDD_BO); } + dprintf("%s@%d: Done\n", __func__, __LINE__); } else { do { if (cur_target - new_target > 100) @@ -868,6 +1051,7 @@ void mx28_power_set_vddd(uint32_t new_target, uint32_t new_brownout) cur_target *= 25; /* 25 mV step*/ cur_target += 800; /* 800 mV lowest */ } while (new_target < cur_target); + dprintf("%s@%d: Done\n", __func__, __LINE__); } clrsetbits_le32(&power_regs->hw_power_vdddctrl, @@ -880,25 +1064,79 @@ void mx28_power_init(void) struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; + dprintf("%s: %s %s\n", __func__, __DATE__, __TIME__); + dprintf("ctrl=%x\n", readl(&power_regs->hw_power_ctrl)); + dprintf("sts=%x\n", readl(&power_regs->hw_power_sts)); +#ifdef CONFIG_SPL_FIXED_BATT_SUPPLY_ + writel(0x00018024, &power_regs->hw_power_ctrl); + writel(0x20100592, &power_regs->hw_power_5vctrl); + writel(0x00000018, &power_regs->hw_power_dcdc4p2); + writel(0x0061071c, &power_regs->hw_power_vdddctrl); + writel(0x0000270c, &power_regs->hw_power_vddactrl); + writel(0x0004260a, &power_regs->hw_power_vddioctrl); +#else + dprintf("%s@%d\n", __func__, __LINE__); mx28_power_clock2xtal(); + dprintf("%s@%d\n", __func__, __LINE__); mx28_power_clear_auto_restart(); + dprintf("%s@%d\n", __func__, __LINE__); mx28_power_set_linreg(); + dprintf("%s@%d\n", __func__, __LINE__); +#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY mx28_power_setup_5v_detect(); + dprintf("%s@%d\n", __func__, __LINE__); mx28_power_configure_power_source(); - mx28_enable_output_rail_protection(); +// dprintf("%s@%d\n", __func__, __LINE__); +// mx28_enable_output_rail_protection(); + dprintf("%s@%d\n", __func__, __LINE__); mx28_power_set_vddio(3300, 3150); + dprintf("%s@%d\n", __func__, __LINE__); - mx28_power_set_vddd(1350, 1200); + mx28_power_set_vddd(1500, 1325); + dprintf("%s@%d\n", __func__, __LINE__); writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ | POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ | POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ | POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr); +#ifndef CONFIG_SPL_FIXED_BATT_SUPPLY writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set); - +#endif early_delay(1000); +#else + dprintf("%s@%d\n", __func__, __LINE__); + mx28_src_power_init(); + dprintf("%s@%d\n", __func__, __LINE__); + mx28_5v_boot(); + dprintf("%s@%d\n", __func__, __LINE__); + mx28_power_clock2pll(); + dprintf("%s@%d\n", __func__, __LINE__); + mx28_init_batt_bo(); + dprintf("%s@%d\n", __func__, __LINE__); + mx28_switch_vddd_to_dcdc_source(); + + dprintf("%s@%d\n", __func__, __LINE__); + mx28_power_set_vddio(3300, 3150); + + dprintf("%s@%d\n", __func__, __LINE__); + mx28_power_set_vddd(1500, 1325); + dprintf("%s@%d\n", __func__, __LINE__); + + writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ | + POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ | + POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ | + POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr); +#endif +#endif + dprintf("sts=%x\n", readl(&power_regs->hw_power_sts)); + dprintf("vddioctrl=%x\n", readl(&power_regs->hw_power_vddioctrl)); + dprintf("vdddctrl=%x\n", readl(&power_regs->hw_power_vdddctrl)); + dprintf("5vctrl=%x\n", readl(&power_regs->hw_power_5vctrl)); + dprintf("dcdc4p2=%x\n", readl(&power_regs->hw_power_dcdc4p2)); + dprintf("%s@%d: Finished\n", __func__, __LINE__); + memdump(0x80044000, 0x60); } #ifdef CONFIG_SPL_MX28_PSWITCH_WAIT @@ -907,6 +1145,7 @@ void mx28_power_wait_pswitch(void) struct mx28_power_regs *power_regs = (struct mx28_power_regs *)MXS_POWER_BASE; + dprintf("%s@%d: \n", __func__, __LINE__); while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK)) ; }