drivers/platform/arm64/huawei-gaokun-ec.c

Source file repositories/reference/linux-study-clean/drivers/platform/arm64/huawei-gaokun-ec.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/arm64/huawei-gaokun-ec.c
Extension
.c
Size
19605 bytes
Lines
828
Domain
Driver Families
Bucket
drivers/platform
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 gaokun_ec {
	struct i2c_client *client;
	struct mutex lock; /* EC transaction lock */
	struct blocking_notifier_head notifier_list;
	struct device *hwmon_dev;
	struct input_dev *idev;
	bool suspended;
};

static int gaokun_ec_request(struct gaokun_ec *ec, const u8 *req,
			     size_t resp_len, u8 *resp)
{
	struct i2c_client *client = ec->client;
	struct i2c_msg msgs[] = {
		{
			.addr = client->addr,
			.flags = client->flags,
			.len = REQ_LEN(req),
			.buf = (void *)req,
		}, {
			.addr = client->addr,
			.flags = client->flags | I2C_M_RD,
			.len = resp_len,
			.buf = resp,
		},
	};
	int ret;

	guard(mutex)(&ec->lock);
	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
	if (ret != ARRAY_SIZE(msgs)) {
		dev_err(&client->dev, "I2C transfer error %d\n", ret);
		goto out_after_break;
	}

	ret = *resp;
	if (ret)
		dev_err(&client->dev, "EC transaction error %d\n", ret);

out_after_break:
	usleep_range(2000, 2500); /* have a break, ACPI did this */

	return ret;
}

/* -------------------------------------------------------------------------- */
/* Common API */

/**
 * gaokun_ec_read - Read from EC
 * @ec: The gaokun_ec structure
 * @req: The sequence to request
 * @resp_len: The size to read
 * @resp: The buffer to store response sequence
 *
 * This function is used to read data after writing a magic sequence to EC.
 * All EC operations depend on this function.
 *
 * Huawei uses magic sequences everywhere to complete various functions, all
 * these sequences are passed to ECCD(a ACPI method which is quiet similar
 * to gaokun_ec_request), there is no good abstraction to generalize these
 * sequences, so just wrap it for now. Almost all magic sequences are kept
 * in this file.
 *
 * Return: 0 on success or negative error code.
 */
int gaokun_ec_read(struct gaokun_ec *ec, const u8 *req,
		   size_t resp_len, u8 *resp)
{
	return gaokun_ec_request(ec, req, resp_len, resp);
}
EXPORT_SYMBOL_GPL(gaokun_ec_read);

/**
 * gaokun_ec_write - Write to EC
 * @ec: The gaokun_ec structure
 * @req: The sequence to request
 *
 * This function has no big difference from gaokun_ec_read. When caller care
 * only write status and no actual data are returned, then use it.
 *
 * Return: 0 on success or negative error code.
 */
int gaokun_ec_write(struct gaokun_ec *ec, const u8 *req)
{
	u8 ec_resp[] = MKRESP(0);

	return gaokun_ec_request(ec, req, sizeof(ec_resp), ec_resp);
}
EXPORT_SYMBOL_GPL(gaokun_ec_write);

Annotation

Implementation Notes