brintos

brintos / linux-shallow public Read only

0
0
Text · 27.9 KiB · 333341e Raw
1108 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * hid-ft260.c - FTDI FT260 USB HID to I2C host bridge4 *5 * Copyright (c) 2021, Michael Zaidman <michaelz@xsightlabs.com>6 *7 * Data Sheet:8 *   https://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT260.pdf9 */10 11#include "hid-ids.h"12#include <linux/hidraw.h>13#include <linux/i2c.h>14#include <linux/module.h>15#include <linux/usb.h>16 17#ifdef DEBUG18static int ft260_debug = 1;19#else20static int ft260_debug;21#endif22module_param_named(debug, ft260_debug, int, 0600);23MODULE_PARM_DESC(debug, "Toggle FT260 debugging messages");24 25#define ft260_dbg(format, arg...)					  \26	do {								  \27		if (ft260_debug)					  \28			pr_info("%s: " format, __func__, ##arg);	  \29	} while (0)30 31#define FT260_REPORT_MAX_LENGTH (64)32#define FT260_I2C_DATA_REPORT_ID(len) (FT260_I2C_REPORT_MIN + (len - 1) / 4)33 34#define FT260_WAKEUP_NEEDED_AFTER_MS (4800) /* 5s minus 200ms margin */35 36/*37 * The ft260 input report format defines 62 bytes for the data payload, but38 * when requested 62 bytes, the controller returns 60 and 2 in separate input39 * reports. To achieve better performance with the multi-report read data40 * transfers, we set the maximum read payload length to a multiple of 60.41 * With a 100 kHz I2C clock, one 240 bytes read takes about 1/27 second,42 * which is excessive; On the other hand, some higher layer drivers like at2443 * or optoe limit the i2c reads to 128 bytes. To not block other drivers out44 * of I2C for potentially troublesome amounts of time, we select the maximum45 * read payload length to be 180 bytes.46*/47#define FT260_RD_DATA_MAX (180)48#define FT260_WR_DATA_MAX (60)49 50/*51 * Device interface configuration.52 * The FT260 has 2 interfaces that are controlled by DCNF0 and DCNF1 pins.53 * First implementes USB HID to I2C bridge function and54 * second - USB HID to UART bridge function.55 */56enum {57	FT260_MODE_ALL			= 0x00,58	FT260_MODE_I2C			= 0x01,59	FT260_MODE_UART			= 0x02,60	FT260_MODE_BOTH			= 0x03,61};62 63/* Control pipe */64enum {65	FT260_GET_RQST_TYPE		= 0xA1,66	FT260_GET_REPORT		= 0x01,67	FT260_SET_RQST_TYPE		= 0x21,68	FT260_SET_REPORT		= 0x09,69	FT260_FEATURE			= 0x03,70};71 72/* Report IDs / Feature In */73enum {74	FT260_CHIP_VERSION		= 0xA0,75	FT260_SYSTEM_SETTINGS		= 0xA1,76	FT260_I2C_STATUS		= 0xC0,77	FT260_I2C_READ_REQ		= 0xC2,78	FT260_I2C_REPORT_MIN		= 0xD0,79	FT260_I2C_REPORT_MAX		= 0xDE,80	FT260_GPIO			= 0xB0,81	FT260_UART_INTERRUPT_STATUS	= 0xB1,82	FT260_UART_STATUS		= 0xE0,83	FT260_UART_RI_DCD_STATUS	= 0xE1,84	FT260_UART_REPORT		= 0xF0,85};86 87/* Feature Out */88enum {89	FT260_SET_CLOCK			= 0x01,90	FT260_SET_I2C_MODE		= 0x02,91	FT260_SET_UART_MODE		= 0x03,92	FT260_ENABLE_INTERRUPT		= 0x05,93	FT260_SELECT_GPIO2_FUNC		= 0x06,94	FT260_ENABLE_UART_DCD_RI	= 0x07,95	FT260_SELECT_GPIOA_FUNC		= 0x08,96	FT260_SELECT_GPIOG_FUNC		= 0x09,97	FT260_SET_INTERRUPT_TRIGGER	= 0x0A,98	FT260_SET_SUSPEND_OUT_POLAR	= 0x0B,99	FT260_ENABLE_UART_RI_WAKEUP	= 0x0C,100	FT260_SET_UART_RI_WAKEUP_CFG	= 0x0D,101	FT260_SET_I2C_RESET		= 0x20,102	FT260_SET_I2C_CLOCK_SPEED	= 0x22,103	FT260_SET_UART_RESET		= 0x40,104	FT260_SET_UART_CONFIG		= 0x41,105	FT260_SET_UART_BAUD_RATE	= 0x42,106	FT260_SET_UART_DATA_BIT		= 0x43,107	FT260_SET_UART_PARITY		= 0x44,108	FT260_SET_UART_STOP_BIT		= 0x45,109	FT260_SET_UART_BREAKING		= 0x46,110	FT260_SET_UART_XON_XOFF		= 0x49,111};112 113/* Response codes in I2C status report */114enum {115	FT260_I2C_STATUS_SUCCESS	= 0x00,116	FT260_I2C_STATUS_CTRL_BUSY	= 0x01,117	FT260_I2C_STATUS_ERROR		= 0x02,118	FT260_I2C_STATUS_ADDR_NO_ACK	= 0x04,119	FT260_I2C_STATUS_DATA_NO_ACK	= 0x08,120	FT260_I2C_STATUS_ARBITR_LOST	= 0x10,121	FT260_I2C_STATUS_CTRL_IDLE	= 0x20,122	FT260_I2C_STATUS_BUS_BUSY	= 0x40,123};124 125/* I2C Conditions flags */126enum {127	FT260_FLAG_NONE			= 0x00,128	FT260_FLAG_START		= 0x02,129	FT260_FLAG_START_REPEATED	= 0x03,130	FT260_FLAG_STOP			= 0x04,131	FT260_FLAG_START_STOP		= 0x06,132	FT260_FLAG_START_STOP_REPEATED	= 0x07,133};134 135#define FT260_SET_REQUEST_VALUE(report_id) ((FT260_FEATURE << 8) | report_id)136 137/* Feature In reports */138 139struct ft260_get_chip_version_report {140	u8 report;		/* FT260_CHIP_VERSION */141	u8 chip_code[4];	/* FTDI chip identification code */142	u8 reserved[8];143} __packed;144 145struct ft260_get_system_status_report {146	u8 report;		/* FT260_SYSTEM_SETTINGS */147	u8 chip_mode;		/* DCNF0 and DCNF1 status, bits 0-1 */148	u8 clock_ctl;		/* 0 - 12MHz, 1 - 24MHz, 2 - 48MHz */149	u8 suspend_status;	/* 0 - not suspended, 1 - suspended */150	u8 pwren_status;	/* 0 - FT260 is not ready, 1 - ready */151	u8 i2c_enable;		/* 0 - disabled, 1 - enabled */152	u8 uart_mode;		/* 0 - OFF; 1 - RTS_CTS, 2 - DTR_DSR, */153				/* 3 - XON_XOFF, 4 - No flow control */154	u8 hid_over_i2c_en;	/* 0 - disabled, 1 - enabled */155	u8 gpio2_function;	/* 0 - GPIO,  1 - SUSPOUT, */156				/* 2 - PWREN, 4 - TX_LED */157	u8 gpioA_function;	/* 0 - GPIO, 3 - TX_ACTIVE, 4 - TX_LED */158	u8 gpioG_function;	/* 0 - GPIO, 2 - PWREN, */159				/* 5 - RX_LED, 6 - BCD_DET */160	u8 suspend_out_pol;	/* 0 - active-high, 1 - active-low */161	u8 enable_wakeup_int;	/* 0 - disabled, 1 - enabled */162	u8 intr_cond;		/* Interrupt trigger conditions */163	u8 power_saving_en;	/* 0 - disabled, 1 - enabled */164	u8 reserved[10];165} __packed;166 167struct ft260_get_i2c_status_report {168	u8 report;		/* FT260_I2C_STATUS */169	u8 bus_status;		/* I2C bus status */170	__le16 clock;		/* I2C bus clock in range 60-3400 KHz */171	u8 reserved;172} __packed;173 174/* Feature Out reports */175 176struct ft260_set_system_clock_report {177	u8 report;		/* FT260_SYSTEM_SETTINGS */178	u8 request;		/* FT260_SET_CLOCK */179	u8 clock_ctl;		/* 0 - 12MHz, 1 - 24MHz, 2 - 48MHz */180} __packed;181 182struct ft260_set_i2c_mode_report {183	u8 report;		/* FT260_SYSTEM_SETTINGS */184	u8 request;		/* FT260_SET_I2C_MODE */185	u8 i2c_enable;		/* 0 - disabled, 1 - enabled */186} __packed;187 188struct ft260_set_uart_mode_report {189	u8 report;		/* FT260_SYSTEM_SETTINGS */190	u8 request;		/* FT260_SET_UART_MODE */191	u8 uart_mode;		/* 0 - OFF; 1 - RTS_CTS, 2 - DTR_DSR, */192				/* 3 - XON_XOFF, 4 - No flow control */193} __packed;194 195struct ft260_set_i2c_reset_report {196	u8 report;		/* FT260_SYSTEM_SETTINGS */197	u8 request;		/* FT260_SET_I2C_RESET */198} __packed;199 200struct ft260_set_i2c_speed_report {201	u8 report;		/* FT260_SYSTEM_SETTINGS */202	u8 request;		/* FT260_SET_I2C_CLOCK_SPEED */203	__le16 clock;		/* I2C bus clock in range 60-3400 KHz */204} __packed;205 206/* Data transfer reports */207 208struct ft260_i2c_write_request_report {209	u8 report;		/* FT260_I2C_REPORT */210	u8 address;		/* 7-bit I2C address */211	u8 flag;		/* I2C transaction condition */212	u8 length;		/* data payload length */213	u8 data[FT260_WR_DATA_MAX]; /* data payload */214} __packed;215 216struct ft260_i2c_read_request_report {217	u8 report;		/* FT260_I2C_READ_REQ */218	u8 address;		/* 7-bit I2C address */219	u8 flag;		/* I2C transaction condition */220	__le16 length;		/* data payload length */221} __packed;222 223struct ft260_i2c_input_report {224	u8 report;		/* FT260_I2C_REPORT */225	u8 length;		/* data payload length */226	u8 data[2];		/* data payload */227} __packed;228 229static const struct hid_device_id ft260_devices[] = {230	{ HID_USB_DEVICE(USB_VENDOR_ID_FUTURE_TECHNOLOGY,231			 USB_DEVICE_ID_FT260) },232	{ /* END OF LIST */ }233};234MODULE_DEVICE_TABLE(hid, ft260_devices);235 236struct ft260_device {237	struct i2c_adapter adap;238	struct hid_device *hdev;239	struct completion wait;240	struct mutex lock;241	u8 write_buf[FT260_REPORT_MAX_LENGTH];242	unsigned long need_wakeup_at;243	u8 *read_buf;244	u16 read_idx;245	u16 read_len;246	u16 clock;247};248 249static int ft260_hid_feature_report_get(struct hid_device *hdev,250					unsigned char report_id, u8 *data,251					size_t len)252{253	u8 *buf;254	int ret;255 256	buf = kmalloc(len, GFP_KERNEL);257	if (!buf)258		return -ENOMEM;259 260	ret = hid_hw_raw_request(hdev, report_id, buf, len, HID_FEATURE_REPORT,261				 HID_REQ_GET_REPORT);262	if (likely(ret == len))263		memcpy(data, buf, len);264	else if (ret >= 0)265		ret = -EIO;266	kfree(buf);267	return ret;268}269 270static int ft260_hid_feature_report_set(struct hid_device *hdev, u8 *data,271					size_t len)272{273	u8 *buf;274	int ret;275 276	buf = kmemdup(data, len, GFP_KERNEL);277	if (!buf)278		return -ENOMEM;279 280	buf[0] = FT260_SYSTEM_SETTINGS;281 282	ret = hid_hw_raw_request(hdev, buf[0], buf, len, HID_FEATURE_REPORT,283				 HID_REQ_SET_REPORT);284 285	kfree(buf);286	return ret;287}288 289static int ft260_i2c_reset(struct hid_device *hdev)290{291	struct ft260_set_i2c_reset_report report;292	int ret;293 294	report.request = FT260_SET_I2C_RESET;295 296	ret = ft260_hid_feature_report_set(hdev, (u8 *)&report, sizeof(report));297	if (ret < 0) {298		hid_err(hdev, "failed to reset I2C controller: %d\n", ret);299		return ret;300	}301 302	ft260_dbg("done\n");303	return ret;304}305 306static int ft260_xfer_status(struct ft260_device *dev, u8 bus_busy)307{308	struct hid_device *hdev = dev->hdev;309	struct ft260_get_i2c_status_report report;310	int ret;311 312	if (time_is_before_jiffies(dev->need_wakeup_at)) {313		ret = ft260_hid_feature_report_get(hdev, FT260_I2C_STATUS,314						(u8 *)&report, sizeof(report));315		if (unlikely(ret < 0)) {316			hid_err(hdev, "failed to retrieve status: %d, no wakeup\n",317				ret);318		} else {319			dev->need_wakeup_at = jiffies +320				msecs_to_jiffies(FT260_WAKEUP_NEEDED_AFTER_MS);321			ft260_dbg("bus_status %#02x, wakeup\n",322				  report.bus_status);323		}324	}325 326	ret = ft260_hid_feature_report_get(hdev, FT260_I2C_STATUS,327					   (u8 *)&report, sizeof(report));328	if (unlikely(ret < 0)) {329		hid_err(hdev, "failed to retrieve status: %d\n", ret);330		return ret;331	}332 333	dev->clock = le16_to_cpu(report.clock);334	ft260_dbg("bus_status %#02x, clock %u\n", report.bus_status,335		  dev->clock);336 337	if (report.bus_status & (FT260_I2C_STATUS_CTRL_BUSY | bus_busy))338		return -EAGAIN;339 340	/*341	 * The error condition (bit 1) is a status bit reflecting any342	 * error conditions. When any of the bits 2, 3, or 4 are raised343	 * to 1, bit 1 is also set to 1.344	 */345	if (report.bus_status & FT260_I2C_STATUS_ERROR) {346		hid_err(hdev, "i2c bus error: %#02x\n", report.bus_status);347		return -EIO;348	}349 350	return 0;351}352 353static int ft260_hid_output_report(struct hid_device *hdev, u8 *data,354				   size_t len)355{356	u8 *buf;357	int ret;358 359	buf = kmemdup(data, len, GFP_KERNEL);360	if (!buf)361		return -ENOMEM;362 363	ret = hid_hw_output_report(hdev, buf, len);364 365	kfree(buf);366	return ret;367}368 369static int ft260_hid_output_report_check_status(struct ft260_device *dev,370						u8 *data, int len)371{372	u8 bus_busy;373	int ret, usec, try = 100;374	struct hid_device *hdev = dev->hdev;375	struct ft260_i2c_write_request_report *rep =376		(struct ft260_i2c_write_request_report *)data;377 378	ret = ft260_hid_output_report(hdev, data, len);379	if (ret < 0) {380		hid_err(hdev, "%s: failed to start transfer, ret %d\n",381			__func__, ret);382		ft260_i2c_reset(hdev);383		return ret;384	}385 386	/* transfer time = 1 / clock(KHz) * 9 bits * bytes */387	usec = len * 9000 / dev->clock;388	if (usec > 2000) {389		usec -= 1500;390		usleep_range(usec, usec + 100);391		ft260_dbg("wait %d usec, len %d\n", usec, len);392	}393 394	/*395	 * Do not check the busy bit for combined transactions396	 * since the controller keeps the bus busy between writing397	 * and reading IOs to ensure an atomic operation.398	 */399	if (rep->flag == FT260_FLAG_START)400		bus_busy = 0;401	else402		bus_busy = FT260_I2C_STATUS_BUS_BUSY;403 404	do {405		ret = ft260_xfer_status(dev, bus_busy);406		if (ret != -EAGAIN)407			break;408	} while (--try);409 410	if (ret == 0)411		return 0;412 413	ft260_i2c_reset(hdev);414	return -EIO;415}416 417static int ft260_i2c_write(struct ft260_device *dev, u8 addr, u8 *data,418			   int len, u8 flag)419{420	int ret, wr_len, idx = 0;421	struct hid_device *hdev = dev->hdev;422	struct ft260_i2c_write_request_report *rep =423		(struct ft260_i2c_write_request_report *)dev->write_buf;424 425	if (len < 1)426		return -EINVAL;427 428	rep->flag = FT260_FLAG_START;429 430	do {431		if (len <= FT260_WR_DATA_MAX) {432			wr_len = len;433			if (flag == FT260_FLAG_START_STOP)434				rep->flag |= FT260_FLAG_STOP;435		} else {436			wr_len = FT260_WR_DATA_MAX;437		}438 439		rep->report = FT260_I2C_DATA_REPORT_ID(wr_len);440		rep->address = addr;441		rep->length = wr_len;442 443		memcpy(rep->data, &data[idx], wr_len);444 445		ft260_dbg("rep %#02x addr %#02x off %d len %d wlen %d flag %#x d[0] %#02x\n",446			  rep->report, addr, idx, len, wr_len,447			  rep->flag, data[0]);448 449		ret = ft260_hid_output_report_check_status(dev, (u8 *)rep,450							   wr_len + 4);451		if (ret < 0) {452			hid_err(hdev, "%s: failed with %d\n", __func__, ret);453			return ret;454		}455 456		len -= wr_len;457		idx += wr_len;458		rep->flag = 0;459 460	} while (len > 0);461 462	return 0;463}464 465static int ft260_smbus_write(struct ft260_device *dev, u8 addr, u8 cmd,466			     u8 *data, u8 data_len, u8 flag)467{468	int ret = 0;469	int len = 4;470 471	struct ft260_i2c_write_request_report *rep =472		(struct ft260_i2c_write_request_report *)dev->write_buf;473 474	if (data_len >= sizeof(rep->data))475		return -EINVAL;476 477	rep->address = addr;478	rep->data[0] = cmd;479	rep->length = data_len + 1;480	rep->flag = flag;481	len += rep->length;482 483	rep->report = FT260_I2C_DATA_REPORT_ID(len);484 485	if (data_len > 0)486		memcpy(&rep->data[1], data, data_len);487 488	ft260_dbg("rep %#02x addr %#02x cmd %#02x datlen %d replen %d\n",489		  rep->report, addr, cmd, rep->length, len);490 491	ret = ft260_hid_output_report_check_status(dev, (u8 *)rep, len);492 493	return ret;494}495 496static int ft260_i2c_read(struct ft260_device *dev, u8 addr, u8 *data,497			  u16 len, u8 flag)498{499	u16 rd_len;500	u16 rd_data_max = 60;501	int timeout, ret = 0;502	struct ft260_i2c_read_request_report rep;503	struct hid_device *hdev = dev->hdev;504	u8 bus_busy = 0;505 506	if ((flag & FT260_FLAG_START_REPEATED) == FT260_FLAG_START_REPEATED)507		flag = FT260_FLAG_START_REPEATED;508	else509		flag = FT260_FLAG_START;510	do {511		if (len <= rd_data_max) {512			rd_len = len;513			flag |= FT260_FLAG_STOP;514		} else {515			rd_len = rd_data_max;516		}517		rd_data_max = FT260_RD_DATA_MAX;518 519		rep.report = FT260_I2C_READ_REQ;520		rep.length = cpu_to_le16(rd_len);521		rep.address = addr;522		rep.flag = flag;523 524		ft260_dbg("rep %#02x addr %#02x len %d rlen %d flag %#x\n",525			  rep.report, rep.address, len, rd_len, flag);526 527		reinit_completion(&dev->wait);528 529		dev->read_idx = 0;530		dev->read_buf = data;531		dev->read_len = rd_len;532 533		ret = ft260_hid_output_report(hdev, (u8 *)&rep, sizeof(rep));534		if (ret < 0) {535			hid_err(hdev, "%s: failed with %d\n", __func__, ret);536			goto ft260_i2c_read_exit;537		}538 539		timeout = msecs_to_jiffies(5000);540		if (!wait_for_completion_timeout(&dev->wait, timeout)) {541			ret = -ETIMEDOUT;542			ft260_i2c_reset(hdev);543			goto ft260_i2c_read_exit;544		}545 546		dev->read_buf = NULL;547 548		if (flag & FT260_FLAG_STOP)549			bus_busy = FT260_I2C_STATUS_BUS_BUSY;550 551		ret = ft260_xfer_status(dev, bus_busy);552		if (ret < 0) {553			ret = -EIO;554			ft260_i2c_reset(hdev);555			goto ft260_i2c_read_exit;556		}557 558		len -= rd_len;559		data += rd_len;560		flag = 0;561 562	} while (len > 0);563 564ft260_i2c_read_exit:565	dev->read_buf = NULL;566	return ret;567}568 569/*570 * A random read operation is implemented as a dummy write operation, followed571 * by a current address read operation. The dummy write operation is used to572 * load the target byte address into the current byte address counter, from573 * which the subsequent current address read operation then reads.574 */575static int ft260_i2c_write_read(struct ft260_device *dev, struct i2c_msg *msgs)576{577	int ret;578	int wr_len = msgs[0].len;579	int rd_len = msgs[1].len;580	struct hid_device *hdev = dev->hdev;581	u8 addr = msgs[0].addr;582	u16 read_off = 0;583 584	if (wr_len > 2) {585		hid_err(hdev, "%s: invalid wr_len: %d\n", __func__, wr_len);586		return -EOPNOTSUPP;587	}588 589	if (ft260_debug) {590		if (wr_len == 2)591			read_off = be16_to_cpu(*(__be16 *)msgs[0].buf);592		else593			read_off = *msgs[0].buf;594 595		pr_info("%s: off %#x rlen %d wlen %d\n", __func__,596			read_off, rd_len, wr_len);597	}598 599	ret = ft260_i2c_write(dev, addr, msgs[0].buf, wr_len,600			      FT260_FLAG_START);601	if (ret < 0)602		return ret;603 604	ret = ft260_i2c_read(dev, addr, msgs[1].buf, rd_len,605			     FT260_FLAG_START_STOP_REPEATED);606	if (ret < 0)607		return ret;608 609	return 0;610}611 612static int ft260_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,613			  int num)614{615	int ret;616	struct ft260_device *dev = i2c_get_adapdata(adapter);617	struct hid_device *hdev = dev->hdev;618 619	mutex_lock(&dev->lock);620 621	ret = hid_hw_power(hdev, PM_HINT_FULLON);622	if (ret < 0) {623		hid_err(hdev, "failed to enter FULLON power mode: %d\n", ret);624		mutex_unlock(&dev->lock);625		return ret;626	}627 628	if (num == 1) {629		if (msgs->flags & I2C_M_RD)630			ret = ft260_i2c_read(dev, msgs->addr, msgs->buf,631					     msgs->len, FT260_FLAG_START_STOP);632		else633			ret = ft260_i2c_write(dev, msgs->addr, msgs->buf,634					      msgs->len, FT260_FLAG_START_STOP);635		if (ret < 0)636			goto i2c_exit;637 638	} else {639		/* Combined write then read message */640		ret = ft260_i2c_write_read(dev, msgs);641		if (ret < 0)642			goto i2c_exit;643	}644 645	ret = num;646i2c_exit:647	hid_hw_power(hdev, PM_HINT_NORMAL);648	mutex_unlock(&dev->lock);649	return ret;650}651 652static int ft260_smbus_xfer(struct i2c_adapter *adapter, u16 addr, u16 flags,653			    char read_write, u8 cmd, int size,654			    union i2c_smbus_data *data)655{656	int ret;657	struct ft260_device *dev = i2c_get_adapdata(adapter);658	struct hid_device *hdev = dev->hdev;659 660	ft260_dbg("smbus size %d\n", size);661 662	mutex_lock(&dev->lock);663 664	ret = hid_hw_power(hdev, PM_HINT_FULLON);665	if (ret < 0) {666		hid_err(hdev, "power management error: %d\n", ret);667		mutex_unlock(&dev->lock);668		return ret;669	}670 671	switch (size) {672	case I2C_SMBUS_BYTE:673		if (read_write == I2C_SMBUS_READ)674			ret = ft260_i2c_read(dev, addr, &data->byte, 1,675					     FT260_FLAG_START_STOP);676		else677			ret = ft260_smbus_write(dev, addr, cmd, NULL, 0,678						FT260_FLAG_START_STOP);679		break;680	case I2C_SMBUS_BYTE_DATA:681		if (read_write == I2C_SMBUS_READ) {682			ret = ft260_smbus_write(dev, addr, cmd, NULL, 0,683						FT260_FLAG_START);684			if (ret)685				goto smbus_exit;686 687			ret = ft260_i2c_read(dev, addr, &data->byte, 1,688					     FT260_FLAG_START_STOP_REPEATED);689		} else {690			ret = ft260_smbus_write(dev, addr, cmd, &data->byte, 1,691						FT260_FLAG_START_STOP);692		}693		break;694	case I2C_SMBUS_WORD_DATA:695		if (read_write == I2C_SMBUS_READ) {696			ret = ft260_smbus_write(dev, addr, cmd, NULL, 0,697						FT260_FLAG_START);698			if (ret)699				goto smbus_exit;700 701			ret = ft260_i2c_read(dev, addr, (u8 *)&data->word, 2,702					     FT260_FLAG_START_STOP_REPEATED);703		} else {704			ret = ft260_smbus_write(dev, addr, cmd,705						(u8 *)&data->word, 2,706						FT260_FLAG_START_STOP);707		}708		break;709	case I2C_SMBUS_BLOCK_DATA:710		if (read_write == I2C_SMBUS_READ) {711			ret = ft260_smbus_write(dev, addr, cmd, NULL, 0,712						FT260_FLAG_START);713			if (ret)714				goto smbus_exit;715 716			ret = ft260_i2c_read(dev, addr, data->block,717					     data->block[0] + 1,718					     FT260_FLAG_START_STOP_REPEATED);719		} else {720			ret = ft260_smbus_write(dev, addr, cmd, data->block,721						data->block[0] + 1,722						FT260_FLAG_START_STOP);723		}724		break;725	case I2C_SMBUS_I2C_BLOCK_DATA:726		if (read_write == I2C_SMBUS_READ) {727			ret = ft260_smbus_write(dev, addr, cmd, NULL, 0,728						FT260_FLAG_START);729			if (ret)730				goto smbus_exit;731 732			ret = ft260_i2c_read(dev, addr, data->block + 1,733					     data->block[0],734					     FT260_FLAG_START_STOP_REPEATED);735		} else {736			ret = ft260_smbus_write(dev, addr, cmd, data->block + 1,737						data->block[0],738						FT260_FLAG_START_STOP);739		}740		break;741	default:742		hid_err(hdev, "unsupported smbus transaction size %d\n", size);743		ret = -EOPNOTSUPP;744	}745 746smbus_exit:747	hid_hw_power(hdev, PM_HINT_NORMAL);748	mutex_unlock(&dev->lock);749	return ret;750}751 752static u32 ft260_functionality(struct i2c_adapter *adap)753{754	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE |755	       I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |756	       I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_I2C_BLOCK;757}758 759static const struct i2c_adapter_quirks ft260_i2c_quirks = {760	.flags = I2C_AQ_COMB_WRITE_THEN_READ,761	.max_comb_1st_msg_len = 2,762};763 764static const struct i2c_algorithm ft260_i2c_algo = {765	.master_xfer = ft260_i2c_xfer,766	.smbus_xfer = ft260_smbus_xfer,767	.functionality = ft260_functionality,768};769 770static int ft260_get_system_config(struct hid_device *hdev,771				   struct ft260_get_system_status_report *cfg)772{773	int ret;774	int len = sizeof(struct ft260_get_system_status_report);775 776	ret = ft260_hid_feature_report_get(hdev, FT260_SYSTEM_SETTINGS,777					   (u8 *)cfg, len);778	if (ret < 0) {779		hid_err(hdev, "failed to retrieve system status\n");780		return ret;781	}782	return 0;783}784 785static int ft260_is_interface_enabled(struct hid_device *hdev)786{787	struct ft260_get_system_status_report cfg;788	struct usb_interface *usbif = to_usb_interface(hdev->dev.parent);789	int interface = usbif->cur_altsetting->desc.bInterfaceNumber;790	int ret;791 792	ret = ft260_get_system_config(hdev, &cfg);793	if (ret < 0)794		return ret;795 796	ft260_dbg("interface:  0x%02x\n", interface);797	ft260_dbg("chip mode:  0x%02x\n", cfg.chip_mode);798	ft260_dbg("clock_ctl:  0x%02x\n", cfg.clock_ctl);799	ft260_dbg("i2c_enable: 0x%02x\n", cfg.i2c_enable);800	ft260_dbg("uart_mode:  0x%02x\n", cfg.uart_mode);801 802	switch (cfg.chip_mode) {803	case FT260_MODE_ALL:804	case FT260_MODE_BOTH:805		if (interface == 1)806			hid_info(hdev, "uart interface is not supported\n");807		else808			ret = 1;809		break;810	case FT260_MODE_UART:811		hid_info(hdev, "uart interface is not supported\n");812		break;813	case FT260_MODE_I2C:814		ret = 1;815		break;816	}817	return ret;818}819 820static int ft260_byte_show(struct hid_device *hdev, int id, u8 *cfg, int len,821			   u8 *field, u8 *buf)822{823	int ret;824 825	ret = ft260_hid_feature_report_get(hdev, id, cfg, len);826	if (ret < 0)827		return ret;828 829	return scnprintf(buf, PAGE_SIZE, "%d\n", *field);830}831 832static int ft260_word_show(struct hid_device *hdev, int id, u8 *cfg, int len,833			   __le16 *field, u8 *buf)834{835	int ret;836 837	ret = ft260_hid_feature_report_get(hdev, id, cfg, len);838	if (ret < 0)839		return ret;840 841	return scnprintf(buf, PAGE_SIZE, "%d\n", le16_to_cpu(*field));842}843 844#define FT260_ATTR_SHOW(name, reptype, id, type, func)			       \845	static ssize_t name##_show(struct device *kdev,			       \846				   struct device_attribute *attr, char *buf)   \847	{								       \848		struct reptype rep;					       \849		struct hid_device *hdev = to_hid_device(kdev);		       \850		type *field = &rep.name;				       \851		int len = sizeof(rep);					       \852									       \853		return func(hdev, id, (u8 *)&rep, len, field, buf);	       \854	}855 856#define FT260_SSTAT_ATTR_SHOW(name)					       \857		FT260_ATTR_SHOW(name, ft260_get_system_status_report,	       \858				FT260_SYSTEM_SETTINGS, u8, ft260_byte_show)859 860#define FT260_I2CST_ATTR_SHOW(name)					       \861		FT260_ATTR_SHOW(name, ft260_get_i2c_status_report,	       \862				FT260_I2C_STATUS, __le16, ft260_word_show)863 864#define FT260_ATTR_STORE(name, reptype, id, req, type, ctype, func)	       \865	static ssize_t name##_store(struct device *kdev,		       \866				    struct device_attribute *attr,	       \867				    const char *buf, size_t count)	       \868	{								       \869		struct reptype rep;					       \870		struct hid_device *hdev = to_hid_device(kdev);		       \871		type name;						       \872		int ret;						       \873									       \874		if (!func(buf, 10, (ctype *)&name)) {			       \875			rep.name = name;				       \876			rep.report = id;				       \877			rep.request = req;				       \878			ret = ft260_hid_feature_report_set(hdev, (u8 *)&rep,   \879							   sizeof(rep));       \880			if (!ret)					       \881				ret = count;				       \882		} else {						       \883			ret = -EINVAL;					       \884		}							       \885		return ret;						       \886	}887 888#define FT260_BYTE_ATTR_STORE(name, reptype, req)			       \889		FT260_ATTR_STORE(name, reptype, FT260_SYSTEM_SETTINGS, req,    \890				 u8, u8, kstrtou8)891 892#define FT260_WORD_ATTR_STORE(name, reptype, req)			       \893		FT260_ATTR_STORE(name, reptype, FT260_SYSTEM_SETTINGS, req,    \894				 __le16, u16, kstrtou16)895 896FT260_SSTAT_ATTR_SHOW(chip_mode);897static DEVICE_ATTR_RO(chip_mode);898 899FT260_SSTAT_ATTR_SHOW(pwren_status);900static DEVICE_ATTR_RO(pwren_status);901 902FT260_SSTAT_ATTR_SHOW(suspend_status);903static DEVICE_ATTR_RO(suspend_status);904 905FT260_SSTAT_ATTR_SHOW(hid_over_i2c_en);906static DEVICE_ATTR_RO(hid_over_i2c_en);907 908FT260_SSTAT_ATTR_SHOW(power_saving_en);909static DEVICE_ATTR_RO(power_saving_en);910 911FT260_SSTAT_ATTR_SHOW(i2c_enable);912FT260_BYTE_ATTR_STORE(i2c_enable, ft260_set_i2c_mode_report,913		      FT260_SET_I2C_MODE);914static DEVICE_ATTR_RW(i2c_enable);915 916FT260_SSTAT_ATTR_SHOW(uart_mode);917FT260_BYTE_ATTR_STORE(uart_mode, ft260_set_uart_mode_report,918		      FT260_SET_UART_MODE);919static DEVICE_ATTR_RW(uart_mode);920 921FT260_SSTAT_ATTR_SHOW(clock_ctl);922FT260_BYTE_ATTR_STORE(clock_ctl, ft260_set_system_clock_report,923		      FT260_SET_CLOCK);924static DEVICE_ATTR_RW(clock_ctl);925 926FT260_I2CST_ATTR_SHOW(clock);927FT260_WORD_ATTR_STORE(clock, ft260_set_i2c_speed_report,928		      FT260_SET_I2C_CLOCK_SPEED);929static DEVICE_ATTR_RW(clock);930 931static ssize_t i2c_reset_store(struct device *kdev,932			       struct device_attribute *attr, const char *buf,933			       size_t count)934{935	struct hid_device *hdev = to_hid_device(kdev);936	int ret = ft260_i2c_reset(hdev);937 938	if (ret)939		return ret;940	return count;941}942static DEVICE_ATTR_WO(i2c_reset);943 944static const struct attribute_group ft260_attr_group = {945	.attrs = (struct attribute *[]) {946		  &dev_attr_chip_mode.attr,947		  &dev_attr_pwren_status.attr,948		  &dev_attr_suspend_status.attr,949		  &dev_attr_hid_over_i2c_en.attr,950		  &dev_attr_power_saving_en.attr,951		  &dev_attr_i2c_enable.attr,952		  &dev_attr_uart_mode.attr,953		  &dev_attr_clock_ctl.attr,954		  &dev_attr_i2c_reset.attr,955		  &dev_attr_clock.attr,956		  NULL957	}958};959 960static int ft260_probe(struct hid_device *hdev, const struct hid_device_id *id)961{962	struct ft260_device *dev;963	struct ft260_get_chip_version_report version;964	int ret;965 966	if (!hid_is_usb(hdev))967		return -EINVAL;968 969	dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL);970	if (!dev)971		return -ENOMEM;972 973	ret = hid_parse(hdev);974	if (ret) {975		hid_err(hdev, "failed to parse HID\n");976		return ret;977	}978 979	ret = hid_hw_start(hdev, 0);980	if (ret) {981		hid_err(hdev, "failed to start HID HW\n");982		return ret;983	}984 985	ret = hid_hw_open(hdev);986	if (ret) {987		hid_err(hdev, "failed to open HID HW\n");988		goto err_hid_stop;989	}990 991	ret = ft260_hid_feature_report_get(hdev, FT260_CHIP_VERSION,992					   (u8 *)&version, sizeof(version));993	if (ret < 0) {994		hid_err(hdev, "failed to retrieve chip version\n");995		goto err_hid_close;996	}997 998	hid_info(hdev, "chip code: %02x%02x %02x%02x\n",999		 version.chip_code[0], version.chip_code[1],1000		 version.chip_code[2], version.chip_code[3]);1001 1002	ret = ft260_is_interface_enabled(hdev);1003	if (ret <= 0)1004		goto err_hid_close;1005 1006	hid_info(hdev, "USB HID v%x.%02x Device [%s] on %s\n",1007		hdev->version >> 8, hdev->version & 0xff, hdev->name,1008		hdev->phys);1009 1010	hid_set_drvdata(hdev, dev);1011	dev->hdev = hdev;1012	dev->adap.owner = THIS_MODULE;1013	dev->adap.class = I2C_CLASS_HWMON;1014	dev->adap.algo = &ft260_i2c_algo;1015	dev->adap.quirks = &ft260_i2c_quirks;1016	dev->adap.dev.parent = &hdev->dev;1017	snprintf(dev->adap.name, sizeof(dev->adap.name),1018		 "FT260 usb-i2c bridge");1019 1020	mutex_init(&dev->lock);1021	init_completion(&dev->wait);1022 1023	ret = ft260_xfer_status(dev, FT260_I2C_STATUS_BUS_BUSY);1024	if (ret)1025		ft260_i2c_reset(hdev);1026 1027	i2c_set_adapdata(&dev->adap, dev);1028	ret = i2c_add_adapter(&dev->adap);1029	if (ret) {1030		hid_err(hdev, "failed to add i2c adapter\n");1031		goto err_hid_close;1032	}1033 1034	ret = sysfs_create_group(&hdev->dev.kobj, &ft260_attr_group);1035	if (ret < 0) {1036		hid_err(hdev, "failed to create sysfs attrs\n");1037		goto err_i2c_free;1038	}1039 1040	return 0;1041 1042err_i2c_free:1043	i2c_del_adapter(&dev->adap);1044err_hid_close:1045	hid_hw_close(hdev);1046err_hid_stop:1047	hid_hw_stop(hdev);1048	return ret;1049}1050 1051static void ft260_remove(struct hid_device *hdev)1052{1053	struct ft260_device *dev = hid_get_drvdata(hdev);1054 1055	if (!dev)1056		return;1057 1058	sysfs_remove_group(&hdev->dev.kobj, &ft260_attr_group);1059	i2c_del_adapter(&dev->adap);1060 1061	hid_hw_close(hdev);1062	hid_hw_stop(hdev);1063}1064 1065static int ft260_raw_event(struct hid_device *hdev, struct hid_report *report,1066			   u8 *data, int size)1067{1068	struct ft260_device *dev = hid_get_drvdata(hdev);1069	struct ft260_i2c_input_report *xfer = (void *)data;1070 1071	if (xfer->report >= FT260_I2C_REPORT_MIN &&1072	    xfer->report <= FT260_I2C_REPORT_MAX) {1073		ft260_dbg("i2c resp: rep %#02x len %d\n", xfer->report,1074			  xfer->length);1075 1076		if ((dev->read_buf == NULL) ||1077		    (xfer->length > dev->read_len - dev->read_idx)) {1078			hid_err(hdev, "unexpected report %#02x, length %d\n",1079				xfer->report, xfer->length);1080			return -1;1081		}1082 1083		memcpy(&dev->read_buf[dev->read_idx], &xfer->data,1084		       xfer->length);1085		dev->read_idx += xfer->length;1086 1087		if (dev->read_idx == dev->read_len)1088			complete(&dev->wait);1089 1090	} else {1091		hid_err(hdev, "unhandled report %#02x\n", xfer->report);1092	}1093	return 0;1094}1095 1096static struct hid_driver ft260_driver = {1097	.name		= "ft260",1098	.id_table	= ft260_devices,1099	.probe		= ft260_probe,1100	.remove		= ft260_remove,1101	.raw_event	= ft260_raw_event,1102};1103 1104module_hid_driver(ft260_driver);1105MODULE_DESCRIPTION("FTDI FT260 USB HID to I2C host bridge");1106MODULE_AUTHOR("Michael Zaidman <michael.zaidman@gmail.com>");1107MODULE_LICENSE("GPL v2");1108