Unverified Commit 3783cdc1 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'qcom-drivers-for-6.18-2' of...

Merge tag 'qcom-drivers-for-6.18-2' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into soc/drivers

More Qualcomm device driver updates for v6.18

Introduce support for loading firmware into the QUP serial engines from
Linux, which allows deferring selection of which protocol (uart, i2c,
spi, etc) a given SE should have until the OS loads.

Also introduce the "object invoke" interface in the SCM driver, to
provide interface to the Qualcomm TEE driver.

* tag 'qcom-drivers-for-6.18-2' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux:
  serial: qcom-geni: Load UART qup Firmware from linux side
  spi: geni-qcom: Load spi qup Firmware from linux side
  i2c: qcom-geni: Load i2c qup Firmware from linux side
  soc: qcom: geni-se: Add support to load QUP SE Firmware via Linux subsystem
  soc: qcom: geni-se: Cleanup register defines and update copyright
  dt-bindings: qcom: se-common: Add QUP Peripheral-specific properties for I2C, SPI, and SERIAL bus
  firmware: qcom: scm: add support for object invocation
  firmware: qcom: tzmem: export shm_bridge create/delete

Link: https://lore.kernel.org/r/20250921020225.595403-1-andersson@kernel.org


Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 9674bc88 3f170730
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ required:

allOf:
  - $ref: /schemas/i2c/i2c-controller.yaml#
  - $ref: /schemas/soc/qcom/qcom,se-common-props.yaml#
  - if:
      properties:
        compatible:
+1 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ maintainers:

allOf:
  - $ref: /schemas/serial/serial.yaml#
  - $ref: /schemas/soc/qcom/qcom,se-common-props.yaml#

properties:
  compatible:
+26 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/soc/qcom/qcom,se-common-props.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: QUP Peripheral-specific properties for I2C, SPI and SERIAL bus

description:
  The Generic Interface (GENI) based Qualcomm Universal Peripheral (QUP) is
  a programmable module that supports a wide range of serial interfaces
  such as UART, SPI, I2C, I3C, etc. This defines the common properties used
  across QUP-supported peripherals.

maintainers:
  - Mukesh Kumar Savaliya <mukesh.savaliya@oss.qualcomm.com>
  - Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>

properties:
  qcom,enable-gsi-dma:
    $ref: /schemas/types.yaml#/definitions/flag
    description:
      Configure the Serial Engine (SE) to transfer data in QCOM GPI DMA mode.
      By default, FIFO mode (PIO/CPU DMA) will be selected.

additionalProperties: true
+1 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ description:

allOf:
  - $ref: /schemas/spi/spi-controller.yaml#
  - $ref: /schemas/soc/qcom/qcom,se-common-props.yaml#

properties:
  compatible:
+119 −0
Original line number Diff line number Diff line
@@ -2097,6 +2097,122 @@ static int qcom_scm_qseecom_init(struct qcom_scm *scm)

#endif /* CONFIG_QCOM_QSEECOM */

/**
 * qcom_scm_qtee_invoke_smc() - Invoke a QTEE object.
 * @inbuf: start address of memory area used for inbound buffer.
 * @inbuf_size: size of the memory area used for inbound buffer.
 * @outbuf: start address of memory area used for outbound buffer.
 * @outbuf_size: size of the memory area used for outbound buffer.
 * @result: result of QTEE object invocation.
 * @response_type: response type returned by QTEE.
 *
 * @response_type determines how the contents of @inbuf and @outbuf
 * should be processed.
 *
 * Return: On success, return 0 or <0 on failure.
 */
int qcom_scm_qtee_invoke_smc(phys_addr_t inbuf, size_t inbuf_size,
			     phys_addr_t outbuf, size_t outbuf_size,
			     u64 *result, u64 *response_type)
{
	struct qcom_scm_desc desc = {
		.svc = QCOM_SCM_SVC_SMCINVOKE,
		.cmd = QCOM_SCM_SMCINVOKE_INVOKE,
		.owner = ARM_SMCCC_OWNER_TRUSTED_OS,
		.args[0] = inbuf,
		.args[1] = inbuf_size,
		.args[2] = outbuf,
		.args[3] = outbuf_size,
		.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RW, QCOM_SCM_VAL,
					 QCOM_SCM_RW, QCOM_SCM_VAL),
	};
	struct qcom_scm_res res;
	int ret;

	ret = qcom_scm_call(__scm->dev, &desc, &res);
	if (ret)
		return ret;

	if (response_type)
		*response_type = res.result[0];

	if (result)
		*result = res.result[1];

	return 0;
}
EXPORT_SYMBOL(qcom_scm_qtee_invoke_smc);

/**
 * qcom_scm_qtee_callback_response() - Submit response for callback request.
 * @buf: start address of memory area used for outbound buffer.
 * @buf_size: size of the memory area used for outbound buffer.
 * @result: Result of QTEE object invocation.
 * @response_type: Response type returned by QTEE.
 *
 * @response_type determines how the contents of @buf should be processed.
 *
 * Return: On success, return 0 or <0 on failure.
 */
int qcom_scm_qtee_callback_response(phys_addr_t buf, size_t buf_size,
				    u64 *result, u64 *response_type)
{
	struct qcom_scm_desc desc = {
		.svc = QCOM_SCM_SVC_SMCINVOKE,
		.cmd = QCOM_SCM_SMCINVOKE_CB_RSP,
		.owner = ARM_SMCCC_OWNER_TRUSTED_OS,
		.args[0] = buf,
		.args[1] = buf_size,
		.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW, QCOM_SCM_VAL),
	};
	struct qcom_scm_res res;
	int ret;

	ret = qcom_scm_call(__scm->dev, &desc, &res);
	if (ret)
		return ret;

	if (response_type)
		*response_type = res.result[0];

	if (result)
		*result = res.result[1];

	return 0;
}
EXPORT_SYMBOL(qcom_scm_qtee_callback_response);

static void qcom_scm_qtee_free(void *data)
{
	struct platform_device *qtee_dev = data;

	platform_device_unregister(qtee_dev);
}

static void qcom_scm_qtee_init(struct qcom_scm *scm)
{
	struct platform_device *qtee_dev;
	u64 result, response_type;
	int ret;

	/*
	 * Probe for smcinvoke support. This will fail due to invalid buffers,
	 * but first, it checks whether the call is supported in QTEE syscall
	 * handler. If it is not supported, -EIO is returned.
	 */
	ret = qcom_scm_qtee_invoke_smc(0, 0, 0, 0, &result, &response_type);
	if (ret == -EIO)
		return;

	/* Setup QTEE interface device. */
	qtee_dev = platform_device_register_data(scm->dev, "qcomtee",
						 PLATFORM_DEVID_NONE, NULL, 0);
	if (IS_ERR(qtee_dev))
		return;

	devm_add_action_or_reset(scm->dev, qcom_scm_qtee_free, qtee_dev);
}

/**
 * qcom_scm_is_available() - Checks if SCM is available
 */
@@ -2329,6 +2445,9 @@ static int qcom_scm_probe(struct platform_device *pdev)
	ret = qcom_scm_qseecom_init(scm);
	WARN(ret < 0, "failed to initialize qseecom: %d\n", ret);

	/* Initialize the QTEE object interface. */
	qcom_scm_qtee_init(scm);

	return 0;
}

Loading