Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f9c6ef6c authored by Ricardo Ribalda Delgado's avatar Ricardo Ribalda Delgado Committed by Mark Brown
Browse files

spi/xilinx: Support for spi mode CS_HIGH



The core controls the chip select lines individually.

By default, all the lines are consider active_low. After
spi_setup_transfer, it has its real value.

Signed-off-by: default avatarRicardo Ribalda Delgado <ricardo.ribalda@gmail.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent d9f58812
Loading
Loading
Loading
Loading
+38 −24
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ struct xilinx_spi {
	int remaining_bytes;	/* the number of bytes left to transfer */
	u8 bits_per_word;
	int buffer_size;	/* buffer size in words */
	u32 cs_inactive;	/* Level of the CS pins when inactive*/
	unsigned int (*read_fn)(void __iomem *);
	void (*write_fn)(u32, void __iomem *);
	void (*tx_fn)(struct xilinx_spi *);
@@ -194,14 +195,17 @@ static void xspi_init_hw(struct xilinx_spi *xspi)
static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
{
	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
	u16 cr;
	u32 cs;

	if (is_on == BITBANG_CS_INACTIVE) {
		/* Deselect the slave on the SPI bus */
		xspi->write_fn(0xffff, xspi->regs + XSPI_SSR_OFFSET);
	} else if (is_on == BITBANG_CS_ACTIVE) {
		xspi->write_fn(xspi->cs_inactive, xspi->regs + XSPI_SSR_OFFSET);
		return;
	}

	/* Set the SPI clock phase and polarity */
		u16 cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET)
			 & ~XSPI_CR_MODE_MASK;
	cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET)	& ~XSPI_CR_MODE_MASK;
	if (spi->mode & SPI_CPHA)
		cr |= XSPI_CR_CPHA;
	if (spi->mode & SPI_CPOL)
@@ -217,10 +221,11 @@ static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
	 * parameter)
	 */

	cs = xspi->cs_inactive;
	cs ^= BIT(spi->chip_select);

	/* Activate the chip select */
		xspi->write_fn(~(0x0001 << spi->chip_select),
			xspi->regs + XSPI_SSR_OFFSET);
	}
	xspi->write_fn(cs, xspi->regs + XSPI_SSR_OFFSET);
}

/* spi_bitbang requires custom setup_transfer() to be defined if there is a
@@ -229,6 +234,13 @@ static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
static int xilinx_spi_setup_transfer(struct spi_device *spi,
		struct spi_transfer *t)
{
	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);

	if (spi->mode & SPI_CS_HIGH)
		xspi->cs_inactive &= ~BIT(spi->chip_select);
	else
		xspi->cs_inactive |= BIT(spi->chip_select);

	return 0;
}

@@ -376,9 +388,11 @@ static int xilinx_spi_probe(struct platform_device *pdev)
		return -ENODEV;

	/* the spi->mode bits understood by this driver: */
	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_LOOP;
	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_LOOP |
			    SPI_CS_HIGH;

	xspi = spi_master_get_devdata(master);
	xspi->cs_inactive = 0xffffffff;
	xspi->bitbang.master = master;
	xspi->bitbang.chipselect = xilinx_spi_chipselect;
	xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer;