661 lines
15 KiB
C
661 lines
15 KiB
C
/* linux/arch/arm/mach-msm/rpc_hsusb.c
|
|
*
|
|
* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
|
|
*
|
|
* All source code in this file is licensed under the following license except
|
|
* where indicated.
|
|
*
|
|
* 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.
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, you can find it at http://www.fsf.org
|
|
*/
|
|
|
|
#include <linux/err.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/module.h>
|
|
#include <mach/rpc_hsusb.h>
|
|
#include <asm/mach-types.h>
|
|
|
|
static struct msm_rpc_endpoint *usb_ep;
|
|
static struct msm_rpc_endpoint *chg_ep;
|
|
|
|
#define MSM_RPC_CHG_PROG 0x3000001a
|
|
|
|
struct msm_chg_rpc_ids {
|
|
unsigned long vers_comp;
|
|
unsigned chg_usb_charger_connected_proc;
|
|
unsigned chg_usb_charger_disconnected_proc;
|
|
unsigned chg_usb_i_is_available_proc;
|
|
unsigned chg_usb_i_is_not_available_proc;
|
|
};
|
|
|
|
struct msm_hsusb_rpc_ids {
|
|
unsigned long prog;
|
|
unsigned long vers_comp;
|
|
unsigned long init_phy;
|
|
unsigned long vbus_pwr_up;
|
|
unsigned long vbus_pwr_down;
|
|
unsigned long update_product_id;
|
|
unsigned long update_serial_num;
|
|
unsigned long update_is_serial_num_null;
|
|
unsigned long reset_rework_installed;
|
|
unsigned long enable_pmic_ulpi_data0;
|
|
unsigned long disable_pmic_ulpi_data0;
|
|
};
|
|
|
|
static struct msm_hsusb_rpc_ids usb_rpc_ids;
|
|
static struct msm_chg_rpc_ids chg_rpc_ids;
|
|
|
|
static int msm_hsusb_init_rpc_ids(unsigned long vers)
|
|
{
|
|
if (vers == 0x00010001) {
|
|
usb_rpc_ids.prog = 0x30000064;
|
|
usb_rpc_ids.vers_comp = 0x00010001;
|
|
usb_rpc_ids.init_phy = 2;
|
|
usb_rpc_ids.vbus_pwr_up = 6;
|
|
usb_rpc_ids.vbus_pwr_down = 7;
|
|
usb_rpc_ids.update_product_id = 8;
|
|
usb_rpc_ids.update_serial_num = 9;
|
|
usb_rpc_ids.update_is_serial_num_null = 10;
|
|
usb_rpc_ids.reset_rework_installed = 17;
|
|
usb_rpc_ids.enable_pmic_ulpi_data0 = 18;
|
|
usb_rpc_ids.disable_pmic_ulpi_data0 = 19;
|
|
return 0;
|
|
} else if (vers == 0x00010002) {
|
|
usb_rpc_ids.prog = 0x30000064;
|
|
usb_rpc_ids.vers_comp = 0x00010002;
|
|
usb_rpc_ids.init_phy = 2;
|
|
usb_rpc_ids.vbus_pwr_up = 6;
|
|
usb_rpc_ids.vbus_pwr_down = 7;
|
|
usb_rpc_ids.update_product_id = 8;
|
|
usb_rpc_ids.update_serial_num = 9;
|
|
usb_rpc_ids.update_is_serial_num_null = 10;
|
|
usb_rpc_ids.reset_rework_installed = 17;
|
|
usb_rpc_ids.enable_pmic_ulpi_data0 = 18;
|
|
usb_rpc_ids.disable_pmic_ulpi_data0 = 19;
|
|
return 0;
|
|
} else {
|
|
pr_err("%s: no matches found for version\n",
|
|
__func__);
|
|
return -ENODATA;
|
|
}
|
|
}
|
|
|
|
static int msm_chg_init_rpc(unsigned long vers)
|
|
{
|
|
if (((vers & RPC_VERSION_MAJOR_MASK) == 0x00010000) ||
|
|
((vers & RPC_VERSION_MAJOR_MASK) == 0x00020000) ||
|
|
((vers & RPC_VERSION_MAJOR_MASK) == 0x00030000) ||
|
|
((vers & RPC_VERSION_MAJOR_MASK) == 0x00040000)) {
|
|
chg_ep = msm_rpc_connect_compatible(MSM_RPC_CHG_PROG, vers,
|
|
MSM_RPC_UNINTERRUPTIBLE);
|
|
if (IS_ERR(chg_ep))
|
|
return -ENODATA;
|
|
chg_rpc_ids.vers_comp = vers;
|
|
chg_rpc_ids.chg_usb_charger_connected_proc = 7;
|
|
chg_rpc_ids.chg_usb_charger_disconnected_proc = 8;
|
|
chg_rpc_ids.chg_usb_i_is_available_proc = 9;
|
|
chg_rpc_ids.chg_usb_i_is_not_available_proc = 10;
|
|
return 0;
|
|
} else
|
|
return -ENODATA;
|
|
}
|
|
|
|
/* rpc connect for hsusb */
|
|
int msm_hsusb_rpc_connect(void)
|
|
{
|
|
|
|
if (usb_ep && !IS_ERR(usb_ep)) {
|
|
pr_debug("%s: usb_ep already connected\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/* Initialize rpc ids */
|
|
if (msm_hsusb_init_rpc_ids(0x00010001)) {
|
|
pr_err("%s: rpc ids initialization failed\n"
|
|
, __func__);
|
|
return -ENODATA;
|
|
}
|
|
|
|
usb_ep = msm_rpc_connect_compatible(usb_rpc_ids.prog,
|
|
usb_rpc_ids.vers_comp,
|
|
MSM_RPC_UNINTERRUPTIBLE);
|
|
|
|
if (IS_ERR(usb_ep)) {
|
|
pr_err("%s: connect compatible failed vers = %lx\n",
|
|
__func__, usb_rpc_ids.vers_comp);
|
|
|
|
/* Initialize rpc ids */
|
|
if (msm_hsusb_init_rpc_ids(0x00010002)) {
|
|
pr_err("%s: rpc ids initialization failed\n",
|
|
__func__);
|
|
return -ENODATA;
|
|
}
|
|
usb_ep = msm_rpc_connect_compatible(usb_rpc_ids.prog,
|
|
usb_rpc_ids.vers_comp,
|
|
MSM_RPC_UNINTERRUPTIBLE);
|
|
}
|
|
|
|
if (IS_ERR(usb_ep)) {
|
|
pr_err("%s: connect compatible failed vers = %lx\n",
|
|
__func__, usb_rpc_ids.vers_comp);
|
|
return -EAGAIN;
|
|
} else
|
|
pr_debug("%s: rpc connect success vers = %lx\n",
|
|
__func__, usb_rpc_ids.vers_comp);
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(msm_hsusb_rpc_connect);
|
|
|
|
/* rpc connect for charging */
|
|
int msm_chg_rpc_connect(void)
|
|
{
|
|
uint32_t chg_vers;
|
|
|
|
if (machine_is_msm7x27_surf() || machine_is_qsd8x50_surf())
|
|
return -ENOTSUPP;
|
|
|
|
if (chg_ep && !IS_ERR(chg_ep)) {
|
|
pr_debug("%s: chg_ep already connected\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
chg_vers = 0x00040001;
|
|
if (!msm_chg_init_rpc(chg_vers))
|
|
goto chg_found;
|
|
|
|
chg_vers = 0x00030001;
|
|
if (!msm_chg_init_rpc(chg_vers))
|
|
goto chg_found;
|
|
|
|
chg_vers = 0x00020001;
|
|
if (!msm_chg_init_rpc(chg_vers))
|
|
goto chg_found;
|
|
|
|
chg_vers = 0x00010001;
|
|
if (!msm_chg_init_rpc(chg_vers))
|
|
goto chg_found;
|
|
|
|
pr_err("%s: connect compatible failed \n",
|
|
__func__);
|
|
return -EAGAIN;
|
|
|
|
chg_found:
|
|
pr_debug("%s: connected to rpc vers = %x\n",
|
|
__func__, chg_vers);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(msm_chg_rpc_connect);
|
|
|
|
/* rpc call for phy_reset */
|
|
int msm_hsusb_phy_reset(void)
|
|
{
|
|
int rc = 0;
|
|
struct hsusb_phy_start_req {
|
|
struct rpc_request_hdr hdr;
|
|
} req;
|
|
|
|
if (!usb_ep || IS_ERR(usb_ep)) {
|
|
pr_err("%s: phy_reset rpc failed before call,"
|
|
"rc = %ld\n", __func__, PTR_ERR(usb_ep));
|
|
return -EAGAIN;
|
|
}
|
|
|
|
rc = msm_rpc_call(usb_ep, usb_rpc_ids.init_phy,
|
|
&req, sizeof(req), 5 * HZ);
|
|
|
|
if (rc < 0) {
|
|
pr_err("%s: phy_reset rpc failed! rc = %d\n",
|
|
__func__, rc);
|
|
} else
|
|
pr_debug("msm_hsusb_phy_reset\n");
|
|
|
|
return rc;
|
|
}
|
|
EXPORT_SYMBOL(msm_hsusb_phy_reset);
|
|
|
|
/* rpc call for vbus powerup */
|
|
int msm_hsusb_vbus_powerup(void)
|
|
{
|
|
int rc = 0;
|
|
struct hsusb_phy_start_req {
|
|
struct rpc_request_hdr hdr;
|
|
} req;
|
|
|
|
if (!usb_ep || IS_ERR(usb_ep)) {
|
|
pr_err("%s: vbus_powerup rpc failed before call,"
|
|
"rc = %ld\n", __func__, PTR_ERR(usb_ep));
|
|
return -EAGAIN;
|
|
}
|
|
|
|
rc = msm_rpc_call(usb_ep, usb_rpc_ids.vbus_pwr_up,
|
|
&req, sizeof(req), 5 * HZ);
|
|
|
|
if (rc < 0) {
|
|
pr_err("%s: vbus_powerup failed! rc = %d\n",
|
|
__func__, rc);
|
|
} else
|
|
pr_debug("msm_hsusb_vbus_powerup\n");
|
|
|
|
return rc;
|
|
}
|
|
EXPORT_SYMBOL(msm_hsusb_vbus_powerup);
|
|
|
|
/* rpc call for vbus shutdown */
|
|
int msm_hsusb_vbus_shutdown(void)
|
|
{
|
|
int rc = 0;
|
|
struct hsusb_phy_start_req {
|
|
struct rpc_request_hdr hdr;
|
|
} req;
|
|
|
|
if (!usb_ep || IS_ERR(usb_ep)) {
|
|
pr_err("%s: vbus_shutdown rpc failed before call,"
|
|
"rc = %ld\n", __func__, PTR_ERR(usb_ep));
|
|
return -EAGAIN;
|
|
}
|
|
|
|
rc = msm_rpc_call(usb_ep, usb_rpc_ids.vbus_pwr_down,
|
|
&req, sizeof(req), 5 * HZ);
|
|
|
|
if (rc < 0) {
|
|
pr_err("%s: vbus_shutdown failed! rc = %d\n",
|
|
__func__, rc);
|
|
} else
|
|
pr_debug("msm_hsusb_vbus_shutdown\n");
|
|
|
|
return rc;
|
|
}
|
|
EXPORT_SYMBOL(msm_hsusb_vbus_shutdown);
|
|
|
|
int msm_hsusb_send_productID(uint32_t product_id)
|
|
{
|
|
int rc = 0;
|
|
struct hsusb_phy_start_req {
|
|
struct rpc_request_hdr hdr;
|
|
uint32_t product_id;
|
|
} req;
|
|
|
|
if (!usb_ep || IS_ERR(usb_ep)) {
|
|
pr_err("%s: rpc connect failed: rc = %ld\n",
|
|
__func__, PTR_ERR(usb_ep));
|
|
return -EAGAIN;
|
|
}
|
|
|
|
req.product_id = cpu_to_be32(product_id);
|
|
rc = msm_rpc_call(usb_ep, usb_rpc_ids.update_product_id,
|
|
&req, sizeof(req),
|
|
5 * HZ);
|
|
if (rc < 0)
|
|
pr_err("%s: rpc call failed! error: %d\n",
|
|
__func__, rc);
|
|
else
|
|
pr_debug("%s: rpc call success\n" , __func__);
|
|
|
|
return rc;
|
|
}
|
|
EXPORT_SYMBOL(msm_hsusb_send_productID);
|
|
|
|
int msm_hsusb_send_serial_number(const char *serial_number)
|
|
{
|
|
int rc = 0, serial_len, rlen;
|
|
struct hsusb_send_sn_req {
|
|
struct rpc_request_hdr hdr;
|
|
uint32_t length;
|
|
char sn[0];
|
|
} *req;
|
|
|
|
if (!usb_ep || IS_ERR(usb_ep)) {
|
|
pr_err("%s: rpc connect failed: rc = %ld\n",
|
|
__func__, PTR_ERR(usb_ep));
|
|
return -EAGAIN;
|
|
}
|
|
|
|
/*
|
|
* USB driver passes null terminated string to us. Modem processor
|
|
* expects serial number to be 32 bit aligned.
|
|
*/
|
|
serial_len = strlen(serial_number)+1;
|
|
rlen = sizeof(struct rpc_request_hdr) + sizeof(uint32_t) +
|
|
((serial_len + 3) & ~3);
|
|
|
|
req = kmalloc(rlen, GFP_KERNEL);
|
|
if (!req)
|
|
return -ENOMEM;
|
|
|
|
req->length = cpu_to_be32(serial_len);
|
|
strncpy(req->sn , serial_number, serial_len);
|
|
rc = msm_rpc_call(usb_ep, usb_rpc_ids.update_serial_num,
|
|
req, rlen, 5 * HZ);
|
|
if (rc < 0)
|
|
pr_err("%s: rpc call failed! error: %d\n",
|
|
__func__, rc);
|
|
else
|
|
pr_debug("%s: rpc call success\n", __func__);
|
|
|
|
kfree(req);
|
|
return rc;
|
|
}
|
|
EXPORT_SYMBOL(msm_hsusb_send_serial_number);
|
|
|
|
int msm_hsusb_is_serial_num_null(uint32_t val)
|
|
{
|
|
int rc = 0;
|
|
struct hsusb_phy_start_req {
|
|
struct rpc_request_hdr hdr;
|
|
uint32_t value;
|
|
} req;
|
|
|
|
if (!usb_ep || IS_ERR(usb_ep)) {
|
|
pr_err("%s: rpc connect failed: rc = %ld\n",
|
|
__func__, PTR_ERR(usb_ep));
|
|
return -EAGAIN;
|
|
}
|
|
if (!usb_rpc_ids.update_is_serial_num_null) {
|
|
pr_err("%s: proc id not supported \n", __func__);
|
|
return -ENODATA;
|
|
}
|
|
|
|
req.value = cpu_to_be32(val);
|
|
rc = msm_rpc_call(usb_ep, usb_rpc_ids.update_is_serial_num_null,
|
|
&req, sizeof(req),
|
|
5 * HZ);
|
|
if (rc < 0)
|
|
pr_err("%s: rpc call failed! error: %d\n" ,
|
|
__func__, rc);
|
|
else
|
|
pr_debug("%s: rpc call success\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
EXPORT_SYMBOL(msm_hsusb_is_serial_num_null);
|
|
|
|
int msm_chg_usb_charger_connected(uint32_t device)
|
|
{
|
|
int rc = 0;
|
|
struct hsusb_start_req {
|
|
struct rpc_request_hdr hdr;
|
|
uint32_t otg_dev;
|
|
} req;
|
|
|
|
if (!chg_ep || IS_ERR(chg_ep))
|
|
return -EAGAIN;
|
|
req.otg_dev = cpu_to_be32(device);
|
|
rc = msm_rpc_call(chg_ep, chg_rpc_ids.chg_usb_charger_connected_proc,
|
|
&req, sizeof(req), 5 * HZ);
|
|
|
|
if (rc < 0) {
|
|
pr_err("%s: charger_connected failed! rc = %d\n",
|
|
__func__, rc);
|
|
} else
|
|
pr_debug("msm_chg_usb_charger_connected\n");
|
|
|
|
return rc;
|
|
}
|
|
EXPORT_SYMBOL(msm_chg_usb_charger_connected);
|
|
|
|
int msm_chg_usb_i_is_available(uint32_t sample)
|
|
{
|
|
int rc = 0;
|
|
struct hsusb_start_req {
|
|
struct rpc_request_hdr hdr;
|
|
uint32_t i_ma;
|
|
} req;
|
|
|
|
if (!chg_ep || IS_ERR(chg_ep))
|
|
return -EAGAIN;
|
|
req.i_ma = cpu_to_be32(sample);
|
|
rc = msm_rpc_call(chg_ep, chg_rpc_ids.chg_usb_i_is_available_proc,
|
|
&req, sizeof(req), 5 * HZ);
|
|
|
|
if (rc < 0) {
|
|
pr_err("%s: charger_i_available failed! rc = %d\n",
|
|
__func__, rc);
|
|
} else
|
|
pr_debug("msm_chg_usb_i_is_available(%u)\n", sample);
|
|
|
|
return rc;
|
|
}
|
|
EXPORT_SYMBOL(msm_chg_usb_i_is_available);
|
|
|
|
int msm_chg_usb_i_is_not_available(void)
|
|
{
|
|
int rc = 0;
|
|
struct hsusb_start_req {
|
|
struct rpc_request_hdr hdr;
|
|
} req;
|
|
|
|
if (!chg_ep || IS_ERR(chg_ep))
|
|
return -EAGAIN;
|
|
rc = msm_rpc_call(chg_ep, chg_rpc_ids.chg_usb_i_is_not_available_proc,
|
|
&req, sizeof(req), 5 * HZ);
|
|
|
|
if (rc < 0) {
|
|
pr_err("%s: charger_i_not_available failed! rc ="
|
|
"%d \n", __func__, rc);
|
|
} else
|
|
pr_debug("msm_chg_usb_i_is_not_available\n");
|
|
|
|
return rc;
|
|
}
|
|
EXPORT_SYMBOL(msm_chg_usb_i_is_not_available);
|
|
|
|
int msm_chg_usb_charger_disconnected(void)
|
|
{
|
|
int rc = 0;
|
|
struct hsusb_start_req {
|
|
struct rpc_request_hdr hdr;
|
|
} req;
|
|
|
|
if (!chg_ep || IS_ERR(chg_ep))
|
|
return -EAGAIN;
|
|
rc = msm_rpc_call(chg_ep, chg_rpc_ids.chg_usb_charger_disconnected_proc,
|
|
&req, sizeof(req), 5 * HZ);
|
|
|
|
if (rc < 0) {
|
|
pr_err("%s: charger_disconnected failed! rc = %d\n",
|
|
__func__, rc);
|
|
} else
|
|
pr_debug("msm_chg_usb_charger_disconnected\n");
|
|
|
|
return rc;
|
|
}
|
|
EXPORT_SYMBOL(msm_chg_usb_charger_disconnected);
|
|
|
|
/* rpc call to close connection */
|
|
int msm_hsusb_rpc_close(void)
|
|
{
|
|
int rc = 0;
|
|
|
|
if (IS_ERR(usb_ep)) {
|
|
pr_err("%s: rpc_close failed before call, rc = %ld\n",
|
|
__func__, PTR_ERR(usb_ep));
|
|
return -EAGAIN;
|
|
}
|
|
|
|
rc = msm_rpc_close(usb_ep);
|
|
usb_ep = NULL;
|
|
|
|
if (rc < 0) {
|
|
pr_err("%s: close rpc failed! rc = %d\n",
|
|
__func__, rc);
|
|
return -EAGAIN;
|
|
} else
|
|
pr_debug("rpc close success\n");
|
|
|
|
return rc;
|
|
}
|
|
EXPORT_SYMBOL(msm_hsusb_rpc_close);
|
|
|
|
/* rpc call to close charging connection */
|
|
int msm_chg_rpc_close(void)
|
|
{
|
|
int rc = 0;
|
|
|
|
if (IS_ERR(chg_ep)) {
|
|
pr_err("%s: rpc_close failed before call, rc = %ld\n",
|
|
__func__, PTR_ERR(chg_ep));
|
|
return -EAGAIN;
|
|
}
|
|
|
|
rc = msm_rpc_close(chg_ep);
|
|
chg_ep = NULL;
|
|
|
|
if (rc < 0) {
|
|
pr_err("%s: close rpc failed! rc = %d\n",
|
|
__func__, rc);
|
|
return -EAGAIN;
|
|
} else
|
|
pr_debug("rpc close success\n");
|
|
|
|
return rc;
|
|
}
|
|
EXPORT_SYMBOL(msm_chg_rpc_close);
|
|
|
|
int msm_hsusb_reset_rework_installed(void)
|
|
{
|
|
int rc = 0;
|
|
struct hsusb_start_req {
|
|
struct rpc_request_hdr hdr;
|
|
} req;
|
|
struct hsusb_rpc_rep {
|
|
struct rpc_reply_hdr hdr;
|
|
uint32_t rework;
|
|
} rep;
|
|
|
|
memset(&rep, 0, sizeof(rep));
|
|
|
|
if (!usb_ep || IS_ERR(usb_ep)) {
|
|
pr_err("%s: hsusb rpc connection not initialized, rc = %ld\n",
|
|
__func__, PTR_ERR(usb_ep));
|
|
return -EAGAIN;
|
|
}
|
|
|
|
rc = msm_rpc_call_reply(usb_ep, usb_rpc_ids.reset_rework_installed,
|
|
&req, sizeof(req),
|
|
&rep, sizeof(rep), 5 * HZ);
|
|
|
|
if (rc < 0) {
|
|
pr_err("%s: rpc call failed! error: (%d)"
|
|
"proc id: (%lx)\n",
|
|
__func__, rc,
|
|
usb_rpc_ids.reset_rework_installed);
|
|
return rc;
|
|
}
|
|
|
|
pr_info("%s: rework: (%d)\n", __func__, rep.rework);
|
|
return be32_to_cpu(rep.rework);
|
|
}
|
|
EXPORT_SYMBOL(msm_hsusb_reset_rework_installed);
|
|
|
|
static int msm_hsusb_pmic_ulpidata0_config(int enable)
|
|
{
|
|
int rc = 0;
|
|
struct hsusb_start_req {
|
|
struct rpc_request_hdr hdr;
|
|
} req;
|
|
|
|
if (!usb_ep || IS_ERR(usb_ep)) {
|
|
pr_err("%s: hsusb rpc connection not initialized, rc = %ld\n",
|
|
__func__, PTR_ERR(usb_ep));
|
|
return -EAGAIN;
|
|
}
|
|
|
|
if (enable)
|
|
rc = msm_rpc_call(usb_ep, usb_rpc_ids.enable_pmic_ulpi_data0,
|
|
&req, sizeof(req), 5 * HZ);
|
|
else
|
|
rc = msm_rpc_call(usb_ep, usb_rpc_ids.disable_pmic_ulpi_data0,
|
|
&req, sizeof(req), 5 * HZ);
|
|
|
|
if (rc < 0)
|
|
pr_err("%s: rpc call failed! error: %d\n",
|
|
__func__, rc);
|
|
return rc;
|
|
}
|
|
|
|
int msm_hsusb_enable_pmic_ulpidata0(void)
|
|
{
|
|
return msm_hsusb_pmic_ulpidata0_config(1);
|
|
}
|
|
EXPORT_SYMBOL(msm_hsusb_enable_pmic_ulpidata0);
|
|
|
|
int msm_hsusb_disable_pmic_ulpidata0(void)
|
|
{
|
|
return msm_hsusb_pmic_ulpidata0_config(0);
|
|
}
|
|
EXPORT_SYMBOL(msm_hsusb_disable_pmic_ulpidata0);
|
|
|
|
|
|
/* wrapper for sending pid and serial# info to bootloader */
|
|
int usb_diag_update_pid_and_serial_num(uint32_t pid, const char *snum)
|
|
{
|
|
int ret;
|
|
|
|
ret = msm_hsusb_send_productID(pid);
|
|
if (ret)
|
|
return ret;
|
|
|
|
if (!snum) {
|
|
ret = msm_hsusb_is_serial_num_null(1);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
|
|
ret = msm_hsusb_is_serial_num_null(0);
|
|
if (ret)
|
|
return ret;
|
|
ret = msm_hsusb_send_serial_number(snum);
|
|
if (ret)
|
|
return ret;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_USB_MSM_72K
|
|
/* charger api wrappers */
|
|
int hsusb_chg_init(int connect)
|
|
{
|
|
if (connect)
|
|
return msm_chg_rpc_connect();
|
|
else
|
|
return msm_chg_rpc_close();
|
|
}
|
|
EXPORT_SYMBOL(hsusb_chg_init);
|
|
|
|
void hsusb_chg_vbus_draw(unsigned mA)
|
|
{
|
|
msm_chg_usb_i_is_available(mA);
|
|
}
|
|
EXPORT_SYMBOL(hsusb_chg_vbus_draw);
|
|
|
|
void hsusb_chg_connected(enum chg_type chgtype)
|
|
{
|
|
char *chg_types[] = {"STD DOWNSTREAM PORT",
|
|
"CARKIT",
|
|
"DEDICATED CHARGER",
|
|
"INVALID"};
|
|
|
|
if (chgtype == USB_CHG_TYPE__INVALID) {
|
|
msm_chg_usb_i_is_not_available();
|
|
msm_chg_usb_charger_disconnected();
|
|
return;
|
|
}
|
|
|
|
pr_info("\nCharger Type: %s\n", chg_types[chgtype]);
|
|
|
|
msm_chg_usb_charger_connected(chgtype);
|
|
}
|
|
EXPORT_SYMBOL(hsusb_chg_connected);
|
|
#endif
|