1// SPDX-License-Identifier: BSD-2-Clause 2/* 3 * Copyright (c) 2020 Foundries.io Ltd 4 */ 5 6#include <dm.h> 7#include <i2c.h> 8#include <tee.h> 9#include "optee_msg.h" 10#include "optee_private.h" 11 12static int check_xfer_flags(struct udevice *chip, uint tee_flags) 13{ 14 uint flags; 15 int ret; 16 17 ret = i2c_get_chip_flags(chip, &flags); 18 if (ret) 19 return ret; 20 21 if (tee_flags & OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT) { 22 if (!(flags & DM_I2C_CHIP_10BIT)) 23 return -EINVAL; 24 } else { 25 if (flags & DM_I2C_CHIP_10BIT) 26 return -EINVAL; 27 } 28 29 return 0; 30} 31 32void optee_suppl_cmd_i2c_transfer(struct optee_msg_arg *arg) 33{ 34 const u8 attr[] = { 35 OPTEE_MSG_ATTR_TYPE_VALUE_INPUT, 36 OPTEE_MSG_ATTR_TYPE_VALUE_INPUT, 37 OPTEE_MSG_ATTR_TYPE_RMEM_INOUT, 38 OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT, 39 }; 40 struct udevice *chip_dev; 41 struct tee_shm *shm; 42 u8 *buf; 43 int ret; 44 45 if (arg->num_params != ARRAY_SIZE(attr) || 46 arg->params[0].attr != attr[0] || 47 arg->params[1].attr != attr[1] || 48 arg->params[2].attr != attr[2] || 49 arg->params[3].attr != attr[3]) { 50 goto bad; 51 } 52 53 shm = (struct tee_shm *)(unsigned long)arg->params[2].u.rmem.shm_ref; 54 buf = shm->addr; 55 if (!buf) 56 goto bad; 57 58 if (i2c_get_chip_for_busnum((int)arg->params[0].u.value.b, 59 (int)arg->params[0].u.value.c, 60 0, &chip_dev)) 61 goto bad; 62 63 if (check_xfer_flags(chip_dev, arg->params[1].u.value.a)) 64 goto bad; 65 66 switch (arg->params[0].u.value.a) { 67 case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD: 68 ret = dm_i2c_read(chip_dev, 0, buf, 69 (size_t)arg->params[2].u.rmem.size); 70 break; 71 case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR: 72 ret = dm_i2c_write(chip_dev, 0, buf, 73 (size_t)arg->params[2].u.rmem.size); 74 break; 75 default: 76 goto bad; 77 } 78 79 if (ret) { 80 arg->ret = TEE_ERROR_COMMUNICATION; 81 } else { 82 arg->params[3].u.value.a = arg->params[2].u.rmem.size; 83 arg->ret = TEE_SUCCESS; 84 } 85 86 return; 87bad: 88 arg->ret = TEE_ERROR_BAD_PARAMETERS; 89} 90