Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1// SPDX-License-Identifier: GPL-2.0
  2//
  3// QiHeng Electronics ch341a USB-to-SPI adapter driver
  4//
  5// Copyright (C) 2024 Johannes Thumshirn <jth@kernel.org>
  6//
  7// Based on ch341a_spi.c from the flashrom project.
  8
  9#include <linux/module.h>
 10#include <linux/usb.h>
 11#include <linux/spi/spi.h>
 12
 13#define CH341_PACKET_LENGTH 32
 14#define CH341_DEFAULT_TIMEOUT 1000
 15
 16#define CH341A_CMD_UIO_STREAM 0xab
 17
 18#define CH341A_CMD_UIO_STM_END 0x20
 19#define CH341A_CMD_UIO_STM_DIR 0x40
 20#define CH341A_CMD_UIO_STM_OUT 0x80
 21
 22#define CH341A_CMD_I2C_STREAM 0xaa
 23#define CH341A_CMD_I2C_STM_SET 0x60
 24#define CH341A_CMD_I2C_STM_END 0x00
 25
 26#define CH341A_CMD_SPI_STREAM 0xa8
 27
 28#define CH341A_STM_I2C_100K 0x01
 29
 30struct ch341_spi_dev {
 31	struct spi_controller *ctrl;
 32	struct usb_device *udev;
 33	unsigned int write_pipe;
 34	unsigned int read_pipe;
 35	int rx_len;
 36	void *rx_buf;
 37	u8 *tx_buf;
 38	struct urb *rx_urb;
 39	struct spi_device *spidev;
 40};
 41
 42static void ch341_set_cs(struct spi_device *spi, bool is_high)
 43{
 44	struct ch341_spi_dev *ch341 =
 45		spi_controller_get_devdata(spi->controller);
 46	int err;
 47
 48	memset(ch341->tx_buf, 0, CH341_PACKET_LENGTH);
 49	ch341->tx_buf[0] = CH341A_CMD_UIO_STREAM;
 50	ch341->tx_buf[1] = CH341A_CMD_UIO_STM_OUT | (is_high ? 0x36 : 0x37);
 51
 52	if (is_high) {
 53		ch341->tx_buf[2] = CH341A_CMD_UIO_STM_DIR | 0x3f;
 54		ch341->tx_buf[3] = CH341A_CMD_UIO_STM_END;
 55	} else {
 56		ch341->tx_buf[2] = CH341A_CMD_UIO_STM_END;
 57	}
 58
 59	err = usb_bulk_msg(ch341->udev, ch341->write_pipe, ch341->tx_buf,
 60			   (is_high ? 4 : 3), NULL, CH341_DEFAULT_TIMEOUT);
 61	if (err)
 62		dev_err(&spi->dev,
 63			"error sending USB message for setting CS (%d)\n", err);
 64}
 65
 66static int ch341_transfer_one(struct spi_controller *host,
 67			      struct spi_device *spi,
 68			      struct spi_transfer *trans)
 69{
 70	struct ch341_spi_dev *ch341 =
 71		spi_controller_get_devdata(spi->controller);
 72	int len;
 73	int ret;
 74
 75	len = min(CH341_PACKET_LENGTH, trans->len + 1);
 76
 77	memset(ch341->tx_buf, 0, CH341_PACKET_LENGTH);
 78
 79	ch341->tx_buf[0] = CH341A_CMD_SPI_STREAM;
 80
 81	memcpy(ch341->tx_buf + 1, trans->tx_buf, len);
 82
 83	ret = usb_bulk_msg(ch341->udev, ch341->write_pipe, ch341->tx_buf, len,
 84			   NULL, CH341_DEFAULT_TIMEOUT);
 85	if (ret)
 86		return ret;
 87
 88	return usb_bulk_msg(ch341->udev, ch341->read_pipe, trans->rx_buf,
 89			    len - 1, NULL, CH341_DEFAULT_TIMEOUT);
 90}
 91
 92static void ch341_recv(struct urb *urb)
 93{
 94	struct ch341_spi_dev *ch341 = urb->context;
 95	struct usb_device *udev = ch341->udev;
 96
 97	switch (urb->status) {
 98	case 0:
 99		/* success */
100		break;
101	case -ENOENT:
102	case -ECONNRESET:
103	case -EPIPE:
104	case -ESHUTDOWN:
105		dev_dbg(&udev->dev, "rx urb terminated with status: %d\n",
106			urb->status);
107		return;
108	default:
109		dev_dbg(&udev->dev, "rx urb error: %d\n", urb->status);
110		break;
111	}
112}
113
114static int ch341_config_stream(struct ch341_spi_dev *ch341)
115{
116	memset(ch341->tx_buf, 0, CH341_PACKET_LENGTH);
117	ch341->tx_buf[0] = CH341A_CMD_I2C_STREAM;
118	ch341->tx_buf[1] = CH341A_CMD_I2C_STM_SET | CH341A_STM_I2C_100K;
119	ch341->tx_buf[2] = CH341A_CMD_I2C_STM_END;
120
121	return usb_bulk_msg(ch341->udev, ch341->write_pipe, ch341->tx_buf, 3,
122			    NULL, CH341_DEFAULT_TIMEOUT);
123}
124
125static int ch341_enable_pins(struct ch341_spi_dev *ch341, bool enable)
126{
127	memset(ch341->tx_buf, 0, CH341_PACKET_LENGTH);
128	ch341->tx_buf[0] = CH341A_CMD_UIO_STREAM;
129	ch341->tx_buf[1] = CH341A_CMD_UIO_STM_OUT | 0x37;
130	ch341->tx_buf[2] = CH341A_CMD_UIO_STM_DIR | (enable ? 0x3f : 0x00);
131	ch341->tx_buf[3] = CH341A_CMD_UIO_STM_END;
132
133	return usb_bulk_msg(ch341->udev, ch341->write_pipe, ch341->tx_buf, 4,
134			    NULL, CH341_DEFAULT_TIMEOUT);
135}
136
137static struct spi_board_info chip = {
138	.modalias = "spi-ch341a",
139};
140
141static int ch341_probe(struct usb_interface *intf,
142		       const struct usb_device_id *id)
143{
144	struct usb_device *udev = interface_to_usbdev(intf);
145	struct usb_endpoint_descriptor *in, *out;
146	struct ch341_spi_dev *ch341;
147	struct spi_controller *ctrl;
148	int ret;
149
150	ret = usb_find_common_endpoints(intf->cur_altsetting, &in, &out, NULL,
151					NULL);
152	if (ret)
153		return ret;
154
155	ctrl = devm_spi_alloc_host(&udev->dev, sizeof(struct ch341_spi_dev));
156	if (!ctrl)
157		return -ENOMEM;
158
159	ch341 = spi_controller_get_devdata(ctrl);
160	ch341->ctrl = ctrl;
161	ch341->udev = udev;
162	ch341->write_pipe = usb_sndbulkpipe(udev, usb_endpoint_num(out));
163	ch341->read_pipe = usb_rcvbulkpipe(udev, usb_endpoint_num(in));
164
165	ch341->rx_len = usb_endpoint_maxp(in);
166	ch341->rx_buf = devm_kzalloc(&udev->dev, ch341->rx_len, GFP_KERNEL);
167	if (!ch341->rx_buf)
168		return -ENOMEM;
169
170	ch341->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
171	if (!ch341->rx_urb)
172		return -ENOMEM;
173
174	ch341->tx_buf =
175		devm_kzalloc(&udev->dev, CH341_PACKET_LENGTH, GFP_KERNEL);
176	if (!ch341->tx_buf)
177		return -ENOMEM;
178
179	usb_fill_bulk_urb(ch341->rx_urb, udev, ch341->read_pipe, ch341->rx_buf,
180			  ch341->rx_len, ch341_recv, ch341);
181
182	ret = usb_submit_urb(ch341->rx_urb, GFP_KERNEL);
183	if (ret) {
184		usb_free_urb(ch341->rx_urb);
185		return -ENOMEM;
186	}
187
188	ctrl->bus_num = -1;
189	ctrl->mode_bits = SPI_CPHA;
190	ctrl->transfer_one = ch341_transfer_one;
191	ctrl->set_cs = ch341_set_cs;
192	ctrl->auto_runtime_pm = false;
193
194	usb_set_intfdata(intf, ch341);
195
196	ret = ch341_config_stream(ch341);
197	if (ret)
198		return ret;
199
200	ret = ch341_enable_pins(ch341, true);
201	if (ret)
202		return ret;
203
204	ret = spi_register_controller(ctrl);
205	if (ret)
206		return ret;
207
208	ch341->spidev = spi_new_device(ctrl, &chip);
209	if (!ch341->spidev)
210		return -ENOMEM;
211
212	return 0;
213}
214
215static void ch341_disconnect(struct usb_interface *intf)
216{
217	struct ch341_spi_dev *ch341 = usb_get_intfdata(intf);
218
219	spi_unregister_device(ch341->spidev);
220	spi_unregister_controller(ch341->ctrl);
221	ch341_enable_pins(ch341, false);
222	usb_free_urb(ch341->rx_urb);
223}
224
225static const struct usb_device_id ch341_id_table[] = {
226	{ USB_DEVICE(0x1a86, 0x5512) },
227	{ }
228};
229MODULE_DEVICE_TABLE(usb, ch341_id_table);
230
231static struct usb_driver ch341a_usb_driver = {
232	.name = "spi-ch341",
233	.probe = ch341_probe,
234	.disconnect = ch341_disconnect,
235	.id_table = ch341_id_table,
236};
237module_usb_driver(ch341a_usb_driver);
238
239MODULE_AUTHOR("Johannes Thumshirn <jth@kernel.org>");
240MODULE_DESCRIPTION("QiHeng Electronics ch341 USB2SPI");
241MODULE_LICENSE("GPL v2");