huawei-mrd-kernel/drivers/power/supply/mt81xx/mtk_charger_intf.c

211 lines
4.6 KiB
C

/*
* Copyright (C) 2015 MediaTek Inc.
*
* 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.
*
* 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.
*/
#include "mt_charging.h"
#include <linux/platform_device.h>
#include <mt-plat/mt_boot.h>
#include <mt-plat/mt_gpio.h>
#include <mt-plat/mt_reboot.h>
#include <mt-plat/upmu_common.h>
#include <linux/delay.h>
#include <linux/reboot.h>
#include "mtk_charger_intf.h"
#define STATUS_OK 0
/* Necessary functions for integrating with MTK */
/* All of them are copied from original source code of MTK */
#define GETARRAYNUM(array) (ARRAY_SIZE(array))
/* for MT6391 */
static const u32 VCDT_HV_VTH[] = {
BATTERY_VOLT_04_000000_V, BATTERY_VOLT_04_100000_V,
BATTERY_VOLT_04_150000_V, BATTERY_VOLT_04_200000_V,
BATTERY_VOLT_04_250000_V, BATTERY_VOLT_04_300000_V,
BATTERY_VOLT_04_350000_V, BATTERY_VOLT_04_400000_V,
BATTERY_VOLT_04_450000_V, BATTERY_VOLT_04_500000_V,
BATTERY_VOLT_04_550000_V, BATTERY_VOLT_04_600000_V,
BATTERY_VOLT_07_000000_V, BATTERY_VOLT_07_500000_V,
BATTERY_VOLT_08_500000_V, BATTERY_VOLT_10_500000_V};
static u32 charging_parameter_to_value(const u32 *parameter,
const u32 array_size, const u32 val)
{
u32 i;
for (i = 0; i < array_size; i++) {
if (val == *(parameter + i))
return i;
}
/* not find the value */
pr_debug("NO register value match. val=%d\r\n", val);
/* TODO: ASSERT(0); */
return 0;
}
static u32 bmt_find_closest_level(const u32 *pList, u32 number, u32 level)
{
u32 i;
u32 max_value_in_last_element;
if (pList[0] < pList[1])
max_value_in_last_element = true;
else
max_value_in_last_element = false;
if (max_value_in_last_element == true) {
for (i = (number - 1); i != 0; i--) {
/* max value in the last element */
if (pList[i] <= level)
return pList[i];
}
pr_debug("Can't find closest level, small value first \r\n");
return pList[0];
}
for (i = 0; i < number; i++) {
/* max value in the first element */
if (pList[i] <= level)
return pList[i];
}
pr_debug("Can't find closest level, large value first \r\n");
return pList[number - 1];
}
/* The following functions are for chr_control_interface */
int mtk_charger_set_hv_threshold(void *data)
{
u32 status = STATUS_OK;
u32 set_hv_voltage;
u32 array_size;
u16 register_value;
u32 voltage = *(u32 *)(data);
array_size = GETARRAYNUM(VCDT_HV_VTH);
set_hv_voltage =
bmt_find_closest_level(VCDT_HV_VTH, array_size, voltage);
register_value = charging_parameter_to_value(VCDT_HV_VTH, array_size,
set_hv_voltage);
upmu_set_rg_vcdt_hv_vth(register_value);
return status;
}
int mtk_charger_get_hv_status(void *data)
{
u32 status = STATUS_OK;
*(bool *)(data) = upmu_get_rgs_vcdt_hv_det();
return status;
}
int mtk_charger_get_battery_status(void *data)
{
u32 status = STATUS_OK;
/* upmu_set_baton_tdet_en(1); */
upmu_set_rg_baton_en(1);
*(bool *)(data) = upmu_get_rgs_baton_undet();
return status;
}
int mtk_charger_get_charger_det_status(void *data)
{
u32 status = STATUS_OK;
*(bool *)(data) = upmu_get_rgs_chrdet();
return status;
}
int mtk_charger_get_charger_type(void *data)
{
u32 status = STATUS_OK;
*(int *)(data) = hw_charger_type_detection();
return status;
}
int mtk_charger_get_is_pcm_timer_trigger(void *data)
{
u32 status = STATUS_OK;
if (slp_get_wake_reason() == 3)
*(bool *)(data) = true;
else
*(bool *)(data) = false;
pr_debug("slp_get_wake_reason=%d\n",
slp_get_wake_reason());
*(bool *)(data) = false;
return status;
}
int mtk_charger_set_platform_reset(void *data)
{
u32 status = STATUS_OK;
pr_debug("charging_set_platform_reset\n");
if (system_state == SYSTEM_BOOTING)
arch_reset(0, NULL);
else
orderly_reboot(true);
return status;
}
int mtk_charger_get_platform_boot_mode(void *data)
{
u32 status = STATUS_OK;
*(u32 *)(data) = get_boot_mode();
pr_debug("get_boot_mode=%d\n", get_boot_mode());
return status;
}
int (*mtk_charger_intf[CHARGING_CMD_NUMBER])(void *data);
int chr_control_interface(int cmd, void *data)
{
int ret = 0;
if (cmd < CHARGING_CMD_NUMBER) {
if (mtk_charger_intf[cmd] != NULL)
ret = mtk_charger_intf[cmd](data);
else
ret = -ENOTSUPP;
} else
ret = -ENOTSUPP;
if (ret == -ENOTSUPP)
pr_debug("%s: function %d is not support\n",
__func__, cmd);
else if (ret < 0)
pr_debug("%s: function %d failed, ret = %d\n",
__func__, cmd, ret);
return ret;
}