245 lines
5.6 KiB
C
245 lines
5.6 KiB
C
/* Copyright (c) 2009, The Linux Foundation. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 and
|
|
* only 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.
|
|
*
|
|
*/
|
|
#include <linux/err.h>
|
|
#include <linux/module.h>
|
|
#include <mach/rpc_hsusb.h>
|
|
#include <mach/msm_hsusb.h>
|
|
#include <mach/msm_rpcrouter.h>
|
|
#include <mach/board.h>
|
|
|
|
#define PM_APP_OTG_PROG 0x30000080
|
|
#define PM_APP_OTG_VERS 0x00010001
|
|
|
|
#define PM_APP_OTG_INIT_PHY 17
|
|
#define PM_APP_OTG_RESET_PHY 18
|
|
#define PM_APP_OTG_SUSPEND_PHY 7
|
|
#define PM_APP_OTG_RESUME_PHY 8
|
|
#define PM_APP_OTG_DEV_DISCONNECTED 9
|
|
#define PM_APP_OTG_SET_WAKEUP 10
|
|
#define PM_APP_OTG_ACQUIRE_BUS 3
|
|
#define PM_APP_OTG_RELINQUISH_BUS 4
|
|
|
|
#define PM_APP_OTG_INIT_DONE_CB_PROC 1
|
|
#define PM_APP_OTG_HOST_INIT_CB_PROC 3
|
|
#define PM_APP_OTG_REMOTE_DEV_LOST_CB_PROC 8
|
|
#define PM_APP_OTG_REMOTE_DEV_RESUMED_CB_PROC 9
|
|
#define PM_APP_OTG_ERROR_NOTIFY_CB_PROC 11
|
|
|
|
#define NUM_OF_CALLBACKS 11
|
|
static struct msm_rpc_client *client;
|
|
static struct msm_otg_ops *host_ops;
|
|
|
|
static int msm_fsusb_rpc_arg(struct msm_rpc_client *client,
|
|
void *buf, void *data)
|
|
{
|
|
int i, size = 0;
|
|
uint32_t proc = *(uint32_t *)data;
|
|
|
|
switch (proc) {
|
|
case PM_APP_OTG_INIT_PHY: {
|
|
for (i = 0; i < NUM_OF_CALLBACKS; i++) {
|
|
*((uint32_t *)buf) = cpu_to_be32(0x11111111);
|
|
size += sizeof(uint32_t);
|
|
buf += sizeof(uint32_t);
|
|
}
|
|
|
|
/* sleep_assert callback fucntion will be registered locally*/
|
|
*((uint32_t *)buf) = cpu_to_be32(0xffffffff);
|
|
size += sizeof(uint32_t);
|
|
break;
|
|
}
|
|
case PM_APP_OTG_SET_WAKEUP: {
|
|
*((uint32_t *)buf) = cpu_to_be32(1);
|
|
size += sizeof(uint32_t);
|
|
break;
|
|
}
|
|
case PM_APP_OTG_ACQUIRE_BUS: {
|
|
*((uint32_t *)buf) = cpu_to_be32(0xffffffff);
|
|
size += sizeof(uint32_t);
|
|
break;
|
|
}
|
|
default:
|
|
pr_info("%s: No arguments expected\n", __func__);
|
|
}
|
|
return size;
|
|
}
|
|
|
|
int msm_fsusb_init_phy(void)
|
|
{
|
|
uint32_t data = PM_APP_OTG_INIT_PHY;
|
|
|
|
return msm_rpc_client_req(client,
|
|
PM_APP_OTG_INIT_PHY,
|
|
msm_fsusb_rpc_arg, &data,
|
|
NULL, NULL, -1);
|
|
}
|
|
EXPORT_SYMBOL(msm_fsusb_init_phy);
|
|
|
|
int msm_fsusb_reset_phy(void)
|
|
{
|
|
return msm_rpc_client_req(client,
|
|
PM_APP_OTG_RESET_PHY,
|
|
NULL, NULL,
|
|
NULL, NULL, -1);
|
|
|
|
}
|
|
EXPORT_SYMBOL(msm_fsusb_reset_phy);
|
|
|
|
int msm_fsusb_suspend_phy(void)
|
|
{
|
|
return msm_rpc_client_req(client,
|
|
PM_APP_OTG_SUSPEND_PHY,
|
|
NULL, NULL,
|
|
NULL, NULL, -1);
|
|
|
|
}
|
|
EXPORT_SYMBOL(msm_fsusb_suspend_phy);
|
|
|
|
int msm_fsusb_resume_phy(void)
|
|
{
|
|
return msm_rpc_client_req(client,
|
|
PM_APP_OTG_RESUME_PHY,
|
|
NULL, NULL,
|
|
NULL, NULL, -1);
|
|
|
|
}
|
|
EXPORT_SYMBOL(msm_fsusb_resume_phy);
|
|
|
|
int msm_fsusb_remote_dev_disconnected(void)
|
|
{
|
|
return msm_rpc_client_req(client,
|
|
PM_APP_OTG_DEV_DISCONNECTED,
|
|
NULL, NULL,
|
|
NULL, NULL, -1);
|
|
|
|
}
|
|
EXPORT_SYMBOL(msm_fsusb_remote_dev_disconnected);
|
|
|
|
int msm_fsusb_set_remote_wakeup(void)
|
|
{
|
|
uint32_t data = PM_APP_OTG_SET_WAKEUP;
|
|
|
|
return msm_rpc_client_req(client,
|
|
PM_APP_OTG_SET_WAKEUP,
|
|
msm_fsusb_rpc_arg, &data,
|
|
NULL, NULL, -1);
|
|
|
|
}
|
|
EXPORT_SYMBOL(msm_fsusb_set_remote_wakeup);
|
|
|
|
static int msm_fsusb_acquire_bus(void)
|
|
{
|
|
uint32_t data = PM_APP_OTG_ACQUIRE_BUS;
|
|
|
|
return msm_rpc_client_req(client,
|
|
PM_APP_OTG_ACQUIRE_BUS,
|
|
msm_fsusb_rpc_arg, &data,
|
|
NULL, NULL, -1);
|
|
|
|
}
|
|
|
|
static int msm_fsusb_relinquish_bus(void)
|
|
{
|
|
return msm_rpc_client_req(client,
|
|
PM_APP_OTG_RELINQUISH_BUS,
|
|
NULL, NULL,
|
|
NULL, NULL, -1);
|
|
|
|
}
|
|
|
|
static void msm_fsusb_request_session(void)
|
|
{
|
|
int ret;
|
|
|
|
ret = msm_fsusb_relinquish_bus();
|
|
if (ret < 0)
|
|
pr_err("relinquish_bus rpc failed\n");
|
|
ret = msm_fsusb_acquire_bus();
|
|
if (ret < 0)
|
|
pr_err("acquire_bus rpc failed\n");
|
|
}
|
|
|
|
static int msm_fsusb_cb_func(struct msm_rpc_client *client,
|
|
void *buffer, int in_size)
|
|
{
|
|
struct rpc_request_hdr *req;
|
|
int rc;
|
|
|
|
req = buffer;
|
|
|
|
msm_rpc_start_accepted_reply(client, be32_to_cpu(req->xid),
|
|
RPC_ACCEPTSTAT_SUCCESS);
|
|
rc = msm_rpc_send_accepted_reply(client, 0);
|
|
if (rc) {
|
|
pr_err("%s: sending reply failed: %d\n", __func__, rc);
|
|
return rc;
|
|
}
|
|
|
|
switch (be32_to_cpu(req->procedure)) {
|
|
case PM_APP_OTG_INIT_DONE_CB_PROC: {
|
|
pr_debug("pm_app_otg_init_done callback received");
|
|
msm_fsusb_request_session();
|
|
break;
|
|
}
|
|
case PM_APP_OTG_HOST_INIT_CB_PROC: {
|
|
pr_debug("pm_app_otg_host_init_cb_proc callback received");
|
|
host_ops->request(host_ops->handle, REQUEST_START);
|
|
break;
|
|
}
|
|
case PM_APP_OTG_REMOTE_DEV_LOST_CB_PROC: {
|
|
pr_debug("pm_app_otg_remote_dev_lost_cb_proc"
|
|
" callback received");
|
|
msm_fsusb_acquire_bus();
|
|
host_ops->request(host_ops->handle, REQUEST_STOP);
|
|
break;
|
|
}
|
|
case PM_APP_OTG_REMOTE_DEV_RESUMED_CB_PROC: {
|
|
pr_debug("pm_app_otg_remote_dev_resumed_cb_proc"
|
|
"callback received");
|
|
host_ops->request(host_ops->handle, REQUEST_RESUME);
|
|
break;
|
|
}
|
|
case PM_APP_OTG_ERROR_NOTIFY_CB_PROC: {
|
|
pr_err("pm_app_otg_error_notify_cb_proc callback received");
|
|
break;
|
|
}
|
|
default:
|
|
pr_err("%s: unknown callback(proc = %d) received\n",
|
|
__func__, req->procedure);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int msm_fsusb_rpc_init(struct msm_otg_ops *ops)
|
|
{
|
|
host_ops = ops;
|
|
client = msm_rpc_register_client("fsusb",
|
|
PM_APP_OTG_PROG,
|
|
PM_APP_OTG_VERS, 1,
|
|
msm_fsusb_cb_func);
|
|
if (IS_ERR(client)) {
|
|
pr_err("%s: couldn't open rpc client\n", __func__);
|
|
return PTR_ERR(client);
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
EXPORT_SYMBOL(msm_fsusb_rpc_init);
|
|
|
|
void msm_fsusb_rpc_deinit(void)
|
|
{
|
|
msm_rpc_unregister_client(client);
|
|
}
|
|
EXPORT_SYMBOL(msm_fsusb_rpc_deinit);
|