6db4831e98
Android 14
653 lines
15 KiB
C
653 lines
15 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2020 MediaTek Inc.
|
|
* Author Wy Chuang<wy.chuang@mediatek.com>
|
|
*/
|
|
|
|
#include <linux/device.h>
|
|
#include <linux/iio/consumer.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/mfd/mt6397/core.h>/* PMIC MFD core header */
|
|
#include <linux/module.h>
|
|
#include <linux/of.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/regmap.h>
|
|
#include <linux/power_supply.h>
|
|
|
|
#include "charger_class.h"
|
|
#include "mt6357-pulse-charger.h"
|
|
|
|
struct mt6357_charger_desc {
|
|
u32 ichg; /* uA */
|
|
u32 cv; /* uV */
|
|
u32 vcdt_hv_thres; /* uV */
|
|
u32 vbat_ov_thres; /* uV */
|
|
};
|
|
|
|
static struct mt6357_charger_desc mt6357_chg_default_desc = {
|
|
.ichg = 500000,
|
|
.cv = 4350000,
|
|
.vcdt_hv_thres = 7000000,
|
|
.vbat_ov_thres = 4450000,
|
|
};
|
|
|
|
struct mt6357_charger {
|
|
const char *charger_dev_name;
|
|
struct charger_properties charger_prop;
|
|
struct charger_device *charger_dev;
|
|
struct mt6357_charger_desc *desc;
|
|
|
|
struct platform_device *pdev;
|
|
struct mt6397_chip *chip;
|
|
struct regmap *regmap;
|
|
|
|
};
|
|
|
|
static const u32 CS_VTH[] = {
|
|
2000000, 1600000, 1500000, 1350000,
|
|
1200000, 1100000, 1000000, 900000,
|
|
800000, 700000, 650000, 550000,
|
|
450000, 300000, 200000, 70000,
|
|
};
|
|
|
|
static const u32 VBAT_CV_VTH[] = {
|
|
3900000, 4000000, 4050000, 4100000,
|
|
4150000, 4200000, 4212500, 4225000,
|
|
4237500, 4250000, 4262500, 4275000,
|
|
4287500, 4300000, 4312500, 4325000,
|
|
4337500, 4350000, 4362500, 4375000,
|
|
4387500, 4400000, 4412500, 4425000,
|
|
4437500, 4450000, 4462500, 4475000,
|
|
4487500, 4500000, 4600000,
|
|
};
|
|
|
|
static const u32 VCDT_HV_VTH[] = {
|
|
3000000, 3900000, 4000000, 4100000,
|
|
4150000, 4200000, 4250000, 4300000,
|
|
4350000, 4400000, 4450000, 6000000,
|
|
6500000, 7000000, 7500000, 8500000,
|
|
9500000, 10500000, 11500000, 12500000,
|
|
14000000,
|
|
};
|
|
|
|
static const u32 VBAT_OV_VTH[] = {
|
|
4200000, 4200000, 4300000, 4400000,
|
|
4450000, 4500000, 4600000, 4700000,
|
|
};
|
|
|
|
static void chr_set_register_value(struct regmap *map,
|
|
unsigned int addr,
|
|
unsigned int mask,
|
|
unsigned int shift,
|
|
unsigned int val)
|
|
{
|
|
regmap_update_bits(map,
|
|
addr,
|
|
mask << shift,
|
|
val << shift);
|
|
}
|
|
|
|
static unsigned int chr_get_register_value(struct regmap *map,
|
|
unsigned int addr,
|
|
unsigned int mask,
|
|
unsigned int shift)
|
|
{
|
|
unsigned int value;
|
|
|
|
regmap_read(map, addr, &value);
|
|
value =
|
|
(value &
|
|
(mask << shift))
|
|
>> shift;
|
|
return value;
|
|
}
|
|
|
|
static unsigned int chg_get_register(struct regmap *map,
|
|
unsigned int addr)
|
|
{
|
|
return chr_get_register_value(map, addr, 0xffff, 0);
|
|
}
|
|
|
|
static u32 charging_value_to_parameter(const u32 *parameter,
|
|
const u32 array_size,
|
|
const u32 val)
|
|
{
|
|
if (val < array_size)
|
|
return parameter[val];
|
|
|
|
pr_notice("Can't find the parameter\n");
|
|
return parameter[0];
|
|
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
pr_notice("no register value matched\n");
|
|
return 0;
|
|
}
|
|
|
|
static u32 bmt_find_closest_level(const u32 *pList, u32 number, u32 level)
|
|
{
|
|
int 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) {
|
|
/* max value in the last element */
|
|
for (i = (number - 1); i >= 0; i--) {
|
|
if (pList[i] <= level) {
|
|
/* pr_notice("zzf_%d<=%d i=%d\n", pList[i], level, i); */
|
|
return pList[i];
|
|
}
|
|
}
|
|
|
|
pr_notice("Can't find closest level\n");
|
|
return pList[0];
|
|
}
|
|
|
|
/* max value in the first element */
|
|
for (i = 0; i < number; i++) {
|
|
if (pList[i] <= level)
|
|
return pList[i];
|
|
}
|
|
|
|
pr_notice("Can't find closest level\n");
|
|
return pList[number - 1];
|
|
}
|
|
|
|
static int mt6357_get_min_ichg(struct charger_device *chg_dev, u32 *uA)
|
|
{
|
|
u32 array_size;
|
|
|
|
array_size = ARRAY_SIZE(CS_VTH);
|
|
*uA = charging_value_to_parameter(CS_VTH, array_size, array_size - 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mt6357_set_cv(struct charger_device *chg_dev, u32 cv)
|
|
{
|
|
int ret = 0;
|
|
u32 array_size;
|
|
u32 set_cv, register_value;
|
|
struct mt6357_charger *info = dev_get_drvdata(&chg_dev->dev);
|
|
|
|
array_size = ARRAY_SIZE(VBAT_CV_VTH);
|
|
set_cv = bmt_find_closest_level(VBAT_CV_VTH, array_size, cv);
|
|
register_value = charging_parameter_to_value(VBAT_CV_VTH,
|
|
array_size, set_cv);
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_VBAT_CV_VTH_ADDR,
|
|
PMIC_RG_VBAT_CV_VTH_MASK,
|
|
PMIC_RG_VBAT_CV_VTH_SHIFT,
|
|
register_value);
|
|
pr_notice("%s: cv = %d mV (0x%x)\n", __func__, set_cv, register_value);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mt6357_kick_wdt(struct charger_device *chg_dev)
|
|
{
|
|
int ret = 0;
|
|
struct mt6357_charger *info = dev_get_drvdata(&chg_dev->dev);
|
|
|
|
pr_notice("%s\n", __func__);
|
|
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_CHRWDT_WR_ADDR,
|
|
PMIC_RG_CHRWDT_WR_MASK,
|
|
PMIC_RG_CHRWDT_WR_SHIFT,
|
|
1);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mt6357_get_ichg(struct charger_device *chg_dev, u32 *ichg)
|
|
{
|
|
int ret = 0;
|
|
u32 array_size;
|
|
u32 val;
|
|
struct mt6357_charger *info = dev_get_drvdata(&chg_dev->dev);
|
|
|
|
array_size = ARRAY_SIZE(CS_VTH);
|
|
val = chr_get_register_value(info->regmap,
|
|
PMIC_RG_CS_VTH_ADDR,
|
|
PMIC_RG_CS_VTH_MASK,
|
|
PMIC_RG_CS_VTH_SHIFT);
|
|
*ichg = charging_value_to_parameter(CS_VTH, array_size, val);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mt6357_set_ichg(struct charger_device *chg_dev, u32 ichg)
|
|
{
|
|
u32 array_size;
|
|
u32 set_ichg, register_value;
|
|
struct mt6357_charger *info = dev_get_drvdata(&chg_dev->dev);
|
|
|
|
array_size = ARRAY_SIZE(CS_VTH);
|
|
set_ichg = bmt_find_closest_level(CS_VTH, array_size, ichg);
|
|
register_value = charging_parameter_to_value(CS_VTH,
|
|
array_size, set_ichg);
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_CS_VTH_ADDR,
|
|
PMIC_RG_CS_VTH_MASK,
|
|
PMIC_RG_CS_VTH_SHIFT,
|
|
register_value);
|
|
pr_notice("%s: 0x%x %d %d\n", __func__, register_value, ichg, set_ichg);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mt6357_is_charging_enabled(struct charger_device *chg_dev, bool *en)
|
|
{
|
|
unsigned short val;
|
|
struct mt6357_charger *info = dev_get_drvdata(&chg_dev->dev);
|
|
|
|
val = chr_get_register_value(info->regmap,
|
|
PMIC_RG_CHR_EN_ADDR,
|
|
PMIC_RG_CHR_EN_MASK,
|
|
PMIC_RG_CHR_EN_SHIFT);
|
|
*en = (val == 1) ? true : false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mt6357_plug_in(struct charger_device *chg_dev)
|
|
{
|
|
int ret = 0;
|
|
struct mt6357_charger *info = dev_get_drvdata(&chg_dev->dev);
|
|
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_ULC_DET_EN_ADDR,
|
|
PMIC_RG_ULC_DET_EN_MASK,
|
|
PMIC_RG_ULC_DET_EN_SHIFT,
|
|
1);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mt6357_enable_charging(struct charger_device *chg_dev, bool en)
|
|
{
|
|
int ret = 0;
|
|
struct mt6357_charger *info = dev_get_drvdata(&chg_dev->dev);
|
|
|
|
pr_notice("[%s] en: %d\n", __func__, en);
|
|
|
|
if (en) {
|
|
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_CSDAC_MODE_ADDR,
|
|
PMIC_RG_CSDAC_MODE_MASK,
|
|
PMIC_RG_CSDAC_MODE_SHIFT,
|
|
1);
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_CS_EN_ADDR,
|
|
PMIC_RG_CS_EN_MASK,
|
|
PMIC_RG_CS_EN_SHIFT,
|
|
1);
|
|
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_ULC_DET_EN_ADDR,
|
|
PMIC_RG_ULC_DET_EN_MASK,
|
|
PMIC_RG_ULC_DET_EN_SHIFT,
|
|
1);
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_HWCV_EN_ADDR,
|
|
PMIC_RG_HWCV_EN_MASK,
|
|
PMIC_RG_HWCV_EN_SHIFT,
|
|
1);
|
|
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_VBAT_CV_EN_ADDR,
|
|
PMIC_RG_VBAT_CV_EN_MASK,
|
|
PMIC_RG_VBAT_CV_EN_SHIFT,
|
|
1);
|
|
/* enable debug flag output */
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_PCHR_FLAG_EN_ADDR,
|
|
PMIC_RG_PCHR_FLAG_EN_MASK,
|
|
PMIC_RG_PCHR_FLAG_EN_SHIFT,
|
|
1);
|
|
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_CSDAC_EN_ADDR,
|
|
PMIC_RG_CSDAC_EN_MASK,
|
|
PMIC_RG_CSDAC_EN_SHIFT,
|
|
1);
|
|
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_CHR_EN_ADDR,
|
|
PMIC_RG_CHR_EN_MASK,
|
|
PMIC_RG_CHR_EN_SHIFT,
|
|
1);
|
|
|
|
/* pmic_enable_interrupt(INT_WATCHDOG, 1, "PMIC"); */
|
|
} else {
|
|
/* chr_set_register_value(info->regmap,PMIC_RG_INT_EN_WATCHDOG, 0);
|
|
* TODO: remove it
|
|
*/
|
|
/* pmic_enable_interrupt(INT_WATCHDOG, 0, "PMIC"); */
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_CHRWDT_EN_ADDR,
|
|
PMIC_RG_CHRWDT_EN_MASK,
|
|
PMIC_RG_CHRWDT_EN_SHIFT,
|
|
0);
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_CHR_EN_ADDR,
|
|
PMIC_RG_CHR_EN_MASK,
|
|
PMIC_RG_CHR_EN_SHIFT,
|
|
0);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static int mt6357_get_cv(struct charger_device *chg_dev, u32 *cv)
|
|
{
|
|
int ret = 0;
|
|
u32 array_size;
|
|
u32 val;
|
|
struct mt6357_charger *info = dev_get_drvdata(&chg_dev->dev);
|
|
|
|
array_size = ARRAY_SIZE(VBAT_CV_VTH);
|
|
val = chr_get_register_value(info->regmap,
|
|
PMIC_RG_VBAT_CV_VTH_ADDR,
|
|
PMIC_RG_VBAT_CV_VTH_MASK,
|
|
PMIC_RG_VBAT_CV_VTH_SHIFT);
|
|
*cv = charging_value_to_parameter(VBAT_CV_VTH, array_size, val);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mt6357_dump_register(struct charger_device *chg_dev)
|
|
{
|
|
int ret = 0;
|
|
u32 i = 0;
|
|
u32 ichg = 0, cv = 0;
|
|
bool chg_en = false;
|
|
struct mt6357_charger *info = dev_get_drvdata(&chg_dev->dev);
|
|
|
|
ret = mt6357_get_ichg(chg_dev, &ichg);
|
|
ret = mt6357_get_cv(chg_dev, &cv);
|
|
ret = mt6357_is_charging_enabled(chg_dev, &chg_en);
|
|
|
|
for (i = MT6357_CHR_TOP_CON0; i <= MT6357_PCHR_ELR1; i += 2)
|
|
pr_notice("[0x%x]=0x%x\t", i, chg_get_register(info->regmap, i));
|
|
pr_notice("\n");
|
|
|
|
for (i = MT6357_CHR_CON0; i <= MT6357_CHR_CON9; i += 2)
|
|
pr_notice("[0x%x]=0x%x\t", i, chg_get_register(info->regmap, i));
|
|
pr_notice("\n");
|
|
|
|
pr_notice("ICHG = %dmA, CV = %dmV, CHG_EN = %d\n",
|
|
ichg / 1000, cv / 1000, chg_en);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static struct charger_ops mt6357_charger_ops = {
|
|
/* normal charging */
|
|
.plug_in = mt6357_plug_in,
|
|
/* .plug_out = mt6357_plug_out, */
|
|
.enable = mt6357_enable_charging,
|
|
.is_enabled = mt6357_is_charging_enabled,
|
|
.get_charging_current = mt6357_get_ichg,
|
|
.set_charging_current = mt6357_set_ichg,
|
|
.get_min_charging_current = mt6357_get_min_ichg,
|
|
.get_constant_voltage = mt6357_get_cv,
|
|
.set_constant_voltage = mt6357_set_cv,
|
|
.kick_wdt = mt6357_kick_wdt,
|
|
.dump_registers = mt6357_dump_register,
|
|
|
|
/* Event */
|
|
//.event = mt6357_do_event,
|
|
};
|
|
|
|
static int mt6357_charger_parse_dt(struct mt6357_charger *info,
|
|
struct device *dev)
|
|
{
|
|
struct device_node *np = dev->of_node;
|
|
struct mt6357_charger_desc *desc = NULL;
|
|
|
|
pr_notice("%s: starts\n", __func__);
|
|
|
|
if (!np) {
|
|
pr_notice("%s: no device node\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
info->desc = &mt6357_chg_default_desc;
|
|
|
|
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
|
|
if (!desc)
|
|
return -ENOMEM;
|
|
|
|
memcpy(desc, &mt6357_chg_default_desc,
|
|
sizeof(struct mt6357_charger_desc));
|
|
|
|
if (of_property_read_string(np, "charger_name",
|
|
&info->charger_dev_name) < 0) {
|
|
pr_notice("%s: no charger name\n", __func__);
|
|
info->charger_dev_name = "primary_chg";
|
|
}
|
|
|
|
if (of_property_read_string(np, "alias_name",
|
|
&info->charger_prop.alias_name) < 0) {
|
|
pr_notice("%s: no alias name\n", __func__);
|
|
info->charger_prop.alias_name = "mt6357";
|
|
}
|
|
|
|
if (of_property_read_u32(np, "ichg", &desc->ichg) < 0)
|
|
pr_notice("%s: no ichg\n", __func__);
|
|
|
|
if (of_property_read_u32(np, "cv", &desc->cv) < 0)
|
|
pr_notice("%s: no cv\n", __func__);
|
|
|
|
if (of_property_read_u32(np, "vcdt_hv_thres", &desc->vcdt_hv_thres) < 0)
|
|
pr_notice("%s: no vcdt_hv_thres\n", __func__);
|
|
|
|
if (of_property_read_u32(np, "vbat_ov_thres", &desc->vbat_ov_thres) < 0)
|
|
pr_notice("%s: no vbat_ov_thres\n", __func__);
|
|
|
|
info->desc = desc;
|
|
|
|
pr_notice("chr name:%s alias:%s\n",
|
|
info->charger_dev_name, info->charger_prop.alias_name);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mt6357_charger_init_setting(struct mt6357_charger *info)
|
|
{
|
|
int ret = 0;
|
|
unsigned short val;
|
|
|
|
val = chr_get_register_value(info->regmap,
|
|
PMIC_RG_VBAT_CV_VTH_ADDR,
|
|
PMIC_RG_VBAT_CV_VTH_MASK,
|
|
PMIC_RG_VBAT_CV_VTH_SHIFT);
|
|
pr_notice("[%s] VBAT_CV_VTH: 0x%x\n", __func__, val);
|
|
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_CHRWDT_TD_ADDR,
|
|
PMIC_RG_CHRWDT_TD_MASK,
|
|
PMIC_RG_CHRWDT_TD_SHIFT,
|
|
3); /* 32s */
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_CHRWDT_EN_ADDR,
|
|
PMIC_RG_CHRWDT_EN_MASK,
|
|
PMIC_RG_CHRWDT_EN_SHIFT,
|
|
1);
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_CHRWDT_WR_ADDR,
|
|
PMIC_RG_CHRWDT_WR_MASK,
|
|
PMIC_RG_CHRWDT_WR_SHIFT,
|
|
1);
|
|
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_VCDT_MODE_ADDR,
|
|
PMIC_RG_VCDT_MODE_MASK,
|
|
PMIC_RG_VCDT_MODE_SHIFT,
|
|
0);
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_VCDT_HV_EN_ADDR,
|
|
PMIC_RG_VCDT_HV_EN_MASK,
|
|
PMIC_RG_VCDT_HV_EN_SHIFT,
|
|
1);
|
|
/* force leave USBDL mode */
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_USBDL_SET_ADDR,
|
|
PMIC_RG_USBDL_SET_MASK,
|
|
PMIC_RG_USBDL_SET_SHIFT,
|
|
0);
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_USBDL_RST_ADDR,
|
|
PMIC_RG_USBDL_RST_MASK,
|
|
PMIC_RG_USBDL_RST_SHIFT,
|
|
1);
|
|
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_BC11_BB_CTRL_ADDR,
|
|
PMIC_RG_BC11_BB_CTRL_MASK,
|
|
PMIC_RG_BC11_BB_CTRL_SHIFT,
|
|
1);
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_BC11_RST_ADDR,
|
|
PMIC_RG_BC11_RST_MASK,
|
|
PMIC_RG_BC11_RST_SHIFT,
|
|
1);
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_VBAT_OV_EN_ADDR,
|
|
PMIC_RG_VBAT_OV_EN_MASK,
|
|
PMIC_RG_VBAT_OV_EN_SHIFT,
|
|
1);
|
|
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_CSDAC_MODE_ADDR,
|
|
PMIC_RG_CSDAC_MODE_MASK,
|
|
PMIC_RG_CSDAC_MODE_SHIFT,
|
|
1); /* CC mode */
|
|
|
|
/* TODO */
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_VBAT_OV_VTH_ADDR,
|
|
PMIC_RG_VBAT_OV_VTH_MASK,
|
|
PMIC_RG_VBAT_OV_VTH_SHIFT,
|
|
4); /* 4450mV */
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_VCDT_HV_VTH_ADDR,
|
|
PMIC_RG_VCDT_HV_VTH_MASK,
|
|
PMIC_RG_VCDT_HV_VTH_SHIFT,
|
|
0xd); /* 7000mV */
|
|
|
|
chr_set_register_value(info->regmap,
|
|
PMIC_RG_ULC_DET_EN_ADDR,
|
|
PMIC_RG_ULC_DET_EN_MASK,
|
|
PMIC_RG_ULC_DET_EN_SHIFT,
|
|
1);
|
|
/* chr_set_register_value(info->regmap, PMIC_RG_LOW_ICH_DB, 1); 16ms */
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mt6357_charger_probe(struct platform_device *pdev)
|
|
{
|
|
int ret = 0;
|
|
struct mt6357_charger *info = NULL;
|
|
|
|
pr_notice("%s: starts\n", __func__);
|
|
|
|
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
|
|
if (!info)
|
|
return -ENOMEM;
|
|
|
|
info->chip = (struct mt6397_chip *)dev_get_drvdata(
|
|
pdev->dev.parent);
|
|
info->regmap = info->chip->regmap;
|
|
|
|
mt6357_charger_parse_dt(info, &pdev->dev);
|
|
platform_set_drvdata(pdev, info);
|
|
info->pdev = pdev;
|
|
|
|
/* Register charger device */
|
|
info->charger_dev = charger_device_register(info->charger_dev_name,
|
|
&pdev->dev, info, &mt6357_charger_ops, &info->charger_prop);
|
|
if (IS_ERR_OR_NULL(info->charger_dev)) {
|
|
ret = PTR_ERR(info->charger_dev);
|
|
goto err_register_charger_dev;
|
|
}
|
|
|
|
info->charger_dev->is_polling_mode = true;
|
|
dev_set_drvdata(&info->charger_dev->dev, info);
|
|
mt6357_charger_init_setting(info);
|
|
|
|
|
|
pr_notice("%s: done\n", __func__);
|
|
|
|
return 0;
|
|
|
|
err_register_charger_dev:
|
|
devm_kfree(&pdev->dev, info);
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
static const struct of_device_id mt6357_charger_of_match[] = {
|
|
{.compatible = "mediatek,mt6357-pulse-charger",},
|
|
{},
|
|
};
|
|
|
|
static int mt6357_charger_remove(struct platform_device *pdev)
|
|
{
|
|
struct mtk_charger_type *info = platform_get_drvdata(pdev);
|
|
|
|
if (info)
|
|
devm_kfree(&pdev->dev, info);
|
|
return 0;
|
|
}
|
|
|
|
MODULE_DEVICE_TABLE(of, mt6357_charger_of_match);
|
|
|
|
static struct platform_driver mt6357_charger_driver = {
|
|
.probe = mt6357_charger_probe,
|
|
.remove = mt6357_charger_remove,
|
|
//.shutdown = mt6357_charger_shutdown,
|
|
.driver = {
|
|
.name = "mt6357-charger",
|
|
.of_match_table = mt6357_charger_of_match,
|
|
},
|
|
};
|
|
|
|
static int __init mt6357_charger_init(void)
|
|
{
|
|
return platform_driver_register(&mt6357_charger_driver);
|
|
}
|
|
module_init(mt6357_charger_init);
|
|
|
|
static void __exit mt6357_charger_exit(void)
|
|
{
|
|
platform_driver_unregister(&mt6357_charger_driver);
|
|
}
|
|
module_exit(mt6357_charger_exit);
|
|
|
|
MODULE_AUTHOR("wy.chuang <wy.chuang@mediatek.com>");
|
|
MODULE_DESCRIPTION("MTK 6357 Charger Driver");
|
|
MODULE_LICENSE("GPL");
|
|
|