/*************************************************************************\
* "$RCSfile: JTAG.c,v $"                                                  *
***************************************************************************
* Information by CVS or VSS:                                              *
*     Last check in on: $Date: 2010-04-20 07:54:51 $                      *
*     by                $Author: schluckebier $
*     Revision        : $Revision: 1.4 $                                 *
\*************************************************************************/
/*! \file JTAG.c
*	\brief JTAG
*	\author (c) 2007 - 2010 IMAGO Technologies GmbH
*
*	$Revision: 1.4 $
*	$Date: 2010-04-20 07:54:51 $
**************************************************************************/

#include "vision_box.h"

#define ENABLE_OUTPUTS (1 << 16)

static int JTAG_DeviceCount;

typedef struct sSUN_CONFIG
{
	unsigned int Version;
	int CycleTime;
	unsigned int DSP_SourceBase;
	unsigned int DSP_SourceShift;
	int DSP_SourceAutoEvent;
	unsigned int DSP_CtrlReg;
} SUN_CONFIG;

extern SUN_CONFIG VIB_SunConfig;

/*************************************************************************/
int JTAG_ReadWrite(unsigned int TMS, unsigned int TDI, unsigned int *pReadValue, int bitCount)
/*************************************************************************/
{
	static int BitCount = -1;
	int count;

	if (bitCount > 32)
		return -1;

	if (bitCount > 16)
		count = 16;
	else
		count = bitCount;

	if (BitCount != count)
	{
		VIB_SetReg(0x08100000, count);
		BitCount = count;
	}

	*pReadValue = 0;
	if (VIB_SunReadRegister(0x08200000, (TMS << 16) | (TDI & 0xffff), pReadValue, 10) < 0)
		return -1;

	if (bitCount > 16)
	{
		// recursive call necessary
		unsigned int read2;
		if (JTAG_ReadWrite(TMS >> 16, TDI >> 16, &read2, bitCount - 16) < 0)
			return -1;

		*pReadValue &= 0x0000FFFF;
		*pReadValue |= read2 << 16;
	}
	return 0;
}

/*************************************************************************/
int JTAG_Write(unsigned int TMS, unsigned int TDI, int bitCount)
/*************************************************************************/
{
	unsigned int dummy;

	if (JTAG_ReadWrite(TMS, TDI, &dummy, bitCount) < 0)
		return -1;

	return 0;
}

/*************************************************************************/
int JTAG_Read(unsigned int *pReadValue, int bitCount)
/*************************************************************************/
{
	if (JTAG_ReadWrite(0, 0, pReadValue, bitCount) < 0)
		return -1;

	*pReadValue >>= (32-bitCount);
	return 0;
}

/*************************************************************************/
int JTAG_ScanChain()
/*************************************************************************/
{
	int i;
	unsigned int value;

	// Reset TAP of all devices
	JTAG_Write(0x3f, 0, 6);

	// go to Shift-IR
	JTAG_Write(0x6, 0, 5);

	// BYPASS instruction
	for (i=0; i<4; i++)
		JTAG_Write(0x0000, 0xffffffff, 32);
	JTAG_Write(0x1, 0x1, 1);	// last Bit, go to Exit1-IR

	// go to Shift-DR
	JTAG_Write(0x3, 0xf, 4);

	JTAG_ReadWrite(0, 0, &value, 32);
	JTAG_Write(0, 1, 1);

	for (JTAG_DeviceCount = 1; JTAG_DeviceCount < 32; JTAG_DeviceCount++)
	{
		JTAG_Read(&value, 1);
		if (value)
			return 0;
	}
	return -1;
}

/*************************************************************************/
int JTAG_Init()
/*************************************************************************/
{
	unsigned int value;
	int i;
	//int kHz = 1000;	// 1 MHz
	int kHz = 2000;	// 2 MHz
	int clkCounter;

	if (VIB_SunConfig.Version < 804140000)
	{
		printf("JTAG is not supported.\n");
		return -1;
	}
	clkCounter = 1000000000/kHz / (2 * VIB_SunConfig.CycleTime);
	clkCounter = MIN(clkCounter, 0xffff);

	// Enable JTAG-outputs and adjust frequency
	VIB_SetReg(0x08000000, ENABLE_OUTPUTS | clkCounter);
	VIB_SetReg(0x08100000, 1);
	VIB_SunReadRegister(0x08200000, 0xffffffff, &value, 10);

	if (JTAG_ScanChain() < 0)
	{
		printf("Error scanning JTAG chain\n");
		return -1;
	}
	printf("Found %d JTAG Devices.\n\n", JTAG_DeviceCount);

	// IDs lesen
	JTAG_Write(0x3f, 0, 6);	// Reset TAP of all devices
	JTAG_Write(0x2, 0, 4);	// go to Shift-DR
	for (i=0; i<JTAG_DeviceCount; i++)
	{
		JTAG_Read(&value, 1);	// lsb
		JTAG_Read(&value, 11);	// Manufacturer's ID
		printf("Manufacturer's ID: 0x%X\n", value);
		JTAG_Read(&value, 16);	// Part number
		printf("Part number: 0x%X\n", value);
		JTAG_Read(&value, 4);	// Version
		printf("Version: 0x%X\n\n", value);
	}
	return 0;
}

/*************************************************************************/
