1*0d6140beSAndroid Build Coastguard Worker /*
2*0d6140beSAndroid Build Coastguard Worker * This file is part of the flashrom project.
3*0d6140beSAndroid Build Coastguard Worker *
4*0d6140beSAndroid Build Coastguard Worker * Copyright (C) 2011 asbokid <[email protected]>
5*0d6140beSAndroid Build Coastguard Worker * Copyright (C) 2014 Pluto Yang <[email protected]>
6*0d6140beSAndroid Build Coastguard Worker * Copyright (C) 2015-2016 Stefan Tauner
7*0d6140beSAndroid Build Coastguard Worker * Copyright (C) 2015 Urja Rannikko <[email protected]>
8*0d6140beSAndroid Build Coastguard Worker *
9*0d6140beSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or modify
10*0d6140beSAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
11*0d6140beSAndroid Build Coastguard Worker * the Free Software Foundation; either version 2 of the License, or
12*0d6140beSAndroid Build Coastguard Worker * (at your option) any later version.
13*0d6140beSAndroid Build Coastguard Worker *
14*0d6140beSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
15*0d6140beSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
16*0d6140beSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17*0d6140beSAndroid Build Coastguard Worker * GNU General Public License for more details.
18*0d6140beSAndroid Build Coastguard Worker */
19*0d6140beSAndroid Build Coastguard Worker
20*0d6140beSAndroid Build Coastguard Worker #include <stdlib.h>
21*0d6140beSAndroid Build Coastguard Worker #include <string.h>
22*0d6140beSAndroid Build Coastguard Worker #include <libusb.h>
23*0d6140beSAndroid Build Coastguard Worker #include "flash.h"
24*0d6140beSAndroid Build Coastguard Worker #include "programmer.h"
25*0d6140beSAndroid Build Coastguard Worker
26*0d6140beSAndroid Build Coastguard Worker /* LIBUSB_CALL ensures the right calling conventions on libusb callbacks.
27*0d6140beSAndroid Build Coastguard Worker * However, the macro is not defined everywhere. m(
28*0d6140beSAndroid Build Coastguard Worker */
29*0d6140beSAndroid Build Coastguard Worker #ifndef LIBUSB_CALL
30*0d6140beSAndroid Build Coastguard Worker #define LIBUSB_CALL
31*0d6140beSAndroid Build Coastguard Worker #endif
32*0d6140beSAndroid Build Coastguard Worker
33*0d6140beSAndroid Build Coastguard Worker #define USB_TIMEOUT 1000 /* 1000 ms is plenty and we have no backup strategy anyway. */
34*0d6140beSAndroid Build Coastguard Worker #define WRITE_EP 0x02
35*0d6140beSAndroid Build Coastguard Worker #define READ_EP 0x82
36*0d6140beSAndroid Build Coastguard Worker
37*0d6140beSAndroid Build Coastguard Worker #define CH341_PACKET_LENGTH 0x20
38*0d6140beSAndroid Build Coastguard Worker #define CH341_MAX_PACKETS 256
39*0d6140beSAndroid Build Coastguard Worker #define CH341_MAX_PACKET_LEN (CH341_PACKET_LENGTH * CH341_MAX_PACKETS)
40*0d6140beSAndroid Build Coastguard Worker
41*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_SET_OUTPUT 0xA1
42*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_IO_ADDR 0xA2
43*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_PRINT_OUT 0xA3
44*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_SPI_STREAM 0xA8
45*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_SIO_STREAM 0xA9
46*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_I2C_STREAM 0xAA
47*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_UIO_STREAM 0xAB
48*0d6140beSAndroid Build Coastguard Worker
49*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_I2C_STM_START 0x74
50*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_I2C_STM_STOP 0x75
51*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_I2C_STM_OUT 0x80
52*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_I2C_STM_IN 0xC0
53*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_I2C_STM_MAX ( min( 0x3F, CH341_PACKET_LENGTH ) )
54*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_I2C_STM_SET 0x60 // bit 2: SPI with two data pairs D5,D4=out, D7,D6=in
55*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_I2C_STM_US 0x40
56*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_I2C_STM_MS 0x50
57*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_I2C_STM_DLY 0x0F
58*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_I2C_STM_END 0x00
59*0d6140beSAndroid Build Coastguard Worker
60*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_UIO_STM_IN 0x00
61*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_UIO_STM_DIR 0x40
62*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_UIO_STM_OUT 0x80
63*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_UIO_STM_US 0xC0
64*0d6140beSAndroid Build Coastguard Worker #define CH341A_CMD_UIO_STM_END 0x20
65*0d6140beSAndroid Build Coastguard Worker
66*0d6140beSAndroid Build Coastguard Worker #define CH341A_STM_I2C_20K 0x00
67*0d6140beSAndroid Build Coastguard Worker #define CH341A_STM_I2C_100K 0x01
68*0d6140beSAndroid Build Coastguard Worker #define CH341A_STM_I2C_400K 0x02
69*0d6140beSAndroid Build Coastguard Worker #define CH341A_STM_I2C_750K 0x03
70*0d6140beSAndroid Build Coastguard Worker #define CH341A_STM_SPI_DBL 0x04
71*0d6140beSAndroid Build Coastguard Worker
72*0d6140beSAndroid Build Coastguard Worker
73*0d6140beSAndroid Build Coastguard Worker /* Number of parallel IN transfers. 32 seems to produce the most stable throughput on Windows. */
74*0d6140beSAndroid Build Coastguard Worker #define USB_IN_TRANSFERS 32
75*0d6140beSAndroid Build Coastguard Worker
76*0d6140beSAndroid Build Coastguard Worker struct ch341a_spi_data {
77*0d6140beSAndroid Build Coastguard Worker struct libusb_device_handle *handle;
78*0d6140beSAndroid Build Coastguard Worker
79*0d6140beSAndroid Build Coastguard Worker /* We need to use many queued IN transfers for any resemblance of performance (especially on Windows)
80*0d6140beSAndroid Build Coastguard Worker * because USB spec says that transfers end on non-full packets and the device sends the 31 reply
81*0d6140beSAndroid Build Coastguard Worker * data bytes to each 32-byte packet with command + 31 bytes of data... */
82*0d6140beSAndroid Build Coastguard Worker struct libusb_transfer *transfer_out;
83*0d6140beSAndroid Build Coastguard Worker struct libusb_transfer *transfer_ins[USB_IN_TRANSFERS];
84*0d6140beSAndroid Build Coastguard Worker
85*0d6140beSAndroid Build Coastguard Worker /* Accumulate delays to be plucked between CS deassertion and CS assertions. */
86*0d6140beSAndroid Build Coastguard Worker unsigned int stored_delay_us;
87*0d6140beSAndroid Build Coastguard Worker };
88*0d6140beSAndroid Build Coastguard Worker
89*0d6140beSAndroid Build Coastguard Worker static const struct dev_entry devs_ch341a_spi[] = {
90*0d6140beSAndroid Build Coastguard Worker {0x1A86, 0x5512, OK, "Winchiphead (WCH)", "CH341A"},
91*0d6140beSAndroid Build Coastguard Worker
92*0d6140beSAndroid Build Coastguard Worker {0},
93*0d6140beSAndroid Build Coastguard Worker };
94*0d6140beSAndroid Build Coastguard Worker
95*0d6140beSAndroid Build Coastguard Worker enum trans_state {TRANS_ACTIVE = -2, TRANS_ERR = -1, TRANS_IDLE = 0};
96*0d6140beSAndroid Build Coastguard Worker
print_hex(const void * buf,size_t len)97*0d6140beSAndroid Build Coastguard Worker static void print_hex(const void *buf, size_t len)
98*0d6140beSAndroid Build Coastguard Worker {
99*0d6140beSAndroid Build Coastguard Worker size_t i;
100*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < len; i++) {
101*0d6140beSAndroid Build Coastguard Worker msg_pspew(" %02x", ((uint8_t *)buf)[i]);
102*0d6140beSAndroid Build Coastguard Worker if (i % CH341_PACKET_LENGTH == CH341_PACKET_LENGTH - 1)
103*0d6140beSAndroid Build Coastguard Worker msg_pspew("\n");
104*0d6140beSAndroid Build Coastguard Worker }
105*0d6140beSAndroid Build Coastguard Worker }
106*0d6140beSAndroid Build Coastguard Worker
cb_common(const char * func,struct libusb_transfer * transfer)107*0d6140beSAndroid Build Coastguard Worker static void cb_common(const char *func, struct libusb_transfer *transfer)
108*0d6140beSAndroid Build Coastguard Worker {
109*0d6140beSAndroid Build Coastguard Worker int *transfer_cnt = (int*)transfer->user_data;
110*0d6140beSAndroid Build Coastguard Worker
111*0d6140beSAndroid Build Coastguard Worker if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
112*0d6140beSAndroid Build Coastguard Worker /* Silently ACK and exit. */
113*0d6140beSAndroid Build Coastguard Worker *transfer_cnt = TRANS_IDLE;
114*0d6140beSAndroid Build Coastguard Worker return;
115*0d6140beSAndroid Build Coastguard Worker }
116*0d6140beSAndroid Build Coastguard Worker
117*0d6140beSAndroid Build Coastguard Worker if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
118*0d6140beSAndroid Build Coastguard Worker msg_perr("\n%s: error: %s\n", func, libusb_error_name(transfer->status));
119*0d6140beSAndroid Build Coastguard Worker *transfer_cnt = TRANS_ERR;
120*0d6140beSAndroid Build Coastguard Worker } else {
121*0d6140beSAndroid Build Coastguard Worker *transfer_cnt = transfer->actual_length;
122*0d6140beSAndroid Build Coastguard Worker }
123*0d6140beSAndroid Build Coastguard Worker }
124*0d6140beSAndroid Build Coastguard Worker
125*0d6140beSAndroid Build Coastguard Worker /* callback for bulk out async transfer */
cb_out(struct libusb_transfer * transfer)126*0d6140beSAndroid Build Coastguard Worker static void LIBUSB_CALL cb_out(struct libusb_transfer *transfer)
127*0d6140beSAndroid Build Coastguard Worker {
128*0d6140beSAndroid Build Coastguard Worker cb_common(__func__, transfer);
129*0d6140beSAndroid Build Coastguard Worker }
130*0d6140beSAndroid Build Coastguard Worker
131*0d6140beSAndroid Build Coastguard Worker /* callback for bulk in async transfer */
cb_in(struct libusb_transfer * transfer)132*0d6140beSAndroid Build Coastguard Worker static void LIBUSB_CALL cb_in(struct libusb_transfer *transfer)
133*0d6140beSAndroid Build Coastguard Worker {
134*0d6140beSAndroid Build Coastguard Worker cb_common(__func__, transfer);
135*0d6140beSAndroid Build Coastguard Worker }
136*0d6140beSAndroid Build Coastguard Worker
usb_transfer(const struct ch341a_spi_data * data,const char * func,unsigned int writecnt,unsigned int readcnt,const uint8_t * writearr,uint8_t * readarr)137*0d6140beSAndroid Build Coastguard Worker static int32_t usb_transfer(const struct ch341a_spi_data *data, const char *func,
138*0d6140beSAndroid Build Coastguard Worker unsigned int writecnt, unsigned int readcnt, const uint8_t *writearr, uint8_t *readarr)
139*0d6140beSAndroid Build Coastguard Worker {
140*0d6140beSAndroid Build Coastguard Worker int state_out = TRANS_IDLE;
141*0d6140beSAndroid Build Coastguard Worker data->transfer_out->buffer = (uint8_t*)writearr;
142*0d6140beSAndroid Build Coastguard Worker data->transfer_out->length = writecnt;
143*0d6140beSAndroid Build Coastguard Worker data->transfer_out->user_data = &state_out;
144*0d6140beSAndroid Build Coastguard Worker
145*0d6140beSAndroid Build Coastguard Worker /* Schedule write first */
146*0d6140beSAndroid Build Coastguard Worker if (writecnt > 0) {
147*0d6140beSAndroid Build Coastguard Worker state_out = TRANS_ACTIVE;
148*0d6140beSAndroid Build Coastguard Worker int ret = libusb_submit_transfer(data->transfer_out);
149*0d6140beSAndroid Build Coastguard Worker if (ret) {
150*0d6140beSAndroid Build Coastguard Worker msg_perr("%s: failed to submit OUT transfer: %s\n", func, libusb_error_name(ret));
151*0d6140beSAndroid Build Coastguard Worker state_out = TRANS_ERR;
152*0d6140beSAndroid Build Coastguard Worker goto err;
153*0d6140beSAndroid Build Coastguard Worker }
154*0d6140beSAndroid Build Coastguard Worker }
155*0d6140beSAndroid Build Coastguard Worker
156*0d6140beSAndroid Build Coastguard Worker /* Handle all asynchronous packets as long as we have stuff to write or read. The write(s) simply need
157*0d6140beSAndroid Build Coastguard Worker * to complete but we need to scheduling reads as long as we are not done. */
158*0d6140beSAndroid Build Coastguard Worker unsigned int free_idx = 0; /* The IN transfer we expect to be free next. */
159*0d6140beSAndroid Build Coastguard Worker unsigned int in_idx = 0; /* The IN transfer we expect to be completed next. */
160*0d6140beSAndroid Build Coastguard Worker unsigned int in_done = 0;
161*0d6140beSAndroid Build Coastguard Worker unsigned int in_active = 0;
162*0d6140beSAndroid Build Coastguard Worker unsigned int out_done = 0;
163*0d6140beSAndroid Build Coastguard Worker uint8_t *in_buf = readarr;
164*0d6140beSAndroid Build Coastguard Worker int state_in[USB_IN_TRANSFERS] = {0};
165*0d6140beSAndroid Build Coastguard Worker do {
166*0d6140beSAndroid Build Coastguard Worker /* Schedule new reads as long as there are free transfers and unscheduled bytes to read. */
167*0d6140beSAndroid Build Coastguard Worker while ((in_done + in_active) < readcnt && state_in[free_idx] == TRANS_IDLE) {
168*0d6140beSAndroid Build Coastguard Worker unsigned int cur_todo = min(CH341_PACKET_LENGTH - 1, readcnt - in_done - in_active);
169*0d6140beSAndroid Build Coastguard Worker data->transfer_ins[free_idx]->length = cur_todo;
170*0d6140beSAndroid Build Coastguard Worker data->transfer_ins[free_idx]->buffer = in_buf;
171*0d6140beSAndroid Build Coastguard Worker data->transfer_ins[free_idx]->user_data = &state_in[free_idx];
172*0d6140beSAndroid Build Coastguard Worker int ret = libusb_submit_transfer(data->transfer_ins[free_idx]);
173*0d6140beSAndroid Build Coastguard Worker if (ret) {
174*0d6140beSAndroid Build Coastguard Worker state_in[free_idx] = TRANS_ERR;
175*0d6140beSAndroid Build Coastguard Worker msg_perr("%s: failed to submit IN transfer: %s\n",
176*0d6140beSAndroid Build Coastguard Worker func, libusb_error_name(ret));
177*0d6140beSAndroid Build Coastguard Worker goto err;
178*0d6140beSAndroid Build Coastguard Worker }
179*0d6140beSAndroid Build Coastguard Worker in_buf += cur_todo;
180*0d6140beSAndroid Build Coastguard Worker in_active += cur_todo;
181*0d6140beSAndroid Build Coastguard Worker state_in[free_idx] = TRANS_ACTIVE;
182*0d6140beSAndroid Build Coastguard Worker free_idx = (free_idx + 1) % USB_IN_TRANSFERS; /* Increment (and wrap around). */
183*0d6140beSAndroid Build Coastguard Worker }
184*0d6140beSAndroid Build Coastguard Worker
185*0d6140beSAndroid Build Coastguard Worker /* Actually get some work done. */
186*0d6140beSAndroid Build Coastguard Worker libusb_handle_events_timeout(NULL, &(struct timeval){1, 0});
187*0d6140beSAndroid Build Coastguard Worker
188*0d6140beSAndroid Build Coastguard Worker /* Check for the write */
189*0d6140beSAndroid Build Coastguard Worker if (out_done < writecnt) {
190*0d6140beSAndroid Build Coastguard Worker if (state_out == TRANS_ERR) {
191*0d6140beSAndroid Build Coastguard Worker goto err;
192*0d6140beSAndroid Build Coastguard Worker } else if (state_out > 0) {
193*0d6140beSAndroid Build Coastguard Worker out_done += state_out;
194*0d6140beSAndroid Build Coastguard Worker state_out = TRANS_IDLE;
195*0d6140beSAndroid Build Coastguard Worker }
196*0d6140beSAndroid Build Coastguard Worker }
197*0d6140beSAndroid Build Coastguard Worker /* Check for completed transfers. */
198*0d6140beSAndroid Build Coastguard Worker while (state_in[in_idx] != TRANS_IDLE && state_in[in_idx] != TRANS_ACTIVE) {
199*0d6140beSAndroid Build Coastguard Worker if (state_in[in_idx] == TRANS_ERR) {
200*0d6140beSAndroid Build Coastguard Worker goto err;
201*0d6140beSAndroid Build Coastguard Worker }
202*0d6140beSAndroid Build Coastguard Worker /* If a transfer is done, record the number of bytes read and reuse it later. */
203*0d6140beSAndroid Build Coastguard Worker in_done += state_in[in_idx];
204*0d6140beSAndroid Build Coastguard Worker in_active -= state_in[in_idx];
205*0d6140beSAndroid Build Coastguard Worker state_in[in_idx] = TRANS_IDLE;
206*0d6140beSAndroid Build Coastguard Worker in_idx = (in_idx + 1) % USB_IN_TRANSFERS; /* Increment (and wrap around). */
207*0d6140beSAndroid Build Coastguard Worker }
208*0d6140beSAndroid Build Coastguard Worker } while ((out_done < writecnt) || (in_done < readcnt));
209*0d6140beSAndroid Build Coastguard Worker
210*0d6140beSAndroid Build Coastguard Worker if (out_done > 0) {
211*0d6140beSAndroid Build Coastguard Worker msg_pspew("Wrote %d bytes:\n", out_done);
212*0d6140beSAndroid Build Coastguard Worker print_hex(writearr, out_done);
213*0d6140beSAndroid Build Coastguard Worker msg_pspew("\n\n");
214*0d6140beSAndroid Build Coastguard Worker }
215*0d6140beSAndroid Build Coastguard Worker if (in_done > 0) {
216*0d6140beSAndroid Build Coastguard Worker msg_pspew("Read %d bytes:\n", in_done);
217*0d6140beSAndroid Build Coastguard Worker print_hex(readarr, in_done);
218*0d6140beSAndroid Build Coastguard Worker msg_pspew("\n\n");
219*0d6140beSAndroid Build Coastguard Worker }
220*0d6140beSAndroid Build Coastguard Worker return 0;
221*0d6140beSAndroid Build Coastguard Worker err:
222*0d6140beSAndroid Build Coastguard Worker /* Clean up on errors. */
223*0d6140beSAndroid Build Coastguard Worker msg_perr("%s: Failed to %s %d bytes\n", func, (state_out == TRANS_ERR) ? "write" : "read",
224*0d6140beSAndroid Build Coastguard Worker (state_out == TRANS_ERR) ? writecnt : readcnt);
225*0d6140beSAndroid Build Coastguard Worker /* First, we must cancel any ongoing requests and wait for them to be canceled. */
226*0d6140beSAndroid Build Coastguard Worker if ((writecnt > 0) && (state_out == TRANS_ACTIVE)) {
227*0d6140beSAndroid Build Coastguard Worker if (libusb_cancel_transfer(data->transfer_out) != 0)
228*0d6140beSAndroid Build Coastguard Worker state_out = TRANS_ERR;
229*0d6140beSAndroid Build Coastguard Worker }
230*0d6140beSAndroid Build Coastguard Worker if (readcnt > 0) {
231*0d6140beSAndroid Build Coastguard Worker unsigned int i;
232*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < USB_IN_TRANSFERS; i++) {
233*0d6140beSAndroid Build Coastguard Worker if (state_in[i] == TRANS_ACTIVE)
234*0d6140beSAndroid Build Coastguard Worker if (libusb_cancel_transfer(data->transfer_ins[i]) != 0)
235*0d6140beSAndroid Build Coastguard Worker state_in[i] = TRANS_ERR;
236*0d6140beSAndroid Build Coastguard Worker }
237*0d6140beSAndroid Build Coastguard Worker }
238*0d6140beSAndroid Build Coastguard Worker
239*0d6140beSAndroid Build Coastguard Worker /* Wait for cancellations to complete. */
240*0d6140beSAndroid Build Coastguard Worker while (1) {
241*0d6140beSAndroid Build Coastguard Worker bool finished = true;
242*0d6140beSAndroid Build Coastguard Worker if ((writecnt > 0) && (state_out == TRANS_ACTIVE))
243*0d6140beSAndroid Build Coastguard Worker finished = false;
244*0d6140beSAndroid Build Coastguard Worker if (readcnt > 0) {
245*0d6140beSAndroid Build Coastguard Worker unsigned int i;
246*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < USB_IN_TRANSFERS; i++) {
247*0d6140beSAndroid Build Coastguard Worker if (state_in[i] == TRANS_ACTIVE)
248*0d6140beSAndroid Build Coastguard Worker finished = false;
249*0d6140beSAndroid Build Coastguard Worker }
250*0d6140beSAndroid Build Coastguard Worker }
251*0d6140beSAndroid Build Coastguard Worker if (finished)
252*0d6140beSAndroid Build Coastguard Worker break;
253*0d6140beSAndroid Build Coastguard Worker libusb_handle_events_timeout(NULL, &(struct timeval){1, 0});
254*0d6140beSAndroid Build Coastguard Worker }
255*0d6140beSAndroid Build Coastguard Worker return -1;
256*0d6140beSAndroid Build Coastguard Worker }
257*0d6140beSAndroid Build Coastguard Worker
258*0d6140beSAndroid Build Coastguard Worker /* Set the I2C bus speed (speed(b1b0): 0 = 20kHz; 1 = 100kHz, 2 = 400kHz, 3 = 750kHz).
259*0d6140beSAndroid Build Coastguard Worker * Set the SPI bus data width (speed(b2): 0 = Single, 1 = Double). */
config_stream(const struct ch341a_spi_data * data,uint32_t speed)260*0d6140beSAndroid Build Coastguard Worker static int32_t config_stream(const struct ch341a_spi_data *data, uint32_t speed)
261*0d6140beSAndroid Build Coastguard Worker {
262*0d6140beSAndroid Build Coastguard Worker uint8_t buf[] = {
263*0d6140beSAndroid Build Coastguard Worker CH341A_CMD_I2C_STREAM,
264*0d6140beSAndroid Build Coastguard Worker CH341A_CMD_I2C_STM_SET | (speed & 0x7),
265*0d6140beSAndroid Build Coastguard Worker CH341A_CMD_I2C_STM_END
266*0d6140beSAndroid Build Coastguard Worker };
267*0d6140beSAndroid Build Coastguard Worker
268*0d6140beSAndroid Build Coastguard Worker int32_t ret = usb_transfer(data, __func__, sizeof(buf), 0, buf, NULL);
269*0d6140beSAndroid Build Coastguard Worker if (ret < 0) {
270*0d6140beSAndroid Build Coastguard Worker msg_perr("Could not configure stream interface.\n");
271*0d6140beSAndroid Build Coastguard Worker }
272*0d6140beSAndroid Build Coastguard Worker return ret;
273*0d6140beSAndroid Build Coastguard Worker }
274*0d6140beSAndroid Build Coastguard Worker
275*0d6140beSAndroid Build Coastguard Worker /* The assumed map between UIO command bits, pins on CH341A chip and pins on SPI chip:
276*0d6140beSAndroid Build Coastguard Worker * UIO CH341A SPI CH341A SPI name
277*0d6140beSAndroid Build Coastguard Worker * 0 D0/15 CS/1 (CS0)
278*0d6140beSAndroid Build Coastguard Worker * 1 D1/16 unused (CS1)
279*0d6140beSAndroid Build Coastguard Worker * 2 D2/17 unused (CS2)
280*0d6140beSAndroid Build Coastguard Worker * 3 D3/18 SCK/6 (DCK)
281*0d6140beSAndroid Build Coastguard Worker * 4 D4/19 unused (DOUT2)
282*0d6140beSAndroid Build Coastguard Worker * 5 D5/20 SI/5 (DOUT)
283*0d6140beSAndroid Build Coastguard Worker * - The UIO stream commands seem to only have 6 bits of output, and D6/D7 are the SPI inputs,
284*0d6140beSAndroid Build Coastguard Worker * mapped as follows:
285*0d6140beSAndroid Build Coastguard Worker * D6/21 unused (DIN2)
286*0d6140beSAndroid Build Coastguard Worker * D7/22 SO/2 (DIN)
287*0d6140beSAndroid Build Coastguard Worker */
enable_pins(const struct ch341a_spi_data * data,bool enable)288*0d6140beSAndroid Build Coastguard Worker static int32_t enable_pins(const struct ch341a_spi_data *data, bool enable)
289*0d6140beSAndroid Build Coastguard Worker {
290*0d6140beSAndroid Build Coastguard Worker uint8_t buf[] = {
291*0d6140beSAndroid Build Coastguard Worker CH341A_CMD_UIO_STREAM,
292*0d6140beSAndroid Build Coastguard Worker CH341A_CMD_UIO_STM_OUT | 0x37, // CS high (all of them), SCK=0, DOUT*=1
293*0d6140beSAndroid Build Coastguard Worker CH341A_CMD_UIO_STM_DIR | (enable ? 0x3F : 0x00), // Interface output enable / disable
294*0d6140beSAndroid Build Coastguard Worker CH341A_CMD_UIO_STM_END,
295*0d6140beSAndroid Build Coastguard Worker };
296*0d6140beSAndroid Build Coastguard Worker
297*0d6140beSAndroid Build Coastguard Worker int32_t ret = usb_transfer(data, __func__, sizeof(buf), 0, buf, NULL);
298*0d6140beSAndroid Build Coastguard Worker if (ret < 0) {
299*0d6140beSAndroid Build Coastguard Worker msg_perr("Could not %sable output pins.\n", enable ? "en" : "dis");
300*0d6140beSAndroid Build Coastguard Worker }
301*0d6140beSAndroid Build Coastguard Worker return ret;
302*0d6140beSAndroid Build Coastguard Worker }
303*0d6140beSAndroid Build Coastguard Worker
304*0d6140beSAndroid Build Coastguard Worker /* De-assert and assert CS in one operation. */
pluck_cs(uint8_t * ptr,unsigned int * stored_delay_us)305*0d6140beSAndroid Build Coastguard Worker static void pluck_cs(uint8_t *ptr, unsigned int *stored_delay_us)
306*0d6140beSAndroid Build Coastguard Worker {
307*0d6140beSAndroid Build Coastguard Worker /* This was measured to give a minimum deassertion time of 2.25 us,
308*0d6140beSAndroid Build Coastguard Worker * >20x more than needed for most SPI chips (100ns). */
309*0d6140beSAndroid Build Coastguard Worker int delay_cnt = 2;
310*0d6140beSAndroid Build Coastguard Worker if (*stored_delay_us) {
311*0d6140beSAndroid Build Coastguard Worker delay_cnt = (*stored_delay_us * 4) / 3;
312*0d6140beSAndroid Build Coastguard Worker *stored_delay_us = 0;
313*0d6140beSAndroid Build Coastguard Worker }
314*0d6140beSAndroid Build Coastguard Worker *ptr++ = CH341A_CMD_UIO_STREAM;
315*0d6140beSAndroid Build Coastguard Worker *ptr++ = CH341A_CMD_UIO_STM_OUT | 0x37; /* deasserted */
316*0d6140beSAndroid Build Coastguard Worker int i;
317*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < delay_cnt; i++)
318*0d6140beSAndroid Build Coastguard Worker *ptr++ = CH341A_CMD_UIO_STM_OUT | 0x37; /* "delay" */
319*0d6140beSAndroid Build Coastguard Worker *ptr++ = CH341A_CMD_UIO_STM_OUT | 0x36; /* asserted */
320*0d6140beSAndroid Build Coastguard Worker *ptr++ = CH341A_CMD_UIO_STM_END;
321*0d6140beSAndroid Build Coastguard Worker }
322*0d6140beSAndroid Build Coastguard Worker
ch341a_spi_delay(const struct flashctx * flash,unsigned int usecs)323*0d6140beSAndroid Build Coastguard Worker static void ch341a_spi_delay(const struct flashctx *flash, unsigned int usecs)
324*0d6140beSAndroid Build Coastguard Worker {
325*0d6140beSAndroid Build Coastguard Worker struct ch341a_spi_data *data = flash->mst->spi.data;
326*0d6140beSAndroid Build Coastguard Worker
327*0d6140beSAndroid Build Coastguard Worker /* There is space for 28 bytes instructions of 750 ns each in the CS packet (32 - 4 for the actual CS
328*0d6140beSAndroid Build Coastguard Worker * instructions), thus max 21 us, but we avoid getting too near to this boundary and use
329*0d6140beSAndroid Build Coastguard Worker * default_delay() for durations over 20 us. */
330*0d6140beSAndroid Build Coastguard Worker if ((usecs + data->stored_delay_us) > 20) {
331*0d6140beSAndroid Build Coastguard Worker unsigned int inc = 20 - data->stored_delay_us;
332*0d6140beSAndroid Build Coastguard Worker default_delay(usecs - inc);
333*0d6140beSAndroid Build Coastguard Worker usecs = inc;
334*0d6140beSAndroid Build Coastguard Worker }
335*0d6140beSAndroid Build Coastguard Worker data->stored_delay_us += usecs;
336*0d6140beSAndroid Build Coastguard Worker }
337*0d6140beSAndroid Build Coastguard Worker
ch341a_spi_spi_send_command(const struct flashctx * flash,unsigned int writecnt,unsigned int readcnt,const unsigned char * writearr,unsigned char * readarr)338*0d6140beSAndroid Build Coastguard Worker static int ch341a_spi_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr)
339*0d6140beSAndroid Build Coastguard Worker {
340*0d6140beSAndroid Build Coastguard Worker struct ch341a_spi_data *data = flash->mst->spi.data;
341*0d6140beSAndroid Build Coastguard Worker
342*0d6140beSAndroid Build Coastguard Worker /* How many packets ... */
343*0d6140beSAndroid Build Coastguard Worker const size_t packets = (writecnt + readcnt + CH341_PACKET_LENGTH - 2) / (CH341_PACKET_LENGTH - 1);
344*0d6140beSAndroid Build Coastguard Worker
345*0d6140beSAndroid Build Coastguard Worker /* We pluck CS/timeout handling into the first packet thus we need to allocate one extra package. */
346*0d6140beSAndroid Build Coastguard Worker uint8_t wbuf[packets+1][CH341_PACKET_LENGTH];
347*0d6140beSAndroid Build Coastguard Worker uint8_t rbuf[writecnt + readcnt];
348*0d6140beSAndroid Build Coastguard Worker /* Initialize the write buffer to zero to prevent writing random stack contents to device. */
349*0d6140beSAndroid Build Coastguard Worker memset(wbuf[0], 0, CH341_PACKET_LENGTH);
350*0d6140beSAndroid Build Coastguard Worker
351*0d6140beSAndroid Build Coastguard Worker uint8_t *ptr = wbuf[0];
352*0d6140beSAndroid Build Coastguard Worker /* CS usage is optimized by doing both transitions in one packet.
353*0d6140beSAndroid Build Coastguard Worker * Final transition to deselected state is in the pin disable. */
354*0d6140beSAndroid Build Coastguard Worker pluck_cs(ptr, &data->stored_delay_us);
355*0d6140beSAndroid Build Coastguard Worker unsigned int write_left = writecnt;
356*0d6140beSAndroid Build Coastguard Worker unsigned int read_left = readcnt;
357*0d6140beSAndroid Build Coastguard Worker unsigned int p;
358*0d6140beSAndroid Build Coastguard Worker for (p = 0; p < packets; p++) {
359*0d6140beSAndroid Build Coastguard Worker unsigned int write_now = min(CH341_PACKET_LENGTH - 1, write_left);
360*0d6140beSAndroid Build Coastguard Worker unsigned int read_now = min ((CH341_PACKET_LENGTH - 1) - write_now, read_left);
361*0d6140beSAndroid Build Coastguard Worker ptr = wbuf[p+1];
362*0d6140beSAndroid Build Coastguard Worker *ptr++ = CH341A_CMD_SPI_STREAM;
363*0d6140beSAndroid Build Coastguard Worker unsigned int i;
364*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < write_now; ++i)
365*0d6140beSAndroid Build Coastguard Worker *ptr++ = reverse_byte(*writearr++);
366*0d6140beSAndroid Build Coastguard Worker if (read_now) {
367*0d6140beSAndroid Build Coastguard Worker memset(ptr, 0xFF, read_now);
368*0d6140beSAndroid Build Coastguard Worker read_left -= read_now;
369*0d6140beSAndroid Build Coastguard Worker }
370*0d6140beSAndroid Build Coastguard Worker write_left -= write_now;
371*0d6140beSAndroid Build Coastguard Worker }
372*0d6140beSAndroid Build Coastguard Worker
373*0d6140beSAndroid Build Coastguard Worker int32_t ret = usb_transfer(data, __func__, CH341_PACKET_LENGTH + packets + writecnt + readcnt,
374*0d6140beSAndroid Build Coastguard Worker writecnt + readcnt, wbuf[0], rbuf);
375*0d6140beSAndroid Build Coastguard Worker if (ret < 0)
376*0d6140beSAndroid Build Coastguard Worker return -1;
377*0d6140beSAndroid Build Coastguard Worker
378*0d6140beSAndroid Build Coastguard Worker unsigned int i;
379*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < readcnt; i++) {
380*0d6140beSAndroid Build Coastguard Worker *readarr++ = reverse_byte(rbuf[writecnt + i]);
381*0d6140beSAndroid Build Coastguard Worker }
382*0d6140beSAndroid Build Coastguard Worker
383*0d6140beSAndroid Build Coastguard Worker return 0;
384*0d6140beSAndroid Build Coastguard Worker }
385*0d6140beSAndroid Build Coastguard Worker
ch341a_spi_shutdown(void * data)386*0d6140beSAndroid Build Coastguard Worker static int ch341a_spi_shutdown(void *data)
387*0d6140beSAndroid Build Coastguard Worker {
388*0d6140beSAndroid Build Coastguard Worker struct ch341a_spi_data *ch341a_data = data;
389*0d6140beSAndroid Build Coastguard Worker
390*0d6140beSAndroid Build Coastguard Worker enable_pins(ch341a_data, false);
391*0d6140beSAndroid Build Coastguard Worker libusb_free_transfer(ch341a_data->transfer_out);
392*0d6140beSAndroid Build Coastguard Worker int i;
393*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < USB_IN_TRANSFERS; i++)
394*0d6140beSAndroid Build Coastguard Worker libusb_free_transfer(ch341a_data->transfer_ins[i]);
395*0d6140beSAndroid Build Coastguard Worker libusb_release_interface(ch341a_data->handle, 0);
396*0d6140beSAndroid Build Coastguard Worker libusb_attach_kernel_driver(ch341a_data->handle, 0);
397*0d6140beSAndroid Build Coastguard Worker libusb_close(ch341a_data->handle);
398*0d6140beSAndroid Build Coastguard Worker libusb_exit(NULL);
399*0d6140beSAndroid Build Coastguard Worker
400*0d6140beSAndroid Build Coastguard Worker free(data);
401*0d6140beSAndroid Build Coastguard Worker return 0;
402*0d6140beSAndroid Build Coastguard Worker }
403*0d6140beSAndroid Build Coastguard Worker
404*0d6140beSAndroid Build Coastguard Worker static const struct spi_master spi_master_ch341a_spi = {
405*0d6140beSAndroid Build Coastguard Worker .features = SPI_MASTER_4BA,
406*0d6140beSAndroid Build Coastguard Worker /* flashrom's current maximum is 256 B. CH341A was tested on Linux and Windows to accept at least
407*0d6140beSAndroid Build Coastguard Worker * 128 kB. Basically there should be no hard limit because transfers are broken up into USB packets
408*0d6140beSAndroid Build Coastguard Worker * sent to the device and most of their payload streamed via SPI. */
409*0d6140beSAndroid Build Coastguard Worker .max_data_read = 4 * 1024,
410*0d6140beSAndroid Build Coastguard Worker .max_data_write = 4 * 1024,
411*0d6140beSAndroid Build Coastguard Worker .command = ch341a_spi_spi_send_command,
412*0d6140beSAndroid Build Coastguard Worker .read = default_spi_read,
413*0d6140beSAndroid Build Coastguard Worker .write_256 = default_spi_write_256,
414*0d6140beSAndroid Build Coastguard Worker .shutdown = ch341a_spi_shutdown,
415*0d6140beSAndroid Build Coastguard Worker .delay = ch341a_spi_delay,
416*0d6140beSAndroid Build Coastguard Worker };
417*0d6140beSAndroid Build Coastguard Worker
ch341a_spi_init(const struct programmer_cfg * cfg)418*0d6140beSAndroid Build Coastguard Worker static int ch341a_spi_init(const struct programmer_cfg *cfg)
419*0d6140beSAndroid Build Coastguard Worker {
420*0d6140beSAndroid Build Coastguard Worker int32_t ret = libusb_init(NULL);
421*0d6140beSAndroid Build Coastguard Worker if (ret < 0) {
422*0d6140beSAndroid Build Coastguard Worker msg_perr("Couldn't initialize libusb!\n");
423*0d6140beSAndroid Build Coastguard Worker return -1;
424*0d6140beSAndroid Build Coastguard Worker }
425*0d6140beSAndroid Build Coastguard Worker
426*0d6140beSAndroid Build Coastguard Worker /* Enable information, warning, and error messages (only). */
427*0d6140beSAndroid Build Coastguard Worker #if LIBUSB_API_VERSION < 0x01000106
428*0d6140beSAndroid Build Coastguard Worker libusb_set_debug(NULL, 3);
429*0d6140beSAndroid Build Coastguard Worker #else
430*0d6140beSAndroid Build Coastguard Worker libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO);
431*0d6140beSAndroid Build Coastguard Worker #endif
432*0d6140beSAndroid Build Coastguard Worker
433*0d6140beSAndroid Build Coastguard Worker struct ch341a_spi_data *data = calloc(1, sizeof(*data));
434*0d6140beSAndroid Build Coastguard Worker if (!data) {
435*0d6140beSAndroid Build Coastguard Worker msg_perr("Out of memory!\n");
436*0d6140beSAndroid Build Coastguard Worker return 1;
437*0d6140beSAndroid Build Coastguard Worker }
438*0d6140beSAndroid Build Coastguard Worker
439*0d6140beSAndroid Build Coastguard Worker uint16_t vid = devs_ch341a_spi[0].vendor_id;
440*0d6140beSAndroid Build Coastguard Worker uint16_t pid = devs_ch341a_spi[0].device_id;
441*0d6140beSAndroid Build Coastguard Worker data->handle = libusb_open_device_with_vid_pid(NULL, vid, pid);
442*0d6140beSAndroid Build Coastguard Worker if (data->handle == NULL) {
443*0d6140beSAndroid Build Coastguard Worker msg_perr("Couldn't open device %04x:%04x.\n", vid, pid);
444*0d6140beSAndroid Build Coastguard Worker goto free_data;
445*0d6140beSAndroid Build Coastguard Worker }
446*0d6140beSAndroid Build Coastguard Worker
447*0d6140beSAndroid Build Coastguard Worker ret = libusb_detach_kernel_driver(data->handle, 0);
448*0d6140beSAndroid Build Coastguard Worker if (ret != 0 && ret != LIBUSB_ERROR_NOT_FOUND)
449*0d6140beSAndroid Build Coastguard Worker msg_pwarn("Cannot detach the existing USB driver. Claiming the interface may fail. %s\n",
450*0d6140beSAndroid Build Coastguard Worker libusb_error_name(ret));
451*0d6140beSAndroid Build Coastguard Worker
452*0d6140beSAndroid Build Coastguard Worker ret = libusb_claim_interface(data->handle, 0);
453*0d6140beSAndroid Build Coastguard Worker if (ret != 0) {
454*0d6140beSAndroid Build Coastguard Worker msg_perr("Failed to claim interface 0: '%s'\n", libusb_error_name(ret));
455*0d6140beSAndroid Build Coastguard Worker goto close_handle;
456*0d6140beSAndroid Build Coastguard Worker }
457*0d6140beSAndroid Build Coastguard Worker
458*0d6140beSAndroid Build Coastguard Worker struct libusb_device *dev;
459*0d6140beSAndroid Build Coastguard Worker if (!(dev = libusb_get_device(data->handle))) {
460*0d6140beSAndroid Build Coastguard Worker msg_perr("Failed to get device from device handle.\n");
461*0d6140beSAndroid Build Coastguard Worker goto close_handle;
462*0d6140beSAndroid Build Coastguard Worker }
463*0d6140beSAndroid Build Coastguard Worker
464*0d6140beSAndroid Build Coastguard Worker struct libusb_device_descriptor desc;
465*0d6140beSAndroid Build Coastguard Worker ret = libusb_get_device_descriptor(dev, &desc);
466*0d6140beSAndroid Build Coastguard Worker if (ret < 0) {
467*0d6140beSAndroid Build Coastguard Worker msg_perr("Failed to get device descriptor: '%s'\n", libusb_error_name(ret));
468*0d6140beSAndroid Build Coastguard Worker goto release_interface;
469*0d6140beSAndroid Build Coastguard Worker }
470*0d6140beSAndroid Build Coastguard Worker
471*0d6140beSAndroid Build Coastguard Worker msg_pdbg("Device revision is %d.%01d.%01d\n",
472*0d6140beSAndroid Build Coastguard Worker (desc.bcdDevice >> 8) & 0x00FF,
473*0d6140beSAndroid Build Coastguard Worker (desc.bcdDevice >> 4) & 0x000F,
474*0d6140beSAndroid Build Coastguard Worker (desc.bcdDevice >> 0) & 0x000F);
475*0d6140beSAndroid Build Coastguard Worker
476*0d6140beSAndroid Build Coastguard Worker /* Allocate and pre-fill transfer structures. */
477*0d6140beSAndroid Build Coastguard Worker data->transfer_out = libusb_alloc_transfer(0);
478*0d6140beSAndroid Build Coastguard Worker if (!data->transfer_out) {
479*0d6140beSAndroid Build Coastguard Worker msg_perr("Failed to alloc libusb OUT transfer\n");
480*0d6140beSAndroid Build Coastguard Worker goto release_interface;
481*0d6140beSAndroid Build Coastguard Worker }
482*0d6140beSAndroid Build Coastguard Worker int i;
483*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < USB_IN_TRANSFERS; i++) {
484*0d6140beSAndroid Build Coastguard Worker data->transfer_ins[i] = libusb_alloc_transfer(0);
485*0d6140beSAndroid Build Coastguard Worker if (data->transfer_ins[i] == NULL) {
486*0d6140beSAndroid Build Coastguard Worker msg_perr("Failed to alloc libusb IN transfer %d\n", i);
487*0d6140beSAndroid Build Coastguard Worker goto dealloc_transfers;
488*0d6140beSAndroid Build Coastguard Worker }
489*0d6140beSAndroid Build Coastguard Worker }
490*0d6140beSAndroid Build Coastguard Worker /* We use these helpers but dont fill the actual buffer yet. */
491*0d6140beSAndroid Build Coastguard Worker libusb_fill_bulk_transfer(data->transfer_out, data->handle, WRITE_EP, NULL, 0, cb_out, NULL, USB_TIMEOUT);
492*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < USB_IN_TRANSFERS; i++)
493*0d6140beSAndroid Build Coastguard Worker libusb_fill_bulk_transfer(data->transfer_ins[i], data->handle, READ_EP, NULL, 0, cb_in, NULL, USB_TIMEOUT);
494*0d6140beSAndroid Build Coastguard Worker
495*0d6140beSAndroid Build Coastguard Worker if ((config_stream(data, CH341A_STM_I2C_100K) < 0) || (enable_pins(data, true) < 0))
496*0d6140beSAndroid Build Coastguard Worker goto dealloc_transfers;
497*0d6140beSAndroid Build Coastguard Worker
498*0d6140beSAndroid Build Coastguard Worker return register_spi_master(&spi_master_ch341a_spi, data);
499*0d6140beSAndroid Build Coastguard Worker
500*0d6140beSAndroid Build Coastguard Worker dealloc_transfers:
501*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < USB_IN_TRANSFERS; i++) {
502*0d6140beSAndroid Build Coastguard Worker if (data->transfer_ins[i] == NULL)
503*0d6140beSAndroid Build Coastguard Worker break;
504*0d6140beSAndroid Build Coastguard Worker libusb_free_transfer(data->transfer_ins[i]);
505*0d6140beSAndroid Build Coastguard Worker }
506*0d6140beSAndroid Build Coastguard Worker libusb_free_transfer(data->transfer_out);
507*0d6140beSAndroid Build Coastguard Worker release_interface:
508*0d6140beSAndroid Build Coastguard Worker libusb_release_interface(data->handle, 0);
509*0d6140beSAndroid Build Coastguard Worker close_handle:
510*0d6140beSAndroid Build Coastguard Worker libusb_attach_kernel_driver(data->handle, 0);
511*0d6140beSAndroid Build Coastguard Worker libusb_close(data->handle);
512*0d6140beSAndroid Build Coastguard Worker free_data:
513*0d6140beSAndroid Build Coastguard Worker free(data);
514*0d6140beSAndroid Build Coastguard Worker return -1;
515*0d6140beSAndroid Build Coastguard Worker }
516*0d6140beSAndroid Build Coastguard Worker
517*0d6140beSAndroid Build Coastguard Worker const struct programmer_entry programmer_ch341a_spi = {
518*0d6140beSAndroid Build Coastguard Worker .name = "ch341a_spi",
519*0d6140beSAndroid Build Coastguard Worker .type = USB,
520*0d6140beSAndroid Build Coastguard Worker .devs.dev = devs_ch341a_spi,
521*0d6140beSAndroid Build Coastguard Worker .init = ch341a_spi_init,
522*0d6140beSAndroid Build Coastguard Worker };
523