drivers/i3c/master/mipi-i3c-hci/dat_v1.c

Source file repositories/reference/linux-study-clean/drivers/i3c/master/mipi-i3c-hci/dat_v1.c

File Facts

System
Linux kernel
Corpus path
drivers/i3c/master/mipi-i3c-hci/dat_v1.c
Extension
.c
Size
5097 bytes
Lines
203
Domain
Driver Families
Bucket
drivers/i3c
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: BSD-3-Clause
/*
 * Copyright (c) 2020, MIPI Alliance, Inc.
 *
 * Author: Nicolas Pitre <npitre@baylibre.com>
 */

#include <linux/bitfield.h>
#include <linux/bitmap.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/i3c/master.h>
#include <linux/io.h>

#include "hci.h"
#include "dat.h"

/*
 * Device Address Table Structure
 */

#define DAT_1_AUTOCMD_HDR_CODE		W1_MASK(58, 51)
#define DAT_1_AUTOCMD_MODE		W1_MASK(50, 48)
#define DAT_1_AUTOCMD_VALUE		W1_MASK(47, 40)
#define DAT_1_AUTOCMD_MASK		W1_MASK(39, 32)
/*	DAT_0_I2C_DEVICE		W0_BIT_(31) */
#define DAT_0_DEV_NACK_RETRY_CNT	W0_MASK(30, 29)
#define DAT_0_RING_ID			W0_MASK(28, 26)
#define DAT_0_DYNADDR_PARITY		W0_BIT_(23)
#define DAT_0_DYNAMIC_ADDRESS		W0_MASK(22, 16)
#define DAT_0_TS			W0_BIT_(15)
#define DAT_0_MR_REJECT			W0_BIT_(14)
/*	DAT_0_SIR_REJECT		W0_BIT_(13) */
/*	DAT_0_IBI_PAYLOAD		W0_BIT_(12) */
#define DAT_0_STATIC_ADDRESS		W0_MASK(6, 0)

#define dat_w0_read(i)		hci->DAT[i].w0
#define dat_w1_read(i)		hci->DAT[i].w1
#define dat_w0_write(i, v)	hci_dat_w0_write(hci, i, v)
#define dat_w1_write(i, v)	hci_dat_w1_write(hci, i, v)

static inline void hci_dat_w0_write(struct i3c_hci *hci, int i, u32 v)
{
	hci->DAT[i].w0 = v;
	writel(v, hci->DAT_regs + i * 8);
}

static inline void hci_dat_w1_write(struct i3c_hci *hci, int i, u32 v)
{
	hci->DAT[i].w1 = v;
	writel(v, hci->DAT_regs + i * 8 + 4);
}

static int hci_dat_v1_init(struct i3c_hci *hci)
{
	struct device *dev = hci->master.dev.parent;
	unsigned int dat_idx;

	if (!hci->DAT_regs) {
		dev_err(&hci->master.dev,
			"only DAT in register space is supported at the moment\n");
		return -EOPNOTSUPP;
	}
	if (hci->DAT_entry_size != 8) {
		dev_err(&hci->master.dev,
			"only 8-bytes DAT entries are supported at the moment\n");
		return -EOPNOTSUPP;
	}

	if (!hci->DAT) {
		hci->DAT = devm_kcalloc(dev, hci->DAT_entries, hci->DAT_entry_size, GFP_KERNEL);
		if (!hci->DAT)
			return -ENOMEM;
	}

	if (!hci->DAT_data) {
		/* use a bitmap for faster free slot search */
		hci->DAT_data = devm_bitmap_zalloc(dev, hci->DAT_entries, GFP_KERNEL);
		if (!hci->DAT_data)
			return -ENOMEM;

		/* clear them */
		for (dat_idx = 0; dat_idx < hci->DAT_entries; dat_idx++) {
			dat_w0_write(dat_idx, 0);
			dat_w1_write(dat_idx, 0);
		}
	}

	return 0;
}

Annotation

Implementation Notes