/*

 *            Copyright (c) 1998-2004 by NETsilicon Inc.

 *

 *  This software is copyrighted by and is the sole property of

 *  NETsilicon.  All rights, title, ownership, or other interests

 *  in the software remain the property of NETsilicon.  This

 *  software may only be used in accordance with the corresponding

 *  license agreement.  Any unauthorized use, duplication, transmission,

 *  distribution, or disclosure of this software is expressly forbidden.

 *

 *  This Copyright notice may not be removed or modified without prior

 *  written consent of NETsilicon.

 *

 *  NETsilicon, reserves the right to modify this software

 *  without notice.

 *

 *  NETsilicon

 *  411 Waverley Oaks Road                  USA 781.647.1234

 *  Suite 227                               http://www.netsilicon.com

 *  Waltham, MA 02452                       AmericaSales@netsilicon.com

 *

 */



#include <string.h>

#include <stdlib.h>

#include <errno.h>

#include <tx_port.h>

#include <semaphore.h>

#include <ddi.h>

#include <netosIo.h>

#include <reg_def.h>



#include <serParam.h>



#include "netos_spi.h"

#include <NA_ISR.h>

#include <Dma_def.h>

#include <sysClock.h>

#include <reg_def.h>

#include <bool.h>

#include <tx_api.h>

#include <ncc_init.h>

#include "spi_mod.h"



/* #define IMPROVE_SPEED       1 */



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

 **********************************************************************************

 ***                                                                            ***

 *** Function Name:  OptSet()                                                   ***

 ***                                                                            ***

 *** Called by:      onccInitChannel()                                          ***

 ***                                                                            ***

 *** Comments: This routine sets up the hardware (serial Control Register A)    ***

 **********************************************************************************

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

static void OptSet( const ONSPI_CHAN * pChan)

{

 



    UINT32 reg;

     

    SER_REG (pChan->port, CTRL_REGA) = 0;               /* reset port */

    reg = SER_CHANNEL_ENABLE | CTRL_EIGHT_BITS;         /* channel is always enabled with 8 bits*/

    SER_REG (pChan->port, CTRL_REGA) = reg;



}



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

 **********************************************************************************

 ***                                                                            ***

 *** Function Name:  setCtrRebB                                                 ***

 ***                                                                            ***

 *** Called by:      onspiInitChannel()                                         ***

 ***                                                                            ***

 *** Comments:  Hardware initialization Control Register B                      ***

 **********************************************************************************

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

static void setCtrRebB (ONSPI_CHAN * pChan)



{

    UINT32 reg;



    if (pChan->slaveMode)

    {

    	reg = SPI_SLAVE_MODE_VALUE;

    }

    else

    {

    	reg = SPI_MASTER_MODE_VALUE;

    }



    if (pChan->LSBfirst)

	reg &= ~SPI_MSB_FIRST_VALUE;

    else

	reg |= SPI_MSB_FIRST_VALUE;



    SER_REG (pChan->port, CTRL_REGB) = reg;

     

}

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

 **********************************************************************************

 ***                                                                            ***

 *** Function Name:  setABCreg                                                  ***



 ***                                                                            ***

 *** Called by:      onspiInitChannel()                                         ***

 ***                                                                            ***

 *** Comments:  Hardware initialization PORTA, PORTB, and PORTC registry        ***

 **********************************************************************************

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

static void setABCreg (ONSPI_CHAN * pChan)



{

    if (pChan->port == 0)

    {

		if (narm_read_reg(NARM_GSSR_REG, NARM_GSSR_ADDR, rev) >= NETA20UM)

		{

			if (pChan->slaveMode)

			{

				*NARM_PORTA_ADDR = SPI_20UM_PORTA_SLAVE;

			 

			}

			else

			{

				*NARM_PORTA_ADDR = SPI_20UM_PORTA_MASTER;

			}

		}

		else

		{

			/* Prepare mask for port C */

			*NARM_PORTC_ADDR &= PORTC_CHA_MASK;

			/* And port A */

			*NARM_PORTA_ADDR &= PORTAB_MASK;

	

			if (pChan->slaveMode)

			{

				*NARM_PORTA_ADDR |= PORTAB_SLAVE_VALUE;

				*NARM_PORTC_ADDR |= PORTC_CHA_SLAVE_VALUE;

			}

			else

			{

				if (pChan->blockSEL && chipRevision < 0X19) /* Netarm 40 use PORTA4 for SEL */

					*NARM_PORTA_ADDR |=PORTAB_BLICKSEL_VALUE;

				else

					*NARM_PORTA_ADDR |= PORTAB_MASTER_VALUE;



				if (!pChan->blockSEL || chipRevision < 0X19) /* Netarm 50 use PORTC for SEL */

				*NARM_PORTC_ADDR |= PORTC_CHA_MASTER_VALUE;

	    

			}

		}

    }

    else

    {

		if (narm_read_reg(NARM_GSSR_REG, NARM_GSSR_ADDR, rev) >= NETA20UM)

		{

			if (pChan->slaveMode)

			{

				*NARM_PORTC_ADDR = SPI_20UM_PORTC_SLAVE;

			 

			}

			else

			{

				*NARM_PORTC_ADDR = SPI_20UM_PORTC_MASTER;

			}

		}

		else

		{

			/* Prepare mask for port C */  

			*NARM_PORTC_ADDR &= PORTC_CHB_MASK;



			/* And port B */



			*NARM_PORTB_ADDR &= PORTAB_MASK;

	

			if (pChan->slaveMode)

			{

				*NARM_PORTB_ADDR |= PORTAB_SLAVE_VALUE;

				*NARM_PORTC_ADDR |= PORTC_CHB_SLAVE_VALUE;

			}

			else

			{

				if (pChan->blockSEL && chipRevision < 0X19) /* Netarm 40 use PORTB4 for SEL */

					*NARM_PORTB_ADDR |=PORTAB_BLICKSEL_VALUE;

				else

					*NARM_PORTB_ADDR |= PORTAB_MASTER_VALUE;



				if (!pChan->blockSEL || chipRevision < 0X19) /* Netarm 50 use PORTC for SEL */

					*NARM_PORTC_ADDR |= PORTC_CHB_MASTER_VALUE;

			}

		}

    }

  

#if 0

    /* PORTC0 used for timing set it HI */

    *NARM_PORTC_ADDR |= 4;

     reg = *NARM_PORTC_ADDR;

     reg = *NARM_PORTB_ADDR;

     reg = *NARM_PORTA_ADDR;

#endif

   

}



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

 **********************************************************************************

 ***                                                                            ***

 *** Function Name:  blockABCreg                                                ***

 ***                                                                            ***

 *** Called by:      onspiInitChannel()                                         ***

 ***                                                                            ***

 *** Comments:  Block output signal for PORTA, PORTB, and PORTC registry        ***

 ***            by setting all port as a normal input. setABCreg will set a     ***

 ***            correct value for this regesters                                ***

 **********************************************************************************

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

