diff options
Diffstat (limited to 'drivers/spi/spi-rspi.c')
| -rw-r--r-- | drivers/spi/spi-rspi.c | 44 | 
1 files changed, 36 insertions, 8 deletions
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 85575d45901c..06192c9ea813 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -24,6 +24,7 @@  #include <linux/sh_dma.h>  #include <linux/spi/spi.h>  #include <linux/spi/rspi.h> +#include <linux/spinlock.h>  #define RSPI_SPCR		0x00	/* Control Register */  #define RSPI_SSLP		0x01	/* Slave Select Polarity Register */ @@ -79,8 +80,7 @@  #define SPCR_BSWAP		0x01	/* Byte Swap of read-data for DMAC */  /* SSLP - Slave Select Polarity Register */ -#define SSLP_SSL1P		0x02	/* SSL1 Signal Polarity Setting */ -#define SSLP_SSL0P		0x01	/* SSL0 Signal Polarity Setting */ +#define SSLP_SSLP(i)		BIT(i)	/* SSLi Signal Polarity Setting */  /* SPPCR - Pin Control Register */  #define SPPCR_MOIFE		0x20	/* MOSI Idle Value Fixing Enable */ @@ -181,7 +181,9 @@ struct rspi_data {  	void __iomem *addr;  	u32 max_speed_hz;  	struct spi_controller *ctlr; +	struct platform_device *pdev;  	wait_queue_head_t wait; +	spinlock_t lock;		/* Protects RMW-access to RSPI_SSLP */  	struct clk *clk;  	u16 spcmd;  	u8 spsr; @@ -239,7 +241,7 @@ struct spi_ops {  	int (*set_config_register)(struct rspi_data *rspi, int access_size);  	int (*transfer_one)(struct spi_controller *ctlr,  			    struct spi_device *spi, struct spi_transfer *xfer); -	u16 mode_bits; +	u16 extra_mode_bits;  	u16 flags;  	u16 fifo_size;  	u8 num_hw_ss; @@ -919,6 +921,29 @@ static int qspi_setup_sequencer(struct rspi_data *rspi,  	return 0;  } +static int rspi_setup(struct spi_device *spi) +{ +	struct rspi_data *rspi = spi_controller_get_devdata(spi->controller); +	u8 sslp; + +	if (spi->cs_gpiod) +		return 0; + +	pm_runtime_get_sync(&rspi->pdev->dev); +	spin_lock_irq(&rspi->lock); + +	sslp = rspi_read8(rspi, RSPI_SSLP); +	if (spi->mode & SPI_CS_HIGH) +		sslp |= SSLP_SSLP(spi->chip_select); +	else +		sslp &= ~SSLP_SSLP(spi->chip_select); +	rspi_write8(rspi, sslp, RSPI_SSLP); + +	spin_unlock_irq(&rspi->lock); +	pm_runtime_put(&rspi->pdev->dev); +	return 0; +} +  static int rspi_prepare_message(struct spi_controller *ctlr,  				struct spi_message *msg)  { @@ -933,6 +958,8 @@ static int rspi_prepare_message(struct spi_controller *ctlr,  		rspi->spcmd |= SPCMD_CPOL;  	if (spi->mode & SPI_CPHA)  		rspi->spcmd |= SPCMD_CPHA; +	if (spi->mode & SPI_LSB_FIRST) +		rspi->spcmd |= SPCMD_LSBF;  	/* Configure slave signal to assert */  	rspi->spcmd |= SPCMD_SSLA(spi->cs_gpiod ? rspi->ctlr->unused_native_cs @@ -1122,7 +1149,6 @@ static int rspi_remove(struct platform_device *pdev)  static const struct spi_ops rspi_ops = {  	.set_config_register =	rspi_set_config_register,  	.transfer_one =		rspi_transfer_one, -	.mode_bits =		SPI_CPHA | SPI_CPOL | SPI_LOOP,  	.flags =		SPI_CONTROLLER_MUST_TX,  	.fifo_size =		8,  	.num_hw_ss =		2, @@ -1131,7 +1157,6 @@ static const struct spi_ops rspi_ops = {  static const struct spi_ops rspi_rz_ops = {  	.set_config_register =	rspi_rz_set_config_register,  	.transfer_one =		rspi_rz_transfer_one, -	.mode_bits =		SPI_CPHA | SPI_CPOL | SPI_LOOP,  	.flags =		SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX,  	.fifo_size =		8,	/* 8 for TX, 32 for RX */  	.num_hw_ss =		1, @@ -1140,8 +1165,7 @@ static const struct spi_ops rspi_rz_ops = {  static const struct spi_ops qspi_ops = {  	.set_config_register =	qspi_set_config_register,  	.transfer_one =		qspi_transfer_one, -	.mode_bits =		SPI_CPHA | SPI_CPOL | SPI_LOOP | -				SPI_TX_DUAL | SPI_TX_QUAD | +	.extra_mode_bits =	SPI_TX_DUAL | SPI_TX_QUAD |  				SPI_RX_DUAL | SPI_RX_QUAD,  	.flags =		SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX,  	.fifo_size =		32, @@ -1249,16 +1273,20 @@ static int rspi_probe(struct platform_device *pdev)  		goto error1;  	} +	rspi->pdev = pdev;  	pm_runtime_enable(&pdev->dev);  	init_waitqueue_head(&rspi->wait); +	spin_lock_init(&rspi->lock);  	ctlr->bus_num = pdev->id; +	ctlr->setup = rspi_setup;  	ctlr->auto_runtime_pm = true;  	ctlr->transfer_one = ops->transfer_one;  	ctlr->prepare_message = rspi_prepare_message;  	ctlr->unprepare_message = rspi_unprepare_message; -	ctlr->mode_bits = ops->mode_bits; +	ctlr->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST | +			  SPI_LOOP | ops->extra_mode_bits;  	ctlr->flags = ops->flags;  	ctlr->dev.of_node = pdev->dev.of_node;  	ctlr->use_gpio_descriptors = true;  |