This adds a programmer parameter 'speed' in the dediprog driver to controll the transfer rate on the spi bus. The following rates are available (all in kHz): 24000, 12000, 8000, 3000, 2180, 1500, 750, 375
Signed-off-by: Nico Huber nico.huber@secunet.com
Index: dediprog.c =================================================================== --- dediprog.c (Revision 1541) +++ dediprog.c (Arbeitskopie) @@ -135,7 +144,6 @@ return 0; }
-#if 0 /* After dediprog_set_spi_speed, the original app always calls * dediprog_set_spi_voltage(0) and then * dediprog_check_devicestring() four times in a row. @@ -149,43 +157,43 @@ * This looks suspiciously like the microprocessor in the SF100 has to be * restarted/reinitialized in case the speed changes. */ -static int dediprog_set_spi_speed(uint16_t speed) +static int dediprog_set_spi_speed(unsigned int khz) { int ret; - unsigned int khz; + uint16_t speed;
/* Case 1 and 2 are in weird order. Probably an organically "grown" * interface. * Base frequency is 24000 kHz, divisors are (in order) * 1, 3, 2, 8, 11, 16, 32, 64. */ - switch (speed) { - case 0x0: - khz = 24000; + switch (khz) { + case 24000: + speed = 0; break; - case 0x1: - khz = 8000; + case 8000: + khz = 1; break; - case 0x2: - khz = 12000; + case 12000: + khz = 2; break; - case 0x3: - khz = 3000; + case 3000: + khz = 3; break; - case 0x4: - khz = 2180; + case 2180: + khz = 4; break; - case 0x5: - khz = 1500; + case 1500: + khz = 5; break; - case 0x6: - khz = 750; + case 750: + khz = 6; break; - case 0x7: - khz = 375; + case 375: + khz = 7; break; default: - msg_perr("Unknown frequency selector 0x%x! Aborting.\n", speed); + msg_perr("Unsupported frequency %d kHz! Aborting.\n", khz); return 1; } msg_pdbg("Setting SPI speed to %u kHz\n", khz); @@ -198,7 +206,6 @@ } return 0; } -#endif
/* Bulk read interface, will read multiple 512 byte chunks aligned to 512 bytes. * @start start address @@ -701,6 +708,28 @@ return millivolt; }
+static int dediprog_setup(void) +{ + /* URB 6. Command A. */ + if (dediprog_command_a()) { + return 1; + } + /* URB 7. Command A. */ + if (dediprog_command_a()) { + return 1; + } + /* URB 8. Command Prepare Receive Device String. */ + /* URB 9. Command Receive Device String. */ + if (dediprog_check_devicestring()) { + return 1; + } + /* URB 10. Command C. */ + if (dediprog_command_c()) { + return 1; + } + return 0; +} + static const struct spi_programmer spi_programmer_dediprog = { .type = SPI_CONTROLLER_DEDIPROG, .max_data_read = MAX_DATA_UNSPECIFIED, @@ -741,12 +770,18 @@ int dediprog_init(void) { struct usb_device *dev; - char *voltage; - int millivolt = 3500; + char *voltage, *speed; + int khz = 0, millivolt = 3500; int ret;
msg_pspew("%s\n", __func__);
+ speed = extract_programmer_param("speed"); + if (speed) { + khz = strtol(speed, NULL, 0); + free(speed); + msg_pinfo("Setting speed to %i kHz\n", khz); + } voltage = extract_programmer_param("voltage"); if (voltage) { millivolt = parse_voltage(voltage); @@ -791,27 +843,25 @@
dediprog_set_leds(PASS_ON|BUSY_ON|ERROR_ON);
- /* URB 6. Command A. */ - if (dediprog_command_a()) { + /* Perform basic setup. */ + if (dediprog_setup()) { dediprog_set_leds(PASS_OFF|BUSY_OFF|ERROR_ON); return 1; } - /* URB 7. Command A. */ - if (dediprog_command_a()) { - dediprog_set_leds(PASS_OFF|BUSY_OFF|ERROR_ON); - return 1; + + /* + * Set speed if requested. Set voltage to zero beforehand and setup + * again afterwards. Maybe we can skip the first setup. + */ + if (khz) { + if (dediprog_set_spi_voltage(0) || + dediprog_set_spi_speed(khz) || + dediprog_setup()) { + dediprog_set_leds(PASS_OFF|BUSY_OFF|ERROR_ON); + return 1; + } } - /* URB 8. Command Prepare Receive Device String. */ - /* URB 9. Command Receive Device String. */ - if (dediprog_check_devicestring()) { - dediprog_set_leds(PASS_OFF|BUSY_OFF|ERROR_ON); - return 1; - } - /* URB 10. Command C. */ - if (dediprog_command_c()) { - dediprog_set_leds(PASS_OFF|BUSY_OFF|ERROR_ON); - return 1; - } + /* URB 11. Command Set SPI Voltage. */ if (dediprog_set_spi_voltage(millivolt)) { dediprog_set_leds(PASS_OFF|BUSY_OFF|ERROR_ON);