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