OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [soc/] [sw/] [adv_jtag_bridge/] [cable_xpc_dlc9.c] - Rev 21

Compare with Previous | Blame | View Log

/* cable_xpc_dlc9.c - Xilinx Platform Cable (DLC9) driver for the Advanced JTAG Bridge
   Copyright (C) 2008 - 2010 Nathan Yawn, nathan.yawn@opencores.org
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>  // for usleep()
#include <stdlib.h>  // for sleep()
 
 
#include "usb.h"  // libusb header
#include "cable_common.h"
#include "errcodes.h"
 
#define USB_TIMEOUT 500
 
// Note that this is based on the UrJTAG driver for the XPC-USB,
// which was 'experimental' at the time.
// It only supports bit-bang mode, and therefore will not be fast.
 
// USB constants for the DLC9
#define XPCUSB_VID  0x3fd
#define XPCUSB_PID  0x08
 
// Bit meanings in the command byte sent to the DLC9
// DLC9 has no TRST bit
#define XPCUSB_CMD_TDI 0x01
#define XPCUSB_CMD_TDO 0x01
#define XPCUSB_CMD_TMS 0x02
#define XPCUSB_CMD_TCK 0x04
#define XPCUSB_CMD_PROG 0x08
 
 
static struct usb_device *device;
 
 
///////////////////////////////////////////////////////////////////////////////
/*----- Functions for the Xilinx Platform Cable USB (Model DLC9)            */
/////////////////////////////////////////////////////////////////////////////
 
 
static int xpcu_request_28(struct usb_dev_handle *xpcu, int value)
{
  // Maybe clock speed setting?
  if(usb_control_msg(xpcu, 0x40, 0xB0, 0x0028, value, NULL, 0, USB_TIMEOUT)<0)
    {
      fprintf(stderr, "Error sending usb_control_msg(0x28.x)\n");
      return APP_ERR_USB;
    }
 
  return APP_ERR_NONE;
}
 
 
static int xpcu_raise_ioa5(struct usb_dev_handle *xpcu)
{
  if(usb_control_msg(xpcu, 0x40, 0xB0, 0x0018, 0x0000, NULL, 0, USB_TIMEOUT)<0)
    {
      fprintf(stderr, "Error sending usb_control_msg(0x18.0x00) (raise IOA.5{\n");
      return APP_ERR_USB;
    }
 
  return APP_ERR_NONE;
}
 
static int xpcu_select_gpio(struct usb_dev_handle *xpcu, int chain)
{
  if(usb_control_msg(xpcu, 0x40, 0xB0, 0x0052, chain, NULL, 0, USB_TIMEOUT)<0)
    {
      fprintf(stderr, "Error sending usb_control_msg(0x52.x) (select gpio)\n");
      return APP_ERR_USB;
    }
 
  return APP_ERR_NONE;
}
 
static int xpcu_read_firmware_version(struct usb_dev_handle *xpcu, uint16_t *buf)
{
  if(usb_control_msg(xpcu, 0xC0, 0xB0, 0x0050, 0x0000, (char*)buf, 2, USB_TIMEOUT)<0)
    {
      fprintf(stderr,"Error sending usb_control_msg(0x50.0) (read_firmware_version)\n");
      return APP_ERR_USB;
    }
  return APP_ERR_NONE;
}
 
static int xpcu_read_cpld_version(struct usb_dev_handle *xpcu, uint16_t *buf)
{
  if(usb_control_msg(xpcu, 0xC0, 0xB0, 0x0050, 0x0001, (char*)buf, 2, USB_TIMEOUT)<0)
    {
      fprintf(stderr, "Error sending usb_control_msg(0x50.1) (read_cpld_version)\n");
      return APP_ERR_USB;
    }
  return APP_ERR_NONE;
}
 
 
static int xpcusb_enumerate_bus(void)
{
  int             flag;  // for USB bus scanning stop condition
  struct usb_bus *bus;   // pointer on the USB bus
 
  // board detection
  usb_init();
  usb_find_busses();
  usb_find_devices();
 
  flag = 0;
 
  for (bus = usb_get_busses(); bus; bus = bus->next)
  {
    for (device = bus->devices; device; device = device->next)
    {	
      if (device->descriptor.idVendor  == XPCUSB_VID &&
          device->descriptor.idProduct == XPCUSB_PID) 
      {
	      flag = 1;
	      fprintf(stderr, "Found Xilinx Platform Cable USB (DLC9)\n");
	      return APP_ERR_NONE;
      }
    }
    if (flag)
      break;
  }
 
  fprintf(stderr, "Failed to find Xilinx Platform Cable USB\n");
  return APP_ERR_CABLENOTFOUND;
}
 
 
int cable_xpcusb_init()
{
  int err = APP_ERR_NONE;
 
  // Process to reset the XPC USB (DLC9)
  if(err |= xpcusb_enumerate_bus()) {
    return err;
  }
 
  usb_dev_handle *h_device = usb_open(device);
 
  if(h_device == NULL)
    {
      fprintf(stderr, "Init failed to open USB device for reset\n");
      return APP_ERR_USB;
    }
 
  if(usb_reset(h_device) != APP_ERR_NONE)
    fprintf(stderr, "Failed to reset XPC-USB\n");
 
  usb_close(h_device);
 
  // Wait for reset!!!
  sleep(1);
 
  // Do device initialization
  if(err |= xpcusb_enumerate_bus())
    return err;
 
  h_device = usb_open(device);
  if(h_device == NULL)
    {
      fprintf(stderr, "Init failed to open USB device for initialization\n");
      return APP_ERR_USB;
    }
 
  // set the configuration
  if (usb_set_configuration(h_device, device->config->bConfigurationValue))
    {
      usb_close(h_device);
      fprintf(stderr, "USB-reset failed to set configuration\n");
      return APP_ERR_USB;
    }
 
  while (usb_claim_interface(h_device, device->config->interface->altsetting->bInterfaceNumber));
 
  // DO DEVICE-SPECIFIC INIT HERE
  // Don't mess with the order here, it's easy to break.
 
  // Maybe set the clock speed?
  if(xpcu_request_28(h_device, 0x11) != APP_ERR_NONE)	{
    fprintf(stderr, "Request 28 (set clock speed?) failed.\n");
  }
 
  // Set internal TCK,TMS,TDO to 0
  if(usb_control_msg(h_device, 0x40, 0xB0, 0x0030, 0x08, NULL, 0, USB_TIMEOUT)!= APP_ERR_NONE) {
    fprintf(stderr, "usb_control_msg(0x30.0x00) (write port E) failed\n");
  }
 
  // Read firmware version (constant embedded in firmware)
  uint16_t buf;
 
  if(xpcu_read_firmware_version(h_device, &buf) != APP_ERR_NONE)	{
    fprintf(stderr, "Failed to read firmware version.\n");
  }
  else 	{
    printf("firmware version = 0x%04X (%u)\n", buf, buf);
  }
 
  // Read CPLD version (uses the internal GPIF interface)
  if(xpcu_read_cpld_version(h_device, &buf) != APP_ERR_NONE) {
    fprintf(stderr, "Failed to read CPLD version.\n");
  }
  else
    {
      printf("cable CPLD version = 0x%04X (%u)\n", buf, buf);
      if(buf == 0) 		{
	printf("Warning: version '0' can't be correct. Please try resetting the cable\n");
      }
    }
 
  // Set IOA bit 5, which enables output buffers
  if(xpcu_raise_ioa5(h_device) != APP_ERR_NONE) {
    fprintf(stderr, "Failed to enable XPC output buffers\n");
  }
 
  // access external chain for normal operation
  if(xpcu_select_gpio(h_device, 0) != APP_ERR_NONE) {
    fprintf(stderr, "Failed to select external JTAG chain\n");
  }
 
  // Init all done, release cable
  if (usb_release_interface(h_device, device->config->interface->altsetting->bInterfaceNumber)){
    usb_close(h_device);
    fprintf(stderr, "USB-out failed to release interface\n");
    return APP_ERR_USB;
  }
 
  usb_close(h_device);
 
  return APP_ERR_NONE;
}
 
 
int cable_xpcusb_out(uint8_t value)
{
  int             rv;                  // to catch return values of functions
  usb_dev_handle *h_device;            // handle on the ubs device
  uint8_t out;
 
  // open the device
  h_device = usb_open(device);
  if (h_device == NULL){
    usb_close(h_device);
    fprintf(stderr, "USB-out failed to open device\n");
    return APP_ERR_USB;
  }
 
  // set the configuration
  if (usb_set_configuration(h_device, device->config->bConfigurationValue))
    {
      usb_close(h_device);
      fprintf(stderr, "USB-out failed to set configuration\n");
      return APP_ERR_USB;
    }
 
  // wait until device is ready
  while (usb_claim_interface(h_device, device->config->interface->altsetting->bInterfaceNumber));
 
  // send the buffer
  // Translate to USB blaster protocol
  out = 0;
  if(value & TCLK_BIT)
    out |= XPCUSB_CMD_TCK;
  if(value & TDI_BIT)
    out |= XPCUSB_CMD_TDI;
  if(value & TMS_BIT)
    out |= XPCUSB_CMD_TMS;
 
  out |= XPCUSB_CMD_PROG;  // Set output PROG (always necessary)
 
  /* debug
  if(value & TDI_BIT)
    printf("Write 1\n");
  else
    printf("Write 0\n");
  */
 
  rv = usb_control_msg(h_device, 0x40, 0xB0, 0x0030, out, NULL, 0, USB_TIMEOUT);
  if (rv < 0){
    fprintf(stderr, "\nFailed to send a write control message (rv = %d):\n%s\n", rv, usb_strerror());
  }
 
  // release the interface cleanly
  if (usb_release_interface(h_device, device->config->interface->altsetting->bInterfaceNumber)){
    fprintf(stderr, "Warning: failed to release usb interface after write\n");
  }
 
  // close the device
  usb_close(h_device);
  return APP_ERR_NONE;
}
 
 
int cable_xpcusb_inout(uint8_t value, uint8_t *inval)
{
  int rv;                  // to catch return values of functions
  usb_dev_handle *h_device;            // handle on the usb device
  char ret = 0;
  uint8_t out;
 
  // Translate to USB blaster protocol
  out = 0;
  if(value & TCLK_BIT)
    out |= XPCUSB_CMD_TCK;
  if(value & TDI_BIT)
    out |= XPCUSB_CMD_TDI;
  if(value & TMS_BIT)
    out |= XPCUSB_CMD_TMS;
 
  out |= XPCUSB_CMD_PROG;  // Set output PROG (always necessary)
 
  // open the device
  h_device = usb_open(device);
  if (h_device == NULL){
    usb_close(h_device);
    return APP_ERR_USB;
  }
 
  // set the configuration
  if (usb_set_configuration(h_device, device->config->bConfigurationValue)){
    usb_close(h_device);
    return APP_ERR_USB;
  }
 
  // wait until device is ready
  while (usb_claim_interface(h_device, device->config->interface->altsetting->bInterfaceNumber));
 
  // Send the output
  rv = usb_control_msg(h_device, 0x40, 0xB0, 0x0030, out, NULL, 0, USB_TIMEOUT);
  if (rv < 0){
    fprintf(stderr, "\nFailed to send a write control message (rv = %x):\n%s\n", rv, usb_strerror());
    goto usbblaster_in_fail;
  }
 
 
  // receive the response
  rv = usb_control_msg(h_device, 0xC0, 0xB0, 0x0038, 0, (char*)&ret, 1, USB_TIMEOUT);
  if (rv < 0){
    fprintf(stderr, "\nFailed to execute a read control message:\n%s\n", usb_strerror());
    goto usbblaster_in_fail;
  }
 
 
  // release the interface cleanly
  if (usb_release_interface(h_device, device->config->interface->altsetting->bInterfaceNumber)){
    fprintf(stderr, "Warning: failed to release USB interface after read\n");
    usb_close(h_device);
    return APP_ERR_USB;
  }
 
  // close the device
  usb_close(h_device);
 
  /* debug
  if(value & TDI_BIT)
    printf("Write 1, ");
  else
    printf("Write 0, ");
  */
 
  if(ret & XPCUSB_CMD_TDO)
    *inval = 1;
  else
    *inval = 0;
 
  //printf("Read 0\n");
  return APP_ERR_NONE;
 
usbblaster_in_fail:
  usb_release_interface(h_device, device->config->interface->altsetting->bInterfaceNumber);
  usb_close(h_device);
  return APP_ERR_USB;
}
 
 
// Xilinx couldn't be like everyone else.  Oh, no.
// For some reason, "set data/drop TCK" then "read data/raise TCK" won't work.
// So we have our very own bit read/write function.  @whee.
int cable_xpcusb_read_write_bit(uint8_t packet_out, uint8_t *bit_in) {
  uint8_t data = TRST_BIT;  //  TRST is active low, don't clear unless /set/ in 'packet'
  int err = APP_ERR_NONE;
 
  /* Write data, drop clock */
  if(packet_out & TDO) data |= TDI_BIT;
  if(packet_out & TMS) data |= TMS_BIT;
  if(packet_out & TRST) data &= ~TRST_BIT;
 
  err |= cable_xpcusb_inout(data, bit_in);  // read in bit, set data, drop clock
  err |= cable_xpcusb_out(data|TCLK_BIT);  // clk hi
 
  return err;
}
 
 
int cable_xpcusb_opt(int c, char *str)
{
    fprintf(stderr, "Unknown parameter '%c'\n", c);
    return APP_ERR_BAD_PARAM;
}
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.