File Index
Files and directories
Sign in
FILE

cmd_v2.c

File preview with syntax highlighting.

linux-6.19.14/drivers/i3c/master/mipi-i3c-hci/cmd_v2.c C
  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		dev_dbg(&hci->master.dev, "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 = -ETIMEDOUT;
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		dev_dbg(&hci->master.dev,
297			"assigned address %#x to device PID=0x%llx DCR=%#x BCR=%#x",
298			next_addr, pid, dcr, bcr);
299		/*
300		 * TODO: Extend the subsystem layer to allow for registering
301		 * new device and provide BCR/DCR/PID at the same time.
302		 */
303		ret = i3c_master_add_i3c_dev_locked(&hci->master, next_addr);
304		if (ret)
305			break;
306	}
307
308	hci_free_xfer(xfer, 2);
309	return ret;
310}
311
312const struct hci_cmd_ops mipi_i3c_hci_cmd_v2 = {
313	.prep_ccc		= hci_cmd_v2_prep_ccc,
314	.prep_i3c_xfer		= hci_cmd_v2_prep_i3c_xfer,
315	.prep_i2c_xfer		= hci_cmd_v2_prep_i2c_xfer,
316	.perform_daa		= hci_cmd_v2_daa,
317};
~/ Read-only file preview.