| /* 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); |