#include "stdafx.h"
#include <windows.h>
#include "McStar.h"

/////////////////////////////////////////////////////////////////////////////
// VirtualCopy definition
//
extern "C" BOOL VirtualCopy(LPVOID lpvDestMem, LPVOID lpvSrcMem, 
							DWORD dwSizeInBytes, DWORD dwProtectFlag);


/////////////////////////////////////////////////////////////////////////////
// Forward declarations for internal functions
//


/////////////////////////////////////////////////////////////////////////////
// Internal defines
//
#define SSP3_BASE		0x41900000
#define SSCR0_3_OFFSET	0x00
#define SSCR1_3_OFFSET	0x0004		
#define SSSR_3_OFFSET	0x0008		
#define SSITR_3_OFFSET	0x000C		
#define SSDR_3_OFFSET	0x0010		
#define SSTO_3_OFFSET	0x0028		
#define SSPSP_3_OFFSET	0x002C		
#define SSTSA_3_OFFSET	0x0030		
#define SSRSA_3_OFFSET	0x0034	
#define SSTSS_3_OFFSET	0x0038	
#define SSACD_3_OFFSET	0x003C

#define GPIO_BASE		0x40E00000
#define GPLR0_OFFSET	0x00		// level register 0
#define GPLR1_OFFSET	0x04		// level register 1
#define GPLR2_OFFSET	0x08		// level register 2
#define GPLR3_OFFSET	0x0100		// level register 2
#define GPDR0_OFFSET	0x0C		// direction register 0
#define GPDR1_OFFSET	0x10		// direction register 1
#define GPDR2_OFFSET	0x14		// direction register 2
#define GPDR3_OFFSET	0x010C		// direction register 2
#define GPSR0_OFFSET	0x18		// set register 0
#define GPSR1_OFFSET	0x1C		// set register 1
#define GPSR2_OFFSET	0x20		// set register 2
#define GPSR3_OFFSET	0x0118		// set register 2
#define GPCR0_OFFSET	0x24		// clear register 0
#define GPCR1_OFFSET	0x28		// clear register 1
#define GPCR2_OFFSET	0x2C		// clear register 2
#define GPCR3_OFFSET	0x0124		// clear register 2
#define GAFR0_L_OFFSET	0x54		// alt. fxn register 1
#define GAFR0_U_OFFSET	0x58		// alt. fxn register 2
#define GAFR1_L_OFFSET	0x5C		// alt. fxn register 1
#define GAFR1_U_OFFSET	0x60		// alt. fxn register 2
#define GAFR2_L_OFFSET	0x64		// alt. fxn register 1
#define GAFR2_U_OFFSET	0x68		// alt. fxn register 2
#define GAFR3_L_OFFSET	0x6C		// alt. fxn register 1
#define GAFR3_U_OFFSET	0x70		// alt. fxn register 2

