drivers/fsi/fsi-master-i2cr.c

Source file repositories/reference/linux-study-clean/drivers/fsi/fsi-master-i2cr.c

File Facts

System
Linux kernel
Corpus path
drivers/fsi/fsi-master-i2cr.c
Extension
.c
Size
7035 bytes
Lines
317
Domain
Driver Families
Bucket
drivers/fsi
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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: GPL-2.0
/* Copyright (C) IBM Corporation 2023 */

#include <linux/device.h>
#include <linux/fsi.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>

#include "fsi-master-i2cr.h"

#define CREATE_TRACE_POINTS
#include <trace/events/fsi_master_i2cr.h>

#define I2CR_ADDRESS_CFAM(a)	((a) >> 2)
#define I2CR_INITIAL_PARITY	true

#define I2CR_STATUS_CMD		0x60002
#define  I2CR_STATUS_ERR	 BIT_ULL(61)
#define I2CR_ERROR_CMD		0x60004
#define I2CR_LOG_CMD		0x60008

static const u8 i2cr_cfam[] = {
	0xc0, 0x02, 0x0d, 0xa6,
	0x80, 0x01, 0x10, 0x02,
	0x80, 0x01, 0x10, 0x02,
	0x80, 0x01, 0x10, 0x02,
	0x80, 0x01, 0x80, 0x52,
	0x80, 0x01, 0x10, 0x02,
	0x80, 0x01, 0x10, 0x02,
	0x80, 0x01, 0x10, 0x02,
	0x80, 0x01, 0x10, 0x02,
	0x80, 0x01, 0x22, 0x2d,
	0x00, 0x00, 0x00, 0x00,
	0xde, 0xad, 0xc0, 0xde
};

static bool i2cr_check_parity32(u32 v, bool parity)
{
	u32 i;

	for (i = 0; i < 32; ++i) {
		if (v & (1u << i))
			parity = !parity;
	}

	return parity;
}

static bool i2cr_check_parity64(u64 v)
{
	u32 i;
	bool parity = I2CR_INITIAL_PARITY;

	for (i = 0; i < 64; ++i) {
		if (v & (1llu << i))
			parity = !parity;
	}

	return parity;
}

static u32 i2cr_get_command(u32 address, bool parity)
{
	address <<= 1;

	if (i2cr_check_parity32(address, parity))
		address |= 1;

	return address;
}

static int i2cr_transfer(struct i2c_client *client, u32 command, u64 *data)
{
	struct i2c_msg msgs[2];
	int ret;

	msgs[0].addr = client->addr;
	msgs[0].flags = 0;
	msgs[0].len = sizeof(command);
	msgs[0].buf = (__u8 *)&command;
	msgs[1].addr = client->addr;
	msgs[1].flags = I2C_M_RD;
	msgs[1].len = sizeof(*data);
	msgs[1].buf = (__u8 *)data;

	ret = i2c_transfer(client->adapter, msgs, 2);
	if (ret == 2)
		return 0;

Annotation

Implementation Notes