Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f5bcbeb4 authored by Prudhvi Yarlagadda's avatar Prudhvi Yarlagadda Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarPrudhvi Yarlagadda <pyarlaga@codeaurora.org>
parent 2b3f18e8
Loading
Loading
Loading
Loading
+90 −19
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
// 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_rx_eot;
	int num_xfers;
	int num_xfers;
	void *ipc;
	void *ipc;
	bool shared_se;
	bool shared_se; /* GSI Mode */
	bool shared_ee; /* Dual EE use case */
	bool dis_autosuspend;
	bool dis_autosuspend;
	bool cmd_done;
	bool cmd_done;
};
};
@@ -717,6 +718,32 @@ static int spi_geni_prepare_message(struct spi_master *spi,
{
{
	int ret = 0;
	int ret = 0;
	struct spi_geni_master *mas = spi_master_get_devdata(spi);
	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);
	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);
		ret = setup_fifo_params(spi_msg->spi, spi);
	}
	}


exit_prepare_message:
	return ret;
	return ret;
}
}


@@ -741,11 +769,27 @@ static int spi_geni_unprepare_message(struct spi_master *spi_mas,
					struct spi_message *spi_msg)
					struct spi_message *spi_msg)
{
{
	struct spi_geni_master *mas = spi_master_get_devdata(spi_mas);
	struct spi_geni_master *mas = spi_master_get_devdata(spi_mas);
	int count = 0;


	mas->cur_speed_hz = 0;
	mas->cur_speed_hz = 0;
	mas->cur_word_len = 0;
	mas->cur_word_len = 0;
	if (mas->cur_xfer_mode == GSI_DMA)
	if (mas->cur_xfer_mode == GSI_DMA)
		spi_geni_unmap_buf(mas, spi_msg);
		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;
	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.*/
	/* Adjust the IB based on the max speed of the slave.*/
	rsc->ib = max_speed * DEFAULT_BUS_WIDTH;
	rsc->ib = max_speed * DEFAULT_BUS_WIDTH;
	if (mas->shared_se) {
	if (mas->shared_se && !mas->shared_ee) {
		struct se_geni_rsc *rsc;
		struct se_geni_rsc *rsc;
		int ret = 0;
		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);
			"%s: Error %d pinctrl_select_state\n", __func__, ret);
	}
	}


	if (!mas->setup || !mas->shared_ee) {
		ret = pm_runtime_get_sync(mas->dev);
		ret = pm_runtime_get_sync(mas->dev);
		if (ret < 0) {
		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);
							__func__, ret);
			pm_runtime_put_noidle(mas->dev);
			pm_runtime_put_noidle(mas->dev);
			goto exit_prepare_transfer_hardware;
			goto exit_prepare_transfer_hardware;
	} else {
		ret = 0;
		}
		}
		ret = 0;

		if (mas->dis_autosuspend) {
		if (mas->dis_autosuspend) {
			count = atomic_read(&mas->dev->power.usage_count);
			count = atomic_read(&mas->dev->power.usage_count);
			if (count <= 0)
			if (count <= 0)
				GENI_SE_ERR(mas->ipc, false, NULL,
				GENI_SE_ERR(mas->ipc, false, NULL,
				"resume usage count mismatch:%d", count);
				"resume usage count mismatch:%d", count);
		}
		}
	}
	if (unlikely(!mas->setup)) {
	if (unlikely(!mas->setup)) {
		int proto = get_se_proto(mas->base);
		int proto = get_se_proto(mas->base);
		unsigned int major;
		unsigned int major;
@@ -857,6 +904,7 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi)
		dev_info(mas->dev, "tx_fifo %d rx_fifo %d tx_width %d\n",
		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_depth, mas->rx_fifo_depth,
			mas->tx_fifo_width);
			mas->tx_fifo_width);
		if (!mas->shared_ee)
			mas->setup = true;
			mas->setup = true;
		hw_ver = geni_se_qupv3_hw_version(mas->wrapper_dev, &major,
		hw_ver = geni_se_qupv3_hw_version(mas->wrapper_dev, &major,
							&minor, &step);
							&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);
	struct spi_geni_master *mas = spi_master_get_devdata(spi);
	int count = 0;
	int count = 0;


	if (mas->shared_ee)
		return 0;

	if (mas->shared_se) {
	if (mas->shared_se) {
		struct se_geni_rsc *rsc;
		struct se_geni_rsc *rsc;
		int ret = 0;
		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_mark_last_busy(mas->dev);
		pm_runtime_put_autosuspend(mas->dev);
		pm_runtime_put_autosuspend(mas->dev);
	}
	}

	return 0;
	return 0;
}
}


@@ -1459,6 +1511,15 @@ static int spi_geni_probe(struct platform_device *pdev)
	geni_mas->dis_autosuspend =
	geni_mas->dis_autosuspend =
		of_property_read_bool(pdev->dev.of_node,
		of_property_read_bool(pdev->dev.of_node,
				"qcom,disable-autosuspend");
				"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->phys_addr = res->start;
	geni_mas->size = resource_size(res);
	geni_mas->size = resource_size(res);
	geni_mas->base = devm_ioremap(&pdev->dev, res->start,
	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_master *spi = get_spi_master(dev);
	struct spi_geni_master *geni_mas = spi_master_get_devdata(spi);
	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) {
	if (geni_mas->shared_se) {
		ret = se_geni_clks_off(&geni_mas->spi_rsc);
		ret = se_geni_clks_off(&geni_mas->spi_rsc);
		if (ret)
		if (ret)
			GENI_SE_ERR(geni_mas->ipc, false, NULL,
			GENI_SE_ERR(geni_mas->ipc, false, NULL,
			"%s: Error %d turning off clocks\n", __func__, ret);
			"%s: Error %d turning off clocks\n", __func__, ret);
	} else {
		return ret;
		ret = se_geni_resources_off(&geni_mas->spi_rsc);
	}
	}

exit_rt_suspend:
	ret = se_geni_resources_off(&geni_mas->spi_rsc);
	return ret;
	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_master *spi = get_spi_master(dev);
	struct spi_geni_master *geni_mas = spi_master_get_devdata(spi);
	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) {
	if (geni_mas->shared_se) {
		ret = se_geni_clks_on(&geni_mas->spi_rsc);
		ret = se_geni_clks_on(&geni_mas->spi_rsc);
		if (ret)
		if (ret)
			GENI_SE_ERR(geni_mas->ipc, false, NULL,
			GENI_SE_ERR(geni_mas->ipc, false, NULL,
			"%s: Error %d turning on clocks\n", __func__, ret);
			"%s: Error %d turning on clocks\n", __func__, ret);
	} else {
		return ret;
		ret = se_geni_resources_on(&geni_mas->spi_rsc);
	}
	}

exit_rt_resume:
	ret = se_geni_resources_on(&geni_mas->spi_rsc);
	return ret;
	return ret;
}
}