/** * cdns_spi_irq - Interrupt service routine of the SPI controller * @irq: IRQ number * @dev_id: Pointer to the xspi structure * * This function handles TX empty and Mode Fault interrupts only. * On TX empty interrupt this function reads the received data from RX FIFO and * fills the TX FIFO if there is any data remaining to be transferred. * On Mode Fault interrupt this function indicates that transfer is completed, * the SPI subsystem will identify the error as the remaining bytes to be * transferred is non-zero. * * Return: IRQ_HANDLED when handled; IRQ_NONE otherwise. */ static irqreturn_t cdns_spi_irq(int irq, void *dev_id) { struct spi_master *master = dev_id; struct cdns_spi *xspi = spi_master_get_devdata(master); u32 intr_status, status; status = IRQ_NONE; intr_status = cdns_spi_read(xspi, CDNS_SPI_ISR_OFFSET); cdns_spi_write(xspi, CDNS_SPI_ISR_OFFSET, intr_status); if (intr_status & CDNS_SPI_IXR_MODF_MASK) { /* Indicate that transfer is completed, the SPI subsystem will * identify the error as the remaining bytes to be * transferred is non-zero */ cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET, CDNS_SPI_IXR_DEFAULT_MASK); spi_finalize_current_transfer(master); status = IRQ_HANDLED; } else if (intr_status & CDNS_SPI_IXR_TXOW_MASK) { unsigned long trans_cnt; trans_cnt = xspi->rx_bytes - xspi->tx_bytes; /* Read out the data from the RX FIFO */ while (trans_cnt) { u8 data; data = cdns_spi_read(xspi, CDNS_SPI_RXD_OFFSET); if (xspi->rxbuf) *xspi->rxbuf++ = data; xspi->rx_bytes--; trans_cnt--; } if (xspi->tx_bytes) { /* There is more data to send */ cdns_spi_fill_tx_fifo(xspi); } else { /* Transfer is completed */ cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET, CDNS_SPI_IXR_DEFAULT_MASK); spi_finalize_current_transfer(master); } status = IRQ_HANDLED; } return status; }
/** * cdns_spi_config_clock_freq - Sets clock frequency * @spi: Pointer to the spi_device structure * @transfer: Pointer to the spi_transfer structure which provides * information about next transfer setup parameters * * Sets the requested clock frequency. * Note: If the requested frequency is not an exact match with what can be * obtained using the prescalar value the driver sets the clock frequency which * is lower than the requested frequency (maximum lower) for the transfer. If * the requested frequency is higher or lower than that is supported by the SPI * controller the driver will set the highest or lowest frequency supported by * controller. */ static void cdns_spi_config_clock_freq(struct spi_device *spi, struct spi_transfer *transfer) { struct cdns_spi *xspi = spi_master_get_devdata(spi->master); u32 ctrl_reg, baud_rate_val; unsigned long frequency; frequency = clk_get_rate(xspi->ref_clk); ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); /* Set the clock frequency */ if (xspi->speed_hz != transfer->speed_hz) { /* first valid value is 1 */ baud_rate_val = CDNS_SPI_BAUD_DIV_MIN; while ((baud_rate_val < CDNS_SPI_BAUD_DIV_MAX) && (frequency / (2 << baud_rate_val)) > transfer->speed_hz) baud_rate_val++; ctrl_reg &= ~CDNS_SPI_CR_BAUD_DIV; ctrl_reg |= baud_rate_val << CDNS_SPI_BAUD_DIV_SHIFT; xspi->speed_hz = frequency / (2 << baud_rate_val); } cdns_spi_write(xspi, CDNS_SPI_CR, ctrl_reg); }
/** * cdns_spi_config_clock_mode - Sets clock polarity and phase * @spi: Pointer to the spi_device structure * * Sets the requested clock polarity and phase. */ static void cdns_spi_config_clock_mode(struct spi_device *spi) { struct cdns_spi *xspi = spi_master_get_devdata(spi->master); u32 ctrl_reg, new_ctrl_reg; new_ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); ctrl_reg = new_ctrl_reg; /* Set the SPI clock phase and clock polarity */ new_ctrl_reg &= ~(CDNS_SPI_CR_CPHA | CDNS_SPI_CR_CPOL); if (spi->mode & SPI_CPHA) new_ctrl_reg |= CDNS_SPI_CR_CPHA; if (spi->mode & SPI_CPOL) new_ctrl_reg |= CDNS_SPI_CR_CPOL; if (new_ctrl_reg != ctrl_reg) { /* * Just writing the CR register does not seem to apply the clock * setting changes. This is problematic when changing the clock * polarity as it will cause the SPI slave to see spurious clock * transitions. To workaround the issue toggle the ER register. */ cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE); cdns_spi_write(xspi, CDNS_SPI_CR, new_ctrl_reg); cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_ENABLE); } }
/** * cdns_spi_init_hw - Initialize the hardware and configure the SPI controller * @xspi: Pointer to the cdns_spi structure * * On reset the SPI controller is configured to be in master mode, baud rate * divisor is set to 4, threshold value for TX FIFO not full interrupt is set * to 1 and size of the word to be transferred as 8 bit. * This function initializes the SPI controller to disable and clear all the * interrupts, enable manual slave select and manual start, deselect all the * chip select lines, and enable the SPI controller. */ static void cdns_spi_init_hw(struct cdns_spi *xspi) { u32 ctrl_reg = CDNS_SPI_CR_DEFAULT; if (xspi->is_decoded_cs) ctrl_reg |= CDNS_SPI_CR_PERI_SEL; cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE); cdns_spi_write(xspi, CDNS_SPI_IDR, CDNS_SPI_IXR_ALL); /* Clear the RX FIFO */ while (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_RXNEMTY) cdns_spi_read(xspi, CDNS_SPI_RXD); cdns_spi_write(xspi, CDNS_SPI_ISR, CDNS_SPI_IXR_ALL); cdns_spi_write(xspi, CDNS_SPI_CR, ctrl_reg); cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_ENABLE); }
/** * cdns_spi_init_hw - Initialize the hardware and configure the SPI controller * @xspi: Pointer to the cdns_spi structure * * On reset the SPI controller is configured to be in master mode, baud rate * divisor is set to 4, threshold value for TX FIFO not full interrupt is set * to 1 and size of the word to be transferred as 8 bit. * This function initializes the SPI controller to disable and clear all the * interrupts, enable manual slave select and manual start, deselect all the * chip select lines, and enable the SPI controller. */ static void cdns_spi_init_hw(struct cdns_spi *xspi) { cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, CDNS_SPI_ER_DISABLE_MASK); cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET, CDNS_SPI_IXR_ALL_MASK); /* Clear the RX FIFO */ while (cdns_spi_read(xspi, CDNS_SPI_ISR_OFFSET) & CDNS_SPI_IXR_RXNEMTY_MASK) cdns_spi_read(xspi, CDNS_SPI_RXD_OFFSET); cdns_spi_write(xspi, CDNS_SPI_ISR_OFFSET, CDNS_SPI_IXR_ALL_MASK); cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, CDNS_SPI_CR_DEFAULT_MASK); cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, CDNS_SPI_ER_ENABLE_MASK); }
/** * cdns_spi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible * @xspi: Pointer to the cdns_spi structure */ static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi) { unsigned long trans_cnt = 0; while ((trans_cnt < CDNS_SPI_FIFO_DEPTH) && (xspi->tx_bytes > 0)) { /* When xspi in busy condition, bytes may send failed, * then spi control did't work thoroughly, add one byte delay */ if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL) udelay(10); if (xspi->txbuf) cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++); else cdns_spi_write(xspi, CDNS_SPI_TXD, 0); xspi->tx_bytes--; trans_cnt++; } }
/** * cdns_spi_chipselect - Select or deselect the chip select line * @spi: Pointer to the spi_device structure * @enable: Select (1) or deselect (0) the chip select line */ static void cdns_spi_chipselect(struct spi_device *spi, bool enable) { struct cdns_spi *xspi = spi_master_get_devdata(spi->master); u32 ctrl_reg; ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); if (!enable) { /* Deselect the slave */ ctrl_reg |= CDNS_SPI_CR_SSCTRL; } else { /* Select the slave */ ctrl_reg &= ~CDNS_SPI_CR_SSCTRL; if (!(xspi->is_decoded_cs)) ctrl_reg |= ((~(CDNS_SPI_SS0 << spi->chip_select)) << CDNS_SPI_SS_SHIFT) & CDNS_SPI_CR_SSCTRL; else ctrl_reg |= (spi->chip_select << CDNS_SPI_SS_SHIFT) & CDNS_SPI_CR_SSCTRL; } cdns_spi_write(xspi, CDNS_SPI_CR, ctrl_reg); }