static void blockABCreg (ONSPI_CHAN * pChan)



{

    if (pChan->port == 0)

    {

		if (narm_read_reg(NARM_GSSR_REG, NARM_GSSR_ADDR, rev) >= NETA20UM)

		{

			*NARM_PORTA_ADDR = GPIO_PORT_IS_NOT_USED;

		}

		else

		{

			*NARM_PORTA_ADDR &= PORTAB_MASK;

			*NARM_PORTC_ADDR &= PORTC_CHA_MASK;

		}

    }

	 

    else

    {

		if (narm_read_reg(NARM_GSSR_REG, NARM_GSSR_ADDR, rev) >= NETA20UM)

		{

			*NARM_PORTC_ADDR = GPIO_PORT_IS_NOT_USED;

		}

		else

		{

			*NARM_PORTB_ADDR &= PORTAB_MASK;

			*NARM_PORTC_ADDR &= PORTC_CHB_MASK;

		}

    }

}



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

 **********************************************************************************

 ***                                                                            ***

 *** Function Name:  onspiInitChannel()                                         ***

 ***                                                                            ***

 *** Called by:      SpiDevInit()                                               ***

 ***                                                                            ***

 *** Comments:  Hardware initialization of the NCC serial channel.              ***

 **********************************************************************************

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



void onspiInitChannel (ONSPI_CHAN * pChan, bool initSeq)

{

    if (initSeq)

	blockABCreg(pChan); /* Prevent form sending out signals before all registries are set */

     

    /*** Control Register A Configuration ***/

    /* Enable the serial channel */

    SER_REG (pChan->port, CTRL_REGA) = 0;  /* init ctrl reg, this turns off ints */



    /*** Control Register B Configuration ***/

    /* Match timer features are not used */

    SER_REG (pChan->port, CTRL_REGB) = 0;

    SER_REG (pChan->port, RECV_CHAR_TIMER_REG) = 0;

    SER_REG (pChan->port, RECV_BUF_TIMER_REG) = 0;



    /*** Receive Match Register Configuration ***/

    SER_REG (pChan->port, RECV_MATCH_REG) = 0;



     /*** Receive Buffer Gap Timer Register Configuration ***/

    SER_REG (pChan->port, RECV_BUF_TIMER_REG) = 0;



    /*** Receive Character Timer Register Configuration ***/

#ifdef IMPROVE_SPEED

{

    UINT32 reg;



    reg = get_char_gap_count (pChan->baudRate);

    SER_REG (pChan->port, RECV_CHAR_TIMER_REG) = ENABLE_TIMER | reg;

}

#else

    SER_REG (pChan->port, RECV_CHAR_TIMER_REG) = 0;

#endif





    SER_REG (pChan->port, BAUD_REG) = 0;





     /*** Control Register B Configuration ***/

    setCtrRebB(pChan);



    setBitRate(pChan); /*** Bit-Rate (baud) Register Configuration ***/

     

    

   

    OptSet(pChan);    /* go set up options in Reg A */



    chipRevision = narm_read_reg(NARM_GSSR_REG, NARM_GSSR_ADDR, rev);



    /*

     * At this point registries for the serial port are configure

     * GPIO registries A, B, and C are configure as none special functions in the 

     * input mode

     * As the result all output signals from the SPI module are blocked.

     * netos_spiopen will configure everything

     * as it should be 

    */

    if (!initSeq)

	 setABCreg(pChan);

    

}



/*

 * Function: spiResetChannel ()

 *

 * Description: reset serial port registry.

 *              This routine will disable all interrupts.

 *              When called from all routines but waitForCompletion, it will restart serial port.

 *

 * Called by: waitForCompletion, onspiInitChannel,

 *            netos_spiwrite,netos_spiread sendWriteEnable, sendEEPROMCommand

 *

 * Input : pChan - pointer to the channel description

 *         resetPort - true if require to restart serial port

 *

 *

 */



void spiResetChannel (const ONSPI_CHAN *pChan, const bool resetPort )

{

/* reset serial port registries */

    if (resetPort)

	OptSet(pChan);

    else

	SER_REG (pChan->port, CTRL_REGA) &= REGA_INTFLAGS_MASK;

    

/* disable all serial interrupts */

    NADisableIsr (pChan->rxlevel);

    NADisableIsr (pChan->txlevel);

    NADisableIsr (pChan->txDmalevel);

    NADisableIsr (pChan->rxDmalevel);

    if (pChan->ISRlevel != -1)

	NADisableIsr(pChan->ISRlevel);

    

}







