spi-geni-qcom: Add shared_ee dtsi property for spi driver
When shared_ee dtsi flag is set then don't depend on the shared_se checks in prepare/unprepare transfer hardware and runtime resume/suspend APIs of spi driver. Also use runtime resume/suspend calls from prepare/unprepare message so that dual EE use case for spi will not be effected. This change is to help in the cases where spi can be used from secure and non-secure use cases. Spi framework calls unprepare transfer hardware from a kthread after the spi_pump_message call is completed and by that time spi driver might be getting used from a secure use case and at the same time unprepare transfer hardware is selecting the pinctrl to sleep state. Change-Id: Ic8ea126ca5cddd3ca45c080a39841dd6ec1f6760 Signed-off-by: Prudhvi Yarlagadda <pyarlaga@codeaurora.org>
This commit is contained in:
parent
b7cbb1aa77
commit
072f1aabae
1 changed files with 90 additions and 19 deletions
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -148,7 +148,8 @@ struct spi_geni_master {
|
|||
int num_rx_eot;
|
||||
int num_xfers;
|
||||
void *ipc;
|
||||
bool shared_se;
|
||||
bool shared_se; /* GSI Mode */
|
||||
bool shared_ee; /* Dual EE use case */
|
||||
bool dis_autosuspend;
|
||||
bool cmd_done;
|
||||
};
|
||||
|
@ -717,6 +718,32 @@ static int spi_geni_prepare_message(struct spi_master *spi,
|
|||
{
|
||||
int ret = 0;
|
||||
struct spi_geni_master *mas = spi_master_get_devdata(spi);
|
||||
int count;
|
||||
|
||||
if (mas->shared_ee) {
|
||||
if (mas->setup) {
|
||||
ret = pm_runtime_get_sync(mas->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(mas->dev,
|
||||
"%s:pm_runtime_get_sync failed %d\n",
|
||||
__func__, ret);
|
||||
pm_runtime_put_noidle(mas->dev);
|
||||
goto exit_prepare_message;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
if (mas->dis_autosuspend) {
|
||||
count =
|
||||
atomic_read(&mas->dev->power.usage_count);
|
||||
if (count <= 0)
|
||||
GENI_SE_ERR(mas->ipc, false, NULL,
|
||||
"resume usage count mismatch:%d",
|
||||
count);
|
||||
}
|
||||
} else {
|
||||
mas->setup = true;
|
||||
}
|
||||
}
|
||||
|
||||
mas->cur_xfer_mode = select_xfer_mode(spi, spi_msg);
|
||||
|
||||
|
@ -734,6 +761,7 @@ static int spi_geni_prepare_message(struct spi_master *spi,
|
|||
ret = setup_fifo_params(spi_msg->spi, spi);
|
||||
}
|
||||
|
||||
exit_prepare_message:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -741,11 +769,27 @@ static int spi_geni_unprepare_message(struct spi_master *spi_mas,
|
|||
struct spi_message *spi_msg)
|
||||
{
|
||||
struct spi_geni_master *mas = spi_master_get_devdata(spi_mas);
|
||||
int count = 0;
|
||||
|
||||
mas->cur_speed_hz = 0;
|
||||
mas->cur_word_len = 0;
|
||||
if (mas->cur_xfer_mode == GSI_DMA)
|
||||
spi_geni_unmap_buf(mas, spi_msg);
|
||||
|
||||
if (mas->shared_ee) {
|
||||
if (mas->dis_autosuspend) {
|
||||
pm_runtime_put_sync(mas->dev);
|
||||
count = atomic_read(&mas->dev->power.usage_count);
|
||||
if (count < 0)
|
||||
GENI_SE_ERR(mas->ipc, false, NULL,
|
||||
"suspend usage count mismatch:%d",
|
||||
count);
|
||||
} else {
|
||||
pm_runtime_mark_last_busy(mas->dev);
|
||||
pm_runtime_put_autosuspend(mas->dev);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -758,7 +802,7 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi)
|
|||
|
||||
/* Adjust the IB based on the max speed of the slave.*/
|
||||
rsc->ib = max_speed * DEFAULT_BUS_WIDTH;
|
||||
if (mas->shared_se) {
|
||||
if (mas->shared_se && !mas->shared_ee) {
|
||||
struct se_geni_rsc *rsc;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -770,21 +814,24 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi)
|
|||
"%s: Error %d pinctrl_select_state\n", __func__, ret);
|
||||
}
|
||||
|
||||
if (!mas->setup || !mas->shared_ee) {
|
||||
ret = pm_runtime_get_sync(mas->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(mas->dev, "%s:Error enabling SE resources %d\n",
|
||||
dev_err(mas->dev,
|
||||
"%s:pm_runtime_get_sync failed %d\n",
|
||||
__func__, ret);
|
||||
pm_runtime_put_noidle(mas->dev);
|
||||
goto exit_prepare_transfer_hardware;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
if (mas->dis_autosuspend) {
|
||||
count = atomic_read(&mas->dev->power.usage_count);
|
||||
if (count <= 0)
|
||||
GENI_SE_ERR(mas->ipc, false, NULL,
|
||||
"resume usage count mismatch:%d", count);
|
||||
}
|
||||
}
|
||||
if (unlikely(!mas->setup)) {
|
||||
int proto = get_se_proto(mas->base);
|
||||
unsigned int major;
|
||||
|
@ -857,6 +904,7 @@ setup_ipc:
|
|||
dev_info(mas->dev, "tx_fifo %d rx_fifo %d tx_width %d\n",
|
||||
mas->tx_fifo_depth, mas->rx_fifo_depth,
|
||||
mas->tx_fifo_width);
|
||||
if (!mas->shared_ee)
|
||||
mas->setup = true;
|
||||
hw_ver = geni_se_qupv3_hw_version(mas->wrapper_dev, &major,
|
||||
&minor, &step);
|
||||
|
@ -886,6 +934,9 @@ static int spi_geni_unprepare_transfer_hardware(struct spi_master *spi)
|
|||
struct spi_geni_master *mas = spi_master_get_devdata(spi);
|
||||
int count = 0;
|
||||
|
||||
if (mas->shared_ee)
|
||||
return 0;
|
||||
|
||||
if (mas->shared_se) {
|
||||
struct se_geni_rsc *rsc;
|
||||
int ret = 0;
|
||||
|
@ -908,6 +959,7 @@ static int spi_geni_unprepare_transfer_hardware(struct spi_master *spi)
|
|||
pm_runtime_mark_last_busy(mas->dev);
|
||||
pm_runtime_put_autosuspend(mas->dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1459,6 +1511,15 @@ static int spi_geni_probe(struct platform_device *pdev)
|
|||
geni_mas->dis_autosuspend =
|
||||
of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,disable-autosuspend");
|
||||
/*
|
||||
* This property will be set when spi is being used from
|
||||
* dual Execution Environments unlike shared_se flag
|
||||
* which is set if SE is in GSI mode.
|
||||
*/
|
||||
geni_mas->shared_ee =
|
||||
of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,shared_ee");
|
||||
|
||||
geni_mas->phys_addr = res->start;
|
||||
geni_mas->size = resource_size(res);
|
||||
geni_mas->base = devm_ioremap(&pdev->dev, res->start,
|
||||
|
@ -1536,14 +1597,19 @@ static int spi_geni_runtime_suspend(struct device *dev)
|
|||
struct spi_master *spi = get_spi_master(dev);
|
||||
struct spi_geni_master *geni_mas = spi_master_get_devdata(spi);
|
||||
|
||||
if (geni_mas->shared_ee)
|
||||
goto exit_rt_suspend;
|
||||
|
||||
if (geni_mas->shared_se) {
|
||||
ret = se_geni_clks_off(&geni_mas->spi_rsc);
|
||||
if (ret)
|
||||
GENI_SE_ERR(geni_mas->ipc, false, NULL,
|
||||
"%s: Error %d turning off clocks\n", __func__, ret);
|
||||
} else {
|
||||
ret = se_geni_resources_off(&geni_mas->spi_rsc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
exit_rt_suspend:
|
||||
ret = se_geni_resources_off(&geni_mas->spi_rsc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1553,14 +1619,19 @@ static int spi_geni_runtime_resume(struct device *dev)
|
|||
struct spi_master *spi = get_spi_master(dev);
|
||||
struct spi_geni_master *geni_mas = spi_master_get_devdata(spi);
|
||||
|
||||
if (geni_mas->shared_ee)
|
||||
goto exit_rt_resume;
|
||||
|
||||
if (geni_mas->shared_se) {
|
||||
ret = se_geni_clks_on(&geni_mas->spi_rsc);
|
||||
if (ret)
|
||||
GENI_SE_ERR(geni_mas->ipc, false, NULL,
|
||||
"%s: Error %d turning on clocks\n", __func__, ret);
|
||||
} else {
|
||||
ret = se_geni_resources_on(&geni_mas->spi_rsc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
exit_rt_resume:
|
||||
ret = se_geni_resources_on(&geni_mas->spi_rsc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue