diff options
| author | Wolfgang Denk <wd@denx.de> | 2010-10-17 19:57:38 +0200 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2010-10-17 19:57:38 +0200 | 
| commit | 6ca803750e1e08fce26e508f1c35170bf9259bb4 (patch) | |
| tree | 06a94458bc79e19dd3f8e187de5ce6ce6725a905 | |
| parent | d470a6f60ad0d627c21a2769513d2017f9a0da76 (diff) | |
| parent | edad84c299628154ad14ad3726fc22ff45800830 (diff) | |
| download | olio-uboot-2014.01-6ca803750e1e08fce26e508f1c35170bf9259bb4.tar.xz olio-uboot-2014.01-6ca803750e1e08fce26e508f1c35170bf9259bb4.zip | |
Merge branch 'master' of git://git.denx.de/u-boot-imx
| -rw-r--r-- | arch/arm/cpu/arm1136/mx31/generic.c | 17 | ||||
| -rw-r--r-- | arch/arm/include/asm/arch-mx31/mx31-regs.h | 411 | ||||
| -rw-r--r-- | board/davedenx/qong/Makefile | 2 | ||||
| -rw-r--r-- | board/davedenx/qong/fpga.c | 95 | ||||
| -rw-r--r-- | board/davedenx/qong/qong.c | 44 | ||||
| -rw-r--r-- | board/davedenx/qong/qong_fpga.h | 3 | ||||
| -rw-r--r-- | board/freescale/mx51evk/config.mk | 1 | ||||
| -rw-r--r-- | drivers/fpga/Makefile | 1 | ||||
| -rw-r--r-- | drivers/fpga/fpga.c | 11 | ||||
| -rwxr-xr-x | drivers/fpga/ivm_core.c | 3167 | ||||
| -rw-r--r-- | drivers/fpga/lattice.c | 399 | ||||
| -rw-r--r-- | drivers/usb/host/Makefile | 1 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-mxc.c | 130 | ||||
| -rw-r--r-- | drivers/video/mx3fb.c | 31 | ||||
| -rw-r--r-- | include/configs/qong.h | 21 | ||||
| -rw-r--r-- | include/fpga.h | 1 | ||||
| -rwxr-xr-x | include/lattice.h | 319 | 
17 files changed, 4619 insertions, 35 deletions
| diff --git a/arch/arm/cpu/arm1136/mx31/generic.c b/arch/arm/cpu/arm1136/mx31/generic.c index 1415d6c2a..cbe8243ab 100644 --- a/arch/arm/cpu/arm1136/mx31/generic.c +++ b/arch/arm/cpu/arm1136/mx31/generic.c @@ -23,6 +23,7 @@  #include <common.h>  #include <asm/arch/mx31-regs.h> +#include <asm/io.h>  static u32 mx31_decode_pll(u32 reg, u32 infreq)  { @@ -90,6 +91,22 @@ void mx31_gpio_mux(unsigned long mode)  	__REG(reg) = tmp;  } +void mx31_set_pad(enum iomux_pins pin, u32 config) +{ +	u32 field, l; +	void *reg; + +	pin &= IOMUX_PADNUM_MASK; +	reg = (IOMUXC_BASE + 0x154) + (pin + 2) / 3 * 4; +	field = (pin + 2) % 3; + +	l = __raw_readl(reg); +	l &= ~(0x1ff << (field * 10)); +	l |= config << (field * 10); +	__raw_writel(l, reg); + +} +  #if defined(CONFIG_DISPLAY_CPUINFO)  int print_cpuinfo (void)  { diff --git a/arch/arm/include/asm/arch-mx31/mx31-regs.h b/arch/arm/include/asm/arch-mx31/mx31-regs.h index f05e743d7..46ed47cc7 100644 --- a/arch/arm/include/asm/arch-mx31/mx31-regs.h +++ b/arch/arm/include/asm/arch-mx31/mx31-regs.h @@ -64,6 +64,370 @@ struct gpio_regs {  	u32	gpio_psr;  }; +#define IOMUX_PADNUM_MASK	0x1ff +#define IOMUX_PIN(gpionum, padnum) ((padnum) & IOMUX_PADNUM_MASK) + +/* + * various IOMUX pad functions + */ +enum iomux_pad_config { +	PAD_CTL_NOLOOPBACK	= 0x0 << 9, +	PAD_CTL_LOOPBACK	= 0x1 << 9, +	PAD_CTL_PKE_NONE	= 0x0 << 8, +	PAD_CTL_PKE_ENABLE	= 0x1 << 8, +	PAD_CTL_PUE_KEEPER	= 0x0 << 7, +	PAD_CTL_PUE_PUD		= 0x1 << 7, +	PAD_CTL_100K_PD		= 0x0 << 5, +	PAD_CTL_100K_PU		= 0x1 << 5, +	PAD_CTL_47K_PU		= 0x2 << 5, +	PAD_CTL_22K_PU		= 0x3 << 5, +	PAD_CTL_HYS_CMOS	= 0x0 << 4, +	PAD_CTL_HYS_SCHMITZ	= 0x1 << 4, +	PAD_CTL_ODE_CMOS	= 0x0 << 3, +	PAD_CTL_ODE_OpenDrain	= 0x1 << 3, +	PAD_CTL_DRV_NORMAL	= 0x0 << 1, +	PAD_CTL_DRV_HIGH	= 0x1 << 1, +	PAD_CTL_DRV_MAX		= 0x2 << 1, +	PAD_CTL_SRE_SLOW	= 0x0 << 0, +	PAD_CTL_SRE_FAST	= 0x1 << 0 +}; + +/* + * This enumeration is constructed based on the Section + * "sw_pad_ctl & sw_mux_ctl details" of the MX31 IC Spec. Each enumerated + * value is constructed based on the rules described above. + */ + +enum iomux_pins { +	MX31_PIN_TTM_PAD	= IOMUX_PIN(0xff,   0), +	MX31_PIN_CSPI3_SPI_RDY	= IOMUX_PIN(0xff,   1), +	MX31_PIN_CSPI3_SCLK	= IOMUX_PIN(0xff,   2), +	MX31_PIN_CSPI3_MISO	= IOMUX_PIN(0xff,   3), +	MX31_PIN_CSPI3_MOSI	= IOMUX_PIN(0xff,   4), +	MX31_PIN_CLKSS		= IOMUX_PIN(0xff,   5), +	MX31_PIN_CE_CONTROL	= IOMUX_PIN(0xff,   6), +	MX31_PIN_ATA_RESET_B	= IOMUX_PIN(95,     7), +	MX31_PIN_ATA_DMACK	= IOMUX_PIN(94,     8), +	MX31_PIN_ATA_DIOW	= IOMUX_PIN(93,     9), +	MX31_PIN_ATA_DIOR	= IOMUX_PIN(92,    10), +	MX31_PIN_ATA_CS1	= IOMUX_PIN(91,    11), +	MX31_PIN_ATA_CS0	= IOMUX_PIN(90,    12), +	MX31_PIN_SD1_DATA3	= IOMUX_PIN(63,    13), +	MX31_PIN_SD1_DATA2	= IOMUX_PIN(62,    14), +	MX31_PIN_SD1_DATA1	= IOMUX_PIN(61,    15), +	MX31_PIN_SD1_DATA0	= IOMUX_PIN(60,    16), +	MX31_PIN_SD1_CLK	= IOMUX_PIN(59,    17), +	MX31_PIN_SD1_CMD	= IOMUX_PIN(58,    18), +	MX31_PIN_D3_SPL		= IOMUX_PIN(0xff,  19), +	MX31_PIN_D3_CLS		= IOMUX_PIN(0xff,  20), +	MX31_PIN_D3_REV		= IOMUX_PIN(0xff,  21), +	MX31_PIN_CONTRAST	= IOMUX_PIN(0xff,  22), +	MX31_PIN_VSYNC3		= IOMUX_PIN(0xff,  23), +	MX31_PIN_READ		= IOMUX_PIN(0xff,  24), +	MX31_PIN_WRITE		= IOMUX_PIN(0xff,  25), +	MX31_PIN_PAR_RS		= IOMUX_PIN(0xff,  26), +	MX31_PIN_SER_RS		= IOMUX_PIN(89,    27), +	MX31_PIN_LCS1		= IOMUX_PIN(88,    28), +	MX31_PIN_LCS0		= IOMUX_PIN(87,    29), +	MX31_PIN_SD_D_CLK	= IOMUX_PIN(86,    30), +	MX31_PIN_SD_D_IO	= IOMUX_PIN(85,    31), +	MX31_PIN_SD_D_I		= IOMUX_PIN(84,    32), +	MX31_PIN_DRDY0		= IOMUX_PIN(0xff,  33), +	MX31_PIN_FPSHIFT	= IOMUX_PIN(0xff,  34), +	MX31_PIN_HSYNC		= IOMUX_PIN(0xff,  35), +	MX31_PIN_VSYNC0		= IOMUX_PIN(0xff,  36), +	MX31_PIN_LD17		= IOMUX_PIN(0xff,  37), +	MX31_PIN_LD16		= IOMUX_PIN(0xff,  38), +	MX31_PIN_LD15		= IOMUX_PIN(0xff,  39), +	MX31_PIN_LD14		= IOMUX_PIN(0xff,  40), +	MX31_PIN_LD13		= IOMUX_PIN(0xff,  41), +	MX31_PIN_LD12		= IOMUX_PIN(0xff,  42), +	MX31_PIN_LD11		= IOMUX_PIN(0xff,  43), +	MX31_PIN_LD10		= IOMUX_PIN(0xff,  44), +	MX31_PIN_LD9		= IOMUX_PIN(0xff,  45), +	MX31_PIN_LD8		= IOMUX_PIN(0xff,  46), +	MX31_PIN_LD7		= IOMUX_PIN(0xff,  47), +	MX31_PIN_LD6		= IOMUX_PIN(0xff,  48), +	MX31_PIN_LD5		= IOMUX_PIN(0xff,  49), +	MX31_PIN_LD4		= IOMUX_PIN(0xff,  50), +	MX31_PIN_LD3		= IOMUX_PIN(0xff,  51), +	MX31_PIN_LD2		= IOMUX_PIN(0xff,  52), +	MX31_PIN_LD1		= IOMUX_PIN(0xff,  53), +	MX31_PIN_LD0		= IOMUX_PIN(0xff,  54), +	MX31_PIN_USBH2_DATA1	= IOMUX_PIN(0xff,  55), +	MX31_PIN_USBH2_DATA0	= IOMUX_PIN(0xff,  56), +	MX31_PIN_USBH2_NXT	= IOMUX_PIN(0xff,  57), +	MX31_PIN_USBH2_STP	= IOMUX_PIN(0xff,  58), +	MX31_PIN_USBH2_DIR	= IOMUX_PIN(0xff,  59), +	MX31_PIN_USBH2_CLK	= IOMUX_PIN(0xff,  60), +	MX31_PIN_USBOTG_DATA7	= IOMUX_PIN(0xff,  61), +	MX31_PIN_USBOTG_DATA6	= IOMUX_PIN(0xff,  62), +	MX31_PIN_USBOTG_DATA5	= IOMUX_PIN(0xff,  63), +	MX31_PIN_USBOTG_DATA4	= IOMUX_PIN(0xff,  64), +	MX31_PIN_USBOTG_DATA3	= IOMUX_PIN(0xff,  65), +	MX31_PIN_USBOTG_DATA2	= IOMUX_PIN(0xff,  66), +	MX31_PIN_USBOTG_DATA1	= IOMUX_PIN(0xff,  67), +	MX31_PIN_USBOTG_DATA0	= IOMUX_PIN(0xff,  68), +	MX31_PIN_USBOTG_NXT	= IOMUX_PIN(0xff,  69), +	MX31_PIN_USBOTG_STP	= IOMUX_PIN(0xff,  70), +	MX31_PIN_USBOTG_DIR	= IOMUX_PIN(0xff,  71), +	MX31_PIN_USBOTG_CLK	= IOMUX_PIN(0xff,  72), +	MX31_PIN_USB_BYP	= IOMUX_PIN(31,    73), +	MX31_PIN_USB_OC		= IOMUX_PIN(30,    74), +	MX31_PIN_USB_PWR	= IOMUX_PIN(29,    75), +	MX31_PIN_SJC_MOD	= IOMUX_PIN(0xff,  76), +	MX31_PIN_DE_B		= IOMUX_PIN(0xff,  77), +	MX31_PIN_TRSTB		= IOMUX_PIN(0xff,  78), +	MX31_PIN_TDO		= IOMUX_PIN(0xff,  79), +	MX31_PIN_TDI		= IOMUX_PIN(0xff,  80), +	MX31_PIN_TMS		= IOMUX_PIN(0xff,  81), +	MX31_PIN_TCK		= IOMUX_PIN(0xff,  82), +	MX31_PIN_RTCK		= IOMUX_PIN(0xff,  83), +	MX31_PIN_KEY_COL7	= IOMUX_PIN(57,    84), +	MX31_PIN_KEY_COL6	= IOMUX_PIN(56,    85), +	MX31_PIN_KEY_COL5	= IOMUX_PIN(55,    86), +	MX31_PIN_KEY_COL4	= IOMUX_PIN(54,    87), +	MX31_PIN_KEY_COL3	= IOMUX_PIN(0xff,  88), +	MX31_PIN_KEY_COL2	= IOMUX_PIN(0xff,  89), +	MX31_PIN_KEY_COL1	= IOMUX_PIN(0xff,  90), +	MX31_PIN_KEY_COL0	= IOMUX_PIN(0xff,  91), +	MX31_PIN_KEY_ROW7	= IOMUX_PIN(53,    92), +	MX31_PIN_KEY_ROW6	= IOMUX_PIN(52,    93), +	MX31_PIN_KEY_ROW5	= IOMUX_PIN(51,    94), +	MX31_PIN_KEY_ROW4	= IOMUX_PIN(50,    95), +	MX31_PIN_KEY_ROW3	= IOMUX_PIN(0xff,  96), +	MX31_PIN_KEY_ROW2	= IOMUX_PIN(0xff,  97), +	MX31_PIN_KEY_ROW1	= IOMUX_PIN(0xff,  98), +	MX31_PIN_KEY_ROW0	= IOMUX_PIN(0xff,  99), +	MX31_PIN_BATT_LINE	= IOMUX_PIN(49,   100), +	MX31_PIN_CTS2		= IOMUX_PIN(0xff, 101), +	MX31_PIN_RTS2		= IOMUX_PIN(0xff, 102), +	MX31_PIN_TXD2		= IOMUX_PIN(28,   103), +	MX31_PIN_RXD2		= IOMUX_PIN(27,   104), +	MX31_PIN_DTR_DCE2	= IOMUX_PIN(48,   105), +	MX31_PIN_DCD_DTE1	= IOMUX_PIN(47,   106), +	MX31_PIN_RI_DTE1	= IOMUX_PIN(46,   107), +	MX31_PIN_DSR_DTE1	= IOMUX_PIN(45,   108), +	MX31_PIN_DTR_DTE1	= IOMUX_PIN(44,   109), +	MX31_PIN_DCD_DCE1	= IOMUX_PIN(43,   110), +	MX31_PIN_RI_DCE1	= IOMUX_PIN(42,   111), +	MX31_PIN_DSR_DCE1	= IOMUX_PIN(41,   112), +	MX31_PIN_DTR_DCE1	= IOMUX_PIN(40,   113), +	MX31_PIN_CTS1		= IOMUX_PIN(39,   114), +	MX31_PIN_RTS1		= IOMUX_PIN(38,   115), +	MX31_PIN_TXD1		= IOMUX_PIN(37,   116), +	MX31_PIN_RXD1		= IOMUX_PIN(36,   117), +	MX31_PIN_CSPI2_SPI_RDY	= IOMUX_PIN(0xff, 118), +	MX31_PIN_CSPI2_SCLK	= IOMUX_PIN(0xff, 119), +	MX31_PIN_CSPI2_SS2	= IOMUX_PIN(0xff, 120), +	MX31_PIN_CSPI2_SS1	= IOMUX_PIN(0xff, 121), +	MX31_PIN_CSPI2_SS0	= IOMUX_PIN(0xff, 122), +	MX31_PIN_CSPI2_MISO	= IOMUX_PIN(0xff, 123), +	MX31_PIN_CSPI2_MOSI	= IOMUX_PIN(0xff, 124), +	MX31_PIN_CSPI1_SPI_RDY	= IOMUX_PIN(0xff, 125), +	MX31_PIN_CSPI1_SCLK	= IOMUX_PIN(0xff, 126), +	MX31_PIN_CSPI1_SS2	= IOMUX_PIN(0xff, 127), +	MX31_PIN_CSPI1_SS1	= IOMUX_PIN(0xff, 128), +	MX31_PIN_CSPI1_SS0	= IOMUX_PIN(0xff, 129), +	MX31_PIN_CSPI1_MISO	= IOMUX_PIN(0xff, 130), +	MX31_PIN_CSPI1_MOSI	= IOMUX_PIN(0xff, 131), +	MX31_PIN_SFS6		= IOMUX_PIN(26,   132), +	MX31_PIN_SCK6		= IOMUX_PIN(25,   133), +	MX31_PIN_SRXD6		= IOMUX_PIN(24,   134), +	MX31_PIN_STXD6		= IOMUX_PIN(23,   135), +	MX31_PIN_SFS5		= IOMUX_PIN(0xff, 136), +	MX31_PIN_SCK5		= IOMUX_PIN(0xff, 137), +	MX31_PIN_SRXD5		= IOMUX_PIN(22,   138), +	MX31_PIN_STXD5		= IOMUX_PIN(21,   139), +	MX31_PIN_SFS4		= IOMUX_PIN(0xff, 140), +	MX31_PIN_SCK4		= IOMUX_PIN(0xff, 141), +	MX31_PIN_SRXD4		= IOMUX_PIN(20,   142), +	MX31_PIN_STXD4		= IOMUX_PIN(19,   143), +	MX31_PIN_SFS3		= IOMUX_PIN(0xff, 144), +	MX31_PIN_SCK3		= IOMUX_PIN(0xff, 145), +	MX31_PIN_SRXD3		= IOMUX_PIN(18,   146), +	MX31_PIN_STXD3		= IOMUX_PIN(17,   147), +	MX31_PIN_I2C_DAT	= IOMUX_PIN(0xff, 148), +	MX31_PIN_I2C_CLK	= IOMUX_PIN(0xff, 149), +	MX31_PIN_CSI_PIXCLK	= IOMUX_PIN(83,   150), +	MX31_PIN_CSI_HSYNC	= IOMUX_PIN(82,   151), +	MX31_PIN_CSI_VSYNC	= IOMUX_PIN(81,   152), +	MX31_PIN_CSI_MCLK	= IOMUX_PIN(80,   153), +	MX31_PIN_CSI_D15	= IOMUX_PIN(79,   154), +	MX31_PIN_CSI_D14	= IOMUX_PIN(78,   155), +	MX31_PIN_CSI_D13	= IOMUX_PIN(77,   156), +	MX31_PIN_CSI_D12	= IOMUX_PIN(76,   157), +	MX31_PIN_CSI_D11	= IOMUX_PIN(75,   158), +	MX31_PIN_CSI_D10	= IOMUX_PIN(74,   159), +	MX31_PIN_CSI_D9		= IOMUX_PIN(73,   160), +	MX31_PIN_CSI_D8		= IOMUX_PIN(72,   161), +	MX31_PIN_CSI_D7		= IOMUX_PIN(71,   162), +	MX31_PIN_CSI_D6		= IOMUX_PIN(70,   163), +	MX31_PIN_CSI_D5		= IOMUX_PIN(69,   164), +	MX31_PIN_CSI_D4		= IOMUX_PIN(68,   165), +	MX31_PIN_M_GRANT	= IOMUX_PIN(0xff, 166), +	MX31_PIN_M_REQUEST	= IOMUX_PIN(0xff, 167), +	MX31_PIN_PC_POE		= IOMUX_PIN(0xff, 168), +	MX31_PIN_PC_RW_B	= IOMUX_PIN(0xff, 169), +	MX31_PIN_IOIS16		= IOMUX_PIN(0xff, 170), +	MX31_PIN_PC_RST		= IOMUX_PIN(0xff, 171), +	MX31_PIN_PC_BVD2	= IOMUX_PIN(0xff, 172), +	MX31_PIN_PC_BVD1	= IOMUX_PIN(0xff, 173), +	MX31_PIN_PC_VS2		= IOMUX_PIN(0xff, 174), +	MX31_PIN_PC_VS1		= IOMUX_PIN(0xff, 175), +	MX31_PIN_PC_PWRON	= IOMUX_PIN(0xff, 176), +	MX31_PIN_PC_READY	= IOMUX_PIN(0xff, 177), +	MX31_PIN_PC_WAIT_B	= IOMUX_PIN(0xff, 178), +	MX31_PIN_PC_CD2_B	= IOMUX_PIN(0xff, 179), +	MX31_PIN_PC_CD1_B	= IOMUX_PIN(0xff, 180), +	MX31_PIN_D0		= IOMUX_PIN(0xff, 181), +	MX31_PIN_D1		= IOMUX_PIN(0xff, 182), +	MX31_PIN_D2		= IOMUX_PIN(0xff, 183), +	MX31_PIN_D3		= IOMUX_PIN(0xff, 184), +	MX31_PIN_D4		= IOMUX_PIN(0xff, 185), +	MX31_PIN_D5		= IOMUX_PIN(0xff, 186), +	MX31_PIN_D6		= IOMUX_PIN(0xff, 187), +	MX31_PIN_D7		= IOMUX_PIN(0xff, 188), +	MX31_PIN_D8		= IOMUX_PIN(0xff, 189), +	MX31_PIN_D9		= IOMUX_PIN(0xff, 190), +	MX31_PIN_D10		= IOMUX_PIN(0xff, 191), +	MX31_PIN_D11		= IOMUX_PIN(0xff, 192), +	MX31_PIN_D12		= IOMUX_PIN(0xff, 193), +	MX31_PIN_D13		= IOMUX_PIN(0xff, 194), +	MX31_PIN_D14		= IOMUX_PIN(0xff, 195), +	MX31_PIN_D15		= IOMUX_PIN(0xff, 196), +	MX31_PIN_NFRB		= IOMUX_PIN(16,   197), +	MX31_PIN_NFCE_B		= IOMUX_PIN(15,   198), +	MX31_PIN_NFWP_B		= IOMUX_PIN(14,   199), +	MX31_PIN_NFCLE		= IOMUX_PIN(13,   200), +	MX31_PIN_NFALE		= IOMUX_PIN(12,   201), +	MX31_PIN_NFRE_B		= IOMUX_PIN(11,   202), +	MX31_PIN_NFWE_B		= IOMUX_PIN(10,   203), +	MX31_PIN_SDQS3		= IOMUX_PIN(0xff, 204), +	MX31_PIN_SDQS2		= IOMUX_PIN(0xff, 205), +	MX31_PIN_SDQS1		= IOMUX_PIN(0xff, 206), +	MX31_PIN_SDQS0		= IOMUX_PIN(0xff, 207), +	MX31_PIN_SDCLK_B	= IOMUX_PIN(0xff, 208), +	MX31_PIN_SDCLK		= IOMUX_PIN(0xff, 209), +	MX31_PIN_SDCKE1		= IOMUX_PIN(0xff, 210), +	MX31_PIN_SDCKE0		= IOMUX_PIN(0xff, 211), +	MX31_PIN_SDWE		= IOMUX_PIN(0xff, 212), +	MX31_PIN_CAS		= IOMUX_PIN(0xff, 213), +	MX31_PIN_RAS		= IOMUX_PIN(0xff, 214), +	MX31_PIN_RW		= IOMUX_PIN(0xff, 215), +	MX31_PIN_BCLK		= IOMUX_PIN(0xff, 216), +	MX31_PIN_LBA		= IOMUX_PIN(0xff, 217), +	MX31_PIN_ECB		= IOMUX_PIN(0xff, 218), +	MX31_PIN_CS5		= IOMUX_PIN(0xff, 219), +	MX31_PIN_CS4		= IOMUX_PIN(0xff, 220), +	MX31_PIN_CS3		= IOMUX_PIN(0xff, 221), +	MX31_PIN_CS2		= IOMUX_PIN(0xff, 222), +	MX31_PIN_CS1		= IOMUX_PIN(0xff, 223), +	MX31_PIN_CS0		= IOMUX_PIN(0xff, 224), +	MX31_PIN_OE		= IOMUX_PIN(0xff, 225), +	MX31_PIN_EB1		= IOMUX_PIN(0xff, 226), +	MX31_PIN_EB0		= IOMUX_PIN(0xff, 227), +	MX31_PIN_DQM3		= IOMUX_PIN(0xff, 228), +	MX31_PIN_DQM2		= IOMUX_PIN(0xff, 229), +	MX31_PIN_DQM1		= IOMUX_PIN(0xff, 230), +	MX31_PIN_DQM0		= IOMUX_PIN(0xff, 231), +	MX31_PIN_SD31		= IOMUX_PIN(0xff, 232), +	MX31_PIN_SD30		= IOMUX_PIN(0xff, 233), +	MX31_PIN_SD29		= IOMUX_PIN(0xff, 234), +	MX31_PIN_SD28		= IOMUX_PIN(0xff, 235), +	MX31_PIN_SD27		= IOMUX_PIN(0xff, 236), +	MX31_PIN_SD26		= IOMUX_PIN(0xff, 237), +	MX31_PIN_SD25		= IOMUX_PIN(0xff, 238), +	MX31_PIN_SD24		= IOMUX_PIN(0xff, 239), +	MX31_PIN_SD23		= IOMUX_PIN(0xff, 240), +	MX31_PIN_SD22		= IOMUX_PIN(0xff, 241), +	MX31_PIN_SD21		= IOMUX_PIN(0xff, 242), +	MX31_PIN_SD20		= IOMUX_PIN(0xff, 243), +	MX31_PIN_SD19		= IOMUX_PIN(0xff, 244), +	MX31_PIN_SD18		= IOMUX_PIN(0xff, 245), +	MX31_PIN_SD17		= IOMUX_PIN(0xff, 246), +	MX31_PIN_SD16		= IOMUX_PIN(0xff, 247), +	MX31_PIN_SD15		= IOMUX_PIN(0xff, 248), +	MX31_PIN_SD14		= IOMUX_PIN(0xff, 249), +	MX31_PIN_SD13		= IOMUX_PIN(0xff, 250), +	MX31_PIN_SD12		= IOMUX_PIN(0xff, 251), +	MX31_PIN_SD11		= IOMUX_PIN(0xff, 252), +	MX31_PIN_SD10		= IOMUX_PIN(0xff, 253), +	MX31_PIN_SD9		= IOMUX_PIN(0xff, 254), +	MX31_PIN_SD8		= IOMUX_PIN(0xff, 255), +	MX31_PIN_SD7		= IOMUX_PIN(0xff, 256), +	MX31_PIN_SD6		= IOMUX_PIN(0xff, 257), +	MX31_PIN_SD5		= IOMUX_PIN(0xff, 258), +	MX31_PIN_SD4		= IOMUX_PIN(0xff, 259), +	MX31_PIN_SD3		= IOMUX_PIN(0xff, 260), +	MX31_PIN_SD2		= IOMUX_PIN(0xff, 261), +	MX31_PIN_SD1		= IOMUX_PIN(0xff, 262), +	MX31_PIN_SD0		= IOMUX_PIN(0xff, 263), +	MX31_PIN_SDBA0		= IOMUX_PIN(0xff, 264), +	MX31_PIN_SDBA1		= IOMUX_PIN(0xff, 265), +	MX31_PIN_A25		= IOMUX_PIN(0xff, 266), +	MX31_PIN_A24		= IOMUX_PIN(0xff, 267), +	MX31_PIN_A23		= IOMUX_PIN(0xff, 268), +	MX31_PIN_A22		= IOMUX_PIN(0xff, 269), +	MX31_PIN_A21		= IOMUX_PIN(0xff, 270), +	MX31_PIN_A20		= IOMUX_PIN(0xff, 271), +	MX31_PIN_A19		= IOMUX_PIN(0xff, 272), +	MX31_PIN_A18		= IOMUX_PIN(0xff, 273), +	MX31_PIN_A17		= IOMUX_PIN(0xff, 274), +	MX31_PIN_A16		= IOMUX_PIN(0xff, 275), +	MX31_PIN_A14		= IOMUX_PIN(0xff, 276), +	MX31_PIN_A15		= IOMUX_PIN(0xff, 277), +	MX31_PIN_A13		= IOMUX_PIN(0xff, 278), +	MX31_PIN_A12		= IOMUX_PIN(0xff, 279), +	MX31_PIN_A11		= IOMUX_PIN(0xff, 280), +	MX31_PIN_MA10		= IOMUX_PIN(0xff, 281), +	MX31_PIN_A10		= IOMUX_PIN(0xff, 282), +	MX31_PIN_A9		= IOMUX_PIN(0xff, 283), +	MX31_PIN_A8		= IOMUX_PIN(0xff, 284), +	MX31_PIN_A7		= IOMUX_PIN(0xff, 285), +	MX31_PIN_A6		= IOMUX_PIN(0xff, 286), +	MX31_PIN_A5		= IOMUX_PIN(0xff, 287), +	MX31_PIN_A4		= IOMUX_PIN(0xff, 288), +	MX31_PIN_A3		= IOMUX_PIN(0xff, 289), +	MX31_PIN_A2		= IOMUX_PIN(0xff, 290), +	MX31_PIN_A1		= IOMUX_PIN(0xff, 291), +	MX31_PIN_A0		= IOMUX_PIN(0xff, 292), +	MX31_PIN_VPG1		= IOMUX_PIN(0xff, 293), +	MX31_PIN_VPG0		= IOMUX_PIN(0xff, 294), +	MX31_PIN_DVFS1		= IOMUX_PIN(0xff, 295), +	MX31_PIN_DVFS0		= IOMUX_PIN(0xff, 296), +	MX31_PIN_VSTBY		= IOMUX_PIN(0xff, 297), +	MX31_PIN_POWER_FAIL	= IOMUX_PIN(0xff, 298), +	MX31_PIN_CKIL		= IOMUX_PIN(0xff, 299), +	MX31_PIN_BOOT_MODE4	= IOMUX_PIN(0xff, 300), +	MX31_PIN_BOOT_MODE3	= IOMUX_PIN(0xff, 301), +	MX31_PIN_BOOT_MODE2	= IOMUX_PIN(0xff, 302), +	MX31_PIN_BOOT_MODE1	= IOMUX_PIN(0xff, 303), +	MX31_PIN_BOOT_MODE0	= IOMUX_PIN(0xff, 304), +	MX31_PIN_CLKO		= IOMUX_PIN(0xff, 305), +	MX31_PIN_POR_B		= IOMUX_PIN(0xff, 306), +	MX31_PIN_RESET_IN_B	= IOMUX_PIN(0xff, 307), +	MX31_PIN_CKIH		= IOMUX_PIN(0xff, 308), +	MX31_PIN_SIMPD0		= IOMUX_PIN(35,   309), +	MX31_PIN_SRX0		= IOMUX_PIN(34,   310), +	MX31_PIN_STX0		= IOMUX_PIN(33,   311), +	MX31_PIN_SVEN0		= IOMUX_PIN(32,   312), +	MX31_PIN_SRST0		= IOMUX_PIN(67,   313), +	MX31_PIN_SCLK0		= IOMUX_PIN(66,   314), +	MX31_PIN_GPIO3_1	= IOMUX_PIN(65,   315), +	MX31_PIN_GPIO3_0	= IOMUX_PIN(64,   316), +	MX31_PIN_GPIO1_6	= IOMUX_PIN(6,    317), +	MX31_PIN_GPIO1_5	= IOMUX_PIN(5,    318), +	MX31_PIN_GPIO1_4	= IOMUX_PIN(4,    319), +	MX31_PIN_GPIO1_3	= IOMUX_PIN(3,    320), +	MX31_PIN_GPIO1_2	= IOMUX_PIN(2,    321), +	MX31_PIN_GPIO1_1	= IOMUX_PIN(1,    322), +	MX31_PIN_GPIO1_0	= IOMUX_PIN(0,    323), +	MX31_PIN_PWMO		= IOMUX_PIN(9,    324), +	MX31_PIN_WATCHDOG_RST	= IOMUX_PIN(0xff, 325), +	MX31_PIN_COMPARE	= IOMUX_PIN(8,    326), +	MX31_PIN_CAPTURE	= IOMUX_PIN(7,    327), +};  /* Bit definitions for RCSR register in CCM */  #define CCM_RCSR_NF16B	(1 << 31) @@ -194,6 +558,12 @@ struct gpio_regs {  /* Register offsets based on IOMUXC_BASE */  /* 0x00 .. 0x7b */ +#define MUX_CTL_USBH2_DATA1	0x40 +#define MUX_CTL_USBH2_DIR	0x44 +#define MUX_CTL_USBH2_STP	0x45 +#define MUX_CTL_USBH2_NXT	0x46 +#define MUX_CTL_USBH2_DATA0	0x47 +#define MUX_CTL_USBH2_CLK	0x4B  #define MUX_CTL_RTS1		0x7c  #define MUX_CTL_CTS1		0x7d  #define MUX_CTL_DTR_DCE1	0x7e @@ -214,6 +584,15 @@ struct gpio_regs {  #define MUX_CTL_CSPI1_MISO	0x8d  #define MUX_CTL_CSPI1_SS0	0x8e  #define MUX_CTL_CSPI1_SS1	0x8f +#define MUX_CTL_STXD6		0x90 +#define MUX_CTL_SRXD6		0x91 +#define MUX_CTL_SCK6		0x92 +#define MUX_CTL_SFS6		0x93 + +#define MUX_CTL_STXD3		0x9C +#define MUX_CTL_SRXD3		0x9D +#define MUX_CTL_SCK3		0x9E +#define MUX_CTL_SFS3		0x9F  #define MUX_CTL_NFC_WP		0xD0  #define MUX_CTL_NFC_CE		0xD1 @@ -224,6 +603,9 @@ struct gpio_regs {  #define MUX_CTL_NFC_CLE		0xD7 +#define MUX_CTL_CAPTURE		0x150 +#define MUX_CTL_COMPARE		0x151 +  /*   * Helper macros for the MUX_[contact name]__[pin function] macros   */ @@ -317,4 +699,33 @@ struct gpio_regs {  #define	IRAM_BASE_ADDR	0x1FFFC000  #define IRAM_SIZE	(16 * 1024) +#define MX31_AIPS1_BASE_ADDR	0x43f00000 +#define MX31_OTG_BASE_ADDR	(MX31_AIPS1_BASE_ADDR + 0x88000) + +/* USB portsc */ +/* values for portsc field */ +#define MXC_EHCI_PHY_LOW_POWER_SUSPEND	(1 << 23) +#define MXC_EHCI_FORCE_FS		(1 << 24) +#define MXC_EHCI_UTMI_8BIT		(0 << 28) +#define MXC_EHCI_UTMI_16BIT		(1 << 28) +#define MXC_EHCI_SERIAL			(1 << 29) +#define MXC_EHCI_MODE_UTMI		(0 << 30) +#define MXC_EHCI_MODE_PHILIPS		(1 << 30) +#define MXC_EHCI_MODE_ULPI		(2 << 30) +#define MXC_EHCI_MODE_SERIAL		(3 << 30) + +/* values for flags field */ +#define MXC_EHCI_INTERFACE_DIFF_UNI	(0 << 0) +#define MXC_EHCI_INTERFACE_DIFF_BI	(1 << 0) +#define MXC_EHCI_INTERFACE_SINGLE_UNI	(2 << 0) +#define MXC_EHCI_INTERFACE_SINGLE_BI	(3 << 0) +#define MXC_EHCI_INTERFACE_MASK		(0xf) + +#define MXC_EHCI_POWER_PINS_ENABLED	(1 << 5) +#define MXC_EHCI_TTL_ENABLED		(1 << 6) + +#define MXC_EHCI_INTERNAL_PHY		(1 << 7) +#define MXC_EHCI_IPPUE_DOWN		(1 << 8) +#define MXC_EHCI_IPPUE_UP		(1 << 9) +  #endif /* __ASM_ARCH_MX31_REGS_H */ diff --git a/board/davedenx/qong/Makefile b/board/davedenx/qong/Makefile index 93e198542..ada6e03a2 100644 --- a/board/davedenx/qong/Makefile +++ b/board/davedenx/qong/Makefile @@ -27,7 +27,7 @@ include $(TOPDIR)/config.mk  LIB	= $(obj)lib$(BOARD).a -COBJS	:= qong.o +COBJS	:= qong.o fpga.o  SOBJS	:= lowlevel_init.o  SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/board/davedenx/qong/fpga.c b/board/davedenx/qong/fpga.c new file mode 100644 index 000000000..f865eb422 --- /dev/null +++ b/board/davedenx/qong/fpga.c @@ -0,0 +1,95 @@ +/* + * (C) Copyright 2010 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include <common.h> +#include <asm/arch/mx31.h> +#include <asm/arch/mx31-regs.h> +#include <mxc_gpio.h> +#include <fpga.h> +#include <lattice.h> +#include "qong_fpga.h" + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_FPGA) + +static void qong_jtag_init(void) +{ +	return; +} + +static void qong_fpga_jtag_set_tdi(int value) +{ +	mxc_gpio_set(QONG_FPGA_TDI_PIN, value); +} + +static void qong_fpga_jtag_set_tms(int value) +{ +	mxc_gpio_set(QONG_FPGA_TMS_PIN, value); +} + +static void qong_fpga_jtag_set_tck(int value) +{ +	mxc_gpio_set(QONG_FPGA_TCK_PIN, value); +} + +static int qong_fpga_jtag_get_tdo(void) +{ +	return mxc_gpio_get(QONG_FPGA_TDO_PIN); +} + +lattice_board_specific_func qong_fpga_fns = { +	qong_jtag_init, +	qong_fpga_jtag_set_tdi, +	qong_fpga_jtag_set_tms, +	qong_fpga_jtag_set_tck, +	qong_fpga_jtag_get_tdo +}; + +Lattice_desc qong_fpga[CONFIG_FPGA_COUNT] = { +	{ +		Lattice_XP2, +		lattice_jtag_mode, +		356519, +		(void *) &qong_fpga_fns, +		NULL, +		0, +		"lfxp2_5e_ftbga256" +	}, +}; + +int qong_fpga_init(void) +{ +	int i; + +	fpga_init(); + +	for (i = 0; i < CONFIG_FPGA_COUNT; i++) { +		fpga_add(fpga_lattice, &qong_fpga[i]); +	} +	return 0; +} + +#endif + diff --git a/board/davedenx/qong/qong.c b/board/davedenx/qong/qong.c index 9abc29c5f..8a81cfc68 100644 --- a/board/davedenx/qong/qong.c +++ b/board/davedenx/qong/qong.c @@ -25,6 +25,7 @@  #include <netdev.h>  #include <asm/arch/mx31.h>  #include <asm/arch/mx31-regs.h> +#include <asm/io.h>  #include <nand.h>  #include <fsl_pmic.h>  #include <mxc_gpio.h> @@ -73,6 +74,15 @@ int board_early_init_f (void)  	/* set interrupt pin as input */  	mxc_gpio_direction(QONG_FPGA_IRQ_PIN, MXC_GPIO_DIRECTION_IN); +	/* FPGA JTAG Interface */ +	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_SFS6, MUX_CTL_GPIO)); +	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_SCK6, MUX_CTL_GPIO)); +	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_CAPTURE, MUX_CTL_GPIO)); +	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_COMPARE, MUX_CTL_GPIO)); +	mxc_gpio_direction(QONG_FPGA_TCK_PIN, MXC_GPIO_DIRECTION_OUT); +	mxc_gpio_direction(QONG_FPGA_TMS_PIN, MXC_GPIO_DIRECTION_OUT); +	mxc_gpio_direction(QONG_FPGA_TDI_PIN, MXC_GPIO_DIRECTION_OUT); +	mxc_gpio_direction(QONG_FPGA_TDO_PIN, MXC_GPIO_DIRECTION_IN);  #endif  	/* setup pins for UART1 */ @@ -88,6 +98,38 @@ int board_early_init_f (void)  	mx31_gpio_mux(MUX_CSPI2_SCLK__CSPI2_CLK);  	mx31_gpio_mux(MUX_CSPI2_SPI_RDY__CSPI2_DATAREADY_B); +	/* Setup pins for USB2 Host */ +	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_USBH2_CLK, MUX_CTL_FUNC)); +	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_USBH2_DIR, MUX_CTL_FUNC)); +	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_USBH2_NXT, MUX_CTL_FUNC)); +	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_USBH2_STP, MUX_CTL_FUNC)); +	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_USBH2_DATA0, MUX_CTL_FUNC)); +	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_USBH2_DATA1, MUX_CTL_FUNC)); +	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_STXD3, MUX_CTL_FUNC)); +	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_SRXD3, MUX_CTL_FUNC)); +	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_SCK3, MUX_CTL_FUNC)); +	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_SFS3, MUX_CTL_FUNC)); +	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_STXD6, MUX_CTL_FUNC)); +	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_SRXD6, MUX_CTL_FUNC)); + +#define H2_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \ +			PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU) + +	mx31_set_pad(MX31_PIN_USBH2_CLK, H2_PAD_CFG); +	mx31_set_pad(MX31_PIN_USBH2_DIR, H2_PAD_CFG); +	mx31_set_pad(MX31_PIN_USBH2_NXT, H2_PAD_CFG); +	mx31_set_pad(MX31_PIN_USBH2_STP, H2_PAD_CFG); +	mx31_set_pad(MX31_PIN_USBH2_DATA0, H2_PAD_CFG); /* USBH2_DATA0 */ +	mx31_set_pad(MX31_PIN_USBH2_DATA1, H2_PAD_CFG); /* USBH2_DATA1 */ +	mx31_set_pad(MX31_PIN_SRXD6, H2_PAD_CFG);	/* USBH2_DATA2 */ +	mx31_set_pad(MX31_PIN_STXD6, H2_PAD_CFG);	/* USBH2_DATA3 */ +	mx31_set_pad(MX31_PIN_SFS3, H2_PAD_CFG);	/* USBH2_DATA4 */ +	mx31_set_pad(MX31_PIN_SCK3, H2_PAD_CFG);	/* USBH2_DATA5 */ +	mx31_set_pad(MX31_PIN_SRXD3, H2_PAD_CFG);	/* USBH2_DATA6 */ +	mx31_set_pad(MX31_PIN_STXD3, H2_PAD_CFG);	/* USBH2_DATA7 */ + +	writel(readl((IOMUXC_BASE + 0x8)) | (1 << 11), IOMUXC_BASE + 0x8); +  	return 0;  } @@ -146,6 +188,8 @@ int board_init (void)  	gd->bd->bi_arch_number = MACH_TYPE_QONG;  	gd->bd->bi_boot_params = (0x80000100);	/* adress of boot parameters */ +	qong_fpga_init(); +  	return 0;  } diff --git a/board/davedenx/qong/qong_fpga.h b/board/davedenx/qong/qong_fpga.h index 4e11f5a1c..4e79ac2cf 100644 --- a/board/davedenx/qong/qong_fpga.h +++ b/board/davedenx/qong/qong_fpga.h @@ -24,7 +24,6 @@  #ifndef QONG_FPGA_H  #define QONG_FPGA_H -#ifdef CONFIG_QONG_FPGA  #define QONG_FPGA_CTRL_BASE		CONFIG_FPGA_BASE  #define QONG_FPGA_CTRL_VERSION		(QONG_FPGA_CTRL_BASE + 0x00000000)  #define QONG_FPGA_PERIPH_SIZE		(1 << 24) @@ -35,6 +34,6 @@  #define	QONG_FPGA_TDO_PIN		7  #define	QONG_FPGA_RST_PIN		48  #define	QONG_FPGA_IRQ_PIN		40 -#endif +int qong_fpga_init(void);  #endif /* QONG_FPGA_H */ diff --git a/board/freescale/mx51evk/config.mk b/board/freescale/mx51evk/config.mk index af70ec250..dd4a2c299 100644 --- a/board/freescale/mx51evk/config.mk +++ b/board/freescale/mx51evk/config.mk @@ -23,3 +23,4 @@  LDSCRIPT = $(CPUDIR)/$(SOC)/u-boot.lds  TEXT_BASE = 0x97800000  IMX_CONFIG = $(SRCTREE)/board/$(BOARDDIR)/imximage.cfg +ALL += $(obj)u-boot.imx diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index 52d8e2432..9ecdc5ef1 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -31,6 +31,7 @@ COBJS-$(CONFIG_FPGA_SPARTAN2) += spartan2.o  COBJS-$(CONFIG_FPGA_SPARTAN3) += spartan3.o  COBJS-$(CONFIG_FPGA_VIRTEX2) += virtex2.o  COBJS-$(CONFIG_FPGA_XILINX) += xilinx.o +COBJS-$(CONFIG_FPGA_LATTICE) += ivm_core.o lattice.o  ifdef CONFIG_FPGA_ALTERA  COBJS-y += altera.o  COBJS-$(CONFIG_FPGA_ACEX1K) += ACEX1K.o diff --git a/drivers/fpga/fpga.c b/drivers/fpga/fpga.c index 565951779..e41e72851 100644 --- a/drivers/fpga/fpga.c +++ b/drivers/fpga/fpga.c @@ -28,6 +28,7 @@  #include <common.h>             /* core U-Boot definitions */  #include <xilinx.h>             /* xilinx specific definitions */  #include <altera.h>             /* altera specific definitions */ +#include <lattice.h>  #if 0  #define FPGA_DEBUG              /* define FPGA_DEBUG to get debug messages */ @@ -139,6 +140,10 @@ static int fpga_dev_info( int devnum )  			fpga_no_sup( (char *)__FUNCTION__, "Altera devices" );  #endif  			break; +		case fpga_lattice: +			printf("Lattice Device\nDescriptor @ 0x%p\n", desc); +			ret_val = lattice_info(desc->devdesc); +			break;  		default:  			printf( "%s: Invalid or unsupported device type %d\n",  					__FUNCTION__, desc->devtype ); @@ -224,6 +229,9 @@ int fpga_load( int devnum, void *buf, size_t bsize )  			fpga_no_sup( (char *)__FUNCTION__, "Altera devices" );  #endif  			break; +		case fpga_lattice: +			ret_val = lattice_load(desc->devdesc, buf, bsize); +			break;  		default:  			printf( "%s: Invalid or unsupported device type %d\n",  				__FUNCTION__, desc->devtype ); @@ -257,6 +265,9 @@ int fpga_dump( int devnum, void *buf, size_t bsize )  			fpga_no_sup( (char *)__FUNCTION__, "Altera devices" );  #endif  			break; +		case fpga_lattice: +			ret_val = lattice_dump(desc->devdesc, buf, bsize); +			break;  		default:  			printf( "%s: Invalid or unsupported device type %d\n",  				__FUNCTION__, desc->devtype ); diff --git a/drivers/fpga/ivm_core.c b/drivers/fpga/ivm_core.c new file mode 100755 index 000000000..2b5a485f2 --- /dev/null +++ b/drivers/fpga/ivm_core.c @@ -0,0 +1,3167 @@ +/* + * Porting to u-boot: + * + * (C) Copyright 2010 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * Lattice ispVME Embedded code to load Lattice's FPGA: + * + * Copyright 2009 Lattice Semiconductor Corp. + * + * ispVME Embedded allows programming of Lattice's suite of FPGA + * devices on embedded systems through the JTAG port.  The software + * is distributed in source code form and is open to re - distribution + * and modification where applicable. + * + * Revision History of ivm_core.c module: + * 4/25/06 ht   Change some variables from unsigned short or int + *              to long int to make the code compiler independent. + * 5/24/06 ht   Support using RESET (TRST) pin as a special purpose + *              control pin such as triggering the loading of known + *              state exit. + * 3/6/07 ht added functions to support output to terminals + * + * 09/11/07 NN Type cast mismatch variables + *		   Moved the sclock() function to hardware.c + * 08/28/08 NN Added Calculate checksum support. + * 4/1/09 Nguyen replaced the recursive function call codes on + *        the ispVMLCOUNT function + * See file CREDITS for list of people who contributed to this + * project. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <linux/string.h> +#include <malloc.h> +#include <lattice.h> + +#define vme_out_char(c)	printf("%c", c) +#define vme_out_hex(c)	printf("%x", c) +#define vme_out_string(s) printf("%s", s) + +/* + * + * Global variables used to specify the flow control and data type. + * + *	g_usFlowControl:	flow control register. Each bit in the + *                               register can potentially change the + *                               personality of the embedded engine. + *	g_usDataType:		holds the data type of the current row. + * + */ + +static unsigned short g_usFlowControl; +unsigned short g_usDataType; + +/* + * + * Global variables used to specify the ENDDR and ENDIR. + * + *	g_ucEndDR:		the state that the device goes to after SDR. + *	g_ucEndIR:		the state that the device goes to after SIR. + * + */ + +unsigned char g_ucEndDR = DRPAUSE; +unsigned char g_ucEndIR = IRPAUSE; + +/* + * + * Global variables used to support header/trailer. + * + *	g_usHeadDR:		the number of lead devices in bypass. + *	g_usHeadIR:		the sum of IR length of lead devices. + *	g_usTailDR:		the number of tail devices in bypass. + *	g_usTailIR:		the sum of IR length of tail devices. + * + */ + +static unsigned short g_usHeadDR; +static unsigned short g_usHeadIR; +static unsigned short g_usTailDR; +static unsigned short g_usTailIR; + +/* + * + * Global variable to store the number of bits of data or instruction + * to be shifted into or out from the device. + * + */ + +static unsigned short g_usiDataSize; + +/* + * + * Stores the frequency. Default to 1 MHz. + * + */ + +static int g_iFrequency = 1000; + +/* + * + * Stores the maximum amount of ram needed to hold a row of data. + * + */ + +static unsigned short g_usMaxSize; + +/* + * + * Stores the LSH or RSH value. + * + */ + +static unsigned short g_usShiftValue; + +/* + * + * Stores the current repeat loop value. + * + */ + +static unsigned short g_usRepeatLoops; + +/* + * + * Stores the current vendor. + * + */ + +static signed char g_cVendor = LATTICE; + +/* + * + * Stores the VME file CRC. + * + */ + +unsigned short g_usCalculatedCRC; + +/* + * + * Stores the Device Checksum. + * + */ +/* 08/28/08 NN Added Calculate checksum support. */ +unsigned long g_usChecksum; +static unsigned int g_uiChecksumIndex; + +/* + * + * Stores the current state of the JTAG state machine. + * + */ + +static signed char g_cCurrentJTAGState; + +/* + * + * Global variables used to support looping. + * + *	g_pucHeapMemory:	holds the entire repeat loop. + *	g_iHeapCounter:		points to the current byte in the repeat loop. + *	g_iHEAPSize:		the current size of the repeat in bytes. + * + */ + +unsigned char *g_pucHeapMemory; +unsigned short g_iHeapCounter; +unsigned short g_iHEAPSize; +static unsigned short previous_size; + +/* + * + * Global variables used to support intelligent programming. + * + *	g_usIntelDataIndex:     points to the current byte of the + *                               intelligent buffer. + *	g_usIntelBufferSize:	holds the size of the intelligent + *                               buffer. + * + */ + +unsigned short g_usIntelDataIndex; +unsigned short g_usIntelBufferSize; + +/* + * + * Supported VME versions. + * + */ + +const char *const g_szSupportedVersions[] = { +	"__VME2.0", "__VME3.0", "____12.0", "____12.1", 0}; + +/* + * + * Holds the maximum size of each respective buffer. These variables are used + * to write the HEX files when converting VME to HEX. + * +*/ + +static unsigned short g_usTDOSize; +static unsigned short g_usMASKSize; +static unsigned short g_usTDISize; +static unsigned short g_usDMASKSize; +static unsigned short g_usLCOUNTSize; +static unsigned short g_usHDRSize; +static unsigned short g_usTDRSize; +static unsigned short g_usHIRSize; +static unsigned short g_usTIRSize; +static unsigned short g_usHeapSize; + +/* + * + * Global variables used to store data. + * + *	g_pucOutMaskData:	local RAM to hold one row of MASK data. + *	g_pucInData:		local RAM to hold one row of TDI data. + *	g_pucOutData:		local RAM to hold one row of TDO data. + *	g_pucHIRData:		local RAM to hold the current SIR header. + *	g_pucTIRData:		local RAM to hold the current SIR trailer. + *	g_pucHDRData:		local RAM to hold the current SDR header. + *	g_pucTDRData:		local RAM to hold the current SDR trailer. + *	g_pucIntelBuffer:	local RAM to hold the current intelligent buffer + *	g_pucOutDMaskData:	local RAM to hold one row of DMASK data. + * + */ + +unsigned char	*g_pucOutMaskData	= NULL, +		*g_pucInData		= NULL, +		*g_pucOutData		= NULL, +		*g_pucHIRData		= NULL, +		*g_pucTIRData		= NULL, +		*g_pucHDRData		= NULL, +		*g_pucTDRData		= NULL, +		*g_pucIntelBuffer	= NULL, +		*g_pucOutDMaskData	= NULL; + +/* + * + * JTAG state machine transition table. + * + */ + +struct { +	 unsigned char  CurState;  /* From this state */ +	 unsigned char  NextState; /* Step to this state */ +	 unsigned char  Pattern;   /* The tragetory of TMS */ +	 unsigned char  Pulses;    /* The number of steps */ +} g_JTAGTransistions[25] = { +{ RESET,	RESET,		0xFC, 6 },	/* Transitions from RESET */ +{ RESET,	IDLE,		0x00, 1 }, +{ RESET,	DRPAUSE,	0x50, 5 }, +{ RESET,	IRPAUSE,	0x68, 6 }, +{ IDLE,		RESET,		0xE0, 3 },	/* Transitions from IDLE */ +{ IDLE,		DRPAUSE,	0xA0, 4 }, +{ IDLE,		IRPAUSE,	0xD0, 5 }, +{ DRPAUSE,	RESET,		0xF8, 5 },	/* Transitions from DRPAUSE */ +{ DRPAUSE,	IDLE,		0xC0, 3 }, +{ DRPAUSE,	IRPAUSE,	0xF4, 7 }, +{ DRPAUSE,	DRPAUSE,	0xE8, 6 },/* 06/14/06 Support POLL STATUS LOOP*/ +{ IRPAUSE,	RESET,		0xF8, 5 },	/* Transitions from IRPAUSE */ +{ IRPAUSE,	IDLE,		0xC0, 3 }, +{ IRPAUSE,	DRPAUSE,	0xE8, 6 }, +{ DRPAUSE,	SHIFTDR,	0x80, 2 }, /* Extra transitions using SHIFTDR */ +{ IRPAUSE,	SHIFTDR,	0xE0, 5 }, +{ SHIFTDR,	DRPAUSE,	0x80, 2 }, +{ SHIFTDR,	IDLE,		0xC0, 3 }, +{ IRPAUSE,	SHIFTIR,	0x80, 2 },/* Extra transitions using SHIFTIR */ +{ SHIFTIR,	IRPAUSE,	0x80, 2 }, +{ SHIFTIR,	IDLE,		0xC0, 3 }, +{ DRPAUSE,	DRCAPTURE,	0xE0, 4 }, /* 11/15/05 Support DRCAPTURE*/ +{ DRCAPTURE, DRPAUSE,	0x80, 2 }, +{ IDLE,     DRCAPTURE,	0x80, 2 }, +{ IRPAUSE,  DRCAPTURE,  0xE0, 4 } +}; + +/* + * + * List to hold all LVDS pairs. + * + */ + +LVDSPair *g_pLVDSList; +unsigned short g_usLVDSPairCount; + +/* + * + * Function prototypes. + * + */ + +static signed char ispVMDataCode(void); +static long int ispVMDataSize(void); +static void ispVMData(unsigned char *Data); +static signed char ispVMShift(signed char Code); +static signed char ispVMAmble(signed char Code); +static signed char ispVMLoop(unsigned short a_usLoopCount); +static signed char ispVMBitShift(signed char mode, unsigned short bits); +static void ispVMComment(unsigned short a_usCommentSize); +static void ispVMHeader(unsigned short a_usHeaderSize); +static signed char ispVMLCOUNT(unsigned short a_usCountSize); +static void ispVMClocks(unsigned short Clocks); +static void ispVMBypass(signed char ScanType, unsigned short Bits); +static void ispVMStateMachine(signed char NextState); +static signed char ispVMSend(unsigned short int); +static signed char ispVMRead(unsigned short int); +static signed char ispVMReadandSave(unsigned short int); +static signed char ispVMProcessLVDS(unsigned short a_usLVDSCount); +static void ispVMMemManager(signed char types, unsigned short size); + +/* + * + * External variables and functions in hardware.c module + * + */ +static signed char g_cCurrentJTAGState; + +#ifdef DEBUG + +/* + * + * GetState + * + * Returns the state as a string based on the opcode. Only used + * for debugging purposes. + * + */ + +const char *GetState(unsigned char a_ucState) +{ +	switch (a_ucState) { +	case RESET: +		return "RESET"; +	case IDLE: +		return "IDLE"; +	case IRPAUSE: +		return "IRPAUSE"; +	case DRPAUSE: +		return "DRPAUSE"; +	case SHIFTIR: +		return "SHIFTIR"; +	case SHIFTDR: +		return "SHIFTDR"; +	case DRCAPTURE:/* 11/15/05 support DRCAPTURE*/ +		return "DRCAPTURE"; +	default: +		break; +	} + +	return 0; +} + +/* + * + * PrintData + * + * Prints the data. Only used for debugging purposes. + * + */ + +void PrintData(unsigned short a_iDataSize, unsigned char *a_pucData) +{ +	/* 09/11/07 NN added local variables initialization */ +	unsigned short usByteSize  = 0; +	unsigned short usBitIndex  = 0; +	signed short usByteIndex   = 0; +	unsigned char ucByte       = 0; +	unsigned char ucFlipByte   = 0; + +	if (a_iDataSize % 8) { +		/* 09/11/07 NN Type cast mismatch variables */ +		usByteSize = (unsigned short)(a_iDataSize / 8 + 1); +	} else { +		/* 09/11/07 NN Type cast mismatch variables */ +		usByteSize = (unsigned short)(a_iDataSize / 8); +	} +	puts("("); +	/* 09/11/07 NN Type cast mismatch variables */ +	for (usByteIndex = (signed short)(usByteSize - 1); +		usByteIndex >= 0; usByteIndex--) { +		ucByte = a_pucData[usByteIndex]; +		ucFlipByte = 0x00; + +		/* +		* +		* Flip each byte. +		* +		*/ + +		for (usBitIndex = 0; usBitIndex < 8; usBitIndex++) { +			ucFlipByte <<= 1; +			if (ucByte & 0x1) { +				ucFlipByte |= 0x1; +			} + +			ucByte >>= 1; +		} + +		/* +		* +		* Print the flipped byte. +		* +		*/ + +		printf("%.02X", ucFlipByte); +		if ((usByteSize - usByteIndex) % 40 == 39) { +			puts("\n\t\t"); +		} +		if (usByteIndex < 0) +			break; +	} +	puts(")"); +} +#endif /* DEBUG */ + +void ispVMMemManager(signed char cTarget, unsigned short usSize) +{ +	switch (cTarget) { +	case XTDI: +	case TDI: +		if (g_pucInData != NULL) { +			if (previous_size == usSize) {/*memory exist*/ +				break; +			} else { +				free(g_pucInData); +				g_pucInData = NULL; +			} +		} +		g_pucInData = (unsigned char *) malloc(usSize / 8 + 2); +		previous_size = usSize; +	case XTDO: +	case TDO: +		if (g_pucOutData != NULL) { +			if (previous_size == usSize) { /*already exist*/ +				break; +			} else { +				free(g_pucOutData); +				g_pucOutData = NULL; +			} +		} +		g_pucOutData = (unsigned char *) malloc(usSize / 8 + 2); +		previous_size = usSize; +		break; +	case MASK: +		if (g_pucOutMaskData != NULL) { +			if (previous_size == usSize) {/*already allocated*/ +				break; +			} else { +				free(g_pucOutMaskData); +				g_pucOutMaskData = NULL; +			} +		} +		g_pucOutMaskData = (unsigned char *) malloc(usSize / 8 + 2); +		previous_size = usSize; +		break; +	case HIR: +		if (g_pucHIRData != NULL) { +			free(g_pucHIRData); +			g_pucHIRData = NULL; +		} +		g_pucHIRData = (unsigned char *) malloc(usSize / 8 + 2); +		break; +	case TIR: +		if (g_pucTIRData != NULL) { +			free(g_pucTIRData); +			g_pucTIRData = NULL; +		} +		g_pucTIRData = (unsigned char *) malloc(usSize / 8 + 2); +		break; +	case HDR: +		if (g_pucHDRData != NULL) { +			free(g_pucHDRData); +			g_pucHDRData = NULL; +		} +		g_pucHDRData = (unsigned char *) malloc(usSize / 8 + 2); +		break; +	case TDR: +		if (g_pucTDRData != NULL) { +			free(g_pucTDRData); +			g_pucTDRData = NULL; +		} +		g_pucTDRData = (unsigned char *) malloc(usSize / 8 + 2); +		break; +	case HEAP: +		if (g_pucHeapMemory != NULL) { +			free(g_pucHeapMemory); +			g_pucHeapMemory = NULL; +		} +		g_pucHeapMemory = (unsigned char *) malloc(usSize + 2); +		break; +	case DMASK: +		if (g_pucOutDMaskData != NULL) { +			if (previous_size == usSize) { /*already allocated*/ +				break; +			} else { +				free(g_pucOutDMaskData); +				g_pucOutDMaskData = NULL; +			} +		} +		g_pucOutDMaskData = (unsigned char *) malloc(usSize / 8 + 2); +		previous_size = usSize; +		break; +	case LHEAP: +		if (g_pucIntelBuffer != NULL) { +			free(g_pucIntelBuffer); +			g_pucIntelBuffer = NULL; +		} +		g_pucIntelBuffer = (unsigned char *) malloc(usSize + 2); +		break; +	case LVDS: +		if (g_pLVDSList != NULL) { +			free(g_pLVDSList); +			g_pLVDSList = NULL; +		} +		g_pLVDSList = (LVDSPair *) malloc(usSize * sizeof(LVDSPair)); +		if (g_pLVDSList) +			memset(g_pLVDSList, 0, usSize * sizeof(LVDSPair)); +		break; +	default: +		return; +    } +} + +void ispVMFreeMem(void) +{ +	if (g_pucHeapMemory != NULL) { +		free(g_pucHeapMemory); +		g_pucHeapMemory = NULL; +	} + +	if (g_pucOutMaskData != NULL) { +		free(g_pucOutMaskData); +		g_pucOutMaskData = NULL; +	} + +	if (g_pucInData != NULL) { +		free(g_pucInData); +		g_pucInData = NULL; +	} + +	if (g_pucOutData != NULL) { +		free(g_pucOutData); +		g_pucOutData = NULL; +	} + +	if (g_pucHIRData != NULL) { +		free(g_pucHIRData); +		g_pucHIRData = NULL; +	} + +	if (g_pucTIRData != NULL) { +		free(g_pucTIRData); +		g_pucTIRData = NULL; +	} + +	if (g_pucHDRData != NULL) { +		free(g_pucHDRData); +		g_pucHDRData = NULL; +	} + +	if (g_pucTDRData != NULL) { +		free(g_pucTDRData); +		g_pucTDRData = NULL; +	} + +	if (g_pucOutDMaskData != NULL) { +		free(g_pucOutDMaskData); +		g_pucOutDMaskData = NULL; +	} + +	if (g_pucIntelBuffer != NULL) { +		free(g_pucIntelBuffer); +		g_pucIntelBuffer = NULL; +	} + +	if (g_pLVDSList != NULL) { +		free(g_pLVDSList); +		g_pLVDSList = NULL; +	} +} + + +/* + * + * ispVMDataSize + * + * Returns a VME-encoded number, usually used to indicate the + * bit length of an SIR/SDR command. + * + */ + +long int ispVMDataSize() +{ +	/* 09/11/07 NN added local variables initialization */ +	long int iSize           = 0; +	signed char cCurrentByte = 0; +	signed char cIndex       = 0; +	cIndex = 0; +	while ((cCurrentByte = GetByte()) & 0x80) { +		iSize |= ((long int) (cCurrentByte & 0x7F)) << cIndex; +		cIndex += 7; +	} +	iSize |= ((long int) (cCurrentByte & 0x7F)) << cIndex; +	return iSize; +} + +/* + * + * ispVMCode + * + * This is the heart of the embedded engine. All the high-level opcodes + * are extracted here. Once they have been identified, then it + * will call other functions to handle the processing. + * + */ + +signed char ispVMCode() +{ +	/* 09/11/07 NN added local variables initialization */ +	unsigned short iRepeatSize = 0; +	signed char cOpcode	   = 0; +	signed char cRetCode       = 0; +	unsigned char ucState      = 0; +	unsigned short usDelay     = 0; +	unsigned short usToggle    = 0; +	unsigned char usByte       = 0; + +	/* +	* +	* Check the compression flag only if this is the first time +	* this function is entered. Do not check the compression flag if +	* it is being called recursively from other functions within +	* the embedded engine. +	* +	*/ + +	if (!(g_usDataType & LHEAP_IN) && !(g_usDataType & HEAP_IN)) { +		usByte = GetByte(); +		if (usByte == 0xf1) { +			g_usDataType |= COMPRESS; +		} else if (usByte == 0xf2) { +			g_usDataType &= ~COMPRESS; +		} else { +			return VME_INVALID_FILE; +		} +	} + +	/* +	* +	* Begin looping through all the VME opcodes. +	* +	*/ + +	while ((cOpcode = GetByte()) >= 0) { + +		switch (cOpcode) { +		case STATE: + +			/* +			 * Step the JTAG state machine. +			 */ + +			ucState = GetByte(); + +			/* +			 * Step the JTAG state machine to DRCAPTURE +			 * to support Looping. +			 */ + +			if ((g_usDataType & LHEAP_IN) && +				 (ucState == DRPAUSE) && +				 (g_cCurrentJTAGState == ucState)) { +				ispVMStateMachine(DRCAPTURE); +			} + +			ispVMStateMachine(ucState); + +#ifdef DEBUG +			if (g_usDataType & LHEAP_IN) { +				debug("LDELAY %s ", GetState(ucState)); +			} else { +				debug("STATE %s;\n", GetState(ucState)); +			} +#endif /* DEBUG */ +			break; +		case SIR: +		case SDR: +		case XSDR: + +#ifdef DEBUG +			switch (cOpcode) { +			case SIR: +				puts("SIR "); +				break; +			case SDR: +			case XSDR: +				if (g_usDataType & LHEAP_IN) { +					puts("LSDR "); +				} else { +					puts("SDR "); +				} +				break; +			} +#endif /* DEBUG */ +			/* +			* +			* Shift in data into the device. +			* +			*/ + +			cRetCode = ispVMShift(cOpcode); +			if (cRetCode != 0) { +				return cRetCode; +			} +			break; +		case WAIT: + +			/* +			* +			* Observe delay. +			* +			*/ + +			/* 09/11/07 NN Type cast mismatch variables */ +			usDelay = (unsigned short) ispVMDataSize(); +			ispVMDelay(usDelay); + +#ifdef DEBUG +			if (usDelay & 0x8000) { + +				/* +				 * Since MSB is set, the delay time must be +				 * decoded to millisecond. The SVF2VME encodes +				 * the MSB to represent millisecond. +				 */ + +				usDelay &= ~0x8000; +				if (g_usDataType & LHEAP_IN) { +					printf("%.2E SEC;\n", +						(float) usDelay / 1000); +				} else { +					printf("RUNTEST %.2E SEC;\n", +						(float) usDelay / 1000); +				} +			} else { +				/* +				 * Since MSB is not set, the delay time +				 * is given as microseconds. +				 */ + +				if (g_usDataType & LHEAP_IN) { +					printf("%.2E SEC;\n", +						(float) usDelay / 1000000); +				} else { +					printf("RUNTEST %.2E SEC;\n", +						(float) usDelay / 1000000); +				} +			} +#endif /* DEBUG */ +			break; +		case TCK: + +			/* +			 * Issue clock toggles. +			*/ + +			/* 09/11/07 NN Type cast mismatch variables */ +			usToggle = (unsigned short) ispVMDataSize(); +			ispVMClocks(usToggle); + +#ifdef DEBUG +			printf("RUNTEST %d TCK;\n", usToggle); +#endif /* DEBUG */ +			break; +		case ENDDR: + +			/* +			* +			* Set the ENDDR. +			* +			*/ + +			g_ucEndDR = GetByte(); + +#ifdef DEBUG +			printf("ENDDR %s;\n", GetState(g_ucEndDR)); +#endif /* DEBUG */ +			break; +		case ENDIR: + +			/* +			* +			* Set the ENDIR. +			* +			*/ + +			g_ucEndIR = GetByte(); + +#ifdef DEBUG +			printf("ENDIR %s;\n", GetState(g_ucEndIR)); +#endif /* DEBUG */ +			break; +		case HIR: +		case TIR: +		case HDR: +		case TDR: + +#ifdef DEBUG +			switch (cOpcode) { +			case HIR: +				puts("HIR "); +				break; +			case TIR: +				puts("TIR "); +				break; +			case HDR: +				puts("HDR "); +				break; +			case TDR: +				puts("TDR "); +				break; +			} +#endif /* DEBUG */ +			/* +			 * Set the header/trailer of the device in order +			 * to bypass +			 * successfully. +			 */ + +			cRetCode = ispVMAmble(cOpcode); +			if (cRetCode != 0) { +				return cRetCode; +			} + +#ifdef DEBUG +			puts(";\n"); +#endif /* DEBUG */ +			break; +		case MEM: + +			/* +			 * The maximum RAM required to support +			 * processing one row of the VME file. +			 */ + +			/* 09/11/07 NN Type cast mismatch variables */ +			g_usMaxSize = (unsigned short) ispVMDataSize(); + +#ifdef DEBUG +			printf("// MEMSIZE %d\n", g_usMaxSize); +#endif /* DEBUG */ +			break; +		case VENDOR: + +			/* +			* +			* Set the VENDOR type. +			* +			*/ + +			cOpcode = GetByte(); +			switch (cOpcode) { +			case LATTICE: +#ifdef DEBUG +				puts("// VENDOR LATTICE\n"); +#endif /* DEBUG */ +				g_cVendor = LATTICE; +				break; +			case ALTERA: +#ifdef DEBUG +				puts("// VENDOR ALTERA\n"); +#endif /* DEBUG */ +				g_cVendor = ALTERA; +				break; +			case XILINX: +#ifdef DEBUG +				puts("// VENDOR XILINX\n"); +#endif /* DEBUG */ +				g_cVendor = XILINX; +				break; +			default: +				break; +			} +			break; +		case SETFLOW: + +			/* +			 * Set the flow control. Flow control determines +			 * the personality of the embedded engine. +			 */ + +			/* 09/11/07 NN Type cast mismatch variables */ +			g_usFlowControl |= (unsigned short) ispVMDataSize(); +			break; +		case RESETFLOW: + +			/* +			* +			* Unset the flow control. +			* +			*/ + +			/* 09/11/07 NN Type cast mismatch variables */ +			g_usFlowControl &= (unsigned short) ~(ispVMDataSize()); +			break; +		case HEAP: + +			/* +			* +			* Allocate heap size to store loops. +			* +			*/ + +			cRetCode = GetByte(); +			if (cRetCode != SECUREHEAP) { +				return VME_INVALID_FILE; +			} +			/* 09/11/07 NN Type cast mismatch variables */ +			g_iHEAPSize = (unsigned short) ispVMDataSize(); + +			/* +			 * Store the maximum size of the HEAP buffer. +			 * Used to convert VME to HEX. +			 */ + +			if (g_iHEAPSize > g_usHeapSize) { +				g_usHeapSize = g_iHEAPSize; +			} + +			ispVMMemManager(HEAP, (unsigned short) g_iHEAPSize); +			break; +		case REPEAT: + +			/* +			* +			* Execute loops. +			* +			*/ + +			g_usRepeatLoops = 0; + +			/* 09/11/07 NN Type cast mismatch variables */ +			iRepeatSize = (unsigned short) ispVMDataSize(); + +			cRetCode = ispVMLoop((unsigned short) iRepeatSize); +			if (cRetCode != 0) { +				return cRetCode; +			} +			break; +		case ENDLOOP: + +			/* +			* +			* Exit point from processing loops. +			* +			*/ + +			return cRetCode; +		case ENDVME: + +			/* +			 * The only valid exit point that indicates +			 * end of programming. +			 */ + +			return cRetCode; +		case SHR: + +			/* +			* +			* Right-shift address. +			* +			*/ + +			g_usFlowControl |= SHIFTRIGHT; + +			/* 09/11/07 NN Type cast mismatch variables */ +			g_usShiftValue = (unsigned short) (g_usRepeatLoops * +				(unsigned short)GetByte()); +			break; +		case SHL: + +			/* +			 * Left-shift address. +			 */ + +			g_usFlowControl |= SHIFTLEFT; + +			/* 09/11/07 NN Type cast mismatch variables */ +			g_usShiftValue = (unsigned short) (g_usRepeatLoops * +				(unsigned short)GetByte()); +			break; +		case FREQUENCY: + +			/* +			* +			* Set the frequency. +			* +			*/ + +			/* 09/11/07 NN Type cast mismatch variables */ +			g_iFrequency = (int) (ispVMDataSize() / 1000); +			if (g_iFrequency == 1) +				g_iFrequency = 1000; + +#ifdef DEBUG +			printf("FREQUENCY %.2E HZ;\n", +				(float) g_iFrequency * 1000); +#endif /* DEBUG */ +			break; +		case LCOUNT: + +			/* +			* +			* Process LCOUNT command. +			* +			*/ + +			cRetCode = ispVMLCOUNT((unsigned short)ispVMDataSize()); +			if (cRetCode != 0) { +				return cRetCode; +			} +			break; +		case VUES: + +			/* +			* +			* Set the flow control to verify USERCODE. +			* +			*/ + +			g_usFlowControl |= VERIFYUES; +			break; +		case COMMENT: + +			/* +			* +			* Display comment. +			* +			*/ + +			ispVMComment((unsigned short) ispVMDataSize()); +			break; +		case LVDS: + +			/* +			* +			* Process LVDS command. +			* +			*/ + +			ispVMProcessLVDS((unsigned short) ispVMDataSize()); +			break; +		case HEADER: + +			/* +			* +			* Discard header. +			* +			*/ + +			ispVMHeader((unsigned short) ispVMDataSize()); +			break; +		/* 03/14/06 Support Toggle ispENABLE signal*/ +		case ispEN: +			ucState = GetByte(); +			if ((ucState == ON) || (ucState == 0x01)) +				writePort(g_ucPinENABLE, 0x01); +			else +				writePort(g_ucPinENABLE, 0x00); +			ispVMDelay(1); +			break; +		/* 05/24/06 support Toggle TRST pin*/ +		case TRST: +			ucState = GetByte(); +			if (ucState == 0x01) +				writePort(g_ucPinTRST, 0x01); +			else +				writePort(g_ucPinTRST, 0x00); +			ispVMDelay(1); +			break; +		default: + +			/* +			* +			* Invalid opcode encountered. +			* +			*/ + +#ifdef DEBUG +			printf("\nINVALID OPCODE: 0x%.2X\n", cOpcode); +#endif /* DEBUG */ + +			return VME_INVALID_FILE; +		} +	} + +	/* +	* +	* Invalid exit point. Processing the token 'ENDVME' is the only +	* valid way to exit the embedded engine. +	* +	*/ + +	return VME_INVALID_FILE; +} + +/* + * + * ispVMDataCode + * + * Processes the TDI/TDO/MASK/DMASK etc of an SIR/SDR command. + * + */ + +signed char ispVMDataCode() +{ +	/* 09/11/07 NN added local variables initialization */ +	signed char cDataByte    = 0; +	signed char siDataSource = 0;  /*source of data from file by default*/ + +	if (g_usDataType & HEAP_IN) { +		siDataSource = 1;  /*the source of data from memory*/ +	} + +	/* +	* +	* Clear the data type register. +	* +	**/ + +	g_usDataType &= ~(MASK_DATA + TDI_DATA + +		TDO_DATA + DMASK_DATA + CMASK_DATA); + +	/* +	 * Iterate through SIR/SDR command and look for TDI, +	 * TDO, MASK, etc. +	 */ + +	while ((cDataByte = GetByte()) >= 0) { +			ispVMMemManager(cDataByte, g_usMaxSize); +			switch (cDataByte) { +			case TDI: + +				/* +				 * Store the maximum size of the TDI buffer. +				 * Used to convert VME to HEX. +				 */ + +				if (g_usiDataSize > g_usTDISize) { +					g_usTDISize = g_usiDataSize; +				} +				/* +				 * Updated data type register to indicate that +				 * TDI data is currently being used. Process the +				 * data in the VME file into the TDI buffer. +				 */ + +				g_usDataType |= TDI_DATA; +				ispVMData(g_pucInData); +				break; +			case XTDO: + +				/* +				 * Store the maximum size of the TDO buffer. +				 * Used to convert VME to HEX. +				 */ + +				if (g_usiDataSize > g_usTDOSize) { +					g_usTDOSize = g_usiDataSize; +				} + +				/* +				 * Updated data type register to indicate that +				 * TDO data is currently being used. +				 */ + +				g_usDataType |= TDO_DATA; +				break; +			case TDO: + +				/* +				 * Store the maximum size of the TDO buffer. +				 * Used to convert VME to HEX. +				 */ + +				if (g_usiDataSize > g_usTDOSize) { +					g_usTDOSize = g_usiDataSize; +				} + +				/* +				 * Updated data type register to indicate +				 * that TDO data is currently being used. +				 * Process the data in the VME file into the +				 * TDO buffer. +				 */ + +				g_usDataType |= TDO_DATA; +				ispVMData(g_pucOutData); +				break; +			case MASK: + +				/* +				 * Store the maximum size of the MASK buffer. +				 * Used to convert VME to HEX. +				 */ + +				if (g_usiDataSize > g_usMASKSize) { +					g_usMASKSize = g_usiDataSize; +				} + +				/* +				 * Updated data type register to indicate that +				 * MASK data is currently being used. Process +				 * the data in the VME file into the MASK buffer +				 */ + +				g_usDataType |= MASK_DATA; +				ispVMData(g_pucOutMaskData); +				break; +			case DMASK: + +				/* +				 * Store the maximum size of the DMASK buffer. +				 * Used to convert VME to HEX. +				 */ + +				if (g_usiDataSize > g_usDMASKSize) { +					g_usDMASKSize = g_usiDataSize; +				} + +				/* +				 * Updated data type register to indicate that +				 * DMASK data is currently being used. Process +				 * the data in the VME file into the DMASK +				 * buffer. +				 */ + +				g_usDataType |= DMASK_DATA; +				ispVMData(g_pucOutDMaskData); +				break; +			case CMASK: + +				/* +				 * Updated data type register to indicate that +				 * MASK data is currently being used. Process +				 * the data in the VME file into the MASK buffer +				 */ + +				g_usDataType |= CMASK_DATA; +				ispVMData(g_pucOutMaskData); +				break; +			case CONTINUE: +				return 0; +			default: +				/* +				 * Encountered invalid opcode. +				 */ +				return VME_INVALID_FILE; +			} + +			switch (cDataByte) { +			case TDI: + +				/* +				 * Left bit shift. Used when performing +				 * algorithm looping. +				 */ + +				if (g_usFlowControl & SHIFTLEFT) { +					ispVMBitShift(SHL, g_usShiftValue); +					g_usFlowControl &= ~SHIFTLEFT; +				} + +				/* +				 * Right bit shift. Used when performing +				 * algorithm looping. +				 */ + +				if (g_usFlowControl & SHIFTRIGHT) { +					ispVMBitShift(SHR, g_usShiftValue); +					g_usFlowControl &= ~SHIFTRIGHT; +				} +			default: +				break; +			} + +			if (siDataSource) { +				g_usDataType |= HEAP_IN; /*restore from memory*/ +			} +	} + +	if (siDataSource) {  /*fetch data from heap memory upon return*/ +		g_usDataType |= HEAP_IN; +	} + +	if (cDataByte < 0) { + +		/* +		 * Encountered invalid opcode. +		 */ + +		return VME_INVALID_FILE; +	} else { +		return 0; +	} +} + +/* + * + * ispVMData + * Extract one row of data operand from the current data type opcode. Perform + * the decompression if necessary. Extra RAM is not required for the + * decompression process. The decompression scheme employed in this module + * is on row by row basis. The format of the data stream: + * [compression code][compressed data stream] + * 0x00    --No compression + * 0x01    --Compress by 0x00. + *           Example: + *           Original stream:   0x000000000000000000000001 + *           Compressed stream: 0x01000901 + *           Detail:            0x01 is the code, 0x00 is the key, + *                              0x09 is the count of 0x00 bytes, + *                              0x01 is the uncompressed byte. + * 0x02    --Compress by 0xFF. + *           Example: + *           Original stream:   0xFFFFFFFFFFFFFFFFFFFFFF01 + *           Compressed stream: 0x02FF0901 + *           Detail:            0x02 is the code, 0xFF is the key, + *                              0x09 is the count of 0xFF bytes, + *                              0x01 is the uncompressed byte. + * 0x03 + * : : + * 0xFE   -- Compress by nibble blocks. + *           Example: + *           Original stream:   0x84210842108421084210 + *           Compressed stream: 0x0584210 + *           Detail:            0x05 is the code, means 5 nibbles block. + *                              0x84210 is the 5 nibble blocks. + *                              The whole row is 80 bits given by g_usiDataSize. + *                              The number of times the block repeat itself + *                              is found by g_usiDataSize/(4*0x05) which is 4. + * 0xFF   -- Compress by the most frequently happen byte. + *           Example: + *           Original stream:   0x04020401030904040404 + *           Compressed stream: 0xFF04(0,1,0x02,0,1,0x01,1,0x03,1,0x09,0,0,0) + *                          or: 0xFF044090181C240 + *           Detail:            0xFF is the code, 0x04 is the key. + *                              a bit of 0 represent the key shall be put into + *                              the current bit position and a bit of 1 + *                              represent copying the next of 8 bits of data + *                              in. + * + */ + +void ispVMData(unsigned char *ByteData) +{ +	/* 09/11/07 NN added local variables initialization */ +	unsigned short size               = 0; +	unsigned short i, j, m, getData   = 0; +	unsigned char cDataByte           = 0; +	unsigned char compress            = 0; +	unsigned short FFcount            = 0; +	unsigned char compr_char          = 0xFF; +	unsigned short index              = 0; +	signed char compression           = 0; + +	/*convert number in bits to bytes*/ +	if (g_usiDataSize % 8 > 0) { +		/* 09/11/07 NN Type cast mismatch variables */ +		size = (unsigned short)(g_usiDataSize / 8 + 1); +	} else { +		/* 09/11/07 NN Type cast mismatch variables */ +		size = (unsigned short)(g_usiDataSize / 8); +	} + +	/* +	 * If there is compression, then check if compress by key +	 * of 0x00 or 0xFF or by other keys or by nibble blocks +	 */ + +	if (g_usDataType & COMPRESS) { +		compression = 1; +		compress = GetByte(); +		if ((compress  == VAR) && (g_usDataType & HEAP_IN)) { +			getData = 1; +			g_usDataType &= ~(HEAP_IN); +			compress = GetByte(); +		} + +		switch (compress) { +		case 0x00: +			/* No compression */ +			compression = 0; +			break; +		case 0x01: +			/* Compress by byte 0x00 */ +			compr_char = 0x00; +			break; +		case 0x02: +			/* Compress by byte 0xFF */ +			compr_char = 0xFF; +			break; +		case 0xFF: +			/* Huffman encoding */ +			compr_char = GetByte(); +			i = 8; +			for (index = 0; index < size; index++) { +				ByteData[index] = 0x00; +				if (i > 7) { +					cDataByte = GetByte(); +					i = 0; +				} +				if ((cDataByte << i++) & 0x80) +					m = 8; +				else { +					ByteData[index] = compr_char; +					m = 0; +				} + +				for (j = 0; j < m; j++) { +					if (i > 7) { +						cDataByte = GetByte(); +						i = 0; +					} +					ByteData[index] |= +					((cDataByte << i++) & 0x80) >> j; +				} +			} +			size = 0; +			break; +		default: +			for (index = 0; index < size; index++) +				ByteData[index] = 0x00; +			for (index = 0; index < compress; index++) { +				if (index % 2 == 0) +					cDataByte = GetByte(); +				for (i = 0; i < size * 2 / compress; i++) { +					j = (unsigned short)(index + +						(i * (unsigned short)compress)); +					/*clear the nibble to zero first*/ +					if (j%2) { +						if (index % 2) +							ByteData[j/2] |= +								cDataByte & 0xF; +						else +							ByteData[j/2] |= +								cDataByte >> 4; +					} else { +						if (index % 2) +							ByteData[j/2] |= +								cDataByte << 4; +						else +							ByteData[j/2] |= +							cDataByte & 0xF0; +					} +				} +			} +			size = 0; +			break; +		} +	} + +	FFcount = 0; + +	/* Decompress by byte 0x00 or 0xFF */ +	for (index = 0; index < size; index++) { +		if (FFcount <= 0) { +			cDataByte = GetByte(); +			if ((cDataByte == VAR) && (g_usDataType&HEAP_IN) && +				!getData && !(g_usDataType&COMPRESS)) { +				getData = 1; +				g_usDataType &= ~(HEAP_IN); +				cDataByte = GetByte(); +			} +			ByteData[index] = cDataByte; +			if ((compression) && (cDataByte == compr_char)) +				/* 09/11/07 NN Type cast mismatch variables */ +				FFcount = (unsigned short) ispVMDataSize(); +				/*The number of 0xFF or 0x00 bytes*/ +		} else { +			FFcount--; /*Use up the 0xFF chain first*/ +			ByteData[index] = compr_char; +		} +	} + +	if (getData) { +		g_usDataType |= HEAP_IN; +		getData = 0; +	} +} + +/* + * + * ispVMShift + * + * Processes the SDR/XSDR/SIR commands. + * + */ + +signed char ispVMShift(signed char a_cCode) +{ +	/* 09/11/07 NN added local variables initialization */ +	unsigned short iDataIndex  = 0; +	unsigned short iReadLoop   = 0; +	signed char cRetCode       = 0; + +	cRetCode = 0; +	/* 09/11/07 NN Type cast mismatch variables */ +	g_usiDataSize = (unsigned short) ispVMDataSize(); + +	/*clear the flags first*/ +	g_usDataType &= ~(SIR_DATA + EXPRESS + SDR_DATA); +	switch (a_cCode) { +	case SIR: +		g_usDataType |= SIR_DATA; +		/* +		 * 1/15/04 If performing cascading, then go directly to SHIFTIR. +		 *  Else, go to IRPAUSE before going to SHIFTIR +		 */ +		if (g_usFlowControl & CASCADE) { +			ispVMStateMachine(SHIFTIR); +		} else { +			ispVMStateMachine(IRPAUSE); +			ispVMStateMachine(SHIFTIR); +			if (g_usHeadIR > 0) { +				ispVMBypass(HIR, g_usHeadIR); +				sclock(); +			} +		} +		break; +	case XSDR: +		g_usDataType |= EXPRESS; /*mark simultaneous in and out*/ +	case SDR: +		g_usDataType |= SDR_DATA; +		/* +		 * 1/15/04 If already in SHIFTDR, then do not move state or +		 * shift in header.  This would imply that the previously +		 * shifted frame was a cascaded frame. +		 */ +		if (g_cCurrentJTAGState != SHIFTDR) { +			/* +			 * 1/15/04 If performing cascading, then go directly +			 * to SHIFTDR.  Else, go to DRPAUSE before going +			 * to SHIFTDR +			 */ +			if (g_usFlowControl & CASCADE) { +				if (g_cCurrentJTAGState == DRPAUSE) { +					ispVMStateMachine(SHIFTDR); +					/* +					 * 1/15/04 If cascade flag has been seat +					 * and the current state is DRPAUSE, +					 * this implies that the first cascaded +					 * frame is about to be shifted in.  The +					 * header must be shifted prior to +					 * shifting the first cascaded frame. +					 */ +					if (g_usHeadDR > 0) { +						ispVMBypass(HDR, g_usHeadDR); +						sclock(); +					} +				} else { +					ispVMStateMachine(SHIFTDR); +				} +			} else { +				ispVMStateMachine(DRPAUSE); +				ispVMStateMachine(SHIFTDR); +				if (g_usHeadDR > 0) { +					ispVMBypass(HDR, g_usHeadDR); +					sclock(); +				} +			} +		} +		break; +	default: +		return VME_INVALID_FILE; +	} + +	cRetCode = ispVMDataCode(); + +	if (cRetCode != 0) { +		return VME_INVALID_FILE; +	} + +#ifdef DEBUG +	printf("%d ", g_usiDataSize); + +	if (g_usDataType & TDI_DATA) { +		puts("TDI "); +		PrintData(g_usiDataSize, g_pucInData); +	} + +	if (g_usDataType & TDO_DATA) { +		puts("\n\t\tTDO "); +		PrintData(g_usiDataSize, g_pucOutData); +	} + +	if (g_usDataType & MASK_DATA) { +		puts("\n\t\tMASK "); +		PrintData(g_usiDataSize, g_pucOutMaskData); +	} + +	if (g_usDataType & DMASK_DATA) { +		puts("\n\t\tDMASK "); +		PrintData(g_usiDataSize, g_pucOutDMaskData); +	} + +	puts(";\n"); +#endif /* DEBUG */ + +	if (g_usDataType & TDO_DATA || g_usDataType & DMASK_DATA) { +		if (g_usDataType & DMASK_DATA) { +			cRetCode = ispVMReadandSave(g_usiDataSize); +			if (!cRetCode) { +				if (g_usTailDR > 0) { +					sclock(); +					ispVMBypass(TDR, g_usTailDR); +				} +				ispVMStateMachine(DRPAUSE); +				ispVMStateMachine(SHIFTDR); +				if (g_usHeadDR > 0) { +					ispVMBypass(HDR, g_usHeadDR); +					sclock(); +				} +				for (iDataIndex = 0; +					iDataIndex < g_usiDataSize / 8 + 1; +					iDataIndex++) +					g_pucInData[iDataIndex] = +						g_pucOutData[iDataIndex]; +				g_usDataType &= ~(TDO_DATA + DMASK_DATA); +				cRetCode = ispVMSend(g_usiDataSize); +			} +		} else { +			cRetCode = ispVMRead(g_usiDataSize); +			if (cRetCode == -1 && g_cVendor == XILINX) { +				for (iReadLoop = 0; iReadLoop < 30; +					iReadLoop++) { +					cRetCode = ispVMRead(g_usiDataSize); +					if (!cRetCode) { +						break; +					} else { +						/* Always DRPAUSE */ +						ispVMStateMachine(DRPAUSE); +						/* +						 * Bypass other devices +						 * when appropriate +						 */ +						ispVMBypass(TDR, g_usTailDR); +						ispVMStateMachine(g_ucEndDR); +						ispVMStateMachine(IDLE); +						ispVMDelay(1000); +					} +				} +			} +		} +	} else { /*TDI only*/ +		cRetCode = ispVMSend(g_usiDataSize); +	} + +	/*transfer the input data to the output buffer for the next verify*/ +	if ((g_usDataType & EXPRESS) || (a_cCode == SDR)) { +		if (g_pucOutData) { +			for (iDataIndex = 0; iDataIndex < g_usiDataSize / 8 + 1; +				iDataIndex++) +				g_pucOutData[iDataIndex] = +					g_pucInData[iDataIndex]; +		} +	} + +	switch (a_cCode) { +	case SIR: +		/* 1/15/04 If not performing cascading, then shift ENDIR */ +		if (!(g_usFlowControl & CASCADE)) { +			if (g_usTailIR > 0) { +				sclock(); +				ispVMBypass(TIR, g_usTailIR); +			} +			ispVMStateMachine(g_ucEndIR); +		} +		break; +	case XSDR: +	case SDR: +		/* 1/15/04 If not performing cascading, then shift ENDDR */ +		if (!(g_usFlowControl & CASCADE)) { +			if (g_usTailDR > 0) { +				sclock(); +				ispVMBypass(TDR, g_usTailDR); +			} +			ispVMStateMachine(g_ucEndDR); +		} +		break; +	default: +		break; +	} + +	return cRetCode; +} + +/* + * + * ispVMAmble + * + * This routine is to extract Header and Trailer parameter for SIR and + * SDR operations. + * + * The Header and Trailer parameter are the pre-amble and post-amble bit + * stream need to be shifted into TDI or out of TDO of the devices. Mostly + * is for the purpose of bypassing the leading or trailing devices. ispVM + * supports only shifting data into TDI to bypass the devices. + * + * For a single device, the header and trailer parameters are all set to 0 + * as default by ispVM. If it is for multiple devices, the header and trailer + * value will change as specified by the VME file. + * + */ + +signed char ispVMAmble(signed char Code) +{ +	signed char compress = 0; +	/* 09/11/07 NN Type cast mismatch variables */ +	g_usiDataSize = (unsigned short)ispVMDataSize(); + +#ifdef DEBUG +	printf("%d", g_usiDataSize); +#endif /* DEBUG */ + +	if (g_usiDataSize) { + +		/* +		 * Discard the TDI byte and set the compression bit in the data +		 * type register to false if compression is set because TDI data +		 * after HIR/HDR/TIR/TDR is not compressed. +		 */ + +		GetByte(); +		if (g_usDataType & COMPRESS) { +			g_usDataType &= ~(COMPRESS); +			compress = 1; +		} +	} + +	switch (Code) { +	case HIR: + +		/* +		 * Store the maximum size of the HIR buffer. +		 * Used to convert VME to HEX. +		 */ + +		if (g_usiDataSize > g_usHIRSize) { +			g_usHIRSize = g_usiDataSize; +		} + +		/* +		 * Assign the HIR value and allocate memory. +		 */ + +		g_usHeadIR = g_usiDataSize; +		if (g_usHeadIR) { +			ispVMMemManager(HIR, g_usHeadIR); +			ispVMData(g_pucHIRData); + +#ifdef DEBUG +			puts(" TDI "); +			PrintData(g_usHeadIR, g_pucHIRData); +#endif /* DEBUG */ +		} +		break; +	case TIR: + +		/* +		 * Store the maximum size of the TIR buffer. +		 * Used to convert VME to HEX. +		 */ + +		if (g_usiDataSize > g_usTIRSize) { +			g_usTIRSize = g_usiDataSize; +		} + +		/* +		 * Assign the TIR value and allocate memory. +		 */ + +		g_usTailIR = g_usiDataSize; +		if (g_usTailIR) { +			ispVMMemManager(TIR, g_usTailIR); +			ispVMData(g_pucTIRData); + +#ifdef DEBUG +			puts(" TDI "); +			PrintData(g_usTailIR, g_pucTIRData); +#endif /* DEBUG */ +		} +		break; +	case HDR: + +		/* +		 * Store the maximum size of the HDR buffer. +		 * Used to convert VME to HEX. +		 */ + +		if (g_usiDataSize > g_usHDRSize) { +			g_usHDRSize = g_usiDataSize; +		} + +		/* +		 * Assign the HDR value and allocate memory. +		 * +		 */ + +		g_usHeadDR = g_usiDataSize; +		if (g_usHeadDR) { +			ispVMMemManager(HDR, g_usHeadDR); +			ispVMData(g_pucHDRData); + +#ifdef DEBUG +			puts(" TDI "); +			PrintData(g_usHeadDR, g_pucHDRData); +#endif /* DEBUG */ +		} +		break; +	case TDR: + +		/* +		 * Store the maximum size of the TDR buffer. +		 * Used to convert VME to HEX. +		 */ + +		if (g_usiDataSize > g_usTDRSize) { +			g_usTDRSize = g_usiDataSize; +		} + +		/* +		 * Assign the TDR value and allocate memory. +		 * +		 */ + +		g_usTailDR = g_usiDataSize; +		if (g_usTailDR) { +			ispVMMemManager(TDR, g_usTailDR); +			ispVMData(g_pucTDRData); + +#ifdef DEBUG +			puts(" TDI "); +			PrintData(g_usTailDR, g_pucTDRData); +#endif /* DEBUG */ +		} +		break; +	default: +		break; +	} + +	/* +	* +	* Re-enable compression if it was previously set. +	* +	**/ + +	if (compress) { +		g_usDataType |= COMPRESS; +	} + +	if (g_usiDataSize) { +		Code = GetByte(); +		if (Code == CONTINUE) { +			return 0; +		} else { + +			/* +			 * Encountered invalid opcode. +			 */ + +			return VME_INVALID_FILE; +		} +	} + +	return 0; +} + +/* + * + * ispVMLoop + * + * Perform the function call upon by the REPEAT opcode. + * Memory is to be allocated to store the entire loop from REPEAT to ENDLOOP. + * After the loop is stored then execution begin. The REPEATLOOP flag is set + * on the g_usFlowControl register to indicate the repeat loop is in session + * and therefore fetch opcode from the memory instead of from the file. + * + */ + +signed char ispVMLoop(unsigned short a_usLoopCount) +{ +	/* 09/11/07 NN added local variables initialization */ +	signed char cRetCode      = 0; +	unsigned short iHeapIndex = 0; +	unsigned short iLoopIndex = 0; + +	g_usShiftValue = 0; +	for (iHeapIndex = 0; iHeapIndex < g_iHEAPSize; iHeapIndex++) { +		g_pucHeapMemory[iHeapIndex] = GetByte(); +	} + +	if (g_pucHeapMemory[iHeapIndex - 1] != ENDLOOP) { +		return VME_INVALID_FILE; +	} + +	g_usFlowControl |= REPEATLOOP; +	g_usDataType |= HEAP_IN; + +	for (iLoopIndex = 0; iLoopIndex < a_usLoopCount; iLoopIndex++) { +		g_iHeapCounter = 0; +		cRetCode = ispVMCode(); +		g_usRepeatLoops++; +		if (cRetCode < 0) { +			break; +		} +	} + +	g_usDataType &= ~(HEAP_IN); +	g_usFlowControl &= ~(REPEATLOOP); +	return cRetCode; +} + +/* + * + * ispVMBitShift + * + * Shift the TDI stream left or right by the number of bits. The data in + * *g_pucInData is of the VME format, so the actual shifting is the reverse of + * IEEE 1532 or SVF format. + * + */ + +signed char ispVMBitShift(signed char mode, unsigned short bits) +{ +	/* 09/11/07 NN added local variables initialization */ +	unsigned short i       = 0; +	unsigned short size    = 0; +	unsigned short tmpbits = 0; + +	if (g_usiDataSize % 8 > 0) { +		/* 09/11/07 NN Type cast mismatch variables */ +		size = (unsigned short)(g_usiDataSize / 8 + 1); +	} else { +		/* 09/11/07 NN Type cast mismatch variables */ +		size = (unsigned short)(g_usiDataSize / 8); +	} + +	switch (mode) { +	case SHR: +		for (i = 0; i < size; i++) { +			if (g_pucInData[i] != 0) { +				tmpbits = bits; +				while (tmpbits > 0) { +					g_pucInData[i] <<= 1; +					if (g_pucInData[i] == 0) { +						i--; +						g_pucInData[i] = 1; +					} +					tmpbits--; +				} +			} +		} +		break; +	case SHL: +		for (i = 0; i < size; i++) { +			if (g_pucInData[i] != 0) { +				tmpbits = bits; +				while (tmpbits > 0) { +					g_pucInData[i] >>= 1; +					if (g_pucInData[i] == 0) { +						i--; +						g_pucInData[i] = 8; +					} +					tmpbits--; +				} +			} +		} +		break; +	default: +		return VME_INVALID_FILE; +	} + +	return 0; +} + +/* + * + * ispVMComment + * + * Displays the SVF comments. + * + */ + +void ispVMComment(unsigned short a_usCommentSize) +{ +	char cCurByte = 0; +	for (; a_usCommentSize > 0; a_usCommentSize--) { +		/* +		* +		* Print character to the terminal. +		* +		**/ +		cCurByte = GetByte(); +		vme_out_char(cCurByte); +	} +	cCurByte = '\n'; +	vme_out_char(cCurByte); +} + +/* + * + * ispVMHeader + * + * Iterate the length of the header and discard it. + * + */ + +void ispVMHeader(unsigned short a_usHeaderSize) +{ +	for (; a_usHeaderSize > 0; a_usHeaderSize--) { +		GetByte(); +	} +} + +/* + * + * ispVMCalculateCRC32 + * + * Calculate the 32-bit CRC. + * + */ + +void ispVMCalculateCRC32(unsigned char a_ucData) +{ +	/* 09/11/07 NN added local variables initialization */ +	unsigned char ucIndex          = 0; +	unsigned char ucFlipData       = 0; +	unsigned short usCRCTableEntry = 0; +	unsigned int crc_table[16] = { +		0x0000, 0xCC01, 0xD801, +		0x1400, 0xF001, 0x3C00, +		0x2800, 0xE401, 0xA001, +		0x6C00, 0x7800, 0xB401, +		0x5000, 0x9C01, 0x8801, +		0x4400 +	}; + +	for (ucIndex = 0; ucIndex < 8; ucIndex++) { +		ucFlipData <<= 1; +		if (a_ucData & 0x01) { +			ucFlipData |= 0x01; +		} +		a_ucData >>= 1; +	} + +	/* 09/11/07 NN Type cast mismatch variables */ +	usCRCTableEntry = (unsigned short)(crc_table[g_usCalculatedCRC & 0xF]); +	g_usCalculatedCRC = (unsigned short)((g_usCalculatedCRC >> 4) & 0x0FFF); +	g_usCalculatedCRC = (unsigned short)(g_usCalculatedCRC ^ +			usCRCTableEntry ^ crc_table[ucFlipData & 0xF]); +	usCRCTableEntry = (unsigned short)(crc_table[g_usCalculatedCRC & 0xF]); +	g_usCalculatedCRC = (unsigned short)((g_usCalculatedCRC >> 4) & 0x0FFF); +	g_usCalculatedCRC = (unsigned short)(g_usCalculatedCRC ^ +		usCRCTableEntry ^ crc_table[(ucFlipData >> 4) & 0xF]); +} + +/* + * + * ispVMLCOUNT + * + * Process the intelligent programming loops. + * + */ + +signed char ispVMLCOUNT(unsigned short a_usCountSize) +{ +	unsigned short usContinue	  = 1; +	unsigned short usIntelBufferIndex = 0; +	unsigned short usCountIndex       = 0; +	signed char cRetCode              = 0; +	signed char cRepeatHeap           = 0; +	signed char cOpcode               = 0; +	unsigned char ucState             = 0; +	unsigned short usDelay            = 0; +	unsigned short usToggle           = 0; +	unsigned char usByte              = 0; + +	g_usIntelBufferSize = (unsigned short)ispVMDataSize(); + +	/* +	 * Allocate memory for intel buffer. +	 * +	 */ + +	ispVMMemManager(LHEAP, g_usIntelBufferSize); + +	/* +	 * Store the maximum size of the intelligent buffer. +	 * Used to convert VME to HEX. +	 */ + +	if (g_usIntelBufferSize > g_usLCOUNTSize) { +		g_usLCOUNTSize = g_usIntelBufferSize; +	} + +	/* +	 * Copy intel data to the buffer. +	 */ + +	for (usIntelBufferIndex = 0; usIntelBufferIndex < g_usIntelBufferSize; +		usIntelBufferIndex++) { +		g_pucIntelBuffer[usIntelBufferIndex] = GetByte(); +	} + +	/* +	 * Set the data type register to get data from the intelligent +	 * data buffer. +	 */ + +	g_usDataType |= LHEAP_IN; + +	/* +	* +	* If the HEAP_IN flag is set, temporarily unset the flag so data will be +	* retrieved from the status buffer. +	* +	**/ + +	if (g_usDataType & HEAP_IN) { +		g_usDataType &= ~HEAP_IN; +		cRepeatHeap = 1; +	} + +#ifdef DEBUG +	printf("LCOUNT %d;\n", a_usCountSize); +#endif /* DEBUG */ + +	/* +	 * Iterate through the intelligent programming command. +	*/ + +	for (usCountIndex = 0; usCountIndex < a_usCountSize; usCountIndex++) { + +		/* +		* +		* Initialize the intel data index to 0 before each iteration. +		* +		**/ + +		g_usIntelDataIndex = 0; +		cOpcode            = 0; +		ucState            = 0; +		usDelay            = 0; +		usToggle           = 0; +		usByte             = 0; +		usContinue		   = 1; + +		/* +		* +		* Begin looping through all the VME opcodes. +		* +		*/ +		/* +		* 4/1/09 Nguyen replaced the recursive function call codes on +		*        the ispVMLCOUNT function +		* +		*/ +		while (usContinue) { +			cOpcode = GetByte(); +			switch (cOpcode) { +			case HIR: +			case TIR: +			case HDR: +			case TDR: +				/* +				 * Set the header/trailer of the device in order +				 * to bypass successfully. +				 */ + +				ispVMAmble(cOpcode); +			break; +			case STATE: + +				/* +				 * Step the JTAG state machine. +				 */ + +				ucState = GetByte(); +				/* +				 * Step the JTAG state machine to DRCAPTURE +				 * to support Looping. +				 */ + +				if ((g_usDataType & LHEAP_IN) && +					 (ucState == DRPAUSE) && +					 (g_cCurrentJTAGState == ucState)) { +					ispVMStateMachine(DRCAPTURE); +				} +				ispVMStateMachine(ucState); +#ifdef DEBUG +				printf("LDELAY %s ", GetState(ucState)); +#endif /* DEBUG */ +				break; +			case SIR: +#ifdef DEBUG +				printf("SIR "); +#endif /* DEBUG */ +				/* +				 * Shift in data into the device. +				 */ + +				cRetCode = ispVMShift(cOpcode); +				break; +			case SDR: + +#ifdef DEBUG +				printf("LSDR "); +#endif /* DEBUG */ +				/* +				 * Shift in data into the device. +				 */ + +				cRetCode = ispVMShift(cOpcode); +				break; +			case WAIT: + +				/* +				* +				* Observe delay. +				* +				*/ + +				usDelay = (unsigned short)ispVMDataSize(); +				ispVMDelay(usDelay); + +#ifdef DEBUG +				if (usDelay & 0x8000) { + +					/* +					 * Since MSB is set, the delay time must +					 * be decoded to millisecond. The +					 * SVF2VME encodes the MSB to represent +					 * millisecond. +					 */ + +					usDelay &= ~0x8000; +					printf("%.2E SEC;\n", +						(float) usDelay / 1000); +				} else { +					/* +					 * Since MSB is not set, the delay time +					 * is given as microseconds. +					 */ + +					printf("%.2E SEC;\n", +						(float) usDelay / 1000000); +				} +#endif /* DEBUG */ +				break; +			case TCK: + +				/* +				 * Issue clock toggles. +				 */ + +				usToggle = (unsigned short)ispVMDataSize(); +				ispVMClocks(usToggle); + +#ifdef DEBUG +				printf("RUNTEST %d TCK;\n", usToggle); +#endif /* DEBUG */ +				break; +			case ENDLOOP: + +				/* +				 * Exit point from processing loops. +				 */ +				usContinue = 0; +				break; + +			case COMMENT: + +				/* +				 * Display comment. +				 */ + +				ispVMComment((unsigned short) ispVMDataSize()); +				break; +			case ispEN: +				ucState = GetByte(); +				if ((ucState == ON) || (ucState == 0x01)) +					writePort(g_ucPinENABLE, 0x01); +				else +					writePort(g_ucPinENABLE, 0x00); +				ispVMDelay(1); +				break; +			case TRST: +				if (GetByte() == 0x01) +					writePort(g_ucPinTRST, 0x01); +				else +					writePort(g_ucPinTRST, 0x00); +				ispVMDelay(1); +				break; +			default: + +				/* +				 * Invalid opcode encountered. +				 */ + +				debug("\nINVALID OPCODE: 0x%.2X\n", cOpcode); + +				return VME_INVALID_FILE; +			} +		} +		if (cRetCode >= 0) { +			/* +			 * Break if intelligent programming is successful. +			 */ + +			break; +		} + +	} +	/* +	 * If HEAP_IN flag was temporarily disabled, +	 * re-enable it before exiting +	 */ + +	if (cRepeatHeap) { +		g_usDataType |= HEAP_IN; +	} + +	/* +	 * Set the data type register to not get data from the +	 * intelligent data buffer. +	 */ + +	g_usDataType &= ~LHEAP_IN; +	return cRetCode; +} +/* + * + * ispVMClocks + * + * Applies the specified number of pulses to TCK. + * + */ + +void ispVMClocks(unsigned short Clocks) +{ +	unsigned short iClockIndex = 0; +	for (iClockIndex = 0; iClockIndex < Clocks; iClockIndex++) { +		sclock(); +	} +} + +/* + * + * ispVMBypass + * + * This procedure takes care of the HIR, HDR, TIR, TDR for the + * purpose of putting the other devices into Bypass mode. The + * current state is checked to find out if it is at DRPAUSE or + * IRPAUSE. If it is at DRPAUSE, perform bypass register scan. + * If it is at IRPAUSE, scan into instruction registers the bypass + * instruction. + * + */ + +void ispVMBypass(signed char ScanType, unsigned short Bits) +{ +	/* 09/11/07 NN added local variables initialization */ +	unsigned short iIndex       = 0; +	unsigned short iSourceIndex = 0; +	unsigned char cBitState     = 0; +	unsigned char cCurByte      = 0; +	unsigned char *pcSource    = NULL; + +	if (Bits <= 0) { +		return; +	} + +	switch (ScanType) { +	case HIR: +		pcSource = g_pucHIRData; +		break; +	case TIR: +		pcSource = g_pucTIRData; +		break; +	case HDR: +		pcSource = g_pucHDRData; +		break; +	case TDR: +		pcSource = g_pucTDRData; +		break; +	default: +		break; +	} + +	iSourceIndex = 0; +	cBitState = 0; +	for (iIndex = 0; iIndex < Bits - 1; iIndex++) { +		/* Scan instruction or bypass register */ +		if (iIndex % 8 == 0) { +			cCurByte = pcSource[iSourceIndex++]; +		} +		cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80) +			? 0x01 : 0x00); +		writePort(g_ucPinTDI, cBitState); +		sclock(); +	} + +	if (iIndex % 8 == 0)  { +		cCurByte = pcSource[iSourceIndex++]; +	} + +	cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80) +		? 0x01 : 0x00); +	writePort(g_ucPinTDI, cBitState); +} + +/* + * + * ispVMStateMachine + * + * This procedure steps all devices in the daisy chain from a given + * JTAG state to the next desirable state. If the next state is TLR, + * the JTAG state machine is brute forced into TLR by driving TMS + * high and pulse TCK 6 times. + * + */ + +void ispVMStateMachine(signed char cNextJTAGState) +{ +	/* 09/11/07 NN added local variables initialization */ +	signed char cPathIndex  = 0; +	signed char cStateIndex = 0; + +	if ((g_cCurrentJTAGState == cNextJTAGState) && +		(cNextJTAGState != RESET)) { +		return; +	} + +	for (cStateIndex = 0; cStateIndex < 25; cStateIndex++) { +		if ((g_cCurrentJTAGState == +			 g_JTAGTransistions[cStateIndex].CurState) && +			(cNextJTAGState == +				 g_JTAGTransistions[cStateIndex].NextState)) { +			break; +		} +	} + +	g_cCurrentJTAGState = cNextJTAGState; +	for (cPathIndex = 0; +		cPathIndex < g_JTAGTransistions[cStateIndex].Pulses; +		cPathIndex++) { +		if ((g_JTAGTransistions[cStateIndex].Pattern << cPathIndex) +			& 0x80) { +			writePort(g_ucPinTMS, (unsigned char) 0x01); +		} else { +			writePort(g_ucPinTMS, (unsigned char) 0x00); +		} +		sclock(); +	} + +	writePort(g_ucPinTDI, 0x00); +	writePort(g_ucPinTMS, 0x00); +} + +/* + * + * ispVMStart + * + * Enable the port to the device and set the state to RESET (TLR). + * + */ + +void ispVMStart() +{ +#ifdef DEBUG +	printf("// ISPVM EMBEDDED ADDED\n"); +	printf("STATE RESET;\n"); +#endif +	g_usFlowControl	= 0; +	g_usDataType = g_uiChecksumIndex = g_cCurrentJTAGState = 0; +	g_usHeadDR = g_usHeadIR = g_usTailDR = g_usTailIR = 0; +	g_usMaxSize = g_usShiftValue = g_usRepeatLoops = 0; +	g_usTDOSize =  g_usMASKSize = g_usTDISize = 0; +	g_usDMASKSize = g_usLCOUNTSize = g_usHDRSize = 0; +	g_usTDRSize = g_usHIRSize = g_usTIRSize =  g_usHeapSize	= 0; +	g_pLVDSList = NULL; +	g_usLVDSPairCount = 0; +	previous_size = 0; + +	ispVMStateMachine(RESET);    /*step devices to RESET state*/ +} + +/* + * + * ispVMEnd + * + * Set the state of devices to RESET to enable the devices and disable + * the port. + * + */ + +void ispVMEnd() +{ +#ifdef DEBUG +	printf("// ISPVM EMBEDDED ADDED\n"); +	printf("STATE RESET;\n"); +	printf("RUNTEST 1.00E-001 SEC;\n"); +#endif + +	ispVMStateMachine(RESET);   /*step devices to RESET state */ +	ispVMDelay(1000);              /*wake up devices*/ +} + +/* + * + * ispVMSend + * + * Send the TDI data stream to devices. The data stream can be + * instructions or data. + * + */ + +signed char ispVMSend(unsigned short a_usiDataSize) +{ +	/* 09/11/07 NN added local variables initialization */ +	unsigned short iIndex       = 0; +	unsigned short iInDataIndex = 0; +	unsigned char cCurByte      = 0; +	unsigned char cBitState     = 0; + +	for (iIndex = 0; iIndex < a_usiDataSize - 1; iIndex++) { +		if (iIndex % 8 == 0) { +			cCurByte = g_pucInData[iInDataIndex++]; +		} +		cBitState = (unsigned char)(((cCurByte << iIndex % 8) & 0x80) +			? 0x01 : 0x00); +		writePort(g_ucPinTDI, cBitState); +		sclock(); +	} + +	if (iIndex % 8 == 0) { +		/* Take care of the last bit */ +		cCurByte = g_pucInData[iInDataIndex]; +	} + +	cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80) +		? 0x01 : 0x00); + +	writePort(g_ucPinTDI, cBitState); +	if (g_usFlowControl & CASCADE) { +		/*1/15/04 Clock in last bit for the first n-1 cascaded frames */ +		sclock(); +	} + +	return 0; +} + +/* + * + * ispVMRead + * + * Read the data stream from devices and verify. + * + */ + +signed char ispVMRead(unsigned short a_usiDataSize) +{ +	/* 09/11/07 NN added local variables initialization */ +	unsigned short usDataSizeIndex    = 0; +	unsigned short usErrorCount       = 0; +	unsigned short usLastBitIndex     = 0; +	unsigned char cDataByte           = 0; +	unsigned char cMaskByte           = 0; +	unsigned char cInDataByte         = 0; +	unsigned char cCurBit             = 0; +	unsigned char cByteIndex          = 0; +	unsigned short usBufferIndex      = 0; +	unsigned char ucDisplayByte       = 0x00; +	unsigned char ucDisplayFlag       = 0x01; +	char StrChecksum[256]            = {0}; +	unsigned char g_usCalculateChecksum = 0x00; + +	/* 09/11/07 NN Type cast mismatch variables */ +	usLastBitIndex = (unsigned short)(a_usiDataSize - 1); + +#ifndef DEBUG +	/* +	 * If mask is not all zeros, then set the display flag to 0x00, +	 * otherwise it shall be set to 0x01 to indicate that data read +	 * from the device shall be displayed. If DEBUG is defined, +	 * always display data. +	 */ + +	for (usDataSizeIndex = 0; usDataSizeIndex < (a_usiDataSize + 7) / 8; +		usDataSizeIndex++) { +		if (g_usDataType & MASK_DATA) { +			if (g_pucOutMaskData[usDataSizeIndex] != 0x00) { +				ucDisplayFlag = 0x00; +				break; +			} +		} else if (g_usDataType & CMASK_DATA) { +			g_usCalculateChecksum = 0x01; +			ucDisplayFlag = 0x00; +			break; +		} else { +			ucDisplayFlag = 0x00; +			break; +		} +	} +#endif /* DEBUG */ + +	/* +	* +	* Begin shifting data in and out of the device. +	* +	**/ + +	for (usDataSizeIndex = 0; usDataSizeIndex < a_usiDataSize; +		usDataSizeIndex++) { +		if (cByteIndex == 0) { + +			/* +			 * Grab byte from TDO buffer. +			 */ + +			if (g_usDataType & TDO_DATA) { +				cDataByte = g_pucOutData[usBufferIndex]; +			} + +			/* +			 * Grab byte from MASK buffer. +			 */ + +			if (g_usDataType & MASK_DATA) { +				cMaskByte = g_pucOutMaskData[usBufferIndex]; +			} else { +				cMaskByte = 0xFF; +			} + +			/* +			 * Grab byte from CMASK buffer. +			 */ + +			if (g_usDataType & CMASK_DATA) { +				cMaskByte = 0x00; +				g_usCalculateChecksum = 0x01; +			} + +			/* +			 * Grab byte from TDI buffer. +			 */ + +			if (g_usDataType & TDI_DATA) { +				cInDataByte = g_pucInData[usBufferIndex]; +			} + +			usBufferIndex++; +		} + +		cCurBit = readPort(); + +		if (ucDisplayFlag) { +			ucDisplayByte <<= 1; +			ucDisplayByte |= cCurBit; +		} + +		/* +		 * Check if data read from port matches with expected TDO. +		 */ + +		if (g_usDataType & TDO_DATA) { +			/* 08/28/08 NN Added Calculate checksum support. */ +			if (g_usCalculateChecksum) { +				if (cCurBit == 0x01) +					g_usChecksum += +						(1 << (g_uiChecksumIndex % 8)); +				g_uiChecksumIndex++; +			} else { +				if ((((cMaskByte << cByteIndex) & 0x80) +					? 0x01 : 0x00)) { +					if (cCurBit != (unsigned char) +					(((cDataByte << cByteIndex) & 0x80) +						? 0x01 : 0x00)) { +						usErrorCount++; +					} +				} +			} +		} + +		/* +		 * Write TDI data to the port. +		 */ + +		writePort(g_ucPinTDI, +			(unsigned char)(((cInDataByte << cByteIndex) & 0x80) +				? 0x01 : 0x00)); + +		if (usDataSizeIndex < usLastBitIndex) { + +			/* +			 * Clock data out from the data shift register. +			 */ + +			sclock(); +		} else if (g_usFlowControl & CASCADE) { + +			/* +			 * Clock in last bit for the first N - 1 cascaded frames +			 */ + +			sclock(); +		} + +		/* +		 * Increment the byte index. If it exceeds 7, then reset it back +		 * to zero. +		 */ + +		cByteIndex++; +		if (cByteIndex >= 8) { +			if (ucDisplayFlag) { + +			/* +			 * Store displayed data in the TDO buffer. By reusing +			 * the TDO buffer to store displayed data, there is no +			 * need to allocate a buffer simply to hold display +			 * data. This will not cause any false verification +			 * errors because the true TDO byte has already +			 * been consumed. +			 */ + +				g_pucOutData[usBufferIndex - 1] = ucDisplayByte; +				ucDisplayByte = 0; +			} + +			cByteIndex = 0; +		} +		/* 09/12/07 Nguyen changed to display the 1 bit expected data */ +		else if (a_usiDataSize == 1) { +			if (ucDisplayFlag) { + +				/* +				 * Store displayed data in the TDO buffer. +				 * By reusing the TDO buffer to store displayed +				 * data, there is no need to allocate +				 * a buffer simply to hold display data. This +				 * will not cause any false verification errors +				 * because the true TDO byte has already +				 * been consumed. +				 */ + +				/* +				 * Flip ucDisplayByte and store it in cDataByte. +				 */ +				cDataByte = 0x00; +				for (usBufferIndex = 0; usBufferIndex < 8; +					usBufferIndex++) { +					cDataByte <<= 1; +					if (ucDisplayByte & 0x01) { +						cDataByte |= 0x01; +					} +					ucDisplayByte >>= 1; +				} +				g_pucOutData[0] = cDataByte; +				ucDisplayByte = 0; +			} + +			cByteIndex = 0; +		} +	} + +	if (ucDisplayFlag) { + +#ifdef DEBUG +		debug("RECEIVED TDO ("); +#else +		vme_out_string("Display Data: 0x"); +#endif /* DEBUG */ + +		/* 09/11/07 NN Type cast mismatch variables */ +		for (usDataSizeIndex = (unsigned short) +				((a_usiDataSize + 7) / 8); +			usDataSizeIndex > 0 ; usDataSizeIndex--) { +			cMaskByte = g_pucOutData[usDataSizeIndex - 1]; +			cDataByte = 0x00; + +			/* +			 * Flip cMaskByte and store it in cDataByte. +			 */ + +			for (usBufferIndex = 0; usBufferIndex < 8; +				usBufferIndex++) { +				cDataByte <<= 1; +				if (cMaskByte & 0x01) { +					cDataByte |= 0x01; +				} +				cMaskByte >>= 1; +			} +#ifdef DEBUG +			printf("%.2X", cDataByte); +			if ((((a_usiDataSize + 7) / 8) - usDataSizeIndex) +				% 40 == 39) { +				printf("\n\t\t"); +			} +#else +			vme_out_hex(cDataByte); +#endif /* DEBUG */ +		} + +#ifdef DEBUG +		printf(")\n\n"); +#else +		vme_out_string("\n\n"); +#endif /* DEBUG */ +		/* 09/02/08 Nguyen changed to display the data Checksum */ +		if (g_usChecksum != 0) { +			g_usChecksum &= 0xFFFF; +			sprintf(StrChecksum, "Data Checksum: %.4lX\n\n", +				g_usChecksum); +			vme_out_string(StrChecksum); +			g_usChecksum = 0; +		} +	} + +	if (usErrorCount > 0) { +		if (g_usFlowControl & VERIFYUES) { +			vme_out_string( +				"USERCODE verification failed.   " +				"Continue programming......\n\n"); +			g_usFlowControl &= ~(VERIFYUES); +			return 0; +		} else { + +#ifdef DEBUG +			printf("TOTAL ERRORS: %d\n", usErrorCount); +#endif /* DEBUG */ + +			return VME_VERIFICATION_FAILURE; +		} +	} else { +		if (g_usFlowControl & VERIFYUES) { +			vme_out_string("USERCODE verification passed.    " +				"Programming aborted.\n\n"); +			g_usFlowControl &= ~(VERIFYUES); +			return 1; +		} else { +			return 0; +		} +	} +} + +/* + * + * ispVMReadandSave + * + * Support dynamic I/O. + * + */ + +signed char ispVMReadandSave(unsigned short int a_usiDataSize) +{ +	/* 09/11/07 NN added local variables initialization */ +	unsigned short int usDataSizeIndex = 0; +	unsigned short int usLastBitIndex  = 0; +	unsigned short int usBufferIndex   = 0; +	unsigned short int usOutBitIndex   = 0; +	unsigned short int usLVDSIndex     = 0; +	unsigned char cDataByte            = 0; +	unsigned char cDMASKByte           = 0; +	unsigned char cInDataByte          = 0; +	unsigned char cCurBit              = 0; +	unsigned char cByteIndex           = 0; +	signed char cLVDSByteIndex         = 0; + +	/* 09/11/07 NN Type cast mismatch variables */ +	usLastBitIndex = (unsigned short) (a_usiDataSize - 1); + +	/* +	* +	* Iterate through the data bits. +	* +	*/ + +	for (usDataSizeIndex = 0; usDataSizeIndex < a_usiDataSize; +		usDataSizeIndex++) { +		if (cByteIndex == 0) { + +			/* +			 * Grab byte from DMASK buffer. +			 */ + +			if (g_usDataType & DMASK_DATA) { +				cDMASKByte = g_pucOutDMaskData[usBufferIndex]; +			} else { +				cDMASKByte = 0x00; +			} + +			/* +			 * Grab byte from TDI buffer. +			 */ + +			if (g_usDataType & TDI_DATA) { +				cInDataByte = g_pucInData[usBufferIndex]; +			} + +			usBufferIndex++; +		} + +		cCurBit = readPort(); +		cDataByte = (unsigned char)(((cInDataByte << cByteIndex) & 0x80) +			? 0x01 : 0x00); + +		/* +		 * Initialize the byte to be zero. +		 */ + +		if (usOutBitIndex % 8 == 0) { +			g_pucOutData[usOutBitIndex / 8] = 0x00; +		} + +		/* +		 * Use TDI, DMASK, and device TDO to create new TDI (actually +		 * stored in g_pucOutData). +		 */ + +		if ((((cDMASKByte << cByteIndex) & 0x80) ? 0x01 : 0x00)) { + +			if (g_pLVDSList) { +				for (usLVDSIndex = 0; +					 usLVDSIndex < g_usLVDSPairCount; +					usLVDSIndex++) { +					if (g_pLVDSList[usLVDSIndex]. +						usNegativeIndex == +						usDataSizeIndex) { +						g_pLVDSList[usLVDSIndex]. +							ucUpdate = 0x01; +						break; +					} +				} +			} + +			/* +			 * DMASK bit is 1, use TDI. +			 */ + +			g_pucOutData[usOutBitIndex / 8] |= (unsigned char) +				(((cDataByte & 0x1) ? 0x01 : 0x00) << +				(7 - usOutBitIndex % 8)); +		} else { + +			/* +			 * DMASK bit is 0, use device TDO. +			 */ + +			g_pucOutData[usOutBitIndex / 8] |= (unsigned char) +				(((cCurBit & 0x1) ? 0x01 : 0x00) << +				(7 - usOutBitIndex % 8)); +		} + +		/* +		 * Shift in TDI in order to get TDO out. +		 */ + +		usOutBitIndex++; +		writePort(g_ucPinTDI, cDataByte); +		if (usDataSizeIndex < usLastBitIndex) { +			sclock(); +		} + +		/* +		 * Increment the byte index. If it exceeds 7, then reset it back +		 * to zero. +		 */ + +		cByteIndex++; +		if (cByteIndex >= 8) { +			cByteIndex = 0; +		} +	} + +	/* +	 * If g_pLVDSList exists and pairs need updating, then update +	 * the negative-pair to receive the flipped positive-pair value. +	 */ + +	if (g_pLVDSList) { +		for (usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount; +			usLVDSIndex++) { +			if (g_pLVDSList[usLVDSIndex].ucUpdate) { + +				/* +				 * Read the positive value and flip it. +				 */ + +				cDataByte = (unsigned char) +				 (((g_pucOutData[g_pLVDSList[usLVDSIndex]. +					usPositiveIndex / 8] +					<< (g_pLVDSList[usLVDSIndex]. +					usPositiveIndex % 8)) & 0x80) ? +					0x01 : 0x00); +				/* 09/11/07 NN Type cast mismatch variables */ +				cDataByte = (unsigned char) (!cDataByte); + +				/* +				 * Get the byte that needs modification. +				 */ + +				cInDataByte = +				g_pucOutData[g_pLVDSList[usLVDSIndex]. +					usNegativeIndex / 8]; + +				if (cDataByte) { + +					/* +					 * Copy over the current byte and +					 * set the negative bit to 1. +					 */ + +					cDataByte = 0x00; +					for (cLVDSByteIndex = 7; +						cLVDSByteIndex >= 0; +						cLVDSByteIndex--) { +						cDataByte <<= 1; +						if (7 - +						(g_pLVDSList[usLVDSIndex]. +							usNegativeIndex % 8) == +							cLVDSByteIndex) { + +							/* +							 * Set negative bit to 1 +							 */ + +							cDataByte |= 0x01; +						} else if (cInDataByte & 0x80) { +							cDataByte |= 0x01; +						} + +						cInDataByte <<= 1; +					} + +					/* +					 * Store the modified byte. +					 */ + +					g_pucOutData[g_pLVDSList[usLVDSIndex]. +					usNegativeIndex / 8] = cDataByte; +				} else { + +					/* +					 * Copy over the current byte and set +					 * the negative bit to 0. +					 */ + +					cDataByte = 0x00; +					for (cLVDSByteIndex = 7; +						cLVDSByteIndex >= 0; +						cLVDSByteIndex--) { +						cDataByte <<= 1; +						if (7 - +						(g_pLVDSList[usLVDSIndex]. +						usNegativeIndex % 8) == +						cLVDSByteIndex) { + +							/* +							 * Set negative bit to 0 +							 */ + +							cDataByte |= 0x00; +						} else if (cInDataByte & 0x80) { +							cDataByte |= 0x01; +						} + +						cInDataByte <<= 1; +					} + +					/* +					 * Store the modified byte. +					 */ + +					g_pucOutData[g_pLVDSList[usLVDSIndex]. +					usNegativeIndex / 8] = cDataByte; +				} + +				break; +			} +		} +	} + +	return 0; +} + +signed char ispVMProcessLVDS(unsigned short a_usLVDSCount) +{ +	unsigned short usLVDSIndex = 0; + +	/* +	 * Allocate memory to hold LVDS pairs. +	 */ + +	ispVMMemManager(LVDS, a_usLVDSCount); +	g_usLVDSPairCount = a_usLVDSCount; + +#ifdef DEBUG +	printf("LVDS %d (", a_usLVDSCount); +#endif /* DEBUG */ + +	/* +	 * Iterate through each given LVDS pair. +	 */ + +	for (usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount; usLVDSIndex++) { + +		/* +		 * Assign the positive and negative indices of the LVDS pair. +		 */ + +		/* 09/11/07 NN Type cast mismatch variables */ +		g_pLVDSList[usLVDSIndex].usPositiveIndex = +			(unsigned short) ispVMDataSize(); +		/* 09/11/07 NN Type cast mismatch variables */ +		g_pLVDSList[usLVDSIndex].usNegativeIndex = +			(unsigned short)ispVMDataSize(); + +#ifdef DEBUG +		if (usLVDSIndex < g_usLVDSPairCount - 1) { +			printf("%d:%d, ", +				g_pLVDSList[usLVDSIndex].usPositiveIndex, +				g_pLVDSList[usLVDSIndex].usNegativeIndex); +		} else { +			printf("%d:%d", +				g_pLVDSList[usLVDSIndex].usPositiveIndex, +				g_pLVDSList[usLVDSIndex].usNegativeIndex); +		} +#endif /* DEBUG */ + +	} + +#ifdef DEBUG +	printf(");\n", a_usLVDSCount); +#endif /* DEBUG */ + +	return 0; +} diff --git a/drivers/fpga/lattice.c b/drivers/fpga/lattice.c new file mode 100644 index 000000000..a0e782310 --- /dev/null +++ b/drivers/fpga/lattice.c @@ -0,0 +1,399 @@ +/* + * (C) Copyright 2010 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * (C) Copyright 2002 + * Rich Ireland, Enterasys Networks, rireland@enterasys.com. + * + * ispVM functions adapted from Lattice's ispmVMEmbedded code: + * Copyright 2009 Lattice Semiconductor Corp. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include <common.h> +#include <malloc.h> +#include <fpga.h> +#include <lattice.h> + +static lattice_board_specific_func *pfns; +static char *fpga_image; +static unsigned long read_bytes; +static unsigned long bufsize; +static unsigned short expectedCRC; + +/* + * External variables and functions declared in ivm_core.c module. + */ +extern unsigned short g_usCalculatedCRC; +extern unsigned short g_usDataType; +extern unsigned char *g_pucIntelBuffer; +extern unsigned char *g_pucHeapMemory; +extern unsigned short g_iHeapCounter; +extern unsigned short g_iHEAPSize; +extern unsigned short g_usIntelDataIndex; +extern unsigned short g_usIntelBufferSize; +extern char *const g_szSupportedVersions[]; + + +/* + * ispVMDelay + * + * Users must implement a delay to observe a_usTimeDelay, where + * bit 15 of the a_usTimeDelay defines the unit. + *      1 = milliseconds + *      0 = microseconds + * Example: + *      a_usTimeDelay = 0x0001 = 1 microsecond delay. + *      a_usTimeDelay = 0x8001 = 1 millisecond delay. + * + * This subroutine is called upon to provide a delay from 1 millisecond to a few + * hundreds milliseconds each time. + * It is understood that due to a_usTimeDelay is defined as unsigned short, a 16 + * bits integer, this function is restricted to produce a delay to 64000 + * micro-seconds or 32000 milli-second maximum. The VME file will never pass on + * to this function a delay time > those maximum number. If it needs more than + * those maximum, the VME file will launch the delay function several times to + * realize a larger delay time cummulatively. + * It is perfectly alright to provide a longer delay than required. It is not + * acceptable if the delay is shorter. + */ +void ispVMDelay(unsigned short delay) +{ +	if (delay & 0x8000) +		delay = (delay & ~0x8000) * 1000; +	udelay(delay); +} + +void writePort(unsigned char a_ucPins, unsigned char a_ucValue) +{ +	a_ucValue = a_ucValue ? 1 : 0; + +	switch (a_ucPins) { +	case g_ucPinTDI: +		pfns->jtag_set_tdi(a_ucValue); +		break; +	case g_ucPinTCK: +		pfns->jtag_set_tck(a_ucValue); +		break; +	case g_ucPinTMS: +		pfns->jtag_set_tms(a_ucValue); +		break; +	default: +		printf("%s: requested unknown pin\n", __func__); +	} +} + +unsigned char readPort(void) +{ +	return pfns->jtag_get_tdo(); +} + +void sclock(void) +{ +	writePort(g_ucPinTCK, 0x01); +	writePort(g_ucPinTCK, 0x00); +} + +void calibration(void) +{ +	/* Apply 2 pulses to TCK. */ +	writePort(g_ucPinTCK, 0x00); +	writePort(g_ucPinTCK, 0x01); +	writePort(g_ucPinTCK, 0x00); +	writePort(g_ucPinTCK, 0x01); +	writePort(g_ucPinTCK, 0x00); + +	ispVMDelay(0x8001); + +	/* Apply 2 pulses to TCK. */ +	writePort(g_ucPinTCK, 0x01); +	writePort(g_ucPinTCK, 0x00); +	writePort(g_ucPinTCK, 0x01); +	writePort(g_ucPinTCK, 0x00); +} + +/* + * GetByte + * + * Returns a byte to the caller. The returned byte depends on the + * g_usDataType register. If the HEAP_IN bit is set, then the byte + * is returned from the HEAP. If the LHEAP_IN bit is set, then + * the byte is returned from the intelligent buffer. Otherwise, + * the byte is returned directly from the VME file. + */ +unsigned char GetByte(void) +{ +	unsigned char ucData; +	unsigned int block_size = 4 * 1024; + +	if (g_usDataType & HEAP_IN) { + +		/* +		 * Get data from repeat buffer. +		 */ + +		if (g_iHeapCounter > g_iHEAPSize) { + +			/* +			 * Data over-run. +			 */ + +			return 0xFF; +		} + +		ucData = g_pucHeapMemory[g_iHeapCounter++]; +	} else if (g_usDataType & LHEAP_IN) { + +		/* +		 * Get data from intel buffer. +		 */ + +		if (g_usIntelDataIndex >= g_usIntelBufferSize) { +			return 0xFF; +		} + +		ucData = g_pucIntelBuffer[g_usIntelDataIndex++]; +	} else { +		if (read_bytes == bufsize) { +			return 0xFF; +		} +		ucData = *fpga_image++; +		read_bytes++; + +		if (!(read_bytes % block_size)) { +			printf("Downloading FPGA %ld/%ld completed\r", +				read_bytes, +				bufsize); +		} + +		if (expectedCRC != 0) { +			ispVMCalculateCRC32(ucData); +		} +	} + +	return ucData; +} + +signed char ispVM(void) +{ +	char szFileVersion[9]      = { 0 }; +	signed char cRetCode         = 0; +	signed char cIndex           = 0; +	signed char cVersionIndex    = 0; +	unsigned char ucReadByte     = 0; +	unsigned short crc; + +	g_pucHeapMemory		= NULL; +	g_iHeapCounter		= 0; +	g_iHEAPSize		= 0; +	g_usIntelDataIndex	= 0; +	g_usIntelBufferSize	= 0; +	g_usCalculatedCRC = 0; +	expectedCRC   = 0; +	ucReadByte = GetByte(); +	switch (ucReadByte) { +	case FILE_CRC: +		crc = (unsigned char)GetByte(); +		crc <<= 8; +		crc |= GetByte(); +		expectedCRC = crc; + +		for (cIndex = 0; cIndex < 8; cIndex++) +			szFileVersion[cIndex] = GetByte(); + +		break; +	default: +		szFileVersion[0] = (signed char) ucReadByte; +		for (cIndex = 1; cIndex < 8; cIndex++) +			szFileVersion[cIndex] = GetByte(); + +		break; +	} + +	/* +	 * +	 * Compare the VME file version against the supported version. +	 * +	 */ + +	for (cVersionIndex = 0; g_szSupportedVersions[cVersionIndex] != 0; +		cVersionIndex++) { +		for (cIndex = 0; cIndex < 8; cIndex++) { +			if (szFileVersion[cIndex] != +				g_szSupportedVersions[cVersionIndex][cIndex]) { +				cRetCode = VME_VERSION_FAILURE; +				break; +			} +			cRetCode = 0; +		} + +		if (cRetCode == 0) { +			break; +		} +	} + +	if (cRetCode < 0) { +		return VME_VERSION_FAILURE; +	} + +	printf("VME file checked: starting downloading to FPGA\n"); + +	ispVMStart(); + +	cRetCode = ispVMCode(); + +	ispVMEnd(); +	ispVMFreeMem(); +	puts("\n"); + +	if (cRetCode == 0 && expectedCRC != 0 && +			(expectedCRC != g_usCalculatedCRC)) { +		printf("Expected CRC:   0x%.4X\n", expectedCRC); +		printf("Calculated CRC: 0x%.4X\n", g_usCalculatedCRC); +		return VME_CRC_FAILURE; +	} +	return cRetCode; +} + +static int lattice_validate(Lattice_desc *desc, const char *fn) +{ +	int ret_val = FALSE; + +	if (desc) { +		if ((desc->family > min_lattice_type) && +			(desc->family < max_lattice_type)) { +			if ((desc->iface > min_lattice_iface_type) && +				(desc->iface < max_lattice_iface_type)) { +				if (desc->size) { +					ret_val = TRUE; +				} else { +					printf("%s: NULL part size\n", fn); +				} +			} else { +				printf("%s: Invalid Interface type, %d\n", +					fn, desc->iface); +			} +		} else { +			printf("%s: Invalid family type, %d\n", +				fn, desc->family); +		} +	} else { +		printf("%s: NULL descriptor!\n", fn); +	} + +	return ret_val; +} + +int lattice_load(Lattice_desc *desc, void *buf, size_t bsize) +{ +	int ret_val = FPGA_FAIL; + +	if (!lattice_validate(desc, (char *)__func__)) { +		printf("%s: Invalid device descriptor\n", __func__); +	} else { +		pfns = desc->iface_fns; + +		switch (desc->family) { +		case Lattice_XP2: +			fpga_image = buf; +			read_bytes = 0; +			bufsize = bsize; +			debug("%s: Launching the Lattice ISPVME Loader:" +				" addr 0x%x size 0x%x...\n", +				__func__, fpga_image, bufsize); +			ret_val = ispVM(); +			if (ret_val) +				printf("%s: error %d downloading FPGA image\n", +					__func__, ret_val); +			else +				puts("FPGA downloaded successfully\n"); +			break; +		default: +			printf("%s: Unsupported family type, %d\n", +					__func__, desc->family); +		} +	} + +	return ret_val; +} + +int lattice_dump(Lattice_desc *desc, void *buf, size_t bsize) +{ +	puts("Dump not supported for Lattice FPGA\n"); + +	return FPGA_FAIL; + +} + +int lattice_info(Lattice_desc *desc) +{ +	int ret_val = FPGA_FAIL; + +	if (lattice_validate(desc, (char *)__func__)) { +		printf("Family:        \t"); +		switch (desc->family) { +		case Lattice_XP2: +			puts("XP2\n"); +			break; +			/* Add new family types here */ +		default: +			printf("Unknown family type, %d\n", desc->family); +		} + +		puts("Interface type:\t"); +		switch (desc->iface) { +		case lattice_jtag_mode: +			puts("JTAG Mode\n"); +			break; +			/* Add new interface types here */ +		default: +			printf("Unsupported interface type, %d\n", desc->iface); +		} + +		printf("Device Size:   \t%d bytes\n", +				desc->size); + +		if (desc->iface_fns) { +			printf("Device Function Table @ 0x%p\n", +				desc->iface_fns); +			switch (desc->family) { +			case Lattice_XP2: +				break; +				/* Add new family types here */ +			default: +				break; +			} +		} else { +			puts("No Device Function Table.\n"); +		} + +		if (desc->desc) +			printf("Model:         \t%s\n", desc->desc); + +		ret_val = FPGA_SUCCESS; +	} else { +		printf("%s: Invalid device descriptor\n", __func__); +	} + +	return ret_val; +} + + diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 255679a18..399520e22 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -36,6 +36,7 @@ COBJS-$(CONFIG_USB_SL811HS) += sl811-hcd.o  # echi  COBJS-$(CONFIG_USB_EHCI) += ehci-hcd.o  COBJS-$(CONFIG_USB_EHCI_FSL) += ehci-fsl.o +COBJS-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o  COBJS-$(CONFIG_USB_EHCI_PPC4XX) += ehci-ppc4xx.o  COBJS-$(CONFIG_USB_EHCI_IXP4XX) += ehci-ixp.o  COBJS-$(CONFIG_USB_EHCI_KIRKWOOD) += ehci-kirkwood.o diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c new file mode 100644 index 000000000..af8ee907e --- /dev/null +++ b/drivers/usb/host/ehci-mxc.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> + * + * 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 <common.h> +#include <usb.h> +#include <asm/io.h> +#include <asm/arch/mx31-regs.h> +#include <usb/ehci-fsl.h> +#include <errno.h> + +#include "ehci.h" +#include "ehci-core.h" + +#define USBCTRL_OTGBASE_OFFSET	0x600 + +#define MX31_OTG_SIC_SHIFT	29 +#define MX31_OTG_SIC_MASK	(0x3 << MX31_OTG_SIC_SHIFT) +#define MX31_OTG_PM_BIT		(1 << 24) + +#define MX31_H2_SIC_SHIFT	21 +#define MX31_H2_SIC_MASK	(0x3 << MX31_H2_SIC_SHIFT) +#define MX31_H2_PM_BIT		(1 << 16) +#define MX31_H2_DT_BIT		(1 << 5) + +#define MX31_H1_SIC_SHIFT	13 +#define MX31_H1_SIC_MASK	(0x3 << MX31_H1_SIC_SHIFT) +#define MX31_H1_PM_BIT		(1 << 8) +#define MX31_H1_DT_BIT		(1 << 4) + +static int mxc_set_usbcontrol(int port, unsigned int flags) +{ +	unsigned int v; +#ifdef CONFIG_MX31 +		v = readl(MX31_OTG_BASE_ADDR + USBCTRL_OTGBASE_OFFSET); + +		switch (port) { +		case 0:	/* OTG port */ +			v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT); +			v |= (flags & MXC_EHCI_INTERFACE_MASK) +					<< MX31_OTG_SIC_SHIFT; +			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) +				v |= MX31_OTG_PM_BIT; + +			break; +		case 1: /* H1 port */ +			v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | +				MX31_H1_DT_BIT); +			v |= (flags & MXC_EHCI_INTERFACE_MASK) +						<< MX31_H1_SIC_SHIFT; +			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) +				v |= MX31_H1_PM_BIT; + +			if (!(flags & MXC_EHCI_TTL_ENABLED)) +				v |= MX31_H1_DT_BIT; + +			break; +		case 2:	/* H2 port */ +			v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | +				MX31_H2_DT_BIT); +			v |= (flags & MXC_EHCI_INTERFACE_MASK) +						<< MX31_H2_SIC_SHIFT; +			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) +				v |= MX31_H2_PM_BIT; + +			if (!(flags & MXC_EHCI_TTL_ENABLED)) +				v |= MX31_H2_DT_BIT; + +			break; +		default: +			return -EINVAL; +		} + +		writel(v, MX31_OTG_BASE_ADDR + +				     USBCTRL_OTGBASE_OFFSET); +#endif +		return 0; +} + +int ehci_hcd_init(void) +{ +	u32 tmp; +	struct usb_ehci *ehci; +	struct clock_control_regs *sc_regs = +		(struct clock_control_regs *)CCM_BASE; + +	tmp = __raw_readl(&sc_regs->ccmr); +	__raw_writel(__raw_readl(&sc_regs->ccmr) | (1 << 9), &sc_regs->ccmr) ; + +	udelay(80); + +	/* Take USB2 */ +	ehci = (struct usb_ehci *)(MX31_OTG_BASE_ADDR + +		(0x200 * CONFIG_MXC_USB_PORT)); +	hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); +	hcor = (struct ehci_hcor *)((uint32_t) hccr + +			HC_LENGTH(ehci_readl(&hccr->cr_capbase))); +	setbits_le32(&ehci->usbmode, CM_HOST); +	setbits_le32(&ehci->control, USB_EN); + +	__raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); + +	mxc_set_usbcontrol(CONFIG_MXC_USB_PORT, CONFIG_MXC_USB_FLAGS); + +	return 0; +} + +/* + * Destroy the appropriate control structures corresponding + * the the EHCI host controller. + */ +int ehci_hcd_stop(void) +{ +	return 0; +} diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 7f04b4944..51831f0e6 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -334,37 +334,6 @@ enum ipu_panel {  #define IOMUX_MODE_L(pin, mode) IOMUX_MODE(((pin) + 0xc) ^ 3, mode) -enum lcd_pin { -	MX31_PIN_D3_SPL		= IOMUX_PIN(0xff,  19), -	MX31_PIN_D3_CLS		= IOMUX_PIN(0xff,  20), -	MX31_PIN_D3_REV		= IOMUX_PIN(0xff,  21), -	MX31_PIN_CONTRAST	= IOMUX_PIN(0xff,  22), -	MX31_PIN_VSYNC3		= IOMUX_PIN(0xff,  23), - -	MX31_PIN_DRDY0		= IOMUX_PIN(0xff,  33), -	MX31_PIN_FPSHIFT	= IOMUX_PIN(0xff,  34), -	MX31_PIN_HSYNC		= IOMUX_PIN(0xff,  35), - -	MX31_PIN_LD17		= IOMUX_PIN(0xff,  37), -	MX31_PIN_LD16		= IOMUX_PIN(0xff,  38), -	MX31_PIN_LD15		= IOMUX_PIN(0xff,  39), -	MX31_PIN_LD14		= IOMUX_PIN(0xff,  40), -	MX31_PIN_LD13		= IOMUX_PIN(0xff,  41), -	MX31_PIN_LD12		= IOMUX_PIN(0xff,  42), -	MX31_PIN_LD11		= IOMUX_PIN(0xff,  43), -	MX31_PIN_LD10		= IOMUX_PIN(0xff,  44), -	MX31_PIN_LD9		= IOMUX_PIN(0xff,  45), -	MX31_PIN_LD8		= IOMUX_PIN(0xff,  46), -	MX31_PIN_LD7		= IOMUX_PIN(0xff,  47), -	MX31_PIN_LD6		= IOMUX_PIN(0xff,  48), -	MX31_PIN_LD5		= IOMUX_PIN(0xff,  49), -	MX31_PIN_LD4		= IOMUX_PIN(0xff,  50), -	MX31_PIN_LD3		= IOMUX_PIN(0xff,  51), -	MX31_PIN_LD2		= IOMUX_PIN(0xff,  52), -	MX31_PIN_LD1		= IOMUX_PIN(0xff,  53), -	MX31_PIN_LD0		= IOMUX_PIN(0xff,  54), -}; -  struct chan_param_mem_planar {  	/* Word 0 */  	u32	xv:10; diff --git a/include/configs/qong.h b/include/configs/qong.h index 7f284efe5..f26ced1d7 100644 --- a/include/configs/qong.h +++ b/include/configs/qong.h @@ -66,8 +66,11 @@  #define CONFIG_FSL_PMIC_MODE	(SPI_MODE_0 | SPI_CS_HIGH)  /* FPGA */ +#define CONFIG_FPGA  #define CONFIG_QONG_FPGA	1  #define CONFIG_FPGA_BASE	(CS1_BASE) +#define CONFIG_FPGA_LATTICE +#define CONFIG_FPGA_COUNT	1  #ifdef CONFIG_QONG_FPGA  /* Ethernet */ @@ -86,6 +89,22 @@  #define CONFIG_BMP_16BPP  #define CONFIG_DISPLAY_COM57H5M10XRC +/* USB */ +#define CONFIG_CMD_USB +#ifdef CONFIG_CMD_USB +#define CONFIG_USB_EHCI			/* Enable EHCI USB support */ +#define CONFIG_USB_EHCI_MXC +#define CONFIG_EHCI_HCD_INIT_AFTER_RESET +#define CONFIG_MXC_USB_PORT	2 +#define CONFIG_MXC_USB_PORTSC	(MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT) +#define CONFIG_MXC_USB_FLAGS	MXC_EHCI_POWER_PINS_ENABLED +#define CONFIG_EHCI_IS_TDI +#define CONFIG_USB_STORAGE +#define CONFIG_DOS_PARTITION +#define CONFIG_SUPPORT_VFAT +#define CONFIG_CMD_FAT +#endif /* CONFIG_CMD_USB */ +  /*   * Reducing the ARP timeout from default 5 seconds to 200ms we speed up the   * initial TFTP transfer, should the user wish one, significantly. @@ -247,7 +266,7 @@ extern int qong_nand_rdy(void *chip);  #define	CONFIG_ENV_IS_IN_FLASH	1  #define CONFIG_ENV_SECT_SIZE	0x20000  #define CONFIG_ENV_SIZE		CONFIG_ENV_SECT_SIZE -#define CONFIG_ENV_ADDR		(CONFIG_SYS_FLASH_BASE + 0x60000) +#define CONFIG_ENV_ADDR		(CONFIG_SYS_FLASH_BASE + 0x80000)  /* Address and size of Redundant Environment Sector	*/  #define CONFIG_ENV_OFFSET_REDUND	(CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE) diff --git a/include/fpga.h b/include/fpga.h index 84d7b9fc1..ac24f2b27 100644 --- a/include/fpga.h +++ b/include/fpga.h @@ -61,6 +61,7 @@ typedef enum {			/* typedef fpga_type */  	fpga_min_type,		/* range check value */  	fpga_xilinx,		/* Xilinx Family) */  	fpga_altera,		/* unimplemented */ +	fpga_lattice,		/* Lattice family */  	fpga_undefined		/* invalid range check value */  } fpga_type;			/* end, typedef fpga_type */ diff --git a/include/lattice.h b/include/lattice.h new file mode 100755 index 000000000..33d2ac3df --- /dev/null +++ b/include/lattice.h @@ -0,0 +1,319 @@ +/* + * Porting to U-Boot: + * + * (C) Copyright 2010 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * Lattice's ispVME Embedded Tool to load Lattice's FPGA: + * + * Lattice Semiconductor Corp. Copyright 2009 + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef _VME_OPCODE_H +#define _VME_OPCODE_H + +#define VME_VERSION_NUMBER "12.1" + +/* Maximum declarations. */ + +#define VMEHEXMAX	60000L	/* The hex file is split 60K per file. */ +#define SCANMAX		64000L	/* The maximum SDR/SIR burst. */ + +/* + * + * Supported JTAG state transitions. + * + */ + +#define RESET		0x00 +#define IDLE		0x01 +#define IRPAUSE		0x02 +#define DRPAUSE		0x03 +#define SHIFTIR		0x04 +#define SHIFTDR		0x05 +/* 11/15/05 Nguyen changed to support DRCAPTURE*/ +#define DRCAPTURE	0x06 + +/* + * Flow control register bit definitions.  A set bit indicates + * that the register currently exhibits the corresponding mode. + */ + +#define INTEL_PRGM	0x0001	/* Intelligent programming is in effect. */ +#define CASCADE		0x0002	/* Currently splitting large SDR. */ +#define REPEATLOOP	0x0008	/* Currently executing a repeat loop. */ +#define SHIFTRIGHT	0x0080	/* The next data stream needs a right shift. */ +#define SHIFTLEFT	0x0100	/* The next data stream needs a left shift. */ +#define VERIFYUES	0x0200	/* Continue if fail is in effect. */ + +/* + * DataType register bit definitions.  A set bit indicates + * that the register currently holds the corresponding type of data. + */ + +#define EXPRESS		0x0001    /* Simultaneous program and verify. */ +#define SIR_DATA	0x0002    /* SIR is the active SVF command. */ +#define SDR_DATA	0x0004    /* SDR is the active SVF command. */ +#define COMPRESS	0x0008    /* Data is compressed. */ +#define TDI_DATA	0x0010    /* TDI data is present. */ +#define TDO_DATA	0x0020    /* TDO data is present. */ +#define MASK_DATA	0x0040    /* MASK data is present. */ +#define HEAP_IN		0x0080    /* Data is from the heap. */ +#define LHEAP_IN	0x0200    /* Data is from intel data buffer. */ +#define VARIABLE	0x0400    /* Data is from a declared variable. */ +#define CRC_DATA	0x0800	 /* CRC data is pressent. */ +#define CMASK_DATA	0x1000    /* CMASK data is pressent. */ +#define RMASK_DATA	0x2000	 /* RMASK data is pressent. */ +#define READ_DATA	0x4000    /* READ data is pressent. */ +#define DMASK_DATA	0x8000	 /* DMASK data is pressent. */ + +/* + * + * Pin opcodes. + * + */ + +#define signalENABLE	0x1C    /* ispENABLE pin. */ +#define signalTMS	0x1D    /* TMS pin. */ +#define signalTCK	0x1E    /* TCK pin. */ +#define signalTDI	0x1F    /* TDI pin. */ +#define signalTRST	0x20    /* TRST pin. */ + +/* + * + * Supported vendors. + * + */ + +#define VENDOR		0x56 +#define LATTICE		0x01 +#define ALTERA		0x02 +#define XILINX		0x03 + +/* + * Opcode definitions. + * + * Note: opcodes must be unique. + */ + +#define ENDDATA		0x00	/* The end of the current SDR data stream. */ +#define RUNTEST		0x01	/* The duration to stay at the stable state. */ +#define ENDDR		0x02	/* The stable state after SDR. */ +#define ENDIR		0x03	/* The stable state after SIR. */ +#define ENDSTATE	0x04	/* The stable state after RUNTEST. */ +#define TRST		0x05	/* Assert the TRST pin. */ +#define HIR		0x06	/* +				 * The sum of the IR bits of the +				 * leading devices. +				 */ +#define TIR		0x07	/* +				 * The sum of the IR bits of the trailing +				 * devices. +				 */ +#define HDR		0x08	/* The number of leading devices. */ +#define TDR		0x09	/* The number of trailing devices. */ +#define ispEN		0x0A	/* Assert the ispEN pin. */ +#define FREQUENCY	0x0B	/* +				 * The maximum clock rate to run the JTAG state +				 * machine. +				 */ +#define STATE		0x10	/* Move to the next stable state. */ +#define SIR		0x11	/* The instruction stream follows. */ +#define SDR		0x12	/* The data stream follows. */ +#define TDI		0x13	/* The following data stream feeds into +					the device. */ +#define TDO		0x14	/* +				 * The following data stream is compared against +				 * the device. +				 */ +#define MASK		0x15	/* The following data stream is used as mask. */ +#define XSDR		0x16	/* +				 * The following data stream is for simultaneous +				 * program and verify. +				 */ +#define XTDI		0x17	/* The following data stream is for shift in +				 * only. It must be stored for the next +				 * XSDR. +				 */ +#define XTDO		0x18	/* +				 * There is not data stream.  The data stream +				 * was stored from the previous XTDI. +				 */ +#define MEM		0x19	/* +				 * The maximum memory needed to allocate in +				 * order hold one row of data. +				 */ +#define WAIT		0x1A	/* The duration of delay to observe. */ +#define TCK		0x1B	/* The number of TCK pulses. */ +#define SHR		0x23	/* +				 * Set the flow control register for +				 * right shift +				 */ +#define SHL		0x24	/* +				 * Set the flow control register for left shift. +				 */ +#define HEAP		0x32	/* The memory size needed to hold one loop. */ +#define REPEAT		0x33	/* The beginning of the loop. */ +#define LEFTPAREN	0x35	/* The beginning of data following the loop. */ +#define VAR		0x55	/* Plac holder for loop data. */ +#define SEC		0x1C	/* +				 * The delay time in seconds that must be +				 * observed. +				 */ +#define SMASK		0x1D	/* The mask for TDI data. */ +#define MAX_WAIT	0x1E	/* The absolute maximum wait time. */ +#define ON		0x1F	/* Assert the targeted pin. */ +#define OFF		0x20	/* Dis-assert the targeted pin. */ +#define SETFLOW		0x30	/* Change the flow control register. */ +#define RESETFLOW	0x31	/* Clear the flow control register. */ + +#define CRC		0x47	/* +				 * The following data stream is used for CRC +				 * calculation. +				 */ +#define CMASK		0x48	/* +				 * The following data stream is used as mask +				 * for CRC calculation. +				 */ +#define RMASK		0x49	/* +				 * The following data stream is used as mask +				 * for read and save. +				 */ +#define READ		0x50	/* +				 * The following data stream is used for read +				 * and save. +				 */ +#define ENDLOOP		0x59	/* The end of the repeat loop. */ +#define SECUREHEAP	0x60	/* Used to secure the HEAP opcode. */ +#define VUES		0x61	/* Support continue if fail. */ +#define DMASK		0x62	/* +				 * The following data stream is used for dynamic +				 * I/O. +				 */ +#define COMMENT		0x63	/* Support SVF comments in the VME file. */ +#define HEADER		0x64	/* Support header in VME file. */ +#define FILE_CRC	0x65	/* Support crc-protected VME file. */ +#define LCOUNT		0x66	/* Support intelligent programming. */ +#define LDELAY		0x67	/* Support intelligent programming. */ +#define LSDR		0x68	/* Support intelligent programming. */ +#define LHEAP		0x69	/* +				 * Memory needed to hold intelligent data +				 * buffer +				 */ +#define CONTINUE	0x70	/* Allow continuation. */ +#define LVDS		0x71	/* Support LVDS. */ +#define ENDVME		0x7F	/* End of the VME file. */ +#define ENDFILE		0xFF	/* End of file. */ + +/* + * + * ispVM Embedded Return Codes. + * + */ + +#define VME_VERIFICATION_FAILURE	-1 +#define VME_FILE_READ_FAILURE		-2 +#define VME_VERSION_FAILURE		-3 +#define VME_INVALID_FILE		-4 +#define VME_ARGUMENT_FAILURE		-5 +#define VME_CRC_FAILURE			-6 + +#define g_ucPinTDI	0x01 +#define g_ucPinTCK	0x02 +#define g_ucPinTMS	0x04 +#define g_ucPinENABLE	0x08 +#define g_ucPinTRST	0x10 + +/* + * + * Type definitions. + * + */ + +/* Support LVDS */ +typedef struct { +	unsigned short usPositiveIndex; +	unsigned short usNegativeIndex; +	unsigned char  ucUpdate; +} LVDSPair; + +typedef enum { +	min_lattice_iface_type,		/* insert all new types after this */ +	lattice_jtag_mode,		/* jtag/tap  */ +	max_lattice_iface_type		/* insert all new types before this */ +} Lattice_iface; + +typedef enum { +	min_lattice_type, +	Lattice_XP2,			/* Lattice XP2 Family */ +	max_lattice_type		/* insert all new types before this */ +} Lattice_Family; + +typedef struct { +	Lattice_Family	family;	/* part type */ +	Lattice_iface	iface;	/* interface type */ +	size_t		size;	/* bytes of data part can accept */ +	void		*iface_fns; /* interface function table */ +	void		*base;	/* base interface address */ +	int		cookie;	/* implementation specific cookie */ +	char		*desc;	/* description string */ +} Lattice_desc;			/* end, typedef Altera_desc */ + +/* Lattice Model Type */ +#define CONFIG_SYS_XP2		CONFIG_SYS_FPGA_DEV(0x1) + +/* Board specific implementation specific function types */ +typedef void (*Lattice_jtag_init)(void); +typedef void (*Lattice_jtag_set_tdi)(int v); +typedef void (*Lattice_jtag_set_tms)(int v); +typedef void (*Lattice_jtag_set_tck)(int v); +typedef int (*Lattice_jtag_get_tdo)(void); + +typedef struct { +	Lattice_jtag_init	jtag_init; +	Lattice_jtag_set_tdi	jtag_set_tdi; +	Lattice_jtag_set_tms	jtag_set_tms; +	Lattice_jtag_set_tck	jtag_set_tck; +	Lattice_jtag_get_tdo	jtag_get_tdo; +} lattice_board_specific_func; + +void writePort(unsigned char pins, unsigned char value); +unsigned char readPort(void); +void sclock(void); +void ispVMDelay(unsigned short int a_usMicroSecondDelay); +void calibration(void); + +int lattice_load(Lattice_desc *desc, void *buf, size_t bsize); +int lattice_dump(Lattice_desc *desc, void *buf, size_t bsize); +int lattice_info(Lattice_desc *desc); + +void ispVMStart(void); +void ispVMEnd(void); +signed char ispVMCode(void); +void ispVMDelay(unsigned short int a_usMicroSecondDelay); +void ispVMCalculateCRC32(unsigned char a_ucData); +unsigned char GetByte(void); +void writePort(unsigned char pins, unsigned char value); +unsigned char readPort(void); +void sclock(void); +#endif + |