android_kernel_samsung_msm8976/drivers/battery/sec_board-msm.c

273 lines
5.7 KiB
C

/*
* sec_board-8084.c
* Samsung Mobile Battery Driver
*
* Copyright (C) 2012 Samsung Electronics
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/battery/sec_battery.h>
#include <linux/qpnp/pin.h>
#include <linux/qpnp/qpnp-adc.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/krait-regulator.h>
#define SHORT_BATTERY_STANDARD 100
#if defined(CONFIG_EXTCON)
extern int get_jig_state(void);
#endif
int current_cable_type = POWER_SUPPLY_TYPE_BATTERY;
static struct qpnp_vadc_chip *adc_client;
static enum qpnp_vadc_channels temp_channel;
static enum qpnp_vadc_channels chg_temp_channel;
void sec_bat_check_batt_id(struct sec_battery_info *battery)
{
}
static void sec_bat_adc_ap_init(struct platform_device *pdev,
struct sec_battery_info *battery)
{
if (!battery->dev) {
pr_err("%s : can't get battery dev \n", __func__);
} else {
adc_client = qpnp_get_vadc(battery->dev, "sec-battery");
if (IS_ERR(adc_client)) {
int rc;
rc = PTR_ERR(adc_client);
if (rc != -EPROBE_DEFER)
pr_err("%s: Fail to get vadc %d\n", __func__, rc);
}
}
#if defined(CONFIG_PROJECT_GTS28VE) || defined(CONFIG_PROJECT_GTS210VE)
temp_channel = P_MUX4_1_1;
#else
temp_channel = P_MUX2_1_1;
#endif
if (battery->pdata->chg_temp_check)
#if defined(CONFIG_PROJECT_GTS28VE) || defined(CONFIG_PROJECT_GTS210VE)
chg_temp_channel = P_MUX2_1_1;
#else
chg_temp_channel = P_MUX4_1_1;
#endif
}
static int sec_bat_adc_ap_read(struct sec_battery_info *battery, int channel)
{
struct qpnp_vadc_result results;
int data = -1;
int rc;
switch (channel)
{
case SEC_BAT_ADC_CHANNEL_TEMP :
rc = qpnp_vadc_read(adc_client, temp_channel, &results);
if (rc) {
pr_err("%s: Unable to read batt temperature rc=%d, temp_channel=%d\n",
__func__, rc, temp_channel);
return 33000;
}
data = results.adc_code;
break;
case SEC_BAT_ADC_CHANNEL_TEMP_AMBIENT:
data = 33000;
break;
case SEC_BAT_ADC_CHANNEL_BAT_CHECK :
break;
case SEC_BAT_ADC_CHANNEL_CHG_TEMP:
rc = qpnp_vadc_read(adc_client, chg_temp_channel, &results);
if (rc) {
pr_err("%s: Unable to read chg temperature rc=%d\n",
__func__, rc);
return 33000;
}
data = results.adc_code;
break;
default :
break;
}
pr_debug("%s: data(%d)\n", __func__, data);
return data;
}
static void sec_bat_adc_ap_exit(void)
{
}
static void sec_bat_adc_none_init(struct platform_device *pdev,
struct sec_battery_info *battery)
{
}
static int sec_bat_adc_none_read(struct sec_battery_info *battery, int channel)
{
return 0;
}
static void sec_bat_adc_none_exit(void)
{
}
static void sec_bat_adc_ic_init(struct platform_device *pdev,
struct sec_battery_info *battery)
{
}
static int sec_bat_adc_ic_read(struct sec_battery_info *battery, int channel)
{
return 0;
}
static void sec_bat_adc_ic_exit(void)
{
}
static int adc_read_type(struct sec_battery_info *battery, int channel)
{
int adc = 0;
switch (battery->pdata->temp_adc_type)
{
case SEC_BATTERY_ADC_TYPE_NONE :
adc = sec_bat_adc_none_read(battery, channel);
break;
case SEC_BATTERY_ADC_TYPE_AP :
adc = sec_bat_adc_ap_read(battery, channel);
break;
case SEC_BATTERY_ADC_TYPE_IC :
adc = sec_bat_adc_ic_read(battery, channel);
break;
case SEC_BATTERY_ADC_TYPE_NUM :
break;
default :
break;
}
pr_debug("[%s] ADC = %d\n", __func__, adc);
return adc;
}
static void adc_init_type(struct platform_device *pdev,
struct sec_battery_info *battery)
{
switch (battery->pdata->temp_adc_type)
{
case SEC_BATTERY_ADC_TYPE_NONE :
sec_bat_adc_none_init(pdev, battery);
break;
case SEC_BATTERY_ADC_TYPE_AP :
sec_bat_adc_ap_init(pdev, battery);
break;
case SEC_BATTERY_ADC_TYPE_IC :
sec_bat_adc_ic_init(pdev, battery);
break;
case SEC_BATTERY_ADC_TYPE_NUM :
break;
default :
break;
}
}
static void adc_exit_type(struct sec_battery_info *battery)
{
switch (battery->pdata->temp_adc_type)
{
case SEC_BATTERY_ADC_TYPE_NONE :
sec_bat_adc_none_exit();
break;
case SEC_BATTERY_ADC_TYPE_AP :
sec_bat_adc_ap_exit();
break;
case SEC_BATTERY_ADC_TYPE_IC :
sec_bat_adc_ic_exit();
break;
case SEC_BATTERY_ADC_TYPE_NUM :
break;
default :
break;
}
}
int adc_read(struct sec_battery_info *battery, int channel)
{
int adc = 0;
adc = adc_read_type(battery, channel);
pr_debug("[%s]adc = %d\n", __func__, adc);
return adc;
}
void adc_exit(struct sec_battery_info *battery)
{
adc_exit_type(battery);
}
bool sec_bat_check_jig_status(void)
{
return false;
}
/* callback for battery check
* return : bool
* true - battery detected, false battery NOT detected
*/
bool sec_bat_check_callback(struct sec_battery_info *battery)
{
return true;
}
void sec_bat_check_cable_result_callback(struct device *dev,
int cable_type)
{
}
int sec_bat_check_cable_callback(struct sec_battery_info *battery)
{
return POWER_SUPPLY_TYPE_BATTERY;
}
void board_battery_init(struct platform_device *pdev, struct sec_battery_info *battery)
{
adc_init_type(pdev, battery);
}
void board_fuelgauge_init(void *data)
{
}
void cable_initial_check(struct sec_battery_info *battery)
{
union power_supply_propval value;
pr_info("%s : current_cable_type : (%d)\n", __func__, current_cable_type);
if (POWER_SUPPLY_TYPE_BATTERY != current_cable_type) {
value.intval = current_cable_type;
psy_do_property("battery", set,
POWER_SUPPLY_PROP_ONLINE, value);
} else {
psy_do_property(battery->pdata->charger_name, get,
POWER_SUPPLY_PROP_ONLINE, value);
if (value.intval == POWER_SUPPLY_TYPE_WIRELESS) {
value.intval = 1;
psy_do_property("wireless", set,
POWER_SUPPLY_PROP_ONLINE, value);
}
}
}