drivers/iio/accel/mma9551_core.c

Source file repositories/reference/linux-study-clean/drivers/iio/accel/mma9551_core.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/accel/mma9551_core.c
Extension
.c
Size
21820 bytes
Lines
804
Domain
Driver Families
Bucket
drivers/iio
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

struct mma9551_mbox_request {
	u8 start_mbox;		/* Always 0. */
	u8 app_id;
	/*
	 * See Section 5.3.1 of the MMA955xL Software Reference Manual.
	 *
	 * Bit 7: reserved, always 0
	 * Bits 6-4: command
	 * Bits 3-0: upper bits of register offset
	 */
	u8 cmd_off;
	u8 lower_off;
	u8 nbytes;
	u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS - 1];
} __packed;

struct mma9551_mbox_response {
	u8 app_id;
	/*
	 * See Section 5.3.3 of the MMA955xL Software Reference Manual.
	 *
	 * Bit 7: COCO
	 * Bits 6-0: Error code.
	 */
	u8 coco_err;
	u8 nbytes;
	u8 req_bytes;
	u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS];
} __packed;

struct mma9551_version_info {
	__be32 device_id;
	u8 rom_version[2];
	u8 fw_version[2];
	u8 hw_version[2];
	u8 fw_build[2];
};

static int mma9551_transfer(struct i2c_client *client,
			    u8 app_id, u8 command, u16 offset,
			    u8 *inbytes, int num_inbytes,
			    u8 *outbytes, int num_outbytes)
{
	struct mma9551_mbox_request req;
	struct mma9551_mbox_response rsp;
	struct i2c_msg in, out;
	u8 req_len, err_code;
	int ret, retries;

	if (offset >= 1 << 12) {
		dev_err(&client->dev, "register offset too large\n");
		return -EINVAL;
	}

	req_len = 1 + MMA9551_MAILBOX_CTRL_REGS + num_inbytes;
	req.start_mbox = 0;
	req.app_id = app_id;
	req.cmd_off = command | (offset >> 8);
	req.lower_off = offset;

	if (command == MMA9551_CMD_WRITE_CONFIG)
		req.nbytes = num_inbytes;
	else
		req.nbytes = num_outbytes;
	if (num_inbytes)
		memcpy(req.buf, inbytes, num_inbytes);

	out.addr = client->addr;
	out.flags = 0;
	out.len = req_len;
	out.buf = (u8 *)&req;

	ret = i2c_transfer(client->adapter, &out, 1);
	if (ret < 0) {
		dev_err(&client->dev, "i2c write failed\n");
		return ret;
	}

	retries = MMA9551_I2C_READ_RETRIES;
	do {
		udelay(MMA9551_I2C_READ_DELAY);

		in.addr = client->addr;
		in.flags = I2C_M_RD;
		in.len = sizeof(rsp);
		in.buf = (u8 *)&rsp;

		ret = i2c_transfer(client->adapter, &in, 1);
		if (ret < 0) {
			dev_err(&client->dev, "i2c read failed\n");

Annotation

Implementation Notes