Пример #1
0
/**
 * \brief Send instrucion over SPI or QSPI
 *
 * \param qspi  Pointer to an Qspi instance.
 *
 * \return Returns 1 if At least one instruction end has been detected since the last read of QSPI_SR.; otherwise
 * returns 0.
 */
extern void QSPI_SendFrame( Qspi* qspi, qspiFrame *pFrame, AccesType  ReadWrite)
{  
    uint32_t regIFR, regICR, DummyRead;
    uint32_t *pQspiBuffer = (uint32_t *)QSPIMEM_ADDR;

    assert((qspi->QSPI_MR) & QSPI_MR_SMM);

    regIFR = (pFrame->spiMode | QSPI_IFR_INSTEN | (pFrame->OptionLen << QSPI_IFR_OPTL_Pos) | (pFrame->DummyCycles << QSPI_IFR_NBDUM_Pos)  | (pFrame->ContinuousRead << 14)) ;
    // Write the instruction to reg
    regICR = ( QSPI_ICR_OPT(pFrame->Option) | QSPI_ICR_INST(pFrame->Instruction));

    if(pFrame->OptionEn)
    {
        regIFR|=QSPI_IFR_OPTEN;
    }

    /* Instruction frame without Data, only Instruction**/  
    if(!(pFrame->DataSize))               
    {
        if(pFrame->InstAddrFlag)                            // If contain Address, put in IAr reg        
        {
            qspi->QSPI_IAR = pFrame->InstAddr;
            regIFR |= QSPI_IFR_ADDREN;
        }    
        qspi->QSPI_ICR = regICR;                            //  update Instruction code reg
        qspi->QSPI_IFR = regIFR;                            // Instruction Frame reg 
    }
    else  /* Instruction frame with Data and Instruction**/
    {    
        regIFR |= QSPI_IFR_DATAEN;    
        if(ReadWrite)
        {
            regIFR |= QSPI_IFR_TFRTYP_TRSFR_WRITE;      
            qspi->QSPI_ICR = regICR;
            qspi->QSPI_IFR = regIFR ;
            DummyRead =  qspi->QSPI_IFR;                        // to synchronize system bus accesses   
            if(pFrame->InstAddrFlag)
            {
                pQspiBuffer +=  pFrame->InstAddr;
            }
            memcpy(pQspiBuffer  ,pFrame->pData,  pFrame->DataSize); 
        } 
        else
        {      
            qspi->QSPI_ICR = regICR;
            qspi->QSPI_IFR = regIFR ;
            DummyRead =  qspi->QSPI_IFR;                        // to synchronize system bus accesses   
            memcpy(pFrame->pData,  pQspiBuffer,  pFrame->DataSize); 
        }

    }
    memory_barrier();
    qspi->QSPI_CR = QSPI_CR_LASTXFER;                     // End transmission after all data has been sent
    while(!(qspi->QSPI_SR & QSPI_SR_INSTRE));             // poll CR reg to know status if Intrustion has end



}
Пример #2
0
/**
 * \brief Send instrucion over SPI or QSPI
 *
 * \param qspi  Pointer to an Qspi instance.
 *
 * \return Returns 1 if At least one instruction end has been detected since the last read of QSPI_SR.; otherwise
 * returns 0.
 */
