Rebased this one, following patches are based on it.
This adds a programmer parameter 'spispeed' to the dediprog driver to
control the transfer rate on the spi bus. The following rates are
available (in Hz):
375k, 750k, 1.5M, 2.18M, 3M, 8M, 12M and 24M
The original driver reinitializes the programmer after setting the
speed, so the initialization calls have moved into a new function
dediprog_setup() which is called twice.
Signed-off-by: Nico Huber <nico.huber(a)secunet.com>
diff --git a/dediprog.c b/dediprog.c
index a81cf83..60067a8 100644
--- a/dediprog.c
+++ b/dediprog.c
@@ -152,7 +152,23 @@ static int dediprog_set_spi_voltage(int millivolt)
return 0;
}
-#if 0
+struct dediprog_spispeeds {
+ const char *const name;
+ const int speed;
+};
+
+static const struct dediprog_spispeeds spispeeds[] = {
+ { "24M", 0x0 },
+ { "12M", 0x2 },
+ { "8M", 0x1 },
+ { "3M", 0x3 },
+ { "2.18M", 0x4 },
+ { "1.5M", 0x5 },
+ { "750k", 0x6 },
+ { "375k", 0x7 },
+ { NULL, 0x0 },
+};
+
/* 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.
@@ -160,56 +176,20 @@ static int dediprog_set_spi_voltage(int millivolt)
* 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 spispeed_idx)
{
int ret;
- unsigned int khz;
- /* 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;
- break;
- case 0x1:
- khz = 8000;
- break;
- case 0x2:
- khz = 12000;
- break;
- case 0x3:
- khz = 3000;
- break;
- case 0x4:
- khz = 2180;
- break;
- case 0x5:
- khz = 1500;
- break;
- case 0x6:
- khz = 750;
- break;
- case 0x7:
- khz = 375;
- break;
- default:
- msg_perr("Unknown frequency selector 0x%x! Aborting.\n", speed);
- return 1;
- }
- msg_pdbg("Setting SPI speed to %u kHz\n", khz);
+ msg_pdbg("SPI speed is %sHz\n", spispeeds[spispeed_idx].name);
- ret = usb_control_msg(dediprog_handle, 0x42, 0x61, speed, 0xff, NULL,
- 0x0, DEFAULT_TIMEOUT);
+ ret = usb_control_msg(dediprog_handle, 0x42, 0x61, spispeeds[spispeed_idx].speed, 0xff,
+ NULL, 0x0, DEFAULT_TIMEOUT);
if (ret != 0x0) {
- msg_perr("Command Set SPI Speed 0x%x failed!\n", speed);
+ msg_perr("Command Set SPI Speed 0x%x failed!\n", spispeeds[spispeed_idx].speed);
return 1;
}
return 0;
}
-#endif
/* Bulk read interface, will read multiple 512 byte chunks aligned to 512 bytes.
* @start start address
@@ -736,6 +716,28 @@ static int parse_voltage(char *voltage)
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,
@@ -777,12 +779,21 @@ static int dediprog_shutdown(void *data)
int dediprog_init(void)
{
struct usb_device *dev;
- char *voltage;
- int millivolt = 3500;
- int ret;
+ char *voltage, *spispeed;
+ int spispeed_idx = 2, millivolt = 3500;
+ int i, ret;
msg_pspew("%s\n", __func__);
+ spispeed = extract_programmer_param("spispeed");
+ if (spispeed) {
+ for (i = 0; spispeeds[i].name; ++i) {
+ if (!strcasecmp(spispeeds[i].name, spispeed)) {
+ spispeed_idx = i;
+ break;
+ }
+ }
+ }
voltage = extract_programmer_param("voltage");
if (voltage) {
millivolt = parse_voltage(voltage);
@@ -821,33 +832,26 @@ int dediprog_init(void)
return 1;
}
dediprog_endpoint = 2;
-
+
if (register_shutdown(dediprog_shutdown, NULL))
return 1;
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;
- }
- /* 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()) {
+
+ /* After setting voltage and speed, perform setup again. */
+ if (dediprog_set_spi_voltage(0) ||
+ dediprog_set_spi_speed(spispeed_idx) ||
+ dediprog_setup()) {
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);
diff --git a/flashrom.8 b/flashrom.8
index b054c28..99e064e 100644
--- a/flashrom.8
+++ b/flashrom.8
@@ -651,6 +651,18 @@ where
can be
.BR 0V ", " 1.8V ", " 2.5V ", " 3.5V
or the equivalent in mV.
+.sp
+An optional
+.B spispeed
+parameter specifies the frequency of the SPI bus. Syntax is
+.sp
+.B " flashrom \-p dediprog:spispeed=frequency"
+.sp
+where
+.B frequency
+can be
+.BR 375k ", " 750k ", " 1.5M ", " 2.18M ", " 3M ", " 8M ", " 12M " or " 24M
+(in Hz). The default is a frequency of 12 MHz.
.SS
.BR "rayer_spi " programmer
The default I/O base address used for the parallel port is 0x378 and you can use