/*FUNCTION**************************************************************** * * Function Name : _dspi_polled_ioctl * Returned Value : MQX error code * Comments : * This function performs miscellaneous services for * the SPI I/O device. * *END*********************************************************************/ uint_32 _dspi_polled_ioctl ( /* [IN] The address of the device specific information */ DSPI_INFO_STRUCT_PTR io_info_ptr, /* [IN] The command to perform */ uint_32 cmd, /* [IN] Parameters for the command */ uint_32_ptr param_ptr, /* [IN] Opening flags */ uint_32 flags ) { VDSPI_REG_STRUCT_PTR dspi_ptr; SPI_CS_CALLBACK_STRUCT_PTR callbacks; uint_32 val, num; uint_32 result = SPI_OK; SPI_READ_WRITE_STRUCT_PTR rw_ptr; dspi_ptr = io_info_ptr->DSPI_PTR; switch (cmd) { case IO_IOCTL_SPI_GET_BAUD: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { val = dspi_ptr->CTAR[0]; val = (BAUDRATE_PRESCALER[DSPI_CTAR_PBR_GET(val)] * BAUDRATE_SCALER[DSPI_CTAR_BR_GET(val)]) >> ((val & DSPI_CTAR_DBR_MASK) != 0); *param_ptr = (uint_32)((io_info_ptr->INIT.CLOCK_SPEED) / val); } break; case IO_IOCTL_SPI_SET_BAUD: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else if (0 == (*param_ptr)) { result = SPI_ERROR_BAUD_RATE_INVALID; } else { /* Disable SPI module */ dspi_ptr->MCR |= DSPI_MCR_HALT_MASK; /* Read current settings and clear those to be changed */ val = dspi_ptr->CTAR[0]; val &= ~(DSPI_CTAR_PBR_MASK | DSPI_CTAR_BR_MASK | DSPI_CTAR_DBR_MASK); val &= ~(DSPI_CTAR_PCSSCK_MASK | DSPI_CTAR_CSSCK_MASK); val &= ~(DSPI_CTAR_PASC_MASK | DSPI_CTAR_ASC_MASK); val &= ~(DSPI_CTAR_PDT_MASK | DSPI_CTAR_DT_MASK); /* Calculate dividers */ val |= _dspi_find_baudrate (io_info_ptr->INIT.CLOCK_SPEED, *param_ptr); /* Write settins to register */ dspi_ptr->CTAR[0] = val; /* Re-enable SPI module */ dspi_ptr->MCR &= (~ DSPI_MCR_HALT_MASK); } break; case IO_IOCTL_SPI_DEVICE_DISABLE: dspi_ptr->MCR |= DSPI_MCR_HALT_MASK; break; case IO_IOCTL_SPI_DEVICE_ENABLE: dspi_ptr->MCR &= (~ DSPI_MCR_HALT_MASK); break; case IO_IOCTL_SPI_GET_MODE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { if (dspi_ptr->CTAR[0] & DSPI_CTAR_CPOL_MASK) { if (dspi_ptr->CTAR[0] & DSPI_CTAR_CPHA_MASK) { *param_ptr = SPI_CLK_POL_PHA_MODE3; } else { *param_ptr = SPI_CLK_POL_PHA_MODE2; } } else { if (dspi_ptr->CTAR[0] & DSPI_CTAR_CPHA_MASK) { *param_ptr = SPI_CLK_POL_PHA_MODE1; } else { *param_ptr = SPI_CLK_POL_PHA_MODE0; } } } break; case IO_IOCTL_SPI_SET_MODE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { /* Disable SPI module */ dspi_ptr->MCR |= DSPI_MCR_HALT_MASK; switch (*param_ptr) { case (SPI_CLK_POL_PHA_MODE0): /* Inactive state of SPI_CLK = logic 0 */ dspi_ptr->CTAR[0] &= (~ DSPI_CTAR_CPOL_MASK); /* SPI_CLK transitions middle of bit timing */ dspi_ptr->CTAR[0] &= (~ DSPI_CTAR_CPHA_MASK); break; case (SPI_CLK_POL_PHA_MODE1): /* Inactive state of SPI_CLK = logic 0 */ dspi_ptr->CTAR[0] &= (~ DSPI_CTAR_CPOL_MASK); /* SPI_CLK transitions begining of bit timing */ dspi_ptr->CTAR[0] |= DSPI_CTAR_CPHA_MASK; break; case (SPI_CLK_POL_PHA_MODE2): /* Inactive state of SPI_CLK = logic 1 */ dspi_ptr->CTAR[0] |= DSPI_CTAR_CPOL_MASK; /* SPI_CLK transitions middle of bit timing */ dspi_ptr->CTAR[0] &= (~ DSPI_CTAR_CPHA_MASK); break; case (SPI_CLK_POL_PHA_MODE3): /* Inactive state of SPI_CLK = logic 1 */ dspi_ptr->CTAR[0] |= DSPI_CTAR_CPOL_MASK; /* SPI_CLK transitions begining of bit timing */ dspi_ptr->CTAR[0] |= DSPI_CTAR_CPHA_MASK; break; default: result = SPI_ERROR_MODE_INVALID; break; } /* Enable SPI module */ dspi_ptr->MCR &= (~ DSPI_MCR_HALT_MASK); } break; case IO_IOCTL_SPI_GET_TRANSFER_MODE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { if (dspi_ptr->MCR & DSPI_MCR_MSTR_MASK) { *param_ptr = SPI_DEVICE_MASTER_MODE; } else { *param_ptr = SPI_DEVICE_SLAVE_MODE; } } break; case IO_IOCTL_SPI_SET_TRANSFER_MODE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { /* Disable SPI module */ dspi_ptr->MCR |= DSPI_MCR_HALT_MASK; /* Set transfer mode */ if (*param_ptr == SPI_DEVICE_SLAVE_MODE) { dspi_ptr->MCR &= (~ DSPI_MCR_MSTR_MASK); } else if (*param_ptr == SPI_DEVICE_MASTER_MODE) { dspi_ptr->MCR |= DSPI_MCR_MSTR_MASK; } else { result = SPI_ERROR_TRANSFER_MODE_INVALID; } /* Enable SPI module */ dspi_ptr->MCR &= (~ DSPI_MCR_HALT_MASK); } break; case IO_IOCTL_SPI_GET_ENDIAN: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else if (dspi_ptr->CTAR[0] & DSPI_CTAR_LSBFE_MASK) { *param_ptr = SPI_DEVICE_LITTLE_ENDIAN; } else { *param_ptr = SPI_DEVICE_BIG_ENDIAN; } break; case IO_IOCTL_SPI_SET_ENDIAN: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else if (! (dspi_ptr->MCR & DSPI_MCR_MSTR_MASK)) { result = SPI_ERROR_ENDIAN_INVALID; } else if (*param_ptr == SPI_DEVICE_LITTLE_ENDIAN) { dspi_ptr->CTAR[0] |= DSPI_CTAR_LSBFE_MASK; } else if (*param_ptr == SPI_DEVICE_BIG_ENDIAN) { dspi_ptr->CTAR[0] &= (~ DSPI_CTAR_LSBFE_MASK); } else { result = SPI_ERROR_ENDIAN_INVALID; } break; case IO_IOCTL_SPI_GET_STATS: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { *((SPI_STATISTICS_STRUCT_PTR)param_ptr) = io_info_ptr->STATS; } break; case IO_IOCTL_SPI_CLEAR_STATS: io_info_ptr->STATS.INTERRUPTS = 0; io_info_ptr->STATS.RX_PACKETS = 0; io_info_ptr->STATS.RX_OVERFLOWS = 0; io_info_ptr->STATS.TX_PACKETS = 0; io_info_ptr->STATS.TX_ABORTS = 0; io_info_ptr->STATS.TX_UNDERFLOWS= 0; break; case IO_IOCTL_FLUSH_OUTPUT: case IO_IOCTL_SPI_FLUSH_DEASSERT_CS: while ((io_info_ptr->RX_COUNT) || (io_info_ptr->TX_COUNT) || (io_info_ptr->DMA_FLAGS)) {}; // waiting for completion if ((0 == (flags & SPI_FLAG_NO_DEASSERT_ON_FLUSH)) || (IO_IOCTL_SPI_FLUSH_DEASSERT_CS == cmd)) { /* Deassert all chip selects */ if (dspi_ptr->MCR & DSPI_MCR_MSTR_MASK) { _dspi_polled_cs(io_info_ptr, 0); dspi_ptr->MCR |= DSPI_MCR_HALT_MASK; dspi_ptr->MCR &= (~ DSPI_MCR_MSTR_MASK); dspi_ptr->MCR |= DSPI_MCR_MSTR_MASK; dspi_ptr->MCR &= (~ DSPI_MCR_HALT_MASK); } } break; case IO_IOCTL_SPI_GET_FRAMESIZE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { *param_ptr = DSPI_CTAR_FMSZ_GET(dspi_ptr->CTAR[0]) + 1; } break; case IO_IOCTL_SPI_SET_FRAMESIZE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { /* Disable SPI module */ dspi_ptr->MCR |= DSPI_MCR_HALT_MASK; dspi_ptr->CTAR[0] &= (~ (DSPI_CTAR_FMSZ(0x0F))); dspi_ptr->CTAR[0] |= DSPI_CTAR_FMSZ(*param_ptr - 1); /* Enable SPI module */ dspi_ptr->MCR &= (~ DSPI_MCR_HALT_MASK); } break; case IO_IOCTL_SPI_GET_CS: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { *param_ptr = DSPI_PUSHR_PCS(io_info_ptr->CS); } break; case IO_IOCTL_SPI_SET_CS: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { io_info_ptr->CS = DSPI_PUSHR_PCS_GET(*param_ptr); } break; case IO_IOCTL_SPI_ENABLE_MODF: result = MQX_IO_OPERATION_NOT_AVAILABLE; break; case IO_IOCTL_SPI_DISABLE_MODF: break; case IO_IOCTL_SPI_SET_CS_CALLBACK: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { callbacks = (SPI_CS_CALLBACK_STRUCT_PTR)(param_ptr); for (num = 0; num < DSPI_CS_COUNT; num++) { if (0 != (callbacks->MASK & (DSPI_PUSHR_PCS(1 << num)))) { io_info_ptr->CS_CALLBACK[num] = callbacks->CALLBACK; io_info_ptr->CS_USERDATA[num] = callbacks->USERDATA; } } } break; case IO_IOCTL_SPI_READ_WRITE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { rw_ptr = (SPI_READ_WRITE_STRUCT_PTR)param_ptr; _dspi_polled_tx_rx (io_info_ptr, (uint_8_ptr)(rw_ptr->WRITE_BUFFER), (uint_8_ptr)(rw_ptr->READ_BUFFER), rw_ptr->BUFFER_LENGTH); } break; case IO_IOCTL_SPI_KEEP_QSPI_CS_ACTIVE: result = MQX_IO_OPERATION_NOT_AVAILABLE; break; default: result = IO_ERROR_INVALID_IOCTL_CMD; break; } return result; }
/*FUNCTION**************************************************************** * * Function Name : _dspi_polled_ioctl * Returned Value : MQX error code * Comments : * This function performs miscellaneous services for * the SPI I/O device. * *END*********************************************************************/ uint_32 _dspi_polled_ioctl ( /* [IN] The address of the device specific information */ DSPI_INFO_STRUCT_PTR io_info_ptr, /* [IN] The command to perform */ uint_32 cmd, /* [IN] Parameters for the command */ uint_32_ptr param_ptr, /* [IN] Opening flags */ uint_32 flags ) { SPI_MemMapPtr dspi_ptr; SPI_CS_CALLBACK_STRUCT_PTR callbacks; uint_32 val, num, size, command; uint_32 result = SPI_OK; SPI_READ_WRITE_STRUCT_PTR rw_ptr; uchar_ptr input, output; dspi_ptr = io_info_ptr->DSPI_PTR; switch (cmd) { case IO_IOCTL_SPI_GET_BAUD: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { val = dspi_ptr->CTAR[0]; val = BAUDRATE_PRESCALER[SPI_CTAR_PBR_GET(val)] * BAUDRATE_SCALER[SPI_CTAR_BR_GET(val)]; *param_ptr = (uint_32)((io_info_ptr->INIT.CLOCK_SPEED) / val); } break; case IO_IOCTL_SPI_SET_BAUD: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else if (0 == (*param_ptr)) { result = SPI_ERROR_BAUD_RATE_INVALID; } else { val = _dspi_find_baudrate (io_info_ptr->INIT.CLOCK_SPEED, *param_ptr); /* Disable SPI module */ dspi_ptr->MCR |= SPI_MCR_HALT_MASK; /* Set the frequency divider */ dspi_ptr->CTAR[0] &= (~ (SPI_CTAR_PBR(0x0F) | SPI_CTAR_BR(0x0F))); dspi_ptr->CTAR[0] |= val; /* Enable SPI module */ dspi_ptr->MCR &= (~ SPI_MCR_HALT_MASK); } break; case IO_IOCTL_SPI_DEVICE_DISABLE: dspi_ptr->MCR |= SPI_MCR_HALT_MASK; break; case IO_IOCTL_SPI_DEVICE_ENABLE: dspi_ptr->MCR &= (~ SPI_MCR_HALT_MASK); break; case IO_IOCTL_SPI_GET_MODE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { if (dspi_ptr->CTAR[0] & SPI_CTAR_CPOL_MASK) { if (dspi_ptr->CTAR[0] & SPI_CTAR_CPHA_MASK) { *param_ptr = SPI_CLK_POL_PHA_MODE3; } else { *param_ptr = SPI_CLK_POL_PHA_MODE2; } } else { if (dspi_ptr->CTAR[0] & SPI_CTAR_CPHA_MASK) { *param_ptr = SPI_CLK_POL_PHA_MODE1; } else { *param_ptr = SPI_CLK_POL_PHA_MODE0; } } } break; case IO_IOCTL_SPI_SET_MODE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { /* Disable SPI module */ dspi_ptr->MCR |= SPI_MCR_HALT_MASK; switch (*param_ptr) { case (SPI_CLK_POL_PHA_MODE0): /* Inactive state of SPI_CLK = logic 0 */ dspi_ptr->CTAR[0] &= (~ SPI_CTAR_CPOL_MASK); /* SPI_CLK transitions middle of bit timing */ dspi_ptr->CTAR[0] &= (~ SPI_CTAR_CPHA_MASK); break; case (SPI_CLK_POL_PHA_MODE1): /* Inactive state of SPI_CLK = logic 0 */ dspi_ptr->CTAR[0] &= (~ SPI_CTAR_CPOL_MASK); /* SPI_CLK transitions begining of bit timing */ dspi_ptr->CTAR[0] |= SPI_CTAR_CPHA_MASK; break; case (SPI_CLK_POL_PHA_MODE2): /* Inactive state of SPI_CLK = logic 1 */ dspi_ptr->CTAR[0] |= SPI_CTAR_CPOL_MASK; /* SPI_CLK transitions middle of bit timing */ dspi_ptr->CTAR[0] &= (~ SPI_CTAR_CPHA_MASK); break; case (SPI_CLK_POL_PHA_MODE3): /* Inactive state of SPI_CLK = logic 1 */ dspi_ptr->CTAR[0] |= SPI_CTAR_CPOL_MASK; /* SPI_CLK transitions begining of bit timing */ dspi_ptr->CTAR[0] |= SPI_CTAR_CPHA_MASK; break; default: result = SPI_ERROR_MODE_INVALID; break; } /* Enable SPI module */ dspi_ptr->MCR &= (~ SPI_MCR_HALT_MASK); } break; case IO_IOCTL_SPI_GET_TRANSFER_MODE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { if (dspi_ptr->MCR & SPI_MCR_MSTR_MASK) { *param_ptr = SPI_DEVICE_MASTER_MODE; } else { *param_ptr = SPI_DEVICE_SLAVE_MODE; } } break; case IO_IOCTL_SPI_SET_TRANSFER_MODE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { /* Disable SPI module */ dspi_ptr->MCR |= SPI_MCR_HALT_MASK; /* Set transfer mode */ if (*param_ptr == SPI_DEVICE_SLAVE_MODE) { dspi_ptr->MCR &= (~ SPI_MCR_MSTR_MASK); } else if (*param_ptr == SPI_DEVICE_MASTER_MODE) { dspi_ptr->MCR |= SPI_MCR_MSTR_MASK; } else { result = SPI_ERROR_TRANSFER_MODE_INVALID; } /* Enable SPI module */ dspi_ptr->MCR &= (~ SPI_MCR_HALT_MASK); } break; case IO_IOCTL_SPI_GET_ENDIAN: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else if (dspi_ptr->CTAR[0] & SPI_CTAR_LSBFE_MASK) { *param_ptr = SPI_DEVICE_LITTLE_ENDIAN; } else { *param_ptr = SPI_DEVICE_BIG_ENDIAN; } break; case IO_IOCTL_SPI_SET_ENDIAN: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else if (! (dspi_ptr->MCR & SPI_MCR_MSTR_MASK)) { result = SPI_ERROR_ENDIAN_INVALID; } else if (*param_ptr == SPI_DEVICE_LITTLE_ENDIAN) { dspi_ptr->CTAR[0] |= SPI_CTAR_LSBFE_MASK; } else if (*param_ptr == SPI_DEVICE_BIG_ENDIAN) { dspi_ptr->CTAR[0] &= (~ SPI_CTAR_LSBFE_MASK); } else { result = SPI_ERROR_ENDIAN_INVALID; } break; case IO_IOCTL_SPI_GET_STATS: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { *((SPI_STATISTICS_STRUCT_PTR)param_ptr) = io_info_ptr->STATS; } break; case IO_IOCTL_SPI_CLEAR_STATS: io_info_ptr->STATS.INTERRUPTS = 0; io_info_ptr->STATS.RX_PACKETS = 0; io_info_ptr->STATS.RX_OVERFLOWS = 0; io_info_ptr->STATS.TX_PACKETS = 0; io_info_ptr->STATS.TX_ABORTS = 0; io_info_ptr->STATS.TX_UNDERFLOWS= 0; break; case IO_IOCTL_FLUSH_OUTPUT: case IO_IOCTL_SPI_FLUSH_DEASSERT_CS: while ((0 != io_info_ptr->RECEIVING) || (0 != io_info_ptr->ONTHEWAY) || (dspi_ptr->RSER & SPI_RSER_TFFF_RE_MASK)) {}; // waiting for completion if ((0 == (flags & SPI_FLAG_NO_DEASSERT_ON_FLUSH)) || (IO_IOCTL_SPI_FLUSH_DEASSERT_CS == cmd)) { /* Deassert all chip selects */ if (dspi_ptr->MCR & SPI_MCR_MSTR_MASK) { for (num = 0; num < DSPI_CS_COUNT; num++) { if ((NULL != io_info_ptr->CS_CALLBACK[num]) && (0 != (io_info_ptr->CS_ACTIVE & (1 << num)))) { io_info_ptr->CS_CALLBACK[num] (SPI_PUSHR_PCS(1 << num), 1, io_info_ptr->CS_USERDATA[num]); } } io_info_ptr->CS_ACTIVE = 0; dspi_ptr->RSER &= (~ SPI_RSER_RFDF_RE_MASK); val = (uint_32)-1; _dspi_polled_tx_rx (io_info_ptr, (uchar_ptr)&val, TRUE, 0); dspi_ptr->RSER |= SPI_RSER_RFDF_RE_MASK; } } break; case IO_IOCTL_SPI_GET_FRAMESIZE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { *param_ptr = SPI_CTAR_FMSZ_GET(dspi_ptr->CTAR[0]) + 1; } break; case IO_IOCTL_SPI_SET_FRAMESIZE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { /* Disable SPI module */ dspi_ptr->MCR |= SPI_MCR_HALT_MASK; dspi_ptr->CTAR[0] &= (~ (SPI_CTAR_FMSZ(0x0F))); dspi_ptr->CTAR[0] |= SPI_CTAR_FMSZ(*param_ptr - 1); /* Enable SPI module */ dspi_ptr->MCR &= (~ SPI_MCR_HALT_MASK); } break; case IO_IOCTL_SPI_GET_CS: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { *param_ptr = SPI_PUSHR_PCS(io_info_ptr->CS); } break; case IO_IOCTL_SPI_SET_CS: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { io_info_ptr->CS = SPI_PUSHR_PCS_GET(*param_ptr); } break; case IO_IOCTL_SPI_ENABLE_MODF: result = MQX_IO_OPERATION_NOT_AVAILABLE; break; case IO_IOCTL_SPI_DISABLE_MODF: break; case IO_IOCTL_SPI_SET_CS_CALLBACK: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { callbacks = (SPI_CS_CALLBACK_STRUCT_PTR)(param_ptr); for (num = 0; num < DSPI_CS_COUNT; num++) { if (0 != (callbacks->MASK & (SPI_PUSHR_PCS(1 << num)))) { io_info_ptr->CS_CALLBACK[num] = callbacks->CALLBACK; io_info_ptr->CS_USERDATA[num] = callbacks->USERDATA; } } } break; case IO_IOCTL_SPI_READ_WRITE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { rw_ptr = (SPI_READ_WRITE_STRUCT_PTR)param_ptr; command = SPI_PUSHR_CONT_MASK | SPI_PUSHR_PCS(io_info_ptr->CS); size = rw_ptr->BUFFER_LENGTH; input = (uchar_ptr)rw_ptr->WRITE_BUFFER; output = (uchar_ptr)rw_ptr->READ_BUFFER; for (num = 0; num < size; num++) { val = _dspi_polled_tx_rx (io_info_ptr, input, TRUE, command); if (SPI_CTAR_FMSZ_GET(dspi_ptr->CTAR[0]) > 7) { output[0] = (uint_8)(val >> 8); output++; input++; } output[0] = (uint_8)val; output++; input++; io_info_ptr->STATS.RX_PACKETS++; io_info_ptr->STATS.TX_PACKETS++; } } break; case IO_IOCTL_SPI_KEEP_QSPI_CS_ACTIVE: result = MQX_IO_OPERATION_NOT_AVAILABLE; break; default: result = IO_ERROR_INVALID_IOCTL_CMD; break; }