162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * MCP2221A - Microchip USB to I2C Host Protocol Bridge
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2020, Rishi Gupta <gupt21@gmail.com>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/20005565B.pdf
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci#include <linux/err.h>
1262306a36Sopenharmony_ci#include <linux/mutex.h>
1362306a36Sopenharmony_ci#include <linux/bitfield.h>
1462306a36Sopenharmony_ci#include <linux/completion.h>
1562306a36Sopenharmony_ci#include <linux/delay.h>
1662306a36Sopenharmony_ci#include <linux/hid.h>
1762306a36Sopenharmony_ci#include <linux/hidraw.h>
1862306a36Sopenharmony_ci#include <linux/i2c.h>
1962306a36Sopenharmony_ci#include <linux/gpio/driver.h>
2062306a36Sopenharmony_ci#include <linux/iio/iio.h>
2162306a36Sopenharmony_ci#include "hid-ids.h"
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/* Commands codes in a raw output report */
2462306a36Sopenharmony_cienum {
2562306a36Sopenharmony_ci	MCP2221_I2C_WR_DATA = 0x90,
2662306a36Sopenharmony_ci	MCP2221_I2C_WR_NO_STOP = 0x94,
2762306a36Sopenharmony_ci	MCP2221_I2C_RD_DATA = 0x91,
2862306a36Sopenharmony_ci	MCP2221_I2C_RD_RPT_START = 0x93,
2962306a36Sopenharmony_ci	MCP2221_I2C_GET_DATA = 0x40,
3062306a36Sopenharmony_ci	MCP2221_I2C_PARAM_OR_STATUS	= 0x10,
3162306a36Sopenharmony_ci	MCP2221_I2C_SET_SPEED = 0x20,
3262306a36Sopenharmony_ci	MCP2221_I2C_CANCEL = 0x10,
3362306a36Sopenharmony_ci	MCP2221_GPIO_SET = 0x50,
3462306a36Sopenharmony_ci	MCP2221_GPIO_GET = 0x51,
3562306a36Sopenharmony_ci	MCP2221_SET_SRAM_SETTINGS = 0x60,
3662306a36Sopenharmony_ci	MCP2221_GET_SRAM_SETTINGS = 0x61,
3762306a36Sopenharmony_ci	MCP2221_READ_FLASH_DATA = 0xb0,
3862306a36Sopenharmony_ci};
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci/* Response codes in a raw input report */
4162306a36Sopenharmony_cienum {
4262306a36Sopenharmony_ci	MCP2221_SUCCESS = 0x00,
4362306a36Sopenharmony_ci	MCP2221_I2C_ENG_BUSY = 0x01,
4462306a36Sopenharmony_ci	MCP2221_I2C_START_TOUT = 0x12,
4562306a36Sopenharmony_ci	MCP2221_I2C_STOP_TOUT = 0x62,
4662306a36Sopenharmony_ci	MCP2221_I2C_WRADDRL_TOUT = 0x23,
4762306a36Sopenharmony_ci	MCP2221_I2C_WRDATA_TOUT = 0x44,
4862306a36Sopenharmony_ci	MCP2221_I2C_WRADDRL_NACK = 0x25,
4962306a36Sopenharmony_ci	MCP2221_I2C_MASK_ADDR_NACK = 0x40,
5062306a36Sopenharmony_ci	MCP2221_I2C_WRADDRL_SEND = 0x21,
5162306a36Sopenharmony_ci	MCP2221_I2C_ADDR_NACK = 0x25,
5262306a36Sopenharmony_ci	MCP2221_I2C_READ_COMPL = 0x55,
5362306a36Sopenharmony_ci	MCP2221_ALT_F_NOT_GPIOV = 0xEE,
5462306a36Sopenharmony_ci	MCP2221_ALT_F_NOT_GPIOD = 0xEF,
5562306a36Sopenharmony_ci};
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci/* MCP GPIO direction encoding */
5862306a36Sopenharmony_cienum {
5962306a36Sopenharmony_ci	MCP2221_DIR_OUT = 0x00,
6062306a36Sopenharmony_ci	MCP2221_DIR_IN = 0x01,
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci#define MCP_NGPIO	4
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci/* MCP GPIO set command layout */
6662306a36Sopenharmony_cistruct mcp_set_gpio {
6762306a36Sopenharmony_ci	u8 cmd;
6862306a36Sopenharmony_ci	u8 dummy;
6962306a36Sopenharmony_ci	struct {
7062306a36Sopenharmony_ci		u8 change_value;
7162306a36Sopenharmony_ci		u8 value;
7262306a36Sopenharmony_ci		u8 change_direction;
7362306a36Sopenharmony_ci		u8 direction;
7462306a36Sopenharmony_ci	} gpio[MCP_NGPIO];
7562306a36Sopenharmony_ci} __packed;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci/* MCP GPIO get command layout */
7862306a36Sopenharmony_cistruct mcp_get_gpio {
7962306a36Sopenharmony_ci	u8 cmd;
8062306a36Sopenharmony_ci	u8 dummy;
8162306a36Sopenharmony_ci	struct {
8262306a36Sopenharmony_ci		u8 value;
8362306a36Sopenharmony_ci		u8 direction;
8462306a36Sopenharmony_ci	} gpio[MCP_NGPIO];
8562306a36Sopenharmony_ci} __packed;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci/*
8862306a36Sopenharmony_ci * There is no way to distinguish responses. Therefore next command
8962306a36Sopenharmony_ci * is sent only after response to previous has been received. Mutex
9062306a36Sopenharmony_ci * lock is used for this purpose mainly.
9162306a36Sopenharmony_ci */
9262306a36Sopenharmony_cistruct mcp2221 {
9362306a36Sopenharmony_ci	struct hid_device *hdev;
9462306a36Sopenharmony_ci	struct i2c_adapter adapter;
9562306a36Sopenharmony_ci	struct mutex lock;
9662306a36Sopenharmony_ci	struct completion wait_in_report;
9762306a36Sopenharmony_ci	struct delayed_work init_work;
9862306a36Sopenharmony_ci	u8 *rxbuf;
9962306a36Sopenharmony_ci	u8 txbuf[64];
10062306a36Sopenharmony_ci	int rxbuf_idx;
10162306a36Sopenharmony_ci	int status;
10262306a36Sopenharmony_ci	u8 cur_i2c_clk_div;
10362306a36Sopenharmony_ci	struct gpio_chip *gc;
10462306a36Sopenharmony_ci	u8 gp_idx;
10562306a36Sopenharmony_ci	u8 gpio_dir;
10662306a36Sopenharmony_ci	u8 mode[4];
10762306a36Sopenharmony_ci#if IS_REACHABLE(CONFIG_IIO)
10862306a36Sopenharmony_ci	struct iio_chan_spec iio_channels[3];
10962306a36Sopenharmony_ci	u16 adc_values[3];
11062306a36Sopenharmony_ci	u8 adc_scale;
11162306a36Sopenharmony_ci	u8 dac_value;
11262306a36Sopenharmony_ci	u16 dac_scale;
11362306a36Sopenharmony_ci#endif
11462306a36Sopenharmony_ci};
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistruct mcp2221_iio {
11762306a36Sopenharmony_ci	struct mcp2221 *mcp;
11862306a36Sopenharmony_ci};
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci/*
12162306a36Sopenharmony_ci * Default i2c bus clock frequency 400 kHz. Modify this if you
12262306a36Sopenharmony_ci * want to set some other frequency (min 50 kHz - max 400 kHz).
12362306a36Sopenharmony_ci */
12462306a36Sopenharmony_cistatic uint i2c_clk_freq = 400;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci/* Synchronously send output report to the device */
12762306a36Sopenharmony_cistatic int mcp_send_report(struct mcp2221 *mcp,
12862306a36Sopenharmony_ci					u8 *out_report, size_t len)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	u8 *buf;
13162306a36Sopenharmony_ci	int ret;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	buf = kmemdup(out_report, len, GFP_KERNEL);
13462306a36Sopenharmony_ci	if (!buf)
13562306a36Sopenharmony_ci		return -ENOMEM;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	/* mcp2221 uses interrupt endpoint for out reports */
13862306a36Sopenharmony_ci	ret = hid_hw_output_report(mcp->hdev, buf, len);
13962306a36Sopenharmony_ci	kfree(buf);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	if (ret < 0)
14262306a36Sopenharmony_ci		return ret;
14362306a36Sopenharmony_ci	return 0;
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci/*
14762306a36Sopenharmony_ci * Send o/p report to the device and wait for i/p report to be
14862306a36Sopenharmony_ci * received from the device. If the device does not respond,
14962306a36Sopenharmony_ci * we timeout.
15062306a36Sopenharmony_ci */
15162306a36Sopenharmony_cistatic int mcp_send_data_req_status(struct mcp2221 *mcp,
15262306a36Sopenharmony_ci			u8 *out_report, int len)
15362306a36Sopenharmony_ci{
15462306a36Sopenharmony_ci	int ret;
15562306a36Sopenharmony_ci	unsigned long t;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	reinit_completion(&mcp->wait_in_report);
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	ret = mcp_send_report(mcp, out_report, len);
16062306a36Sopenharmony_ci	if (ret)
16162306a36Sopenharmony_ci		return ret;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	t = wait_for_completion_timeout(&mcp->wait_in_report,
16462306a36Sopenharmony_ci							msecs_to_jiffies(4000));
16562306a36Sopenharmony_ci	if (!t)
16662306a36Sopenharmony_ci		return -ETIMEDOUT;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	return mcp->status;
16962306a36Sopenharmony_ci}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci/* Check pass/fail for actual communication with i2c slave */
17262306a36Sopenharmony_cistatic int mcp_chk_last_cmd_status(struct mcp2221 *mcp)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	memset(mcp->txbuf, 0, 8);
17562306a36Sopenharmony_ci	mcp->txbuf[0] = MCP2221_I2C_PARAM_OR_STATUS;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	return mcp_send_data_req_status(mcp, mcp->txbuf, 8);
17862306a36Sopenharmony_ci}
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci/* Cancels last command releasing i2c bus just in case occupied */
18162306a36Sopenharmony_cistatic int mcp_cancel_last_cmd(struct mcp2221 *mcp)
18262306a36Sopenharmony_ci{
18362306a36Sopenharmony_ci	memset(mcp->txbuf, 0, 8);
18462306a36Sopenharmony_ci	mcp->txbuf[0] = MCP2221_I2C_PARAM_OR_STATUS;
18562306a36Sopenharmony_ci	mcp->txbuf[2] = MCP2221_I2C_CANCEL;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	return mcp_send_data_req_status(mcp, mcp->txbuf, 8);
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic int mcp_set_i2c_speed(struct mcp2221 *mcp)
19162306a36Sopenharmony_ci{
19262306a36Sopenharmony_ci	int ret;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	memset(mcp->txbuf, 0, 8);
19562306a36Sopenharmony_ci	mcp->txbuf[0] = MCP2221_I2C_PARAM_OR_STATUS;
19662306a36Sopenharmony_ci	mcp->txbuf[3] = MCP2221_I2C_SET_SPEED;
19762306a36Sopenharmony_ci	mcp->txbuf[4] = mcp->cur_i2c_clk_div;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	ret = mcp_send_data_req_status(mcp, mcp->txbuf, 8);
20062306a36Sopenharmony_ci	if (ret) {
20162306a36Sopenharmony_ci		/* Small delay is needed here */
20262306a36Sopenharmony_ci		usleep_range(980, 1000);
20362306a36Sopenharmony_ci		mcp_cancel_last_cmd(mcp);
20462306a36Sopenharmony_ci	}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	return 0;
20762306a36Sopenharmony_ci}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci/*
21062306a36Sopenharmony_ci * An output report can contain minimum 1 and maximum 60 user data
21162306a36Sopenharmony_ci * bytes. If the number of data bytes is more then 60, we send it
21262306a36Sopenharmony_ci * in chunks of 60 bytes. Last chunk may contain exactly 60 or less
21362306a36Sopenharmony_ci * bytes. Total number of bytes is informed in very first report to
21462306a36Sopenharmony_ci * mcp2221, from that point onwards it first collect all the data
21562306a36Sopenharmony_ci * from host and then send to i2c slave device.
21662306a36Sopenharmony_ci */
21762306a36Sopenharmony_cistatic int mcp_i2c_write(struct mcp2221 *mcp,
21862306a36Sopenharmony_ci				struct i2c_msg *msg, int type, u8 last_status)
21962306a36Sopenharmony_ci{
22062306a36Sopenharmony_ci	int ret, len, idx, sent;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	idx = 0;
22362306a36Sopenharmony_ci	sent  = 0;
22462306a36Sopenharmony_ci	if (msg->len < 60)
22562306a36Sopenharmony_ci		len = msg->len;
22662306a36Sopenharmony_ci	else
22762306a36Sopenharmony_ci		len = 60;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	do {
23062306a36Sopenharmony_ci		mcp->txbuf[0] = type;
23162306a36Sopenharmony_ci		mcp->txbuf[1] = msg->len & 0xff;
23262306a36Sopenharmony_ci		mcp->txbuf[2] = msg->len >> 8;
23362306a36Sopenharmony_ci		mcp->txbuf[3] = (u8)(msg->addr << 1);
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci		memcpy(&mcp->txbuf[4], &msg->buf[idx], len);
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci		ret = mcp_send_data_req_status(mcp, mcp->txbuf, len + 4);
23862306a36Sopenharmony_ci		if (ret)
23962306a36Sopenharmony_ci			return ret;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci		usleep_range(980, 1000);
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci		if (last_status) {
24462306a36Sopenharmony_ci			ret = mcp_chk_last_cmd_status(mcp);
24562306a36Sopenharmony_ci			if (ret)
24662306a36Sopenharmony_ci				return ret;
24762306a36Sopenharmony_ci		}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci		sent = sent + len;
25062306a36Sopenharmony_ci		if (sent >= msg->len)
25162306a36Sopenharmony_ci			break;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci		idx = idx + len;
25462306a36Sopenharmony_ci		if ((msg->len - sent) < 60)
25562306a36Sopenharmony_ci			len = msg->len - sent;
25662306a36Sopenharmony_ci		else
25762306a36Sopenharmony_ci			len = 60;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci		/*
26062306a36Sopenharmony_ci		 * Testing shows delay is needed between successive writes
26162306a36Sopenharmony_ci		 * otherwise next write fails on first-try from i2c core.
26262306a36Sopenharmony_ci		 * This value is obtained through automated stress testing.
26362306a36Sopenharmony_ci		 */
26462306a36Sopenharmony_ci		usleep_range(980, 1000);
26562306a36Sopenharmony_ci	} while (len > 0);
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	return ret;
26862306a36Sopenharmony_ci}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci/*
27162306a36Sopenharmony_ci * Device reads all data (0 - 65535 bytes) from i2c slave device and
27262306a36Sopenharmony_ci * stores it in device itself. This data is read back from device to
27362306a36Sopenharmony_ci * host in multiples of 60 bytes using input reports.
27462306a36Sopenharmony_ci */
27562306a36Sopenharmony_cistatic int mcp_i2c_smbus_read(struct mcp2221 *mcp,
27662306a36Sopenharmony_ci				struct i2c_msg *msg, int type, u16 smbus_addr,
27762306a36Sopenharmony_ci				u8 smbus_len, u8 *smbus_buf)
27862306a36Sopenharmony_ci{
27962306a36Sopenharmony_ci	int ret;
28062306a36Sopenharmony_ci	u16 total_len;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	mcp->txbuf[0] = type;
28362306a36Sopenharmony_ci	if (msg) {
28462306a36Sopenharmony_ci		mcp->txbuf[1] = msg->len & 0xff;
28562306a36Sopenharmony_ci		mcp->txbuf[2] = msg->len >> 8;
28662306a36Sopenharmony_ci		mcp->txbuf[3] = (u8)(msg->addr << 1);
28762306a36Sopenharmony_ci		total_len = msg->len;
28862306a36Sopenharmony_ci		mcp->rxbuf = msg->buf;
28962306a36Sopenharmony_ci	} else {
29062306a36Sopenharmony_ci		mcp->txbuf[1] = smbus_len;
29162306a36Sopenharmony_ci		mcp->txbuf[2] = 0;
29262306a36Sopenharmony_ci		mcp->txbuf[3] = (u8)(smbus_addr << 1);
29362306a36Sopenharmony_ci		total_len = smbus_len;
29462306a36Sopenharmony_ci		mcp->rxbuf = smbus_buf;
29562306a36Sopenharmony_ci	}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	ret = mcp_send_data_req_status(mcp, mcp->txbuf, 4);
29862306a36Sopenharmony_ci	if (ret)
29962306a36Sopenharmony_ci		return ret;
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	mcp->rxbuf_idx = 0;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	do {
30462306a36Sopenharmony_ci		memset(mcp->txbuf, 0, 4);
30562306a36Sopenharmony_ci		mcp->txbuf[0] = MCP2221_I2C_GET_DATA;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci		ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
30862306a36Sopenharmony_ci		if (ret)
30962306a36Sopenharmony_ci			return ret;
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci		ret = mcp_chk_last_cmd_status(mcp);
31262306a36Sopenharmony_ci		if (ret)
31362306a36Sopenharmony_ci			return ret;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci		usleep_range(980, 1000);
31662306a36Sopenharmony_ci	} while (mcp->rxbuf_idx < total_len);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	return ret;
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_cistatic int mcp_i2c_xfer(struct i2c_adapter *adapter,
32262306a36Sopenharmony_ci				struct i2c_msg msgs[], int num)
32362306a36Sopenharmony_ci{
32462306a36Sopenharmony_ci	int ret;
32562306a36Sopenharmony_ci	struct mcp2221 *mcp = i2c_get_adapdata(adapter);
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	hid_hw_power(mcp->hdev, PM_HINT_FULLON);
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	mutex_lock(&mcp->lock);
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	/* Setting speed before every transaction is required for mcp2221 */
33262306a36Sopenharmony_ci	ret = mcp_set_i2c_speed(mcp);
33362306a36Sopenharmony_ci	if (ret)
33462306a36Sopenharmony_ci		goto exit;
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	if (num == 1) {
33762306a36Sopenharmony_ci		if (msgs->flags & I2C_M_RD) {
33862306a36Sopenharmony_ci			ret = mcp_i2c_smbus_read(mcp, msgs, MCP2221_I2C_RD_DATA,
33962306a36Sopenharmony_ci							0, 0, NULL);
34062306a36Sopenharmony_ci		} else {
34162306a36Sopenharmony_ci			ret = mcp_i2c_write(mcp, msgs, MCP2221_I2C_WR_DATA, 1);
34262306a36Sopenharmony_ci		}
34362306a36Sopenharmony_ci		if (ret)
34462306a36Sopenharmony_ci			goto exit;
34562306a36Sopenharmony_ci		ret = num;
34662306a36Sopenharmony_ci	} else if (num == 2) {
34762306a36Sopenharmony_ci		/* Ex transaction; send reg address and read its contents */
34862306a36Sopenharmony_ci		if (msgs[0].addr == msgs[1].addr &&
34962306a36Sopenharmony_ci			!(msgs[0].flags & I2C_M_RD) &&
35062306a36Sopenharmony_ci			 (msgs[1].flags & I2C_M_RD)) {
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci			ret = mcp_i2c_write(mcp, &msgs[0],
35362306a36Sopenharmony_ci						MCP2221_I2C_WR_NO_STOP, 0);
35462306a36Sopenharmony_ci			if (ret)
35562306a36Sopenharmony_ci				goto exit;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci			ret = mcp_i2c_smbus_read(mcp, &msgs[1],
35862306a36Sopenharmony_ci						MCP2221_I2C_RD_RPT_START,
35962306a36Sopenharmony_ci						0, 0, NULL);
36062306a36Sopenharmony_ci			if (ret)
36162306a36Sopenharmony_ci				goto exit;
36262306a36Sopenharmony_ci			ret = num;
36362306a36Sopenharmony_ci		} else {
36462306a36Sopenharmony_ci			dev_err(&adapter->dev,
36562306a36Sopenharmony_ci				"unsupported multi-msg i2c transaction\n");
36662306a36Sopenharmony_ci			ret = -EOPNOTSUPP;
36762306a36Sopenharmony_ci		}
36862306a36Sopenharmony_ci	} else {
36962306a36Sopenharmony_ci		dev_err(&adapter->dev,
37062306a36Sopenharmony_ci			"unsupported multi-msg i2c transaction\n");
37162306a36Sopenharmony_ci		ret = -EOPNOTSUPP;
37262306a36Sopenharmony_ci	}
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ciexit:
37562306a36Sopenharmony_ci	hid_hw_power(mcp->hdev, PM_HINT_NORMAL);
37662306a36Sopenharmony_ci	mutex_unlock(&mcp->lock);
37762306a36Sopenharmony_ci	return ret;
37862306a36Sopenharmony_ci}
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_cistatic int mcp_smbus_write(struct mcp2221 *mcp, u16 addr,
38162306a36Sopenharmony_ci				u8 command, u8 *buf, u8 len, int type,
38262306a36Sopenharmony_ci				u8 last_status)
38362306a36Sopenharmony_ci{
38462306a36Sopenharmony_ci	int data_len, ret;
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	mcp->txbuf[0] = type;
38762306a36Sopenharmony_ci	mcp->txbuf[1] = len + 1; /* 1 is due to command byte itself */
38862306a36Sopenharmony_ci	mcp->txbuf[2] = 0;
38962306a36Sopenharmony_ci	mcp->txbuf[3] = (u8)(addr << 1);
39062306a36Sopenharmony_ci	mcp->txbuf[4] = command;
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	switch (len) {
39362306a36Sopenharmony_ci	case 0:
39462306a36Sopenharmony_ci		data_len = 5;
39562306a36Sopenharmony_ci		break;
39662306a36Sopenharmony_ci	case 1:
39762306a36Sopenharmony_ci		mcp->txbuf[5] = buf[0];
39862306a36Sopenharmony_ci		data_len = 6;
39962306a36Sopenharmony_ci		break;
40062306a36Sopenharmony_ci	case 2:
40162306a36Sopenharmony_ci		mcp->txbuf[5] = buf[0];
40262306a36Sopenharmony_ci		mcp->txbuf[6] = buf[1];
40362306a36Sopenharmony_ci		data_len = 7;
40462306a36Sopenharmony_ci		break;
40562306a36Sopenharmony_ci	default:
40662306a36Sopenharmony_ci		if (len > I2C_SMBUS_BLOCK_MAX)
40762306a36Sopenharmony_ci			return -EINVAL;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci		memcpy(&mcp->txbuf[5], buf, len);
41062306a36Sopenharmony_ci		data_len = len + 5;
41162306a36Sopenharmony_ci	}
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	ret = mcp_send_data_req_status(mcp, mcp->txbuf, data_len);
41462306a36Sopenharmony_ci	if (ret)
41562306a36Sopenharmony_ci		return ret;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	if (last_status) {
41862306a36Sopenharmony_ci		usleep_range(980, 1000);
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci		ret = mcp_chk_last_cmd_status(mcp);
42162306a36Sopenharmony_ci		if (ret)
42262306a36Sopenharmony_ci			return ret;
42362306a36Sopenharmony_ci	}
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	return ret;
42662306a36Sopenharmony_ci}
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_cistatic int mcp_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
42962306a36Sopenharmony_ci				unsigned short flags, char read_write,
43062306a36Sopenharmony_ci				u8 command, int size,
43162306a36Sopenharmony_ci				union i2c_smbus_data *data)
43262306a36Sopenharmony_ci{
43362306a36Sopenharmony_ci	int ret;
43462306a36Sopenharmony_ci	struct mcp2221 *mcp = i2c_get_adapdata(adapter);
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	hid_hw_power(mcp->hdev, PM_HINT_FULLON);
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	mutex_lock(&mcp->lock);
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	ret = mcp_set_i2c_speed(mcp);
44162306a36Sopenharmony_ci	if (ret)
44262306a36Sopenharmony_ci		goto exit;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	switch (size) {
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	case I2C_SMBUS_QUICK:
44762306a36Sopenharmony_ci		if (read_write == I2C_SMBUS_READ)
44862306a36Sopenharmony_ci			ret = mcp_i2c_smbus_read(mcp, NULL, MCP2221_I2C_RD_DATA,
44962306a36Sopenharmony_ci						addr, 0, &data->byte);
45062306a36Sopenharmony_ci		else
45162306a36Sopenharmony_ci			ret = mcp_smbus_write(mcp, addr, command, NULL,
45262306a36Sopenharmony_ci						0, MCP2221_I2C_WR_DATA, 1);
45362306a36Sopenharmony_ci		break;
45462306a36Sopenharmony_ci	case I2C_SMBUS_BYTE:
45562306a36Sopenharmony_ci		if (read_write == I2C_SMBUS_READ)
45662306a36Sopenharmony_ci			ret = mcp_i2c_smbus_read(mcp, NULL, MCP2221_I2C_RD_DATA,
45762306a36Sopenharmony_ci						addr, 1, &data->byte);
45862306a36Sopenharmony_ci		else
45962306a36Sopenharmony_ci			ret = mcp_smbus_write(mcp, addr, command, NULL,
46062306a36Sopenharmony_ci						0, MCP2221_I2C_WR_DATA, 1);
46162306a36Sopenharmony_ci		break;
46262306a36Sopenharmony_ci	case I2C_SMBUS_BYTE_DATA:
46362306a36Sopenharmony_ci		if (read_write == I2C_SMBUS_READ) {
46462306a36Sopenharmony_ci			ret = mcp_smbus_write(mcp, addr, command, NULL,
46562306a36Sopenharmony_ci						0, MCP2221_I2C_WR_NO_STOP, 0);
46662306a36Sopenharmony_ci			if (ret)
46762306a36Sopenharmony_ci				goto exit;
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci			ret = mcp_i2c_smbus_read(mcp, NULL,
47062306a36Sopenharmony_ci						MCP2221_I2C_RD_RPT_START,
47162306a36Sopenharmony_ci						addr, 1, &data->byte);
47262306a36Sopenharmony_ci		} else {
47362306a36Sopenharmony_ci			ret = mcp_smbus_write(mcp, addr, command, &data->byte,
47462306a36Sopenharmony_ci						1, MCP2221_I2C_WR_DATA, 1);
47562306a36Sopenharmony_ci		}
47662306a36Sopenharmony_ci		break;
47762306a36Sopenharmony_ci	case I2C_SMBUS_WORD_DATA:
47862306a36Sopenharmony_ci		if (read_write == I2C_SMBUS_READ) {
47962306a36Sopenharmony_ci			ret = mcp_smbus_write(mcp, addr, command, NULL,
48062306a36Sopenharmony_ci						0, MCP2221_I2C_WR_NO_STOP, 0);
48162306a36Sopenharmony_ci			if (ret)
48262306a36Sopenharmony_ci				goto exit;
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci			ret = mcp_i2c_smbus_read(mcp, NULL,
48562306a36Sopenharmony_ci						MCP2221_I2C_RD_RPT_START,
48662306a36Sopenharmony_ci						addr, 2, (u8 *)&data->word);
48762306a36Sopenharmony_ci		} else {
48862306a36Sopenharmony_ci			ret = mcp_smbus_write(mcp, addr, command,
48962306a36Sopenharmony_ci						(u8 *)&data->word, 2,
49062306a36Sopenharmony_ci						MCP2221_I2C_WR_DATA, 1);
49162306a36Sopenharmony_ci		}
49262306a36Sopenharmony_ci		break;
49362306a36Sopenharmony_ci	case I2C_SMBUS_BLOCK_DATA:
49462306a36Sopenharmony_ci		if (read_write == I2C_SMBUS_READ) {
49562306a36Sopenharmony_ci			ret = mcp_smbus_write(mcp, addr, command, NULL,
49662306a36Sopenharmony_ci						0, MCP2221_I2C_WR_NO_STOP, 1);
49762306a36Sopenharmony_ci			if (ret)
49862306a36Sopenharmony_ci				goto exit;
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci			mcp->rxbuf_idx = 0;
50162306a36Sopenharmony_ci			mcp->rxbuf = data->block;
50262306a36Sopenharmony_ci			mcp->txbuf[0] = MCP2221_I2C_GET_DATA;
50362306a36Sopenharmony_ci			ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
50462306a36Sopenharmony_ci			if (ret)
50562306a36Sopenharmony_ci				goto exit;
50662306a36Sopenharmony_ci		} else {
50762306a36Sopenharmony_ci			if (!data->block[0]) {
50862306a36Sopenharmony_ci				ret = -EINVAL;
50962306a36Sopenharmony_ci				goto exit;
51062306a36Sopenharmony_ci			}
51162306a36Sopenharmony_ci			ret = mcp_smbus_write(mcp, addr, command, data->block,
51262306a36Sopenharmony_ci						data->block[0] + 1,
51362306a36Sopenharmony_ci						MCP2221_I2C_WR_DATA, 1);
51462306a36Sopenharmony_ci		}
51562306a36Sopenharmony_ci		break;
51662306a36Sopenharmony_ci	case I2C_SMBUS_I2C_BLOCK_DATA:
51762306a36Sopenharmony_ci		if (read_write == I2C_SMBUS_READ) {
51862306a36Sopenharmony_ci			ret = mcp_smbus_write(mcp, addr, command, NULL,
51962306a36Sopenharmony_ci						0, MCP2221_I2C_WR_NO_STOP, 1);
52062306a36Sopenharmony_ci			if (ret)
52162306a36Sopenharmony_ci				goto exit;
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci			mcp->rxbuf_idx = 0;
52462306a36Sopenharmony_ci			mcp->rxbuf = data->block;
52562306a36Sopenharmony_ci			mcp->txbuf[0] = MCP2221_I2C_GET_DATA;
52662306a36Sopenharmony_ci			ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
52762306a36Sopenharmony_ci			if (ret)
52862306a36Sopenharmony_ci				goto exit;
52962306a36Sopenharmony_ci		} else {
53062306a36Sopenharmony_ci			if (!data->block[0]) {
53162306a36Sopenharmony_ci				ret = -EINVAL;
53262306a36Sopenharmony_ci				goto exit;
53362306a36Sopenharmony_ci			}
53462306a36Sopenharmony_ci			ret = mcp_smbus_write(mcp, addr, command,
53562306a36Sopenharmony_ci						&data->block[1], data->block[0],
53662306a36Sopenharmony_ci						MCP2221_I2C_WR_DATA, 1);
53762306a36Sopenharmony_ci		}
53862306a36Sopenharmony_ci		break;
53962306a36Sopenharmony_ci	case I2C_SMBUS_PROC_CALL:
54062306a36Sopenharmony_ci		ret = mcp_smbus_write(mcp, addr, command,
54162306a36Sopenharmony_ci						(u8 *)&data->word,
54262306a36Sopenharmony_ci						2, MCP2221_I2C_WR_NO_STOP, 0);
54362306a36Sopenharmony_ci		if (ret)
54462306a36Sopenharmony_ci			goto exit;
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci		ret = mcp_i2c_smbus_read(mcp, NULL,
54762306a36Sopenharmony_ci						MCP2221_I2C_RD_RPT_START,
54862306a36Sopenharmony_ci						addr, 2, (u8 *)&data->word);
54962306a36Sopenharmony_ci		break;
55062306a36Sopenharmony_ci	case I2C_SMBUS_BLOCK_PROC_CALL:
55162306a36Sopenharmony_ci		ret = mcp_smbus_write(mcp, addr, command, data->block,
55262306a36Sopenharmony_ci						data->block[0] + 1,
55362306a36Sopenharmony_ci						MCP2221_I2C_WR_NO_STOP, 0);
55462306a36Sopenharmony_ci		if (ret)
55562306a36Sopenharmony_ci			goto exit;
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci		ret = mcp_i2c_smbus_read(mcp, NULL,
55862306a36Sopenharmony_ci						MCP2221_I2C_RD_RPT_START,
55962306a36Sopenharmony_ci						addr, I2C_SMBUS_BLOCK_MAX,
56062306a36Sopenharmony_ci						data->block);
56162306a36Sopenharmony_ci		break;
56262306a36Sopenharmony_ci	default:
56362306a36Sopenharmony_ci		dev_err(&mcp->adapter.dev,
56462306a36Sopenharmony_ci			"unsupported smbus transaction size:%d\n", size);
56562306a36Sopenharmony_ci		ret = -EOPNOTSUPP;
56662306a36Sopenharmony_ci	}
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ciexit:
56962306a36Sopenharmony_ci	hid_hw_power(mcp->hdev, PM_HINT_NORMAL);
57062306a36Sopenharmony_ci	mutex_unlock(&mcp->lock);
57162306a36Sopenharmony_ci	return ret;
57262306a36Sopenharmony_ci}
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_cistatic u32 mcp_i2c_func(struct i2c_adapter *adapter)
57562306a36Sopenharmony_ci{
57662306a36Sopenharmony_ci	return I2C_FUNC_I2C |
57762306a36Sopenharmony_ci			I2C_FUNC_SMBUS_READ_BLOCK_DATA |
57862306a36Sopenharmony_ci			I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
57962306a36Sopenharmony_ci			(I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_PEC);
58062306a36Sopenharmony_ci}
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_cistatic const struct i2c_algorithm mcp_i2c_algo = {
58362306a36Sopenharmony_ci	.master_xfer = mcp_i2c_xfer,
58462306a36Sopenharmony_ci	.smbus_xfer = mcp_smbus_xfer,
58562306a36Sopenharmony_ci	.functionality = mcp_i2c_func,
58662306a36Sopenharmony_ci};
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci#if IS_REACHABLE(CONFIG_GPIOLIB)
58962306a36Sopenharmony_cistatic int mcp_gpio_get(struct gpio_chip *gc,
59062306a36Sopenharmony_ci				unsigned int offset)
59162306a36Sopenharmony_ci{
59262306a36Sopenharmony_ci	int ret;
59362306a36Sopenharmony_ci	struct mcp2221 *mcp = gpiochip_get_data(gc);
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	mcp->txbuf[0] = MCP2221_GPIO_GET;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	mcp->gp_idx = offsetof(struct mcp_get_gpio, gpio[offset]);
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	mutex_lock(&mcp->lock);
60062306a36Sopenharmony_ci	ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
60162306a36Sopenharmony_ci	mutex_unlock(&mcp->lock);
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci	return ret;
60462306a36Sopenharmony_ci}
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_cistatic void mcp_gpio_set(struct gpio_chip *gc,
60762306a36Sopenharmony_ci				unsigned int offset, int value)
60862306a36Sopenharmony_ci{
60962306a36Sopenharmony_ci	struct mcp2221 *mcp = gpiochip_get_data(gc);
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci	memset(mcp->txbuf, 0, 18);
61262306a36Sopenharmony_ci	mcp->txbuf[0] = MCP2221_GPIO_SET;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	mcp->gp_idx = offsetof(struct mcp_set_gpio, gpio[offset].value);
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	mcp->txbuf[mcp->gp_idx - 1] = 1;
61762306a36Sopenharmony_ci	mcp->txbuf[mcp->gp_idx] = !!value;
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	mutex_lock(&mcp->lock);
62062306a36Sopenharmony_ci	mcp_send_data_req_status(mcp, mcp->txbuf, 18);
62162306a36Sopenharmony_ci	mutex_unlock(&mcp->lock);
62262306a36Sopenharmony_ci}
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_cistatic int mcp_gpio_dir_set(struct mcp2221 *mcp,
62562306a36Sopenharmony_ci				unsigned int offset, u8 val)
62662306a36Sopenharmony_ci{
62762306a36Sopenharmony_ci	memset(mcp->txbuf, 0, 18);
62862306a36Sopenharmony_ci	mcp->txbuf[0] = MCP2221_GPIO_SET;
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci	mcp->gp_idx = offsetof(struct mcp_set_gpio, gpio[offset].direction);
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	mcp->txbuf[mcp->gp_idx - 1] = 1;
63362306a36Sopenharmony_ci	mcp->txbuf[mcp->gp_idx] = val;
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	return mcp_send_data_req_status(mcp, mcp->txbuf, 18);
63662306a36Sopenharmony_ci}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_cistatic int mcp_gpio_direction_input(struct gpio_chip *gc,
63962306a36Sopenharmony_ci				unsigned int offset)
64062306a36Sopenharmony_ci{
64162306a36Sopenharmony_ci	int ret;
64262306a36Sopenharmony_ci	struct mcp2221 *mcp = gpiochip_get_data(gc);
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	mutex_lock(&mcp->lock);
64562306a36Sopenharmony_ci	ret = mcp_gpio_dir_set(mcp, offset, MCP2221_DIR_IN);
64662306a36Sopenharmony_ci	mutex_unlock(&mcp->lock);
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	return ret;
64962306a36Sopenharmony_ci}
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_cistatic int mcp_gpio_direction_output(struct gpio_chip *gc,
65262306a36Sopenharmony_ci				unsigned int offset, int value)
65362306a36Sopenharmony_ci{
65462306a36Sopenharmony_ci	int ret;
65562306a36Sopenharmony_ci	struct mcp2221 *mcp = gpiochip_get_data(gc);
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	mutex_lock(&mcp->lock);
65862306a36Sopenharmony_ci	ret = mcp_gpio_dir_set(mcp, offset, MCP2221_DIR_OUT);
65962306a36Sopenharmony_ci	mutex_unlock(&mcp->lock);
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	/* Can't configure as output, bailout early */
66262306a36Sopenharmony_ci	if (ret)
66362306a36Sopenharmony_ci		return ret;
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	mcp_gpio_set(gc, offset, value);
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	return 0;
66862306a36Sopenharmony_ci}
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_cistatic int mcp_gpio_get_direction(struct gpio_chip *gc,
67162306a36Sopenharmony_ci				unsigned int offset)
67262306a36Sopenharmony_ci{
67362306a36Sopenharmony_ci	int ret;
67462306a36Sopenharmony_ci	struct mcp2221 *mcp = gpiochip_get_data(gc);
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	mcp->txbuf[0] = MCP2221_GPIO_GET;
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci	mcp->gp_idx = offsetof(struct mcp_get_gpio, gpio[offset]);
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci	mutex_lock(&mcp->lock);
68162306a36Sopenharmony_ci	ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
68262306a36Sopenharmony_ci	mutex_unlock(&mcp->lock);
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	if (ret)
68562306a36Sopenharmony_ci		return ret;
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	if (mcp->gpio_dir == MCP2221_DIR_IN)
68862306a36Sopenharmony_ci		return GPIO_LINE_DIRECTION_IN;
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	return GPIO_LINE_DIRECTION_OUT;
69162306a36Sopenharmony_ci}
69262306a36Sopenharmony_ci#endif
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci/* Gives current state of i2c engine inside mcp2221 */
69562306a36Sopenharmony_cistatic int mcp_get_i2c_eng_state(struct mcp2221 *mcp,
69662306a36Sopenharmony_ci				u8 *data, u8 idx)
69762306a36Sopenharmony_ci{
69862306a36Sopenharmony_ci	int ret;
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci	switch (data[idx]) {
70162306a36Sopenharmony_ci	case MCP2221_I2C_WRADDRL_NACK:
70262306a36Sopenharmony_ci	case MCP2221_I2C_WRADDRL_SEND:
70362306a36Sopenharmony_ci		ret = -ENXIO;
70462306a36Sopenharmony_ci		break;
70562306a36Sopenharmony_ci	case MCP2221_I2C_START_TOUT:
70662306a36Sopenharmony_ci	case MCP2221_I2C_STOP_TOUT:
70762306a36Sopenharmony_ci	case MCP2221_I2C_WRADDRL_TOUT:
70862306a36Sopenharmony_ci	case MCP2221_I2C_WRDATA_TOUT:
70962306a36Sopenharmony_ci		ret = -ETIMEDOUT;
71062306a36Sopenharmony_ci		break;
71162306a36Sopenharmony_ci	case MCP2221_I2C_ENG_BUSY:
71262306a36Sopenharmony_ci		ret = -EAGAIN;
71362306a36Sopenharmony_ci		break;
71462306a36Sopenharmony_ci	case MCP2221_SUCCESS:
71562306a36Sopenharmony_ci		ret = 0x00;
71662306a36Sopenharmony_ci		break;
71762306a36Sopenharmony_ci	default:
71862306a36Sopenharmony_ci		ret = -EIO;
71962306a36Sopenharmony_ci	}
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci	return ret;
72262306a36Sopenharmony_ci}
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci/*
72562306a36Sopenharmony_ci * MCP2221 uses interrupt endpoint for input reports. This function
72662306a36Sopenharmony_ci * is called by HID layer when it receives i/p report from mcp2221,
72762306a36Sopenharmony_ci * which is actually a response to the previously sent command.
72862306a36Sopenharmony_ci *
72962306a36Sopenharmony_ci * MCP2221A firmware specific return codes are parsed and 0 or
73062306a36Sopenharmony_ci * appropriate negative error code is returned. Delayed response
73162306a36Sopenharmony_ci * results in timeout error and stray reponses results in -EIO.
73262306a36Sopenharmony_ci */
73362306a36Sopenharmony_cistatic int mcp2221_raw_event(struct hid_device *hdev,
73462306a36Sopenharmony_ci				struct hid_report *report, u8 *data, int size)
73562306a36Sopenharmony_ci{
73662306a36Sopenharmony_ci	u8 *buf;
73762306a36Sopenharmony_ci	struct mcp2221 *mcp = hid_get_drvdata(hdev);
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci	switch (data[0]) {
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci	case MCP2221_I2C_WR_DATA:
74262306a36Sopenharmony_ci	case MCP2221_I2C_WR_NO_STOP:
74362306a36Sopenharmony_ci	case MCP2221_I2C_RD_DATA:
74462306a36Sopenharmony_ci	case MCP2221_I2C_RD_RPT_START:
74562306a36Sopenharmony_ci		switch (data[1]) {
74662306a36Sopenharmony_ci		case MCP2221_SUCCESS:
74762306a36Sopenharmony_ci			mcp->status = 0;
74862306a36Sopenharmony_ci			break;
74962306a36Sopenharmony_ci		default:
75062306a36Sopenharmony_ci			mcp->status = mcp_get_i2c_eng_state(mcp, data, 2);
75162306a36Sopenharmony_ci		}
75262306a36Sopenharmony_ci		complete(&mcp->wait_in_report);
75362306a36Sopenharmony_ci		break;
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci	case MCP2221_I2C_PARAM_OR_STATUS:
75662306a36Sopenharmony_ci		switch (data[1]) {
75762306a36Sopenharmony_ci		case MCP2221_SUCCESS:
75862306a36Sopenharmony_ci			if ((mcp->txbuf[3] == MCP2221_I2C_SET_SPEED) &&
75962306a36Sopenharmony_ci				(data[3] != MCP2221_I2C_SET_SPEED)) {
76062306a36Sopenharmony_ci				mcp->status = -EAGAIN;
76162306a36Sopenharmony_ci				break;
76262306a36Sopenharmony_ci			}
76362306a36Sopenharmony_ci			if (data[20] & MCP2221_I2C_MASK_ADDR_NACK) {
76462306a36Sopenharmony_ci				mcp->status = -ENXIO;
76562306a36Sopenharmony_ci				break;
76662306a36Sopenharmony_ci			}
76762306a36Sopenharmony_ci			mcp->status = mcp_get_i2c_eng_state(mcp, data, 8);
76862306a36Sopenharmony_ci#if IS_REACHABLE(CONFIG_IIO)
76962306a36Sopenharmony_ci			memcpy(&mcp->adc_values, &data[50], sizeof(mcp->adc_values));
77062306a36Sopenharmony_ci#endif
77162306a36Sopenharmony_ci			break;
77262306a36Sopenharmony_ci		default:
77362306a36Sopenharmony_ci			mcp->status = -EIO;
77462306a36Sopenharmony_ci		}
77562306a36Sopenharmony_ci		complete(&mcp->wait_in_report);
77662306a36Sopenharmony_ci		break;
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_ci	case MCP2221_I2C_GET_DATA:
77962306a36Sopenharmony_ci		switch (data[1]) {
78062306a36Sopenharmony_ci		case MCP2221_SUCCESS:
78162306a36Sopenharmony_ci			if (data[2] == MCP2221_I2C_ADDR_NACK) {
78262306a36Sopenharmony_ci				mcp->status = -ENXIO;
78362306a36Sopenharmony_ci				break;
78462306a36Sopenharmony_ci			}
78562306a36Sopenharmony_ci			if (!mcp_get_i2c_eng_state(mcp, data, 2)
78662306a36Sopenharmony_ci				&& (data[3] == 0)) {
78762306a36Sopenharmony_ci				mcp->status = 0;
78862306a36Sopenharmony_ci				break;
78962306a36Sopenharmony_ci			}
79062306a36Sopenharmony_ci			if (data[3] == 127) {
79162306a36Sopenharmony_ci				mcp->status = -EIO;
79262306a36Sopenharmony_ci				break;
79362306a36Sopenharmony_ci			}
79462306a36Sopenharmony_ci			if (data[2] == MCP2221_I2C_READ_COMPL) {
79562306a36Sopenharmony_ci				buf = mcp->rxbuf;
79662306a36Sopenharmony_ci				memcpy(&buf[mcp->rxbuf_idx], &data[4], data[3]);
79762306a36Sopenharmony_ci				mcp->rxbuf_idx = mcp->rxbuf_idx + data[3];
79862306a36Sopenharmony_ci				mcp->status = 0;
79962306a36Sopenharmony_ci				break;
80062306a36Sopenharmony_ci			}
80162306a36Sopenharmony_ci			mcp->status = -EIO;
80262306a36Sopenharmony_ci			break;
80362306a36Sopenharmony_ci		default:
80462306a36Sopenharmony_ci			mcp->status = -EIO;
80562306a36Sopenharmony_ci		}
80662306a36Sopenharmony_ci		complete(&mcp->wait_in_report);
80762306a36Sopenharmony_ci		break;
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci	case MCP2221_GPIO_GET:
81062306a36Sopenharmony_ci		switch (data[1]) {
81162306a36Sopenharmony_ci		case MCP2221_SUCCESS:
81262306a36Sopenharmony_ci			if ((data[mcp->gp_idx] == MCP2221_ALT_F_NOT_GPIOV) ||
81362306a36Sopenharmony_ci				(data[mcp->gp_idx + 1] == MCP2221_ALT_F_NOT_GPIOD)) {
81462306a36Sopenharmony_ci				mcp->status = -ENOENT;
81562306a36Sopenharmony_ci			} else {
81662306a36Sopenharmony_ci				mcp->status = !!data[mcp->gp_idx];
81762306a36Sopenharmony_ci				mcp->gpio_dir = data[mcp->gp_idx + 1];
81862306a36Sopenharmony_ci			}
81962306a36Sopenharmony_ci			break;
82062306a36Sopenharmony_ci		default:
82162306a36Sopenharmony_ci			mcp->status = -EAGAIN;
82262306a36Sopenharmony_ci		}
82362306a36Sopenharmony_ci		complete(&mcp->wait_in_report);
82462306a36Sopenharmony_ci		break;
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	case MCP2221_GPIO_SET:
82762306a36Sopenharmony_ci		switch (data[1]) {
82862306a36Sopenharmony_ci		case MCP2221_SUCCESS:
82962306a36Sopenharmony_ci			if ((data[mcp->gp_idx] == MCP2221_ALT_F_NOT_GPIOV) ||
83062306a36Sopenharmony_ci				(data[mcp->gp_idx - 1] == MCP2221_ALT_F_NOT_GPIOV)) {
83162306a36Sopenharmony_ci				mcp->status = -ENOENT;
83262306a36Sopenharmony_ci			} else {
83362306a36Sopenharmony_ci				mcp->status = 0;
83462306a36Sopenharmony_ci			}
83562306a36Sopenharmony_ci			break;
83662306a36Sopenharmony_ci		default:
83762306a36Sopenharmony_ci			mcp->status = -EAGAIN;
83862306a36Sopenharmony_ci		}
83962306a36Sopenharmony_ci		complete(&mcp->wait_in_report);
84062306a36Sopenharmony_ci		break;
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci	case MCP2221_SET_SRAM_SETTINGS:
84362306a36Sopenharmony_ci		switch (data[1]) {
84462306a36Sopenharmony_ci		case MCP2221_SUCCESS:
84562306a36Sopenharmony_ci			mcp->status = 0;
84662306a36Sopenharmony_ci			break;
84762306a36Sopenharmony_ci		default:
84862306a36Sopenharmony_ci			mcp->status = -EAGAIN;
84962306a36Sopenharmony_ci		}
85062306a36Sopenharmony_ci		complete(&mcp->wait_in_report);
85162306a36Sopenharmony_ci		break;
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	case MCP2221_GET_SRAM_SETTINGS:
85462306a36Sopenharmony_ci		switch (data[1]) {
85562306a36Sopenharmony_ci		case MCP2221_SUCCESS:
85662306a36Sopenharmony_ci			memcpy(&mcp->mode, &data[22], 4);
85762306a36Sopenharmony_ci#if IS_REACHABLE(CONFIG_IIO)
85862306a36Sopenharmony_ci			mcp->dac_value = data[6] & GENMASK(4, 0);
85962306a36Sopenharmony_ci#endif
86062306a36Sopenharmony_ci			mcp->status = 0;
86162306a36Sopenharmony_ci			break;
86262306a36Sopenharmony_ci		default:
86362306a36Sopenharmony_ci			mcp->status = -EAGAIN;
86462306a36Sopenharmony_ci		}
86562306a36Sopenharmony_ci		complete(&mcp->wait_in_report);
86662306a36Sopenharmony_ci		break;
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	case MCP2221_READ_FLASH_DATA:
86962306a36Sopenharmony_ci		switch (data[1]) {
87062306a36Sopenharmony_ci		case MCP2221_SUCCESS:
87162306a36Sopenharmony_ci			mcp->status = 0;
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci			/* Only handles CHIP SETTINGS subpage currently */
87462306a36Sopenharmony_ci			if (mcp->txbuf[1] != 0) {
87562306a36Sopenharmony_ci				mcp->status = -EIO;
87662306a36Sopenharmony_ci				break;
87762306a36Sopenharmony_ci			}
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci#if IS_REACHABLE(CONFIG_IIO)
88062306a36Sopenharmony_ci			{
88162306a36Sopenharmony_ci				u8 tmp;
88262306a36Sopenharmony_ci				/* DAC scale value */
88362306a36Sopenharmony_ci				tmp = FIELD_GET(GENMASK(7, 6), data[6]);
88462306a36Sopenharmony_ci				if ((data[6] & BIT(5)) && tmp)
88562306a36Sopenharmony_ci					mcp->dac_scale = tmp + 4;
88662306a36Sopenharmony_ci				else
88762306a36Sopenharmony_ci					mcp->dac_scale = 5;
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci				/* ADC scale value */
89062306a36Sopenharmony_ci				tmp = FIELD_GET(GENMASK(4, 3), data[7]);
89162306a36Sopenharmony_ci				if ((data[7] & BIT(2)) && tmp)
89262306a36Sopenharmony_ci					mcp->adc_scale = tmp - 1;
89362306a36Sopenharmony_ci				else
89462306a36Sopenharmony_ci					mcp->adc_scale = 0;
89562306a36Sopenharmony_ci			}
89662306a36Sopenharmony_ci#endif
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci			break;
89962306a36Sopenharmony_ci		default:
90062306a36Sopenharmony_ci			mcp->status = -EAGAIN;
90162306a36Sopenharmony_ci		}
90262306a36Sopenharmony_ci		complete(&mcp->wait_in_report);
90362306a36Sopenharmony_ci		break;
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	default:
90662306a36Sopenharmony_ci		mcp->status = -EIO;
90762306a36Sopenharmony_ci		complete(&mcp->wait_in_report);
90862306a36Sopenharmony_ci	}
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	return 1;
91162306a36Sopenharmony_ci}
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci/* Device resource managed function for HID unregistration */
91462306a36Sopenharmony_cistatic void mcp2221_hid_unregister(void *ptr)
91562306a36Sopenharmony_ci{
91662306a36Sopenharmony_ci	struct hid_device *hdev = ptr;
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_ci	hid_hw_close(hdev);
91962306a36Sopenharmony_ci	hid_hw_stop(hdev);
92062306a36Sopenharmony_ci}
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci/* This is needed to be sure hid_hw_stop() isn't called twice by the subsystem */
92362306a36Sopenharmony_cistatic void mcp2221_remove(struct hid_device *hdev)
92462306a36Sopenharmony_ci{
92562306a36Sopenharmony_ci	struct mcp2221 *mcp = hid_get_drvdata(hdev);
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	cancel_delayed_work_sync(&mcp->init_work);
92862306a36Sopenharmony_ci}
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci#if IS_REACHABLE(CONFIG_IIO)
93162306a36Sopenharmony_cistatic int mcp2221_read_raw(struct iio_dev *indio_dev,
93262306a36Sopenharmony_ci			    struct iio_chan_spec const *channel, int *val,
93362306a36Sopenharmony_ci			    int *val2, long mask)
93462306a36Sopenharmony_ci{
93562306a36Sopenharmony_ci	struct mcp2221_iio *priv = iio_priv(indio_dev);
93662306a36Sopenharmony_ci	struct mcp2221 *mcp = priv->mcp;
93762306a36Sopenharmony_ci	int ret;
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ci	if (mask == IIO_CHAN_INFO_SCALE) {
94062306a36Sopenharmony_ci		if (channel->output)
94162306a36Sopenharmony_ci			*val = 1 << mcp->dac_scale;
94262306a36Sopenharmony_ci		else
94362306a36Sopenharmony_ci			*val = 1 << mcp->adc_scale;
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci		return IIO_VAL_INT;
94662306a36Sopenharmony_ci	}
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_ci	mutex_lock(&mcp->lock);
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	if (channel->output) {
95162306a36Sopenharmony_ci		*val = mcp->dac_value;
95262306a36Sopenharmony_ci		ret = IIO_VAL_INT;
95362306a36Sopenharmony_ci	} else {
95462306a36Sopenharmony_ci		/* Read ADC values */
95562306a36Sopenharmony_ci		ret = mcp_chk_last_cmd_status(mcp);
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci		if (!ret) {
95862306a36Sopenharmony_ci			*val = le16_to_cpu((__force __le16) mcp->adc_values[channel->address]);
95962306a36Sopenharmony_ci			if (*val >= BIT(10))
96062306a36Sopenharmony_ci				ret =  -EINVAL;
96162306a36Sopenharmony_ci			else
96262306a36Sopenharmony_ci				ret = IIO_VAL_INT;
96362306a36Sopenharmony_ci		}
96462306a36Sopenharmony_ci	}
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_ci	mutex_unlock(&mcp->lock);
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	return ret;
96962306a36Sopenharmony_ci}
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_cistatic int mcp2221_write_raw(struct iio_dev *indio_dev,
97262306a36Sopenharmony_ci			     struct iio_chan_spec const *chan,
97362306a36Sopenharmony_ci			     int val, int val2, long mask)
97462306a36Sopenharmony_ci{
97562306a36Sopenharmony_ci	struct mcp2221_iio *priv = iio_priv(indio_dev);
97662306a36Sopenharmony_ci	struct mcp2221 *mcp = priv->mcp;
97762306a36Sopenharmony_ci	int ret;
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	if (val < 0 || val >= BIT(5))
98062306a36Sopenharmony_ci		return -EINVAL;
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci	mutex_lock(&mcp->lock);
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	memset(mcp->txbuf, 0, 12);
98562306a36Sopenharmony_ci	mcp->txbuf[0] = MCP2221_SET_SRAM_SETTINGS;
98662306a36Sopenharmony_ci	mcp->txbuf[4] = BIT(7) | val;
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	ret = mcp_send_data_req_status(mcp, mcp->txbuf, 12);
98962306a36Sopenharmony_ci	if (!ret)
99062306a36Sopenharmony_ci		mcp->dac_value = val;
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci	mutex_unlock(&mcp->lock);
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	return ret;
99562306a36Sopenharmony_ci}
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_cistatic const struct iio_info mcp2221_info = {
99862306a36Sopenharmony_ci	.read_raw = &mcp2221_read_raw,
99962306a36Sopenharmony_ci	.write_raw = &mcp2221_write_raw,
100062306a36Sopenharmony_ci};
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_cistatic int mcp_iio_channels(struct mcp2221 *mcp)
100362306a36Sopenharmony_ci{
100462306a36Sopenharmony_ci	int idx, cnt = 0;
100562306a36Sopenharmony_ci	bool dac_created = false;
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	/* GP0 doesn't have ADC/DAC alternative function */
100862306a36Sopenharmony_ci	for (idx = 1; idx < MCP_NGPIO; idx++) {
100962306a36Sopenharmony_ci		struct iio_chan_spec *chan = &mcp->iio_channels[cnt];
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci		switch (mcp->mode[idx]) {
101262306a36Sopenharmony_ci		case 2:
101362306a36Sopenharmony_ci			chan->address = idx - 1;
101462306a36Sopenharmony_ci			chan->channel = cnt++;
101562306a36Sopenharmony_ci			break;
101662306a36Sopenharmony_ci		case 3:
101762306a36Sopenharmony_ci			/* GP1 doesn't have DAC alternative function */
101862306a36Sopenharmony_ci			if (idx == 1 || dac_created)
101962306a36Sopenharmony_ci				continue;
102062306a36Sopenharmony_ci			/* DAC1 and DAC2 outputs are connected to the same DAC */
102162306a36Sopenharmony_ci			dac_created = true;
102262306a36Sopenharmony_ci			chan->output = 1;
102362306a36Sopenharmony_ci			cnt++;
102462306a36Sopenharmony_ci			break;
102562306a36Sopenharmony_ci		default:
102662306a36Sopenharmony_ci			continue;
102762306a36Sopenharmony_ci		};
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci		chan->type = IIO_VOLTAGE;
103062306a36Sopenharmony_ci		chan->indexed = 1;
103162306a36Sopenharmony_ci		chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
103262306a36Sopenharmony_ci		chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
103362306a36Sopenharmony_ci		chan->scan_index = -1;
103462306a36Sopenharmony_ci	}
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci	return cnt;
103762306a36Sopenharmony_ci}
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_cistatic void mcp_init_work(struct work_struct *work)
104062306a36Sopenharmony_ci{
104162306a36Sopenharmony_ci	struct iio_dev *indio_dev;
104262306a36Sopenharmony_ci	struct mcp2221 *mcp = container_of(work, struct mcp2221, init_work.work);
104362306a36Sopenharmony_ci	struct mcp2221_iio *data;
104462306a36Sopenharmony_ci	static int retries = 5;
104562306a36Sopenharmony_ci	int ret, num_channels;
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	hid_hw_power(mcp->hdev, PM_HINT_FULLON);
104862306a36Sopenharmony_ci	mutex_lock(&mcp->lock);
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci	mcp->txbuf[0] = MCP2221_GET_SRAM_SETTINGS;
105162306a36Sopenharmony_ci	ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	if (ret == -EAGAIN)
105462306a36Sopenharmony_ci		goto reschedule_task;
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci	num_channels = mcp_iio_channels(mcp);
105762306a36Sopenharmony_ci	if (!num_channels)
105862306a36Sopenharmony_ci		goto unlock;
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	mcp->txbuf[0] = MCP2221_READ_FLASH_DATA;
106162306a36Sopenharmony_ci	mcp->txbuf[1] = 0;
106262306a36Sopenharmony_ci	ret = mcp_send_data_req_status(mcp, mcp->txbuf, 2);
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	if (ret == -EAGAIN)
106562306a36Sopenharmony_ci		goto reschedule_task;
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(&mcp->hdev->dev, sizeof(*data));
106862306a36Sopenharmony_ci	if (!indio_dev)
106962306a36Sopenharmony_ci		goto unlock;
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	data = iio_priv(indio_dev);
107262306a36Sopenharmony_ci	data->mcp = mcp;
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci	indio_dev->name = "mcp2221";
107562306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
107662306a36Sopenharmony_ci	indio_dev->info = &mcp2221_info;
107762306a36Sopenharmony_ci	indio_dev->channels = mcp->iio_channels;
107862306a36Sopenharmony_ci	indio_dev->num_channels = num_channels;
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	devm_iio_device_register(&mcp->hdev->dev, indio_dev);
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ciunlock:
108362306a36Sopenharmony_ci	mutex_unlock(&mcp->lock);
108462306a36Sopenharmony_ci	hid_hw_power(mcp->hdev, PM_HINT_NORMAL);
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci	return;
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_cireschedule_task:
108962306a36Sopenharmony_ci	mutex_unlock(&mcp->lock);
109062306a36Sopenharmony_ci	hid_hw_power(mcp->hdev, PM_HINT_NORMAL);
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci	if (!retries--)
109362306a36Sopenharmony_ci		return;
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	/* Device is not ready to read SRAM or FLASH data, try again */
109662306a36Sopenharmony_ci	schedule_delayed_work(&mcp->init_work, msecs_to_jiffies(100));
109762306a36Sopenharmony_ci}
109862306a36Sopenharmony_ci#endif
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_cistatic int mcp2221_probe(struct hid_device *hdev,
110162306a36Sopenharmony_ci					const struct hid_device_id *id)
110262306a36Sopenharmony_ci{
110362306a36Sopenharmony_ci	int ret;
110462306a36Sopenharmony_ci	struct mcp2221 *mcp;
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_ci	mcp = devm_kzalloc(&hdev->dev, sizeof(*mcp), GFP_KERNEL);
110762306a36Sopenharmony_ci	if (!mcp)
110862306a36Sopenharmony_ci		return -ENOMEM;
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	ret = hid_parse(hdev);
111162306a36Sopenharmony_ci	if (ret) {
111262306a36Sopenharmony_ci		hid_err(hdev, "can't parse reports\n");
111362306a36Sopenharmony_ci		return ret;
111462306a36Sopenharmony_ci	}
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_ci	/*
111762306a36Sopenharmony_ci	 * This driver uses the .raw_event callback and therefore does not need any
111862306a36Sopenharmony_ci	 * HID_CONNECT_xxx flags.
111962306a36Sopenharmony_ci	 */
112062306a36Sopenharmony_ci	ret = hid_hw_start(hdev, 0);
112162306a36Sopenharmony_ci	if (ret) {
112262306a36Sopenharmony_ci		hid_err(hdev, "can't start hardware\n");
112362306a36Sopenharmony_ci		return ret;
112462306a36Sopenharmony_ci	}
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci	hid_info(hdev, "USB HID v%x.%02x Device [%s] on %s\n", hdev->version >> 8,
112762306a36Sopenharmony_ci			hdev->version & 0xff, hdev->name, hdev->phys);
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_ci	ret = hid_hw_open(hdev);
113062306a36Sopenharmony_ci	if (ret) {
113162306a36Sopenharmony_ci		hid_err(hdev, "can't open device\n");
113262306a36Sopenharmony_ci		hid_hw_stop(hdev);
113362306a36Sopenharmony_ci		return ret;
113462306a36Sopenharmony_ci	}
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci	mutex_init(&mcp->lock);
113762306a36Sopenharmony_ci	init_completion(&mcp->wait_in_report);
113862306a36Sopenharmony_ci	hid_set_drvdata(hdev, mcp);
113962306a36Sopenharmony_ci	mcp->hdev = hdev;
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci	ret = devm_add_action_or_reset(&hdev->dev, mcp2221_hid_unregister, hdev);
114262306a36Sopenharmony_ci	if (ret)
114362306a36Sopenharmony_ci		return ret;
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	hid_device_io_start(hdev);
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_ci	/* Set I2C bus clock diviser */
114862306a36Sopenharmony_ci	if (i2c_clk_freq > 400)
114962306a36Sopenharmony_ci		i2c_clk_freq = 400;
115062306a36Sopenharmony_ci	if (i2c_clk_freq < 50)
115162306a36Sopenharmony_ci		i2c_clk_freq = 50;
115262306a36Sopenharmony_ci	mcp->cur_i2c_clk_div = (12000000 / (i2c_clk_freq * 1000)) - 3;
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_ci	mcp->adapter.owner = THIS_MODULE;
115562306a36Sopenharmony_ci	mcp->adapter.class = I2C_CLASS_HWMON;
115662306a36Sopenharmony_ci	mcp->adapter.algo = &mcp_i2c_algo;
115762306a36Sopenharmony_ci	mcp->adapter.retries = 1;
115862306a36Sopenharmony_ci	mcp->adapter.dev.parent = &hdev->dev;
115962306a36Sopenharmony_ci	snprintf(mcp->adapter.name, sizeof(mcp->adapter.name),
116062306a36Sopenharmony_ci			"MCP2221 usb-i2c bridge");
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci	i2c_set_adapdata(&mcp->adapter, mcp);
116362306a36Sopenharmony_ci	ret = devm_i2c_add_adapter(&hdev->dev, &mcp->adapter);
116462306a36Sopenharmony_ci	if (ret) {
116562306a36Sopenharmony_ci		hid_err(hdev, "can't add usb-i2c adapter: %d\n", ret);
116662306a36Sopenharmony_ci		return ret;
116762306a36Sopenharmony_ci	}
116862306a36Sopenharmony_ci
116962306a36Sopenharmony_ci#if IS_REACHABLE(CONFIG_GPIOLIB)
117062306a36Sopenharmony_ci	/* Setup GPIO chip */
117162306a36Sopenharmony_ci	mcp->gc = devm_kzalloc(&hdev->dev, sizeof(*mcp->gc), GFP_KERNEL);
117262306a36Sopenharmony_ci	if (!mcp->gc)
117362306a36Sopenharmony_ci		return -ENOMEM;
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci	mcp->gc->label = "mcp2221_gpio";
117662306a36Sopenharmony_ci	mcp->gc->direction_input = mcp_gpio_direction_input;
117762306a36Sopenharmony_ci	mcp->gc->direction_output = mcp_gpio_direction_output;
117862306a36Sopenharmony_ci	mcp->gc->get_direction = mcp_gpio_get_direction;
117962306a36Sopenharmony_ci	mcp->gc->set = mcp_gpio_set;
118062306a36Sopenharmony_ci	mcp->gc->get = mcp_gpio_get;
118162306a36Sopenharmony_ci	mcp->gc->ngpio = MCP_NGPIO;
118262306a36Sopenharmony_ci	mcp->gc->base = -1;
118362306a36Sopenharmony_ci	mcp->gc->can_sleep = 1;
118462306a36Sopenharmony_ci	mcp->gc->parent = &hdev->dev;
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci	ret = devm_gpiochip_add_data(&hdev->dev, mcp->gc, mcp);
118762306a36Sopenharmony_ci	if (ret)
118862306a36Sopenharmony_ci		return ret;
118962306a36Sopenharmony_ci#endif
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci#if IS_REACHABLE(CONFIG_IIO)
119262306a36Sopenharmony_ci	INIT_DELAYED_WORK(&mcp->init_work, mcp_init_work);
119362306a36Sopenharmony_ci	schedule_delayed_work(&mcp->init_work, msecs_to_jiffies(100));
119462306a36Sopenharmony_ci#endif
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci	return 0;
119762306a36Sopenharmony_ci}
119862306a36Sopenharmony_ci
119962306a36Sopenharmony_cistatic const struct hid_device_id mcp2221_devices[] = {
120062306a36Sopenharmony_ci	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_MCP2221) },
120162306a36Sopenharmony_ci	{ }
120262306a36Sopenharmony_ci};
120362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(hid, mcp2221_devices);
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_cistatic struct hid_driver mcp2221_driver = {
120662306a36Sopenharmony_ci	.name		= "mcp2221",
120762306a36Sopenharmony_ci	.id_table	= mcp2221_devices,
120862306a36Sopenharmony_ci	.probe		= mcp2221_probe,
120962306a36Sopenharmony_ci	.remove		= mcp2221_remove,
121062306a36Sopenharmony_ci	.raw_event	= mcp2221_raw_event,
121162306a36Sopenharmony_ci};
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci/* Register with HID core */
121462306a36Sopenharmony_cimodule_hid_driver(mcp2221_driver);
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ciMODULE_AUTHOR("Rishi Gupta <gupt21@gmail.com>");
121762306a36Sopenharmony_ciMODULE_DESCRIPTION("MCP2221 Microchip HID USB to I2C master bridge");
121862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
1219