int wbsio_check_for_spi(void) { if (0 == (wbsio_spibase = wbsio_get_spibase(WBSIO_PORT1))) if (0 == (wbsio_spibase = wbsio_get_spibase(WBSIO_PORT2))) return 1; msg_pspew("\nwbsio_spibase = 0x%x\n", wbsio_spibase); msg_pdbg("%s: Winbond saved on 4 register bits so max chip size is " "1024 kB!\n", __func__); max_rom_decode.spi = 1024 * 1024; register_spi_master(&spi_master_wbsio); return 0; }
int jlink_spi_init(void) { char *arg; unsigned long speed = 0; register_shutdown(jlink_spi_shutdown, NULL); arg = extract_programmer_param("spispeed"); if (arg) { char *endptr; errno = 0; speed = strtoul(arg, &endptr, 10); if (*endptr != '\0' || errno != 0) { msg_perr("Invalid SPI speed specified: %s.\n", arg); free(arg); return 1; } if (speed < 1) { msg_perr("SPI speed must be at least 1 kHz.\n"); free(arg); return 1; } } free(arg); int ret; bool use_serial_number; uint32_t serial_number; arg = extract_programmer_param("serial"); if (arg) { if (!strlen(arg)) { msg_perr("Emptpy serial number specified.\n"); free(arg); return 1; } ret = jaylink_parse_serial_number(arg, &serial_number); if (ret == JAYLINK_ERR) { msg_perr("Invalid serial number specified: %s.\n", arg); free(arg); return 1; } if (ret != JAYLINK_OK) { msg_perr("jaylink_parse_serial_number() failed: %s.\n", jaylink_strerror(ret)); free(arg); return 1; } use_serial_number = true; } else { use_serial_number = false; } free(arg); reset_cs = true; arg = extract_programmer_param("cs"); if (arg) { if (!strcasecmp(arg, "reset")) { reset_cs = true; } else if (!strcasecmp(arg, "trst")) { reset_cs = false; } else { msg_perr("Invalid chip select pin specified: '%s'.\n", arg); free(arg); return 1; } } free(arg); if (reset_cs) msg_pdbg("Using RESET as chip select signal.\n"); else msg_pdbg("Using TRST as chip select signal.\n"); ret = jaylink_init(&jaylink_ctx); if (ret != JAYLINK_OK) { msg_perr("jaylink_init() failed: %s.\n", jaylink_strerror(ret)); return 1; } ret = jaylink_discovery_scan(jaylink_ctx, 0); if (ret != JAYLINK_OK) { msg_perr("jaylink_discover_scan() failed: %s.\n", jaylink_strerror(ret)); return 1; } struct jaylink_device **devs; ret = jaylink_get_devices(jaylink_ctx, &devs, NULL); if (ret != JAYLINK_OK) { msg_perr("jaylink_get_devices() failed: %s.\n", jaylink_strerror(ret)); return 1; } if (!use_serial_number) msg_pdbg("No device selected, using first device.\n"); size_t i; struct jaylink_device *dev; bool device_found = false; for (i = 0; devs[i]; i++) { if (use_serial_number) { uint32_t tmp; ret = jaylink_device_get_serial_number(devs[i], &tmp); if (ret == JAYLINK_ERR_NOT_AVAILABLE) { continue; } else if (ret != JAYLINK_OK) { msg_pwarn("jaylink_device_get_serial_number() failed: %s.\n", jaylink_strerror(ret)); continue; } if (serial_number != tmp) continue; } ret = jaylink_open(devs[i], &jaylink_devh); if (ret == JAYLINK_OK) { dev = devs[i]; device_found = true; break; } jaylink_devh = NULL; } jaylink_free_devices(devs, true); if (!device_found) { msg_perr("No J-Link device found.\n"); return 1; } size_t length; char *firmware_version; ret = jaylink_get_firmware_version(jaylink_devh, &firmware_version, &length); if (ret != JAYLINK_OK) { msg_perr("jaylink_get_firmware_version() failed: %s.\n", jaylink_strerror(ret)); return 1; } else if (length > 0) { msg_pdbg("Firmware: %s\n", firmware_version); free(firmware_version); } ret = jaylink_device_get_serial_number(dev, &serial_number); if (ret == JAYLINK_OK) { msg_pdbg("S/N: %" PRIu32 "\n", serial_number); } else if (ret == JAYLINK_ERR_NOT_AVAILABLE) { msg_pdbg("S/N: N/A\n"); } else { msg_perr("jaylink_device_get_serial_number() failed: %s.\n", jaylink_strerror(ret)); return 1; } uint8_t caps[JAYLINK_DEV_EXT_CAPS_SIZE]; memset(caps, 0, sizeof(caps)); ret = jaylink_get_caps(jaylink_devh, caps); if (ret != JAYLINK_OK) { msg_perr("jaylink_get_caps() failed: %s.\n", jaylink_strerror(ret)); return 1; } if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_EXT_CAPS)) { ret = jaylink_get_extended_caps(jaylink_devh, caps); if (ret != JAYLINK_OK) { msg_perr("jaylink_get_available_interfaces() failed: %s.\n", jaylink_strerror(ret)); return 1; } } uint32_t ifaces; ret = jaylink_get_available_interfaces(jaylink_devh, &ifaces); if (ret != JAYLINK_OK) { msg_perr("jaylink_get_available_interfaces() failed: %s.\n", jaylink_strerror(ret)); return 1; } if (!(ifaces & (1 << JAYLINK_TIF_JTAG))) { msg_perr("Device does not support JTAG interface.\n"); return 1; } ret = jaylink_select_interface(jaylink_devh, JAYLINK_TIF_JTAG, NULL); if (ret != JAYLINK_OK) { msg_perr("jaylink_select_interface() failed: %s.\n", jaylink_strerror(ret)); return 1; } struct jaylink_hardware_status hwstat; ret = jaylink_get_hardware_status(jaylink_devh, &hwstat); if (ret != JAYLINK_OK) { msg_perr("jaylink_get_hardware_status() failed: %s.\n", jaylink_strerror(ret)); return 1; } msg_pdbg("VTarget: %u.%03u V\n", hwstat.target_voltage / 1000, hwstat.target_voltage % 1000); if (hwstat.target_voltage < MIN_TARGET_VOLTAGE) { msg_perr("Target voltage is below %u.%03u V. You need to attach VTref to the I/O voltage of " "the chip.\n", MIN_TARGET_VOLTAGE / 1000, MIN_TARGET_VOLTAGE % 1000); return 1; } struct jaylink_speed device_speeds; device_speeds.freq = DEFAULT_FREQ; device_speeds.div = DEFAULT_FREQ_DIV; if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_SPEEDS)) { ret = jaylink_get_speeds(jaylink_devh, &device_speeds); if (ret != JAYLINK_OK) { msg_perr("jaylink_get_speeds() failed: %s.\n", jaylink_strerror(ret)); return 1; } } device_speeds.freq /= 1000; msg_pdbg("Maximum SPI speed: %" PRIu32 " kHz\n", device_speeds.freq / device_speeds.div); if (!speed) { speed = device_speeds.freq / device_speeds.div; msg_pdbg("SPI speed not specified, using %lu kHz.\n", speed); } if (speed > (device_speeds.freq / device_speeds.div)) { msg_perr("Specified SPI speed of %lu kHz is too high. Maximum is %" PRIu32 " kHz.\n", speed, device_speeds.freq / device_speeds.div); return 1; } ret = jaylink_set_speed(jaylink_devh, speed); if (ret != JAYLINK_OK) { msg_perr("jaylink_set_speed() failed: %s.\n", jaylink_strerror(ret)); return 1; } msg_pdbg("SPI speed: %lu kHz\n", speed); /* Ensure that the CS signal is not active initially. */ if (!deassert_cs()) return 1; register_spi_master(&spi_master_jlink_spi); return 0; }
int pickit2_spi_init(void) { unsigned int usedevice = 0; // FIXME: allow to select one of multiple devices uint8_t buf[CMD_LENGTH] = { CMD_EXEC_SCRIPT, 10, /* Script length */ SCR_SET_PINS, 2, /* Bit-0=0(PDC Out), Bit-1=1(PGD In), Bit-2=0(PDC LL), Bit-3=0(PGD LL) */ SCR_SET_AUX, 0, /* Bit-0=0(Aux Out), Bit-1=0(Aux LL) */ SCR_VDD_ON, SCR_MCLR_GND_OFF, /* Let CS# float */ SCR_VPP_PWM_ON, SCR_VPP_ON, /* Pull CS# high */ SCR_BUSY_LED_ON, CMD_CLR_DLOAD_BUFF, CMD_CLR_ULOAD_BUFF, CMD_END_OF_BUFFER }; int spispeed_idx = 0; char *spispeed = extract_programmer_param("spispeed"); if (spispeed != NULL) { int i = 0; for (; spispeeds[i].name; i++) { if (strcasecmp(spispeeds[i].name, spispeed) == 0) { spispeed_idx = i; break; } } if (spispeeds[i].name == NULL) { msg_perr("Error: Invalid 'spispeed' value.\n"); free(spispeed); return 1; } free(spispeed); } int millivolt = 3500; char *voltage = extract_programmer_param("voltage"); if (voltage != NULL) { millivolt = parse_voltage(voltage); free(voltage); if (millivolt < 0) return 1; } /* Here comes the USB stuff */ usb_init(); (void)usb_find_busses(); (void)usb_find_devices(); struct usb_device *dev = get_device_by_vid_pid(PICKIT2_VID, PICKIT2_PID, usedevice); if (dev == NULL) { msg_perr("Could not find a PICkit2 on USB!\n"); return 1; } msg_pdbg("Found USB device (%04x:%04x).\n", dev->descriptor.idVendor, dev->descriptor.idProduct); pickit2_handle = usb_open(dev); int ret = usb_set_configuration(pickit2_handle, 1); if (ret != 0) { msg_perr("Could not set USB device configuration: %i %s\n", ret, usb_strerror()); if (usb_close(pickit2_handle) != 0) msg_perr("Could not close USB device!\n"); return 1; } ret = usb_claim_interface(pickit2_handle, 0); if (ret != 0) { msg_perr("Could not claim USB device interface %i: %i %s\n", 0, ret, usb_strerror()); if (usb_close(pickit2_handle) != 0) msg_perr("Could not close USB device!\n"); return 1; } if (register_shutdown(pickit2_shutdown, NULL) != 0) { return 1; } if (pickit2_get_firmware_version()) { return 1; } /* Command Set SPI Speed */ if (pickit2_set_spi_speed(spispeed_idx)) { return 1; } /* Command Set SPI Voltage */ msg_pdbg("Setting voltage to %i mV.\n", millivolt); if (pickit2_set_spi_voltage(millivolt) != 0) { return 1; } /* Perform basic setup. * Configure pin directions and logic levels, turn Vdd on, turn busy LED on and clear buffers. */ ret = usb_interrupt_write(pickit2_handle, ENDPOINT_OUT, (char *)buf, CMD_LENGTH, DFLT_TIMEOUT); if (ret != CMD_LENGTH) { msg_perr("Command Setup failed (%s)!\n", usb_strerror()); return 1; } register_spi_master(&spi_master_pickit2); return 0; }
/* Returns 0 upon success, a negative number upon errors. */ int mstarddc_spi_init(void) { int ret = 0; // Get device, address from command-line char *i2c_device = extract_programmer_param("dev"); if (i2c_device != NULL && strlen(i2c_device) > 0) { char *i2c_address = strchr(i2c_device, ':'); if (i2c_address != NULL) { *i2c_address = '\0'; i2c_address++; } if (i2c_address == NULL || strlen(i2c_address) == 0) { msg_perr("Error: no address specified.\n" "Use flashrom -p mstarddc_spi:dev=/dev/device:address.\n"); ret = -1; goto out; } mstarddc_addr = strtol(i2c_address, NULL, 16); // FIXME: error handling } else { msg_perr("Error: no device specified.\n" "Use flashrom -p mstarddc_spi:dev=/dev/device:address.\n"); ret = -1; goto out; } msg_pinfo("Info: Will try to use device %s and address 0x%02x.\n", i2c_device, mstarddc_addr); // Get noreset=1 option from command-line char *noreset = extract_programmer_param("noreset"); if (noreset != NULL && noreset[0] == '1') mstarddc_doreset = 0; free(noreset); msg_pinfo("Info: Will %sreset the device at the end.\n", mstarddc_doreset ? "" : "NOT "); // Open device if ((mstarddc_fd = open(i2c_device, O_RDWR)) < 0) { switch (errno) { case EACCES: msg_perr("Error opening %s: Permission denied.\n" "Please use sudo or run as root.\n", i2c_device); break; case ENOENT: msg_perr("Error opening %s: No such file.\n" "Please check you specified the correct device.\n", i2c_device); break; default: msg_perr("Error opening %s: %s.\n", i2c_device, strerror(errno)); } ret = -1; goto out; } // Set slave address if (ioctl(mstarddc_fd, I2C_SLAVE, mstarddc_addr) < 0) { msg_perr("Error setting slave address 0x%02x: errno %d.\n", mstarddc_addr, errno); ret = -1; goto out; } // Enable ISP mode uint8_t cmd[5] = { 'M', 'S', 'T', 'A', 'R' }; if (write(mstarddc_fd, cmd, 5) < 0) { int enable_err = errno; uint8_t end_cmd = MSTARDDC_SPI_END; // Assume device is already in ISP mode, try to send END command if (write(mstarddc_fd, &end_cmd, 1) < 0) { msg_perr("Error enabling ISP mode: errno %d & %d.\n" "Please check that device (%s) and address (0x%02x) are correct.\n", enable_err, errno, i2c_device, mstarddc_addr); ret = -1; goto out; } } // Register shutdown function register_shutdown(mstarddc_spi_shutdown, NULL); // Register programmer register_spi_master(&spi_master_mstarddc); out: free(i2c_device); return ret; }