[flashrom] [PATCH] Enable spi clock setting in dediprog driver

Nico Huber nico.huber at secunet.com
Wed Jun 13 11:01:57 CEST 2012


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 at 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);




More information about the flashrom mailing list