blob: d883dd033bdc61f4a1ef97d80368ea55918f8767 [file] [log] [blame]
/*
* sm5713-muic-afc.c - afc driver for the SiliconMitus sm5713
*
* Copyright (C) 2017 SiliconMitus
*
*
* 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 driver is based on max77843-muic-afc.c
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/wakelock.h>
#include <linux/delay.h>
#include <linux/power_supply.h>
#include <linux/device.h>
#include <linux/battery/sec_battery.h>
#include <linux/mfd/sm5713.h>
#include <linux/mfd/sm5713-private.h>
/* MUIC header file */
#include <linux/muic/muic.h>
#include <linux/muic/sm5713-muic.h>
#if defined(CONFIG_MUIC_NOTIFIER)
#include <linux/muic/muic_notifier.h>
#endif /* CONFIG_MUIC_NOTIFIER */
#define SM5713_MUIC_REG_AFCTASTATUS 0x2D
#define SM5713_MUIC_REG_REVID1 0x3e
#define SM5713_MUIC_AFC_TA 0x00
#define SM5713_MUIC_QC20 0x01
static struct sm5713_muic_data *afc_init_data;
/* To make AFC work properly on boot */
static int is_charger_ready;
static struct work_struct muic_afc_init_work;
static int afc_prepare_afctxd;
static int afc_prepare_qc20;
static int sm5713_muic_voltage_control(int afctxd, int qc20)
{
struct sm5713_muic_data *muic_data = afc_init_data;
pr_info("[%s:%s] old_afctxd(0x%x), afctxd(0x%x), qc20(0x%x)\n",
MUIC_DEV_NAME, __func__, muic_data->old_afctxd,
afctxd, qc20);
muic_data->attached_dev = ATTACHED_DEV_AFC_CHARGER_PREPARE_MUIC;
muic_notifier_attach_attached_dev(muic_data->attached_dev);
afc_prepare_afctxd = afctxd;
afc_prepare_qc20 = qc20;
cancel_delayed_work(&muic_data->afc_prepare_work);
schedule_delayed_work(&muic_data->afc_prepare_work,
msecs_to_jiffies(100)); /* 100ms */
pr_info("[%s:%s] afc_prepare_work(afctxd=0x%x,qc20=%d) start\n",
MUIC_DEV_NAME, __func__,
afc_prepare_afctxd, afc_prepare_qc20);
return 0;
}
static int muic_disable_afc(int disable)
{
struct sm5713_muic_data *muic_data = afc_init_data;
struct i2c_client *i2c = muic_data->i2c;
int ret = 0;
pr_info("[%s:%s] disable: %d\n", MUIC_DEV_NAME, __func__, disable);
if (disable) { /* AFC disable : 9V(12V) -> 5V */
switch (muic_data->attached_dev) {
case ATTACHED_DEV_AFC_CHARGER_9V_MUIC:
case ATTACHED_DEV_AFC_CHARGER_PREPARE_MUIC:
case ATTACHED_DEV_QC_CHARGER_9V_MUIC:
case ATTACHED_DEV_QC_CHARGER_PREPARE_MUIC:
pr_info("[%s:%s] attached_dev(%d)\n", MUIC_DEV_NAME,
__func__, muic_data->attached_dev);
if (muic_data->attached_dev ==
ATTACHED_DEV_QC_CHARGER_9V_MUIC) {
muic_data->old_afctxd = muic_data->qc20_vbus;
sm5713_muic_voltage_control(SM5713_ENQC20_5V,
SM5713_MUIC_QC20);
} else {
muic_data->old_afctxd = sm5713_i2c_read_byte(
i2c, SM5713_MUIC_REG_AFCTXD);
sm5713_muic_voltage_control(SM5713_MUIC_HV_5V,
SM5713_MUIC_AFC_TA);
}
break;
default:
pr_info("[%s:%s] skip: attached_dev(%d)\n",
MUIC_DEV_NAME, __func__,
muic_data->attached_dev);
break;
}
} else { /* AFC enable : 5V -> 9V(12V) */
#if defined(CONFIG_MUIC_SUPPORT_CCIC)
if (muic_data->ccic_afc_state == SM5713_MUIC_AFC_ABNORMAL) {
pr_info("[%s:%s] ccic abnormal: AFC(QC20) skip\n",
MUIC_DEV_NAME, __func__);
return 0;
}
#endif
switch (muic_data->attached_dev) {
case ATTACHED_DEV_AFC_CHARGER_5V_MUIC:
case ATTACHED_DEV_AFC_CHARGER_PREPARE_MUIC:
case ATTACHED_DEV_QC_CHARGER_5V_MUIC:
case ATTACHED_DEV_QC_CHARGER_PREPARE_MUIC:
pr_info("[%s:%s] attached_dev(%d), old_afctxd(0x%x)\n",
MUIC_DEV_NAME, __func__,
muic_data->attached_dev,
muic_data->old_afctxd);
if (muic_data->attached_dev ==
ATTACHED_DEV_QC_CHARGER_5V_MUIC) {
muic_data->old_afctxd = muic_data->qc20_vbus;
sm5713_muic_voltage_control(SM5713_ENQC20_9V,
SM5713_MUIC_QC20);
} else {
if (muic_data->old_afctxd == 0x00) {
sm5713_muic_voltage_control(
SM5713_MUIC_HV_9V,
SM5713_MUIC_AFC_TA);
} else {
sm5713_muic_voltage_control(
muic_data->old_afctxd,
SM5713_MUIC_AFC_TA);
}
}
break;
default:
pr_info("[%s:%s] skip: attached_dev(%d)\n",
MUIC_DEV_NAME, __func__,
muic_data->attached_dev);
break;
}
}
return ret;
}
int muic_request_disable_afc_state(void)
{
pr_info("[%s:%s]\n", MUIC_DEV_NAME, __func__);
muic_disable_afc(1); /* 9V(12V) -> 5V */
return 0;
}
EXPORT_SYMBOL(muic_request_disable_afc_state);
int muic_check_fled_state(bool enable, u8 mode)
{
struct sm5713_muic_data *muic_data = afc_init_data;
pr_info("[%s:%s] enable(%d), mode(%d)\n", MUIC_DEV_NAME, __func__,
enable, mode);
if (mode == FLED_MODE_TORCH) { /* torch */
cancel_delayed_work(&muic_data->afc_torch_work);
pr_info("[%s:%s] afc_torch_work cancel\n",
MUIC_DEV_NAME, __func__);
muic_data->fled_torch_enable = enable;
} else if (mode == FLED_MODE_FLASH) { /* flash */
muic_data->fled_flash_enable = enable;
}
pr_info("[%s:%s] fled_torch_enable(%d), fled_flash_enable(%d)\n",
MUIC_DEV_NAME, __func__, muic_data->fled_torch_enable,
muic_data->fled_flash_enable);
if ((muic_data->fled_torch_enable == false) &&
(muic_data->fled_flash_enable == false)) {
if (muic_data->hv_voltage == 5) {
pr_info("[%s:%s] skip high voltage setting\n",
MUIC_DEV_NAME, __func__);
return 0;
}
if ((mode == FLED_MODE_TORCH) && (enable == false)) {
cancel_delayed_work(&muic_data->afc_torch_work);
schedule_delayed_work(&muic_data->afc_torch_work,
msecs_to_jiffies(5000));
pr_info("[%s:%s] afc_torch_work start(5sec)\n",
MUIC_DEV_NAME, __func__);
} else {
muic_disable_afc(0); /* 5V -> 9V(12V) */
}
}
return 0;
}
EXPORT_SYMBOL(muic_check_fled_state);
int sm5713_set_afc_ctrl_reg(struct sm5713_muic_data *muic_data, int shift,
bool on)
{
struct i2c_client *i2c = muic_data->i2c;
u8 reg_val = 0;
int ret = 0;
pr_info("[%s:%s] Register[%d], set [%d]\n", MUIC_DEV_NAME, __func__,
shift, on);
ret = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_AFCCNTL);
if (ret < 0)
pr_err("[%s:%s](%d)\n", MUIC_DEV_NAME, __func__, ret);
if (on)
reg_val = ret | (0x1 << shift);
else
reg_val = ret & ~(0x1 << shift);
if (reg_val ^ ret) {
pr_debug("[%s:%s] reg_val(0x%x) != AFC_CTRL reg(0x%x), update reg\n",
MUIC_DEV_NAME, __func__, reg_val, ret);
ret = sm5713_i2c_write_byte(i2c, SM5713_MUIC_REG_AFCCNTL,
reg_val);
if (ret < 0)
pr_err("[%s:%s] err write AFC_CTRL(%d)\n",
MUIC_DEV_NAME, __func__, ret);
} else {
pr_debug("[%s:%s] (0x%x), just return\n",
MUIC_DEV_NAME, __func__, ret);
return 0;
}
ret = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_AFCCNTL);
if (ret < 0)
pr_err("[%s:%s] err read AFC_CTRL(%d)\n",
MUIC_DEV_NAME, __func__, ret);
else
pr_debug("[%s:%s] AFC_CTRL reg after change(0x%x)\n",
MUIC_DEV_NAME, __func__, ret);
return ret;
}
static int muic_get_vbus_value(void)
{
struct sm5713_muic_data *muic_data = afc_init_data;
struct i2c_client *i2c = muic_data->i2c;
int vbus_voltage = 0, voltage1 = 0, voltage2 = 0;
int irqvbus = 0;
int intmask2 = 0;
int retry = 0;
pr_info("[%s:%s] attached_dev(%d)\n", MUIC_DEV_NAME, __func__,
muic_data->attached_dev);
intmask2 = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_INTMASK2);
intmask2 = intmask2 | 0x04;
sm5713_i2c_write_byte(i2c, SM5713_MUIC_REG_INTMASK2, intmask2);
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_VBUS_READ, 1);
for (retry = 0; retry < 10 ; retry++) {
msleep(20);
irqvbus = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_INT2);
if (irqvbus & INT2_VBUS_UPDATE_MASK) {
pr_info("[%s:%s] VBUS update Success(%d), retry: %d)\n",
MUIC_DEV_NAME, __func__, irqvbus, retry);
break;
}
pr_info("[%s:%s] VBUS update Fail(%d), retry: %d)\n",
MUIC_DEV_NAME, __func__, irqvbus, retry);
}
intmask2 = intmask2 & 0xFB;
sm5713_i2c_write_byte(i2c, SM5713_MUIC_REG_INTMASK2, intmask2);
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_VBUS_READ, 0);
if (retry >= 10) {
pr_info("[%s:%s] VBUS update Failed(%d)\n",
MUIC_DEV_NAME, __func__, retry);
return 0;
}
voltage1 = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_VBUS_VOLTAGE1);
voltage2 = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_VBUS_VOLTAGE2);
vbus_voltage = voltage1*1000 + (voltage2*3900)/1000;
pr_info("[%s:%s] voltage1=[0x%02x], voltage2=[0x%02x], vbus_voltage=%d mV\n",
MUIC_DEV_NAME, __func__, voltage1, voltage2, vbus_voltage);
return vbus_voltage;
}
static void muic_afc_prepare_work(struct work_struct *work)
{
struct sm5713_muic_data *muic_data = afc_init_data;
struct i2c_client *i2c = muic_data->i2c;
union power_supply_propval value;
int ret = 0, reg_val = 0;
int retry = 0;
int intmask2 = 0;
int irqafc = 0;
int afcstatus = 0, afc_dpreset = 0;
int vbus_voltage = 0;
int vbus_txd_voltage = 0;
int voltage_min = 0, voltage_max = 0;
pr_info("[%s:%s]\n", MUIC_DEV_NAME, __func__);
for (retry = 0; retry < 10; retry++) {
psy_do_property("sm5713-charger", get,
POWER_SUPPLY_PROP_CURRENT_MAX, value);
if (value.intval <= 500) {
pr_info("[%s:%s]PREPARE Success(%d), retry(%d)\n",
MUIC_DEV_NAME, __func__,
value.intval, retry);
break;
}
if (value.intval == 1650) {
muic_data->attached_dev =
ATTACHED_DEV_AFC_CHARGER_PREPARE_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
}
pr_info("[%s:%s]PREPARE fail(%d), retry(%d)\n",
MUIC_DEV_NAME, __func__, value.intval, retry);
msleep(50);
}
mutex_lock(&muic_data->afc_mutex);
/* QC20 */
if (afc_prepare_qc20 == SM5713_MUIC_QC20) {
pr_info("[%s:%s]QC20: afctxd(0x%x)\n", MUIC_DEV_NAME, __func__,
afc_prepare_afctxd);
ret = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_AFCCNTL);
reg_val = (ret & 0x3F) | (afc_prepare_afctxd<<6);
sm5713_i2c_write_byte(i2c, SM5713_MUIC_REG_AFCCNTL, reg_val);
pr_info("[%s:%s] read REG_AFCCNTL=0x%x , write REG_AFCCNTL=0x%x , qc20_vbus=%d\n",
MUIC_DEV_NAME, __func__, ret, reg_val,
afc_prepare_afctxd);
muic_data->qc20_vbus = afc_prepare_afctxd;
if (muic_data->qc20_vbus == SM5713_ENQC20_5V) {
muic_data->attached_dev =
ATTACHED_DEV_QC_CHARGER_5V_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
} else if (muic_data->qc20_vbus == SM5713_ENQC20_9V) {
muic_data->attached_dev =
ATTACHED_DEV_QC_CHARGER_9V_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
} else {
muic_data->attached_dev =
ATTACHED_DEV_QC_CHARGER_9V_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
}
} else { /* AFC TA */
pr_info("[%s:%s] AFC: afctxd(0x%x), old_afctxd(0x%x)\n",
MUIC_DEV_NAME, __func__, afc_prepare_afctxd,
muic_data->old_afctxd);
sm5713_i2c_write_byte(i2c, SM5713_MUIC_REG_AFCTXD,
afc_prepare_afctxd);
/* AFC(INT2) mask */
intmask2 = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_INTMASK2);
intmask2 = intmask2 | 0x3F;
sm5713_i2c_write_byte(i2c, SM5713_MUIC_REG_INTMASK2, intmask2);
/* ENAFC set '1' */
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_ENAFC, 1);
afc_dpreset = 0;
for (retry = 0; retry < 30 ; retry++) {
msleep(50);
irqafc = sm5713_i2c_read_byte(i2c,
SM5713_MUIC_REG_INT2);
if (irqafc & INT2_AFC_ACCEPTED_MASK) {
pr_info("[%s:%s] AFC_ACCEPTED Success(0x%x), retry(%d)\n",
MUIC_DEV_NAME, __func__,
irqafc, retry);
break;
}
if ((irqafc & INT2_AFC_TA_ATTACHED_MASK) &&
(afc_dpreset == 1)) {
pr_info("[%s:%s] AFC_TA_ATTACHED(0x%x), retry(%d)\n",
MUIC_DEV_NAME, __func__,
irqafc, retry);
break;
}
if (irqafc & INT2_AFC_ERROR_MASK) {
/* ENAFC set '0' */
sm5713_set_afc_ctrl_reg(muic_data,
AFCCTRL_ENAFC, 0);
/* read AFC_STATUS */
afcstatus = sm5713_i2c_read_byte(i2c,
SM5713_MUIC_REG_AFCSTATUS);
pr_info("[%s:%s] AFC_ERROR(0x%x), afcstatus(0x%x), retry(%d)\n",
MUIC_DEV_NAME, __func__, irqafc,
afcstatus, retry);
/* DP_RESET '1' */
sm5713_set_afc_ctrl_reg(muic_data,
AFCCTRL_DP_RESET, 1);
afc_dpreset = 1;
} else {
pr_info("[%s:%s] AFC_ACCEPTED Fail(0x%x), retry(%d)\n",
MUIC_DEV_NAME, __func__,
irqafc, retry);
}
}
/* ENAFC set '0' */
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_ENAFC, 0);
/* AFC(INT2) unmask */
intmask2 = intmask2 & 0xC0;
sm5713_i2c_write_byte(i2c, SM5713_MUIC_REG_INTMASK2, intmask2);
vbus_voltage = muic_get_vbus_value();
vbus_txd_voltage = sm5713_i2c_read_byte(i2c,
SM5713_MUIC_REG_AFCTXD);
pr_info("[%s:%s] AFC_TXD [0x%02x]\n", MUIC_DEV_NAME, __func__,
vbus_txd_voltage);
vbus_txd_voltage = 5000 + ((vbus_txd_voltage&0xF0)>>4)*1000;
pr_info("[%s:%s] vbus_voltage:%d mV , AFC_TXD_VOLTAGE:%d mV\n",
MUIC_DEV_NAME, __func__, vbus_voltage,
vbus_txd_voltage);
voltage_min = vbus_txd_voltage - 2000; /* - 2000mV */
voltage_max = vbus_txd_voltage + 1000; /* + 1000mV */
if ((voltage_min <= vbus_voltage) &&
(vbus_voltage <= voltage_max)) { /* AFC DONE */
if (vbus_txd_voltage == 12000) { /* 12V */
muic_data->attached_dev =
ATTACHED_DEV_AFC_CHARGER_9V_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
pr_info("[%s:%s] AFC 12V (%d)\n",
MUIC_DEV_NAME, __func__,
muic_data->attached_dev);
} else if (vbus_txd_voltage == 9000) { /* 9V */
muic_data->attached_dev =
ATTACHED_DEV_AFC_CHARGER_9V_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
pr_info("[%s:%s] AFC 9V (%d)\n",
MUIC_DEV_NAME, __func__,
muic_data->attached_dev);
} else { /* 5V */
muic_data->attached_dev =
ATTACHED_DEV_AFC_CHARGER_5V_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
pr_info("[%s:%s] AFC 5V (%d)\n",
MUIC_DEV_NAME, __func__,
muic_data->attached_dev);
}
} else {
muic_data->attached_dev =
ATTACHED_DEV_AFC_CHARGER_5V_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
pr_info("[%s:%s] AFC 5V (%d)\n",
MUIC_DEV_NAME, __func__,
muic_data->attached_dev);
}
}
afc_prepare_qc20 = 0;
mutex_unlock(&muic_data->afc_mutex);
}
int sm5713_afc_ta_attach(struct sm5713_muic_data *muic_data)
{
struct i2c_client *i2c = muic_data->i2c;
union power_supply_propval value;
int ret = 0, afctxd = 0;
int retry = 0;
if (!is_charger_ready) {
pr_info("[%s:%s] charger is not ready, return\n",
MUIC_DEV_NAME, __func__);
return ret;
}
if (muic_data->pdata->afc_disable) {
pr_info("[%s:%s] AFC is disabled by USER, return\n",
MUIC_DEV_NAME, __func__);
muic_data->attached_dev = ATTACHED_DEV_AFC_CHARGER_DISABLED_MUIC;
muic_notifier_attach_attached_dev(muic_data->attached_dev);
return ret;
}
pr_info("[%s:%s] AFC_TA_ATTACHED\n", MUIC_DEV_NAME, __func__);
/* read VBUS VALID */
ret = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_REVID1);
if (ret < 0)
pr_err("[%s:%s] err read VBUS\n", MUIC_DEV_NAME, __func__);
pr_info("[%s:%s] VBUS[0x%02x]\n", MUIC_DEV_NAME, __func__, ret);
if ((ret&0x01) == 0x00) {
pr_info("[%s:%s] VBUS NOT VALID [0x%02x] just return\n",
MUIC_DEV_NAME, __func__, ret);
return 0;
}
/* read clear : AFC_STATUS */
ret = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_AFCSTATUS);
if (ret < 0)
pr_err("[%s:%s] err read AFC_STATUS\n",
MUIC_DEV_NAME, __func__);
pr_info("[%s:%s] AFC_STATUS [0x%02x]\n", MUIC_DEV_NAME, __func__, ret);
if ((muic_data->fled_torch_enable == 1) ||
(muic_data->fled_flash_enable == 1)) {
pr_info("[%s:%s] FLASH or Torch On, Skip AFC\n",
MUIC_DEV_NAME, __func__);
muic_data->attached_dev = ATTACHED_DEV_AFC_CHARGER_5V_MUIC;
muic_notifier_attach_attached_dev(muic_data->attached_dev);
return 0;
}
#if defined(CONFIG_MUIC_SUPPORT_CCIC)
if (muic_data->ccic_afc_state == SM5713_MUIC_AFC_ABNORMAL) {
muic_data->ccic_afc_state_count = 0;
cancel_delayed_work(&muic_data->ccic_afc_work);
cancel_delayed_work(&muic_data->afc_retry_work);
schedule_delayed_work(&muic_data->ccic_afc_work,
msecs_to_jiffies(200));
pr_info("[%s:%s] CCIC Abnormal State, ccic_afc_work(%d) start\n",
MUIC_DEV_NAME, __func__,
muic_data->ccic_afc_state_count);
return 0;
}
#endif
muic_data->attached_dev = ATTACHED_DEV_AFC_CHARGER_PREPARE_MUIC;
muic_notifier_attach_attached_dev(muic_data->attached_dev);
for (retry = 0; retry < 20; retry++) {
msleep(50);
psy_do_property("sm5713-charger", get,
POWER_SUPPLY_PROP_CURRENT_MAX, value);
if (value.intval <= 500) {
pr_info("[%s:%s]PREPARE Success(%d mA)\n",
MUIC_DEV_NAME, __func__, value.intval);
break;
}
pr_info("[%s:%s]PREPARE fail(%d mA)\n", MUIC_DEV_NAME, __func__,
value.intval);
}
cancel_delayed_work(&muic_data->afc_retry_work);
schedule_delayed_work(&muic_data->afc_retry_work,
msecs_to_jiffies(5000)); /* 5sec */
pr_info("[%s:%s] afc_retry_work(ATTACH) start\n",
MUIC_DEV_NAME, __func__);
/* voltage(9.0V) + current(1.65A) setting : 0x46 */
/* voltage(12.0V) + current(2.1A) setting : 0x79 */
afctxd = AFC_TXBYTE_9V_1_65A;
ret = sm5713_i2c_write_byte(i2c, SM5713_MUIC_REG_AFCTXD, afctxd);
if (ret < 0)
pr_err("[%s:%s] err write AFC_TXD(%d)\n",
MUIC_DEV_NAME, __func__, ret);
pr_info("[%s:%s] AFC_TXD [0x%02x]\n", MUIC_DEV_NAME, __func__, afctxd);
/* ENAFC set '1' */
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_ENAFC, 1);
pr_info("[%s:%s] AFCCTRL_ENAFC 1\n", MUIC_DEV_NAME, __func__);
muic_data->afc_retry_count = 0;
muic_data->afc_vbus_retry_count = 0;
return 0;
}
int sm5713_afc_ta_accept(struct sm5713_muic_data *muic_data)
{
struct i2c_client *i2c = muic_data->i2c;
int dev1 = 0;
pr_info("[%s:%s] AFC_ACCEPTED\n", MUIC_DEV_NAME, __func__);
/* ENAFC set '0' */
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_ENAFC, 0);
cancel_delayed_work(&muic_data->afc_retry_work);
pr_info("[%s:%s] afc_retry_work(ACCEPTED) cancel\n",
MUIC_DEV_NAME, __func__);
if ((muic_data->fled_torch_enable == 1) ||
(muic_data->fled_flash_enable == 1)) {
pr_info("[%s:%s] FLASH or Torch On, AFC_ACCEPTED VBUS(9V->5V)\n",
MUIC_DEV_NAME, __func__);
muic_disable_afc(1); /* 9V(12V) -> 5V */
return 0;
}
dev1 = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_DEVICETYPE1);
pr_info("[%s:%s] dev1 [0x%02x]\n", MUIC_DEV_NAME, __func__, dev1);
if (dev1 & DEV_TYPE1_AFC_TA) {
/* VBUS_READ */
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_VBUS_READ, 1);
pr_info("[%s:%s] VBUS READ start(AFC)\n", MUIC_DEV_NAME,
__func__);
if (muic_data->attached_dev !=
ATTACHED_DEV_AFC_CHARGER_PREPARE_MUIC) {
muic_data->attached_dev =
ATTACHED_DEV_AFC_CHARGER_PREPARE_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
}
muic_data->afc_vbus_retry_count = 0;
} else {
muic_data->attached_dev = ATTACHED_DEV_AFC_CHARGER_5V_MUIC;
muic_notifier_attach_attached_dev(muic_data->attached_dev);
pr_info("[%s:%s] attached_dev(%d)\n", MUIC_DEV_NAME, __func__,
muic_data->attached_dev);
}
return 0;
}
int sm5713_afc_vbus_update(struct sm5713_muic_data *muic_data)
{
struct i2c_client *i2c = muic_data->i2c;
int vbus_txd_voltage = 0;
int vbus_voltage = 0, voltage1 = 0, voltage2 = 0;
int voltage_min = 0, voltage_max = 0;
int dev1 = 0;
int ret = 0, reg_val = 0;
pr_info("[%s:%s] AFC_VBUS_UPDATE\n", MUIC_DEV_NAME, __func__);
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_VBUS_READ, 0);
if (muic_data->attached_dev == ATTACHED_DEV_NONE_MUIC) {
pr_info("[%s:%s] Device type is None\n",
MUIC_DEV_NAME, __func__);
return 0;
}
voltage1 = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_VBUS_VOLTAGE1);
voltage2 = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_VBUS_VOLTAGE2);
vbus_voltage = voltage1*1000 + (voltage2*3900)/1000;
pr_info("[%s:%s] voltage1=[0x%02x], voltage2=[0x%02x], vbus_voltage=%d mV\n",
MUIC_DEV_NAME, __func__, voltage1, voltage2, vbus_voltage);
dev1 = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_DEVICETYPE1);
pr_info("[%s:%s] DEVICE_TYPE1 [0x%02x]\n", MUIC_DEV_NAME, __func__,
dev1);
if (dev1 & DEV_TYPE1_QC20_TA) { /* QC20_TA vbus update */
if (muic_data->qc20_vbus == SM5713_ENQC20_12V) {
voltage_min = 10000; /* - 10000mV */
voltage_max = 13000; /* + 13000mV */
} else if (muic_data->qc20_vbus == SM5713_ENQC20_9V) {
voltage_min = 7000; /* - 7000mV */
voltage_max = 10000; /* + 10000mV */
}
pr_info("[%s:%s] QC20 vbus_voltage:%d mV (%d)\n",
MUIC_DEV_NAME, __func__,
vbus_voltage, muic_data->qc20_vbus);
if ((voltage_min <= vbus_voltage) &&
(vbus_voltage <= voltage_max)) { /* AFC DONE */
if (muic_data->qc20_vbus == SM5713_ENQC20_12V) {
muic_data->attached_dev =
ATTACHED_DEV_QC_CHARGER_9V_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
pr_info("[%s:%s] QC20 12V (%d)\n",
MUIC_DEV_NAME, __func__,
muic_data->attached_dev);
} else if (muic_data->qc20_vbus == SM5713_ENQC20_9V) {
muic_data->attached_dev =
ATTACHED_DEV_QC_CHARGER_9V_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
pr_info("[%s:%s] QC20 9V (%d)\n",
MUIC_DEV_NAME, __func__,
muic_data->attached_dev);
} else if (muic_data->qc20_vbus == SM5713_ENQC20_5V) {
muic_data->attached_dev =
ATTACHED_DEV_QC_CHARGER_5V_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
pr_info("[%s:%s] QC20 5V (%d)\n",
MUIC_DEV_NAME, __func__,
muic_data->attached_dev);
}
} else { /* vbus fail */
if (muic_data->afc_vbus_retry_count < 3) {
msleep(100);
muic_data->afc_vbus_retry_count++;
/* VBUS_READ */
sm5713_set_afc_ctrl_reg(muic_data,
AFCCTRL_VBUS_READ, 1);
pr_info("[%s:%s] [QC20] VBUS READ retry = %d\n",
MUIC_DEV_NAME, __func__,
muic_data->afc_vbus_retry_count);
} else {
msleep(100);
muic_data->qc20_vbus = SM5713_ENQC20_9V;
ret = sm5713_i2c_read_byte(i2c,
SM5713_MUIC_REG_AFCCNTL);
/* QC20 9V */
reg_val = (ret & 0x3F) |
(muic_data->qc20_vbus<<6);
sm5713_i2c_write_byte(i2c,
SM5713_MUIC_REG_AFCCNTL,
reg_val);
pr_info("[%s:%s] read REG_AFCCNTL=0x%x, write REG_AFCCNTL=0x%x, qc20_vbus=%d\n",
MUIC_DEV_NAME, __func__, ret,
reg_val, muic_data->qc20_vbus);
if (muic_data->qc20_vbus == SM5713_ENQC20_12V) {
/* VBUS_READ */
sm5713_set_afc_ctrl_reg(muic_data,
AFCCTRL_VBUS_READ, 1);
pr_info("[%s:%s] VBUS READ start(QC20-9V)\n",
MUIC_DEV_NAME,
__func__);
muic_data->afc_vbus_retry_count = 0;
} else {
muic_data->attached_dev =
ATTACHED_DEV_QC_CHARGER_5V_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
}
}
}
} else if (dev1 & DEV_TYPE1_AFC_TA) { /* AFC vbus update */
vbus_txd_voltage = sm5713_i2c_read_byte(i2c,
SM5713_MUIC_REG_AFCTXD);
pr_info("[%s:%s] AFC_TXD [0x%02x]\n", MUIC_DEV_NAME, __func__,
vbus_txd_voltage);
vbus_txd_voltage = 5000 + ((vbus_txd_voltage&0xF0)>>4)*1000;
pr_info("[%s:%s] vbus_voltage:%d mV , AFC_TXD_VOLTAGE:%d mV\n",
MUIC_DEV_NAME, __func__,
vbus_voltage, vbus_txd_voltage);
voltage_min = vbus_txd_voltage - 2000; /* - 2000mV */
voltage_max = vbus_txd_voltage + 1000; /* + 1000mV */
if ((voltage_min <= vbus_voltage) &&
(vbus_voltage <= voltage_max)) { /* AFC DONE */
muic_data->afc_vbus_retry_count = 0;
pr_info("[%s:%s] AFC done\n", MUIC_DEV_NAME, __func__);
if (vbus_txd_voltage == 12000) { /* 12V */
muic_data->attached_dev =
ATTACHED_DEV_AFC_CHARGER_12V_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
pr_info("[%s:%s] AFC 12V (%d)\n",
MUIC_DEV_NAME, __func__,
muic_data->attached_dev);
} else if (vbus_txd_voltage == 9000) { /* 9V */
muic_data->attached_dev =
ATTACHED_DEV_AFC_CHARGER_9V_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
pr_info("[%s:%s] AFC 9V (%d)\n",
MUIC_DEV_NAME, __func__,
muic_data->attached_dev);
} else { /* 5V */
muic_data->attached_dev =
ATTACHED_DEV_AFC_CHARGER_5V_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
pr_info("[%s:%s] AFC 5V (%d)\n",
MUIC_DEV_NAME, __func__,
muic_data->attached_dev);
}
} else {
/* VBUS_READ */
if (muic_data->afc_vbus_retry_count < 3) {
msleep(100);
muic_data->afc_vbus_retry_count++;
/* VBUS_READ */
sm5713_set_afc_ctrl_reg(muic_data,
AFCCTRL_VBUS_READ, 1);
pr_info("[%s:%s] VBUS READ retry = %d\n",
MUIC_DEV_NAME, __func__,
muic_data->afc_vbus_retry_count);
} else {
muic_data->attached_dev =
ATTACHED_DEV_AFC_CHARGER_5V_MUIC;
muic_notifier_attach_attached_dev(
muic_data->attached_dev);
muic_data->afc_vbus_retry_count = 0;
}
}
} /* if (dev1 & DEV_TYPE1_QC20_TA){ // QC20_TA vbus update */
return 0;
}
int sm5713_afc_multi_byte(struct sm5713_muic_data *muic_data)
{
struct i2c_client *i2c = muic_data->i2c;
int multi_byte[15] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int i = 0;
int ret = 0;
int voltage_find = 0;
pr_info("[%s:%s] AFC_MULTI_BYTE\n", MUIC_DEV_NAME, __func__);
/* ENAFC set '0' */
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_ENAFC, 0);
/* read AFC_RXD1 ~ RXD15 */
voltage_find = 0;
for (i = 0 ; i < 15 ; i++) {
multi_byte[i] = sm5713_i2c_read_byte(i2c,
SM5713_MUIC_REG_AFC_RXD1 + i);
if (multi_byte[i] < 0) {
pr_err("[%s:%s] err read AFC_RXD%d %d\n",
MUIC_DEV_NAME, __func__, i+1, multi_byte[i]);
}
pr_info("[%s:%s] AFC_RXD%d [0x%02x]\n", MUIC_DEV_NAME, __func__,
i+1, multi_byte[i]);
if (multi_byte[i] == 0x00)
break;
if (i >= 1) /* voltate find */
if (((multi_byte[i]&0xF0)>>4) >=
((multi_byte[voltage_find]&0xF0)>>4))
voltage_find = i;
}
pr_info("[%s:%s] AFC_RXD%d multi_byte[%d]=0x%02x\n",
MUIC_DEV_NAME, __func__,
voltage_find+1, voltage_find, multi_byte[voltage_find]);
ret = sm5713_i2c_write_byte(i2c, SM5713_MUIC_REG_AFCTXD,
multi_byte[voltage_find]);
if (ret < 0)
pr_err("[%s:%s] err write AFC_TXD(%d)\n",
MUIC_DEV_NAME, __func__, ret);
/* ENAFC set '1' */
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_ENAFC, 1);
pr_info("[%s:%s] AFCCTRL_ENAFC 1\n", MUIC_DEV_NAME, __func__);
return 0;
}
int sm5713_afc_error(struct sm5713_muic_data *muic_data)
{
struct i2c_client *i2c = muic_data->i2c;
int value = 0;
int dev1 = 0;
int ret = 0, reg_val = 0;
pr_info("[%s:%s] AFC_ERROR (%d)\n", MUIC_DEV_NAME, __func__,
muic_data->afc_retry_count);
/* ENAFC set '0' */
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_ENAFC, 0);
/* read AFC_STATUS */
value = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_AFCSTATUS);
if (value < 0)
pr_err("[%s:%s] err read AFC_STATUS %d\n",
MUIC_DEV_NAME, __func__, value);
pr_info("[%s:%s] REG_AFCSTATUS [0x%02x]\n", MUIC_DEV_NAME, __func__,
value);
dev1 = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_DEVICETYPE1);
if (muic_data->afc_retry_count < 5) {
pr_info("[%s:%s] DEVICE_TYPE1 [0x%02x]\n",
MUIC_DEV_NAME, __func__, dev1);
if ((dev1 & DEV_TYPE1_QC20_TA) &&
(muic_data->afc_retry_count >= 2)) {
/* QC20_9V_TA */
muic_data->qc20_vbus = SM5713_ENQC20_9V;
ret = sm5713_i2c_read_byte(i2c,
SM5713_MUIC_REG_AFCCNTL);
reg_val = (ret & 0x3F) | (SM5713_ENQC20_9V<<6);
sm5713_i2c_write_byte(i2c, SM5713_MUIC_REG_AFCCNTL,
reg_val);
pr_info("[%s:%s] read REG_AFCCNTL=0x%x , write REG_AFCCNTL=0x%x , qc20_vbus=%d\n",
MUIC_DEV_NAME, __func__, ret, reg_val,
muic_data->qc20_vbus);
/* VBUS_READ */
sm5713_set_afc_ctrl_reg(muic_data,
AFCCTRL_VBUS_READ, 1);
pr_info("[%s:%s] VBUS READ start(QC20-9V)\n",
MUIC_DEV_NAME, __func__);
msleep(50); /* 50ms delay */
} else {
msleep(100); /* 100ms delay */
/* ENAFC set '1' */
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_ENAFC, 1);
muic_data->afc_retry_count++;
pr_info("[%s:%s] re-start AFC (afc_retry_count=%d)\n",
MUIC_DEV_NAME, __func__,
muic_data->afc_retry_count);
}
} else {
pr_info("[%s:%s] ENAFC end = %d\n", MUIC_DEV_NAME, __func__,
muic_data->afc_retry_count);
if (dev1 & DEV_TYPE1_QC20_TA)
muic_data->attached_dev =
ATTACHED_DEV_QC_CHARGER_ERR_V_MUIC;
else
muic_data->attached_dev =
ATTACHED_DEV_AFC_CHARGER_ERR_V_MUIC;
muic_notifier_attach_attached_dev(muic_data->attached_dev);
}
return 0;
}
int sm5713_afc_sta_chg(struct sm5713_muic_data *muic_data)
{
pr_info("[%s:%s] AFC_STA_CHG (attached_dev: %d)\n",
MUIC_DEV_NAME, __func__, muic_data->attached_dev);
return 0;
}
static void hv_muic_change_afc_voltage(int tx_data)
{
struct sm5713_muic_data *muic_data = afc_init_data;
struct i2c_client *i2c = muic_data->i2c;
u8 val = 0;
union power_supply_propval value;
int retry = 0;
pr_info("[%s:%s] change afc voltage(%x)\n",
MUIC_DEV_NAME, __func__, tx_data);
/* QC20 */
if ((muic_data->attached_dev == ATTACHED_DEV_QC_CHARGER_9V_MUIC) ||
(muic_data->attached_dev == ATTACHED_DEV_QC_CHARGER_5V_MUIC)) {
switch (tx_data) {
case SM5713_MUIC_HV_5V:
/* QC20 5V */
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_QC20_9V, 0);
muic_data->attached_dev =
ATTACHED_DEV_QC_CHARGER_5V_MUIC;
break;
case SM5713_MUIC_HV_9V:
/* QC20 9V */
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_QC20_9V, 1);
muic_data->attached_dev =
ATTACHED_DEV_QC_CHARGER_9V_MUIC;
break;
default:
break;
}
} else { /* AFC */
val = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_AFCTXD);
if (val == tx_data) {
pr_info("[%s:%s] same to current voltage 0x%x\n",
MUIC_DEV_NAME, __func__, val);
return;
}
for (retry = 0; retry < 10; retry++) {
msleep(50);
psy_do_property("sm5713-charger", get,
POWER_SUPPLY_PROP_CURRENT_MAX, value);
if (value.intval <= 500) {
pr_info("[%s:%s]PREPARE Success(%d)\n",
MUIC_DEV_NAME, __func__,
value.intval);
break;
}
pr_info("[%s:%s]PREPARE fail(%d)\n",
MUIC_DEV_NAME, __func__, value.intval);
}
cancel_delayed_work(&muic_data->afc_retry_work);
schedule_delayed_work(&muic_data->afc_retry_work,
msecs_to_jiffies(5000)); /* 5sec */
pr_info("[%s:%s] afc_retry_work(afc voltage) start\n",
MUIC_DEV_NAME, __func__);
sm5713_i2c_write_byte(i2c, SM5713_MUIC_REG_AFCTXD, tx_data);
/* ENAFC set '1' */
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_ENAFC, 1);
}
}
int sm5713_muic_afc_set_voltage(int vol)
{
int now_vol = 0;
struct sm5713_muic_data *muic_data = afc_init_data;
switch (muic_data->attached_dev) {
case ATTACHED_DEV_AFC_CHARGER_PREPARE_MUIC:
case ATTACHED_DEV_AFC_CHARGER_5V_MUIC:
case ATTACHED_DEV_AFC_CHARGER_5V_DUPLI_MUIC:
case ATTACHED_DEV_AFC_CHARGER_9V_MUIC:
case ATTACHED_DEV_AFC_CHARGER_9V_DUPLI_MUIC:
case ATTACHED_DEV_QC_CHARGER_PREPARE_MUIC:
case ATTACHED_DEV_QC_CHARGER_5V_MUIC:
case ATTACHED_DEV_QC_CHARGER_9V_MUIC:
break;
default:
pr_info("[%s:%s] not HV charger, returnV\n",
MUIC_DEV_NAME, __func__);
return -EINVAL;
}
switch (muic_data->attached_dev) {
case ATTACHED_DEV_AFC_CHARGER_9V_MUIC:
case ATTACHED_DEV_QC_CHARGER_9V_MUIC:
now_vol = 9;
break;
case ATTACHED_DEV_AFC_CHARGER_5V_MUIC:
case ATTACHED_DEV_QC_CHARGER_5V_MUIC:
now_vol = 5;
break;
default:
break;
}
if (now_vol == vol) {
pr_info("[%s:%s] same voltage(%d), return\n",
MUIC_DEV_NAME, __func__, vol);
return 0;
}
/* do not set high voltage at below conditions */
if (vol > 5) {
if ((muic_data->fled_torch_enable == 1) ||
(muic_data->fled_flash_enable == 1)) {
pr_info("[%s:%s] FLASH or Torch On, Skip AFC\n",
MUIC_DEV_NAME, __func__);
return 0;
}
#if defined(CONFIG_MUIC_SUPPORT_CCIC)
if (muic_data->ccic_afc_state == SM5713_MUIC_AFC_ABNORMAL) {
pr_info("[%s:%s] ccic abnormal: AFC(QC20) skip\n",
MUIC_DEV_NAME, __func__);
return 0;
}
#endif
}
pr_info("[%s:%s] vol = %dV\n", MUIC_DEV_NAME, __func__, vol);
muic_data->hv_voltage = vol;
if (vol == 5) {
hv_muic_change_afc_voltage(SM5713_MUIC_HV_5V);
} else if (vol == 9) {
hv_muic_change_afc_voltage(SM5713_MUIC_HV_9V);
} else if (vol == 12) {
hv_muic_change_afc_voltage(SM5713_MUIC_HV_12V);
} else {
pr_warn("[%s:%s]invalid value\n", MUIC_DEV_NAME, __func__);
return -EINVAL;
}
return 0;
}
static void muic_afc_torch_work(struct work_struct *work)
{
pr_info("[%s:%s]\n", MUIC_DEV_NAME, __func__);
muic_disable_afc(0); /* 5V -> 9V(12V) */
}
static void muic_afc_retry_work(struct work_struct *work)
{
struct sm5713_muic_data *muic_data = afc_init_data;
struct i2c_client *i2c = muic_data->i2c;
int ret = 0, vbus = 0;
ret = sm5713_i2c_read_byte(i2c, SM5713_MUIC_REG_AFCSTATUS);
pr_info("[%s:%s]: Read REG_AFCSTATUS = [0x%02x]\n",
MUIC_DEV_NAME, __func__, ret);
pr_info("[%s:%s] attached_dev = %d\n", MUIC_DEV_NAME, __func__,
muic_data->attached_dev);
if (muic_data->attached_dev == ATTACHED_DEV_AFC_CHARGER_PREPARE_MUIC) {
vbus = sm5713_i2c_read_byte(i2c, 0x3E);
if (!(vbus & 0x01)) {
pr_info("[%s:%s] VBUS is nothing\n",
MUIC_DEV_NAME, __func__);
muic_notifier_detach_attached_dev(
muic_data->attached_dev);
muic_data->attached_dev = ATTACHED_DEV_NONE_MUIC;
return;
}
pr_info("[%s:%s] [MUIC] device type is afc prepare, DP_RESET\n",
MUIC_DEV_NAME, __func__);
/* DP_RESET '1' */
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_DP_RESET, 1);
}
}
#if defined(CONFIG_MUIC_SUPPORT_CCIC)
static void sm5713_muic_ccic_afc_handler(struct work_struct *work)
{
struct sm5713_muic_data *muic_data =
container_of(work, struct sm5713_muic_data, ccic_afc_work.work);
pr_info("[%s:%s] ccic_afc_state:%d, ccic_afc_state_count:%d\n",
MUIC_DEV_NAME, __func__, muic_data->ccic_afc_state,
muic_data->ccic_afc_state_count);
if (muic_data->ccic_afc_state_count > 4) {
cancel_delayed_work(&muic_data->ccic_afc_work);
muic_data->attached_dev = ATTACHED_DEV_TA_MUIC;
muic_notifier_attach_attached_dev(muic_data->attached_dev);
return;
}
if (muic_data->ccic_afc_state == SM5713_MUIC_AFC_NORMAL) {
pr_info("[%s:%s] SM5713_MUIC_AFC_NORMAL\n",
MUIC_DEV_NAME, __func__);
/* ENAFC set '1' */
sm5713_set_afc_ctrl_reg(muic_data, AFCCTRL_ENAFC, 1);
pr_info("[%s:%s] AFCCTRL_ENAFC 1\n", MUIC_DEV_NAME, __func__);
muic_data->afc_retry_count = 0;
muic_data->afc_vbus_retry_count = 0;
} else {
muic_data->ccic_afc_state_count++;
cancel_delayed_work(&muic_data->ccic_afc_work);
schedule_delayed_work(&muic_data->ccic_afc_work,
msecs_to_jiffies(200));
pr_info("[%s:%s] ccic_afc_work(%d) start\n", MUIC_DEV_NAME,
__func__, muic_data->ccic_afc_state_count);
}
}
#endif
static void sm5713_hv_muic_init_detect(struct work_struct *work)
{
struct sm5713_muic_data *muic_data = afc_init_data;
int afc_ta_attached = 0;
pr_info("[%s:%s]\n", MUIC_DEV_NAME, __func__);
afc_ta_attached = sm5713_i2c_read_byte(muic_data->i2c,
SM5713_MUIC_REG_AFCTASTATUS);
pr_info("[%s:%s] REG_AFCTASTATUS:[0x%02x]\n", MUIC_DEV_NAME, __func__,
afc_ta_attached);
/* AFC_TA_ATTACHED */
if (afc_ta_attached & 0x01)
sm5713_afc_ta_attach(muic_data);
}
int sm5713_muic_charger_init(void)
{
int ret = -EINVAL;
pr_info("[%s:%s]\n", MUIC_DEV_NAME, __func__);
if (!afc_init_data) {
pr_info("[%s:%s] MUIC AFC is not ready.\n",
MUIC_DEV_NAME, __func__);
return ret;
}
if (is_charger_ready) {
pr_info("[%s:%s] charger is already ready.\n",
MUIC_DEV_NAME, __func__);
return ret;
}
is_charger_ready = true;
if (afc_init_data->attached_dev == ATTACHED_DEV_TA_MUIC)
schedule_work(&muic_afc_init_work);
return 0;
}
void sm5713_hv_muic_initialize(struct sm5713_muic_data *muic_data)
{
pr_info("[%s:%s]\n", MUIC_DEV_NAME, __func__);
afc_init_data = muic_data;
is_charger_ready = false;
/* To make AFC work properly on boot */
INIT_WORK(&muic_afc_init_work, sm5713_hv_muic_init_detect);
INIT_DELAYED_WORK(&muic_data->afc_retry_work, muic_afc_retry_work);
INIT_DELAYED_WORK(&muic_data->afc_torch_work, muic_afc_torch_work);
INIT_DELAYED_WORK(&muic_data->afc_prepare_work, muic_afc_prepare_work);
#if defined(CONFIG_MUIC_SUPPORT_CCIC)
INIT_DELAYED_WORK(&muic_data->ccic_afc_work,
sm5713_muic_ccic_afc_handler);
#endif
}