android_kernel_samsung_msm8976/drivers/muic/universal/muic_apis.c

851 lines
18 KiB
C

/*
* muic_apis.c
*
* Copyright (C) 2014 Samsung Electronics
* Thomas Ryu <smilesr.ryu@samsung.com>
*
* 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 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/host_notify.h>
#include <linux/string.h>
#include <linux/muic/muic.h>
#if defined(CONFIG_MUIC_NOTIFIER)
#include <linux/muic/muic_notifier.h>
#endif /* CONFIG_MUIC_NOTIFIER */
#if defined (CONFIG_OF)
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#endif /* CONFIG_OF */
#include "muic-internal.h"
#include "muic_i2c.h"
#include "muic_regmap.h"
int attach_ta(muic_data_t *pmuic)
{
struct vendor_ops *pvendor = pmuic->regmapdesc->vendorops;
if (pvendor->attach_ta) {
pr_info("%s: ", __func__);
pvendor->attach_ta(pmuic->regmapdesc);
} else
pr_info("%s: No Vendor API ready.\n", __func__);
return 0;
}
int detach_ta(muic_data_t *pmuic)
{
struct vendor_ops *pvendor = pmuic->regmapdesc->vendorops;
if (pvendor->detach_ta) {
pr_info("%s: ", __func__);
pvendor->detach_ta(pmuic->regmapdesc);
} else
pr_info("%s: No Vendor API ready.\n", __func__);
return 0;
}
static int get_charger_type(muic_data_t *pmuic)
{
struct regmap_ops *pops = pmuic->regmapdesc->regmapops;
int uattr;
pops->ioctl(pmuic->regmapdesc, GET_CHGTYPE, NULL, &uattr);
return regmap_read_value(pmuic->regmapdesc, uattr);
}
static int set_BCD_RESCAN_reg(muic_data_t *pmuic, int value)
{
struct regmap_ops *pops = pmuic->regmapdesc->regmapops;
struct vendor_ops *pvendor = pmuic->regmapdesc->vendorops;
int uattr, ret;
if (pvendor && pvendor->rescan) {
ret = pvendor->rescan(pmuic->regmapdesc, value);
return ret;
}
pops->ioctl(pmuic->regmapdesc, GET_RESID3, NULL, &uattr);
#if defined(CONFIG_MUIC_UNIVERSAL_SM5504)
value = !value;
#else
uattr |= _ATTR_OVERWRITE_M;
#endif
ret = regmap_write_value(pmuic->regmapdesc, uattr, value);
_REGMAP_TRACE(pmuic->regmapdesc, 'w', ret, uattr, value);
return ret;
}
int do_BCD_rescan(muic_data_t *pmuic)
{
static int bcd_rescan = 0;
pr_info("%s\n", __func__);
if (bcd_rescan) {
int chg_type = get_charger_type(pmuic);
int new_dev = 0;
bcd_rescan = 0;
if (chg_type < 0)
pr_err("%s:%s err %d\n", MUIC_DEV_NAME, __func__, chg_type);
pr_info("%s [MUIC] BCD result chg_type = 0x%x \n", __func__, chg_type);
switch(chg_type) {
case 0x01 : // DCP
new_dev = ATTACHED_DEV_TA_MUIC;
break;
case 0x02 : // CDP
new_dev = ATTACHED_DEV_CDP_MUIC;
break;
case 0x04 : // SDP
new_dev = ATTACHED_DEV_USB_MUIC;
break;
case 0x08 : // Time out SDP
new_dev = ATTACHED_DEV_USB_MUIC;
break;
case 0x10 : // U200
new_dev = ATTACHED_DEV_TA_MUIC;
break;
}
return new_dev;
}
pr_info("[MUIC] 219K USB Cable/Charger Connected\n");
pr_info("[MUIC] BCD rescan\n");
// 0x21 -> 1 0x21 -> 0
set_BCD_RESCAN_reg(pmuic, 0x01);
msleep(1);
pr_info("[MUIC] Writing BCD_RECAN\n");
set_BCD_RESCAN_reg(pmuic, 0x00);
bcd_rescan = 1;
return 0;
}
int get_switch_mode(muic_data_t *pmuic)
{
struct vendor_ops *pvendor = pmuic->regmapdesc->vendorops;
int val=0;
if (pvendor->get_switch) {
pr_info("%s: ", __func__);
val = pvendor->get_switch(pmuic->regmapdesc);
} else{
pr_info("%s: No Vendor API ready.\n", __func__);
val = -1;
}
return val;
}
void set_switch_mode(muic_data_t *pmuic, int mode)
{
struct vendor_ops *pvendor = pmuic->regmapdesc->vendorops;
if (pvendor->set_switch) {
pr_info("%s: ", __func__);
pvendor->set_switch(pmuic->regmapdesc,mode);
} else{
pr_info("%s: No Vendor API ready.\n", __func__);
}
return;
}
int get_adc_scan_mode(muic_data_t *pmuic)
{
struct vendor_ops *pvendor = pmuic->regmapdesc->vendorops;
int value = 0;
if (pvendor->get_adc_scan_mode) {
pr_info("%s: ", __func__);
value = pvendor->get_adc_scan_mode(pmuic->regmapdesc);
} else{
pr_info("%s: No Vendor API ready.\n", __func__);
value = -1;
}
return value;
}
void set_adc_scan_mode(muic_data_t *pmuic, const u8 val)
{
struct vendor_ops *pvendor = pmuic->regmapdesc->vendorops;
if (pvendor->set_adc_scan_mode) {
pr_info("%s: ", __func__);
pvendor->set_adc_scan_mode(pmuic->regmapdesc,val);
} else
pr_info("%s: No Vendor API ready.\n", __func__);
return;
}
#define com_to_open com_to_open_with_vbus
#ifndef com_to_open
int com_to_open(muic_data_t *pmuic)
{
int ret = 0;
ret = regmap_com_to(pmuic->regmapdesc, COM_OPEN);
if (ret < 0)
pr_err("%s:%s com_to_open err\n", MUIC_DEV_NAME, __func__);
return ret;
}
#endif
int com_to_open_with_vbus(muic_data_t *pmuic)
{
int ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
ret = regmap_com_to(pmuic->regmapdesc, COM_OPEN_WITH_V_BUS);
if (ret < 0)
pr_err("%s:%s com_to_open err\n", MUIC_DEV_NAME, __func__);
return ret;
}
int com_to_usb_ap(muic_data_t *pmuic)
{
int ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
ret = regmap_com_to(pmuic->regmapdesc, COM_USB_AP);
if (ret < 0)
pr_err("%s:%s set_com_usb err\n", MUIC_DEV_NAME, __func__);
return ret;
}
int com_to_usb_cp(muic_data_t *pmuic)
{
int ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
ret = regmap_com_to(pmuic->regmapdesc, COM_USB_CP);
if (ret < 0)
pr_err("%s:%s set_com_usb err\n", MUIC_DEV_NAME, __func__);
return ret;
}
static int set_rustproof_mode(struct regmap_desc *pdesc, int op)
{
struct vendor_ops *pvendor = pdesc->vendorops;
if (pvendor->set_rustproof) {
pr_info("%s: %s", __func__, op ? "On" : "Off");
pvendor->set_rustproof(pdesc, op);
} else
pr_err("%s: No Vendor API ready.\n", __func__);
return 0;
}
int com_to_uart_ap(muic_data_t *pmuic)
{
int com_index = 0, ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
com_index = pmuic->is_rustproof ? COM_OPEN_WITH_V_BUS : COM_UART_AP;
ret = regmap_com_to(pmuic->regmapdesc, com_index);
if (ret < 0)
pr_err("%s:%s set_com_uart err\n", MUIC_DEV_NAME, __func__);
if(pmuic->is_rustproof) {
pr_info("%s:%s rustproof mode Enabled\n",
MUIC_DEV_NAME, __func__);
set_rustproof_mode(pmuic->regmapdesc, 1);
}
return ret;
}
int com_to_uart_cp(muic_data_t *pmuic)
{
int com_index = 0, ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
com_index = pmuic->is_rustproof ? COM_OPEN_WITH_V_BUS : COM_UART_CP;
ret = regmap_com_to(pmuic->regmapdesc, com_index);
if (ret < 0)
pr_err("%s:%s set_com_uart err\n", MUIC_DEV_NAME, __func__);
if(pmuic->is_rustproof) {
pr_info("%s:%s rustproof mode Enabled\n",
MUIC_DEV_NAME, __func__);
set_rustproof_mode(pmuic->regmapdesc, 1);
}
return ret;
}
int com_to_audio(muic_data_t *pmuic)
{
int ret = 0;
ret = regmap_com_to(pmuic->regmapdesc, COM_AUDIO);
if (ret < 0)
pr_err("%s:%s set_com_audio err\n", MUIC_DEV_NAME, __func__);
return ret;
}
int switch_to_ap_usb(muic_data_t *pmuic)
{
int ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
ret = com_to_usb_ap(pmuic);
if (ret < 0) {
pr_err("%s:%s com->usb set err\n", MUIC_DEV_NAME, __func__);
return ret;
}
return ret;
}
int switch_to_cp_usb(muic_data_t *pmuic)
{
int ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
ret = com_to_usb_cp(pmuic);
if (ret < 0) {
pr_err("%s:%s com->usb set err\n", MUIC_DEV_NAME, __func__);
return ret;
}
return ret;
}
int switch_to_ap_uart(muic_data_t *pmuic)
{
struct muic_platform_data *pdata = pmuic->pdata;
int ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
if (pdata->set_gpio_uart_sel)
pdata->set_gpio_uart_sel(MUIC_PATH_UART_AP);
ret = com_to_uart_ap(pmuic);
if (ret < 0) {
pr_err("%s:%s com->uart set err\n", MUIC_DEV_NAME, __func__);
return ret;
}
return ret;
}
int switch_to_cp_uart(muic_data_t *pmuic)
{
struct muic_platform_data *pdata = pmuic->pdata;
int ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
if (pdata->set_gpio_uart_sel)
pdata->set_gpio_uart_sel(MUIC_PATH_UART_CP);
ret = com_to_uart_cp(pmuic);
if (ret < 0) {
pr_err("%s:%s com->uart set err\n", MUIC_DEV_NAME, __func__);
return ret;
}
return ret;
}
int attach_uart_util(muic_data_t *pmuic,
muic_attached_dev_t new_dev)
{
int ret = 0;
pmuic->attached_dev = new_dev;
if (pmuic->pdata->usb_path == MUIC_PATH_UART_AP) {
ret = switch_to_ap_uart(pmuic);
}
else if (pmuic->pdata->usb_path == MUIC_PATH_UART_CP) {
ret = switch_to_cp_uart(pmuic);
}
else
pr_warn("%s:%s invalid usb_path\n", MUIC_DEV_NAME, __func__);
return ret;
}
int attach_usb_util(muic_data_t *pmuic,
muic_attached_dev_t new_dev)
{
int ret = 0;
pmuic->attached_dev = new_dev;
if (pmuic->pdata->usb_path == MUIC_PATH_USB_AP) {
ret = switch_to_ap_usb(pmuic);
}
else if (pmuic->pdata->usb_path == MUIC_PATH_USB_CP) {
ret = switch_to_cp_usb(pmuic);
}
else
pr_warn("%s:%s invalid usb_path\n", MUIC_DEV_NAME, __func__);
return ret;
}
int attach_usb(muic_data_t *pmuic,
muic_attached_dev_t new_dev)
{
int ret = 0;
if (pmuic->attached_dev == new_dev) {
pr_info("%s:%s duplicated(USB)\n", MUIC_DEV_NAME, __func__);
return ret;
}
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
ret = attach_usb_util(pmuic, new_dev);
if (ret < 0) {
pr_err("%s:%s fail.(%d)\n", MUIC_DEV_NAME, __func__, ret);
return ret;
}
return ret;
}
int detach_usb(muic_data_t *pmuic)
{
int ret = 0;
pr_info("%s:%s attached_dev type(%d)\n", MUIC_DEV_NAME, __func__,
pmuic->attached_dev);
ret = com_to_open_with_vbus(pmuic);
if (ret < 0) {
pr_err("%s:%s fail.(%d)\n", MUIC_DEV_NAME, __func__, ret);
return ret;
}
pmuic->attached_dev = ATTACHED_DEV_NONE_MUIC;
return ret;
}
int attach_otg_usb(muic_data_t *pmuic,
muic_attached_dev_t new_dev)
{
int ret = 0;
if (pmuic->attached_dev == new_dev) {
pr_info("%s:%s duplicated(USB)\n", MUIC_DEV_NAME, __func__);
return ret;
}
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
/* LANHUB doesn't work under AUTO switch mode, so turn it off */
/* set MANUAL SW mode */
set_switch_mode(pmuic,SWMODE_MANUAL);
/* enable RAW DATA mode, only for OTG LANHUB */
set_adc_scan_mode(pmuic,ADC_SCANMODE_CONTINUOUS);
ret = switch_to_ap_usb(pmuic);
pmuic->attached_dev = new_dev;
return ret;
}
int detach_otg_usb(muic_data_t *pmuic)
{
int ret = 0;
pr_info("%s:%s attached_dev type(%d)\n", MUIC_DEV_NAME, __func__,
pmuic->attached_dev);
ret = com_to_open_with_vbus(pmuic);
if (ret < 0) {
pr_err("%s:%s fail.(%d)\n", MUIC_DEV_NAME, __func__, ret);
return ret;
}
if (get_switch_mode(pmuic) != SWMODE_AUTO)
set_switch_mode(pmuic, SWMODE_AUTO);
if (get_adc_scan_mode(pmuic) != ADC_SCANMODE_ONESHOT)
set_adc_scan_mode(pmuic, ADC_SCANMODE_ONESHOT);
pmuic->attached_dev = ATTACHED_DEV_NONE_MUIC;
return ret;
}
int attach_ps_cable(muic_data_t *pmuic,
muic_attached_dev_t new_dev)
{
int ret = 0;
pr_info("%s:%s new_dev(%d)\n", MUIC_DEV_NAME, __func__, new_dev);
com_to_open_with_vbus(pmuic);
pmuic->attached_dev = new_dev;
return ret;
}
int detach_ps_cable(muic_data_t *pmuic)
{
int ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
pmuic->attached_dev = ATTACHED_DEV_NONE_MUIC;
return ret;
}
/* Do the followings on attachment.
* 1. Do not run charger detection.
* 2. Set AP USB path
* 3. Set continuous adc scan mode with USB's notification.
*/
int attach_gamepad(muic_data_t *pmuic,
muic_attached_dev_t new_dev)
{
// struct vendor_ops *pvendor = pmuic->regmapdesc->vendorops;
int ret = 0;
if (pmuic->attached_dev == new_dev) {
pr_info("%s:%s duplicated(gamepad)\n", MUIC_DEV_NAME, __func__);
return ret;
}
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
// if (pvendor && pvendor->enable_chgdet)
// pvendor->enable_chgdet(pmuic->regmapdesc, 0);
ret = switch_to_ap_usb(pmuic);
pmuic->attached_dev = new_dev;
return 0;
}
int detach_gamepad(muic_data_t *pmuic)
{
// struct vendor_ops *pvendor = pmuic->regmapdesc->vendorops;
int ret = 0;
pr_info("%s:%s attached_dev type(%d)\n", MUIC_DEV_NAME, __func__,
pmuic->attached_dev);
ret = com_to_open_with_vbus(pmuic);
if (ret < 0) {
pr_err("%s:%s fail.(%d)\n", MUIC_DEV_NAME, __func__, ret);
return ret;
}
// if (pvendor && pvendor->enable_chgdet)
// pvendor->enable_chgdet(pmuic->regmapdesc, 1);
set_adc_scan_mode(pmuic, ADC_SCANMODE_ONESHOT);
pmuic->is_gamepad = false;
pmuic->attached_dev = ATTACHED_DEV_NONE_MUIC;
return 0;
}
int attach_deskdock(muic_data_t *pmuic,
muic_attached_dev_t new_dev)
{
int ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
/* Audio-out doesn't work under AUTO switch mode, so turn it off */
/* set MANUAL SW mode */
set_switch_mode(pmuic,SWMODE_MANUAL);
ret = com_to_audio(pmuic);
if (ret < 0) {
pr_err("%s:%s fail.(%d)\n", MUIC_DEV_NAME, __func__, ret);
return ret;
}
pmuic->attached_dev = new_dev;
return ret;
}
int detach_deskdock(muic_data_t *pmuic)
{
int ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
set_switch_mode(pmuic,SWMODE_AUTO);
pmuic->attached_dev = ATTACHED_DEV_NONE_MUIC;
return ret;
}
int attach_audiodock(muic_data_t *pmuic,
muic_attached_dev_t new_dev, u8 vbus)
{
int ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
ret = attach_usb_util(pmuic, new_dev);
if (ret < 0)
pr_err("%s:%s fail.(%d)\n", MUIC_DEV_NAME, __func__, ret);
return ret;
}
int detach_audiodock(muic_data_t *pmuic)
{
int ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
ret = com_to_open_with_vbus(pmuic);
if (ret < 0)
return ret;
pmuic->attached_dev = ATTACHED_DEV_NONE_MUIC;
return ret;
}
int attach_jig_uart_boot_off(muic_data_t *pmuic, muic_attached_dev_t new_dev,
u8 vbvolt)
{
struct muic_platform_data *pdata = pmuic->pdata;
int ret = 0;
pr_info("%s:%s JIG UART BOOT-OFF(0x%x)\n", MUIC_DEV_NAME, __func__,
vbvolt);
if (pdata->uart_path == MUIC_PATH_UART_AP)
ret = switch_to_ap_uart(pmuic);
else
ret = switch_to_cp_uart(pmuic);
/* if VBUS is enabled, call host_notify_cb to check if it is OTGTEST*/
if (vbvolt) {
if (pmuic->is_otg_test) {
pr_info("%s:%s OTG_TEST\n", MUIC_DEV_NAME, __func__);
/* in OTG_TEST mode, do not charge */
new_dev = ATTACHED_DEV_JIG_UART_OFF_VB_OTG_MUIC;
} else
/* JIG_UART_OFF_VB */
new_dev = ATTACHED_DEV_JIG_UART_OFF_VB_MUIC;
} else
new_dev = ATTACHED_DEV_JIG_UART_OFF_MUIC;
pmuic->attached_dev = new_dev;
return new_dev;
}
int detach_jig_uart_boot_off(muic_data_t *pmuic)
{
int ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
if(pmuic->is_rustproof) {
pr_info("%s:%s rustproof mode : Set Auto SW mode\n",
MUIC_DEV_NAME, __func__);
set_rustproof_mode(pmuic->regmapdesc, 0);
}
pmuic->attached_dev = ATTACHED_DEV_NONE_MUIC;
return ret;
}
/*
* QA's requirement on JIG_UART_ON(619K)
* 1. Factory Test Mode
* Send a deskdock Noti. to wakeup the device.
* (OPEN->619K->OPEN->523K )
* 2. Normal
* Do not charge the device. (No charging Icon and current)
* Need to set the path OPEN and cut off VBUS input.
*/
int attach_jig_uart_boot_on(muic_data_t *pmuic, muic_attached_dev_t new_dev)
{
int com_index = COM_OPEN;
int ret = 0;
pr_info("%s:%s JIG UART BOOT-ON(0x%x)\n",
MUIC_DEV_NAME, __func__, new_dev);
ret = regmap_com_to(pmuic->regmapdesc, com_index);
if (ret < 0)
pr_err("%s:%s set_com_uart err\n", MUIC_DEV_NAME, __func__);
if (pmuic->is_rustproof) {
pr_info("%s:%s rustproof mode is set.\n",
MUIC_DEV_NAME, __func__);
set_rustproof_mode(pmuic->regmapdesc, 1);
}
pmuic->attached_dev = new_dev;
return ret;
}
int detach_jig_uart_boot_on(muic_data_t *pmuic)
{
int ret = 0;
pr_info("%s:%s rustproof mode is restored.\n",
MUIC_DEV_NAME, __func__);
set_rustproof_mode(pmuic->regmapdesc, 0);
pmuic->attached_dev = ATTACHED_DEV_NONE_MUIC;
return ret;
}
int attach_jig_usb_boot_off(muic_data_t *pmuic,
u8 vbvolt)
{
int ret = 0;
if (pmuic->attached_dev == ATTACHED_DEV_JIG_USB_OFF_MUIC) {
pr_info("%s:%s duplicated(JIG USB OFF)\n", MUIC_DEV_NAME,
__func__);
return ret;
}
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
ret = attach_usb_util(pmuic, ATTACHED_DEV_JIG_USB_OFF_MUIC);
if (ret < 0) {
pr_err("%s:%s fail.(%d)\n", MUIC_DEV_NAME, __func__, ret);
return ret;
}
return ret;
}
int attach_jig_usb_boot_on(muic_data_t *pmuic,
u8 vbvolt)
{
int ret = 0;
if (pmuic->attached_dev == ATTACHED_DEV_JIG_USB_ON_MUIC) {
pr_info("%s:%s duplicated(JIG USB ON)\n", MUIC_DEV_NAME,
__func__);
return ret;
}
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
ret = attach_usb_util(pmuic, ATTACHED_DEV_JIG_USB_ON_MUIC);
if (ret < 0)
return ret;
return ret;
}
int attach_mhl(muic_data_t *pmuic)
{
int ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
ret = com_to_open_with_vbus(pmuic);
if (ret < 0) {
pr_err("%s:%s fail.(%d)\n", MUIC_DEV_NAME, __func__, ret);
return ret;
}
pmuic->attached_dev = ATTACHED_DEV_MHL_MUIC;
return ret;
}
int detach_mhl(muic_data_t *pmuic)
{
int ret = 0;
pr_info("%s:%s\n", MUIC_DEV_NAME, __func__);
if(ret < 0)
pr_err("%s:%s err detach_charger(%d)\n", MUIC_DEV_NAME, __func__, ret);
pmuic->attached_dev = ATTACHED_DEV_NONE_MUIC;
return ret;
}
int get_adc(muic_data_t *pmuic)
{
struct regmap_ops *pops = pmuic->regmapdesc->regmapops;
int uattr;
pops->ioctl(pmuic->regmapdesc, GET_ADC, NULL, &uattr);
return regmap_read_value(pmuic->regmapdesc, uattr);
}
int get_vps_data(muic_data_t *pmuic, void *pdata)
{
struct vendor_ops *pvendor = pmuic->regmapdesc->vendorops;
if (pvendor->get_vps_data)
pvendor->get_vps_data(pmuic->regmapdesc, pdata);
else
pr_info("%s: No Vendor API ready.\n", __func__);
return 0;
}