cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cmd_v2.c (8569B)


      1// SPDX-License-Identifier: BSD-3-Clause
      2/*
      3 * Copyright (c) 2020, MIPI Alliance, Inc.
      4 *
      5 * Author: Nicolas Pitre <npitre@baylibre.com>
      6 *
      7 * I3C HCI v2.0 Command Descriptor Handling
      8 *
      9 * Note: The I3C HCI v2.0 spec is still in flux. The code here will change.
     10 */
     11
     12#include <linux/bitfield.h>
     13#include <linux/i3c/master.h>
     14
     15#include "hci.h"
     16#include "cmd.h"
     17#include "xfer_mode_rate.h"
     18
     19
     20/*
     21 * Unified Data Transfer Command
     22 */
     23
     24#define CMD_0_ATTR_U			FIELD_PREP(CMD_0_ATTR, 0x4)
     25
     26#define CMD_U3_HDR_TSP_ML_CTRL(v)	FIELD_PREP(W3_MASK(107, 104), v)
     27#define CMD_U3_IDB4(v)			FIELD_PREP(W3_MASK(103,  96), v)
     28#define CMD_U3_HDR_CMD(v)		FIELD_PREP(W3_MASK(103,  96), v)
     29#define CMD_U2_IDB3(v)			FIELD_PREP(W2_MASK( 95,  88), v)
     30#define CMD_U2_HDR_BT(v)		FIELD_PREP(W2_MASK( 95,  88), v)
     31#define CMD_U2_IDB2(v)			FIELD_PREP(W2_MASK( 87,  80), v)
     32#define CMD_U2_BT_CMD2(v)		FIELD_PREP(W2_MASK( 87,  80), v)
     33#define CMD_U2_IDB1(v)			FIELD_PREP(W2_MASK( 79,  72), v)
     34#define CMD_U2_BT_CMD1(v)		FIELD_PREP(W2_MASK( 79,  72), v)
     35#define CMD_U2_IDB0(v)			FIELD_PREP(W2_MASK( 71,  64), v)
     36#define CMD_U2_BT_CMD0(v)		FIELD_PREP(W2_MASK( 71,  64), v)
     37#define CMD_U1_ERR_HANDLING(v)		FIELD_PREP(W1_MASK( 63,  62), v)
     38#define CMD_U1_ADD_FUNC(v)		FIELD_PREP(W1_MASK( 61,  56), v)
     39#define CMD_U1_COMBO_XFER			   W1_BIT_( 55)
     40#define CMD_U1_DATA_LENGTH(v)		FIELD_PREP(W1_MASK( 53,  32), v)
     41#define CMD_U0_TOC				   W0_BIT_( 31)
     42#define CMD_U0_ROC				   W0_BIT_( 30)
     43#define CMD_U0_MAY_YIELD			   W0_BIT_( 29)
     44#define CMD_U0_NACK_RCNT(v)		FIELD_PREP(W0_MASK( 28,  27), v)
     45#define CMD_U0_IDB_COUNT(v)		FIELD_PREP(W0_MASK( 26,  24), v)
     46#define CMD_U0_MODE_INDEX(v)		FIELD_PREP(W0_MASK( 22,  18), v)
     47#define CMD_U0_XFER_RATE(v)		FIELD_PREP(W0_MASK( 17,  15), v)
     48#define CMD_U0_DEV_ADDRESS(v)		FIELD_PREP(W0_MASK( 14,   8), v)
     49#define CMD_U0_RnW				   W0_BIT_(  7)
     50#define CMD_U0_TID(v)			FIELD_PREP(W0_MASK(  6,   3), v)
     51
     52/*
     53 * Address Assignment Command
     54 */
     55
     56#define CMD_0_ATTR_A			FIELD_PREP(CMD_0_ATTR, 0x2)
     57
     58#define CMD_A1_DATA_LENGTH(v)		FIELD_PREP(W1_MASK( 53,  32), v)
     59#define CMD_A0_TOC				   W0_BIT_( 31)
     60#define CMD_A0_ROC				   W0_BIT_( 30)
     61#define CMD_A0_XFER_RATE(v)		FIELD_PREP(W0_MASK( 17,  15), v)
     62#define CMD_A0_ASSIGN_ADDRESS(v)	FIELD_PREP(W0_MASK( 14,   8), v)
     63#define CMD_A0_TID(v)			FIELD_PREP(W0_MASK(  6,   3), v)
     64
     65
     66static unsigned int get_i3c_rate_idx(struct i3c_hci *hci)
     67{
     68	struct i3c_bus *bus = i3c_master_get_bus(&hci->master);
     69
     70	if (bus->scl_rate.i3c >= 12000000)
     71		return XFERRATE_I3C_SDR0;
     72	if (bus->scl_rate.i3c > 8000000)
     73		return XFERRATE_I3C_SDR1;
     74	if (bus->scl_rate.i3c > 6000000)
     75		return XFERRATE_I3C_SDR2;
     76	if (bus->scl_rate.i3c > 4000000)
     77		return XFERRATE_I3C_SDR3;
     78	if (bus->scl_rate.i3c > 2000000)
     79		return XFERRATE_I3C_SDR4;
     80	return XFERRATE_I3C_SDR_FM_FMP;
     81}
     82
     83static unsigned int get_i2c_rate_idx(struct i3c_hci *hci)
     84{
     85	struct i3c_bus *bus = i3c_master_get_bus(&hci->master);
     86
     87	if (bus->scl_rate.i2c >= 1000000)
     88		return XFERRATE_I2C_FMP;
     89	return XFERRATE_I2C_FM;
     90}
     91
     92static void hci_cmd_v2_prep_private_xfer(struct i3c_hci *hci,
     93					 struct hci_xfer *xfer,
     94					 u8 addr, unsigned int mode,
     95					 unsigned int rate)
     96{
     97	u8 *data = xfer->data;
     98	unsigned int data_len = xfer->data_len;
     99	bool rnw = xfer->rnw;
    100
    101	xfer->cmd_tid = hci_get_tid();
    102
    103	if (!rnw && data_len <= 5) {
    104		xfer->cmd_desc[0] =
    105			CMD_0_ATTR_U |
    106			CMD_U0_TID(xfer->cmd_tid) |
    107			CMD_U0_DEV_ADDRESS(addr) |
    108			CMD_U0_XFER_RATE(rate) |
    109			CMD_U0_MODE_INDEX(mode) |
    110			CMD_U0_IDB_COUNT(data_len);
    111		xfer->cmd_desc[1] =
    112			CMD_U1_DATA_LENGTH(0);
    113		xfer->cmd_desc[2] = 0;
    114		xfer->cmd_desc[3] = 0;
    115		switch (data_len) {
    116		case 5:
    117			xfer->cmd_desc[3] |= CMD_U3_IDB4(data[4]);
    118			fallthrough;
    119		case 4:
    120			xfer->cmd_desc[2] |= CMD_U2_IDB3(data[3]);
    121			fallthrough;
    122		case 3:
    123			xfer->cmd_desc[2] |= CMD_U2_IDB2(data[2]);
    124			fallthrough;
    125		case 2:
    126			xfer->cmd_desc[2] |= CMD_U2_IDB1(data[1]);
    127			fallthrough;
    128		case 1:
    129			xfer->cmd_desc[2] |= CMD_U2_IDB0(data[0]);
    130			fallthrough;
    131		case 0:
    132			break;
    133		}
    134		/* we consumed all the data with the cmd descriptor */
    135		xfer->data = NULL;
    136	} else {
    137		xfer->cmd_desc[0] =
    138			CMD_0_ATTR_U |
    139			CMD_U0_TID(xfer->cmd_tid) |
    140			(rnw ? CMD_U0_RnW : 0) |
    141			CMD_U0_DEV_ADDRESS(addr) |
    142			CMD_U0_XFER_RATE(rate) |
    143			CMD_U0_MODE_INDEX(mode);
    144		xfer->cmd_desc[1] =
    145			CMD_U1_DATA_LENGTH(data_len);
    146		xfer->cmd_desc[2] = 0;
    147		xfer->cmd_desc[3] = 0;
    148	}
    149}
    150
    151static int hci_cmd_v2_prep_ccc(struct i3c_hci *hci, struct hci_xfer *xfer,
    152			       u8 ccc_addr, u8 ccc_cmd, bool raw)
    153{
    154	unsigned int mode = XFERMODE_IDX_I3C_SDR;
    155	unsigned int rate = get_i3c_rate_idx(hci);
    156	u8 *data = xfer->data;
    157	unsigned int data_len = xfer->data_len;
    158	bool rnw = xfer->rnw;
    159
    160	if (raw && ccc_addr != I3C_BROADCAST_ADDR) {
    161		hci_cmd_v2_prep_private_xfer(hci, xfer, ccc_addr, mode, rate);
    162		return 0;
    163	}
    164
    165	xfer->cmd_tid = hci_get_tid();
    166
    167	if (!rnw && data_len <= 4) {
    168		xfer->cmd_desc[0] =
    169			CMD_0_ATTR_U |
    170			CMD_U0_TID(xfer->cmd_tid) |
    171			CMD_U0_DEV_ADDRESS(ccc_addr) |
    172			CMD_U0_XFER_RATE(rate) |
    173			CMD_U0_MODE_INDEX(mode) |
    174			CMD_U0_IDB_COUNT(data_len + (!raw ? 0 : 1));
    175		xfer->cmd_desc[1] =
    176			CMD_U1_DATA_LENGTH(0);
    177		xfer->cmd_desc[2] =
    178			CMD_U2_IDB0(ccc_cmd);
    179		xfer->cmd_desc[3] = 0;
    180		switch (data_len) {
    181		case 4:
    182			xfer->cmd_desc[3] |= CMD_U3_IDB4(data[3]);
    183			fallthrough;
    184		case 3:
    185			xfer->cmd_desc[2] |= CMD_U2_IDB3(data[2]);
    186			fallthrough;
    187		case 2:
    188			xfer->cmd_desc[2] |= CMD_U2_IDB2(data[1]);
    189			fallthrough;
    190		case 1:
    191			xfer->cmd_desc[2] |= CMD_U2_IDB1(data[0]);
    192			fallthrough;
    193		case 0:
    194			break;
    195		}
    196		/* we consumed all the data with the cmd descriptor */
    197		xfer->data = NULL;
    198	} else {
    199		xfer->cmd_desc[0] =
    200			CMD_0_ATTR_U |
    201			CMD_U0_TID(xfer->cmd_tid) |
    202			(rnw ? CMD_U0_RnW : 0) |
    203			CMD_U0_DEV_ADDRESS(ccc_addr) |
    204			CMD_U0_XFER_RATE(rate) |
    205			CMD_U0_MODE_INDEX(mode) |
    206			CMD_U0_IDB_COUNT(!raw ? 0 : 1);
    207		xfer->cmd_desc[1] =
    208			CMD_U1_DATA_LENGTH(data_len);
    209		xfer->cmd_desc[2] =
    210			CMD_U2_IDB0(ccc_cmd);
    211		xfer->cmd_desc[3] = 0;
    212	}
    213
    214	return 0;
    215}
    216
    217static void hci_cmd_v2_prep_i3c_xfer(struct i3c_hci *hci,
    218				     struct i3c_dev_desc *dev,
    219				     struct hci_xfer *xfer)
    220{
    221	unsigned int mode = XFERMODE_IDX_I3C_SDR;
    222	unsigned int rate = get_i3c_rate_idx(hci);
    223	u8 addr = dev->info.dyn_addr;
    224
    225	hci_cmd_v2_prep_private_xfer(hci, xfer, addr, mode, rate);
    226}
    227
    228static void hci_cmd_v2_prep_i2c_xfer(struct i3c_hci *hci,
    229				     struct i2c_dev_desc *dev,
    230				     struct hci_xfer *xfer)
    231{
    232	unsigned int mode = XFERMODE_IDX_I2C;
    233	unsigned int rate = get_i2c_rate_idx(hci);
    234	u8 addr = dev->addr;
    235
    236	hci_cmd_v2_prep_private_xfer(hci, xfer, addr, mode, rate);
    237}
    238
    239static int hci_cmd_v2_daa(struct i3c_hci *hci)
    240{
    241	struct hci_xfer *xfer;
    242	int ret;
    243	u8 next_addr = 0;
    244	u32 device_id[2];
    245	u64 pid;
    246	unsigned int dcr, bcr;
    247	DECLARE_COMPLETION_ONSTACK(done);
    248
    249	xfer = hci_alloc_xfer(2);
    250	if (!xfer)
    251		return -ENOMEM;
    252
    253	xfer[0].data = &device_id;
    254	xfer[0].data_len = 8;
    255	xfer[0].rnw = true;
    256	xfer[0].cmd_desc[1] = CMD_A1_DATA_LENGTH(8);
    257	xfer[1].completion = &done;
    258
    259	for (;;) {
    260		ret = i3c_master_get_free_addr(&hci->master, next_addr);
    261		if (ret < 0)
    262			break;
    263		next_addr = ret;
    264		DBG("next_addr = 0x%02x", next_addr);
    265		xfer[0].cmd_tid = hci_get_tid();
    266		xfer[0].cmd_desc[0] =
    267			CMD_0_ATTR_A |
    268			CMD_A0_TID(xfer[0].cmd_tid) |
    269			CMD_A0_ROC;
    270		xfer[1].cmd_tid = hci_get_tid();
    271		xfer[1].cmd_desc[0] =
    272			CMD_0_ATTR_A |
    273			CMD_A0_TID(xfer[1].cmd_tid) |
    274			CMD_A0_ASSIGN_ADDRESS(next_addr) |
    275			CMD_A0_ROC |
    276			CMD_A0_TOC;
    277		hci->io->queue_xfer(hci, xfer, 2);
    278		if (!wait_for_completion_timeout(&done, HZ) &&
    279		    hci->io->dequeue_xfer(hci, xfer, 2)) {
    280			ret = -ETIME;
    281			break;
    282		}
    283		if (RESP_STATUS(xfer[0].response) != RESP_SUCCESS) {
    284			ret = 0;  /* no more devices to be assigned */
    285			break;
    286		}
    287		if (RESP_STATUS(xfer[1].response) != RESP_SUCCESS) {
    288			ret = -EIO;
    289			break;
    290		}
    291
    292		pid = FIELD_GET(W1_MASK(47, 32), device_id[1]);
    293		pid = (pid << 32) | device_id[0];
    294		bcr = FIELD_GET(W1_MASK(55, 48), device_id[1]);
    295		dcr = FIELD_GET(W1_MASK(63, 56), device_id[1]);
    296		DBG("assigned address %#x to device PID=0x%llx DCR=%#x BCR=%#x",
    297		    next_addr, pid, dcr, bcr);
    298		/*
    299		 * TODO: Extend the subsystem layer to allow for registering
    300		 * new device and provide BCR/DCR/PID at the same time.
    301		 */
    302		ret = i3c_master_add_i3c_dev_locked(&hci->master, next_addr);
    303		if (ret)
    304			break;
    305	}
    306
    307	hci_free_xfer(xfer, 2);
    308	return ret;
    309}
    310
    311const struct hci_cmd_ops mipi_i3c_hci_cmd_v2 = {
    312	.prep_ccc		= hci_cmd_v2_prep_ccc,
    313	.prep_i3c_xfer		= hci_cmd_v2_prep_i3c_xfer,
    314	.prep_i2c_xfer		= hci_cmd_v2_prep_i2c_xfer,
    315	.perform_daa		= hci_cmd_v2_daa,
    316};