lineage_kernel_xcoverpro/drivers/muic/muic_core.c

906 lines
23 KiB
C
Executable File

/* drivers/muic/muic-core.c
*
* Copyright (c) 2020 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* 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/platform_device.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/gpio.h>
/* switch device header */
#ifdef CONFIG_SWITCH
#include <linux/switch.h>
#endif /* CONFIG_SWITCH */
#if defined(CONFIG_USE_SAFEOUT)
#include <linux/regulator/consumer.h>
#endif
#if defined(CONFIG_USB_HW_PARAM)
#include <linux/usb_notify.h>
#endif
#include <linux/muic/muic.h>
#include <linux/muic/muic_interface.h>
#if defined(CONFIG_MUIC_NOTIFIER)
#include <linux/muic/muic_notifier.h>
#endif /* CONFIG_MUIC_NOTIFIER */
#if defined(CONFIG_MUIC_NOTIFIER)
static struct notifier_block cable_data_notifier_block;
#endif
static void muic_jig_uart_cb(int jig_state)
{
pr_info("%s: MUIC uart type(%d)\n", __func__, jig_state);
#ifdef CONFIG_SWITCH
switch_set_state(&switch_uart3, jig_state);
#endif
}
static int muic_core_switch_to_usb(struct muic_platform_data *muic_pdata, int path)
{
int ret = 0;
struct muic_interface_t *muic_if = (struct muic_interface_t *)muic_pdata->muic_if;
pr_info("%s\n", __func__);
#if !defined(CONFIG_MUIC_USB_SWITCH)
if (muic_pdata->gpio_usb_sel) {
MUIC_PDATA_FUNC_MULTI_PARAM(muic_if->set_gpio_usb_sel,
muic_pdata->drv_data, path, &ret);
if (ret) {
pr_err("%s com->uart set err\n", __func__);
return ret;
}
}
#endif
MUIC_PDATA_FUNC(muic_if->set_switch_to_usb, muic_pdata->drv_data, &ret);
if (ret) {
pr_err("%s com->usb set err\n", __func__);
return ret;
}
return ret;
}
static int muic_core_switch_to_uart(struct muic_platform_data *muic_pdata, int path)
{
int ret = 0;
struct muic_interface_t *muic_if = (struct muic_interface_t *)muic_pdata->muic_if;
pr_info("%s\n", __func__);
#if !defined(CONFIG_MUIC_UART_SWITCH)
if (muic_pdata->gpio_uart_sel) {
MUIC_PDATA_FUNC_MULTI_PARAM(muic_if->set_gpio_uart_sel,
muic_pdata->drv_data, path, &ret);
if (ret) {
pr_err("%s com->uart set err\n", __func__);
return ret;
}
}
#endif
MUIC_PDATA_FUNC(muic_if->set_switch_to_uart, muic_pdata->drv_data, &ret);
if (ret) {
pr_err("%s com->uart set err\n", __func__);
return ret;
}
return ret;
}
static int muic_core_attach_charger(struct muic_platform_data *muic_pdata,
muic_attached_dev_t new_dev)
{
int ret = 0;
pr_info("%s : %d\n", __func__, new_dev);
muic_pdata->attached_dev = new_dev;
return ret;
}
static int muic_core_detach_charger(struct muic_platform_data *muic_pdata)
{
int ret = 0;
#ifndef CONFIG_MUIC_SKIP_INCOMPLETE_INSERT
struct muic_interface_t *muic_if = (struct muic_interface_t *)muic_pdata->muic_if;
#endif
pr_info("%s\n", __func__);
#ifndef CONFIG_MUIC_SKIP_INCOMPLETE_INSERT
if (muic_if != NULL)
muic_if->is_dcp_charger = false;
#endif
muic_pdata->attached_dev = ATTACHED_DEV_NONE_MUIC;
return ret;
}
static int muic_core_attach_usb_util(struct muic_platform_data *muic_pdata,
muic_attached_dev_t new_dev)
{
int ret = 0;
ret = muic_core_switch_to_usb(muic_pdata, muic_pdata->usb_path);
if (ret)
return ret;
ret = muic_core_attach_charger(muic_pdata, new_dev);
return ret;
}
static int muic_core_attach_usb(struct muic_platform_data *muic_pdata,
muic_attached_dev_t new_dev)
{
int ret = 0;
if (muic_pdata->attached_dev == new_dev) {
pr_info("%s duplicated\n", __func__);
return ret;
}
pr_info("%s\n",__func__);
ret = muic_core_attach_usb_util(muic_pdata, new_dev);
if (ret)
return ret;
return ret;
}
static int muic_core_attach_otg_usb(struct muic_platform_data *muic_pdata,
muic_attached_dev_t new_dev)
{
int ret = 0;
struct muic_interface_t *muic_if = (struct muic_interface_t *)muic_pdata->muic_if;
if (muic_pdata->attached_dev == new_dev) {
pr_info("%s duplicated\n", __func__);
return ret;
}
pr_info("%s\n", __func__);
if (muic_if->set_com_to_otg) {
ret = muic_if->set_com_to_otg(muic_pdata->drv_data);
if (ret) {
pr_err("%s switch set err\n", __func__);
return ret;
}
} else {
pr_err("%s func not set.\n", __func__);
}
muic_pdata->attached_dev = new_dev;
return ret;
}
static int muic_core_detach_otg_usb(struct muic_platform_data *muic_pdata)
{
int ret = 0;
struct muic_interface_t *muic_if = (struct muic_interface_t *)muic_pdata->muic_if;
pr_info("%s : %d\n",
__func__, muic_pdata->attached_dev);
if (muic_if->set_com_to_open) {
ret = muic_if->set_com_to_open(muic_pdata->drv_data);
if (ret) {
pr_err("%s switch set err\n", __func__);
return ret;
}
} else {
pr_err("%s func not set.\n", __func__);
}
muic_pdata->attached_dev = ATTACHED_DEV_NONE_MUIC;
if (muic_pdata->usb_path == MUIC_PATH_USB_CP)
return ret;
return ret;
}
static int muic_core_detach_usb(struct muic_platform_data *muic_pdata)
{
int ret = 0;
struct muic_interface_t *muic_if = (struct muic_interface_t *)muic_pdata->muic_if;
pr_info("%s : %d\n",
__func__, muic_pdata->attached_dev);
ret = muic_core_detach_charger(muic_pdata);
if (ret)
return ret;
if (muic_if->set_com_to_open) {
ret = muic_if->set_com_to_open(muic_pdata->drv_data);
if (ret) {
pr_err("%s switch set err\n", __func__);
return ret;
}
} else {
pr_err("%s func not set.\n", __func__);
}
muic_pdata->attached_dev = ATTACHED_DEV_NONE_MUIC;
if (muic_pdata->usb_path == MUIC_PATH_USB_CP)
return ret;
return ret;
}
static int muic_core_attach_jig_uart_boot_off(struct muic_platform_data *muic_pdata,
muic_attached_dev_t new_dev)
{
int ret = 0;
pr_info("%s(%d)\n",
__func__, new_dev);
ret = muic_core_switch_to_uart(muic_pdata, muic_pdata->uart_path);
ret = muic_core_attach_charger(muic_pdata, new_dev);
return ret;
}
static int muic_core_detach_jig_uart_boot_off(struct muic_platform_data *muic_pdata)
{
int ret = 0;
pr_info("%s\n", __func__);
ret = muic_core_detach_charger(muic_pdata);
if (ret)
pr_err("%s err detach_charger(%d)\n", __func__, ret);
muic_pdata->attached_dev = ATTACHED_DEV_NONE_MUIC;
return ret;
}
static int muic_core_attach_jig_usb_boot_off(struct muic_platform_data *muic_pdata,
u8 vbvolt)
{
int ret = 0;
if (muic_pdata->attached_dev == ATTACHED_DEV_JIG_USB_OFF_MUIC) {
pr_info("%s duplicated\n", __func__);
return ret;
}
pr_info("%s\n", __func__);
ret = muic_core_attach_usb_util(muic_pdata, ATTACHED_DEV_JIG_USB_OFF_MUIC);
if (ret)
return ret;
return ret;
}
static int muic_core_attach_jig_usb_boot_on(struct muic_platform_data *muic_pdata,
u8 vbvolt)
{
int ret = 0;
if (muic_pdata->attached_dev == ATTACHED_DEV_JIG_USB_ON_MUIC) {
pr_info("%s duplicated\n", __func__);
return ret;
}
pr_info("%s\n", __func__);
ret = muic_core_attach_usb_util(muic_pdata, ATTACHED_DEV_JIG_USB_ON_MUIC);
if (ret)
return ret;
return ret;
}
static int muic_core_handle_attached_prev_dev(struct muic_platform_data *muic_pdata,
muic_attached_dev_t new_dev, bool *noti)
{
int ret = 0;
bool lc_noti = *noti;
pr_info("%s attached_dev: %d, new_dev: %d\n",
__func__, muic_pdata->attached_dev, new_dev);
switch (muic_pdata->attached_dev) {
case ATTACHED_DEV_USB_MUIC:
case ATTACHED_DEV_CDP_MUIC:
case ATTACHED_DEV_JIG_USB_OFF_MUIC:
case ATTACHED_DEV_JIG_USB_ON_MUIC:
case ATTACHED_DEV_TIMEOUT_OPEN_MUIC:
if (new_dev != muic_pdata->attached_dev) {
pr_info("%s new(%d)!=attached(%d)\n",
__func__, new_dev, muic_pdata->attached_dev);
ret = muic_core_detach_usb(muic_pdata);
}
break;
case ATTACHED_DEV_OTG_MUIC:
/* OTG -> LANHUB, meaning TA is attached to LANHUB(OTG) */
if (new_dev != muic_pdata->attached_dev) {
pr_info("%s new(%d)!=attached(%d)",
__func__, new_dev, muic_pdata->attached_dev);
ret = muic_core_detach_otg_usb(muic_pdata);
}
break;
case ATTACHED_DEV_TA_MUIC:
case ATTACHED_DEV_UNDEFINED_CHARGING_MUIC:
if (new_dev != muic_pdata->attached_dev) {
pr_info("%s new(%d)!=attached(%d)\n",
__func__, new_dev, muic_pdata->attached_dev);
ret = muic_core_detach_charger(muic_pdata);
}
break;
case ATTACHED_DEV_JIG_UART_OFF_VB_OTG_MUIC:
case ATTACHED_DEV_JIG_UART_OFF_VB_FG_MUIC:
case ATTACHED_DEV_JIG_UART_OFF_VB_MUIC:
case ATTACHED_DEV_JIG_UART_OFF_MUIC:
if (new_dev != muic_pdata->attached_dev) {
if (muic_core_get_ccic_cable_state(muic_pdata)) {
lc_noti = false;
}
pr_info("%s new(%d)!=attached(%d)\n",
__func__, new_dev, muic_pdata->attached_dev);
ret = muic_core_detach_jig_uart_boot_off(muic_pdata);
}
break;
case ATTACHED_DEV_JIG_UART_ON_MUIC:
case ATTACHED_DEV_JIG_UART_ON_VB_MUIC:
if (new_dev != muic_pdata->attached_dev) {
if (muic_core_get_ccic_cable_state(muic_pdata)) {
lc_noti = false;
}
pr_info("%s new(%d)!=attached(%d)\n",
__func__, new_dev, muic_pdata->attached_dev);
ret = muic_core_detach_jig_uart_boot_off(muic_pdata);
}
break;
case ATTACHED_DEV_NONE_MUIC:
default:
break;
}
if (*noti && lc_noti) {
if (!muic_pdata->suspended)
MUIC_SEND_NOTI_DETACH(muic_pdata->attached_dev);
else
muic_pdata->need_to_noti = true;
}
return ret;
}
static int muic_core_handle_attached_new_dev(struct muic_platform_data *muic_pdata,
muic_attached_dev_t new_dev, bool *noti)
{
int ret = 0;
struct muic_interface_t *muic_if = (struct muic_interface_t *)muic_pdata->muic_if;
pr_info("%s : muic_pdata->attached_dev: %d, new_dev: %d\n",
__func__, muic_pdata->attached_dev, new_dev);
switch (new_dev) {
case ATTACHED_DEV_USB_MUIC:
case ATTACHED_DEV_CDP_MUIC:
case ATTACHED_DEV_TIMEOUT_OPEN_MUIC:
ret = muic_core_attach_usb(muic_pdata, new_dev);
break;
case ATTACHED_DEV_OTG_MUIC:
ret = muic_core_attach_otg_usb(muic_pdata, new_dev);
break;
case ATTACHED_DEV_TA_MUIC:
case ATTACHED_DEV_UNDEFINED_CHARGING_MUIC:
case ATTACHED_DEV_UNSUPPORTED_ID_VB_MUIC:
ret = muic_core_attach_charger(muic_pdata, new_dev);
#if defined(CONFIG_HV_MUIC_S2MU004_AFC) || defined(CONFIG_MUIC_HV)
MUIC_PDATA_FUNC(muic_if->check_afc_ready, muic_pdata->drv_data, &ret);
#endif /* CONFIG_HV_MUIC_S2MU004_AFC */
MUIC_PDATA_FUNC(muic_if->set_com_to_open_with_vbus, muic_pdata->drv_data, &ret);
break;
case ATTACHED_DEV_JIG_UART_OFF_VB_OTG_MUIC:
case ATTACHED_DEV_JIG_UART_OFF_VB_FG_MUIC:
case ATTACHED_DEV_JIG_UART_OFF_VB_MUIC:
case ATTACHED_DEV_JIG_UART_OFF_MUIC:
#if defined(CONFIG_MUIC_SUPPORT_TYPEB)
#if defined(CONFIG_SEC_FACTORY)
muic_pdata->is_jig_on = true;
#endif
#else
muic_pdata->is_jig_on = true;
#endif
ret = muic_core_attach_jig_uart_boot_off(muic_pdata, new_dev);
break;
case ATTACHED_DEV_JIG_UART_ON_MUIC:
case ATTACHED_DEV_JIG_UART_ON_VB_MUIC:
#if !defined(CONFIG_MUIC_SUPPORT_TYPEB)
muic_pdata->is_jig_on = true;
#endif
ret = muic_core_attach_jig_uart_boot_off(muic_pdata, new_dev);
break;
case ATTACHED_DEV_JIG_USB_OFF_MUIC:
#if !defined(CONFIG_MUIC_SUPPORT_TYPEB)
muic_pdata->is_jig_on = true;
#endif
ret = muic_core_attach_jig_usb_boot_off(muic_pdata, muic_pdata->vbvolt);
break;
case ATTACHED_DEV_JIG_USB_ON_MUIC:
#if !defined(CONFIG_MUIC_SUPPORT_TYPEB)
muic_pdata->is_jig_on = true;
#endif
ret = muic_core_attach_jig_usb_boot_on(muic_pdata, muic_pdata->vbvolt);
break;
case ATTACHED_DEV_UNKNOWN_MUIC:
MUIC_PDATA_FUNC(muic_if->set_com_to_open_with_vbus, muic_pdata->drv_data, &ret);
ret = muic_core_attach_charger(muic_pdata, new_dev);
break;
case ATTACHED_DEV_TYPE3_MUIC:
muic_pdata->attached_dev = new_dev;
break;
case ATTACHED_DEV_UNDEFINED_RANGE_MUIC:
muic_pdata->attached_dev = new_dev;
break;
default:
*noti = false;
pr_info("%s unsupported dev=%d, adc=0x%x, vbus=%c\n",
__func__, new_dev, muic_pdata->adc,
(muic_pdata->vbvolt ? 'O' : 'X'));
break;
}
/* TODO: There is no needs to use JIGB pin by MUIC if CCIC is supported */
#ifndef CONFIG_CCIC_S2MU107
MUIC_PDATA_FUNC(muic_if->set_jig_ctrl_on, muic_pdata->drv_data, &ret);
#endif
if (ret)
pr_err("%s something wrong %d (ERR=%d)\n",
__func__, new_dev, ret);
pr_info("%s done\n",__func__);
#if defined(CONFIG_HV_MUIC_S2MU004_AFC) || defined(CONFIG_MUIC_HV)
MUIC_PDATA_FUNC_MULTI_PARAM(muic_if->check_id_err, muic_pdata->drv_data,
new_dev, &ret);
new_dev = ret;
#endif /* CONFIG_HV_MUIC_S2MU004_AFC */
return ret;
}
bool muic_core_get_ccic_cable_state(struct muic_platform_data *muic_pdata)
{
pr_info("%s call, attached_dev : %d\n", __func__, muic_pdata->attached_dev);
switch (muic_pdata->attached_dev) {
case ATTACHED_DEV_JIG_USB_OFF_MUIC:
case ATTACHED_DEV_JIG_USB_ON_MUIC:
case ATTACHED_DEV_JIG_UART_OFF_MUIC:
case ATTACHED_DEV_JIG_UART_OFF_VB_MUIC:
case ATTACHED_DEV_JIG_UART_ON_MUIC:
case ATTACHED_DEV_JIG_UART_ON_VB_MUIC:
case ATTACHED_DEV_OTG_MUIC:
#if defined(CONFIG_MUIC_SUPPORT_PRSWAP)
case ATTACHED_DEV_USB_MUIC:
#endif
return true;
default:
break;
}
return false;
}
int muic_core_handle_attach(struct muic_platform_data *muic_pdata,
muic_attached_dev_t new_dev, int adc, u8 vbvolt)
{
int ret = 0;
bool noti = (new_dev != muic_pdata->attached_dev) ? true : false;
muic_pdata->is_jig_on = false;
pr_info("%s attached_dev: %d, new_dev: %d\n",
__func__, muic_pdata->attached_dev, new_dev);
muic_pdata->adc = adc;
muic_pdata->vbvolt = vbvolt;
if (muic_pdata->attached_dev != ATTACHED_DEV_NONE_MUIC) {
ret = muic_core_handle_attached_prev_dev(muic_pdata, new_dev, &noti);
if (ret)
pr_err("%s prev_dev failed\n", __func__);
}
ret = muic_core_handle_attached_new_dev(muic_pdata, new_dev, &noti);
if (ret)
pr_err("%s new_dev failed\n", __func__);
if (noti) {
if (!muic_pdata->suspended)
MUIC_SEND_NOTI_ATTACH(new_dev);
else
muic_pdata->need_to_noti = true;
}
return ret;
}
EXPORT_SYMBOL_GPL(muic_core_handle_attach);
int muic_core_handle_detach(struct muic_platform_data *muic_pdata)
{
int ret = 0;
bool noti = true;
struct muic_interface_t *muic_if = (struct muic_interface_t *)muic_pdata->muic_if;
MUIC_PDATA_FUNC(muic_if->set_com_to_open, muic_pdata->drv_data, &ret);
#if defined(CONFIG_MUIC_SUPPORT_TYPEB)
muic_pdata->is_jig_on = false;
MUIC_PDATA_FUNC(muic_if->set_jig_ctrl_on, muic_pdata->drv_data, &ret);
#endif
switch (muic_pdata->attached_dev) {
case ATTACHED_DEV_JIG_USB_OFF_MUIC:
case ATTACHED_DEV_JIG_USB_ON_MUIC:
case ATTACHED_DEV_USB_MUIC:
case ATTACHED_DEV_CDP_MUIC:
case ATTACHED_DEV_TIMEOUT_OPEN_MUIC:
#if defined(CONFIG_SEC_FACTORY)
case ATTACHED_DEV_CARKIT_MUIC:
#endif
ret = muic_core_detach_usb(muic_pdata);
break;
case ATTACHED_DEV_OTG_MUIC:
ret = muic_core_detach_otg_usb(muic_pdata);
break;
case ATTACHED_DEV_TA_MUIC:
case ATTACHED_DEV_UNDEFINED_CHARGING_MUIC:
ret = muic_core_detach_charger(muic_pdata);
#if defined(CONFIG_HV_MUIC_S2MU004_AFC) || defined(CONFIG_MUIC_HV)
MUIC_PDATA_FUNC(muic_if->reset_hvcontrol_reg, muic_pdata->drv_data, &ret);
#endif
break;
case ATTACHED_DEV_JIG_UART_OFF_VB_OTG_MUIC:
case ATTACHED_DEV_JIG_UART_OFF_VB_FG_MUIC:
case ATTACHED_DEV_JIG_UART_OFF_VB_MUIC:
case ATTACHED_DEV_JIG_UART_OFF_MUIC:
case ATTACHED_DEV_JIG_UART_ON_MUIC:
case ATTACHED_DEV_JIG_UART_ON_VB_MUIC:
ret = muic_core_detach_jig_uart_boot_off(muic_pdata);
break;
case ATTACHED_DEV_NONE_MUIC:
pr_info("%s duplicated(NONE)\n", __func__);
break;
case ATTACHED_DEV_UNKNOWN_MUIC:
pr_info("%s UNKNOWN\n", __func__);
ret = muic_core_detach_charger(muic_pdata);
muic_pdata->attached_dev = ATTACHED_DEV_NONE_MUIC;
break;
#if defined(CONFIG_HV_MUIC_S2MU004_AFC) || defined(CONFIG_MUIC_HV)
case ATTACHED_DEV_AFC_CHARGER_PREPARE_MUIC:
case ATTACHED_DEV_AFC_CHARGER_PREPARE_DUPLI_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_DISABLED_MUIC:
case ATTACHED_DEV_QC_CHARGER_5V_MUIC:
case ATTACHED_DEV_QC_CHARGER_9V_MUIC:
case ATTACHED_DEV_QC_CHARGER_PREPARE_MUIC:
case ATTACHED_DEV_AFC_CHARGER_ERR_V_MUIC:
case ATTACHED_DEV_AFC_CHARGER_ERR_V_DUPLI_MUIC:
ret = muic_core_detach_charger(muic_pdata);
MUIC_PDATA_FUNC(muic_if->reset_hvcontrol_reg,muic_pdata->drv_data, &ret);
break;
#endif
default:
noti = false;
pr_info("%s invalid type(%d)\n",
__func__, muic_pdata->attached_dev);
muic_pdata->attached_dev = ATTACHED_DEV_NONE_MUIC;
break;
}
if (ret)
pr_err("%s something wrong %d (ERR=%d)\n",
__func__, muic_pdata->attached_dev, ret);
if (noti) {
if (!muic_pdata->suspended)
MUIC_SEND_NOTI_DETACH(muic_pdata->attached_dev);
else
muic_pdata->need_to_noti = true;
}
return ret;
}
EXPORT_SYMBOL_GPL(muic_core_handle_detach);
static inline void muic_core_hv_set_new_state(struct muic_platform_data *muic_pdata,
muic_hv_state_t next_state)
{
muic_pdata->hv_state = next_state;
}
static inline muic_hv_state_t muic_core_hv_get_current_state(struct muic_platform_data *muic_pdata)
{
return muic_pdata->hv_state;
}
bool muic_core_hv_is_hv_dev(struct muic_platform_data *muic_pdata)
{
bool ret = false;
switch (muic_pdata->attached_dev) {
case ATTACHED_DEV_AFC_CHARGER_PREPARE_MUIC:
case ATTACHED_DEV_AFC_CHARGER_PREPARE_DUPLI_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_ERR_V_MUIC:
case ATTACHED_DEV_AFC_CHARGER_ERR_V_DUPLI_MUIC:
case ATTACHED_DEV_HV_ID_ERR_UNDEFINED_MUIC:
case ATTACHED_DEV_HV_ID_ERR_UNSUPPORTED_MUIC:
case ATTACHED_DEV_HV_ID_ERR_SUPPORTED_MUIC:
ret = true;
break;
default:
ret = false;
}
pr_info("%s attached_dev(%d)[%c]\n",
__func__, muic_pdata->attached_dev, (ret ? 'T' : 'F'));
return ret;
}
EXPORT_SYMBOL_GPL(muic_core_hv_is_hv_dev);
void muic_core_hv_handle_state(struct muic_platform_data *muic_pdata,
muic_hv_state_t next_state)
{
struct muic_interface_t *muic_if = muic_pdata->muic_if;
muic_core_hv_set_new_state(muic_pdata, next_state);
switch (next_state) {
case HV_STATE_IDLE:
MUIC_PDATA_VOID_FUNC(muic_if->hv_reset, muic_pdata->drv_data);
break;
case HV_STATE_DCP_CHARGER:
MUIC_PDATA_VOID_FUNC(muic_if->hv_dcp_charger, muic_pdata->drv_data);
break;
case HV_STATE_FAST_CHARGE_ADAPTOR:
MUIC_PDATA_VOID_FUNC(muic_if->hv_fast_charge_adaptor, muic_pdata->drv_data);
break;
case HV_STATE_FAST_CHARGE_COMMUNICATION:
MUIC_PDATA_VOID_FUNC(muic_if->hv_fast_charge_communication, muic_pdata->drv_data);
break;
case HV_STATE_AFC_5V_CHARGER:
MUIC_PDATA_VOID_FUNC(muic_if->hv_afc_5v_charger, muic_pdata->drv_data);
break;
case HV_STATE_AFC_9V_CHARGER:
MUIC_PDATA_VOID_FUNC(muic_if->hv_afc_9v_charger, muic_pdata->drv_data);
break;
case HV_STATE_QC_CHARGER:
MUIC_PDATA_VOID_FUNC(muic_if->hv_qc_charger, muic_pdata->drv_data);
break;
case HV_STATE_QC_5V_CHARGER:
MUIC_PDATA_VOID_FUNC(muic_if->hv_qc_5v_charger, muic_pdata->drv_data);
break;
case HV_STATE_QC_9V_CHARGER:
MUIC_PDATA_VOID_FUNC(muic_if->hv_qc_9v_charger, muic_pdata->drv_data);
break;
default:
pr_err("%s not defined state : %d\n",
__func__, next_state);
break;
}
}
int muic_core_hv_state_manager(struct muic_platform_data *muic_pdata,
muic_hv_transaction_t trans)
{
muic_hv_state_t cur_state = muic_core_hv_get_current_state(muic_pdata);
muic_hv_state_t next_state = HV_STATE_INVALID;
bool skip_trans = false;
switch (cur_state) {
case HV_STATE_IDLE:
switch (trans) {
case HV_TRANS_DCP_DETECTED:
next_state = HV_STATE_DCP_CHARGER;
break;
default:
skip_trans = true;
break;
}
break;
case HV_STATE_DCP_CHARGER:
switch (trans) {
case HV_TRANS_MUIC_DETACH:
case HV_TRANS_NO_RESPONSE:
next_state = HV_STATE_IDLE;
break;
case HV_TRANS_VDNMON_LOW:
next_state = HV_STATE_FAST_CHARGE_ADAPTOR;
break;
default:
skip_trans = true;
break;
}
break;
case HV_STATE_FAST_CHARGE_ADAPTOR:
switch (trans) {
case HV_TRANS_MUIC_DETACH:
next_state = HV_STATE_IDLE;
break;
case HV_TRANS_NO_RESPONSE:
next_state = HV_STATE_QC_CHARGER;
break;
case HV_TRANS_FAST_CHARGE_PING_RESPONSE:
next_state = HV_STATE_FAST_CHARGE_COMMUNICATION;
break;
case HV_TRANS_FAST_CHARGE_REOPEN:
next_state = HV_STATE_FAST_CHARGE_ADAPTOR;
break;
default:
skip_trans = true;
break;
}
break;
case HV_STATE_FAST_CHARGE_COMMUNICATION:
switch (trans) {
case HV_TRANS_MUIC_DETACH:
next_state = HV_STATE_IDLE;
break;
case HV_TRANS_NO_RESPONSE:
next_state = HV_STATE_QC_CHARGER;
break;
case HV_TRANS_FAST_CHARGE_PING_RESPONSE:
next_state = HV_STATE_FAST_CHARGE_COMMUNICATION;
break;
case HV_TRANS_VBUS_BOOST:
next_state = HV_STATE_AFC_9V_CHARGER;
break;
default:
skip_trans = true;
break;
}
break;
case HV_STATE_AFC_5V_CHARGER:
switch (trans) {
case HV_TRANS_MUIC_DETACH:
next_state = HV_STATE_IDLE;
break;
case HV_TRANS_VBUS_BOOST:
next_state = HV_STATE_AFC_9V_CHARGER;
break;
default:
skip_trans = true;
break;
}
break;
case HV_STATE_AFC_9V_CHARGER:
switch (trans) {
case HV_TRANS_MUIC_DETACH:
next_state = HV_STATE_IDLE;
break;
case HV_TRANS_VBUS_REDUCE:
next_state = HV_STATE_AFC_5V_CHARGER;
break;
default:
skip_trans = true;
break;
}
break;
case HV_STATE_QC_CHARGER:
switch (trans) {
case HV_TRANS_MUIC_DETACH:
next_state = HV_STATE_IDLE;
break;
case HV_TRANS_VBUS_BOOST:
next_state = HV_STATE_QC_9V_CHARGER;
break;
default:
skip_trans = true;
break;
}
break;
case HV_STATE_QC_5V_CHARGER:
switch (trans) {
case HV_TRANS_MUIC_DETACH:
next_state = HV_STATE_IDLE;
break;
case HV_TRANS_VBUS_BOOST:
next_state = HV_STATE_QC_9V_CHARGER;
break;
default:
skip_trans = true;
break;
}
break;
case HV_STATE_QC_9V_CHARGER:
switch (trans) {
case HV_TRANS_MUIC_DETACH:
next_state = HV_STATE_IDLE;
break;
case HV_TRANS_VBUS_REDUCE:
next_state = HV_STATE_QC_5V_CHARGER;
break;
default:
skip_trans = true;
break;
}
break;
case HV_STATE_INVALID:
case HV_STATE_MAX_NUM:
default:
skip_trans = true;
break;
}
if (skip_trans) {
pr_info("%s skip to transaction - state(%d), trans(%d)\n", __func__, cur_state, trans);
} else {
pr_info("%s state(%d->%d), trans(%d)\n", __func__, cur_state, next_state, trans);
muic_core_hv_handle_state(muic_pdata, next_state);
}
return 0;
}
EXPORT_SYMBOL_GPL(muic_core_hv_state_manager);
void muic_core_hv_init(struct muic_platform_data *muic_pdata)
{
struct muic_interface_t *muic_if;
if (muic_pdata == NULL)
return;
muic_if = muic_pdata->muic_if;
muic_pdata->hv_state = HV_STATE_IDLE;
MUIC_PDATA_VOID_FUNC(muic_if->hv_reset, muic_pdata->drv_data);
}
EXPORT_SYMBOL_GPL(muic_core_hv_init);
static void muic_init_cable_data_collect_cb(void)
{
#if defined(CONFIG_MUIC_NOTIFIER)
muic_notifier_register(&cable_data_notifier_block,
muic_handle_cable_data_notification, MUIC_NOTIFY_DEV_CABLE_DATA);
#endif /* CONFIG_MUIC_NOTIFIER */
}
struct muic_platform_data *muic_core_init(void *drv_data)
{
muic_pdata.drv_data = drv_data;
muic_pdata.attached_dev = ATTACHED_DEV_NONE_MUIC;
muic_pdata.cleanup_switch_dev_cb = muic_cleanup_switch_dev_cb;
muic_pdata.is_usb_ready = false;
muic_pdata.is_factory_start = false;
muic_pdata.is_rustproof = muic_pdata.rustproof_on;
muic_pdata.init_switch_dev_cb = muic_init_switch_dev_cb;
muic_pdata.init_gpio_cb = muic_init_gpio_cb;
muic_pdata.jig_uart_cb = muic_jig_uart_cb,
muic_pdata.init_cable_data_collect_cb = muic_init_cable_data_collect_cb,
#if defined(CONFIG_USE_SAFEOUT)
muic_pdata.set_safeout = muic_set_safeout,
#endif /* CONFIG_USE_SAFEOUT */
#if defined(CONFIG_MUIC_HV)
muic_pdata.hv_state = HV_STATE_IDLE;
#endif
muic_init_switch_dev_cb();
return &muic_pdata;
}
void muic_core_exit(struct muic_platform_data *muic_pdata)
{
kfree(muic_pdata);
}