extern void QSPI_SendFrameToMem( Qspi* qspi, qspiFrame *pFrame, AccesType  ReadWrite)
{
    uint32_t regIFR, regICR, DummyRead ;
    uint8_t *pQspiMem = (uint8_t *)QSPIMEM_ADDR;

    assert((qspi->QSPI_MR) & QSPI_MR_SMM);  

    regIFR = (pFrame->spiMode | QSPI_IFR_INSTEN | QSPI_IFR_DATAEN | QSPI_IFR_ADDREN | (pFrame->OptionLen << QSPI_IFR_OPTL_Pos) | (pFrame->DummyCycles << QSPI_IFR_NBDUM_Pos) | (pFrame->ContinuousRead << 14)) ;
    // Write the instruction to reg
    regICR = ( QSPI_ICR_OPT(pFrame->Option) | QSPI_ICR_INST(pFrame->Instruction));
    if(pFrame->OptionEn)
    {
        regIFR|=QSPI_IFR_OPTEN;
    }
    pQspiMem +=  pFrame->InstAddr;
    if(ReadWrite)
    {   
        regIFR |= QSPI_IFR_TFRTYP_TRSFR_WRITE_MEMORY;
        memory_barrier();
        qspi->QSPI_ICR = regICR;
        qspi->QSPI_IFR = regIFR ;
        DummyRead =  qspi->QSPI_IFR;                // to synchronize system bus accesses  

        memcpy(pQspiMem  ,pFrame->pData,  pFrame->DataSize); 

    }
    else
    {
        regIFR |= QSPI_IFR_TFRTYP_TRSFR_READ_MEMORY;
        memory_barrier();
        qspi->QSPI_ICR = regICR;
        qspi->QSPI_IFR = regIFR ;
        DummyRead =  qspi->QSPI_IFR;                                                // to synchronize system bus accesses 
        memcpy(pFrame->pData, pQspiMem , pFrame->DataSize);   //  Read QSPI AHB memory space 

    } 
    memory_barrier();
    qspi->QSPI_CR = QSPI_CR_LASTXFER;             // End transmission after all data has been sent
    while(!(qspi->QSPI_SR & QSPI_SR_INSTRE));     // poll CR reg to know status if Intrustion has end

}
Пример #3
0
bool qspi_perform_command(Qspi *qspi, const struct _qspi_cmd *cmd)
{
	uint32_t iar, icr, ifr;
	uint32_t offset;
	uint8_t *ptr;

	iar = 0;
	icr = 0;
	ifr = (cmd->ifr_width & QSPI_IFR_WIDTH_Msk) | (cmd->ifr_type & QSPI_IFR_TFRTYP_Msk);

	/* Compute address parameters */
	switch (cmd->enable.address) {
	case 4:
		ifr |= QSPI_IFR_ADDRL_32_BIT;
		/* fallback to the 24-bit address case */
	case 3:
		iar = (cmd->enable.data) ? 0 : QSPI_IAR_ADDR(cmd->address);
		ifr |= QSPI_IFR_ADDREN;
		offset = cmd->address;
		break;
	case 0:
		offset = 0;
		break;
	default:
		return false;
	}

	/* Compute instruction parameters */
	if (cmd->enable.instruction) {
		icr |= QSPI_ICR_INST(cmd->instruction);
		ifr |= QSPI_IFR_INSTEN;
	}

	/* Compute option parameters */
	if (cmd->enable.mode && cmd->num_mode_cycles) {
		uint32_t mode_cycle_bits, mode_bits;

		icr |= QSPI_ICR_OPT(cmd->mode);
		ifr |= QSPI_IFR_OPTEN;

		switch (ifr & QSPI_IFR_WIDTH_Msk) {
		case QSPI_IFR_WIDTH_SINGLE_BIT_SPI:
		case QSPI_IFR_WIDTH_DUAL_OUTPUT:
		case QSPI_IFR_WIDTH_QUAD_OUTPUT:
			mode_cycle_bits = 1;
			break;
		case QSPI_IFR_WIDTH_DUAL_IO:
		case QSPI_IFR_WIDTH_DUAL_CMD:
			mode_cycle_bits = 2;
			break;
		case QSPI_IFR_WIDTH_QUAD_IO:
		case QSPI_IFR_WIDTH_QUAD_CMD:
			mode_cycle_bits = 4;
			break;
		default:
			return false;
		}

		mode_bits = cmd->num_mode_cycles * mode_cycle_bits;
		switch (mode_bits) {
		case 1:
			ifr |= QSPI_IFR_OPTL_OPTION_1BIT;
			break;

		case 2:
			ifr |= QSPI_IFR_OPTL_OPTION_2BIT;
			break;

		case 4:
			ifr |= QSPI_IFR_OPTL_OPTION_4BIT;
			break;

		case 8:
			ifr |= QSPI_IFR_OPTL_OPTION_8BIT;
			break;

		default:
			return false;
		}
	}

	/* Set number of dummy cycles */
	if (cmd->enable.dummy)
		ifr |= QSPI_IFR_NBDUM(cmd->num_dummy_cycles);
	else
		ifr |= QSPI_IFR_NBDUM(0);

	/* Set data enable */
	if (cmd->enable.data) {
		ifr |= QSPI_IFR_DATAEN;

		/* Special case for Continous Read Mode */
		if (!cmd->tx_buffer && !cmd->rx_buffer)
			ifr |= QSPI_IFR_CRM_ENABLED;
	}

	/* Set QSPI Instruction Frame registers */
	qspi->QSPI_IAR = iar;
	qspi->QSPI_ICR = icr;
	qspi->QSPI_IFR = ifr;

	/* Skip to the final steps if there is no data */
	if (!cmd->enable.data)
		goto no_data;

	/* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */
	(void)qspi->QSPI_IFR;

	/* Send/Receive data */
	if (cmd->tx_buffer) {
		/* Write data */
#ifdef CONFIG_HAVE_AESB
		if(cmd->use_aesb)
			ptr = (uint8_t*)get_qspi_aesb_mem_from_addr(qspi);
		else
#endif
			ptr = (uint8_t*)get_qspi_mem_from_addr(qspi);

		qspi_memcpy(ptr + offset, cmd->tx_buffer, cmd->buffer_len);
	} else if (cmd->rx_buffer) {
		/* Read data */
#ifdef CONFIG_HAVE_AESB
		if (cmd->use_aesb)
			ptr = (uint8_t*)get_qspi_aesb_mem_from_addr(qspi);
		else
#endif
			ptr = (uint8_t*)get_qspi_mem_from_addr(qspi);

		qspi_memcpy(cmd->rx_buffer, ptr + offset, cmd->buffer_len);
	} else {
		/* Stop here for continuous read */
		return true;
	}

no_data:
	/* Release the chip-select */
	qspi->QSPI_CR = QSPI_CR_LASTXFER;

	/* Wait for INSTRuction End */
	struct _timeout timeout;
	timer_start_timeout(&timeout, cmd->timeout);
	while (!(qspi->QSPI_SR & QSPI_SR_INSTRE)) {
		if (timer_timeout_reached(&timeout)) {
			trace_debug("qspi_perform_command timeout reached\r\n");
			return false;
		}
	}

	return true;
}
Пример #4
0
/**
 * \brief Configures instruction register with a given command for QSPI
 *
 * \param pQspi   Pointer to a Qspi instance.
 * \param dwInst  Instruction Code
 * \param dwOpt   Instruction Code option
 */
__STATIC_INLINE void QSPI_SetInst(Qspi *pQspi, uint8_t dwInst, uint8_t dwOpt)
{
	assert(pQspi);
	pQspi->QSPI_ICR = (dwInst | QSPI_ICR_OPT(dwOpt));
}