diff options
author | Jorge Ramirez-Ortiz <jorge@foundries.io> | 2020-06-15 15:11:31 +0200 |
---|---|---|
committer | Jérôme Forissier <jerome@forissier.org> | 2020-08-11 17:08:51 +0200 |
commit | 30c53a72426366d0a4eb4aa396c37b8fd048a82a (patch) | |
tree | c3420ced402773adaf8ebbedb7d21378236c69f6 /core | |
parent | 6ee9f66689c712fa8783785e9e7f2964bcf136e9 (diff) |
core: arm: rpc i2c trampoline driver
Gives OP-TEE access to the i2c buses initialized and controlled by the
REE kernel. This is done by memory mapping a buffer from the thread's
cache where the input or output data is transferred.
Using this mechanism, OP-TEE clients do not have to worry about REE
RUNTIME_PM features switching off clocks from the controllers or
collisions with other bus masters.
This driver assumes that the I2C chip is on a REE statically assigned
bus which value is known to OP-TEE (it will not query/probe the REE).
The slave address can be either seven or ten bits. When using a ten
bit address, the corresponding flag needs to be set in the command and
the REE adapter must support the requested addressing mode.
Signed-off-by: Jorge Ramirez-Ortiz <jorge@foundries.io>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Diffstat (limited to 'core')
-rw-r--r-- | core/arch/arm/kernel/rpc_io_i2c.c | 61 | ||||
-rw-r--r-- | core/arch/arm/kernel/sub.mk | 1 | ||||
-rw-r--r-- | core/include/kernel/rpc_io_i2c.h | 38 | ||||
-rw-r--r-- | core/include/optee_rpc_cmd.h | 22 |
4 files changed, 122 insertions, 0 deletions
diff --git a/core/arch/arm/kernel/rpc_io_i2c.c b/core/arch/arm/kernel/rpc_io_i2c.c new file mode 100644 index 00000000..b48320ad --- /dev/null +++ b/core/arch/arm/kernel/rpc_io_i2c.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2020 Foundries Ltd <jorge@foundries.io> + */ +#include <kernel/rpc_io_i2c.h> +#include <kernel/thread.h> +#include <mm/mobj.h> +#include <string.h> + +/* + * @brief: I2C master transfer request to an I2C slave device. + * It is the responsibility of the caller to validate the number of bytes + * processed by the REE. + * + * @param req: the secure world I2C master request + * @param len: the number of bytes processed by REE + * @returns: TEE_SUCCESS on success, TEE_ERROR_XXX on error. + */ +TEE_Result rpc_io_i2c_transfer(struct rpc_i2c_request *req, size_t *len) +{ + struct thread_param p[4] = { }; + TEE_Result res = TEE_SUCCESS; + struct mobj *mobj = NULL; + uint8_t *va = NULL; + + assert(req); + + if (!len) + return TEE_ERROR_BAD_PARAMETERS; + + va = thread_rpc_shm_cache_alloc(THREAD_SHM_TYPE_KERNEL_PRIVATE, + req->buffer_len, &mobj); + if (!va) + return TEE_ERROR_OUT_OF_MEMORY; + + if (req->mode == RPC_I2C_MODE_WRITE) + memcpy(va, req->buffer, req->buffer_len); + + p[0] = THREAD_PARAM_VALUE(IN, req->mode, req->bus, req->chip); + p[1] = THREAD_PARAM_VALUE(IN, req->flags, 0, 0); + p[2] = THREAD_PARAM_MEMREF(INOUT, mobj, 0, req->buffer_len); + p[3] = THREAD_PARAM_VALUE(OUT, 0, 0, 0); + + res = thread_rpc_cmd(OPTEE_RPC_CMD_I2C_TRANSFER, ARRAY_SIZE(p), p); + if (res != TEE_SUCCESS) + return res; + + /* + * Reporting more bytes than supplied or requested from the I2C chip is + * an REE error + */ + if (p[2].u.value.a > req->buffer_len) + return TEE_ERROR_EXCESS_DATA; + + *len = p[2].u.value.a; + + if (req->mode == RPC_I2C_MODE_READ) + memcpy(req->buffer, va, *len); + + return TEE_SUCCESS; +} diff --git a/core/arch/arm/kernel/sub.mk b/core/arch/arm/kernel/sub.mk index 4190a0c5..71a89553 100644 --- a/core/arch/arm/kernel/sub.mk +++ b/core/arch/arm/kernel/sub.mk @@ -6,6 +6,7 @@ srcs-$(CFG_SECSTOR_TA) += secstor_ta.c endif srcs-y += pseudo_ta.c srcs-y += tee_time.c +srcs-y += rpc_io_i2c.c srcs-y += otp_stubs.c srcs-y += delay.c diff --git a/core/include/kernel/rpc_io_i2c.h b/core/include/kernel/rpc_io_i2c.h new file mode 100644 index 00000000..010f8922 --- /dev/null +++ b/core/include/kernel/rpc_io_i2c.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020 Foundries Ltd <jorge@foundries.io> + */ + +#ifndef __RPC_IO_I2C_H +#define __RPC_IO_I2C_H + +#include <optee_rpc_cmd.h> +#include <tee_api_types.h> + +/* I2C master transfer mode */ +enum rpc_i2c_mode { + RPC_I2C_MODE_WRITE = OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR, + RPC_I2C_MODE_READ = OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD, +}; + +/* I2C master transfer control flags */ +#define RPC_I2C_FLAGS_TEN_BIT OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT + +/* + * The bus identifier defines an implicit ABI with the REE. + * Using this service to access I2C slaves on REE dynamically assigned buses is + * not recommended unless there is a guarantee that the bus identifier will + * persist across reboots. + */ +struct rpc_i2c_request { + enum rpc_i2c_mode mode; + uint16_t bus; /* bus identifier used by the REE [0..n] */ + uint16_t chip; /* slave identifier from its data sheet */ + uint16_t flags; /* transfer flags (ie: ten bit chip address) */ + uint8_t *buffer; + size_t buffer_len; +}; + +TEE_Result rpc_io_i2c_transfer(struct rpc_i2c_request *p, size_t *bytes); + +#endif /* __RPC_IO_I2C_H */ diff --git a/core/include/optee_rpc_cmd.h b/core/include/optee_rpc_cmd.h index 03f80323..3b8d0290 100644 --- a/core/include/optee_rpc_cmd.h +++ b/core/include/optee_rpc_cmd.h @@ -149,6 +149,28 @@ #define OPTEE_RPC_CMD_BENCH_REG 20 /* + * Issue master requests (read and write operations) to an I2C chip. + * + * [in] value[0].a Transfer mode (OPTEE_MSG_RPC_CMD_I2C_TRANSFER_*) + * [in] value[0].b The I2C bus (a.k.a adapter). + * 16 bit field. + * [in] value[0].c The I2C chip (a.k.a address). + * 16 bit field (either 7 or 10 bit effective). + * [in] value[1].a The I2C master control flags (ie, 10 bit address). + * 16 bit field. + * [in/out] memref[2] Buffer used for data transfers. + * [out] value[3].a Number of bytes transferred by the REE. + */ +#define OPTEE_RPC_CMD_I2C_TRANSFER 21 + +/* I2C master transfer modes */ +#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD 0 +#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR 1 + +/* I2C master control flags */ +#define OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT BIT(0) + +/* * Definition of protocol for command OPTEE_RPC_CMD_FS */ |