platform: msm: Add USB BAM support to ChipIdea/RMNET
This change adds USB BAM driver which allows USB BAM to communicate with other peripherals'(e.g. QDSS) BAM. Change-Id: Id16613095564b5790076b12dea8aaa2398e65ab7 Signed-off-by: Prasadarao Durvasula <pdurvasu@codeaurora.org> Signed-off-by: Sivasri Kumar Vanka <sivasri@codeaurora.org> Signed-off-by: Swetha Chikkaboraiah <schikk@codeaurora.org>
This commit is contained in:
committed by
Swetha Chikkaboraiah
parent
2302cd24f3
commit
21e70acc99
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2011-2020,2021 The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
#include <linux/usb/msm_hsusb.h>
|
||||||
|
|
||||||
#define USB_THRESHOLD 512
|
#define USB_THRESHOLD 512
|
||||||
#define USB_BAM_MAX_STR_LEN 50
|
#define USB_BAM_MAX_STR_LEN 50
|
||||||
@@ -60,6 +61,9 @@ do { \
|
|||||||
#define log_event_dbg(x, ...) log_event(LOGLEVEL_DEBUG, x, ##__VA_ARGS__)
|
#define log_event_dbg(x, ...) log_event(LOGLEVEL_DEBUG, x, ##__VA_ARGS__)
|
||||||
#define log_event_err(x, ...) log_event(LOGLEVEL_ERR, x, ##__VA_ARGS__)
|
#define log_event_err(x, ...) log_event(LOGLEVEL_ERR, x, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
/* Reset BAM with pipes connected */
|
||||||
|
#define SPS_BAM_FORCE_RESET (1UL << 11)
|
||||||
|
|
||||||
enum usb_bam_event_type {
|
enum usb_bam_event_type {
|
||||||
USB_BAM_EVENT_WAKEUP_PIPE = 0, /* Wake a pipe */
|
USB_BAM_EVENT_WAKEUP_PIPE = 0, /* Wake a pipe */
|
||||||
USB_BAM_EVENT_WAKEUP, /* Wake a bam (first pipe waked) */
|
USB_BAM_EVENT_WAKEUP, /* Wake a bam (first pipe waked) */
|
||||||
@@ -176,6 +180,7 @@ struct msm_usb_bam_data {
|
|||||||
bool reset_on_connect;
|
bool reset_on_connect;
|
||||||
bool reset_on_disconnect;
|
bool reset_on_disconnect;
|
||||||
bool disable_clk_gating;
|
bool disable_clk_gating;
|
||||||
|
bool ignore_core_reset_ack;
|
||||||
u32 override_threshold;
|
u32 override_threshold;
|
||||||
u32 max_mbps_highspeed;
|
u32 max_mbps_highspeed;
|
||||||
u32 max_mbps_superspeed;
|
u32 max_mbps_superspeed;
|
||||||
@@ -219,6 +224,8 @@ struct usb_bam_ctx_type {
|
|||||||
|
|
||||||
static char *bam_enable_strings[MAX_BAMS] = {
|
static char *bam_enable_strings[MAX_BAMS] = {
|
||||||
[DWC3_CTRL] = "ssusb",
|
[DWC3_CTRL] = "ssusb",
|
||||||
|
[CI_CTRL] = "hsusb",
|
||||||
|
[HSIC_CTRL] = "hsic",
|
||||||
};
|
};
|
||||||
|
|
||||||
struct usb_bam_host_info {
|
struct usb_bam_host_info {
|
||||||
@@ -324,15 +331,25 @@ static void __maybe_unused put_timestamp(char *tbuf)
|
|||||||
nanosec_rem);
|
nanosec_rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline enum usb_ctrl get_bam_type_from_core_name(const char *name)
|
void msm_bam_set_hsic_host_dev(struct device *dev)
|
||||||
{
|
{
|
||||||
if (strnstr(name, bam_enable_strings[DWC3_CTRL],
|
if (dev) {
|
||||||
USB_BAM_MAX_STR_LEN) ||
|
/* Hold the device until allowing lpm */
|
||||||
strnstr(name, "dwc3", USB_BAM_MAX_STR_LEN))
|
log_event_dbg("%s: Getting hsic device %pK\n", __func__, dev);
|
||||||
return DWC3_CTRL;
|
pm_runtime_get(dev);
|
||||||
|
} else if (host_info[HSIC_CTRL].dev) {
|
||||||
|
log_event_dbg("%s: Try Putting hsic device %pK, lpm:%d\n",
|
||||||
|
__func__, host_info[HSIC_CTRL].dev,
|
||||||
|
host_info[HSIC_CTRL].in_lpm);
|
||||||
|
/* Just release previous device if not already done */
|
||||||
|
if (!host_info[HSIC_CTRL].in_lpm) {
|
||||||
|
host_info[HSIC_CTRL].in_lpm = true;
|
||||||
|
pm_runtime_put(host_info[HSIC_CTRL].dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log_event_err("%s: invalid BAM name(%s)\n", __func__, name);
|
host_info[HSIC_CTRL].dev = dev;
|
||||||
return -EINVAL;
|
host_info[HSIC_CTRL].in_lpm = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_bam_set_inactivity_timer(enum usb_ctrl bam)
|
static void usb_bam_set_inactivity_timer(enum usb_ctrl bam)
|
||||||
@@ -379,6 +396,156 @@ void msm_bam_set_usb_host_dev(struct device *dev)
|
|||||||
host_info[CI_CTRL].in_lpm = false;
|
host_info[CI_CTRL].in_lpm = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _msm_bam_host_notify_on_resume(enum usb_ctrl bam_type)
|
||||||
|
{
|
||||||
|
struct usb_bam_ctx_type *ctx = &msm_usb_bam[bam_type];
|
||||||
|
|
||||||
|
spin_lock(&ctx->usb_bam_lock);
|
||||||
|
log_event_dbg("%s: enter bam=%s\n", __func__,
|
||||||
|
bam_enable_strings[bam_type]);
|
||||||
|
|
||||||
|
host_info[bam_type].in_lpm = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is called to notify the usb bam driver
|
||||||
|
* that the hsic core and hsic bam hw are fully resumed
|
||||||
|
* and clocked on. Therefore we can now set the inactivity
|
||||||
|
* timer to the hsic bam hw.
|
||||||
|
*/
|
||||||
|
if (ctx->inactivity_timer_ms)
|
||||||
|
usb_bam_set_inactivity_timer(bam_type);
|
||||||
|
|
||||||
|
spin_unlock(&ctx->usb_bam_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* msm_bam_hsic_host_pipe_empty - Check all HSIC host BAM pipe state
|
||||||
|
*
|
||||||
|
* return true if all BAM pipe used for HSIC Host mode is empty.
|
||||||
|
*/
|
||||||
|
bool msm_bam_hsic_host_pipe_empty(void)
|
||||||
|
{
|
||||||
|
struct usb_bam_pipe_connect *pipe_connect;
|
||||||
|
struct sps_pipe *pipe = NULL;
|
||||||
|
enum usb_ctrl bam = HSIC_CTRL;
|
||||||
|
struct usb_bam_ctx_type *ctx = &msm_usb_bam[bam];
|
||||||
|
int i, ret;
|
||||||
|
u32 status;
|
||||||
|
|
||||||
|
log_event_dbg("%s: enter\n", __func__);
|
||||||
|
|
||||||
|
for (i = 0; i < ctx->max_connections; i++) {
|
||||||
|
pipe_connect = &ctx->usb_bam_connections[i];
|
||||||
|
if (pipe_connect->enabled) {
|
||||||
|
pipe = ctx->usb_bam_sps.sps_pipes[i];
|
||||||
|
ret = sps_is_pipe_empty(pipe, &status);
|
||||||
|
if (ret) {
|
||||||
|
log_event_err("%s(): sps_is_pipe_empty() failed\n",
|
||||||
|
__func__);
|
||||||
|
log_event_err("%s(): SRC index(%d), DEST index(%d):\n",
|
||||||
|
__func__,
|
||||||
|
pipe_connect->src_pipe_index,
|
||||||
|
pipe_connect->dst_pipe_index);
|
||||||
|
WARN_ON(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!status) {
|
||||||
|
log_event_err("%s(): pipe is not empty.\n",
|
||||||
|
__func__);
|
||||||
|
log_event_err("%s(): SRC index(%d), DEST index(%d):\n",
|
||||||
|
__func__,
|
||||||
|
pipe_connect->src_pipe_index,
|
||||||
|
pipe_connect->dst_pipe_index);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_event_dbg("%s(): SRC index(%d), DEST index(%d):\n",
|
||||||
|
__func__,
|
||||||
|
pipe_connect->src_pipe_index,
|
||||||
|
pipe_connect->dst_pipe_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pipe)
|
||||||
|
log_event_err("%s: Bam %s has no connected pipes\n", __func__,
|
||||||
|
bam_enable_strings[bam]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(msm_bam_hsic_host_pipe_empty);
|
||||||
|
|
||||||
|
static bool msm_bam_host_lpm_ok(enum usb_ctrl bam_type)
|
||||||
|
{
|
||||||
|
struct usb_bam_ctx_type *ctx = &msm_usb_bam[bam_type];
|
||||||
|
struct usb_bam_pipe_connect *pipe_iter;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
log_event_dbg("%s: enter bam=%s\n", __func__,
|
||||||
|
bam_enable_strings[bam_type]);
|
||||||
|
|
||||||
|
if (!host_info[bam_type].dev)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
log_event_dbg("%s: Starting hsic full suspend sequence\n",
|
||||||
|
__func__);
|
||||||
|
|
||||||
|
log_event_dbg("%s(): checking HSIC Host pipe state\n", __func__);
|
||||||
|
if (!msm_bam_hsic_host_pipe_empty()) {
|
||||||
|
log_event_err("%s(): HSIC HOST Pipe is not empty\n",
|
||||||
|
__func__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HSIC host will go now to lpm */
|
||||||
|
log_event_dbg("%s: vote for suspend hsic %pK\n",
|
||||||
|
__func__, host_info[bam_type].dev);
|
||||||
|
|
||||||
|
for (i = 0; i < ctx->max_connections; i++) {
|
||||||
|
pipe_iter = &ctx->usb_bam_connections[i];
|
||||||
|
if (pipe_iter->bam_type == bam_type &&
|
||||||
|
pipe_iter->enabled && !pipe_iter->suspended)
|
||||||
|
pipe_iter->suspended = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
host_info[bam_type].in_lpm = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool msm_bam_hsic_lpm_ok(void)
|
||||||
|
{
|
||||||
|
log_event_dbg("%s: enter\n", __func__);
|
||||||
|
|
||||||
|
return msm_bam_host_lpm_ok(HSIC_CTRL);
|
||||||
|
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(msm_bam_hsic_lpm_ok);
|
||||||
|
|
||||||
|
void msm_bam_hsic_host_notify_on_resume(void)
|
||||||
|
{
|
||||||
|
_msm_bam_host_notify_on_resume(HSIC_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline enum usb_ctrl get_bam_type_from_core_name(const char *name)
|
||||||
|
{
|
||||||
|
if (strnstr(name, bam_enable_strings[DWC3_CTRL],
|
||||||
|
USB_BAM_MAX_STR_LEN) ||
|
||||||
|
strnstr(name, "dwc3", USB_BAM_MAX_STR_LEN))
|
||||||
|
return DWC3_CTRL;
|
||||||
|
else if (strnstr(name, bam_enable_strings[HSIC_CTRL],
|
||||||
|
USB_BAM_MAX_STR_LEN) ||
|
||||||
|
strnstr(name, "ci13xxx_msm_hsic", USB_BAM_MAX_STR_LEN))
|
||||||
|
return HSIC_CTRL;
|
||||||
|
else if (strnstr(name, bam_enable_strings[CI_CTRL],
|
||||||
|
USB_BAM_MAX_STR_LEN) ||
|
||||||
|
strnstr(name, "ci", USB_BAM_MAX_STR_LEN))
|
||||||
|
return CI_CTRL;
|
||||||
|
|
||||||
|
log_event_err("%s: invalid BAM name(%s)\n", __func__, name);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
static int usb_bam_alloc_buffer(struct usb_bam_pipe_connect *pipe_connect)
|
static int usb_bam_alloc_buffer(struct usb_bam_pipe_connect *pipe_connect)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -389,7 +556,7 @@ static int usb_bam_alloc_buffer(struct usb_bam_pipe_connect *pipe_connect)
|
|||||||
struct sg_table data_sgt, desc_sgt;
|
struct sg_table data_sgt, desc_sgt;
|
||||||
dma_addr_t data_iova, desc_iova;
|
dma_addr_t data_iova, desc_iova;
|
||||||
|
|
||||||
pr_debug("%s: data_fifo size:%x desc_fifo_size:%x\n",
|
log_event_dbg("%s: data_fifo size:%x desc_fifo_size:%x\n",
|
||||||
__func__, pipe_connect->data_fifo_size,
|
__func__, pipe_connect->data_fifo_size,
|
||||||
pipe_connect->desc_fifo_size);
|
pipe_connect->desc_fifo_size);
|
||||||
|
|
||||||
@@ -563,7 +730,7 @@ int usb_bam_free_fifos(enum usb_ctrl cur_bam, u8 idx)
|
|||||||
struct device *dev = &ctx->usb_bam_pdev->dev;
|
struct device *dev = &ctx->usb_bam_pdev->dev;
|
||||||
u32 data_fifo_size;
|
u32 data_fifo_size;
|
||||||
|
|
||||||
pr_debug("%s(): data size:%x desc size:%x\n",
|
log_event_dbg("%s(): data size:%x desc size:%x\n",
|
||||||
__func__, sps_connection->data.size,
|
__func__, sps_connection->data.size,
|
||||||
sps_connection->desc.size);
|
sps_connection->desc.size);
|
||||||
|
|
||||||
@@ -1053,7 +1220,6 @@ static int usb_bam_disconnect_ipa_cons(
|
|||||||
|
|
||||||
if (!pipe_empty) {
|
if (!pipe_empty) {
|
||||||
if (inject_zlt) {
|
if (inject_zlt) {
|
||||||
pr_debug("%s: Inject ZLT\n", __func__);
|
|
||||||
log_event_dbg("%s: Inject ZLT\n", __func__);
|
log_event_dbg("%s: Inject ZLT\n", __func__);
|
||||||
inject_zlt = false;
|
inject_zlt = false;
|
||||||
sps_pipe_inject_zlt(sps_connection->destination,
|
sps_pipe_inject_zlt(sps_connection->destination,
|
||||||
@@ -2045,12 +2211,12 @@ static int usb_bam_set_ipa_perf(enum usb_ctrl cur_bam,
|
|||||||
ctx->usb_bam_data->max_mbps_highspeed;
|
ctx->usb_bam_data->max_mbps_highspeed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Having a max mbps property in dtsi file is a must
|
* Having a max mbps property in dtsi file is a must
|
||||||
* for target with IPA capability.
|
* for target with IPA capability.
|
||||||
*/
|
*/
|
||||||
if (!ipa_rm_perf_prof.max_supported_bandwidth_mbps) {
|
if (!ipa_rm_perf_prof.max_supported_bandwidth_mbps) {
|
||||||
log_event_err("%s: Max mbps is required for speed %d\n",
|
log_event_err("%s: Max mbps is required for speed %d\n",
|
||||||
__func__, usb_connection_speed);
|
__func__, usb_connection_speed);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2059,18 +2225,69 @@ static int usb_bam_set_ipa_perf(enum usb_ctrl cur_bam,
|
|||||||
__func__, ipa_rm_resource_prod[cur_bam],
|
__func__, ipa_rm_resource_prod[cur_bam],
|
||||||
ipa_rm_perf_prof.max_supported_bandwidth_mbps);
|
ipa_rm_perf_prof.max_supported_bandwidth_mbps);
|
||||||
ret = ipa_rm_set_perf_profile(ipa_rm_resource_prod[cur_bam],
|
ret = ipa_rm_set_perf_profile(ipa_rm_resource_prod[cur_bam],
|
||||||
&ipa_rm_perf_prof);
|
&ipa_rm_perf_prof);
|
||||||
} else {
|
} else {
|
||||||
log_event_dbg("%s: vote ipa_perf resource=%d perf=%d mbps\n",
|
log_event_dbg("%s: vote ipa_perf resource=%d perf=%d mbps\n",
|
||||||
__func__, ipa_rm_resource_cons[cur_bam],
|
__func__, ipa_rm_resource_cons[cur_bam],
|
||||||
ipa_rm_perf_prof.max_supported_bandwidth_mbps);
|
ipa_rm_perf_prof.max_supported_bandwidth_mbps);
|
||||||
ret = ipa_rm_set_perf_profile(ipa_rm_resource_cons[cur_bam],
|
ret = ipa_rm_set_perf_profile(ipa_rm_resource_cons[cur_bam],
|
||||||
&ipa_rm_perf_prof);
|
&ipa_rm_perf_prof);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool _hsic_host_bam_resume_core(void)
|
||||||
|
{
|
||||||
|
log_event_dbg("%s: enter\n", __func__);
|
||||||
|
|
||||||
|
/* Exit from "full suspend" in case of hsic host */
|
||||||
|
if (host_info[HSIC_CTRL].dev) {
|
||||||
|
log_event_dbg("%s: Getting hsic device %pK\n", __func__,
|
||||||
|
host_info[HSIC_CTRL].dev);
|
||||||
|
pm_runtime_get(host_info[HSIC_CTRL].dev);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool usb_bam_resume_core(enum usb_ctrl bam_type,
|
||||||
|
enum usb_bam_mode bam_mode)
|
||||||
|
{
|
||||||
|
log_event_dbg("%s: enter bam=%s\n", __func__,
|
||||||
|
bam_enable_strings[bam_type]);
|
||||||
|
|
||||||
|
if ((bam_mode == USB_BAM_DEVICE) || (bam_type != HSIC_CTRL)) {
|
||||||
|
log_event_err("%s: Invalid BAM type %d\n", __func__, bam_type);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _hsic_host_bam_resume_core();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _msm_bam_wait_for_host_prod_granted(enum usb_ctrl bam_type)
|
||||||
|
{
|
||||||
|
struct usb_bam_ctx_type *ctx = &msm_usb_bam[bam_type];
|
||||||
|
|
||||||
|
spin_lock(&ctx->usb_bam_lock);
|
||||||
|
|
||||||
|
log_event_dbg("%s: enter bam=%s\n", __func__,
|
||||||
|
bam_enable_strings[bam_type]);
|
||||||
|
ctx->is_bam_inactivity = false;
|
||||||
|
|
||||||
|
/* Get back to resume state including wakeup ipa */
|
||||||
|
usb_bam_resume_core(bam_type, USB_BAM_HOST);
|
||||||
|
|
||||||
|
spin_unlock(&ctx->usb_bam_lock);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void msm_bam_wait_for_hsic_host_prod_granted(void)
|
||||||
|
{
|
||||||
|
log_event_dbg("%s: start\n", __func__);
|
||||||
|
_msm_bam_wait_for_host_prod_granted(HSIC_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
int usb_bam_connect_ipa(enum usb_ctrl cur_bam,
|
int usb_bam_connect_ipa(enum usb_ctrl cur_bam,
|
||||||
struct usb_bam_connect_ipa_params *ipa_params)
|
struct usb_bam_connect_ipa_params *ipa_params)
|
||||||
{
|
{
|
||||||
@@ -2170,7 +2387,7 @@ int usb_bam_connect_ipa(enum usb_ctrl cur_bam,
|
|||||||
} else {
|
} else {
|
||||||
spin_unlock(&ctx->usb_bam_lock);
|
spin_unlock(&ctx->usb_bam_lock);
|
||||||
if (!ctx->pipes_enabled_per_bam)
|
if (!ctx->pipes_enabled_per_bam)
|
||||||
pr_debug("No BAM reset on connect, just pipe reset\n");
|
log_event_dbg("No BAM reset on connect, just pipe reset\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ipa_params->dir == USB_TO_PEER_PERIPHERAL) {
|
if (ipa_params->dir == USB_TO_PEER_PERIPHERAL) {
|
||||||
@@ -2669,6 +2886,17 @@ static struct msm_usb_bam_data *usb_bam_dt_to_data(
|
|||||||
if (!usb_bam_data)
|
if (!usb_bam_data)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
rc = of_property_read_u32(node, "qcom,bam-type", &bam);
|
||||||
|
if (rc) {
|
||||||
|
log_event_err("%s: bam type is missing in device tree\n",
|
||||||
|
__func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (bam >= MAX_BAMS) {
|
||||||
|
log_event_err("%s: Invalid bam type %d in device tree\n",
|
||||||
|
__func__, bam);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
usb_bam_data->bam_type = bam;
|
usb_bam_data->bam_type = bam;
|
||||||
|
|
||||||
usb_bam_data->reset_on_connect = of_property_read_bool(node,
|
usb_bam_data->reset_on_connect = of_property_read_bool(node,
|
||||||
@@ -2696,7 +2924,8 @@ static struct msm_usb_bam_data *usb_bam_dt_to_data(
|
|||||||
|
|
||||||
rc = of_property_read_u32(node, "qcom,usb-bam-fifo-baseaddr", &addr);
|
rc = of_property_read_u32(node, "qcom,usb-bam-fifo-baseaddr", &addr);
|
||||||
if (rc)
|
if (rc)
|
||||||
pr_debug("%s: Invalid usb base address property\n", __func__);
|
log_event_dbg("%s: Invalid usb base address property\n",
|
||||||
|
__func__);
|
||||||
else
|
else
|
||||||
usb_bam_data->usb_bam_fifo_baseaddr = addr;
|
usb_bam_data->usb_bam_fifo_baseaddr = addr;
|
||||||
|
|
||||||
@@ -2786,7 +3015,7 @@ static struct msm_usb_bam_data *usb_bam_dt_to_data(
|
|||||||
rc = of_property_read_u32(node, "qcom,pipe-connection-type",
|
rc = of_property_read_u32(node, "qcom,pipe-connection-type",
|
||||||
&usb_bam_connections[i].pipe_type);
|
&usb_bam_connections[i].pipe_type);
|
||||||
if (rc)
|
if (rc)
|
||||||
pr_debug("%s: pipe type is defaulting to bam2bam\n",
|
log_event_dbg("%s: pipe type is defaulting to bam2bam\n",
|
||||||
__func__);
|
__func__);
|
||||||
|
|
||||||
of_property_read_u32(node, "qcom,peer-bam-physical-address",
|
of_property_read_u32(node, "qcom,peer-bam-physical-address",
|
||||||
@@ -2832,6 +3061,54 @@ static struct msm_usb_bam_data *usb_bam_dt_to_data(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void msm_usb_bam_update_props(struct sps_bam_props *props,
|
||||||
|
struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct usb_bam_ctx_type *ctx = dev_get_drvdata(&pdev->dev);
|
||||||
|
enum usb_ctrl bam_type = ctx->usb_bam_data->bam_type;
|
||||||
|
struct device *dev;
|
||||||
|
|
||||||
|
props->phys_addr = ctx->io_res->start;
|
||||||
|
props->virt_addr = NULL;
|
||||||
|
props->virt_size = resource_size(ctx->io_res);
|
||||||
|
props->irq = ctx->irq;
|
||||||
|
props->summing_threshold = ctx->usb_bam_data->override_threshold;
|
||||||
|
props->event_threshold = ctx->usb_bam_data->override_threshold;
|
||||||
|
props->num_pipes = ctx->usb_bam_data->usb_bam_num_pipes;
|
||||||
|
props->callback = usb_bam_sps_events;
|
||||||
|
props->user = bam_enable_strings[bam_type];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HSUSB and HSIC Cores don't support RESET ACK signal to BAMs
|
||||||
|
* Hence, let BAM to ignore acknowledge from USB while resetting PIPE
|
||||||
|
*/
|
||||||
|
if (ctx->usb_bam_data->ignore_core_reset_ack && bam_type != DWC3_CTRL)
|
||||||
|
props->options = SPS_BAM_NO_EXT_P_RST;
|
||||||
|
|
||||||
|
if (ctx->usb_bam_data->disable_clk_gating)
|
||||||
|
props->options |= SPS_BAM_NO_LOCAL_CLK_GATING;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HSUSB BAM is not NDP BAM and it must be enabled before
|
||||||
|
* starting peripheral controller to avoid switching USB core mode
|
||||||
|
* from legacy to BAM with ongoing data transfers.
|
||||||
|
*/
|
||||||
|
if (bam_type == CI_CTRL) {
|
||||||
|
log_event_dbg("Register and enable HSUSB BAM\n");
|
||||||
|
props->options |= SPS_BAM_OPT_ENABLE_AT_BOOT;
|
||||||
|
props->options |= SPS_BAM_FORCE_RESET;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev = &ctx->usb_bam_pdev->dev;
|
||||||
|
if (dev && dev->parent && device_property_present(dev->parent, "iommus")
|
||||||
|
&& !device_property_present(dev->parent,
|
||||||
|
"qcom,smmu-s1-bypass")) {
|
||||||
|
pr_info("%s: setting SPS_BAM_SMMU_EN flag with (%s)\n",
|
||||||
|
__func__, dev_name(dev));
|
||||||
|
props->options |= SPS_BAM_SMMU_EN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int usb_bam_init(struct platform_device *pdev)
|
static int usb_bam_init(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -2842,7 +3119,7 @@ static int usb_bam_init(struct platform_device *pdev)
|
|||||||
|
|
||||||
memset(&props, 0, sizeof(props));
|
memset(&props, 0, sizeof(props));
|
||||||
|
|
||||||
pr_debug("%s\n", __func__);
|
log_event_dbg("%s\n", __func__);
|
||||||
|
|
||||||
props.phys_addr = ctx->io_res->start;
|
props.phys_addr = ctx->io_res->start;
|
||||||
props.virt_size = resource_size(ctx->io_res);
|
props.virt_size = resource_size(ctx->io_res);
|
||||||
@@ -3120,6 +3397,54 @@ enum usb_ctrl usb_bam_get_bam_type(const char *core_name)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(usb_bam_get_bam_type);
|
EXPORT_SYMBOL(usb_bam_get_bam_type);
|
||||||
|
|
||||||
|
bool msm_usb_bam_enable(enum usb_ctrl bam, bool bam_enable)
|
||||||
|
{
|
||||||
|
struct msm_usb_bam_data *usb_bam_data;
|
||||||
|
struct usb_bam_ctx_type *ctx = &msm_usb_bam[bam];
|
||||||
|
static bool bam_enabled;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!ctx->usb_bam_pdev)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
usb_bam_data = ctx->usb_bam_data;
|
||||||
|
if (bam != CI_CTRL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (bam_enabled == bam_enable) {
|
||||||
|
log_event_dbg("%s: USB BAM is already %s\n", __func__,
|
||||||
|
bam_enable ? "Registered" : "De-registered");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bam_enable) {
|
||||||
|
struct sps_bam_props props;
|
||||||
|
|
||||||
|
memset(&props, 0, sizeof(props));
|
||||||
|
msm_usb_bam_update_props(&props, ctx->usb_bam_pdev);
|
||||||
|
msm_hw_bam_disable(1);
|
||||||
|
ret = sps_register_bam_device(&props, &ctx->h_bam);
|
||||||
|
bam_enabled = true;
|
||||||
|
if (ret < 0) {
|
||||||
|
log_event_err("%s: register bam error %d\n",
|
||||||
|
__func__, ret);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
log_event_dbg("%s: USB BAM Registered\n", __func__);
|
||||||
|
msm_hw_bam_disable(0);
|
||||||
|
} else {
|
||||||
|
msm_hw_soft_reset();
|
||||||
|
msm_hw_bam_disable(1);
|
||||||
|
sps_device_reset(ctx->h_bam);
|
||||||
|
sps_deregister_bam_device(ctx->h_bam);
|
||||||
|
log_event_dbg("%s: USB BAM De-registered\n", __func__);
|
||||||
|
bam_enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(msm_usb_bam_enable);
|
||||||
|
|
||||||
static int usb_bam_remove(struct platform_device *pdev)
|
static int usb_bam_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct usb_bam_ctx_type *ctx = dev_get_drvdata(&pdev->dev);
|
struct usb_bam_ctx_type *ctx = dev_get_drvdata(&pdev->dev);
|
||||||
|
|||||||
@@ -313,6 +313,12 @@ int usb_bam_alloc_fifos(enum usb_ctrl cur_bam, u8 idx);
|
|||||||
int usb_bam_free_fifos(enum usb_ctrl cur_bam, u8 idx);
|
int usb_bam_free_fifos(enum usb_ctrl cur_bam, u8 idx);
|
||||||
int get_qdss_bam_info(enum usb_ctrl cur_bam, u8 idx,
|
int get_qdss_bam_info(enum usb_ctrl cur_bam, u8 idx,
|
||||||
phys_addr_t *p_addr, u32 *bam_size);
|
phys_addr_t *p_addr, u32 *bam_size);
|
||||||
|
bool msm_usb_bam_enable(enum usb_ctrl ctrl, bool bam_enable);
|
||||||
|
void msm_bam_set_hsic_host_dev(struct device *dev);
|
||||||
|
bool msm_bam_hsic_lpm_ok(void);
|
||||||
|
void msm_bam_hsic_host_notify_on_resume(void);
|
||||||
|
void msm_bam_wait_for_hsic_host_prod_granted(void);
|
||||||
|
bool msm_bam_hsic_host_pipe_empty(void);
|
||||||
#else
|
#else
|
||||||
static inline int usb_bam_connect(enum usb_ctrl bam, u8 idx, u32 *bam_pipe_idx,
|
static inline int usb_bam_connect(enum usb_ctrl bam, u8 idx, u32 *bam_pipe_idx,
|
||||||
unsigned long iova)
|
unsigned long iova)
|
||||||
@@ -415,6 +421,22 @@ static inline bool msm_usb_bam_enable(enum usb_ctrl ctrl, bool bam_enable)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void msm_bam_set_hsic_host_dev(struct device *dev) {}
|
||||||
|
|
||||||
|
static inline bool msm_bam_hsic_lpm_ok(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void msm_bam_hsic_host_notify_on_resume(void) {}
|
||||||
|
|
||||||
|
static inline void msm_bam_wait_for_hsic_host_prod_granted(void) {}
|
||||||
|
|
||||||
|
static inline bool msm_bam_hsic_host_pipe_empty(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* CONFIG_PM */
|
/* CONFIG_PM */
|
||||||
|
|||||||
Reference in New Issue
Block a user