drivers/input/mouse/elan_i2c_smbus.c

Source file repositories/reference/linux-study-clean/drivers/input/mouse/elan_i2c_smbus.c

File Facts

System
Linux kernel
Corpus path
drivers/input/mouse/elan_i2c_smbus.c
Extension
.c
Size
13569 bytes
Lines
559
Domain
Driver Families
Bucket
drivers/input
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

if (error) {
			dev_err(dev, "failed to write iap password: %d\n",
				error);
			return error;
		}

		/*
		 * Read back password to make sure we enabled flash
		 * successfully.
		 */
		len = i2c_smbus_read_block_data(client,
						ETP_SMBUS_IAP_PASSWORD_READ,
						val);
		if (len < (int)sizeof(u16)) {
			error = len < 0 ? len : -EIO;
			dev_err(dev, "failed to read iap password: %d\n",
				error);
			return error;
		}

		password = be16_to_cpup((__be16 *)val);
		if (password != ETP_SMBUS_IAP_PASSWORD) {
			dev_err(dev, "wrong iap password = 0x%X\n", password);
			return -EIO;
		}

		/* Wait 30ms for MAIN_MODE change to IAP_MODE */
		msleep(30);
	}

	error = elan_smbus_set_flash_key(client);
	if (error)
		return error;

	/* Reset IC */
	error = elan_smbus_iap_reset(client);
	if (error)
		return error;

	return 0;
}


static int elan_smbus_write_fw_block(struct i2c_client *client, u16 fw_page_size,
				     const u8 *page, u16 checksum, int idx)
{
	struct device *dev = &client->dev;
	int error;
	u16 result;
	u8 val[I2C_SMBUS_BLOCK_MAX] = {0};

	/*
	 * Due to the limitation of smbus protocol limiting
	 * transfer to 32 bytes at a time, we must split block
	 * in 2 transfers.
	 */
	error = i2c_smbus_write_block_data(client,
					   ETP_SMBUS_WRITE_FW_BLOCK,
					   fw_page_size / 2,
					   page);
	if (error) {
		dev_err(dev, "Failed to write page %d (part %d): %d\n",
			idx, 1, error);
		return error;
	}

	error = i2c_smbus_write_block_data(client,
					   ETP_SMBUS_WRITE_FW_BLOCK,
					   fw_page_size / 2,
					   page + fw_page_size / 2);
	if (error) {
		dev_err(dev, "Failed to write page %d (part %d): %d\n",
			idx, 2, error);
		return error;
	}


	/* Wait for F/W to update one page ROM data. */
	usleep_range(8000, 10000);

	error = i2c_smbus_read_block_data(client,
					  ETP_SMBUS_IAP_CTRL_CMD, val);
	if (error < 0) {
		dev_err(dev, "Failed to read IAP write result: %d\n",
			error);
		return error;
	}

	result = be16_to_cpup((__be16 *)val);
	if (result & (ETP_FW_IAP_PAGE_ERR | ETP_FW_IAP_INTF_ERR)) {

Annotation

Implementation Notes