mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-10 17:41:54 +00:00
Since pretty much always, we've declared console commands to take a "longhelp" argument with detailed explanations of what the command does. But since almost as long, we've never actually used that argument for anything - we just silently throw it away in the macro. There's only one command (usbchargemode) that even thinks it defines that argument. We're never going to use this, let's just get rid of it. BUG=none BRANCH=none CQ-DEPEND=CL:*279060 CQ-DEPEND=CL:*279158 CQ-DEPEND=CL:*279037 TEST=make buildall; tested on Cr50 hardware Everything builds. Since we never used this arg anyway, there had better not be any difference in the result. Change-Id: Id3f71a53d02e3dc625cfcc12aa71ecb50e35eb9f Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/374163 Reviewed-by: Myles Watson <mylesgw@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
744 lines
16 KiB
C
744 lines
16 KiB
C
/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*
|
|
* TI TPS65090 PMU driver.
|
|
*/
|
|
|
|
#include "clock.h"
|
|
#include "console.h"
|
|
#include "common.h"
|
|
#include "extpower.h"
|
|
#include "host_command.h"
|
|
#include "hooks.h"
|
|
#include "i2c.h"
|
|
#include "pmu_tpschrome.h"
|
|
#include "task.h"
|
|
#include "timer.h"
|
|
#include "util.h"
|
|
|
|
#define CPUTS(outstr) cputs(CC_CHARGER, outstr)
|
|
#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args)
|
|
|
|
#define TPS65090_I2C_ADDR 0x90
|
|
|
|
#define IRQ1_REG 0x00
|
|
#define IRQ2_REG 0x01
|
|
#define IRQ1MASK 0x02
|
|
#define IRQ2MASK 0x03
|
|
#define CG_CTRL0 0x04
|
|
#define CG_CTRL1 0x05
|
|
#define CG_CTRL2 0x06
|
|
#define CG_CTRL3 0x07
|
|
#define CG_CTRL4 0x08
|
|
#define CG_CTRL5 0x09
|
|
#define CG_STATUS1 0x0a
|
|
#define CG_STATUS2 0x0b
|
|
#define DCDC1_CTRL 0x0c
|
|
#define DCDC2_CTRL 0x0d
|
|
#define DCDC3_CTRL 0x0e
|
|
#define FET1_CTRL 0x0f
|
|
#define FET2_CTRL 0x10
|
|
#define FET3_CTRL 0x11
|
|
#define FET4_CTRL 0x12
|
|
#define FET5_CTRL 0x13
|
|
#define FET6_CTRL 0x14
|
|
#define FET7_CTRL 0x15
|
|
#define AD_CTRL 0x16
|
|
#define AD_OUT1 0x17
|
|
#define AD_OUT2 0x18
|
|
#define TPSCHROME_VER 0x19
|
|
|
|
/* Charger control */
|
|
#define CG_EN (1 << 0)
|
|
#define CG_EXT_EN (1 << 1)
|
|
#define CG_FASTCHARGE_SHIFT 2
|
|
#define CG_FASTCHARGE_MASK (7 << CG_FASTCHARGE_SHIFT)
|
|
|
|
/* Charger termination voltage/current */
|
|
#define CG_VSET_SHIFT 3
|
|
#define CG_VSET_MASK (3 << CG_VSET_SHIFT)
|
|
#define CG_ISET_SHIFT 0
|
|
#define CG_ISET_MASK (7 << CG_ISET_SHIFT)
|
|
#define CG_NOITERM (1 << 5)
|
|
#define CG_TSET_SHIFT 5
|
|
#define CG_TSET_MASK (7 << CG_TSET_SHIFT)
|
|
|
|
/* A temperature threshold to force charger hardware error */
|
|
#define CG_TEMP_THRESHOLD_ERROR 0
|
|
|
|
/* Timeout indication */
|
|
#define STATUS_TIMEOUT_MASK 0xc
|
|
#define STATUS_PRECHARGE_TIMEOUT 0x4
|
|
#define STATUS_FASTCHARGE_TIMEOUT 0x8
|
|
|
|
/* IRQ events */
|
|
#define EVENT_VACG (1 << 1) /* AC voltage good */
|
|
#define EVENT_VSYSG (1 << 2) /* System voltage good */
|
|
#define EVENT_VBATG (1 << 3) /* Battery voltage good */
|
|
#define EVENT_CGACT (1 << 4) /* Charging status */
|
|
#define EVENT_CGCPL (1 << 5) /* Charging complete */
|
|
|
|
/* Charger alarm */
|
|
#define CHARGER_ALARM 3
|
|
|
|
/* FET control register bits */
|
|
#define FET_CTRL_ENFET (1 << 0)
|
|
#define FET_CTRL_ADENFET (1 << 1)
|
|
#define FET_CTRL_WAIT (3 << 2) /* Overcurrent timeout max : 3200 us */
|
|
#define FET_CTRL_PGFET (1 << 4)
|
|
|
|
#define FET_CTRL_BASE (FET1_CTRL - 1)
|
|
|
|
#define POWER_GOOD_DELAY_US 3500
|
|
|
|
/* AD control register bits */
|
|
#define AD_CTRL_ENADREF (1 << 4)
|
|
#define AD_CTRL_ADEOC (1 << 5)
|
|
#define AD_CTRL_ADSTART (1 << 6)
|
|
|
|
#define HARD_RESET_TIMEOUT_MS 5
|
|
|
|
/* Charger temperature threshold table */
|
|
static const uint8_t const pmu_temp_threshold[] = {
|
|
1, /* 0b001, 0 degree C */
|
|
2, /* 0b010, 10 degree C */
|
|
5, /* 0b101, 45 degree C */
|
|
7, /* 0b111, 60 degree C */
|
|
};
|
|
|
|
#ifdef CONFIG_PMU_HARD_RESET
|
|
/**
|
|
* Force the pmic to reset completely.
|
|
*
|
|
* This forces an entire system reset, and therefore should never return. The
|
|
* implementation is rather hacky; it simply shorts out the 3.3V rail to force
|
|
* the PMIC to panic. We need this unfortunate hack because it's the only way
|
|
* to reset the I2C engine inside the PMU.
|
|
*/
|
|
static void pmu_hard_reset(void)
|
|
{
|
|
/* Short out the 3.3V rail to force a hard reset of tps Chrome */
|
|
gpio_set_level(GPIO_PMIC_RESET, 1);
|
|
|
|
/* Delay while the power is cut */
|
|
udelay(HARD_RESET_TIMEOUT_MS * 1000);
|
|
|
|
/* Shouldn't get here unless the board doesn't have this capability */
|
|
panic_puts("pmu hard reset failed! (this board may not be capable)\n");
|
|
}
|
|
#else
|
|
static void pmu_hard_reset(void)
|
|
{
|
|
panic_puts("pmu hard reset unsupported!\n");
|
|
}
|
|
#endif
|
|
|
|
/* Read all tps65090 interrupt events */
|
|
static int pmu_get_event(int *event)
|
|
{
|
|
static int prev_event;
|
|
int rv;
|
|
int irq1, irq2;
|
|
|
|
pmu_clear_irq();
|
|
|
|
rv = pmu_read(IRQ1_REG, &irq1);
|
|
if (rv)
|
|
return rv;
|
|
rv = pmu_read(IRQ2_REG, &irq2);
|
|
if (rv)
|
|
return rv;
|
|
|
|
*event = irq1 | (irq2 << 8);
|
|
|
|
if (prev_event != *event) {
|
|
CPRINTS("pmu event: %016b", *event);
|
|
prev_event = *event;
|
|
}
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
/* Clear tps65090 irq */
|
|
int pmu_clear_irq(void)
|
|
{
|
|
return pmu_write(IRQ1_REG, 0);
|
|
}
|
|
|
|
/* Read/write tps65090 register */
|
|
int pmu_read(int reg, int *value)
|
|
{
|
|
return i2c_read8(I2C_PORT_CHARGER, TPS65090_I2C_ADDR, reg, value);
|
|
}
|
|
|
|
int pmu_write(int reg, int value)
|
|
{
|
|
return i2c_write8(I2C_PORT_CHARGER, TPS65090_I2C_ADDR, reg, value);
|
|
}
|
|
|
|
/**
|
|
* Read tpschrome version
|
|
*
|
|
* @param version output value of tpschrome version
|
|
*/
|
|
int pmu_version(int *version)
|
|
{
|
|
return pmu_read(TPSCHROME_VER, version);
|
|
}
|
|
|
|
int pmu_is_charger_alarm(void)
|
|
{
|
|
int status;
|
|
|
|
/**
|
|
* if the I2C access to the PMU fails, we consider the failure as
|
|
* non-critical and wait for the next read without send the alert.
|
|
*/
|
|
if (!pmu_read(CG_STATUS1, &status) && (status & CHARGER_ALARM))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
int pmu_is_charge_timeout(void)
|
|
{
|
|
int status;
|
|
|
|
if (pmu_read(CG_STATUS1, &status))
|
|
return 0;
|
|
|
|
status &= STATUS_TIMEOUT_MASK;
|
|
return (status == STATUS_PRECHARGE_TIMEOUT) ||
|
|
(status == STATUS_FASTCHARGE_TIMEOUT);
|
|
}
|
|
|
|
int pmu_get_power_source(int *ac_good, int *battery_good)
|
|
{
|
|
int rv, event = 0;
|
|
|
|
rv = pmu_get_event(&event);
|
|
if (rv)
|
|
return rv;
|
|
|
|
if (ac_good)
|
|
*ac_good = event & EVENT_VACG;
|
|
if (battery_good)
|
|
*battery_good = event & EVENT_VBATG;
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* Enable charger's charging function
|
|
*
|
|
* When enable, charger ignores external control and charge the
|
|
* battery directly. If EC wants to contorl charging, set the flag
|
|
* to 0.
|
|
*/
|
|
int pmu_enable_charger(int enable)
|
|
{
|
|
int rv;
|
|
int reg;
|
|
|
|
rv = pmu_read(CG_CTRL0, ®);
|
|
if (rv)
|
|
return rv;
|
|
|
|
if (enable)
|
|
reg |= CG_EN;
|
|
else
|
|
reg &= ~CG_EN;
|
|
|
|
return pmu_write(CG_CTRL0, reg);
|
|
}
|
|
|
|
/**
|
|
* Set external charge enable pin
|
|
*
|
|
* @param enable boolean, set 1 to eanble external control
|
|
*/
|
|
int pmu_enable_ext_control(int enable)
|
|
{
|
|
int rv;
|
|
int reg;
|
|
|
|
rv = pmu_read(CG_CTRL0, ®);
|
|
if (rv)
|
|
return rv;
|
|
|
|
if (enable)
|
|
reg |= CG_EXT_EN;
|
|
else
|
|
reg &= ~CG_EXT_EN;
|
|
|
|
return pmu_write(CG_CTRL0, reg);
|
|
}
|
|
|
|
/**
|
|
* Set fast charge timeout
|
|
*
|
|
* @param timeout enum FASTCHARGE_TIMEOUT
|
|
*/
|
|
int pmu_set_fastcharge(enum FASTCHARGE_TIMEOUT timeout)
|
|
{
|
|
int rv;
|
|
int reg;
|
|
|
|
rv = pmu_read(CG_CTRL0, ®);
|
|
if (rv)
|
|
return rv;
|
|
|
|
reg &= ~CG_FASTCHARGE_MASK;
|
|
reg |= (timeout << CG_FASTCHARGE_SHIFT) & CG_FASTCHARGE_MASK;
|
|
|
|
return pmu_write(CG_CTRL0, reg);
|
|
}
|
|
|
|
/**
|
|
* Set termination current for temperature ranges
|
|
*
|
|
* @param range T01 T12 T23 T34 T40
|
|
* @param current enum termination current, I0250 == 25.0%:
|
|
* I0000 I0250 I0375 I0500 I0625 I0750 I0875 I1000
|
|
*/
|
|
int pmu_set_term_current(enum TPS_TEMPERATURE_RANGE range,
|
|
enum TPS_TERMINATION_CURRENT current)
|
|
{
|
|
int rv;
|
|
int reg_val;
|
|
|
|
rv = pmu_read(CG_CTRL1 + range, ®_val);
|
|
if (rv)
|
|
return rv;
|
|
|
|
reg_val &= ~CG_ISET_MASK;
|
|
reg_val |= current << CG_ISET_SHIFT;
|
|
|
|
return pmu_write(CG_CTRL1 + range, reg_val);
|
|
}
|
|
|
|
/**
|
|
* Set termination voltage for temperature ranges
|
|
*
|
|
* @param range T01 T12 T23 T34 T40
|
|
* @param voltage enum termination voltage, V2050 == 2.05V:
|
|
* V2000 V2050 V2075 V2100
|
|
*/
|
|
int pmu_set_term_voltage(enum TPS_TEMPERATURE_RANGE range,
|
|
enum TPS_TERMINATION_VOLTAGE voltage)
|
|
{
|
|
int rv;
|
|
int reg_val;
|
|
|
|
rv = pmu_read(CG_CTRL1 + range, ®_val);
|
|
if (rv)
|
|
return rv;
|
|
|
|
reg_val &= ~CG_VSET_MASK;
|
|
reg_val |= voltage << CG_VSET_SHIFT;
|
|
|
|
return pmu_write(CG_CTRL1 + range, reg_val);
|
|
}
|
|
|
|
/**
|
|
* Set temperature threshold
|
|
*
|
|
* @param temp_n TSET_T1 to TSET_T4
|
|
* @param value 0b000 ~ 0b111, temperature threshold
|
|
*/
|
|
int pmu_set_temp_threshold(enum TPS_TEMPERATURE temp_n, uint8_t value)
|
|
{
|
|
int rv;
|
|
int reg_val;
|
|
|
|
/*
|
|
* Temperature threshold T1 to T4 are stored in TPSCHROME registers
|
|
* CG_CTRL1 to CG_CTRL4.
|
|
*/
|
|
rv = pmu_read(CG_CTRL1 + temp_n, ®_val);
|
|
if (rv)
|
|
return rv;
|
|
|
|
reg_val &= ~CG_TSET_MASK;
|
|
reg_val |= (value << CG_TSET_SHIFT) & CG_TSET_MASK;
|
|
|
|
return pmu_write(CG_CTRL1 + temp_n, reg_val);
|
|
}
|
|
|
|
/**
|
|
* Force charger into error state, turn off charging and blinks charging LED
|
|
*
|
|
* @param enable true to turn off charging and blink LED
|
|
* @return EC_SUCCESS for success
|
|
*/
|
|
int pmu_blink_led(int enable)
|
|
{
|
|
int rv;
|
|
enum TPS_TEMPERATURE t;
|
|
uint8_t threshold;
|
|
|
|
for (t = TSET_T1; t <= TSET_T4; t++) {
|
|
if (enable)
|
|
threshold = CG_TEMP_THRESHOLD_ERROR;
|
|
else
|
|
threshold = pmu_temp_threshold[t];
|
|
|
|
rv = pmu_set_temp_threshold(t, threshold);
|
|
if (rv) {
|
|
/* Retry */
|
|
rv = pmu_set_temp_threshold(t, threshold);
|
|
if (rv)
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* Enable low current charging
|
|
*
|
|
* @param enable enable/disable low current charging
|
|
*/
|
|
int pmu_low_current_charging(int enable)
|
|
{
|
|
int rv;
|
|
int reg_val;
|
|
|
|
rv = pmu_read(CG_CTRL5, ®_val);
|
|
if (rv)
|
|
return rv;
|
|
|
|
if (enable)
|
|
reg_val |= CG_NOITERM;
|
|
else
|
|
reg_val &= ~CG_NOITERM;
|
|
|
|
return pmu_write(CG_CTRL5, reg_val);
|
|
}
|
|
|
|
int pmu_enable_fet(int fet_id, int enable, int *power_good)
|
|
{
|
|
int rv, reg;
|
|
int reg_offset;
|
|
|
|
reg_offset = FET_CTRL_BASE + fet_id;
|
|
|
|
rv = pmu_read(reg_offset, ®);
|
|
if (rv)
|
|
return rv;
|
|
reg |= FET_CTRL_ADENFET | FET_CTRL_WAIT;
|
|
if (enable)
|
|
reg |= FET_CTRL_ENFET;
|
|
else
|
|
reg &= ~FET_CTRL_ENFET;
|
|
|
|
rv = pmu_write(reg_offset, reg);
|
|
if (rv)
|
|
return rv;
|
|
|
|
if (power_good) {
|
|
usleep(POWER_GOOD_DELAY_US);
|
|
rv = pmu_read(reg_offset, ®);
|
|
if (rv)
|
|
return rv;
|
|
*power_good = reg & FET_CTRL_PGFET;
|
|
}
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
int pmu_adc_read(int adc_idx, int flags)
|
|
{
|
|
int ctrl;
|
|
int val1, val2;
|
|
int rv;
|
|
|
|
rv = pmu_read(AD_CTRL, &ctrl);
|
|
if (rv)
|
|
return rv;
|
|
if (!(ctrl & AD_CTRL_ENADREF)) {
|
|
ctrl |= AD_CTRL_ENADREF;
|
|
rv = pmu_write(AD_CTRL, ctrl);
|
|
if (rv)
|
|
return rv;
|
|
/* wait for reference voltage stabilization */
|
|
msleep(10);
|
|
}
|
|
|
|
ctrl = (ctrl & ~0xf) | adc_idx;
|
|
rv = pmu_write(AD_CTRL, ctrl);
|
|
if (rv)
|
|
return rv;
|
|
udelay(150);
|
|
|
|
ctrl |= AD_CTRL_ADSTART;
|
|
rv = pmu_write(AD_CTRL, ctrl);
|
|
if (rv)
|
|
return rv;
|
|
udelay(200);
|
|
|
|
do {
|
|
rv = pmu_read(AD_CTRL, &ctrl);
|
|
if (rv)
|
|
return rv;
|
|
} while (!(ctrl & AD_CTRL_ADEOC));
|
|
|
|
rv = pmu_read(AD_OUT1, &val1) | pmu_read(AD_OUT2, &val2);
|
|
if (rv)
|
|
return rv;
|
|
|
|
if (!(flags & ADC_FLAG_KEEP_ON))
|
|
rv = pmu_write(AD_CTRL, ctrl & ~AD_CTRL_ENADREF);
|
|
|
|
return (val2 << 8) | val1;
|
|
}
|
|
|
|
/**
|
|
* Attempt shutdown.
|
|
*/
|
|
static int pmu_try_shutdown(void)
|
|
{
|
|
int offset;
|
|
|
|
/* Disable each of the DCDCs */
|
|
for (offset = DCDC1_CTRL; offset <= DCDC3_CTRL; offset++) {
|
|
if (pmu_write(offset, 0x0e))
|
|
return EC_ERROR_UNKNOWN;
|
|
}
|
|
/* Disable each of the FETs */
|
|
for (offset = FET1_CTRL; offset <= FET7_CTRL; offset++) {
|
|
if (pmu_write(offset, 0x02))
|
|
return EC_ERROR_UNKNOWN;
|
|
}
|
|
|
|
/* Clear AD controls/status */
|
|
if (pmu_write(AD_CTRL, 0x00))
|
|
return EC_ERROR_UNKNOWN;
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
int pmu_shutdown(void)
|
|
{
|
|
int pmu_shutdown_retries = 3;
|
|
|
|
/* Attempt shutdown */
|
|
while (--pmu_shutdown_retries >= 0) {
|
|
if (!pmu_try_shutdown())
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
#ifdef CONFIG_PMU_HARD_RESET
|
|
/* We ran out of tries, so reset the board */
|
|
CPUTS("PMU shutdown failed. Hard-resetting.\n");
|
|
cflush();
|
|
pmu_hard_reset();
|
|
#endif
|
|
|
|
/* If we're still here, we couldn't shutdown OR reset */
|
|
return EC_ERROR_UNKNOWN;
|
|
}
|
|
|
|
/*
|
|
* Fill all of the pmu registers with known good values, this allows the
|
|
* pmu to recover by rebooting the system if its registers were trashed.
|
|
*/
|
|
static void pmu_init_registers(void)
|
|
{
|
|
const struct {
|
|
uint8_t index;
|
|
uint8_t value;
|
|
} reg[] = {
|
|
{IRQ1MASK, 0x00},
|
|
{IRQ2MASK, 0x00},
|
|
{CG_CTRL0, 0x02},
|
|
{CG_CTRL1, 0x20},
|
|
{CG_CTRL2, 0x4b},
|
|
{CG_CTRL3, 0xbf},
|
|
{CG_CTRL4, 0xf3},
|
|
{CG_CTRL5, 0xc0},
|
|
{DCDC1_CTRL, 0x0e},
|
|
{DCDC2_CTRL, 0x0e},
|
|
{DCDC3_CTRL, 0x0e},
|
|
{FET1_CTRL, 0x02},
|
|
{FET2_CTRL, 0x02},
|
|
{FET3_CTRL, 0x02},
|
|
{FET4_CTRL, 0x02},
|
|
{FET5_CTRL, 0x02},
|
|
{FET6_CTRL, 0x02},
|
|
{FET7_CTRL, 0x02},
|
|
{AD_CTRL, 0x00},
|
|
{IRQ1_REG, 0x00}
|
|
};
|
|
uint8_t i;
|
|
|
|
/*
|
|
* Write all PMU registers. Ignore return value from pmu_write()
|
|
* because there's nothing we can reasonably do if it fails.
|
|
*/
|
|
for (i = 0; i < ARRAY_SIZE(reg); i++)
|
|
pmu_write(reg[i].index, reg[i].value);
|
|
}
|
|
DECLARE_HOOK(HOOK_CHIPSET_PRE_INIT, pmu_init_registers, HOOK_PRIO_DEFAULT);
|
|
|
|
void pmu_init(void)
|
|
{
|
|
int failure = 0, retries_remaining = 3;
|
|
|
|
while (--retries_remaining >= 0) {
|
|
failure = pmu_board_init();
|
|
|
|
/* Enable interrupts */
|
|
if (!failure) {
|
|
failure = pmu_write(IRQ1MASK,
|
|
EVENT_VACG | /* AC voltage good */
|
|
EVENT_VSYSG | /* System voltage good */
|
|
EVENT_VBATG | /* Battery voltage good */
|
|
EVENT_CGACT | /* Charging status */
|
|
EVENT_CGCPL); /* Charging complete */
|
|
}
|
|
if (!failure)
|
|
failure = pmu_write(IRQ2MASK, 0);
|
|
if (!failure)
|
|
failure = pmu_clear_irq();
|
|
|
|
/* Exit the retry loop if there was no failure */
|
|
if (!failure)
|
|
break;
|
|
}
|
|
|
|
if (failure) {
|
|
CPUTS("Failed to initialize PMU. Hard-resetting.\n");
|
|
cflush();
|
|
pmu_hard_reset();
|
|
}
|
|
}
|
|
|
|
/* Initializes PMU when power is turned on. This is necessary because the TPS'
|
|
* 3.3V rail is not powered until the power is turned on. */
|
|
static void pmu_chipset_startup(void)
|
|
{
|
|
pmu_init();
|
|
|
|
#ifdef BOARD_PIT
|
|
/* Enable FET4 by default which allows for SD Card booting */
|
|
{
|
|
int pgood;
|
|
pmu_enable_fet(4, 1, &pgood);
|
|
}
|
|
#endif
|
|
}
|
|
DECLARE_HOOK(HOOK_CHIPSET_STARTUP, pmu_chipset_startup, HOOK_PRIO_DEFAULT);
|
|
|
|
#ifdef CONFIG_CMD_PMU
|
|
static int print_pmu_info(void)
|
|
{
|
|
int reg, ret;
|
|
int value;
|
|
|
|
ccprintf(" ");
|
|
for (reg = 0; reg <= 0x18; reg++)
|
|
ccprintf("%02x ", reg);
|
|
ccprintf("\n");
|
|
|
|
ccprintf("PMU: ");
|
|
for (reg = 0; reg <= 0x18; reg++) {
|
|
ret = pmu_read(reg, &value);
|
|
if (ret)
|
|
return ret;
|
|
ccprintf("%02x ", value);
|
|
}
|
|
ccputs("\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int command_pmu(int argc, char **argv)
|
|
{
|
|
int repeat = 1;
|
|
int rv = 0;
|
|
int loop;
|
|
int value;
|
|
char *e;
|
|
|
|
if (argc > 1) {
|
|
repeat = strtoi(argv[1], &e, 0);
|
|
if (*e) {
|
|
if (strlen(argv[1]) >= 1 && argv[1][0] == 'r') {
|
|
pmu_hard_reset();
|
|
/* If this returns, there was an error */
|
|
return EC_ERROR_UNKNOWN;
|
|
}
|
|
|
|
ccputs("Invalid repeat count\n");
|
|
return EC_ERROR_INVAL;
|
|
}
|
|
}
|
|
|
|
for (loop = 0; loop < repeat; loop++) {
|
|
rv = print_pmu_info();
|
|
usleep(1000);
|
|
}
|
|
|
|
rv = pmu_read(IRQ1_REG, &value);
|
|
if (rv)
|
|
return rv;
|
|
CPRINTS("pmu events b%08b", value);
|
|
CPRINTS("ac gpio %d", extpower_is_present());
|
|
|
|
if (rv)
|
|
ccprintf("Failed - error %d\n", rv);
|
|
|
|
return rv ? EC_ERROR_UNKNOWN : EC_SUCCESS;
|
|
}
|
|
DECLARE_CONSOLE_COMMAND(pmu, command_pmu,
|
|
"<repeat_count|reset>",
|
|
"Print PMU info or force a hard reset");
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
/* TPSchrome LDO pass-through
|
|
*/
|
|
#ifdef CONFIG_I2C_PASSTHROUGH
|
|
static int host_command_ldo_get(struct host_cmd_handler_args *args)
|
|
{
|
|
int rv;
|
|
int val;
|
|
const struct ec_params_ldo_get *p = args->params;
|
|
struct ec_response_ldo_get *r = args->response;
|
|
|
|
/* is this an existing TPSchrome FET ? */
|
|
if ((p->index < 1) || (p->index > 7))
|
|
return EC_RES_ERROR;
|
|
|
|
rv = pmu_read(FET_CTRL_BASE + p->index, &val);
|
|
if (rv)
|
|
return EC_RES_ERROR;
|
|
|
|
r->state = !!(val & FET_CTRL_PGFET);
|
|
args->response_size = sizeof(struct ec_response_ldo_get);
|
|
|
|
return EC_RES_SUCCESS;
|
|
}
|
|
DECLARE_HOST_COMMAND(EC_CMD_LDO_GET,
|
|
host_command_ldo_get,
|
|
EC_VER_MASK(0));
|
|
|
|
static int host_command_ldo_set(struct host_cmd_handler_args *args)
|
|
{
|
|
int rv;
|
|
const struct ec_params_ldo_set *p = args->params;
|
|
|
|
/* is this an existing TPSchrome FET ? */
|
|
if ((p->index < 1) || (p->index > 7))
|
|
return EC_RES_ERROR;
|
|
rv = pmu_enable_fet(p->index, p->state & EC_LDO_STATE_ON, NULL);
|
|
|
|
return rv ? EC_RES_ERROR : EC_RES_SUCCESS;
|
|
}
|
|
DECLARE_HOST_COMMAND(EC_CMD_LDO_SET,
|
|
host_command_ldo_set,
|
|
EC_VER_MASK(0));
|
|
#endif
|