17
17
/* Default SPI clock rate, in kHz */
18
18
#define SPIMAXCLOCK 1000
19
19
20
-
21
- /*
22
- * FTDI bitbang pins:
23
- * D0 - TXD
24
- * D1 - RXD
25
- * D2 - RTS#
26
- * D3 - CTS#
27
- * D4 - DTR#
28
- * D5 - DSR#
29
- * D6 - DCD#
30
- * D7 - RI#
31
- */
32
-
33
- /* Pinout. Change it at will. Beware that FTDI adapters provide 5V or 3V3 I/O
34
- * levels, but CSR chips require 3V3 or 1V8 I/O level. */
35
- #define PIN_nCS (1 << 4) /* FT232RL pin 2 (DTR#/D4), output */
36
- #define PIN_CLK (1 << 2) /* FT232RL pin 3 (RTS#/D2), output */
37
- #define PIN_MOSI (1 << 7) /* FT232RL pin 6 (RI#/D7), output */
38
- #define PIN_MISO (1 << 5) /* FT232RL pin 9 (DSR#/D5), input */
39
- #ifdef ENABLE_LEDS
40
- #define PIN_nLED_RD (1 << 6) /* FT232RL pin 10 (DCD#/D6), output */
41
- #define PIN_nLED_WR (1 << 3) /* FT232RL pin 11 (CTS#/D3), output */
42
- #define PINS_OUTPUT (PIN_MOSI | PIN_CLK | PIN_nCS | PIN_nLED_RD | PIN_nLED_WR)
43
- /* Set initial pin state: CS high, MISO high as pullup, MOSI and CLK low, LEDs off */
44
- #define PINS_INIT (PIN_nCS | PIN_MISO | PIN_nLED_WR | PIN_nLED_RD)
45
- #else
46
- #define PINS_OUTPUT (PIN_MOSI | PIN_CLK | PIN_nCS)
47
- #define PINS_INIT (PIN_nCS | PIN_MISO)
48
- #endif
49
-
50
20
static char * ftdi_type_str = NULL ;
51
21
52
22
static uint8_t * ftdi_out_buf = NULL , * ftdi_in_buf = NULL ;
@@ -57,12 +27,11 @@ static int spi_dev_open = 0;
57
27
static int spi_nrefs = 0 ;
58
28
59
29
static struct ftdi_context ftdic ;
30
+ static enum ftdi_interface ftdi_intf = INTERFACE_A ;
60
31
static uint8_t ftdi_pin_state = 0 ;
61
32
62
- #ifdef ENABLE_LEDS
63
33
#define SPI_LED_FREQ 10 /* Hz */
64
34
static int spi_led_state = 0 ;
65
- #endif
66
35
67
36
#ifdef SPI_STATS
68
37
static struct spi_stats {
@@ -100,6 +69,10 @@ static struct ftdi_device_ids ftdi_device_ids[] = {
100
69
static char * spi_err_buf = NULL ;
101
70
static size_t spi_err_buf_sz = 0 ;
102
71
72
+ static struct spi_pins * spi_pins ;
73
+ static struct spi_pins spi_pin_presets [] = SPI_PIN_PRESETS ;
74
+ static enum spi_pinouts spi_pinout = SPI_PINOUT_DEFAULT ;
75
+
103
76
void spi_set_err_buf (char * buf , size_t sz )
104
77
{
105
78
if (buf && sz ) {
@@ -212,14 +185,16 @@ static int spi_ftdi_xfer(uint8_t *out_buf, uint8_t *in_buf, int size)
212
185
return 0 ;
213
186
}
214
187
215
- #ifdef ENABLE_LEDS
216
188
static void spi_led_tick (void )
217
189
{
218
190
struct timeval tv ;
219
191
220
192
if (spi_led_state == SPI_LED_OFF ) {
221
193
/* Asked to turn LEDs off */
222
- ftdi_pin_state |= PIN_nLED_WR | PIN_nLED_RD ;
194
+ if (spi_pins -> nledr )
195
+ ftdi_pin_state |= spi_pins -> nledr ;
196
+ if (spi_pins -> nledw )
197
+ ftdi_pin_state |= spi_pins -> nledw ;
223
198
return ;
224
199
}
225
200
@@ -229,12 +204,15 @@ static void spi_led_tick(void)
229
204
if (((tv .tv_sec * 1000 + tv .tv_usec / 1000 ) /
230
205
(1000 / SPI_LED_FREQ / 2 )) % 2 == 0 )
231
206
{
232
- if (spi_led_state & SPI_LED_READ )
233
- ftdi_pin_state &= ~PIN_nLED_RD ;
234
- if (spi_led_state & SPI_LED_WRITE )
235
- ftdi_pin_state &= ~PIN_nLED_WR ;
207
+ if (spi_led_state & SPI_LED_READ && spi_pins -> nledr )
208
+ ftdi_pin_state &= ~spi_pins -> nledr ;
209
+ if (spi_led_state & SPI_LED_WRITE && spi_pins -> nledw )
210
+ ftdi_pin_state &= ~spi_pins -> nledw ;
236
211
} else {
237
- ftdi_pin_state |= PIN_nLED_WR | PIN_nLED_RD ;
212
+ if (spi_pins -> nledr )
213
+ ftdi_pin_state |= spi_pins -> nledr ;
214
+ if (spi_pins -> nledw )
215
+ ftdi_pin_state |= spi_pins -> nledw ;
238
216
}
239
217
}
240
218
@@ -243,7 +221,6 @@ void spi_led(int led)
243
221
spi_led_state = led ;
244
222
spi_led_tick ();
245
223
}
246
- #endif
247
224
248
225
/*
249
226
* spi_xfer_*() use global output and input buffers. Output buffer is flushed
@@ -270,9 +247,7 @@ int spi_xfer_begin(int get_status)
270
247
return -1 ;
271
248
}
272
249
273
- #ifdef ENABLE_LEDS
274
250
spi_led_tick ();
275
- #endif
276
251
277
252
#ifdef SPI_STATS
278
253
if (gettimeofday (& spi_stats .tv_xfer_begin , NULL ) < 0 )
@@ -292,24 +267,24 @@ int spi_xfer_begin(int get_status)
292
267
/* BlueCore chip SPI port reset sequence: deassert CS, wait at least two
293
268
* clock cycles */
294
269
295
- ftdi_pin_state |= PIN_nCS ;
270
+ ftdi_pin_state |= spi_pins -> ncs ;
296
271
ftdi_out_buf [ftdi_out_buf_offset ++ ] = ftdi_pin_state ;
297
272
298
- ftdi_pin_state |= PIN_CLK ;
273
+ ftdi_pin_state |= spi_pins -> clk ;
299
274
ftdi_out_buf [ftdi_out_buf_offset ++ ] = ftdi_pin_state ;
300
275
301
- ftdi_pin_state &= ~PIN_CLK ;
276
+ ftdi_pin_state &= ~spi_pins -> clk ;
302
277
ftdi_out_buf [ftdi_out_buf_offset ++ ] = ftdi_pin_state ;
303
278
304
- ftdi_pin_state |= PIN_CLK ;
279
+ ftdi_pin_state |= spi_pins -> clk ;
305
280
ftdi_out_buf [ftdi_out_buf_offset ++ ] = ftdi_pin_state ;
306
281
307
- ftdi_pin_state &= ~PIN_CLK ;
282
+ ftdi_pin_state &= ~spi_pins -> clk ;
308
283
ftdi_out_buf [ftdi_out_buf_offset ++ ] = ftdi_pin_state ;
309
284
310
285
/* Start transfer */
311
286
312
- ftdi_pin_state &= ~PIN_nCS ;
287
+ ftdi_pin_state &= ~spi_pins -> ncs ;
313
288
ftdi_out_buf [ftdi_out_buf_offset ++ ] = ftdi_pin_state ;
314
289
315
290
if (get_status ) {
@@ -330,7 +305,7 @@ int spi_xfer_begin(int get_status)
330
305
if (spi_ftdi_xfer (ftdi_out_buf , ftdi_in_buf , ftdi_out_buf_offset ) < 0 )
331
306
return -1 ;
332
307
333
- if (ftdi_in_buf [status_offset ] & PIN_MISO )
308
+ if (ftdi_in_buf [status_offset ] & spi_pins -> miso )
334
309
status = SPI_CPU_STOPPED ;
335
310
else
336
311
status = SPI_CPU_RUNNING ;
@@ -361,7 +336,7 @@ int spi_xfer_end(void)
361
336
/* Commit the last ftdi_pin_state after spi_xfer() */
362
337
ftdi_out_buf [ftdi_out_buf_offset ++ ] = ftdi_pin_state ;
363
338
364
- ftdi_pin_state |= PIN_nCS ;
339
+ ftdi_pin_state |= spi_pins -> ncs ;
365
340
ftdi_out_buf [ftdi_out_buf_offset ++ ] = ftdi_pin_state ;
366
341
367
342
/* Buffer flush is done on close */
@@ -377,9 +352,7 @@ int spi_xfer_end(void)
377
352
}
378
353
#endif
379
354
380
- #ifdef ENABLE_LEDS
381
355
spi_led (SPI_LED_OFF );
382
- #endif
383
356
384
357
return 0 ;
385
358
}
@@ -395,9 +368,7 @@ int spi_xfer(int cmd, int iosize, void *buf, int size)
395
368
read_offset = 0 ;
396
369
397
370
do {
398
- #ifdef ENABLE_LEDS
399
371
spi_led_tick ();
400
- #endif
401
372
402
373
/* In FTDI sync bitbang mode we need to write something to device to
403
374
* toggle a read. */
@@ -429,22 +400,22 @@ int spi_xfer(int cmd, int iosize, void *buf, int size)
429
400
if (cmd & SPI_XFER_WRITE ) {
430
401
/* Set output bit */
431
402
if (word & bit )
432
- ftdi_pin_state |= PIN_MOSI ;
403
+ ftdi_pin_state |= spi_pins -> mosi ;
433
404
else
434
- ftdi_pin_state &= ~PIN_MOSI ;
405
+ ftdi_pin_state &= ~spi_pins -> mosi ;
435
406
} else {
436
407
/* Write 0 during a read */
437
- ftdi_pin_state &= ~PIN_MOSI ;
408
+ ftdi_pin_state &= ~spi_pins -> mosi ;
438
409
}
439
410
440
411
ftdi_out_buf [ftdi_out_buf_offset ++ ] = ftdi_pin_state ;
441
412
442
413
/* Clock high */
443
- ftdi_pin_state |= PIN_CLK ;
414
+ ftdi_pin_state |= spi_pins -> clk ;
444
415
ftdi_out_buf [ftdi_out_buf_offset ++ ] = ftdi_pin_state ;
445
416
446
417
/* Clock low */
447
- ftdi_pin_state &= ~PIN_CLK ;
418
+ ftdi_pin_state &= ~spi_pins -> clk ;
448
419
}
449
420
write_offset ++ ;
450
421
}
@@ -460,7 +431,7 @@ int spi_xfer(int cmd, int iosize, void *buf, int size)
460
431
for (bit = (1 << (iosize - 1 )); bit != 0 ; bit >>= 1 ) {
461
432
/* Input bit */
462
433
ftdi_in_buf_offset ++ ;
463
- if (ftdi_in_buf [ftdi_in_buf_offset ] & PIN_MISO )
434
+ if (ftdi_in_buf [ftdi_in_buf_offset ] & spi_pins -> miso )
464
435
word |= bit ;
465
436
ftdi_in_buf_offset ++ ;
466
437
}
@@ -546,6 +517,33 @@ static int spi_enumerate_ports(void)
546
517
return 0 ;
547
518
}
548
519
520
+ void spi_set_pinout (enum spi_pinouts pinout )
521
+ {
522
+ spi_pinout = pinout ;
523
+ }
524
+
525
+ int spi_set_interface (const char * intf )
526
+ {
527
+ enum ftdi_interface eintf ;
528
+
529
+ if (intf [1 ] != '\0' )
530
+ return -1 ;
531
+ if (intf [0 ] == 'a' || intf [0 ] == 'A' || intf [0 ] == '0' ) {
532
+ eintf = INTERFACE_A ;
533
+ } else if (intf [0 ] == 'b' || intf [0 ] == 'B' || intf [0 ] == '1' ) {
534
+ eintf = INTERFACE_B ;
535
+ } else if (intf [0 ] == 'c' || intf [0 ] == 'C' || intf [0 ] == '2' ) {
536
+ eintf = INTERFACE_C ;
537
+ } else if (intf [0 ] == 'd' || intf [0 ] == 'D' || intf [0 ] == '3' ) {
538
+ eintf = INTERFACE_D ;
539
+ } else {
540
+ return -1 ;
541
+ }
542
+
543
+ ftdi_intf = eintf ;
544
+ return 0 ;
545
+ }
546
+
549
547
int spi_init (void )
550
548
{
551
549
LOG (DEBUG , "spi_nrefs=%d, spi_dev_open=%d" , spi_nrefs , spi_dev_open );
@@ -570,6 +568,8 @@ int spi_init(void)
570
568
return -1 ;
571
569
}
572
570
571
+ spi_pins = & spi_pin_presets [spi_pinout ];
572
+
573
573
return 0 ;
574
574
}
575
575
@@ -688,6 +688,7 @@ int spi_open(int nport)
688
688
{
689
689
int rc ;
690
690
char * serial ;
691
+ uint8_t output_pins ;
691
692
692
693
LOG (DEBUG , "(%d) spi_dev_open=%d" , nport , spi_dev_open );
693
694
@@ -707,7 +708,12 @@ int spi_open(int nport)
707
708
LOG (WARN , "gettimeofday failed: %s" , strerror (errno ));
708
709
#endif
709
710
710
- /*ftdi_set_interface(&ftdic, INTERFACE_A);*/ /* XXX for multichannel chips */
711
+ rc = ftdi_set_interface (& ftdic , ftdi_intf );
712
+ if (rc < 0 )
713
+ {
714
+ SPI_ERR ("FTDI: ftdi_set_interface() failed: [%d] %s" , rc , ftdi_get_error_string (& ftdic ));
715
+ goto open_err ;
716
+ }
711
717
712
718
/* Serial number can be unavailable due to SerNumEnable* settings in FTDI
713
719
* EEPROM. Don't try to pass a serial number pointer for such a device to
@@ -752,7 +758,13 @@ int spi_open(int nport)
752
758
goto open_err ;
753
759
}
754
760
755
- rc = ftdi_set_bitmode (& ftdic , PINS_OUTPUT , BITMODE_SYNCBB );
761
+ /* Set pins direction */
762
+ output_pins = spi_pins -> mosi | spi_pins -> clk | spi_pins -> ncs ;
763
+ if (spi_pins -> nledr )
764
+ output_pins |= spi_pins -> nledr ;
765
+ if (spi_pins -> nledw )
766
+ output_pins |= spi_pins -> nledw ;
767
+ rc = ftdi_set_bitmode (& ftdic , output_pins , BITMODE_SYNCBB );
756
768
if (rc < 0 ) {
757
769
SPI_ERR ("FTDI: set synchronous bitbang mode failed: [%d] %s" , rc , ftdi_get_error_string (& ftdic ));
758
770
goto open_err ;
@@ -829,7 +841,12 @@ int spi_open(int nport)
829
841
}
830
842
ftdi_out_buf_offset = 0 ;
831
843
832
- ftdi_pin_state = PINS_INIT ;
844
+ /* Set initial pin state: CS high, MISO high as pullup, MOSI and CLK low, LEDs off */
845
+ ftdi_pin_state = spi_pins -> ncs | spi_pins -> miso ;
846
+ if (spi_pins -> nledr )
847
+ ftdi_pin_state |= spi_pins -> nledr ;
848
+ if (spi_pins -> nledw )
849
+ ftdi_pin_state |= spi_pins -> nledw ;
833
850
ftdi_out_buf [ftdi_out_buf_offset ++ ] = ftdi_pin_state ;
834
851
835
852
return 0 ;
@@ -943,9 +960,7 @@ int spi_close(void)
943
960
LOG (DEBUG , "spi_nrefs=%d, spi_dev_open=%d" , spi_nrefs , spi_dev_open );
944
961
945
962
if (spi_dev_open ) {
946
- #ifdef ENABLE_LEDS
947
963
spi_led (SPI_LED_OFF );
948
- #endif
949
964
950
965
/* Flush and reset the buffers */
951
966
if (ftdi_out_buf_offset ) {
0 commit comments