VOID InitPSP2( VOID )
{
	LPVOID	m_hSSP3,
			m_hGPIO,
			m_hCKEN;
	DWORD	*ptr;

	m_hSSP3 = MapAddress(SSP3_BASE);
	m_hCKEN = MapAddress(CKEN_BASE);
	m_hGPIO = MapAddress(GPIO_BASE);

	// Disable SSP Clock
	ptr = (DWORD*)m_hCKEN;
	*ptr &= ~(0x1 << 4);	

	DEBUGMSG(1,(TEXT("Register values after Init PSP2 \r\n")));

	//Set GPIO alternate function bits for SSP port
	ptr = (DWORD*)m_hGPIO;
	ptr += (GAFR2_U_OFFSET / sizeof(DWORD));
	*ptr &= ~(0x03 << 2);	// clear AF81 bits
	*ptr |= (0x1 << 2);		// AF81 bits set for AF1 - SSPTXD3 output
	*ptr &= ~(0x03 << 4);	// clear AF82 bits
	*ptr |= (0x1 << 4);		// AF82 bits set for AF1 - SSPRXD3 input
	*ptr &= ~(0x03 << 6);	// clear AF83 bits
	*ptr |= (0x1 << 6);		// AF83 bits set for AF1 - SSPSFRM3 output
	*ptr &= ~(0x03 << 8);	// clear AF84 bits
	*ptr |= (0x1 << 8);		// AF84 bits set for AF1 - SSPCLK3 output
	DEBUGMSG(1,(TEXT("GAFR2_U = 0x%8x \r\n"),*ptr));

	//Set SSP3 SSCR0 register
	ptr = (DWORD*)m_hSSP3;
	ptr += (SSCR0_3_OFFSET / sizeof(DWORD));
	*ptr = 0;			// clear all SSCR0 bits
	*ptr |= (0x3 << 4); // Set Frame Format to PSP 
	*ptr |= (0x1 << 20);// Set Extended Data Size Select
	*ptr &= 0xFFF000FF; // Clear Serial Clock Rate bits
	*ptr |= (0x1 << 8); // Set Serial Clock Rate
	*ptr &= 0xFFFFFFF0; // Clear Data Size Select bits
	*ptr |= 0x07;		// Set Data Size Select to 24 bits
	DEBUGMSG(1,(TEXT("SSCR0_3 = 0x%8x \r\n"),*ptr));

	//Set SSP3 SSCR1 register
	ptr = (DWORD*)m_hSSP3;
	ptr += (SSCR1_3_OFFSET / sizeof(DWORD));
	*ptr = 0;				// clear all SSCR1 bits
	*ptr |= (0x1 << 28);	// Set Slave Clock Free Running just active only during transfers just to make sure 
	*ptr |= (0x0 << 25);	// Set SSPSCLK direction to Master mode just to make sure
	*ptr |= (0x1 << 24);	// Set SSP Frame Direction to Slave 
	*ptr |= (0x1 << 23);	// Set Receive Without Transmit mode
	DEBUGMSG(1,(TEXT("SSCR1_3 = 0x%8x \r\n"),*ptr));

	//Set GPIO direction register msut be written after PSP bits are set
	ptr = (DWORD*)m_hGPIO;
	ptr += (GPDR2_OFFSET / sizeof(DWORD));
	*ptr |= (0x1 << 17); // GPIO 81 set to output
	*ptr &= ~(0x1 << 18); // GPIO 82 set to input
	*ptr &= ~(0x1 << 19); // GPIO 83 set to input
	*ptr |= (0x1 << 20); // GPIO 84 set to output
	DEBUGMSG(1,(TEXT("GPDR2 = 0x%8x \r\n"),*ptr));

	//Clear the RX FIFO Overrun bit (not sure this needs to be done for read only operations)
	ptr = (DWORD*)m_hSSP3;
	ptr += (SSSR_3_OFFSET / sizeof(DWORD));
	*ptr |= (0x1 << 7);	
	DEBUGMSG(1,(TEXT("SSSR_3 = 0x%8x \r\n"),*ptr));

	//Enable SSP Synchronous Serial Enable
	ptr = (DWORD*)m_hSSP3;
	ptr += (SSCR0_3_OFFSET / sizeof(DWORD));
	*ptr |= (0x1 << 7); // GPIO 81 set to output
	DEBUGMSG(1,(TEXT("SSCR0_3 = 0x%8x \r\n"),*ptr));

	// Enable SSP Clock 
	ptr = (DWORD*)m_hCKEN;
	*ptr |= (0x1 << 4);	

	UnmapAddress(m_hSSP3);
	UnmapAddress(m_hCKEN);
	UnmapAddress(m_hGPIO);

	DEBUGMSG(1,(TEXT(" InitNSSP: - \r\n")));

	return ;
}

#define	MEMORY_SIZE					0x10000  // 64kiB memory space; max allocation for VirtualAlloc is 64MiB

/////////////////////////////////////////////
// MapAddress 
//  Maps the desired memory address.
//  This function should be called first and its
//  return value is then passed to the ReadData16 or
//  WriteData16 functions as the baseAddress.
//
// [I] baseAddress - base address to map
// [O] Virtual Address pointer to mapped region
// 
/////////////////////////////////////////////
LPVOID MapAddress(DWORD baseAddress)
{
	LPVOID pAddr = VirtualAlloc(0, MEMORY_SIZE, MEM_RESERVE, PAGE_NOACCESS);
	
	if(pAddr)	
	{
		if(VirtualCopy (pAddr, (PVOID)(baseAddress >> 8), 
				MEMORY_SIZE, PAGE_PHYSICAL|PAGE_READWRITE|PAGE_NOCACHE) == TRUE) 
		{
				DEBUGMSG(1, (_T("0x%08x mapped to: 0x%08x\r\n"), baseAddress, pAddr));
		}
		else 
		{
			RETAILMSG(1, (_T("Error! at VirtualCopy()\r\n")));

			return NULL;
		}
	}
	else 
	{
		RETAILMSG(1, (_T("Error! at VirtualAlloc()\r\n")));
		return NULL;
	}

	return pAddr;
}

void UnmapAddress(LPVOID address)
{
	VirtualFree(address, 0, MEM_RELEASE);
	address = NULL;
}

