Initial commit
This commit is contained in:
commit
641476a75e
95 changed files with 28756 additions and 0 deletions
266
source/power/max17050.c
Normal file
266
source/power/max17050.c
Normal file
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* Fuel gauge driver for Nintendo Switch's Maxim 17050
|
||||
*
|
||||
* Copyright (C) 2011 Samsung Electronics
|
||||
* MyungJoo Ham <myungjoo.ham@samsung.com>
|
||||
* Copyright (C) 2018 CTCaer
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This driver is based on max17040_battery.c
|
||||
*/
|
||||
|
||||
#include "max17050.h"
|
||||
#include "../soc/i2c.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
/* Status register bits */
|
||||
#define STATUS_POR_BIT (1 << 1)
|
||||
#define STATUS_BST_BIT (1 << 3)
|
||||
#define STATUS_VMN_BIT (1 << 8)
|
||||
#define STATUS_TMN_BIT (1 << 9)
|
||||
#define STATUS_SMN_BIT (1 << 10)
|
||||
#define STATUS_BI_BIT (1 << 11)
|
||||
#define STATUS_VMX_BIT (1 << 12)
|
||||
#define STATUS_TMX_BIT (1 << 13)
|
||||
#define STATUS_SMX_BIT (1 << 14)
|
||||
#define STATUS_BR_BIT (1 << 15)
|
||||
|
||||
#define VFSOC0_LOCK 0x0000
|
||||
#define VFSOC0_UNLOCK 0x0080
|
||||
|
||||
#define MAX17050_VMAX_TOLERANCE 50 /* 50 mV */
|
||||
|
||||
int max17050_get_property(enum MAX17050_reg reg, int *value)
|
||||
{
|
||||
u16 data;
|
||||
|
||||
switch (reg)
|
||||
{
|
||||
case MAX17050_Age: // Age (percent). Based on 100% x (FullCAP Register/DesignCap).
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_Age);
|
||||
*value = data >> 8; /* Show MSB. 1% increments */
|
||||
break;
|
||||
case MAX17050_Cycles: // Cycle count.
|
||||
i2c_recv_buf_small((u8 *)value, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_Cycles);
|
||||
break;
|
||||
case MAX17050_MinVolt: // Voltage max/min
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_MinMaxVolt);
|
||||
*value = (data & 0xff) * 20; /* Voltage MIN. Units of 20mV */
|
||||
break;
|
||||
case MAX17050_MaxVolt: // Voltage max/min
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_MinMaxVolt);
|
||||
*value = (data >> 8) * 20; /* Voltage MAX. Units of LSB = 20mV */
|
||||
break;
|
||||
case MAX17050_V_empty: // Voltage min design.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_V_empty);
|
||||
*value = (data >> 7) * 10; /* Units of LSB = 10mV */
|
||||
break;
|
||||
case MAX17050_VCELL: // Voltage now.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_VCELL);
|
||||
*value = data * 625 / 8 / 1000;
|
||||
break;
|
||||
case MAX17050_AvgVCELL: // Voltage avg.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_AvgVCELL);
|
||||
*value = data * 625 / 8 / 1000;
|
||||
break;
|
||||
case MAX17050_OCVInternal: // Voltage ocv.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_OCVInternal);
|
||||
*value = data * 625 / 8 / 1000;
|
||||
break;
|
||||
case MAX17050_RepSOC: // Capacity %.
|
||||
i2c_recv_buf_small((u8 *)value, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_RepSOC);
|
||||
break;
|
||||
case MAX17050_DesignCap: // Charge full design.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_DesignCap);
|
||||
data = data * 5 / 10;
|
||||
*value = data;
|
||||
break;
|
||||
case MAX17050_FullCAP: // Charge full.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_FullCAP);
|
||||
data = data * 5 / 10;
|
||||
*value = data;
|
||||
break;
|
||||
case MAX17050_RepCap: // Charge now.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_RepCap);
|
||||
data = data * 5 / 10;
|
||||
*value = data;
|
||||
break;
|
||||
case MAX17050_TEMP: // Temp.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_TEMP);
|
||||
*value = (s16)data;
|
||||
*value = *value * 10 / 256;
|
||||
break;
|
||||
case MAX17050_Current: // Current now.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_Current);
|
||||
*value = (s16)data;
|
||||
*value *= 1562500 / MAX17050_DEFAULT_SNS_RESISTOR;
|
||||
break;
|
||||
case MAX17050_AvgCurrent: // Current avg.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_AvgCurrent);
|
||||
*value = (s16)data;
|
||||
*value *= 1562500 / MAX17050_DEFAULT_SNS_RESISTOR;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _max17050_write_verify_reg(u8 reg, u16 value)
|
||||
{
|
||||
int retries = 8;
|
||||
int ret;
|
||||
u16 read_value;
|
||||
|
||||
do
|
||||
{
|
||||
ret = i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, reg, (u8 *)&value, 2);
|
||||
i2c_recv_buf_small((u8 *)&read_value, 2, I2C_1, MAXIM17050_I2C_ADDR, reg);
|
||||
if (read_value != value)
|
||||
{
|
||||
ret = -1;
|
||||
retries--;
|
||||
}
|
||||
} while (retries && read_value != value);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _max17050_override_por(u8 reg, u16 value)
|
||||
{
|
||||
if (value)
|
||||
i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, reg, (u8 *)&value, 2);
|
||||
}
|
||||
|
||||
static void _max17050_load_new_capacity_params()
|
||||
{
|
||||
u16 fullcap, repSoc, dq_acc, dp_acc;
|
||||
|
||||
fullcap = 0x2476; // 4667mAh design capacity.
|
||||
dq_acc = 0x10bc; // From a healthy fuel gauge.
|
||||
dp_acc = 0x5e09; // =||=
|
||||
repSoc = 0x6400; // 100%.
|
||||
|
||||
_max17050_write_verify_reg(MAX17050_RemCap, fullcap);
|
||||
_max17050_write_verify_reg(MAX17050_RepCap, fullcap);
|
||||
|
||||
_max17050_write_verify_reg(MAX17050_dQacc, dq_acc);
|
||||
_max17050_write_verify_reg(MAX17050_dPacc, dp_acc);
|
||||
|
||||
_max17050_write_verify_reg(MAX17050_FullCAP, fullcap);
|
||||
//i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_DesignCap, (u8 *)&fullcap, 2);
|
||||
_max17050_write_verify_reg(MAX17050_FullCAPNom, fullcap);
|
||||
/* Update SOC register with new SOC */
|
||||
i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_RepSOC, (u8 *)&repSoc, 2);
|
||||
}
|
||||
|
||||
static void _max17050_reset_vfsoc0_reg()
|
||||
{
|
||||
u16 lockVal = 0;
|
||||
u16 vfSoc = 0x6440; // >100% for fully charged battery
|
||||
|
||||
lockVal = VFSOC0_UNLOCK;
|
||||
i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_VFSOC0Enable, (u8 *)&lockVal, 2);
|
||||
|
||||
_max17050_write_verify_reg(MAX17050_VFSOC0, vfSoc);
|
||||
|
||||
lockVal = VFSOC0_LOCK;
|
||||
i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_VFSOC0Enable, (u8 *)&lockVal, 2);
|
||||
}
|
||||
|
||||
static void _max17050_update_capacity_regs()
|
||||
{
|
||||
u16 value = 0x2476; // Set to 4667mAh design capacity.
|
||||
_max17050_write_verify_reg(MAX17050_FullCAP, value);
|
||||
_max17050_write_verify_reg(MAX17050_FullCAPNom, value);
|
||||
//i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_DesignCap, config->design_cap, 2);
|
||||
}
|
||||
|
||||
static void _max17050_write_config_regs()
|
||||
{
|
||||
u16 value = 0;
|
||||
|
||||
value = 0x7254;
|
||||
i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_CONFIG, (u8 *)&value, 2);
|
||||
value = 0x2473;
|
||||
i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_LearnCFG, (u8 *)&value, 2);
|
||||
//i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_FilterCFG, (u8 *)&value, 2)
|
||||
//i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_RelaxCFG, (u8 *)&value, 2)
|
||||
//i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_FullSOCThr, (u8 *)&value, 2)
|
||||
}
|
||||
|
||||
/*
|
||||
* Block write all the override values coming from platform data.
|
||||
* This function MUST be called before the POR initialization proceedure
|
||||
* specified by maxim.
|
||||
*/
|
||||
static void _max17050_override_por_values()
|
||||
{
|
||||
u16 dq_acc = 0x10bc; // From a healthy fuel gauge.
|
||||
u16 dp_acc = 0x5e09; // =||=
|
||||
|
||||
_max17050_override_por(MAX17050_dQacc, dq_acc);
|
||||
_max17050_override_por(MAX17050_dPacc, dp_acc);
|
||||
|
||||
//_max17050_override_por(MAX17050_RCOMP0, config->rcomp0); //0x58
|
||||
//_max17050_override_por(MAX17050_TempCo, config->tcompc0); //0x1b22
|
||||
|
||||
//u16 k_empty0 = 0x439;
|
||||
//_max17050_override_por(map, MAX17050_K_empty0, k_empty0); // Unknown cell data
|
||||
}
|
||||
|
||||
static void _max17050_set_por_bit(u16 value)
|
||||
{
|
||||
_max17050_write_verify_reg(MAX17050_STATUS, value);
|
||||
}
|
||||
|
||||
int max17050_fix_configuration()
|
||||
{
|
||||
/* Init phase, set the POR bit */
|
||||
_max17050_set_por_bit(STATUS_POR_BIT);
|
||||
|
||||
/* Override POR values */
|
||||
_max17050_override_por_values();
|
||||
/* After Power up, the MAX17050 requires 500ms in order
|
||||
* to perform signal debouncing and initial SOC reporting
|
||||
*/
|
||||
msleep(500);
|
||||
|
||||
/* Initialize configaration */
|
||||
_max17050_write_config_regs();
|
||||
|
||||
/* update capacity params */
|
||||
_max17050_update_capacity_regs();
|
||||
|
||||
/* delay must be atleast 350mS to allow VFSOC
|
||||
* to be calculated from the new configuration
|
||||
*/
|
||||
msleep(350);
|
||||
|
||||
/* reset vfsoc0 reg */
|
||||
_max17050_reset_vfsoc0_reg();
|
||||
|
||||
/* load new capacity params */
|
||||
_max17050_load_new_capacity_params();
|
||||
|
||||
/* Init complete, Clear the POR bit */
|
||||
//_max17050_set_por_bit(0); // Should we? Or let the switch to reconfigure POR?
|
||||
|
||||
// Sets POR, BI, BR.
|
||||
_max17050_set_por_bit(0x8801);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue