diff options
author | Gary King <gking@nvidia.com> | 2010-03-11 09:04:44 -0800 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-03-11 20:28:30 -0800 |
commit | d7410ca658ea62a51163655f000cf20c640c76f9 (patch) | |
tree | cb3821cc28bd1df23ec18a98d8cc05a430ad6df8 /arch | |
parent | 01ba7d51e2e9456c1a99b2454553259edd09d373 (diff) |
serial: delete tegra DDK serial driver
this driver is no longer being used, and its continued existence
just causes confusion.
Change-Id: Ia5b4a350b6590bbd0e8914625e9e81951096fb8c
Reviewed-on: http://git-master/r/843
Reviewed-by: John Davis <jodavis@nvidia.com>
Reviewed-by: Gary King <gking@nvidia.com>
Tested-by: Gary King <gking@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/nvddk/Makefile | 3 | ||||
-rw-r--r-- | arch/arm/mach-tegra/nvddk/ap15ddk_uart_hw_private.c | 965 | ||||
-rw-r--r-- | arch/arm/mach-tegra/nvddk/ddkuart_hw_private.h | 390 | ||||
-rw-r--r-- | arch/arm/mach-tegra/nvddk/nvddk_uart.c | 2834 |
4 files changed, 0 insertions, 4192 deletions
diff --git a/arch/arm/mach-tegra/nvddk/Makefile b/arch/arm/mach-tegra/nvddk/Makefile index 15a897de16bf..347675bb74cb 100644 --- a/arch/arm/mach-tegra/nvddk/Makefile +++ b/arch/arm/mach-tegra/nvddk/Makefile @@ -19,8 +19,5 @@ endif obj-$(CONFIG_KEYBOARD_TEGRA) += nvddk_kbc.o obj-$(CONFIG_MTD_NAND_TEGRA) += nvddk_nand.o -obj-$(CONFIG_SERIAL_TEGRA_DDK) += nvddk_uart.o -obj-$(CONFIG_SERIAL_TEGRA_DDK) += ap15ddk_uart_hw_private.o - obj-$(CONFIG_MMC_TEGRA_SDIO) += nvddk_sdio.o obj-$(CONFIG_TEGRA_SNOR) += nvsnor_controller.o diff --git a/arch/arm/mach-tegra/nvddk/ap15ddk_uart_hw_private.c b/arch/arm/mach-tegra/nvddk/ap15ddk_uart_hw_private.c deleted file mode 100644 index 8d4320ec94f9..000000000000 --- a/arch/arm/mach-tegra/nvddk/ap15ddk_uart_hw_private.c +++ /dev/null @@ -1,965 +0,0 @@ -/* - * Copyright (c) 2007-2009 NVIDIA Corporation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NVIDIA Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @file - * @brief <b>nVIDIA Driver Development Kit: - * Private functions for the uart hw access</b> - * - * @b Description: Implements the private interfacing functions for the uart - * hw interface. - * - */ - -#include "nvrm_drf.h" -#include "ddkuart_hw_private.h" -#include "nvrm_hardware_access.h" -#include "nvassert.h" - -// hardware includes -#include "ap15/aruart.h" - -// Allowed uart baud rate accuracy in percent. As per theory, it should be 5% -enum {UART_BAUDRATE_ACCURACY = 5}; - -#define UART_REG_READ32(pUartHwRegsVirtBaseAdd, reg) \ - NV_READ32((pUartHwRegsVirtBaseAdd) + ((UART_##reg##_0)/4)) - -#define UART_REG_WRITE32(pUartHwRegsVirtBaseAdd, reg, val) \ - do { \ - NV_WRITE32((((pUartHwRegsVirtBaseAdd) + ((UART_##reg##_0)/4))), (val)); \ - } while (0) - -#define IS_POSSIBLE_RX_ERROR (NV_DRF_DEF(UART, LSR, BRK, BREAK) | \ - NV_DRF_DEF(UART, LSR, FIFOE, ERR) | \ - NV_DRF_DEF(UART, LSR, FERR, FRAME_ERR) | \ - NV_DRF_DEF(UART, LSR, OVRF, OVERRUN_ERROR) | \ - NV_DRF_DEF(UART, LSR, PERR, PARITY_ERR)) - -#define IS_DATA_IN_FIFO NV_DRF_DEF(UART, LSR, RDR, DATA_IN_FIFO) - -#define TX_EMPTY_STATUS (NV_DRF_DEF(UART, LSR, TMTY, EMPTY) | \ - NV_DRF_DEF(UART, LSR, THRE, EMPTY)) - -/** - * Initialize the uart register. - */ -void NvDdkPrivUartHwRegisterInitialize(NvU32 CommChannelId, UartHwRegisters *pUartHwRegs) -{ - // Initialize the member of Uart hw register structure. - pUartHwRegs->ModemSignalSatus = 0; - pUartHwRegs->IsRtsHwFlowSupported = NV_FALSE; - pUartHwRegs->IsEndOfDataIntSupport = NV_FALSE; - - pUartHwRegs->FcrRegister = 0; - pUartHwRegs->IerRegister = 0; - pUartHwRegs->LcrRegister = 0; - pUartHwRegs->McrRegister = 0; - pUartHwRegs->DllRegister = 0; - pUartHwRegs->DlmRegister = 0; - - pUartHwRegs->IsDmaMode = NV_TRUE; - pUartHwRegs->pRegsVirtBaseAdd = NULL; - pUartHwRegs->ChannelId = CommChannelId; - pUartHwRegs->RegsPhyBaseAdd = 0; - pUartHwRegs->BankSize = 0; - pUartHwRegs->TransmitTrigLevel = 1; - pUartHwRegs->IsRtsActive = NV_FALSE; - pUartHwRegs->IsDtrActive = NV_FALSE; -} - -/** - * Initialize the uart fifos. - */ -void NvDdkPrivUartHwInitFifo(UartHwRegisters *pUartHwRegs) -{ - pUartHwRegs->FcrRegister = NV_DRF_DEF(UART, IIR_FCR, FCR_EN_FIFO, ENABLE); - NvDdkPrivUartHwResetFifo(pUartHwRegs, UartDataDirection_Both); - NvDdkPrivUartHwSetFifoTriggerLevel(pUartHwRegs, UartDataDirection_Both, 4); - NvDdkPrivUartHwUpdateModemSignal(pUartHwRegs); - NvDdkPrivUartHwSetModemSignal(pUartHwRegs, NvDdkUartSignalName_Rts, NV_FALSE); - } - -/** - * Get the clock frequency required related to the baud rate. - */ -void -NvDdkPrivUartHwGetReqdClockSourceFreq( - NvU32 BaudRate, - NvU32 *pMinClockFreqReqd, - NvU32 *pClockFreqReqd, - NvU32 *pMaxClockFreqReqd) -{ - NvU32 MaxClockFreqReq = 0; - NvU32 MinClockFreqReq = 0; - NvU32 ClockFreqReqd = 0; - - *pMinClockFreqReqd = 1; - *pClockFreqReqd = 1; - *pMaxClockFreqReqd = 1; - - // Required clock frequency in KHz. - // Required clock freq is 16 times of the required baudrate. - ClockFreqReqd = (BaudRate *16)/1000; - if (!ClockFreqReqd) - ClockFreqReqd = 1; - - // Minimum clock frequency required, -5% - MinClockFreqReq = (NvU32)NvDiv64(((100 - UART_BAUDRATE_ACCURACY)* (NvU64)BaudRate *16), (1000*100)); - if (!MinClockFreqReq) - MinClockFreqReq = 1; - - // Maximum clock frequency required, +5% - MaxClockFreqReq = (NvU32)NvDiv64(((100 + UART_BAUDRATE_ACCURACY)* (NvU64)BaudRate *16),(1000*100)); - if (MaxClockFreqReq <= ClockFreqReqd) - MaxClockFreqReq = ClockFreqReqd + 1; - - *pMinClockFreqReqd = MinClockFreqReq; - *pClockFreqReqd = ClockFreqReqd; - *pMaxClockFreqReqd = MaxClockFreqReq; -} - -/** - * Set the baud rate of uart communication. - */ -NvError -NvDdkPrivUartHwSetBaudRate( - UartHwRegisters *pUartHwRegs, - NvU32 BaudRate, - NvU32 ClockSourceFreq) -{ - NvU32 BaudRateConstant; - - // Calculated baud rate constant for 5% boundary. - NvU32 CalcBRL; - NvU32 CalcBRH; - - // boundary of the baudrate. - NvU32 BR_Dev_L; - NvU32 BR_Dev_H; - - NvU32 ClockFreq; - - // Final baud rate constant. - NvU32 FinalBaudRateConstant = 0; - NvU32 BaudrateDll; - NvU32 BaudrateDlm; - NvU32 LcrValue; - - // Get the upper and lower baud rate constant calculation. - BR_Dev_L = (BaudRate - (BaudRate * UART_BAUDRATE_ACCURACY)/100); - BR_Dev_H = (BaudRate + (BaudRate * UART_BAUDRATE_ACCURACY)/100); - - // Search the clock source which gives the proper baud rate constant - // for given baud rate. - // Get the baud rate constant for given clock frequency. - ClockFreq = ClockSourceFreq*1000; - BaudRateConstant = (ClockFreq /(BaudRate*16)); - - // If baud rate constant is becoming 0 then it will not be possible to set - // the baud rate. - if (!BaudRateConstant) - return NvError_NotSupported; - - // Get the baud rate with calculated baud rate constant and +1. - CalcBRH = (ClockFreq)/(BaudRateConstant *16); - CalcBRL = (ClockFreq)/((BaudRateConstant+1) *16); - - // If calculated low baud rate is in up/down 5 percent baudrates then - // we have got the correct clock source. - if ((CalcBRL >= BR_Dev_L) && (CalcBRL <= BR_Dev_H)) - FinalBaudRateConstant = BaudRateConstant+1; - else if ((CalcBRH >= BR_Dev_L) && (CalcBRH <= BR_Dev_H)) - FinalBaudRateConstant = BaudRateConstant; - else - return NvError_NotSupported; - - // Get the lower byte and upper byte of the baud rate constant. - BaudrateDll = FinalBaudRateConstant & 0xFF; - BaudrateDlm = (FinalBaudRateConstant >> 8) & 0xFF; - - pUartHwRegs->DllRegister = BaudrateDll; - pUartHwRegs->DlmRegister = BaudrateDlm; - - // Enable the LCR-DLAB. - LcrValue = pUartHwRegs->LcrRegister; - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, DLAB, ENABLE, LcrValue); - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, LCR, LcrValue); - - // Program the lower and upper bytes of the baud rate constant. - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, THR_DLAB_0, BaudrateDll); - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, IER_DLAB_0, BaudrateDlm); - - // Disable the DLAB. - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, DLAB, DISABLE, LcrValue); - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, LCR, LcrValue); - return NvSuccess; -} - -/** - * Set the parity of uart communication. - */ -NvError -NvDdkPrivUartHwSetParityBit( - UartHwRegisters *pUartHwRegs, - NvDdkUartParity ParityBit) -{ - NvU32 LcrValue; - - // Get the Lcr register value and set the parity as per per requirement. - LcrValue = pUartHwRegs->LcrRegister; - switch (ParityBit) - { - case NvDdkUartParity_None: - // No parity - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, PAR, NO_PARITY, LcrValue); - break; - - case NvDdkUartParity_Odd: - // Odd parity - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, PAR, PARITY, LcrValue); - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, EVEN, DISABLE, LcrValue); - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, SET_P, NO_PARITY, LcrValue); - break; - - case NvDdkUartParity_Even: - // Even parity. - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, PAR, PARITY, LcrValue); - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, EVEN, ENABLE, LcrValue); - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, SET_P, NO_PARITY, LcrValue); - break; - - default: - // Unknown type of parameter. - return NvError_NotSupported; - } - - pUartHwRegs->LcrRegister = LcrValue; - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, LCR, LcrValue); - return NvSuccess; -} - -/** - * Set the data length of uart communication. - */ -NvError -NvDdkPrivUartHwSetDataLength( - UartHwRegisters *pUartHwRegs, - NvU32 DataLength) -{ - NvU32 LcrValue; - - // Get the lcr register value. - LcrValue = pUartHwRegs->LcrRegister; - if (DataLength == 5) - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, WD_SIZE, WORD_LENGTH_5, LcrValue); - else if (DataLength == 6) - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, WD_SIZE, WORD_LENGTH_6, LcrValue); - else if (DataLength == 7) - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, WD_SIZE, WORD_LENGTH_7, LcrValue); - else if (DataLength == 8) - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, WD_SIZE, WORD_LENGTH_8, LcrValue); - else - return NvError_NotSupported; - - pUartHwRegs->LcrRegister = LcrValue; - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, LCR, LcrValue); - return NvSuccess; -} - -/** - * Set the stop bit of uart communication. - */ -NvError NvDdkPrivUartHwSetStopBit( - UartHwRegisters *pUartHwRegs, - NvDdkUartStopBit StopBit) -{ - NvU32 LcrValue; - - // Get the lcr register value and configured for the stop bit. - LcrValue = pUartHwRegs->LcrRegister; - if (StopBit == NvDdkUartStopBit_1) - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, STOP, DISABLE, LcrValue); - else if ((StopBit == NvDdkUartStopBit_1_5) || (StopBit == NvDdkUartStopBit_2)) - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, STOP, ENABLE, LcrValue); - else - return NvError_NotSupported; - pUartHwRegs->LcrRegister = LcrValue; - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, LCR, LcrValue); - return NvSuccess; -} - -/** - * Start/stop sending the break control signal. - */ -void NvDdkPrivUartHwSetBreakControlSignal( - UartHwRegisters *pUartHwRegs, - NvBool IsStart) -{ - NvU32 LcrValue; - // Get the lcr register value and configured the break send control bit. - LcrValue = pUartHwRegs->LcrRegister; - if (IsStart) - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, SET_B, BREAK, LcrValue); - else - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, SET_B, NO_BREAK, LcrValue); - pUartHwRegs->LcrRegister = LcrValue; - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, LCR, LcrValue); -} - -/** - * Reset the uart fifo register. - */ -void -NvDdkPrivUartHwResetFifo( - UartHwRegisters *pUartHwRegs, - UartDataDirection FifoType) -{ - NvU32 FcrValue; - - // Get the Fcr register value. - FcrValue = pUartHwRegs->FcrRegister; - - // Get the fifo type whether receive and transmit fifo. - // Reset the rx or tx fifo. - if (FifoType & UartDataDirection_Receive) - FcrValue = NV_FLD_SET_DRF_DEF(UART, IIR_FCR, RX_CLR, CLEAR, FcrValue); - - if (FifoType & UartDataDirection_Transmit) - FcrValue = NV_FLD_SET_DRF_DEF(UART, IIR_FCR, TX_CLR, CLEAR, FcrValue); - - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, IIR_FCR, FcrValue); -} - -/** - * Set the fifo trigger level of uart fifo. - */ -void -NvDdkPrivUartHwSetFifoTriggerLevel( - UartHwRegisters *pUartHwRegs, - UartDataDirection FifoType, - NvU32 TriggerLevel) -{ - NvU32 FcrValue; - - // Get the fcr register value and configured for the receive and transmit - // fifo trigger level. - FcrValue = pUartHwRegs->FcrRegister; - FcrValue = NV_FLD_SET_DRF_DEF(UART, IIR_FCR, FCR_EN_FIFO, ENABLE, FcrValue); - - // If it is receive fifo then configure the rx trigger value. - if (FifoType & UartDataDirection_Receive) - { - switch (TriggerLevel) - { - case 1: - FcrValue = NV_FLD_SET_DRF_DEF(UART, IIR_FCR, RX_TRIG, - FIFO_COUNT_GREATER_1, FcrValue); - break; - - case 4: - FcrValue = NV_FLD_SET_DRF_DEF(UART, IIR_FCR, RX_TRIG, - FIFO_COUNT_GREATER_4, FcrValue); - break; - - case 8: - // Fix me ar issue - FcrValue = NV_FLD_SET_DRF_DEF(UART, IIR_FCR, RX_TRIG, - FIFO_COUNT_GREATER_8, FcrValue); - break; - - default: - // Fix me ar issue - FcrValue = NV_FLD_SET_DRF_DEF(UART, IIR_FCR, RX_TRIG, - FIFO_COUNT_GREATER_12, FcrValue); - break; - } - } - if (FifoType & UartDataDirection_Transmit) - { - // It is for transmit fifo, configure for tx fifo trigger level. - switch (TriggerLevel) - { - case 1: - FcrValue = NV_FLD_SET_DRF_DEF(UART, IIR_FCR, TX_TRIG, - FIFO_COUNT_GREATER_1, FcrValue); - pUartHwRegs->TransmitTrigLevel = 1; - break; - - case 4: - FcrValue = NV_FLD_SET_DRF_DEF(UART, IIR_FCR, TX_TRIG, - FIFO_COUNT_GREATER_4, FcrValue); - pUartHwRegs->TransmitTrigLevel = 4; - break; - - case 8: - FcrValue = NV_FLD_SET_DRF_DEF(UART, IIR_FCR, TX_TRIG, - FIFO_COUNT_GREATER_8, FcrValue); - pUartHwRegs->TransmitTrigLevel = 8; - break; - - default: - FcrValue = NV_FLD_SET_DRF_DEF(UART, IIR_FCR, TX_TRIG, - FIFO_COUNT_GREATER_12, FcrValue); - - pUartHwRegs->TransmitTrigLevel = 12; - break; - } - } - - // If no error then write into the uart register. Also update the soft copy - // of fcr register. - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, IIR_FCR, FcrValue); - pUartHwRegs->FcrRegister = FcrValue; -} - -/** - * Set the dma mode operation of uart - */ -void NvDdkPrivUartHwSetDmaMode(UartHwRegisters *pUartHwRegs, NvBool IsEnable) -{ - NvU32 FcrValue; - - // Get the fcr register value and enable/disable the dma bit and write into - // the register. - FcrValue = pUartHwRegs->FcrRegister; - if (IsEnable) - FcrValue = NV_FLD_SET_DRF_DEF(UART, IIR_FCR, DMA, CHANGE, FcrValue); - else - FcrValue = NV_FLD_SET_DRF_DEF(UART, IIR_FCR, DMA, NO_CHANGE, FcrValue); - - pUartHwRegs->IsDmaMode = IsEnable; - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, IIR_FCR, FcrValue); - pUartHwRegs->FcrRegister = FcrValue; -} - -/** - * Write into the transmit fifo register. - * Returns the number of bytes written. - */ -NvU32 -NvDdkPrivUartHwWriteInTransmitFifo( - UartHwRegisters *pUartHwRegs, - NvU8 *pTxBuff, - NvU32 BytesRequested) -{ - NvU32 BytesToWrite; - NvU32 TransmitChar; - NvU32 DataWritten = 0; - - // This function is called once the trigger level interrupt is reach. - // Write the data same as the trigger level without checking the fifo status. - BytesToWrite = NV_MIN(BytesRequested, pUartHwRegs->TransmitTrigLevel); - - while (BytesToWrite) - { - TransmitChar = (NvU32)(*pTxBuff); - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, THR_DLAB_0, TransmitChar); - pTxBuff++; - BytesToWrite--; - DataWritten++; - } - return DataWritten; -} - -/** - * Write into the transmit fifo register. - * Returns the number of bytes written. - */ -NvU32 -NvDdkPrivUartHwPollingWriteInTransmitFifo( - UartHwRegisters *pUartHwRegs, - NvU8 *pTxBuff, - NvU32 BytesRequested) -{ - NvU32 BytesToWrite = BytesRequested; - NvU32 TransmitChar; - NvU32 LsrValue; - - while (BytesToWrite) - { - LsrValue = UART_REG_READ32(pUartHwRegs->pRegsVirtBaseAdd, LSR); - if (!(LsrValue & (NV_DRF_DEF(UART, LSR, TMTY, EMPTY)))) - break; - TransmitChar = (NvU32)(*pTxBuff); - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, THR_DLAB_0, TransmitChar); - pTxBuff++; - BytesToWrite--; - } - return (BytesRequested - BytesToWrite); -} - -/** - * Check whether the Transmit fifo is empty or not. - * Returns TRUE if the Tx fifo is empty otherwise returns FALSE. - */ -NvBool NvDdkPrivUartHwIsTransmitFifoEmpty(UartHwRegisters *pUartHwRegs) -{ - NvU32 LsrValue; - LsrValue = UART_REG_READ32(pUartHwRegs->pRegsVirtBaseAdd, LSR); - if ((LsrValue & TX_EMPTY_STATUS) == TX_EMPTY_STATUS) - return NV_TRUE; - else - return NV_FALSE; -} - -NvBool NvDdkPrivUartHwIsBreakSignalDetected(UartHwRegisters *pUartHwRegs) -{ - NvBool IsBreakDetected = NV_FALSE; - NvU32 LsrValue = UART_REG_READ32(pUartHwRegs->pRegsVirtBaseAdd, LSR); - if (LsrValue & NV_DRF_DEF(UART, LSR, BRK, BREAK)) - { - IsBreakDetected = NV_TRUE; - - // Again read the LSR and if there is fifo error with data then reset - // here - LsrValue = UART_REG_READ32(pUartHwRegs->pRegsVirtBaseAdd, LSR); - if (LsrValue & NV_DRF_DEF(UART, LSR, FIFOE, ERR)) - { - if (LsrValue & NV_DRF_DEF(UART, LSR, RDR, DATA_IN_FIFO)) - return IsBreakDetected; - - // Fifo error without rx data - NvDdkPrivUartHwResetFifo(pUartHwRegs, UartDataDirection_Receive); - } - } - - return IsBreakDetected; -} - -/** - * Read the data from the receive fifo. - */ -NvBool NvDdkPrivUartHwIsDataAvailableInFifo(UartHwRegisters *pUartHwRegs) -{ - NvU32 LsrValue = UART_REG_READ32(pUartHwRegs->pRegsVirtBaseAdd, LSR); - if (LsrValue & NV_DRF_DEF(UART, LSR, RDR, DATA_IN_FIFO)) - return NV_TRUE; - return NV_FALSE; -} - -/** - * Read the data from the receive fifo. - */ -NvError -NvDdkPrivUartHwReadFromReceiveFifo( - UartHwRegisters *pUartHwRegs, - NvU8 *pRxBuff, - NvU32 MaxByteRequested, - NvU32 *pBytesRead) -{ - NvError Error = NvSuccess; - NvU32 BytesToRead; - NvU32 LsrValue = 0; - NvU8 ReadChar; - NvU32 DataRead = 0; - - // Get how many bytes to be read. - BytesToRead = MaxByteRequested; - - // Read till bytes required to be read is there. - while (BytesToRead) - { - // Get the Line status register and check for the error. - LsrValue = UART_REG_READ32(pUartHwRegs->pRegsVirtBaseAdd, LSR); - - // Check if any type of error occurred. - if (LsrValue & IS_POSSIBLE_RX_ERROR) - { - if (LsrValue & NV_DRF_DEF(UART, LSR, OVRF, OVERRUN_ERROR)) - { - // Overrun error - Error = NvError_UartOverrun; - } - else if (LsrValue & NV_DRF_DEF(UART, LSR, PERR, PARITY_ERR)) - { - // Parity error - Error = NvError_UartParity; - } - else if (LsrValue & NV_DRF_DEF(UART, LSR, FERR, FRAME_ERR)) - { - // Framing error - Error = NvError_UartFraming; - } - else if (LsrValue & NV_DRF_DEF(UART, LSR, FIFOE, ERR)) - { - // Fifo error - Error = NvSuccess; - NvDdkPrivUartHwResetFifo(pUartHwRegs, UartDataDirection_Receive); - *pBytesRead = 0; - } - else if (LsrValue & NV_DRF_DEF(UART, LSR, BRK, BREAK)) - { - // Break signal received. - Error = NvError_UartBreakReceived; - } - break; - } - - // No error in fifo, check if data is available and if then read from - // receive fifo. - if (LsrValue & IS_DATA_IN_FIFO) - { - ReadChar = (NvU8)((UART_REG_READ32(pUartHwRegs->pRegsVirtBaseAdd, THR_DLAB_0)) & 0xFF); - *pRxBuff++ = ReadChar; - BytesToRead--; - DataRead++; - } - else - { - // Fifo is empty so exit from loop. - break; - } - } - - *pBytesRead = DataRead; - return Error; -} - -void NvDdkPrivUartHwClearAllInt(UartHwRegisters *pUartHwRegs) -{ - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, IER_DLAB_0, 0); - pUartHwRegs->IerRegister = 0; -} - -void NvDdkPrivUartHwSetReceiveInterrupt( - UartHwRegisters *pUartHwRegs, - NvBool IsEnable, - NvBool IsRxUsingApbDma) -{ - NvU32 IerValue; - - // Get the IER register value. - IerValue = pUartHwRegs->IerRegister; - - // Enable/disable the interrupt bit for the receive fifo ready and - // receive line status error. - if (IsEnable) - { - if (IsRxUsingApbDma) - { - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_RXS, ENABLE, IerValue); - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_RX_TIMEOUT, ENABLE, IerValue); - if (pUartHwRegs->IsEndOfDataIntSupport) - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_EORD, ENABLE, IerValue); - } - else - { - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_RHR, ENABLE, IerValue); - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_RXS, ENABLE, IerValue); - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_RX_TIMEOUT, ENABLE, IerValue); - } - } - else - { - if (IsRxUsingApbDma) - { - // Sw workaround to disable the rx timeout interrupt. - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_RHR, ENABLE, IerValue); - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, IER_DLAB_0, IerValue); - - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_RHR, DISABLE, IerValue); - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_RXS, DISABLE, IerValue); - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_RX_TIMEOUT, DISABLE, IerValue); - if (pUartHwRegs->IsEndOfDataIntSupport) - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_EORD, DISABLE, IerValue); - } - else - { - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_RHR, DISABLE, IerValue); - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_RXS, DISABLE, IerValue); - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_RX_TIMEOUT, DISABLE, IerValue); - } - } - pUartHwRegs->IerRegister = IerValue; - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, IER_DLAB_0, IerValue); -} - -void NvDdkPrivUartHwSetTransmitInterrupt( - UartHwRegisters *pUartHwRegs, - NvBool IsEnable) -{ - NvU32 IerValue; - // Get the IER register value. - IerValue = pUartHwRegs->IerRegister; - - // Enable/disable the transmit fifo empty - if (IsEnable) - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_THR, ENABLE, IerValue); - else - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_THR, DISABLE, IerValue); - pUartHwRegs->IerRegister = IerValue; - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, IER_DLAB_0, IerValue); -} - -void NvDdkPrivUartHwSetModemControlInterrupt( - UartHwRegisters *pUartHwRegs, - NvBool IsEnable) -{ - NvU32 IerValue; - - // Get the IER register value. - IerValue = pUartHwRegs->IerRegister; - - // Enable/disable the modem control signal. - if (IsEnable) - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_MSI, ENABLE, IerValue); - else - IerValue = NV_FLD_SET_DRF_DEF(UART, IER_DLAB_0, IE_MSI, DISABLE, IerValue); - pUartHwRegs->IerRegister = IerValue; - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, IER_DLAB_0, IerValue); -} - -/** - * Get the interrupt reason. - */ -UartHwInterruptSource -NvDdkPrivUartHwGetInterruptReason( - UartHwRegisters *pUartHwRegs) -{ - NvU32 IirValue; - NvU32 P0; - NvU32 P1; - NvU32 P2; - NvU32 InterruptValue = 0; - NvU32 InterruptSource[8] = - { - UartHwInterruptSource_ModemControl, // Modem signal change interrupt - UartHwInterruptSource_Transmit, // Transmit fifo trigger level interrupt - UartHwInterruptSource_Receive, // Rx fifo data ready interrupt - UartHwInterruptSource_ReceiveError, // Line status interrupt - UartHwInterruptSource_EndOfData, // End of data interrupt - UartHwInterruptSource_None, // Unused interrupt - UartHwInterruptSource_RxTimeout, // Rx timeout interrupt - UartHwInterruptSource_None // Unused interrupt - }; - - // Read the Iir register value. - IirValue = UART_REG_READ32(pUartHwRegs->pRegsVirtBaseAdd, IIR_FCR); - - // Check whether all the interrupt is served or not. If there is no - // pending interrupt then return none. - if (IirValue & NV_DRF_DEF(UART, IIR_FCR, IS_STA, NO_INTR_PEND)) - return UartHwInterruptSource_None; - - // Valid interrupt is there, identify the interrupt. - P0 = NV_DRF_VAL(UART, IIR_FCR, IS_PRI0, IirValue); - P1 = NV_DRF_VAL(UART, IIR_FCR, IS_PRI1, IirValue); - P2 = NV_DRF_VAL(UART, IIR_FCR, IS_PRI2, IirValue); - InterruptValue = ((P2 << 2) | (P1 <<1) | (P0)) & 0x7; - return InterruptSource[InterruptValue]; -} - -/** - * Enable/disable the Irda coding. - */ -void -NvDdkPrivUartHwSetIrdaCoding( - UartHwRegisters *pUartHwRegs, - NvBool IsEnable) -{ - NvU32 IrdaCsrValue; - - // Read data from the irda csr register. - IrdaCsrValue = pUartHwRegs->IrdaCsrRegister; - - // Enable/disable the sir modulation bit. - if (IsEnable) - IrdaCsrValue = NV_FLD_SET_DRF_DEF(UART, IRDA_CSR, SIR_A, ENABLE, IrdaCsrValue); - else - IrdaCsrValue = NV_FLD_SET_DRF_DEF(UART, IRDA_CSR, SIR_A, DISABLE, IrdaCsrValue); - - pUartHwRegs->IrdaCsrRegister = IrdaCsrValue; - // Write into the irda csr register. - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, IRDA_CSR, IrdaCsrValue); -} - -/** - * Set the output modem signal to active or inactive state. - */ -void -NvDdkPrivUartHwSetModemSignal( - UartHwRegisters *pUartHwRegs, - NvDdkUartSignalName SignalName, - NvBool IsActive) -{ - NvU32 McrValue= pUartHwRegs->McrRegister; - - if (SignalName & NvDdkUartSignalName_Rts) - { - if (IsActive != pUartHwRegs->IsRtsActive) - { - if (IsActive) - McrValue = NV_FLD_SET_DRF_DEF(UART, MCR, RTS, FORCE_RTS_LOW, McrValue); - else - McrValue = NV_FLD_SET_DRF_DEF(UART, MCR, RTS, FORCE_RTS_HI, McrValue); - pUartHwRegs->IsRtsActive = IsActive; - } - } - - if (SignalName & NvDdkUartSignalName_Dtr) - { - if (IsActive != pUartHwRegs->IsDtrActive) - { - if (IsActive) - McrValue = NV_FLD_SET_DRF_DEF(UART, MCR, DTR, FORCE_DTR_LOW, McrValue); - else - McrValue = NV_FLD_SET_DRF_DEF(UART, MCR, DTR, FORCE_DTR_HI, McrValue); - pUartHwRegs->IsDtrActive = IsActive; - } - } - - // Write the updated value into the register. - if (pUartHwRegs->McrRegister != McrValue) - { - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, MCR, McrValue); - pUartHwRegs->McrRegister = McrValue; - } - return; -} - -/** - * Read the modem signal level and update the state of the signal in the uart hw - * register structure. - */ -void NvDdkPrivUartHwUpdateModemSignal(UartHwRegisters *pUartHwRegs) -{ - NvU32 MsrValue; - - // Read the modem status register. - MsrValue = UART_REG_READ32(pUartHwRegs->pRegsVirtBaseAdd, MSR); - - // If change in CTS then update the CTS value. - if (MsrValue & (NV_DRF_DEF(UART, MSR, CTS, ENABLE))) - pUartHwRegs->ModemSignalSatus |= NvDdkUartSignalName_Cts; - else - pUartHwRegs->ModemSignalSatus &= ~NvDdkUartSignalName_Cts; - - // If change in DSR then update the DSR value. - if (MsrValue & (NV_DRF_DEF(UART, MSR, DSR, ENABLE))) - pUartHwRegs->ModemSignalSatus |= NvDdkUartSignalName_Dsr; - else - pUartHwRegs->ModemSignalSatus &= ~NvDdkUartSignalName_Dsr; - - // If change in RI then update the RI value. - if (MsrValue & (NV_DRF_DEF(UART, MSR, RI, ENABLE))) - pUartHwRegs->ModemSignalSatus |= NvDdkUartSignalName_Ri; - else - pUartHwRegs->ModemSignalSatus &= ~NvDdkUartSignalName_Ri; - - // If change in CD then update the CD value. - if (MsrValue & (NV_DRF_DEF(UART, MSR, CD, ENABLE))) - pUartHwRegs->ModemSignalSatus |= NvDdkUartSignalName_Cd; - else - pUartHwRegs->ModemSignalSatus &= ~NvDdkUartSignalName_Cd; -} - -// NV_TRUE Active: Uart can send the data -// NV_FALSE InActive: Uart can not send the data as other terminal have not -// activated its RTS line -NvBool NvDdkPrivUartHwIsCtsActive(UartHwRegisters *pUartHwRegs) -{ - NvU32 MsrValue = UART_REG_READ32(pUartHwRegs->pRegsVirtBaseAdd, MSR); - if (MsrValue & (NV_DRF_DEF(UART, MSR, CTS, ENABLE))) - return NV_TRUE; - else - return NV_FALSE; -} -/** -* Enable/disable the hw flow control for transmitting the signal. If it is -* enabled then it will only transmit the data if CTS line is Low. If the CTS -* line is high then it will not transmit the data. The controller reads the -* inverted state of the signal state from pin. -*/ -void -NvDdkPrivUartHwSetHWFlowControl( - UartHwRegisters *pUartHwRegs, - NvBool IsEnable) -{ - NvU32 McrValue; - - // Read the modem control register and configured for the CTS hw flow - // bit for the enabling/disabling the hw flow for transmit. - McrValue = pUartHwRegs->McrRegister; - - // Configired the CTS Hw flow bit. - if (IsEnable) - { - McrValue = NV_FLD_SET_DRF_DEF(UART, MCR, CTS_EN, ENABLE, McrValue); - - if (pUartHwRegs->IsRtsHwFlowSupported) - McrValue = NV_FLD_SET_DRF_DEF(UART, MCR, RTS_EN, ENABLE, McrValue); - } - else - { - McrValue = NV_FLD_SET_DRF_DEF(UART, MCR, CTS_EN, DISABLE, McrValue); - if (pUartHwRegs->IsRtsHwFlowSupported) - McrValue = NV_FLD_SET_DRF_DEF(UART, MCR, RTS_EN, DISABLE, McrValue); - } - - pUartHwRegs->McrRegister = McrValue; - - // Write into the register. - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, MCR, McrValue); -} - -void NvDdkPrivUartHwReconfigureRegisters(UartHwRegisters *pUartHwRegs) -{ - NvU32 LcrValue; - - // Fcr Register - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, IIR_FCR, pUartHwRegs->FcrRegister); - - // Lcr, DLL and DLAB registers - // Enable the LCR-DLAB. - LcrValue = pUartHwRegs->LcrRegister; - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, DLAB, ENABLE, LcrValue); - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, LCR, LcrValue); - - // Program the lower and upper bytes of the baud rate constant. - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, THR_DLAB_0, pUartHwRegs->DllRegister); - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, IER_DLAB_0, pUartHwRegs->DlmRegister); - - // Disable the DLAB. - LcrValue = NV_FLD_SET_DRF_DEF(UART, LCR, DLAB, DISABLE, LcrValue); - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, LCR, LcrValue); - - // Mcr register - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, MCR, pUartHwRegs->McrRegister); - - // Irda CSR - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, IRDA_CSR, pUartHwRegs->IrdaCsrRegister); - - // IER register - UART_REG_WRITE32(pUartHwRegs->pRegsVirtBaseAdd, IER_DLAB_0, pUartHwRegs->IerRegister); -} - diff --git a/arch/arm/mach-tegra/nvddk/ddkuart_hw_private.h b/arch/arm/mach-tegra/nvddk/ddkuart_hw_private.h deleted file mode 100644 index fe8f58dc683f..000000000000 --- a/arch/arm/mach-tegra/nvddk/ddkuart_hw_private.h +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (c) 2007-2009 NVIDIA Corporation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NVIDIA Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @file - * @brief <b>nVIDIA Driver Development Kit: - * Private functions for the uart Ddk driver</b> - * - * @b Description: Defines the private interfacing functions for the uart - * hw interface. - * - */ - -#ifndef INCLUDED_DDKUART_HW_PRIVATE_H -#define INCLUDED_DDKUART_HW_PRIVATE_H - -/** - * @defgroup nvddk_uart Universal Asynchronous Receiver Transmitter (UART) - * Controller hw interface API - * - * This is the Universal Asynchronous Receiver Transmitter (UART) hw interface - * controller api. - * - * @ingroup nvddk_modules - * @{ - * - */ - -#include "nvcommon.h" -#include "nvddk_uart.h" - -#if defined(__cplusplus) -extern "C" { -#endif - -/** - * Combines the definition of the uart register and modem signals. - */ -typedef struct UartHwRegistersRec -{ - // Channel instance Id. - NvU32 ChannelId; - - // Virtual base address of the uart hw register. - NvU32 *pRegsVirtBaseAdd; - - // Physical base address of the uart hw register. - NvRmPhysAddr RegsPhyBaseAdd; - - // Register bank size. - NvU32 BankSize; - - // Uart shadow registers to keep the s/w value of registers - - // Currently programmed Fcr register value. - NvU32 FcrRegister; - - // Currently programmed Ier register value. - NvU32 IerRegister; - - // Currently programmed Lcr register value. - NvU32 LcrRegister; - - // Currently programmed Mcr register value. - NvU32 McrRegister; - - // Currently programmed irda csr register value. - NvU32 IrdaCsrRegister; - - // Currently programmed Dlm register value. - NvU32 DlmRegister; - - // Currently programmed Dll register value. - NvU32 DllRegister; - - // Tells whether the dma mode is selected or not. - NvBool IsDmaMode; - - // Modem signal status, 1 on the particular location shows the state to high. - NvU32 ModemSignalSatus; - - // Tells whether the Rts hw flow control is supported or not - NvBool IsRtsHwFlowSupported; - - // Tells whether the end of data interrupt is supported or not - NvBool IsEndOfDataIntSupport; - - // Store the RTS line status - NvBool IsRtsActive; - - NvBool IsDtrActive; - - NvU32 TransmitTrigLevel; -} UartHwRegisters; - -/** - * Combines the uart interrupt sources. - */ -typedef enum -{ - // No Uart interrupt source. - UartHwInterruptSource_None = 0x0, - - // Receive Uart interrupt source. - UartHwInterruptSource_Receive, - - // Receive error Uart interrupt source. - UartHwInterruptSource_ReceiveError, - - // Rx timeout interrupt source. - UartHwInterruptSource_RxTimeout, - - // End of data interrupt source. - UartHwInterruptSource_EndOfData, - - // Transmit interrupt source. - UartHwInterruptSource_Transmit, - - // Modem control interrupt source. - UartHwInterruptSource_ModemControl, - - UartHwInterruptSource_Force32 = 0x7FFFFFFF -} UartHwInterruptSource; - -/** - * Combines the uart hw data direction. - */ -typedef enum -{ - // Invalid fifo type. - UartDataDirection_Invalid = 0x0, - - // Receive direction. - UartDataDirection_Receive = 0x1, - - // Transmit direction. - UartDataDirection_Transmit = 0x2, - - // Both, receive and transmit data direction. - UartDataDirection_Both = 0x3, - - UartDataDirection_Force32 = 0x7FFFFFFF -} UartDataDirection; - -/** - * Initialize the uart hw registers parameters. It does not write anything on - * the controller register. - */ -void -NvDdkPrivUartHwRegisterInitialize( - NvU32 CommChannelId, - UartHwRegisters *pUartHwRegs); -/** - * Initialize the uart fifos. - */ -void NvDdkPrivUartHwInitFifo(UartHwRegisters *pUartHwRegs); - -/** - * Get the clock source frequency required for the given baud rate. - */ -void -NvDdkPrivUartHwGetReqdClockSourceFreq( - NvU32 BaudRate, - NvU32 *pMinClockFreqReqd, - NvU32 *pClockFreqReqd, - NvU32 *pMaxClockFreqReqd); - -/** - * Set the baud rate of uart communication. - */ -NvError -NvDdkPrivUartHwSetBaudRate( - UartHwRegisters *pUartHwRegs, - NvU32 BaudRate, - NvU32 ClockSourceFreq); -/** - * Set the parity of uart communication. - */ -NvError -NvDdkPrivUartHwSetParityBit( - UartHwRegisters *pUartHwRegs, - NvDdkUartParity ParityBit); - -/** - * Set the data length of uart communication. - */ -NvError -NvDdkPrivUartHwSetDataLength( - UartHwRegisters *pUartHwRegs, - NvU32 DataLength); - -/** - * Set the stop bit of uart communication. - */ -NvError NvDdkPrivUartHwSetStopBit( - UartHwRegisters *pUartHwRegs, - NvDdkUartStopBit StopBit); - -/** - * Start/stop sending the break control signal. - */ -void NvDdkPrivUartHwSetBreakControlSignal( - UartHwRegisters *pUartHwRegs, - NvBool IsStart); - -/** - * Reset the uart fifos. - */ -void -NvDdkPrivUartHwResetFifo( - UartHwRegisters *pUartHwRegs, - UartDataDirection FifoType); - -/** - * Set the fifo trigger level of uart fifo. - */ -void -NvDdkPrivUartHwSetFifoTriggerLevel( - UartHwRegisters *pUartHwRegs, - UartDataDirection FifoType, - NvU32 TriggerLevel); - -/** - * Set the dma mode operation of uart - */ -void -NvDdkPrivUartHwSetDmaMode( - UartHwRegisters *pUartHwRegs, - NvBool IsEnable); - -/** - * Write into the transmit fifo register with the trigger level. - * This function should be call when tx trigger level is reached. - */ -NvU32 -NvDdkPrivUartHwWriteInTransmitFifo( - UartHwRegisters *pUartHwRegs, - NvU8 *pTxBuff, - NvU32 BytesRequested); - -/** - * Write into the transmit fifo register and check the fifo status before writing - * into the tx fifo. - * With every write, the fifo status will be checked. - */ -NvU32 -NvDdkPrivUartHwPollingWriteInTransmitFifo( - UartHwRegisters *pUartHwRegs, - NvU8 *pTxBuff, - NvU32 BytesRequested); - -/** - * Check whether the Transmit fiof is empty or not. - * Returns TRUE if the Tx fifo is empty otherwise returns FALSE. - */ -NvBool NvDdkPrivUartHwIsTransmitFifoEmpty(UartHwRegisters *pUartHwRegs); - -/** - * Check whether break condition is received or not. - */ -NvBool NvDdkPrivUartHwIsBreakSignalDetected(UartHwRegisters *pUartHwRegs); - -/** - * Get the Rx fifo status whether data is available in the rx fifo or not. - */ -NvBool NvDdkPrivUartHwIsDataAvailableInFifo(UartHwRegisters *pUartHwRegs); - -/** - * Read the data from the receive fifo. - */ -NvError -NvDdkPrivUartHwReadFromReceiveFifo( - UartHwRegisters *pUartHwRegs, - NvU8 *pRxBuff, - NvU32 MaxBytesRequested, - NvU32 *bytesRead); - -/** - * Clear all the uart interrupt. - */ -void NvDdkPrivUartHwClearAllInt(UartHwRegisters *pUartHwRegs); - -/** - * Configure the receive interrupt. - */ -void NvDdkPrivUartHwSetReceiveInterrupt( - UartHwRegisters *pUartHwRegs, - NvBool IsEnable, - NvBool IsRxUsingApbDma); - -/** - * Configure the transmit interrupt. - */ -void NvDdkPrivUartHwSetTransmitInterrupt( - UartHwRegisters *pUartHwRegs, - NvBool IsEnable); - -/** - * Configure the modem control interrupt. - */ -void NvDdkPrivUartHwSetModemControlInterrupt( - UartHwRegisters *pUartHwRegs, - NvBool IsEnable); - -/** - * Get the interrupt reason. - */ -UartHwInterruptSource -NvDdkPrivUartHwGetInterruptReason( - UartHwRegisters *pUartHwRegs); - -/** - * Enable/disable the Irda coding. - */ -void -NvDdkPrivUartHwSetIrdaCoding( - UartHwRegisters *pUartHwRegs, - NvBool IsEnable); - -/** - * Set the output modem signals to high or low. - */ -void -NvDdkPrivUartHwSetModemSignal( - UartHwRegisters *pUartHwRegs, - NvDdkUartSignalName SignalName, - NvBool IsActive); - -/** - * Get the CTS status from the line. - */ -NvBool NvDdkPrivUartHwIsCtsActive(UartHwRegisters *pUartHwRegs); - -/** - * Read the modem signal level and update the state of the signal in the uart hw - * register structure. - */ -void NvDdkPrivUartHwUpdateModemSignal(UartHwRegisters *pUartHwRegs); - -/** - * Enable/disable the hw flow control for transmitting the signal. If it is - * enabled then it wil only transmit the data if CTS line is high. - */ -void -NvDdkPrivUartHwSetHWFlowControl( - UartHwRegisters *pUartHwRegs, - NvBool IsEnable); - -/** - * Reconfigure the uart controller register. The shadow register content is - * written into the uart controller register. - */ -void NvDdkPrivUartHwReconfigureRegisters(UartHwRegisters *pUartHwRegs); - -/** @}*/ - -#if defined(__cplusplus) -} -#endif - -#endif // INCLUDED_DDKUART_HW_PRIVATE_H diff --git a/arch/arm/mach-tegra/nvddk/nvddk_uart.c b/arch/arm/mach-tegra/nvddk/nvddk_uart.c deleted file mode 100644 index c3f498b3a26d..000000000000 --- a/arch/arm/mach-tegra/nvddk/nvddk_uart.c +++ /dev/null @@ -1,2834 +0,0 @@ -/* - * Copyright (c) 2007-2009 NVIDIA Corporation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NVIDIA Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * @file - * @brief <b>NVIDIA Driver Development Kit: - * Uart ddk Driver implementation</b> - * - * @b Description: Implementation of the NvDdk UART API. - * - * Some constrains and designs details of the uart driver: - * - * We use the continuous double buffering mechanims for the uart receive. - * In this method, the apb dma is programmed for the receive in contunous mode* - * and generte the interrupt after half of the buffer completion. - * Currently the buffer size is 64KB and so dma generate the interrupt after - * every 32 K transfer. So the uart ddk clinet need to copy this dma buffer - * to local buffer before next 32K bytes received. For 4.5Mbps rate, the 32 K - * transfer takes around 70ms and we have the only latency of 70ms to copy this - * buffer. For lower baudrate, the latency is more. - * - * In the receive path, there are three possible errors: - * - FIFO overrun error: If there is no space in the Rx FIFO (16 bytes in uart - * controller) and if data arrives then we get this error. - * As we are using the apb dma in double continuous mode - * with the trigger level of 4 bytes so whenever there - * is 4 bytes in the fifo, the apb dma transfers this to - * memory. This is done by hw and sw does not get involved. - * This transfer is continuous. As hw is transferring the - * data from the fifo to memory, there is very less - * chances of getting the overrun error. We may get only - * when system bus is too much loaded, or - * ahb/apb/cpu/memory frequencies are too low or any - * system bandwidth issue. We have verified 4.5Mbps baud - * rate maximum and not seen any such issue. - - * - Dma buffer overwrite: There is 64KB of dma buffer on which data is filled - * from fifo. This is continuous mode filling and dma - * generates the interrupt after every 32Kbyte of transfers. - * So we have to respond this interrupt till next 32K data - * receive and copy this data to local buffer so that dma - * can fill again on this dma buffer. if we don't copy the - * data in a given time, the dma will overwrite this data - * with the new arriving data and so lose the old data. So - * responding the interrupt in a given time line is necessary - * and it defines the maximum interrupt latency for the - * uart communication. If system does not respond in the - * given time, the system will not perform as expected. - - * - Local buffer full: As ddk copies the incoming data from dma buffer to - * local buffer so that it can be supplied to client when - * client calls the read. If data are arriving continuously - * and data is not being read then buffer will get filled. - * If we have the hw flow control then sw deassert the RTS - * so that no more data can be send from other end. It will - * again assert when the client calls the read and there - * is some threshold level of the space. Currently in ddk - * it is set to 48K minimum so if there is data available - * less than 48K in the local buffer then only RTS will be - * enabled otherwise it will be deasserted. This RTS control - * is done through sw (driver) and so system should - * response the IST/high priority thread in a given time. - * - * Moreover in the cuttent design, the DMA IST/UART IST priorities are high on - * the system as these are ISR. The Rx thread priority in the uart shim driver - * should be the IST priority level. - * - * If the system responds the threads in a given time then we will not see any - * data loss/overrun type of error. - * - * What happen if operating system is unable to schedule the Nvidia UART driver - * routines in a timely fashion or is mishandling hardware handshaking. - * Specifically, it is necessary for the driver to de-assert RTS when it is in - * danger of a FIFO overrun, 16 bytes max, to inform the sender that it should - * hold off on further transmissions. - * - * Answer: - * If OS is unable to respond the IST/higher priority thread on a given time - * line then system is too loaded and need to redesign the application/system - * because it is not meeting the real time requirements for the device (even it - * is soft real time system). - * We don't have the RTS control enable from the hw and so sw control the RTS - * based on the driver buffer state/internal state. For this the thread should - * be scheduled properly so that proper flow control can be controlled. - * Even in double buffering mechanism, the hw control of RTS is also not useful - * as the hw does not know your buffer overwrite issue. - * We are setting the RTS activation/deactivation control to the size of half - * local buffer (minimum local buffer size is 96K). So if there is data in the - * local buffer more than half the local buffer, the RTS will be deactivated - * and if it's less, then only it's activated. This water level mechanism saves - * the 'out of local buffer issue'. - */ - -#include "nvddk_uart.h" -#include "ddkuart_hw_private.h" -#include "nvrm_power.h" -#include "nvrm_memmgr.h" -#include "nvrm_dma.h" -#include "nvodm_query.h" -#include "nvrm_interrupt.h" -#include "nvassert.h" -#include "nvrm_hardware_access.h" -#include "nvodm_query_pinmux.h" -#include "nvrm_pinmux.h" -#include "nvodm_uart.h" - -// Some important debug print to debug the flow -#define DEBUG_WRITE_TIMEOUT 0 -#define DEBUG_READ_RXERROR 0 -#define ENABLE_WRITE_PROFILE 0 -#define ENABLE_READ_PROFILE 0 -// Constants used to size arrays. Must be >= the max of all chips. -enum {MAX_UART_CONTROLLERS = 5}; - -// Assuming 50 ms data size for the 4.5Mbps -// Assuming the 50 ms will be the time taken to copy the recv data into the -// Passed buffer. -enum {UART_RX_DMA_PING_BUFFER_SIZE = 0x8000}; - -// Minimum size of the local buffering of the data to avoid any data loss. -enum {UART_RX_LOCAL_BUFFER_SIZE_MIN = UART_RX_DMA_PING_BUFFER_SIZE*3}; - -// Local buffer threshold for disabling the rts line. -// This is the 2/3rd of the local buffer size. -enum {UART_RX_LOCAL_BUFFER_THRESOLD_MIN = UART_RX_DMA_PING_BUFFER_SIZE << 1}; - -// maximum frequency boost list -enum {MAX_FREQ_REQ_LIST = 3}; - -// Time from last operation on read/write complete on uart port. -// If the time is more than the limit then uart will request for the -// frequency down. -enum {HIGH_FREQUENCY_HOLD_TIMEOUT = 3000}; // 3 seconds - -// Mutex definition which are used for the locking the read/write/channel -// register access. -#define DeclareReadFlowLock NvOsIntrMutexHandle hReadMutex -#define CreateReadFlowLock(hUart) NvOsIntrMutexCreate(&hUart->hReadMutex) -#define LockReadFlow(hUart) NvOsIntrMutexLock(hUart->hReadMutex) -#define UnlockReadFlow(hUart) NvOsIntrMutexUnlock(hUart->hReadMutex) -#define DestroyReadFlowLock(hUart) NvOsIntrMutexDestroy(hUart->hReadMutex) - -#define DeclareWriteFlowLock NvOsIntrMutexHandle hWriteMutex -#define CreateWriteFlowLock(hUart) NvOsIntrMutexCreate(&hUart->hWriteMutex) -#define LockWriteFlow(hUart) NvOsIntrMutexLock(hUart->hWriteMutex) -#define UnlockWriteFlow(hUart) NvOsIntrMutexUnlock(hUart->hWriteMutex) -#define DestroyWriteFlowLock(hUart) NvOsIntrMutexDestroy(hUart->hWriteMutex) - -#define DeclareRegisterAccessLock NvOsIntrMutexHandle hRegisterAccessMutex -#define CreateRegisterAccessLock(hUart) NvOsIntrMutexCreate(&hUart->hRegisterAccessMutex) -#define LockRegisterAccess(hUart) NvOsIntrMutexLock(hUart->hRegisterAccessMutex) -#define UnlockRegisterAccess(hUart) NvOsIntrMutexUnlock(hUart->hRegisterAccessMutex) -#define DestroyRegisterAccessLock(hUart) NvOsIntrMutexDestroy(hUart->hRegisterAccessMutex) - -// Way to reset the semaphore count. -#define ResetSemaphoreCount(hSema) \ - while(NvOsSemaphoreWaitTimeout(hSema, 0) != NvError_Timeout) - -#if DEBUG_READ_RXERROR -#define DEBUG_PRINT_RX_ERR(Expr, Format) \ - do { \ - if (Expr) \ - { \ - NvOsDebugPrintf Format; \ - } \ - } while(0) -#else -#define DEBUG_PRINT_RX_ERR(Expr, Format) -#endif - -#if DEBUG_WRITE_TIMEOUT -#define DEBUG_PRINT_TX_ERR(Expr, Format) \ - do { \ - if (Expr) \ - { \ - NvOsDebugPrintf Format; \ - } \ - } while(0) -#else -#define DEBUG_PRINT_TX_ERR(Expr, Format) -#endif - -/** - * Combines the SOC uart capability structure. - */ -typedef struct SocUartCapabilityRec -{ - // Tells whether the end of data interrupt is supported or not. - NvBool IsEndOfDataIntSupported; - - // Tells whether the RTS hw flow control is supported or not. - NvBool IsRtsHwFlowControlSupported; - - // Fifo depth of the uart controller. - NvU32 FifoDepth; -} SocUartCapability; - -/** - * Combines the uart channel information. - */ -typedef struct -{ - // Nv Rm device handles. - NvRmDeviceHandle hRmDevice; - - // List of the uart handle exist in the ddk. - NvDdkUartHandle hUartList[MAX_UART_CONTROLLERS]; - - // Mutex for uart channel information. - NvOsMutexHandle hUartOpenMutex; -} DdkUartChannelInfo; - -/** - * Combines the Uart transfer information for receive and transmit for the given - * uart channel. - */ -typedef struct -{ - // Tells whether transfer is going on or not? - NvBool IsBusy; - - NvU8 *pReqBuffer; - - // Pointer to the current transfer. - NvU8 *pCurrTransBuf; - - NvU32 BytesRequested; - - NvU32 BytesTransferred; - - // Bytes remaining to transfer. - NvU32 BytesRemaining; - - // Current transfer status. - NvError TransferStatus; - - // On complete semaphore Id which need to be signal after transfer - // completion or abort on the transfer. - NvOsSemaphoreHandle hOnCompleteSema; - - NvBool IsStopReq; -} UartTransferReqInfo; - -/** - * Uart local buffer information. - */ -typedef struct -{ - // Pointer to the local buffer. - NvU8 *pBuffPtr; - - // Read Index - NvU32 ReadIndex; - - // Write index. - NvU32 WriteIndex; - - // Total size of the buffer. - NvU32 TotalBufferSize; - - // Higher buffer level from where the RTS is deactivated to stop the sender - // as ddk is not able to receive more data. - NvU32 BufferLevelHigh; - - // Total data available in the buffer. - NvU32 DataAvailable; - - // Semaphore which will be signalled once the data is available in the - // fifo/dma buffer. Client passed this semaphore Id. - NvOsSemaphoreHandle hDataAvailableSema; - - // Semaphore which will be signalled when there is any error or break receive - // in the Rx line. Client passed this semaphore Id. - NvOsSemaphoreHandle hLineStatusSema; -} UartLocalBuffer; - -/** - * Uart handle which combines all the information related to the given uart - * channels - */ -typedef struct NvDdkUartRec -{ - // Nv Rm device handles. - NvRmDeviceHandle hRmDevice; - - // Instance Id of the uart channels. - NvU32 InstanceId; - - // Number of open count. - NvU32 OpenCount; - - // The uart capability for this uart channel only. - SocUartCapability SocUartCaps; - - // Number of uart interface lines physically available on board. - NvU32 NumberOfInterfaceLine; - - // Uart configuration parameter. - NvDdkUartConfiguarations UartConfig; - - // Uart hw register information. - UartHwRegisters UartHwRegs; - - // Uart write transfer request information. - UartTransferReqInfo WriteReq; - - // Read transfer request information. - UartTransferReqInfo ReadReq; - - // Local buffer information which is used for receive. - UartLocalBuffer LocalRxBuff; - - // Tells whether the dma support is available for this channel. - // This can be false if the dma allocation or the dma buffer creation fails. - NvBool IsDmaSupport; - - // Is receive is dma based transfer or not. - NvBool IsRxApbDmaBased; - - // Is read started or not. - NvBool IsDmaReadStarted; - - // Rx dma handles. - NvRmDmaHandle hRxRmDma; - - // Tx dma handles. - NvRmDmaHandle hTxRmDma; - - // Memory handle to create the uncache memory for dma transfer. - NvRmMemHandle hRmMemory; - - // Rx Dma buffer address. - NvRmPhysAddr RxDmaBuffPhysAdd; - - // Tx Dma buffer address. - NvRmPhysAddr TxDmaBuffPhysAdd; - - NvU32 RxDmaBufferSize; - NvU32 HalfRxDmaBufferSize; - - NvU32 TxDmaBufferSize; - - // Virtual pointer to the Rx dma buffer. - NvU8 *pRxDmaBuffer; - - // Virtual pointer to the Tx dma buffer. - NvU8 *pTxDmaBuffer; - - // Write dma request - NvRmDmaClientBuffer WDmaReq; - - // Read dma request - NvRmDmaClientBuffer RDmaReq; - - // The last read index from dma buffer to the local buffer. - NvU32 LastReadIndex; - - // Is current write is polling - NvBool IsWritePolling; - - // Maximum transmit bytes which can be send by polling. - NvU32 MaxTxBytesPolling; - - // 4 character time in microseconds, the write will wait for this much of - // time when it founds that Tx fifo is full. - NvU32 Char4TimeUs; - - // Receive Synchronous semaphore Id which need to be signalled. - NvOsSemaphoreHandle hRxSynchSema; - - // Transmit Synchronous semaphore Id which need to be signalled. - NvOsSemaphoreHandle hTxSynchSema; - - // Mutex to access the read flow. - DeclareReadFlowLock; - - // Mutex to access the write flow. - DeclareWriteFlowLock; - - // Mutex to access the register which are common for read/write/configuration. - DeclareRegisterAccessLock; - - // Callback for signal change notification. - NvDdkUartSignalChangeCallback hModemSigChngCallback; - - // Arguments to the signal change callback function. - void *ModemSigChngHandlerArgs; - - // Clinet wants the notification on the signal change. - NvU32 ModemSignalName; - - NvBool IsRtsFlowEnable; - - NvBool IsCtsFlowEnable; - - // Pointer to the uart information. - DdkUartChannelInfo *pUartInfo; - - // Semaphore for registering the client with the power manager. - NvOsSemaphoreHandle hRmPowerEventSema; - - // Power client Id. - NvU32 RmPowerClientId; - - // Interrupt handle - NvOsInterruptHandle InterruptHandle; - - // Odm uart handle - NvOdmUartHandle hOdmUart; - - // Busy hints for setting the required frequency of the system/cpu. - NvRmDfsBusyHint UpFreq[MAX_FREQ_REQ_LIST]; - NvRmDfsBusyHint DownFreq[MAX_FREQ_REQ_LIST]; - - // Thread to keep the power/frequency requirement on the channel. - NvOsThreadHandle hUartPowerMgrThread; - - NvOsSemaphoreHandle hUartPowerMgrSema; - - NvBool IsStopPowerThread; - - NvBool IsFreqBoosted; - - NvBool IsSuspendedState; - - NvBool OldRtsState; - - NvBool OldDtrState; -} NvDdkUart; - -static DdkUartChannelInfo *s_pUartInfo = NULL; - -/** - * Get the uart soc capability. - * - */ -static NvError -UartGetSocCapabilities( - NvRmDeviceHandle hRmDevice, - NvU32 UartInstanceId, - SocUartCapability *pUartSocCaps) -{ - NvRmModuleID ModuleId; - static SocUartCapability s_SocUartCapsList[3]; - NvRmModuleCapability UartCapsList[] = - { - { 1, 0, 0, &s_SocUartCapsList[0] }, // Major.Minor = 1.0 - { 1, 1, 0, &s_SocUartCapsList[1] }, // Major.Minor = 1.1 - { 1, 2, 0, &s_SocUartCapsList[2] }, // Major.Minor = 1.2 - }; - SocUartCapability *pUartCaps = NULL; - - ModuleId = NVRM_MODULE_ID(NvRmModuleID_Uart, UartInstanceId); - - s_SocUartCapsList[0].IsEndOfDataIntSupported = NV_FALSE; - s_SocUartCapsList[0].IsRtsHwFlowControlSupported = NV_FALSE; - s_SocUartCapsList[0].FifoDepth = 16; - - s_SocUartCapsList[1].IsEndOfDataIntSupported = NV_TRUE; - s_SocUartCapsList[1].FifoDepth = 16; - - s_SocUartCapsList[2].IsEndOfDataIntSupported = NV_TRUE; - s_SocUartCapsList[2].FifoDepth = 32; - - // FIXEME!! HW Bug: The RTS hw flow control is not working when enabling - // EORD interrupt. - // As the EORD is more important feature then the Rts hw flow control, - // disabling this feature. - s_SocUartCapsList[1].IsRtsHwFlowControlSupported = NV_FALSE; - s_SocUartCapsList[2].IsRtsHwFlowControlSupported = NV_FALSE; - - // Get the capability from modules files. - NV_ASSERT_SUCCESS(NvRmModuleGetCapabilities(hRmDevice, ModuleId, - UartCapsList, NV_ARRAY_SIZE(UartCapsList), - (void **)&pUartCaps)); - pUartSocCaps->IsEndOfDataIntSupported = pUartCaps->IsEndOfDataIntSupported; - pUartSocCaps->IsRtsHwFlowControlSupported = pUartCaps->IsRtsHwFlowControlSupported; - pUartSocCaps->FifoDepth = pUartCaps->FifoDepth; - return NvSuccess; -} - -/** - * Initialize the uart information. - * Thread safety: Caller responsibility. - */ -static NvError InitUartInformation(NvRmDeviceHandle hRmDevice) -{ - NvError Error = NvSuccess; - DdkUartChannelInfo *pUartInfo = NULL; - - NV_ASSERT(NvRmModuleGetNumInstances(hRmDevice, NvRmModuleID_Uart) <= MAX_UART_CONTROLLERS); - if (!s_pUartInfo) - { - // Allocate the memory for the uart information. - pUartInfo = NvOsAlloc(sizeof(*pUartInfo)); - if (!pUartInfo) - return NvError_InsufficientMemory; - NvOsMemset(pUartInfo, 0, sizeof(*pUartInfo)); - - // Initialize all the parameters. - pUartInfo->hRmDevice = hRmDevice; - - // Create the mutex to accss the uart information. - Error = NvOsMutexCreate(&pUartInfo->hUartOpenMutex); - // If error exit till then destroy all allocations. - if (Error) - { - NvOsFree(pUartInfo); - pUartInfo = NULL; - return Error; - } - - if (NvOsAtomicCompareExchange32((NvS32*)&s_pUartInfo, 0, (NvS32)pUartInfo)!=0) - { - NvOsMutexDestroy(pUartInfo->hUartOpenMutex); - NvOsFree(pUartInfo); - } - } - return NvSuccess; -} - -/** - * Create the dma buffer memory handle. - */ -static NvError -CreateDmaBufferMemoryHandle( - NvRmDeviceHandle hRmDevice, - NvRmMemHandle *phMemHandle, - NvRmPhysAddr *pMemPhyAddr, - NvU32 BufferSize) -{ - NvError Error = NvSuccess; - NvRmMemHandle hNewMemHandle = NULL; - - // Initialize the memory handle with NULL - *phMemHandle = NULL; - - /// Create memory handle - Error = NvRmMemHandleCreate(hRmDevice, &hNewMemHandle, BufferSize); - - // Allocates the memory from the sdram - if (!Error) - Error = NvRmMemAlloc(hNewMemHandle, NULL, 0, 0x4, NvOsMemAttribute_Uncached); - - // Pin the memory allocation so that it should not move by memory manager. - // Also get the physical address. - if (!Error) - *pMemPhyAddr = NvRmMemPin(hNewMemHandle); - - // If error then free the memory allocation and memory handle. - if (Error) - { - NvRmMemHandleFree(hNewMemHandle); - hNewMemHandle = NULL; - } - - *phMemHandle = hNewMemHandle; - return Error; -} - - /** - * Destroy the dma buffer memory handle. - * Thread safety: Caller responsibility. - */ -static void DestroyDmaBufferMemoryHandle(NvRmMemHandle hMemHandle) -{ - // Can accept the null parameter. If it is not null then only destroy. - if (hMemHandle) - { - // Unpin the memory allocation. - NvRmMemUnpin(hMemHandle); - - // Free the memory handle. - NvRmMemHandleFree(hMemHandle); - } -} - -/** - * Create the dma transfer buffer for the given handles. - * Thread safety: Caller responsibility. - */ -static NvError -CreateDmaTransferBuffer( - NvRmDeviceHandle hRmDevice, - NvRmMemHandle *phRmMemory, - NvRmPhysAddr *pBuff1PhysAddr, - void **pBuff1Ptr, - NvRmPhysAddr *pBuff2PhysAddr, - void **pBuff2Ptr, - NvU32 OneBufferSize) -{ - NvError Error = NvSuccess; - NvRmMemHandle hRmMemory = NULL; - NvRmPhysAddr BuffPhysAddr; - - // Reset all the members related to the dma buffer. - BuffPhysAddr = 0; - - *phRmMemory = NULL; - *pBuff1Ptr = (void *)NULL; - *pBuff1PhysAddr = 0; - *pBuff2Ptr = (void *)NULL; - *pBuff2PhysAddr = 0; - - // Create the dma buffer memory for receive and transmit. - // It will be double of the OneBufferSize - Error = CreateDmaBufferMemoryHandle(hRmDevice, &hRmMemory, &BuffPhysAddr, - (OneBufferSize << 1)); - if (!Error) - { - // 0 to OneBufferSize-1 is buffer 1 and OneBufferSize to 2*OneBufferSize - // is second buffer. - Error = NvRmMemMap(hRmMemory, 0, OneBufferSize, - NVOS_MEM_READ_WRITE, pBuff1Ptr); - if (!Error) - { - Error = NvRmMemMap(hRmMemory, OneBufferSize, OneBufferSize, - NVOS_MEM_READ_WRITE, pBuff2Ptr); - if (Error) - NvRmMemUnmap(hRmMemory, pBuff1Ptr, OneBufferSize); - } - // If error then free the allocation and reset all changed value. - if (Error) - { - DestroyDmaBufferMemoryHandle(hRmMemory); - hRmMemory = NULL; - *pBuff1Ptr = (void *)NULL; - *pBuff2Ptr = (void *)NULL; - return Error; - } - *phRmMemory = hRmMemory; - *pBuff1PhysAddr = BuffPhysAddr; - *pBuff2PhysAddr = BuffPhysAddr + OneBufferSize; - } - return Error; -} - -/** - * Destroy the dma transfer buffer. - * Thread safety: Caller responsibility. - */ -static void -DestroyDmaTransferBuffer( - NvRmMemHandle hRmMemory, - void *pBuff1Ptr, - void *pBuff2Ptr, - NvU32 OneBufferSize) -{ - NvRmMemUnmap(hRmMemory, pBuff1Ptr, OneBufferSize); - NvRmMemUnmap(hRmMemory, pBuff2Ptr, OneBufferSize); - DestroyDmaBufferMemoryHandle(hRmMemory); -} - -/** - * Initialize the transfer information for the given handles. - * Thread safety: Caller /responsibility. - */ -static void -InitTransferInfo( - NvRmDeviceHandle hRmDevice, - UartTransferReqInfo *pTransferInfo) -{ - NvOsMemset(pTransferInfo, 0, sizeof(UartTransferReqInfo)); - pTransferInfo->IsBusy = NV_FALSE; - pTransferInfo->pReqBuffer = NULL; - pTransferInfo->BytesRequested = 0; - pTransferInfo->BytesTransferred = 0; - pTransferInfo->pCurrTransBuf = NULL; - pTransferInfo->BytesRemaining = 0; - pTransferInfo->TransferStatus = NvSuccess; - pTransferInfo->hOnCompleteSema = NULL; -} - - -/** - * Create the local buffer. - * Thread safety: Caller responsibility. - */ -static NvError CreateLocalRxBuff(NvDdkUartHandle hUart, NvU32 BufferSize) -{ - NvError Error = NvSuccess; - - hUart->LocalRxBuff.pBuffPtr = NULL; - hUart->LocalRxBuff.ReadIndex = 0; - hUart->LocalRxBuff.WriteIndex = 0; - hUart->LocalRxBuff.DataAvailable = 0; - hUart->LocalRxBuff.hDataAvailableSema = NULL; - hUart->LocalRxBuff.TotalBufferSize = BufferSize; - // Setting the RTS activation/deactivation thresold level to the half of the - // buffer size. - hUart->LocalRxBuff.BufferLevelHigh = (BufferSize >> 1); - if (BufferSize) - { - hUart->LocalRxBuff.pBuffPtr = NvOsAlloc(BufferSize); - if (!hUart->LocalRxBuff.pBuffPtr) - Error = NvError_InsufficientMemory; - } - return Error; -} - -/** - * Destroy the local buffer. - * Thread safety: Caller responsibility. - */ -static void DestroyLocalRxBuff(NvDdkUartHandle hUart) -{ - NvOsFree(hUart->LocalRxBuff.pBuffPtr); - hUart->LocalRxBuff.pBuffPtr = NULL; - hUart->LocalRxBuff.ReadIndex = 0; - hUart->LocalRxBuff.DataAvailable = 0; - hUart->LocalRxBuff.WriteIndex = 0; - hUart->LocalRxBuff.hDataAvailableSema = NULL; - hUart->LocalRxBuff.hLineStatusSema = NULL; - hUart->LocalRxBuff.TotalBufferSize = 0; - hUart->LocalRxBuff.BufferLevelHigh = 0; -} - -/** - * Handle the uart receive interrupt. - * Thread safety: Caller responsibility. - */ -static void -HandleUartRxInterrupt( - NvDdkUartHandle hUart, - UartHwInterruptSource InterruptReason) -{ - NvError Error = NvSuccess; - NvU32 SpaceFromWriteIndex; - NvU32 SpaceFromStartIndex; - NvU32 BytesRead; - NvU32 IsNextRead = NV_TRUE; - - - if (hUart->IsRxApbDmaBased) - { - LockRegisterAccess(hUart); - NvDdkPrivUartHwSetReceiveInterrupt(&hUart->UartHwRegs, NV_FALSE, NV_TRUE); - UnlockRegisterAccess(hUart); - NvOsSemaphoreSignal(hUart->LocalRxBuff.hDataAvailableSema); - } - else - { - LockReadFlow(hUart); - if (hUart->LocalRxBuff.ReadIndex > hUart->LocalRxBuff.WriteIndex) - { - // 0.....w....r...(n-1) - SpaceFromWriteIndex = hUart->LocalRxBuff.ReadIndex - - hUart->LocalRxBuff.WriteIndex; - SpaceFromStartIndex = 0; - } - else - { - // 0.....r....w...(n-1) - SpaceFromWriteIndex = hUart->LocalRxBuff.TotalBufferSize - - hUart->LocalRxBuff.WriteIndex; - SpaceFromStartIndex = hUart->LocalRxBuff.ReadIndex; - } - - if (SpaceFromWriteIndex) - { - Error = NvDdkPrivUartHwReadFromReceiveFifo(&hUart->UartHwRegs, - &hUart->LocalRxBuff.pBuffPtr[hUart->LocalRxBuff.WriteIndex], - SpaceFromWriteIndex, &BytesRead); - if (BytesRead) - { - hUart->LocalRxBuff.WriteIndex += BytesRead; - if (hUart->LocalRxBuff.WriteIndex >= hUart->LocalRxBuff.TotalBufferSize) - hUart->LocalRxBuff.WriteIndex = 0; - hUart->LocalRxBuff.DataAvailable += BytesRead; - } - if (BytesRead < SpaceFromWriteIndex) - IsNextRead = NV_FALSE; - } - if ((!Error) && (IsNextRead) && (SpaceFromStartIndex)) - { - Error = NvDdkPrivUartHwReadFromReceiveFifo(&hUart->UartHwRegs, - &hUart->LocalRxBuff.pBuffPtr[hUart->LocalRxBuff.WriteIndex], - SpaceFromStartIndex, &BytesRead); - if (BytesRead) - { - hUart->LocalRxBuff.WriteIndex += BytesRead; - if (hUart->LocalRxBuff.WriteIndex >= hUart->LocalRxBuff.TotalBufferSize) - hUart->LocalRxBuff.WriteIndex = 0; - hUart->LocalRxBuff.DataAvailable += BytesRead; - } - } - - // If flow control is enabled and data available is crossed the thresold - // level then disable the rts so there will not be any incoming data. - if (hUart->LocalRxBuff.DataAvailable >= hUart->LocalRxBuff.BufferLevelHigh) - { - if (hUart->IsRtsFlowEnable) - { - LockRegisterAccess(hUart); - NvDdkPrivUartHwSetModemSignal(&hUart->UartHwRegs, - NvDdkUartSignalName_Rts, NV_FALSE); - UnlockRegisterAccess(hUart); - } - } - UnlockReadFlow(hUart); - - // Update the transfer status. - hUart->ReadReq.TransferStatus = Error; - NvOsSemaphoreSignal(hUart->LocalRxBuff.hDataAvailableSema); - } -} - -/** - * Handle the uart transmit interrupt. - * Thread safety: Caller responsibility. - */ -static void HandleUartTxInterrupt(NvDdkUartHandle hUart) -{ - NvU32 BytesWritten; - - if (hUart->IsWritePolling) - { - LockRegisterAccess(hUart); - NvDdkPrivUartHwSetTransmitInterrupt(&hUart->UartHwRegs, NV_FALSE); - UnlockRegisterAccess(hUart); - - if (hUart->WriteReq.hOnCompleteSema) - NvOsSemaphoreSignal(hUart->WriteReq.hOnCompleteSema); - hUart->WriteReq.hOnCompleteSema = NULL; - return; - } - // Write into the transmit fifo. - BytesWritten = NvDdkPrivUartHwWriteInTransmitFifo(&hUart->UartHwRegs, - hUart->WriteReq.pCurrTransBuf, hUart->WriteReq.BytesRemaining); - if (BytesWritten) - { - hUart->WriteReq.BytesRemaining -= BytesWritten; - hUart->WriteReq.BytesTransferred += BytesWritten; - hUart->WriteReq.pCurrTransBuf += BytesWritten; - } - - // If there is error or the bytes remaining to write is 0 then inform the - // client. - if (!hUart->WriteReq.BytesRemaining) - { - LockRegisterAccess(hUart); - NvDdkPrivUartHwSetTransmitInterrupt(&hUart->UartHwRegs, NV_FALSE); - UnlockRegisterAccess(hUart); - NvOsSemaphoreSignal(hUart->WriteReq.hOnCompleteSema); - } -} - -/** - * Handle the uart modem interrupt. - * Thread safety: Caller responsibility. - */ -static void HandleUartModemInterrupt(NvDdkUartHandle hUart) -{ - NvU32 OldState = (hUart->UartHwRegs.ModemSignalSatus & hUart->ModemSignalName); - NvU32 NewState; - - // Update the modem signal status. - LockRegisterAccess(hUart); - NvDdkPrivUartHwUpdateModemSignal(&hUart->UartHwRegs); - NewState = (hUart->UartHwRegs.ModemSignalSatus & hUart->ModemSignalName); - UnlockRegisterAccess(hUart); - - if (OldState != NewState) - { - // Inform client that there is changes in the modem control signal. - if (hUart->hModemSigChngCallback) - (*(hUart->hModemSigChngCallback)) - (hUart->ModemSigChngHandlerArgs); - } -} - -/** - * Handle all types of the uart interrupts. - * Thread safety: Caller responsibility. - */ -static void HandleUartInterrupt(void *args) -{ - UartHwInterruptSource InterruptReason; - NvDdkUartHandle hUart; - - hUart = (NvDdkUartHandle)args; - - // Some action on this channel, so boost frequency - if (!hUart->IsFreqBoosted) - NvOsSemaphoreSignal(hUart->hUartPowerMgrSema); - - // The interrupt status is provided from high priority till no pending - // interrupt so do in the loop to handle all interrupts. - while (1) - { - // Get the interrupt reason for this uart channel. - InterruptReason = NvDdkPrivUartHwGetInterruptReason(&hUart->UartHwRegs); - - // No pending interrupt or error then break the loop and exit the error. - if (UartHwInterruptSource_None == InterruptReason) - break; - - // there is a valid interrupt reason so call appropriate function. - switch (InterruptReason) - { - case UartHwInterruptSource_ReceiveError: - NvDdkPrivUartHwSetReceiveInterrupt(&hUart->UartHwRegs, NV_FALSE, hUart->IsRxApbDmaBased); - NvOsSemaphoreSignal(hUart->LocalRxBuff.hLineStatusSema); - DEBUG_PRINT_RX_ERR(1, ("HandleUartInterrupt(): RX Error interrupt occured\n")); - break; - - case UartHwInterruptSource_Receive: - case UartHwInterruptSource_RxTimeout: - case UartHwInterruptSource_EndOfData: - HandleUartRxInterrupt(hUart, InterruptReason); - break; - - case UartHwInterruptSource_Transmit: - HandleUartTxInterrupt(hUart); - break; - - case UartHwInterruptSource_ModemControl: - HandleUartModemInterrupt(hUart); - break; - - default: - break; - } - } - - NvRmInterruptDone(hUart->InterruptHandle); - return; -} - -static NvError -RegisterUartInterrupt( - NvRmDeviceHandle hRmDevice, - NvDdkUartHandle hDdkUart) -{ - NvU32 IrqList; - NvOsInterruptHandler IntHandlers; - if (hDdkUart->InterruptHandle) - { - return NvSuccess; - } - IrqList = NvRmGetIrqForLogicalInterrupt(hRmDevice, - NVRM_MODULE_ID(NvRmModuleID_Uart, hDdkUart->InstanceId), 0); - IntHandlers = HandleUartInterrupt; - return(NvRmInterruptRegister(hRmDevice, 1, &IrqList, &IntHandlers, hDdkUart, - &hDdkUart->InterruptHandle, NV_TRUE)); -} - -/** - * Uart power manager thread which manages the frequency requirement for the - * channel. If there is no transaction in the channel for some time then it - * reduces the frequency request otherwise it will keep the request for - * higher frequency. - */ -static void UartPowerManagerThread(void *args) -{ - NvDdkUartHandle hUart = (NvDdkUartHandle)args; - NvError Error = NvSuccess; - NvU32 TimeOut = NV_WAIT_INFINITE; - NvU32 TimeoutErrCount = 0; - NvBool IsFreqDown = NV_TRUE; - for (;;) - { - // Wait till any event occurs for the transmit thread to take any action. - Error = NvOsSemaphoreWaitTimeout(hUart->hUartPowerMgrSema, TimeOut); - if (!Error) // Got the signal from client. - { - // If need to stop the thread the return - if (hUart->IsStopPowerThread) - { - // Bringdown the frequency before returning - if (!IsFreqDown) - NvRmPowerBusyHintMulti(hUart->hRmDevice, hUart->RmPowerClientId, - hUart->DownFreq, MAX_FREQ_REQ_LIST, - NvRmDfsBusyHintSyncMode_Async); - hUart->IsFreqBoosted = NV_FALSE; - break; - } - - TimeoutErrCount = 0; - - // If the new state is suspended state then bringdown the freq - if (hUart->IsSuspendedState) - { - if (!IsFreqDown) - NvRmPowerBusyHintMulti(hUart->hRmDevice, hUart->RmPowerClientId, - hUart->DownFreq, MAX_FREQ_REQ_LIST, - NvRmDfsBusyHintSyncMode_Async); - hUart->IsFreqBoosted = NV_FALSE; - IsFreqDown = NV_TRUE; - // Now boost the freq only when resume is called. - TimeOut = NV_WAIT_INFINITE; - continue; - } - - // If frequency is already boosted then no need to increase the - // frequency - if (IsFreqDown) - NvRmPowerBusyHintMulti(hUart->hRmDevice, hUart->RmPowerClientId, - hUart->UpFreq, MAX_FREQ_REQ_LIST, - NvRmDfsBusyHintSyncMode_Async); - hUart->IsFreqBoosted = NV_TRUE; - IsFreqDown = NV_FALSE; - // Wait for the high freq hold timeout. - TimeOut = HIGH_FREQUENCY_HOLD_TIMEOUT; - continue; - } - - // Dont down the freq in first timeout, do in next timeout. - if (!TimeoutErrCount) - { - // Assume the freq is reduced but actually reduce in next timeout. - hUart->IsFreqBoosted = NV_FALSE; - TimeoutErrCount++; - TimeOut = HIGH_FREQUENCY_HOLD_TIMEOUT; - } - else - { - // No signal from client and second time, timeout happen and so it - // may bringdown the frequency - if (!IsFreqDown) - NvRmPowerBusyHintMulti(hUart->hRmDevice, hUart->RmPowerClientId, - hUart->DownFreq, MAX_FREQ_REQ_LIST, - NvRmDfsBusyHintSyncMode_Async); - hUart->IsFreqBoosted = NV_FALSE; - IsFreqDown = NV_TRUE; - - // Now wait for the signal for freq boosting request. - TimeOut = NV_WAIT_INFINITE; - } - } -} - -static void -SetBaudRateDependentParameter( - NvDdkUartHandle hUart, - NvU32 BaudRate) -{ - NvU32 CpuFreqReqd; - CpuFreqReqd = (BaudRate >= 900000)? 450000: ((BaudRate >= 250000)? 400000: 350000); - - hUart->UpFreq[0].ClockId = NvRmDfsClockId_Cpu; - hUart->UpFreq[0].BoostDurationMs = NV_WAIT_INFINITE; - hUart->UpFreq[0].BoostKHz = CpuFreqReqd; - hUart->UpFreq[0].BusyAttribute = NV_TRUE; - - hUart->UpFreq[1].ClockId = NvRmDfsClockId_Ahb; - hUart->UpFreq[1].BoostDurationMs = NV_WAIT_INFINITE; - hUart->UpFreq[1].BoostKHz = 144000; - hUart->UpFreq[1].BusyAttribute = NV_TRUE; - - hUart->UpFreq[2].ClockId = NvRmDfsClockId_Emc; - hUart->UpFreq[2].BoostDurationMs = NV_WAIT_INFINITE; - hUart->UpFreq[2].BoostKHz = 166000; - hUart->UpFreq[2].BusyAttribute = NV_TRUE; - - hUart->DownFreq[0].ClockId = NvRmDfsClockId_Cpu; - hUart->DownFreq[0].BoostDurationMs = NV_WAIT_INFINITE; - hUart->DownFreq[0].BoostKHz = 0; - hUart->DownFreq[0].BusyAttribute = NV_TRUE; - - hUart->DownFreq[1].ClockId = NvRmDfsClockId_Ahb; - hUart->DownFreq[1].BoostDurationMs = NV_WAIT_INFINITE; - hUart->DownFreq[1].BoostKHz = 0; - hUart->DownFreq[1].BusyAttribute = NV_TRUE; - - hUart->DownFreq[2].ClockId = NvRmDfsClockId_Emc; - hUart->DownFreq[2].BoostDurationMs = NV_WAIT_INFINITE; - hUart->DownFreq[2].BoostKHz = 0; - hUart->DownFreq[2].BusyAttribute = NV_TRUE; - - // Selected 400 microsecond for polling - hUart->MaxTxBytesPolling = (BaudRate >= 2000000)? 0x40 : ((BaudRate >= 900000)? 0x30: 0x10); - hUart->Char4TimeUs = (40000000 + BaudRate - 1)/(BaudRate); // 4 char*1000000us*10bitperchar -} - -/** - * Destroy the handle of uart channel and free all the allocation done for it. - * Thread safety: Caller responsibility. - */ -static void DestroyUartChannelHandle(NvDdkUartHandle hUart) -{ - NvRmModuleID ModuleId; - - // If null pointer for uart handle then return error. - if (!hUart) - return; - - // Close the uart odm handle - if (hUart->hOdmUart) - NvOdmUartClose(hUart->hOdmUart); - - ModuleId = NVRM_MODULE_ID(NvRmModuleID_Uart, hUart->InstanceId); - - if (hUart->RmPowerClientId) - { - // Disable the clocks. - NV_ASSERT_SUCCESS(NvRmPowerModuleClockControl( - hUart->hRmDevice, - ModuleId, hUart->RmPowerClientId, - NV_FALSE)); - - // Disable the power to the controller. - NV_ASSERT_SUCCESS(NvRmPowerVoltageControl( - hUart->hRmDevice, - ModuleId, - hUart->RmPowerClientId, - NvRmVoltsOff, - NvRmVoltsOff, - NULL, - 0, - NULL)); - - // Unregister for the power manager. - NvRmPowerUnRegister(hUart->hRmDevice, hUart->RmPowerClientId); - NvOsSemaphoreDestroy(hUart->hRmPowerEventSema); - } - NvDdkPrivUartHwClearAllInt(&hUart->UartHwRegs); - - if (hUart->InterruptHandle) - { - NvRmInterruptUnregister(hUart->hRmDevice, hUart->InterruptHandle); - hUart->InterruptHandle = NULL; - } - - // Kill the power manager thread. - if (hUart->hUartPowerMgrThread) - { - hUart->IsStopPowerThread = NV_TRUE; - NvOsSemaphoreSignal(hUart->hUartPowerMgrSema); - NvOsThreadJoin(hUart->hUartPowerMgrThread); - } - - NvOsSemaphoreDestroy(hUart->hUartPowerMgrSema); - - // Unmap the virtual mapping of the uart hw register. - NvRmPhysicalMemUnmap(hUart->UartHwRegs.pRegsVirtBaseAdd, - hUart->UartHwRegs.BankSize); - - DestroyLocalRxBuff(hUart); - - if (hUart->IsDmaSupport) - { - // Free the dma handles if it is allocated. - NvRmDmaAbort(hUart->hRxRmDma); - NvRmDmaFree(hUart->hRxRmDma); - - NvRmDmaAbort(hUart->hTxRmDma); - NvRmDmaFree(hUart->hTxRmDma); - - // Destroy Dma Buffers - DestroyDmaTransferBuffer(hUart->hRmMemory, hUart->pRxDmaBuffer, - hUart->pTxDmaBuffer, UART_RX_DMA_PING_BUFFER_SIZE << 1); - } - - // Tri-State the pin-mux pins - NV_ASSERT_SUCCESS(NvRmSetModuleTristate(hUart->hRmDevice, ModuleId, NV_TRUE)); - - // Destroy the mutex allocated for the uart read/write/register/channel access. - DestroyReadFlowLock(hUart); - DestroyWriteFlowLock(hUart); - DestroyRegisterAccessLock(hUart); - - - // Destroy the sync sempahores. - NvOsSemaphoreDestroy(hUart->hRxSynchSema); - NvOsSemaphoreDestroy(hUart->hTxSynchSema); - - // Free the memory of the uart handles. - NvOsFree(hUart); -} - -/** - * Create the handle for the uart channel. - * Thread safety: Caller responsibility. - */ -static NvError CreateUartChannelHandle( - NvRmDeviceHandle hRmDevice, - NvU32 ChannelId, - NvDdkUartHandle *phUart) -{ - NvError Error = NvSuccess; - NvDdkUartHandle hNewUart = NULL; - NvRmModuleID ModuleId; - NvRmModuleUartInterfaceCaps InterfaceCap; - - ModuleId = NVRM_MODULE_ID(NvRmModuleID_Uart, ChannelId); - - *phUart = NULL; - - if (NvRmSetModuleTristate(hRmDevice,ModuleId,NV_FALSE)!=NvSuccess) - return NvError_NotSupported; - - Error = NvRmGetModuleInterfaceCapabilities(hRmDevice, ModuleId, - sizeof(InterfaceCap), &InterfaceCap); - if (Error) - return Error; - - // If the number of lines available in platform is 0 then return error - // as the uart is not supported on the given platform. - if (InterfaceCap.NumberOfInterfaceLines == 0) - return NvError_NotSupported; - - // Allocoate the memory for the uart handle. - hNewUart = NvOsAlloc(sizeof(NvDdkUart)); - if (!hNewUart) - { - return NvError_InsufficientMemory; - } - - // Reset the memory allocated for the uart handle. - NvOsMemset(hNewUart, 0, sizeof(*hNewUart)); - - // Set the uart handle parameters. - hNewUart->hRmDevice = hRmDevice; - hNewUart->InstanceId = ChannelId; - hNewUart->OpenCount = 0; - hNewUart->NumberOfInterfaceLine = InterfaceCap.NumberOfInterfaceLines; - - hNewUart->WriteReq.hOnCompleteSema = NULL; - hNewUart->WriteReq.pCurrTransBuf = NULL; - - hNewUart->ReadReq.hOnCompleteSema = NULL; - hNewUart->ReadReq.pCurrTransBuf = NULL; - - hNewUart->hRxSynchSema = NULL; - hNewUart->hTxSynchSema = NULL; - - hNewUart->IsRtsFlowEnable = NV_FALSE; - hNewUart->IsCtsFlowEnable = NV_FALSE; - - hNewUart->hRmMemory = NULL; - hNewUart->RxDmaBuffPhysAdd = 0; - hNewUart->pRxDmaBuffer = NULL; - hNewUart->hRxRmDma = NULL; - - hNewUart->TxDmaBuffPhysAdd = 0; - hNewUart->pTxDmaBuffer = NULL; - hNewUart->hTxRmDma = NULL; - - hNewUart->hWriteMutex = NULL; - hNewUart->hReadMutex = NULL; - hNewUart->hRegisterAccessMutex = NULL; - - hNewUart->hModemSigChngCallback = NULL; - hNewUart->pUartInfo = s_pUartInfo; - hNewUart->hRmPowerEventSema = NULL; - hNewUart->RmPowerClientId = 0; - hNewUart->hOdmUart = NULL; - - hNewUart->IsRxApbDmaBased = NV_FALSE; - hNewUart->IsDmaReadStarted = NV_FALSE; - - hNewUart->IsStopPowerThread = NV_FALSE; - hNewUart->IsFreqBoosted = NV_FALSE; - hNewUart->IsSuspendedState = NV_FALSE; - - hNewUart->hUartPowerMgrThread = NULL; - hNewUart->hUartPowerMgrSema = NULL; - - // Initialize the uart configuration parameters. - hNewUart->UartConfig.UartBaudRate = 0; - hNewUart->UartConfig.UartDataLength = 5; - hNewUart->UartConfig.UartParityBit = NvDdkUartParity_None; - hNewUart->UartConfig.UartStopBit = NvDdkUartStopBit_1; - hNewUart->UartConfig.IsEnableIrdaModulation = NV_FALSE; - - NvDdkPrivUartHwRegisterInitialize(ChannelId, &hNewUart->UartHwRegs); - hNewUart->OldRtsState = hNewUart->UartHwRegs.IsRtsActive; - hNewUart->OldDtrState = hNewUart->UartHwRegs.IsDtrActive; - - // Initialize the baudrate dependent parameter. - SetBaudRateDependentParameter(hNewUart, 9600); - - // Get the soc capabilities and if error return here now. - Error = UartGetSocCapabilities(hRmDevice, ChannelId, &hNewUart->SocUartCaps); - if (!Error) - { - hNewUart->UartHwRegs.IsEndOfDataIntSupport = - hNewUart->SocUartCaps.IsEndOfDataIntSupported; - hNewUart->UartHwRegs.IsRtsHwFlowSupported = - hNewUart->SocUartCaps.IsRtsHwFlowControlSupported; - } - - // If error the return now. - if (Error) - { - NvOsFree(hNewUart); - return Error; - } - - // Create the odm uart handle - hNewUart->hOdmUart = NvOdmUartOpen(ChannelId); - - // Create the local buffer information. - Error = CreateLocalRxBuff(hNewUart, UART_RX_LOCAL_BUFFER_SIZE_MIN); - - // Create all mutex required for the channel. - if (!Error) - Error = CreateReadFlowLock(hNewUart); - if (!Error) - Error = CreateWriteFlowLock(hNewUart); - if (!Error) - Error = CreateRegisterAccessLock(hNewUart); - - // Create the synchronous semaphores. - if (!Error) - Error = NvOsSemaphoreCreate(&hNewUart->hRxSynchSema, 0); - - if (!Error) - Error = NvOsSemaphoreCreate(&hNewUart->hTxSynchSema, 0); - - // Create the read/write transfer information. - if (!Error) - { - InitTransferInfo(hNewUart->hRmDevice, &hNewUart->WriteReq); - InitTransferInfo(hNewUart->hRmDevice, &hNewUart->ReadReq); - - NvRmModuleGetBaseAddress(hRmDevice, ModuleId, - &hNewUart->UartHwRegs.RegsPhyBaseAdd, &hNewUart->UartHwRegs.BankSize); - - Error = NvRmPhysicalMemMap(hNewUart->UartHwRegs.RegsPhyBaseAdd, - hNewUart->UartHwRegs.BankSize, NVOS_MEM_READ_WRITE, - NvOsMemAttribute_Uncached, - (void **)&hNewUart->UartHwRegs.pRegsVirtBaseAdd); - } - - // Create the dma transfer buffer, allocate the dma and initialize the - // request structure. - if (!Error) - { - Error = CreateDmaTransferBuffer(hNewUart->hRmDevice, &hNewUart->hRmMemory, - &hNewUart->RxDmaBuffPhysAdd, (void **)&hNewUart->pRxDmaBuffer, - &hNewUart->TxDmaBuffPhysAdd, (void **)&hNewUart->pTxDmaBuffer, - UART_RX_DMA_PING_BUFFER_SIZE << 1); - - // Allocate the two dma (one for Rx and One for Tx) with high priority - if (!Error) - Error = NvRmDmaAllocate(hNewUart->hRmDevice, &hNewUart->hRxRmDma, - NV_FALSE, NvRmDmaPriority_High, NvRmDmaModuleID_Uart, - hNewUart->InstanceId); - if (!Error) - { - Error = NvRmDmaAllocate(hNewUart->hRmDevice, &hNewUart->hTxRmDma, - NV_FALSE, NvRmDmaPriority_High, NvRmDmaModuleID_Uart, - hNewUart->InstanceId); - } - if (Error) - { - hNewUart->IsDmaSupport = NV_FALSE; - DestroyDmaTransferBuffer(hNewUart->hRmMemory, hNewUart->pRxDmaBuffer, - hNewUart->pTxDmaBuffer, UART_RX_DMA_PING_BUFFER_SIZE << 1); - - NvRmDmaFree(hNewUart->hRxRmDma); - NvRmDmaFree(hNewUart->hTxRmDma); - hNewUart->hRmMemory = NULL; - hNewUart->pRxDmaBuffer = NULL; - hNewUart->pTxDmaBuffer = NULL; - hNewUart->hRxRmDma = NULL; - hNewUart->hTxRmDma = NULL; - Error = NvSuccess; - - } - else - { - hNewUart->IsDmaSupport = NV_TRUE; - hNewUart->WDmaReq.SourceBufferPhyAddress = hNewUart->TxDmaBuffPhysAdd; - hNewUart->WDmaReq.DestinationBufferPhyAddress = hNewUart->UartHwRegs.RegsPhyBaseAdd; - hNewUart->WDmaReq.SourceAddressWrapSize = 0; - hNewUart->WDmaReq.DestinationAddressWrapSize = 4; - hNewUart->TxDmaBufferSize = UART_RX_DMA_PING_BUFFER_SIZE << 1; - - hNewUart->RDmaReq.SourceBufferPhyAddress = hNewUart->UartHwRegs.RegsPhyBaseAdd; - hNewUart->RDmaReq.DestinationBufferPhyAddress = hNewUart->RxDmaBuffPhysAdd; - hNewUart->RDmaReq.SourceAddressWrapSize = 4; - hNewUart->RDmaReq.DestinationAddressWrapSize = 0; - hNewUart->RxDmaBufferSize = UART_RX_DMA_PING_BUFFER_SIZE << 1; - hNewUart->HalfRxDmaBufferSize = UART_RX_DMA_PING_BUFFER_SIZE; - - } - } - - // Register as the Rm power client - if (!Error) - { - Error = NvOsSemaphoreCreate(&hNewUart->hRmPowerEventSema, 0); - if (!Error) - Error = NvRmPowerRegister(hNewUart->hRmDevice, hNewUart->hRmPowerEventSema, - &hNewUart->RmPowerClientId); - } - - // Enable power for uart module - if (!Error) - Error = NvRmPowerVoltageControl(hNewUart->hRmDevice, ModuleId, - hNewUart->RmPowerClientId, - NvRmVoltsUnspecified, NvRmVoltsUnspecified, - NULL, 0, NULL); - - // Enable the clock. - if (!Error) - Error = NvRmPowerModuleClockControl(hRmDevice, ModuleId, hNewUart->RmPowerClientId, - NV_TRUE); - - // Create the thread which keep the power/frequency requirement of the - // uart channel. - if (!Error) - { - Error = NvOsSemaphoreCreate(&hNewUart->hUartPowerMgrSema, 0); - if (!Error) - Error = NvOsThreadCreate(UartPowerManagerThread, hNewUart, &hNewUart->hUartPowerMgrThread); - } - - // Reset the uart controller. - if (!Error) - NvRmModuleReset(hRmDevice, ModuleId); - - if (!Error) - Error = RegisterUartInterrupt(hRmDevice, hNewUart); - - // Configure the uart handle for the non dma mode transfer as basic transfer. - if (!Error) - { - // Enable the fifo mode of the uart and reset the fifo - NvDdkPrivUartHwInitFifo(&hNewUart->UartHwRegs); - NvDdkPrivUartHwSetDmaMode(&hNewUart->UartHwRegs, hNewUart->IsDmaSupport); - } - // If error then destroy all the allocation done here. - if (Error) - { - DestroyUartChannelHandle(hNewUart); - hNewUart = NULL; - } - *phUart = hNewUart; - return Error; -} - -/** - * Read from the local buffer. - * Thread safety: Caller responsibility. - */ -static NvU32 ReadFromLocalBuffer( - NvU8 *pReceiveBuffer, - NvU32 BytesRequested, - UartLocalBuffer *pRxLocalBuffer) -{ - NvU32 DataToBeRead; - NvU32 DataRead = 0; - - // Get the current write index and then read based on this index. - DataToBeRead = NV_MIN(BytesRequested, pRxLocalBuffer->DataAvailable); - while (DataToBeRead) - { - *pReceiveBuffer++ = pRxLocalBuffer->pBuffPtr[pRxLocalBuffer->ReadIndex++]; - if (pRxLocalBuffer->ReadIndex >= pRxLocalBuffer->TotalBufferSize) - pRxLocalBuffer->ReadIndex = 0; - - DataToBeRead--; - DataRead++; - } - pRxLocalBuffer->DataAvailable = pRxLocalBuffer->DataAvailable - DataRead; - return DataRead; -} - - -/** - * Stop the write operation. - * Thread protection: By caller - */ -static void UartStopWrite(NvDdkUartHandle hUart, NvBool IsResetTxFifoIfNotBusy) -{ - // If write transfer state is not busy then invalid state error. - if (hUart->WriteReq.IsBusy) - { - hUart->WriteReq.IsStopReq = NV_TRUE; - NvOsSemaphoreSignal(hUart->WriteReq.hOnCompleteSema); - if (!hUart->IsDmaSupport) - { - LockRegisterAccess(hUart); - NvDdkPrivUartHwSetTransmitInterrupt(&hUart->UartHwRegs, NV_FALSE); - UnlockRegisterAccess(hUart); - } - } - else - { - if (IsResetTxFifoIfNotBusy) - NvDdkPrivUartHwResetFifo(&hUart->UartHwRegs, - UartDataDirection_Transmit); - } -} - - -/** - * Wait till tx fifo become empty. This is required when either we change the - * baudrate or we go for suspend. - * Thread protection: By caller - */ -static void WaitTillTxFifoEmpty(NvDdkUartHandle hUart) -{ - NvDdkUartConfiguarations *pUartCurrConfig = NULL; - - NvBool IsTxFifoEmpty; - NvU32 CharacterWaitTimeInUs; - NvU32 WaitTimeInMs; - NvU32 RemainingWaitTimeoutUs; - - // Get the uart configuration pointers. - pUartCurrConfig = &hUart->UartConfig; - - // Wait for the Tx fifo to be empty if the current baudrate is non zero. - // Wait time is maximum of (fifo depth + 4) character time, and if it - // does not get flushed then reset the fifo. - // Here + 4 is for the safer side. - if (pUartCurrConfig->UartBaudRate) - { - // 1 char time in microsecond: 1 char*1000000us*10 bitperchar - CharacterWaitTimeInUs = (10000000 + pUartCurrConfig->UartBaudRate - 1)/ - (pUartCurrConfig->UartBaudRate); - RemainingWaitTimeoutUs = (hUart->SocUartCaps.FifoDepth + 4)*CharacterWaitTimeInUs; - WaitTimeInMs = (CharacterWaitTimeInUs + 999)/1000; - while(1) - { - IsTxFifoEmpty = NvDdkPrivUartHwIsTransmitFifoEmpty(&hUart->UartHwRegs); - if (IsTxFifoEmpty) - break; - NvOsSleepMS(WaitTimeInMs); - if (RemainingWaitTimeoutUs > (WaitTimeInMs * 1000)) - { - RemainingWaitTimeoutUs -= (WaitTimeInMs * 1000); - continue; - } - break; - } - - // If the tx fifo is not empty then reset the fifo forcefully. - if (!IsTxFifoEmpty) - { - LockRegisterAccess(hUart); - NvDdkPrivUartHwResetFifo(&hUart->UartHwRegs, UartDataDirection_Transmit); - UnlockRegisterAccess(hUart); - } - } - -} -/** - * Open the uart handle. - */ -NvError -NvDdkUartOpen( - NvRmDeviceHandle hRmDevice, - NvU32 ChannelId, - NvDdkUartHandle *phUart) -{ - NvError Error = NvSuccess; - DdkUartChannelInfo *pUartInfo = NULL; - NvDdkUart *pUartChannel = NULL; - NvU32 InstanceAvailable; - - NV_ASSERT(phUart); - NV_ASSERT(hRmDevice); - - *phUart = NULL; - - InstanceAvailable = NvRmModuleGetNumInstances(hRmDevice, NvRmModuleID_Uart); - if (ChannelId >= InstanceAvailable) - return NvError_NotSupported; - - Error = InitUartInformation(hRmDevice); - if (Error) - return Error; - pUartInfo = s_pUartInfo; - - // Lock the uart info mutex access. - NvOsMutexLock(pUartInfo->hUartOpenMutex); - - // Check for the open uart handle to find out whether same instance port - // name exit or not. - pUartChannel = pUartInfo->hUartList[ChannelId]; - - // If the uart handle does not exist then create it. - if (!pUartChannel) - { - Error = CreateUartChannelHandle(hRmDevice, ChannelId, &pUartChannel); - if (!Error) - { - pUartInfo->hUartList[ChannelId] = pUartChannel; - pUartChannel->OpenCount++; - } - } - - // Unlock the uart info access. - NvOsMutexUnlock(pUartInfo->hUartOpenMutex); - - // If no error then update the passed pointers. - if (!Error) - { - *phUart = pUartChannel; - } - return Error; -} - -/** - * Close the uart handle. - */ -void NvDdkUartClose(NvDdkUartHandle hUart) -{ - DdkUartChannelInfo *pUartInformation = NULL; - - // if null parameter then do nothing. - if (!hUart) - return; - - // Get the uart information pointer. - pUartInformation = hUart->pUartInfo; - - // Lock the uart information access. - NvOsMutexLock(pUartInformation->hUartOpenMutex); - - // decrement the open count and it becomes 0 then release all the allocation - // done for this handle. - hUart->OpenCount--; - - // If the open count become zero then remove from the list of handles and - // free.. - if (hUart->OpenCount == 0) - { - // Read/write should not be on this channel. - NV_ASSERT((!hUart->ReadReq.IsBusy) || (!hUart->WriteReq.IsBusy)); - - pUartInformation->hUartList[hUart->InstanceId] = NULL; - // Now destroy the handles. - DestroyUartChannelHandle(hUart); - } - - // Unlock the uart information access. - NvOsMutexUnlock(pUartInformation->hUartOpenMutex); -} - -/** - * Set the uart configuration which is configured currently. - */ -NvError -NvDdkUartSetConfiguration( - NvDdkUartHandle hUart, - const NvDdkUartConfiguarations* const pUartNewConfig) -{ - NvError Error = NvSuccess; - NvDdkUartConfiguarations *pUartCurrConfig = NULL; - NvU32 ConfiguredClockFreq = 0; - NvRmModuleID ModuleId; - NvU32 MinClockFreqReqd; - NvU32 MaxClockFreqReqd; - NvU32 ClockFreqReqd = 0; - - NV_ASSERT(hUart); - NV_ASSERT(pUartNewConfig); - if (hUart->IsSuspendedState) - return NvError_InvalidState; - - // Stop bit 1.5 is supported only with the data length of 5. - if ((pUartNewConfig->UartStopBit == NvDdkUartStopBit_1_5) && - ((pUartNewConfig->UartDataLength != 5))) - return NvError_NotSupported; - - // Stop bit 2 is not supported with the data length of 5. - if ((pUartNewConfig->UartStopBit == NvDdkUartStopBit_2) && - ((pUartNewConfig->UartDataLength == 5))) - return NvError_NotSupported; - - // Get the uart configuration pointers. - pUartCurrConfig = &hUart->UartConfig; - - // Wait for the Tx fifo to be empty. - WaitTillTxFifoEmpty(hUart); - - LockRegisterAccess(hUart); - // Set the required baud rate if there is any change. - if (pUartNewConfig->UartBaudRate != pUartCurrConfig->UartBaudRate) - { - // Get the clock frequency related to the baud rate. - NvDdkPrivUartHwGetReqdClockSourceFreq(pUartNewConfig->UartBaudRate, - &MinClockFreqReqd, &ClockFreqReqd, &MaxClockFreqReqd); - - ModuleId = NVRM_MODULE_ID(NvRmModuleID_Uart, hUart->InstanceId); - Error = NvRmPowerModuleClockConfig(hUart->hRmDevice, - ModuleId, 0, MinClockFreqReqd, MaxClockFreqReqd, - &ClockFreqReqd, 1, &ConfiguredClockFreq, 0); - - // If not error then check for configured clock frequency and verify. - if (!Error) - { - // Set the baudrate and get the required clock frequency. - Error = NvDdkPrivUartHwSetBaudRate(&hUart->UartHwRegs, - pUartNewConfig->UartBaudRate, ConfiguredClockFreq); - if (!Error) - pUartCurrConfig->UartBaudRate = pUartNewConfig->UartBaudRate; - } - - // If error then return here only. - if (Error) - goto ErrorExit; - - SetBaudRateDependentParameter(hUart, pUartCurrConfig->UartBaudRate); - } - - // Configured for parity bit. - if (pUartNewConfig->UartParityBit != pUartCurrConfig->UartParityBit) - { - Error = NvDdkPrivUartHwSetParityBit(&hUart->UartHwRegs, - pUartNewConfig->UartParityBit); - if (Error) - goto ErrorExit; - pUartCurrConfig->UartParityBit = pUartNewConfig->UartParityBit; - } - - // Configured for the data length. - if (pUartNewConfig->UartDataLength != pUartCurrConfig->UartDataLength) - { - Error = NvDdkPrivUartHwSetDataLength(&hUart->UartHwRegs, - pUartNewConfig->UartDataLength); - if (Error) - goto ErrorExit; - pUartCurrConfig->UartDataLength = pUartNewConfig->UartDataLength; - } - - // Configured for stop bit length. - if (pUartNewConfig->UartStopBit != pUartCurrConfig->UartStopBit) - { - Error = NvDdkPrivUartHwSetStopBit(&hUart->UartHwRegs, - pUartNewConfig->UartStopBit); - if (Error) - goto ErrorExit; - pUartCurrConfig->UartStopBit = pUartNewConfig->UartStopBit; - } - - // Configured for the Irda modulation. - if (pUartNewConfig->IsEnableIrdaModulation != pUartCurrConfig->IsEnableIrdaModulation) - { - NvDdkPrivUartHwSetIrdaCoding(&hUart->UartHwRegs, pUartNewConfig->IsEnableIrdaModulation); - pUartCurrConfig->IsEnableIrdaModulation = pUartNewConfig->IsEnableIrdaModulation; - } -ErrorExit: - UnlockRegisterAccess(hUart); - - // Boost frequency now. - if ((!Error) && (!hUart->IsFreqBoosted)) - NvOsSemaphoreSignal(hUart->hUartPowerMgrSema); - - return Error; -} - -/** - * Get the uart configuartion which is configured currently. - */ -NvError -NvDdkUartGetConfiguration( - NvDdkUartHandle hUart, - NvDdkUartConfiguarations* const pUartDriverConfiguration) -{ - NV_ASSERT(hUart); - NV_ASSERT(pUartDriverConfiguration); - if (hUart->IsSuspendedState) - return NvError_InvalidState; - - LockRegisterAccess(hUart); - // Copy the current configured parameter for the uart communication. - NvOsMemcpy(pUartDriverConfiguration, &hUart->UartConfig, - sizeof(*pUartDriverConfiguration)); - UnlockRegisterAccess(hUart); - return NvSuccess; -} - -NvError -NvDdkUartStartReadOnBuffer( - NvDdkUartHandle hUart, - NvOsSemaphoreHandle hRxEventSema, - NvU32 BufferSize) -{ - NvError Error = NvSuccess; - NvU32 NewBufferSize; - NvU8 *pNewBuff = NULL; - - NV_ASSERT(hUart); - NV_ASSERT(BufferSize); - if (hUart->IsSuspendedState) - return NvError_InvalidState; - - // If reading is going on then it is not possible to change the size of the - // local buffering - if (hUart->ReadReq.IsBusy) - return NvError_InvalidState; - - // Create the local buffer first. - LockReadFlow(hUart); - if (hUart->ReadReq.IsBusy) - { - UnlockReadFlow(hUart); - return NvError_InvalidState; - } - - // Deactivate the RTS line to stop the sender to data send as ddk is not - // able to read the data. - LockRegisterAccess(hUart); - if (hUart->IsRtsFlowEnable) - NvDdkPrivUartHwSetModemSignal(&hUart->UartHwRegs, NvDdkUartSignalName_Rts, NV_FALSE); - - // Disable receive interrupt. - NvDdkPrivUartHwSetReceiveInterrupt(&hUart->UartHwRegs, NV_TRUE, hUart->IsRxApbDmaBased); - UnlockRegisterAccess(hUart); - - // Abort the dma if it is started. - if ((hUart->IsDmaReadStarted) && (hUart->IsRxApbDmaBased)) - NvRmDmaAbort(hUart->hRxRmDma); - - hUart->IsRxApbDmaBased = NV_FALSE; - hUart->IsDmaReadStarted = NV_FALSE; - - // Reset the Rx fifo. - NvDdkPrivUartHwResetFifo(&hUart->UartHwRegs, UartDataDirection_Receive); - - // Check whether it is same size or not. If not then reallocate it. - NewBufferSize = NV_MAX(UART_RX_LOCAL_BUFFER_SIZE_MIN, BufferSize); - if (NewBufferSize != hUart->LocalRxBuff.TotalBufferSize) - { - pNewBuff = NvOsAlloc(NewBufferSize); - - // If allocated successfully then use this memory for local buffering. - if(pNewBuff) - { - // Free the existing buffer. - if (hUart->LocalRxBuff.pBuffPtr) - NvOsFree(hUart->LocalRxBuff.pBuffPtr); - hUart->LocalRxBuff.pBuffPtr = pNewBuff; - } - else - { - NewBufferSize = hUart->LocalRxBuff.TotalBufferSize; - } - } - hUart->LocalRxBuff.ReadIndex = 0; - hUart->LocalRxBuff.WriteIndex = 0; - hUart->LocalRxBuff.DataAvailable = 0; - hUart->LocalRxBuff.TotalBufferSize = NewBufferSize; - hUart->LocalRxBuff.BufferLevelHigh = (NewBufferSize >> 1); - hUart->LocalRxBuff.hDataAvailableSema = hRxEventSema; - hUart->LocalRxBuff.hLineStatusSema = hRxEventSema; - - // Start the dma to start receiving the data. - if (hUart->IsDmaSupport) - { - hUart->RDmaReq.TransferSize = hUart->RxDmaBufferSize; - Error = NvRmDmaStartDmaTransfer(hUart->hRxRmDma, &hUart->RDmaReq, - NvRmDmaDirection_Forward, 0, hUart->LocalRxBuff.hDataAvailableSema); - if (!Error) - { - hUart->IsRxApbDmaBased = NV_TRUE; - hUart->IsDmaReadStarted = NV_TRUE; - hUart->LastReadIndex = 0; - } - Error = NvSuccess; - } - - LockRegisterAccess(hUart); - // Enable the receive interrupt. - NvDdkPrivUartHwSetReceiveInterrupt(&hUart->UartHwRegs, NV_TRUE, hUart->IsRxApbDmaBased); - - // Activate the RTS line as ddk is able to receive more data as receive - // buffer is empty. - if (hUart->IsRtsFlowEnable) - NvDdkPrivUartHwSetModemSignal(&hUart->UartHwRegs, NvDdkUartSignalName_Rts, - NV_TRUE); - - UnlockRegisterAccess(hUart); - UnlockReadFlow(hUart); - return Error; -} - -NvError NvDdkUartClearReceiveBuffer(NvDdkUartHandle hUart) -{ - NV_ASSERT(hUart); - if (hUart->IsSuspendedState) - return NvError_InvalidState; - - return NvDdkUartStartReadOnBuffer(hUart, hUart->LocalRxBuff.hDataAvailableSema, - hUart->LocalRxBuff.TotalBufferSize); -} - -NvError -NvDdkUartUpdateReceiveBuffer( - NvDdkUartHandle hUart, - NvU32 *pAvailableBytes) -{ - NvU32 SpaceAvailable; - NvError Error = NvSuccess; - NvU32 TransferdCount; - NvU32 DataToBeCopied; - NvU8 CpuReadBuffer[30]; - NvU32 TempTransCount; - NvU32 Index; - NvBool IsDmaIndexTobeReset = NV_FALSE; - NvU32 BytesRead; - NvBool IsBreakDetectd; - - NV_ASSERT(hUart); - NV_ASSERT(pAvailableBytes); - if (hUart->IsSuspendedState) - return NvError_InvalidState; - - // Lock the transfer status mutex. - LockReadFlow(hUart); - - BytesRead = 0; - TransferdCount = 0; - IsBreakDetectd = NvDdkPrivUartHwIsBreakSignalDetected(&hUart->UartHwRegs); - if (hUart->IsRxApbDmaBased) - { - if (NvDdkPrivUartHwIsDataAvailableInFifo(&hUart->UartHwRegs)) - { - // Disable the rts line as cpu is going to read the fifo. - if (hUart->IsRtsFlowEnable) - NvDdkPrivUartHwSetModemSignal(&hUart->UartHwRegs, - NvDdkUartSignalName_Rts, NV_FALSE); - - // Get the transfer Count transferred by the dma. Also stop the apb - // dma so that apb dma will not be able to transfer the data. - Error = NvRmDmaGetTransferredCount(hUart->hRxRmDma, &TransferdCount, NV_TRUE); - NV_ASSERT(Error == NvSuccess); - if (Error) - TransferdCount = 0; - - // Now Read the fifo by cpu. - hUart->ReadReq.TransferStatus = - NvDdkPrivUartHwReadFromReceiveFifo(&hUart->UartHwRegs, - CpuReadBuffer, 25, &BytesRead); - DEBUG_PRINT_RX_ERR(hUart->ReadReq.TransferStatus, - ("NvDdkUartUpdateReceiveBuffer(): LSR Status shows error Error occured 0x%08x\n", hUart->ReadReq.TransferStatus)); - - // Now start the dma so that receive data can be transferred again. - Error = NvRmDmaGetTransferredCount(hUart->hRxRmDma, &TempTransCount, NV_FALSE); - NV_ASSERT(Error == NvSuccess); - if (Error) - TransferdCount = 0; - IsDmaIndexTobeReset = NV_TRUE; - } - else - { - // Get the transfer Count transferred by the dma without stopping the dma. - Error = NvRmDmaGetTransferredCount(hUart->hRxRmDma, &TransferdCount, NV_FALSE); - NV_ASSERT(Error == NvSuccess); - if (Error) - TransferdCount = 0; - hUart->ReadReq.TransferStatus = NvSuccess; - - } - if (TransferdCount) - { - //NvOsDebugPrintf("UartUpdate old TransCount 0x%08x and old Last ReadIndex 0x%08x\n ", - //TransferdCount, hUart->LastReadIndex); - if (hUart->LastReadIndex < hUart->HalfRxDmaBufferSize) - TransferdCount = TransferdCount - hUart->LastReadIndex; - else - TransferdCount = TransferdCount - (hUart->LastReadIndex - hUart->HalfRxDmaBufferSize); - } - - // Copy in the circular buffer - if (TransferdCount) - { - SpaceAvailable = hUart->LocalRxBuff.TotalBufferSize - hUart->LocalRxBuff.DataAvailable; - DataToBeCopied = NV_MIN(SpaceAvailable, TransferdCount); - - // For debugging the DataToBeCopied should never be less than - // the TransferdCount - NV_ASSERT(DataToBeCopied == TransferdCount); - for (Index = 0; Index < DataToBeCopied; ++Index) - { - hUart->LocalRxBuff.pBuffPtr[hUart->LocalRxBuff.WriteIndex++] = - hUart->pRxDmaBuffer[hUart->LastReadIndex++]; - if (hUart->LocalRxBuff.WriteIndex >= hUart->LocalRxBuff.TotalBufferSize) - hUart->LocalRxBuff.WriteIndex = 0; - if (hUart->LastReadIndex >= hUart->RxDmaBufferSize) - hUart->LastReadIndex = 0; - hUart->LocalRxBuff.DataAvailable++; - } -// NvOsDebugPrintf("uartUpdate New TransCount 0x%08x and new LastReadIndex 0x%08x\n", -// TransferdCount, hUart->LastReadIndex); - } - if (BytesRead) - { - // Get the lcoal buffer pointer. - SpaceAvailable = hUart->LocalRxBuff.TotalBufferSize - hUart->LocalRxBuff.DataAvailable; - DataToBeCopied = NV_MIN(BytesRead, SpaceAvailable); - - // FixME!! For debugging the DataToBeCopied should never be less than - // the BytesRead - NV_ASSERT(DataToBeCopied == BytesRead); - - for (Index = 0; Index < DataToBeCopied; ++Index) - { - hUart->LocalRxBuff.pBuffPtr[hUart->LocalRxBuff.WriteIndex++] = - CpuReadBuffer[Index]; - if (hUart->LocalRxBuff.WriteIndex >= hUart->LocalRxBuff.TotalBufferSize) - hUart->LocalRxBuff.WriteIndex = 0; - hUart->LocalRxBuff.DataAvailable++; - } - } - - if (IsDmaIndexTobeReset) - hUart->LastReadIndex = 0; - - NvDdkPrivUartHwSetReceiveInterrupt(&hUart->UartHwRegs, NV_TRUE, NV_TRUE); - } - - // See whether the readcall is waiting for the data or not. If yes then - // copy on client buffer. - if (hUart->ReadReq.IsBusy) - { - // If transfer status is success then read form local buffer - // and upate the client information and inform if it - // request has been completed. - if ((hUart->ReadReq.TransferStatus == NvSuccess) && (!IsBreakDetectd)) - { - BytesRead = ReadFromLocalBuffer(hUart->ReadReq.pCurrTransBuf, - hUart->ReadReq.BytesRemaining, &hUart->LocalRxBuff); - - // If bytes read then update the read parameters. - if (BytesRead) - { - hUart->ReadReq.pCurrTransBuf += BytesRead; - hUart->ReadReq.BytesRemaining -= BytesRead; - hUart->ReadReq.BytesTransferred += BytesRead; - } - } - - // If the transfer status is error or bytes remaining for - // client is 0 then inform the client. - if ((hUart->ReadReq.TransferStatus) || (!hUart->ReadReq.BytesRemaining) - || IsBreakDetectd) - { - // Break signal status is higher priority than other status. - if (IsBreakDetectd) - hUart->ReadReq.TransferStatus = NvError_UartBreakReceived; - - // Update the current state. - hUart->ReadReq.IsBusy = NV_FALSE; - - // Inform the client that transfer is complete. - NvOsSemaphoreSignal(hUart->ReadReq.hOnCompleteSema); - } - } - else - { - // Break signal status is higher priority than other status. - if (IsBreakDetectd) - hUart->ReadReq.TransferStatus = NvError_UartBreakReceived; - } - - // If flow control is enabled and if the data available is more then the - // higher water level of the local buffer then disable the rts line. - if (hUart->IsRtsFlowEnable) - { - if (hUart->LocalRxBuff.DataAvailable < hUart->LocalRxBuff.BufferLevelHigh) - NvDdkPrivUartHwSetModemSignal(&hUart->UartHwRegs, - NvDdkUartSignalName_Rts, NV_TRUE); - else - NvDdkPrivUartHwSetModemSignal(&hUart->UartHwRegs, - NvDdkUartSignalName_Rts, NV_FALSE); - } - UnlockReadFlow(hUart); - - *pAvailableBytes = hUart->LocalRxBuff.DataAvailable; - return hUart->ReadReq.TransferStatus; -} - -/** - * Read the data from com channel. - * Thread safety: Provided in the function. - */ -NvError -NvDdkUartRead( - NvDdkUartHandle hUart, - NvU8 *pReceiveBuffer, - NvU32 BytesRequested, - NvU32 *pBytesRead, - NvU32 WaitTimeoutMs) -{ - NvError Error = NvSuccess; - NvU32 BytesRead; -#if ENABLE_READ_PROFILE - NvU32 EntryTime = NvOsGetTimeMS(); -#endif - - NV_ASSERT(hUart); - NV_ASSERT(pReceiveBuffer); - NV_ASSERT(pBytesRead); - if (hUart->IsSuspendedState) - return NvError_InvalidState; - - // Check for the status and if it is in busy state then return error. - if (hUart->ReadReq.IsBusy) - { - DEBUG_PRINT_RX_ERR(1, ("NvDdkUartRead(): Error occured Invalid state\n")); - return NvError_InvalidState; - } - - LockReadFlow(hUart); - if (hUart->ReadReq.IsBusy) - { - UnlockReadFlow(hUart); - DEBUG_PRINT_RX_ERR(1, ("NvDdkUartRead(): Error occured Invalid state\n")); - return NvError_InvalidState; - } - - // Get the data from the local buffer and if it has the requested number of - // bytes then comeout. - BytesRead = ReadFromLocalBuffer(pReceiveBuffer, BytesRequested, &hUart->LocalRxBuff); - // If read completely or if wait timeout is 0 (read whatever available - // in the fifo) or any error then return. - if ((BytesRead == BytesRequested) || (!WaitTimeoutMs) || - (hUart->ReadReq.TransferStatus)) - { - Error = hUart->ReadReq.TransferStatus; - hUart->ReadReq.TransferStatus = NvSuccess; - - // If flow control is enabled and if the data available is less then the - // higher water level of the local buffer then enable the rts line. - if (hUart->IsRtsFlowEnable) - { - if (hUart->LocalRxBuff.DataAvailable < hUart->LocalRxBuff.BufferLevelHigh) - NvDdkPrivUartHwSetModemSignal(&hUart->UartHwRegs, - NvDdkUartSignalName_Rts, NV_TRUE); - } - - UnlockReadFlow(hUart); - *pBytesRead = BytesRead; - DEBUG_PRINT_RX_ERR(Error, ("NvDdkUartRead(): Error occured 0x%08x\n",Error)); -#if ENABLE_READ_PROFILE - if (!Error) - NvOsDebugPrintf("NvDdkUartRead(): EntryTime 0x%08x and ExitTime 0x%08x\n", - EntryTime, NvOsGetTimeMS()); -#endif - return Error; - } - - hUart->ReadReq.pReqBuffer = pReceiveBuffer; - hUart->ReadReq.pCurrTransBuf = pReceiveBuffer + BytesRead; - hUart->ReadReq.BytesRequested = BytesRequested; - hUart->ReadReq.BytesRemaining = BytesRequested - BytesRead; - hUart->ReadReq.BytesTransferred = BytesRead; - hUart->ReadReq.TransferStatus = NvSuccess; - hUart->ReadReq.hOnCompleteSema = hUart->hRxSynchSema; - hUart->ReadReq.IsStopReq = NV_FALSE; - hUart->ReadReq.IsBusy = NV_TRUE; - - // Reset the semaphore count - ResetSemaphoreCount(hUart->hRxSynchSema); - UnlockReadFlow(hUart); - *pBytesRead = 0; - Error = NvOsSemaphoreWaitTimeout(hUart->ReadReq.hOnCompleteSema, WaitTimeoutMs); - - // Check the status - LockReadFlow(hUart); - if ((hUart->ReadReq.TransferStatus) || (hUart->ReadReq.IsStopReq) || - (Error == NvError_Timeout)) - { - hUart->ReadReq.IsBusy = NV_FALSE; - if (!hUart->ReadReq.BytesRemaining) - Error = NvSuccess; - else - Error = (hUart->ReadReq.TransferStatus)? hUart->ReadReq.TransferStatus: NvError_Timeout; - } - UnlockReadFlow(hUart); - - DEBUG_PRINT_RX_ERR(((Error) && (Error != NvError_Timeout)), - ("NvDdkUartRead(): Error occured 0x%08x\n",Error)); - *pBytesRead = hUart->ReadReq.BytesTransferred; - -#if ENABLE_READ_PROFILE - if (!Error) - NvOsDebugPrintf("NvDdkUartRead(): EntryTime 0x%08x and ExitTime 0x%08x\n", - EntryTime, NvOsGetTimeMS()); -#endif - return Error; -} - -/** - * Stop the write opeartion. - */ -void NvDdkUartStopRead(NvDdkUartHandle hUart) -{ - NV_ASSERT(hUart); - if (hUart->IsSuspendedState) - return; - - // Update the current transfer state and current transfer parameters. - LockReadFlow(hUart); - // If read transfer state is not busy then invalid state error. - if (hUart->ReadReq.IsBusy) - { - NvOsSemaphoreSignal(hUart->ReadReq.hOnCompleteSema); - hUart->ReadReq.IsBusy = NV_FALSE; - hUart->ReadReq.IsStopReq = NV_TRUE; - } - UnlockReadFlow(hUart); -} - -/** - * Transmit the data from com channel. - * Thread safety: Provided in the function. - */ -NvError -NvDdkUartWrite( - NvDdkUartHandle hUart, - NvU8 *pTransmitBuffer, - NvU32 BytesRequested, - NvU32 *pBytesWritten, - NvU32 WaitTimeoutMs) -{ - NvError Error = NvSuccess; - NvU32 BytesWritten; - NvU32 StartTime; - NvU32 CurrentTime; - NvU32 TimeElapsed; - NvU32 DmaBytesRemaining; - NvU32 TransferSize; - NvU32 DmaTransferedCount; - NvU32 Timeout; - NvBool IsCtsActive; -#if DEBUG_WRITE_TIMEOUT - NvBool IsCtsPrevActive = NV_FALSE; -#endif -#if ENABLE_WRITE_PROFILE - NvU32 EntryTime = NvOsGetTimeMS(); -#endif - - NV_ASSERT(hUart); - NV_ASSERT(pTransmitBuffer); - NV_ASSERT(pBytesWritten); - - // We dont support the timeout to be 0. Lets assert for debug. - NV_ASSERT(WaitTimeoutMs); - if (!WaitTimeoutMs) - return NvError_BadParameter; - - if (hUart->IsSuspendedState) - return NvError_InvalidState; - -#if DEBUG_WRITE_TIMEOUT - if (hUart->IsCtsFlowEnable) - IsCtsPrevActive = NvDdkPrivUartHwIsCtsActive(&hUart->UartHwRegs); - if (!IsCtsPrevActive) - NvOsDebugPrintf("The CTS is inactive %d\n", IsCtsPrevActive); -#endif - - if (!hUart->IsFreqBoosted) - NvOsSemaphoreSignal(hUart->hUartPowerMgrSema); - - LockWriteFlow(hUart); - // If current write transfer state is busy then return error. - if (hUart->WriteReq.IsBusy) - { - UnlockWriteFlow(hUart); - return NvError_InvalidState; - } - hUart->WriteReq.IsBusy = NV_TRUE; - hUart->WriteReq.pReqBuffer = pTransmitBuffer; - hUart->WriteReq.pCurrTransBuf = pTransmitBuffer; - hUart->WriteReq.BytesRequested = BytesRequested; - hUart->WriteReq.BytesTransferred = 0; - hUart->WriteReq.BytesRemaining = BytesRequested; - hUart->WriteReq.IsStopReq = NV_FALSE; - hUart->IsWritePolling = NV_FALSE; - UnlockWriteFlow(hUart); - - StartTime = NvOsGetTimeMS(); - // Use interrupt/dma based transfer if the number of bytes requested is more - // than polling limit. - if (hUart->WriteReq.BytesRemaining > hUart->MaxTxBytesPolling) - { - if (hUart->IsDmaSupport) - { - // Apb dma based transfer - hUart->WriteReq.hOnCompleteSema = hUart->hTxSynchSema; - - // Reset the semaphore if it is already signalled. - ResetSemaphoreCount(hUart->WriteReq.hOnCompleteSema); - - // APB dma accept multiple of 4 bytes only so transfer the data using the apb dma - // to nearest of 4 in lower side. - DmaBytesRemaining = ((hUart->WriteReq.BytesRequested >> 2) << 2); - while (DmaBytesRemaining) - { - TransferSize = NV_MIN(hUart->TxDmaBufferSize, DmaBytesRemaining); - NvOsMemcpy(hUart->pTxDmaBuffer, hUart->WriteReq.pCurrTransBuf, TransferSize); - hUart->WDmaReq.TransferSize = TransferSize; - Error = NvRmDmaStartDmaTransfer(hUart->hTxRmDma, &hUart->WDmaReq, - NvRmDmaDirection_Forward, 0, hUart->WriteReq.hOnCompleteSema); - if (Error) - break; - - Error = NvOsSemaphoreWaitTimeout(hUart->WriteReq.hOnCompleteSema, WaitTimeoutMs); - // The semaphore can be signalled by stopping the transfer or transfer - // complets. - if ((hUart->WriteReq.IsStopReq) || (Error == NvError_Timeout)) - { - Error = NvRmDmaGetTransferredCount(hUart->hTxRmDma, &DmaTransferedCount, NV_TRUE); - - // Aborting the dma request if the dma current transaction incomplete - NvRmDmaAbort(hUart->hTxRmDma); - if (Error) - { - DmaTransferedCount = 0; - } - else - { - hUart->WriteReq.BytesTransferred += DmaTransferedCount; - hUart->WriteReq.pCurrTransBuf += DmaTransferedCount; - DmaBytesRemaining -= DmaTransferedCount; - // If transfer is not completed the return timeout error - if (!Error) - Error = (DmaBytesRemaining)? NvError_Timeout: NvSuccess; - } - break; - } - hUart->WriteReq.BytesTransferred += TransferSize; - hUart->WriteReq.pCurrTransBuf += TransferSize; - DmaBytesRemaining -= TransferSize; - } - - hUart->WriteReq.BytesRemaining = hUart->WriteReq.BytesRequested - - hUart->WriteReq.BytesTransferred; - } - else - { - // Interrupt based transfer. - hUart->WriteReq.hOnCompleteSema = hUart->hTxSynchSema; - LockRegisterAccess(hUart); - NvDdkPrivUartHwSetFifoTriggerLevel(&hUart->UartHwRegs, UartDataDirection_Transmit, 8); - NvDdkPrivUartHwSetTransmitInterrupt(&hUart->UartHwRegs, NV_TRUE); - UnlockRegisterAccess(hUart); - Error = NvOsSemaphoreWaitTimeout(hUart->WriteReq.hOnCompleteSema, WaitTimeoutMs); - if ((hUart->WriteReq.IsStopReq) || (Error == NvError_Timeout)) - { - LockRegisterAccess(hUart); - NvDdkPrivUartHwSetTransmitInterrupt(&hUart->UartHwRegs, NV_FALSE); - UnlockRegisterAccess(hUart); - } - } - } - - if ((!Error) && (hUart->WriteReq.BytesRemaining) && (!hUart->WriteReq.IsStopReq)) - { - hUart->IsWritePolling = NV_TRUE; - - // Do by polling - while (hUart->WriteReq.BytesRemaining) - { - BytesWritten = NvDdkPrivUartHwPollingWriteInTransmitFifo(&hUart->UartHwRegs, - hUart->WriteReq.pCurrTransBuf, hUart->WriteReq.BytesRemaining); - if (BytesWritten) - { - hUart->WriteReq.pCurrTransBuf += BytesWritten; - hUart->WriteReq.BytesRemaining -= BytesWritten; - hUart->WriteReq.BytesTransferred += BytesWritten; - continue; - } - // Calculate the timeouts. - if (WaitTimeoutMs == NV_WAIT_INFINITE) - Timeout = NV_WAIT_INFINITE; - else - { - CurrentTime = NvOsGetTimeMS(); - TimeElapsed = (CurrentTime >= StartTime)? (CurrentTime - StartTime): - 0xFFFFFFFF-StartTime + CurrentTime; - if (WaitTimeoutMs <= TimeElapsed) - break; - Timeout = (WaitTimeoutMs - TimeElapsed); - } - - // CTS Hw flow disable: As CTS hw flow is disable we will get the - // fifo empty after transmitting the bytes as there is no stop - // for transmit data - // CTS Hw flow enable: If CTS hw flow is enable and If CTS line - // is inactive then we dont know how much time it will take to - // get the fifo empty and in this case better to wait for semaphore - // with the trigger level interrupt. - if (hUart->IsCtsFlowEnable) - { - IsCtsActive = NvDdkPrivUartHwIsCtsActive(&hUart->UartHwRegs); - if (!IsCtsActive) - { - // Wait for fifo get empty - hUart->WriteReq.hOnCompleteSema = hUart->hTxSynchSema; - LockRegisterAccess(hUart); - NvDdkPrivUartHwSetFifoTriggerLevel(&hUart->UartHwRegs, UartDataDirection_Transmit, 4); - NvDdkPrivUartHwSetTransmitInterrupt(&hUart->UartHwRegs, NV_TRUE); - UnlockRegisterAccess(hUart); - Error = NvOsSemaphoreWaitTimeout(hUart->WriteReq.hOnCompleteSema, Timeout); - if ((hUart->WriteReq.IsStopReq) || (Error == NvError_Timeout)) - { - LockRegisterAccess(hUart); - NvDdkPrivUartHwSetTransmitInterrupt(&hUart->UartHwRegs, NV_FALSE); - UnlockRegisterAccess(hUart); - break; - } - continue; - } - } - - // Wait for the 4 character time in efficient way. - // If more than 500 microsecond then wait with the NvOsSleep - if (hUart->Char4TimeUs > 500) - NvOsSleepMS((hUart->Char4TimeUs + 999)/1000); - else - NvOsWaitUS(hUart->Char4TimeUs); - } - } - - DEBUG_PRINT_TX_ERR((Error == NvError_Timeout), - ("NvDdkUartWrite(): BytesRequested 0x%08x and Timeout 0x%08x \n", - BytesRequested, WaitTimeoutMs)); - DEBUG_PRINT_TX_ERR(((Error == NvError_Timeout) &&(hUart->IsCtsFlowEnable)), - ("NvDdkUartWrite(): CTS State starting %d and end %d",IsCtsPrevActive, NvDdkPrivUartHwIsCtsActive(&hUart->UartHwRegs))); - - // If the write is stopped the reset the Tx fifo. - // Fixme!! Do we really need to reset the fifo? - if (hUart->WriteReq.IsStopReq) - NvDdkPrivUartHwResetFifo(&hUart->UartHwRegs, UartDataDirection_Transmit); - - *pBytesWritten = hUart->WriteReq.BytesTransferred; - hUart->WriteReq.IsBusy = NV_FALSE; - -#if ENABLE_WRITE_PROFILE - if (!Error) - NvOsDebugPrintf("NvDdkUartWrite(): EntryTime 0x%08x and ExitTime 0x%08x\n", - EntryTime, NvOsGetTimeMS()); -#endif - return Error; -} - -/** - * Stop the write opeartion. - */ -void NvDdkUartStopWrite(NvDdkUartHandle hUart) -{ - NV_ASSERT(hUart); - if (hUart->IsSuspendedState) - return; - - LockWriteFlow(hUart); - UartStopWrite(hUart, NV_TRUE); - UnlockWriteFlow(hUart); -} - -void -NvDdkUartGetTransferStatus( - NvDdkUartHandle hUart, - NvU32 *pTxBytesToRemain, - NvError *pTxStatus, - NvU32 *pRxBytesAvailable, - NvError *pRxStatus) -{ - NvU32 TxCount = 0; - NvError TxStatus = NvSuccess; - NvU32 RxBytesAvailable; - NvError RxStatus = NvSuccess; - - NvError Err = NvSuccess; - NV_ASSERT(hUart); - if (hUart->IsSuspendedState) - return; - - if (hUart->WriteReq.IsBusy) - { - if ((hUart->WriteReq.BytesRequested > hUart->MaxTxBytesPolling) && - (hUart->IsDmaSupport)) - { - Err = NvRmDmaGetTransferredCount(hUart->hTxRmDma,&TxCount, NV_FALSE); - if (!Err) - TxCount += hUart->WriteReq.BytesTransferred; - else - TxCount = hUart->WriteReq.BytesTransferred; - } - else - TxCount = hUart->WriteReq.BytesTransferred; - TxStatus = hUart->WriteReq.TransferStatus; - } - - RxBytesAvailable = hUart->LocalRxBuff.DataAvailable; - RxStatus = hUart->ReadReq.TransferStatus; - - *pTxBytesToRemain = TxCount; - *pTxStatus = TxStatus; - *pRxBytesAvailable = RxBytesAvailable; - *pRxStatus = RxStatus; -} - -/** - * Start/Stop sending the break signal. - */ -NvError NvDdkUartSetBreakSignal(NvDdkUartHandle hUart, NvBool IsStart) -{ - NV_ASSERT(hUart); - if (hUart->IsSuspendedState) - return NvError_InvalidState; - - // Start sending the break signal. - LockRegisterAccess(hUart); - if (IsStart) - NvDdkPrivUartHwSetBreakControlSignal(&hUart->UartHwRegs, NV_TRUE); - else - NvDdkPrivUartHwSetBreakControlSignal(&hUart->UartHwRegs, NV_FALSE); - UnlockRegisterAccess(hUart); - return NvSuccess; -} - -/** - * Set the flow control signal level. - */ -NvError -NvDdkUartSetFlowControlSignal( - NvDdkUartHandle hUart, - NvDdkUartSignalName SignalName, - NvDdkUartFlowControl FlowControl) -{ - NvError Error = NvSuccess; - NvU32 IsHigh; - NV_ASSERT(hUart); - if (hUart->IsSuspendedState) - return NvError_InvalidState; - - LockRegisterAccess(hUart); - if (FlowControl == NvDdkUartFlowControl_Handshake) - { - // For RTS/CTS handshake flow control, the number of line should be 4 - // or more. - if (hUart->NumberOfInterfaceLine < 4) - { - Error = NvError_NotSupported; - goto Exit; - } - - if (SignalName & NvDdkUartSignalName_Rts) - hUart->IsRtsFlowEnable = NV_TRUE; - - if (SignalName & NvDdkUartSignalName_Cts) - { - NvDdkPrivUartHwSetHWFlowControl(&hUart->UartHwRegs, NV_TRUE); - hUart->IsCtsFlowEnable = NV_TRUE; - } - Error = NvSuccess; - goto Exit; - } - - IsHigh = (FlowControl == NvDdkUartFlowControl_Enable)? NV_TRUE: NV_FALSE; - if (SignalName & NvDdkUartSignalName_Rts) - hUart->IsRtsFlowEnable = NV_FALSE; - - if (SignalName & NvDdkUartSignalName_Cts) - { - if (FlowControl == NvDdkUartFlowControl_Enable) - { - NvDdkPrivUartHwSetHWFlowControl(&hUart->UartHwRegs, NV_TRUE); - hUart->IsCtsFlowEnable = NV_TRUE; - } - else - { - NvDdkPrivUartHwSetHWFlowControl(&hUart->UartHwRegs, NV_FALSE); - hUart->IsCtsFlowEnable = NV_FALSE; - } - } - NvDdkPrivUartHwSetModemSignal(&hUart->UartHwRegs, SignalName, IsHigh); - -Exit: - UnlockRegisterAccess(hUart); - return Error; -} - -/** - * Get the input modem signal level status. - */ -NvError -NvDdkUartGetFlowControlSignalLevel( - NvDdkUartHandle hUart, - NvDdkUartSignalName SignalName, - NvU32 *pSignalState) - -{ - NvError Error = NvSuccess; - NvU32 SignalState = 0; - - NV_ASSERT(hUart); - NV_ASSERT(pSignalState); - if (hUart->IsSuspendedState) - return NvError_InvalidState; - - LockRegisterAccess(hUart); - SignalState = (hUart->UartHwRegs.ModemSignalSatus & SignalName); - UnlockRegisterAccess(hUart); - *pSignalState = SignalState; - return Error; -} - -/** - * Set semaphore for the modem signal status change. Any signal change in modem - * line will signal this semaphore. - */ -NvError -NvDdkUartRegisterModemSignalChange( - NvDdkUartHandle hUart, - NvDdkUartSignalName SignalName, - NvDdkUartSignalChangeCallback Callback, - void *args) -{ - NV_ASSERT(hUart); - if (hUart->IsSuspendedState) - return NvError_InvalidState; - - LockRegisterAccess(hUart); - // Update the semaphore for the modem signal status change. - if (Callback != NULL) - { - hUart->hModemSigChngCallback = Callback; - hUart->ModemSignalName = SignalName; - hUart->ModemSigChngHandlerArgs = args; - // Enable the modem control interrupt only when the number of line are - // 8 i.e. full modem interface is available. - if (hUart->NumberOfInterfaceLine == 8) - NvDdkPrivUartHwSetModemControlInterrupt(&hUart->UartHwRegs, NV_TRUE); - } - else - { - hUart->hModemSigChngCallback = NULL; - hUart->ModemSignalName = 0; - hUart->ModemSigChngHandlerArgs = NULL; - NvDdkPrivUartHwSetModemControlInterrupt(&hUart->UartHwRegs, NV_FALSE); - } - UnlockRegisterAccess(hUart); - return NvSuccess; -} - -NvError NvDdkUartSuspend(NvDdkUartHandle hUart) -{ - NvError Error; - NvRmPowerState PowerState; - NvRmModuleID ModuleId; - NvU32 TimeCount = 50; // 100 ms waiting - - NV_ASSERT(hUart); - if (hUart->IsSuspendedState) - return NvSuccess; - - ModuleId = NVRM_MODULE_ID(NvRmModuleID_Uart, hUart->InstanceId); - - // First Declared as suspended state. - hUart->IsSuspendedState = NV_TRUE; - - // Abort write if it is going - LockWriteFlow(hUart); - UartStopWrite(hUart, NV_FALSE); - UnlockWriteFlow(hUart); - - // Wait for the write busy to come to non-busy, maximum 50 ms. - while((hUart->WriteReq.IsBusy) && TimeCount) - { - NvOsSleepMS(2); - TimeCount--; - } - // Still write busy then something wrong, so dont enter into suspend state. - if (hUart->WriteReq.IsBusy) - { - hUart->IsSuspendedState = NV_FALSE; - return NvError_InvalidState; - } - - // Wait for the Tx fifo to be empty. - WaitTillTxFifoEmpty(hUart); - - // Now abort the read flow - LockReadFlow(hUart); - LockRegisterAccess(hUart); - - hUart->OldRtsState = hUart->UartHwRegs.IsRtsActive; - hUart->OldDtrState = hUart->UartHwRegs.IsDtrActive; - if (hUart->UartHwRegs.IsRtsActive) - NvDdkPrivUartHwSetModemSignal(&hUart->UartHwRegs, NvDdkUartSignalName_Rts, NV_FALSE); - - if (hUart->UartHwRegs.IsDtrActive) - NvDdkPrivUartHwSetModemSignal(&hUart->UartHwRegs, NvDdkUartSignalName_Dtr, NV_FALSE); - - // Abort the dma if it is started. - if ((hUart->IsDmaReadStarted) && (hUart->IsRxApbDmaBased)) - NvRmDmaAbort(hUart->hRxRmDma); - - hUart->IsRxApbDmaBased = NV_FALSE; - hUart->IsDmaReadStarted = NV_FALSE; - hUart->LastReadIndex = 0; - - // Reset the uart controller to clear all status and interrupt request - // if there is any. This is require because after clock disabling, if we - // enter into the ISR, we may not be able to clear that. - NvRmModuleReset(hUart->hRmDevice, ModuleId); - - // Disable the clock - Error = NvRmPowerModuleClockControl(hUart->hRmDevice, ModuleId, - hUart->RmPowerClientId, NV_FALSE); - - // Bring down the freq requirements. - NvOsSemaphoreSignal(hUart->hUartPowerMgrSema); - - // Disable power - if (!Error) - Error = NvRmPowerVoltageControl(hUart->hRmDevice, ModuleId, - hUart->RmPowerClientId, NvRmVoltsOff, NvRmVoltsOff, - NULL, 0, NULL); - - // Tri-State the pin-mux pins - NV_ASSERT_SUCCESS(NvRmSetModuleTristate(hUart->hRmDevice, ModuleId, NV_TRUE)); - - // Check whether the power state is idle - if (!Error) - { - Error = NvRmPowerGetState(hUart->hRmDevice, &PowerState); - // if (!Error) - // NV_ASSERT(PowerState != NvRmPowerState_Active); - } - UnlockRegisterAccess(hUart); - UnlockReadFlow(hUart); - return Error; -} - -NvError NvDdkUartResume(NvDdkUartHandle hUart) -{ - NvError Error; - NvRmPowerState PowerState; - NvRmModuleID ModuleId; - - NV_ASSERT(hUart); - if (!hUart->IsSuspendedState) - return NvSuccess; - - ModuleId = NVRM_MODULE_ID(NvRmModuleID_Uart, hUart->InstanceId); - - LockReadFlow(hUart); - LockRegisterAccess(hUart); - - // Reenable the pin nmux - Error = NvRmSetModuleTristate(hUart->hRmDevice, ModuleId, NV_FALSE); - - // Enable power for uart module - if (!Error) - Error = NvRmPowerVoltageControl(hUart->hRmDevice, ModuleId, - hUart->RmPowerClientId, - NvRmVoltsUnspecified, NvRmVoltsUnspecified, - NULL, 0, NULL); - - // Enable the clock. - if (!Error) - Error = NvRmPowerModuleClockControl(hUart->hRmDevice, ModuleId, - hUart->RmPowerClientId, NV_TRUE); - - // Reset the module. - if (!Error) - NvRmModuleReset(hUart->hRmDevice, ModuleId); - - // Check whether the power state is active - if (!Error) - { - Error = NvRmPowerGetState(hUart->hRmDevice, &PowerState); - if (!Error) - NV_ASSERT(PowerState == NvRmPowerState_Active); - } - - // Restore the registers. - if (!Error) - { - NvDdkPrivUartHwReconfigureRegisters(&hUart->UartHwRegs); - - // Restart the apb dma. - if (hUart->IsDmaSupport) - { - hUart->RDmaReq.TransferSize = hUart->RxDmaBufferSize; - Error = NvRmDmaStartDmaTransfer(hUart->hRxRmDma, &hUart->RDmaReq, - NvRmDmaDirection_Forward, 0, hUart->LocalRxBuff.hDataAvailableSema); - if (!Error) - { - hUart->IsRxApbDmaBased = NV_TRUE; - hUart->IsDmaReadStarted = NV_TRUE; - hUart->LastReadIndex = 0; - } - Error = NvSuccess; - } - - // Enable the receive interrupt. - NvDdkPrivUartHwSetReceiveInterrupt(&hUart->UartHwRegs, NV_TRUE, hUart->IsRxApbDmaBased); - if (hUart->OldRtsState) - NvDdkPrivUartHwSetModemSignal(&hUart->UartHwRegs, NvDdkUartSignalName_Rts, NV_TRUE); - if (hUart->OldDtrState) - NvDdkPrivUartHwSetModemSignal(&hUart->UartHwRegs, NvDdkUartSignalName_Dtr, NV_TRUE); - } - - hUart->IsSuspendedState = NV_FALSE; - NvOsSemaphoreSignal(hUart->hUartPowerMgrSema); - - UnlockRegisterAccess(hUart); - UnlockReadFlow(hUart); - return Error; -} |