Ejemplo n.º 1
0
Archivo: spid.c Proyecto: gstroe/Arm
//------------------------------------------------------------------------------
/// Initializes the Spid structure and the corresponding SPI hardware.
/// Always returns 0.
/// \param pSpid  Pointer to a Spid instance.
/// \param pSpiHw  Associated SPI peripheral.
/// \param spiId  SPI peripheral identifier.
//------------------------------------------------------------------------------
unsigned char SPID_Configure(Spid *pSpid, AT91S_SPI *pSpiHw,
							 unsigned char spiId)
{
	// Initialize the SPI structure
	pSpid->pSpiHw = pSpiHw;
	pSpid->spiId  = spiId;
	pSpid->semaphore = 1;
	pSpid->pCurrentCommand = 0;

	// Enable the SPI clock
	WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << pSpid->spiId));

	// Execute a software reset of the SPI twice
	WRITE_SPI(pSpiHw, SPI_CR, AT91C_SPI_SWRST);
	WRITE_SPI(pSpiHw, SPI_CR, AT91C_SPI_SWRST);

	// Configure SPI in Master Mode with No CS selected !!!
	WRITE_SPI(pSpiHw, SPI_MR, AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | AT91C_SPI_PCS);

	// Disable the PDC transfer
	WRITE_SPI(pSpiHw, SPI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);

	// Enable the SPI
	WRITE_SPI(pSpiHw, SPI_CR, AT91C_SPI_SPIEN);

	// Enable the SPI clock
	WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << pSpid->spiId));

	return 0;
}
Ejemplo n.º 2
0
Archivo: spid.c Proyecto: gstroe/Arm
//------------------------------------------------------------------------------
/// The SPI_Handler must be called by the SPI Interrupt Service Routine with the
/// corresponding Spi instance.
/// The SPI_Handler will unlock the Spi semaphore and invoke the upper application
/// callback.
/// \param pSpid  Pointer to a Spid instance.
//------------------------------------------------------------------------------
void SPID_Handler(Spid *pSpid)
{
	SpidCmd *pSpidCmd = pSpid->pCurrentCommand;
	AT91S_SPI *pSpiHw = pSpid->pSpiHw;
	volatile unsigned int spiSr;

	// Read the status register
	spiSr = READ_SPI(pSpiHw, SPI_SR);

	if (spiSr & AT91C_SPI_RXBUFF) {
		// Disable transmitter and receiver
		WRITE_SPI(pSpiHw, SPI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);

		// Disable the SPI clock
		WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << pSpid->spiId));

		// Disable buffer complete interrupt
		WRITE_SPI(pSpiHw, SPI_IDR, AT91C_SPI_RXBUFF);

		// Release the dataflash semaphore
		pSpid->semaphore++;

		// Invoke the callback associated with the current command
		if (pSpidCmd && pSpidCmd->callback)

			pSpidCmd->callback(0, pSpidCmd->pArgument);

		// Nothing must be done after. A new DF operation may have been started
		// in the callback function.
	}
}
Ejemplo n.º 3
0
//------------------------------------------------------------------------------
/// Initializes a MCI driver instance and the underlying peripheral.
/// \param pMci  Pointer to a MCI driver instance.
/// \param pMciHw  Pointer to a MCI peripheral.
/// \param mciId  MCI peripheral identifier.
/// \param mode  Slot and type of connected card.
//------------------------------------------------------------------------------
void MCI_Init(
    Mci *pMci,
    AT91S_MCI *pMciHw,
    unsigned char mciId,
    unsigned int mode)
{
    unsigned short clkDiv;

    SANITY_CHECK(pMci);
    SANITY_CHECK(pMciHw);
    SANITY_CHECK((mode == MCI_MMC_SLOTA) || (mode == MCI_MMC_SLOTB)
                 || (mode == MCI_SD_SLOTA) || (mode == MCI_SD_SLOTB));

    // Initialize the MCI driver structure
    pMci->pMciHw = pMciHw;
    pMci->mciId  = mciId;
    pMci->semaphore = 1;
    pMci->pCommand = 0;

    // Enable the MCI clock
    WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << mciId));

    // Reset the MCI
    WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_SWRST);

    // Disable the MCI
    WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS | AT91C_MCI_PWSDIS);

    // Disable all the interrupts
    WRITE_MCI(pMciHw, MCI_IDR, 0xFFFFFFFF);

    // Set the Data Timeout Register
    WRITE_MCI(pMciHw, MCI_DTOR, DTOR_1MEGA_CYCLES);

    // Set the Mode Register: 400KHz for MCK = 48MHz (CLKDIV = 58)
    clkDiv = (BOARD_MCK / (400000 * 2)) - 1;
    WRITE_MCI(pMciHw, MCI_MR, (clkDiv | (AT91C_MCI_PWSDIV & (0x7 << 8))));

    // Set the SDCard Register
    WRITE_MCI(pMciHw, MCI_SDCR, mode);

    // Enable the MCI and the Power Saving
    WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIEN);

    // Disable the MCI peripheral clock.
    WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << mciId));
}
Ejemplo n.º 4
0
Archivo: spid.c Proyecto: gstroe/Arm
//------------------------------------------------------------------------------
/// Starts a SPI master transfer. This is a non blocking function. It will
/// return as soon as the transfer is started.
/// Returns 0 if the transfer has been started successfully; otherwise returns
/// SPID_ERROR_LOCK is the driver is in use, or SPID_ERROR if the command is not
/// valid.
/// \param pSpid  Pointer to a Spid instance.
/// \param pCommand Pointer to the SPI command to execute.
//------------------------------------------------------------------------------
unsigned char SPID_SendCommand(Spid *pSpid, SpidCmd *pCommand)
{
	AT91S_SPI *pSpiHw = pSpid->pSpiHw;
	unsigned int spiMr;

	// Try to get the dataflash semaphore
	if (pSpid->semaphore == 0)

		return SPID_ERROR_LOCK;

	pSpid->semaphore--;

	// Enable the SPI clock
	WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << pSpid->spiId));

	// Disable transmitter and receiver
	WRITE_SPI(pSpiHw, SPI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);

	// Write to the MR register
	spiMr = READ_SPI(pSpiHw, SPI_MR);
	spiMr |= AT91C_SPI_PCS;
	spiMr &= ~((1 << pCommand->spiCs) << 16);
	WRITE_SPI(pSpiHw, SPI_MR, spiMr);

	// Initialize the two SPI PDC buffer
	WRITE_SPI(pSpiHw, SPI_RPR, (int) pCommand->pCmd);
	WRITE_SPI(pSpiHw, SPI_RCR, pCommand->cmdSize);
	WRITE_SPI(pSpiHw, SPI_TPR, (int) pCommand->pCmd);
	WRITE_SPI(pSpiHw, SPI_TCR, pCommand->cmdSize);

	WRITE_SPI(pSpiHw, SPI_RNPR, (int) pCommand->pData);
	WRITE_SPI(pSpiHw, SPI_RNCR, pCommand->dataSize);
	WRITE_SPI(pSpiHw, SPI_TNPR, (int) pCommand->pData);
	WRITE_SPI(pSpiHw, SPI_TNCR, pCommand->dataSize);

	// Initialize the callback
	pSpid->pCurrentCommand = pCommand;

	// Enable transmitter and receiver
	WRITE_SPI(pSpiHw, SPI_PTCR, AT91C_PDC_RXTEN | AT91C_PDC_TXTEN);

	// Enable buffer complete interrupt
	WRITE_SPI(pSpiHw, SPI_IER, AT91C_SPI_RXBUFF);

	return 0;
}
Ejemplo n.º 5
0
//------------------------------------------------------------------------------
/// Close a MCI driver instance and the underlying peripheral.
/// \param pMci  Pointer to a MCI driver instance.
/// \param pMciHw  Pointer to a MCI peripheral.
/// \param mciId  MCI peripheral identifier.
//------------------------------------------------------------------------------
void MCI_Close(Mci *pMci)
{
    AT91S_MCI *pMciHw = pMci->pMciHw;

    SANITY_CHECK(pMci);
    SANITY_CHECK(pMciHw);

    // Initialize the MCI driver structure
    pMci->semaphore = 1;
    pMci->pCommand = 0;

    // Disable the MCI peripheral clock.
    WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << pMci->mciId));

    // Disable the MCI
    WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS);

    // Disable all the interrupts
    WRITE_MCI(pMciHw, MCI_IDR, 0xFFFFFFFF);
}
Ejemplo n.º 6
0
//------------------------------------------------------------------------------
/// Starts a MCI  transfer. This is a non blocking function. It will return
/// as soon as the transfer is started.
/// Return 0 if successful; otherwise returns MCI_ERROR_LOCK if the driver is
/// already in use.
/// \param pMci  Pointer to an MCI driver instance.
/// \param pCommand  Pointer to the command to execute.
//------------------------------------------------------------------------------
unsigned char MCI_SendCommand(Mci *pMci, MciCmd *pCommand)
{
    AT91PS_MCI pMciHw = pMci->pMciHw;
    unsigned int mciIer, mciMr;

    SANITY_CHECK(pMci);
    SANITY_CHECK(pMciHw);
    SANITY_CHECK(pCommand);

    // Try to acquire the MCI semaphore
    if (pMci->semaphore == 0) {

        return MCI_ERROR_LOCK;
    }
    pMci->semaphore--;
    // trace_LOG(trace_DEBUG, "MCI_SendCommand %x %d\n\r", READ_MCI(pMciHw, MCI_SR), pCommand->cmd & 0x3f);

    // Command is now being executed
    pMci->pCommand = pCommand;
    pCommand->status = MCI_STATUS_PENDING;

    // Enable the MCI clock
    WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << pMci->mciId));

    //Disable MCI clock, for multi-block data transfer
    MCI_Enable(pMci, DISABLE);

    // Set PDC data transfer direction
    if(pCommand->blockSize > 0) {
        if(pCommand->isRead) {
            WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTEN);
        }
        else {
            WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_TXTEN);
        }
    }
    // Disable transmitter and receiver
    WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);

    mciMr = READ_MCI(pMciHw, MCI_MR) & (~(AT91C_MCI_BLKLEN | AT91C_MCI_PDCMODE));

    // Command with DATA stage
    if (pCommand->blockSize > 0) {
        // Enable PDC mode and set block size
        if(pCommand->conTrans != MCI_CONTINUE_TRANSFER) {

            WRITE_MCI(pMciHw, MCI_MR, mciMr | AT91C_MCI_PDCMODE | (pCommand->blockSize << 16));
        }

        // DATA transfer from card to host
        if (pCommand->isRead) {
            WRITE_MCI(pMciHw, MCI_RPR, (int) pCommand->pData);

            // If Multiblock command set the BLKR register
            /* if (pCommand->nbBlock > 1) {
                WRITE_MCI(pMciHw, MCI_BLKR, pCommand->nbBlock | (pCommand->blockSize << 16));
            }
            else {
                WRITE_MCI(pMciHw, MCI_BLKR, (pCommand->blockSize << 16));
            }*/

            // Sanity check
            if (pCommand->nbBlock == 0)
                pCommand->nbBlock = 1;
            ////////
            if ((pCommand->blockSize & 0x3) != 0) {
                WRITE_MCI(pMciHw, MCI_RCR, (pCommand->nbBlock * pCommand->blockSize) / 4 + 1);
            }
            else {
                WRITE_MCI(pMciHw, MCI_RCR, (pCommand->nbBlock * pCommand->blockSize) / 4);
            }

            WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTEN);
            mciIer = AT91C_MCI_ENDRX | STATUS_ERRORS;
            // mciIer = AT91C_MCI_RXBUFF | STATUS_ERRORS;
        }

        // DATA transfer from host to card
        else {
            // Sanity check
            if (pCommand->nbBlock == 0)
                pCommand->nbBlock = 1;
            WRITE_MCI(pMciHw, MCI_TPR, (int) pCommand->pData);
            // Update the PDC counter
            if ((pCommand->blockSize & 0x3) != 0) {
                WRITE_MCI(pMciHw, MCI_TCR, (pCommand->nbBlock * pCommand->blockSize) / 4 + 1);
            }
            else {
                WRITE_MCI(pMciHw, MCI_TCR, (pCommand->nbBlock * pCommand->blockSize) / 4);
            }
            // MCI_BLKE notifies the end of Multiblock command
            mciIer = AT91C_MCI_BLKE | STATUS_ERRORS;
        }
    }
    // No data transfer: stop at the end of the command
    else {
        WRITE_MCI(pMciHw, MCI_MR, mciMr);
        mciIer = AT91C_MCI_CMDRDY | STATUS_ERRORS;
    }
    // Enable MCI clock
    MCI_Enable(pMci, ENABLE);

    // Send the command
    if((pCommand->conTrans != MCI_CONTINUE_TRANSFER)
            || (pCommand->blockSize == 0)) {

        WRITE_MCI(pMciHw, MCI_ARGR, pCommand->arg);
        WRITE_MCI(pMciHw, MCI_CMDR, pCommand->cmd);
    }

    // In case of transmit, the PDC shall be enabled after sending the command
    if ((pCommand->blockSize > 0) && !(pCommand->isRead)) {
        WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_TXTEN);
    }

    // Ignore data error
//    if (pCommand->blockSize == 0) {
    {
        mciIer &= ~(AT91C_MCI_UNRE | AT91C_MCI_OVRE \
                    | AT91C_MCI_DTOE | AT91C_MCI_DCRCE);
    }

    // Interrupt enable shall be done after PDC TXTEN and RXTEN
    WRITE_MCI(pMciHw, MCI_IER, mciIer);

    return 0;
}