mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-01 00:49:43 +00:00
83d290c56f
When U-Boot started using SPDX tags we were among the early adopters and there weren't a lot of other examples to borrow from. So we picked the area of the file that usually had a full license text and replaced it with an appropriate SPDX-License-Identifier: entry. Since then, the Linux Kernel has adopted SPDX tags and they place it as the very first line in a file (except where shebangs are used, then it's second line) and with slightly different comment styles than us. In part due to community overlap, in part due to better tag visibility and in part for other minor reasons, switch over to that style. This commit changes all instances where we have a single declared license in the tag as both the before and after are identical in tag contents. There's also a few places where I found we did not have a tag and have introduced one. Signed-off-by: Tom Rini <trini@konsulko.com>
270 lines
6.7 KiB
C
270 lines
6.7 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* (C) Copyright 2010
|
|
* Texas Instruments, <www.ti.com>
|
|
*/
|
|
#include <config.h>
|
|
|
|
#include <twl6030.h>
|
|
|
|
static struct twl6030_data *twl;
|
|
|
|
static struct twl6030_data twl6030_info = {
|
|
.chip_type = chip_TWL6030,
|
|
.adc_rbase = GPCH0_LSB,
|
|
.adc_ctrl = CTRL_P2,
|
|
.adc_enable = CTRL_P2_SP2,
|
|
.vbat_mult = TWL6030_VBAT_MULT,
|
|
.vbat_shift = TWL6030_VBAT_SHIFT,
|
|
};
|
|
|
|
static struct twl6030_data twl6032_info = {
|
|
.chip_type = chip_TWL6032,
|
|
.adc_rbase = TWL6032_GPCH0_LSB,
|
|
.adc_ctrl = TWL6032_CTRL_P1,
|
|
.adc_enable = CTRL_P1_SP1,
|
|
.vbat_mult = TWL6032_VBAT_MULT,
|
|
.vbat_shift = TWL6032_VBAT_SHIFT,
|
|
};
|
|
|
|
|
|
static int twl6030_gpadc_read_channel(u8 channel_no)
|
|
{
|
|
u8 lsb = 0;
|
|
u8 msb = 0;
|
|
int ret = 0;
|
|
|
|
ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC,
|
|
twl->adc_rbase + channel_no * 2, &lsb);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC,
|
|
twl->adc_rbase + 1 + channel_no * 2, &msb);
|
|
if (ret)
|
|
return ret;
|
|
|
|
return (msb << 8) | lsb;
|
|
}
|
|
|
|
static int twl6030_gpadc_sw2_trigger(void)
|
|
{
|
|
u8 val;
|
|
int ret = 0;
|
|
|
|
ret = twl6030_i2c_write_u8(TWL6030_CHIP_ADC,
|
|
twl->adc_ctrl, twl->adc_enable);
|
|
if (ret)
|
|
return ret;
|
|
|
|
/* Waiting until the SW1 conversion ends*/
|
|
val = CTRL_P2_BUSY;
|
|
|
|
while (!((val & CTRL_P2_EOCP2) && (!(val & CTRL_P2_BUSY)))) {
|
|
ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC,
|
|
twl->adc_ctrl, &val);
|
|
if (ret)
|
|
return ret;
|
|
udelay(1000);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void twl6030_power_off(void)
|
|
{
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_PHOENIX_DEV_ON,
|
|
TWL6030_PHOENIX_APP_DEVOFF | TWL6030_PHOENIX_CON_DEVOFF |
|
|
TWL6030_PHOENIX_MOD_DEVOFF);
|
|
}
|
|
|
|
void twl6030_stop_usb_charging(void)
|
|
{
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CONTROLLER_CTRL1, 0);
|
|
|
|
return;
|
|
}
|
|
|
|
void twl6030_start_usb_charging(void)
|
|
{
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
|
|
CHARGERUSB_VICHRG, CHARGERUSB_VICHRG_1500);
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
|
|
CHARGERUSB_CINLIMIT, CHARGERUSB_CIN_LIMIT_NONE);
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
|
|
CONTROLLER_INT_MASK, MBAT_TEMP);
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
|
|
CHARGERUSB_INT_MASK, MASK_MCHARGERUSB_THMREG);
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
|
|
CHARGERUSB_VOREG, CHARGERUSB_VOREG_4P0);
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
|
|
CHARGERUSB_CTRL2, CHARGERUSB_CTRL2_VITERM_400);
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CHARGERUSB_CTRL1, TERM);
|
|
/* Enable USB charging */
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
|
|
CONTROLLER_CTRL1, CONTROLLER_CTRL1_EN_CHARGER);
|
|
return;
|
|
}
|
|
|
|
int twl6030_get_battery_current(void)
|
|
{
|
|
int battery_current = 0;
|
|
u8 msb = 0;
|
|
u8 lsb = 0;
|
|
|
|
twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_11, &msb);
|
|
twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_10, &lsb);
|
|
battery_current = ((msb << 8) | lsb);
|
|
|
|
/* convert 10 bit signed number to 16 bit signed number */
|
|
if (battery_current >= 0x2000)
|
|
battery_current = (battery_current - 0x4000);
|
|
|
|
battery_current = battery_current * 3000 / 4096;
|
|
printf("Battery Current: %d mA\n", battery_current);
|
|
|
|
return battery_current;
|
|
}
|
|
|
|
int twl6030_get_battery_voltage(void)
|
|
{
|
|
int battery_volt = 0;
|
|
int ret = 0;
|
|
u8 vbatch;
|
|
|
|
if (twl->chip_type == chip_TWL6030) {
|
|
vbatch = TWL6030_GPADC_VBAT_CHNL;
|
|
} else {
|
|
ret = twl6030_i2c_write_u8(TWL6030_CHIP_ADC,
|
|
TWL6032_GPSELECT_ISB,
|
|
TWL6032_GPADC_VBAT_CHNL);
|
|
if (ret)
|
|
return ret;
|
|
vbatch = 0;
|
|
}
|
|
|
|
/* Start GPADC SW conversion */
|
|
ret = twl6030_gpadc_sw2_trigger();
|
|
if (ret) {
|
|
printf("Failed to convert battery voltage\n");
|
|
return ret;
|
|
}
|
|
|
|
/* measure Vbat voltage */
|
|
battery_volt = twl6030_gpadc_read_channel(vbatch);
|
|
if (battery_volt < 0) {
|
|
printf("Failed to read battery voltage\n");
|
|
return ret;
|
|
}
|
|
battery_volt = (battery_volt * twl->vbat_mult) >> twl->vbat_shift;
|
|
printf("Battery Voltage: %d mV\n", battery_volt);
|
|
|
|
return battery_volt;
|
|
}
|
|
|
|
void twl6030_init_battery_charging(void)
|
|
{
|
|
u8 val = 0;
|
|
int battery_volt = 0;
|
|
int ret = 0;
|
|
|
|
ret = twl6030_i2c_read_u8(TWL6030_CHIP_USB, USB_PRODUCT_ID_LSB, &val);
|
|
if (ret) {
|
|
puts("twl6030_init_battery_charging(): could not determine chip!\n");
|
|
return;
|
|
}
|
|
if (val == 0x30) {
|
|
twl = &twl6030_info;
|
|
} else if (val == 0x32) {
|
|
twl = &twl6032_info;
|
|
} else {
|
|
puts("twl6030_init_battery_charging(): unsupported chip type\n");
|
|
return;
|
|
}
|
|
|
|
/* Enable VBAT measurement */
|
|
if (twl->chip_type == chip_TWL6030) {
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_PM, MISC1, VBAT_MEAS);
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_ADC,
|
|
TWL6030_GPADC_CTRL,
|
|
GPADC_CTRL_SCALER_DIV4);
|
|
} else {
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_ADC,
|
|
TWL6032_GPADC_CTRL2,
|
|
GPADC_CTRL2_CH18_SCALER_EN);
|
|
}
|
|
|
|
/* Enable GPADC module */
|
|
ret = twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, TOGGLE1, FGS | GPADCS);
|
|
if (ret) {
|
|
printf("Failed to enable GPADC\n");
|
|
return;
|
|
}
|
|
|
|
battery_volt = twl6030_get_battery_voltage();
|
|
if (battery_volt < 0)
|
|
return;
|
|
|
|
if (battery_volt < 3000)
|
|
printf("Main battery voltage too low!\n");
|
|
|
|
/* Check for the presence of USB charger */
|
|
twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, CONTROLLER_STAT1, &val);
|
|
|
|
/* check for battery presence indirectly via Fuel gauge */
|
|
if ((val & VBUS_DET) && (battery_volt < 3300))
|
|
twl6030_start_usb_charging();
|
|
|
|
return;
|
|
}
|
|
|
|
void twl6030_power_mmc_init(int dev_index)
|
|
{
|
|
u8 value = 0;
|
|
|
|
if (dev_index == 0) {
|
|
/* 3.0V voltage output for VMMC */
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VMMC_CFG_VOLTAGE,
|
|
TWL6030_CFG_VOLTAGE_30);
|
|
|
|
/* Enable P1 output for VMMC */
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VMMC_CFG_STATE,
|
|
TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON);
|
|
} else if (dev_index == 1) {
|
|
twl6030_i2c_read_u8(TWL6030_CHIP_PM, TWL6030_PH_STS_BOOT,
|
|
&value);
|
|
/* BOOT2 indicates 1.8V/2.8V VAUX1 for eMMC */
|
|
if (value & TWL6030_PH_STS_BOOT2) {
|
|
/* 1.8V voltage output for VAUX1 */
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_VOLTAGE,
|
|
TWL6030_CFG_VOLTAGE_18);
|
|
} else {
|
|
/* 2.8V voltage output for VAUX1 */
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_VOLTAGE,
|
|
TWL6030_CFG_VOLTAGE_28);
|
|
}
|
|
|
|
/* Enable P1 output for VAUX */
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_STATE,
|
|
TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON);
|
|
}
|
|
}
|
|
|
|
void twl6030_usb_device_settings()
|
|
{
|
|
u8 value = 0;
|
|
|
|
/* 3.3V voltage output for VUSB */
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VUSB_CFG_VOLTAGE,
|
|
TWL6030_CFG_VOLTAGE_33);
|
|
|
|
/* Enable P1 output for VUSB */
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VUSB_CFG_STATE,
|
|
TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON);
|
|
|
|
/* Select the input supply for VUSB regulator */
|
|
twl6030_i2c_read_u8(TWL6030_CHIP_PM, TWL6030_MISC2, &value);
|
|
value |= TWL6030_MISC2_VUSB_IN_VSYS;
|
|
value &= ~TWL6030_MISC2_VUSB_IN_PMID;
|
|
twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_MISC2, value);
|
|
}
|