From 5090cc6ae2f79ee779e5faf7c8a28edf42b7d738 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 17 Aug 2016 21:08:01 +0200 Subject: spi: introduce max_message_size hook in spi_master Recently a maximum transfer size was was introduced in struct spi_master. However there are also spi controllers with a maximum message size, e.g. fsl-espi has a max message size of 64KB. Introduce a hook max_message_size to deal with such limitations. Also make sure that spi_max_transfer_size doesn't return greater values than spi_max_message_size, even if hook max_transfer_size is not set. Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- include/linux/spi/spi.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 072cb2aa2413..f2d3960cc3c3 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -312,6 +312,8 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * @flags: other constraints relevant to this driver * @max_transfer_size: function that returns the max transfer size for * a &spi_device; may be %NULL, so the default %SIZE_MAX will be used. + * @max_message_size: function that returns the max message size for + * a &spi_device; may be %NULL, so the default %SIZE_MAX will be used. * @io_mutex: mutex for physical bus access * @bus_lock_spinlock: spinlock for SPI bus locking * @bus_lock_mutex: mutex for exclusion of multiple callers @@ -442,10 +444,11 @@ struct spi_master { #define SPI_MASTER_MUST_TX BIT(4) /* requires tx */ /* - * on some hardware transfer size may be constrained + * on some hardware transfer / message size may be constrained * the limit may depend on device transfer settings */ size_t (*max_transfer_size)(struct spi_device *spi); + size_t (*max_message_size)(struct spi_device *spi); /* I/O mutex */ struct mutex io_mutex; @@ -905,12 +908,26 @@ extern int spi_async_locked(struct spi_device *spi, struct spi_message *message); static inline size_t -spi_max_transfer_size(struct spi_device *spi) +spi_max_message_size(struct spi_device *spi) { struct spi_master *master = spi->master; - if (!master->max_transfer_size) + if (!master->max_message_size) return SIZE_MAX; - return master->max_transfer_size(spi); + return master->max_message_size(spi); +} + +static inline size_t +spi_max_transfer_size(struct spi_device *spi) +{ + struct spi_master *master = spi->master; + size_t tr_max = SIZE_MAX; + size_t msg_max = spi_max_message_size(spi); + + if (master->max_transfer_size) + tr_max = master->max_transfer_size(spi); + + /* transfer size limit must not be greater than messsage size limit */ + return min(tr_max, msg_max); } /*---------------------------------------------------------------------------*/ -- cgit v1.2.3-59-g8ed1b From 7c7289a40425d48bbfcaacc454a8caf5b47f63b0 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 7 Sep 2016 15:43:22 +0300 Subject: spi: pxa2xx: Default thresholds to PXA configuration Most of the devices in the supported list have PXA configuration of FIFO. In particularly Intel Medfield and Merrifield have bigger FIFO, than it's defined for CE4100. Split CE4100 in the similar way how it was done for Intel Quark, i.e. prefix definitions by CE4100 and append necessary pieces of code to switch case conditions. We are on safe side since those bits are ignored on all LPSS IPs. Signed-off-by: Andy Shevchenko Reviewed-by: Jarkko Nikula Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 47 +++++++++++++++++++++++++++++++++++++++++----- include/linux/pxa2xx_ssp.h | 20 ++++++++------------ 2 files changed, 50 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 6a0eb32408b6..cab39b06bc89 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -62,6 +62,13 @@ MODULE_ALIAS("platform:pxa2xx-spi"); | QUARK_X1000_SSCR1_TFT \ | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM) +#define CE4100_SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_SCFR \ + | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \ + | SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \ + | SSCR1_IFS | SSCR1_STRF | SSCR1_EFWR \ + | CE4100_SSCR1_RFT | CE4100_SSCR1_TFT | SSCR1_MWDS \ + | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM) + #define LPSS_GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24) #define LPSS_CS_CONTROL_SW_MODE BIT(0) #define LPSS_CS_CONTROL_CS_HIGH BIT(1) @@ -175,6 +182,8 @@ static u32 pxa2xx_spi_get_ssrc1_change_mask(const struct driver_data *drv_data) switch (drv_data->ssp_type) { case QUARK_X1000_SSP: return QUARK_X1000_SSCR1_CHANGE_MASK; + case CE4100_SSP: + return CE4100_SSCR1_CHANGE_MASK; default: return SSCR1_CHANGE_MASK; } @@ -186,6 +195,8 @@ pxa2xx_spi_get_rx_default_thre(const struct driver_data *drv_data) switch (drv_data->ssp_type) { case QUARK_X1000_SSP: return RX_THRESH_QUARK_X1000_DFLT; + case CE4100_SSP: + return RX_THRESH_CE4100_DFLT; default: return RX_THRESH_DFLT; } @@ -199,6 +210,9 @@ static bool pxa2xx_spi_txfifo_full(const struct driver_data *drv_data) case QUARK_X1000_SSP: mask = QUARK_X1000_SSSR_TFL_MASK; break; + case CE4100_SSP: + mask = CE4100_SSSR_TFL_MASK; + break; default: mask = SSSR_TFL_MASK; break; @@ -216,6 +230,9 @@ static void pxa2xx_spi_clear_rx_thre(const struct driver_data *drv_data, case QUARK_X1000_SSP: mask = QUARK_X1000_SSCR1_RFT; break; + case CE4100_SSP: + mask = CE4100_SSCR1_RFT; + break; default: mask = SSCR1_RFT; break; @@ -230,6 +247,9 @@ static void pxa2xx_spi_set_rx_thre(const struct driver_data *drv_data, case QUARK_X1000_SSP: *sccr1_reg |= QUARK_X1000_SSCR1_RxTresh(threshold); break; + case CE4100_SSP: + *sccr1_reg |= CE4100_SSCR1_RxTresh(threshold); + break; default: *sccr1_reg |= SSCR1_RxTresh(threshold); break; @@ -590,6 +610,9 @@ static void reset_sccr1(struct driver_data *drv_data) case QUARK_X1000_SSP: sccr1_reg &= ~QUARK_X1000_SSCR1_RFT; break; + case CE4100_SSP: + sccr1_reg &= ~CE4100_SSCR1_RFT; + break; default: sccr1_reg &= ~SSCR1_RFT; break; @@ -1220,6 +1243,11 @@ static int setup(struct spi_device *spi) tx_hi_thres = 0; rx_thres = RX_THRESH_QUARK_X1000_DFLT; break; + case CE4100_SSP: + tx_thres = TX_THRESH_CE4100_DFLT; + tx_hi_thres = 0; + rx_thres = RX_THRESH_CE4100_DFLT; + break; case LPSS_LPT_SSP: case LPSS_BYT_SSP: case LPSS_BSW_SSP: @@ -1304,6 +1332,10 @@ static int setup(struct spi_device *spi) | (QUARK_X1000_SSCR1_TxTresh(tx_thres) & QUARK_X1000_SSCR1_TFT); break; + case CE4100_SSP: + chip->threshold = (CE4100_SSCR1_RxTresh(rx_thres) & CE4100_SSCR1_RFT) | + (CE4100_SSCR1_TxTresh(tx_thres) & CE4100_SSCR1_TFT); + break; default: chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) | (SSCR1_TxTresh(tx_thres) & SSCR1_TFT); @@ -1625,15 +1657,20 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) pxa2xx_spi_write(drv_data, SSCR0, 0); switch (drv_data->ssp_type) { case QUARK_X1000_SSP: - tmp = QUARK_X1000_SSCR1_RxTresh(RX_THRESH_QUARK_X1000_DFLT) - | QUARK_X1000_SSCR1_TxTresh(TX_THRESH_QUARK_X1000_DFLT); + tmp = QUARK_X1000_SSCR1_RxTresh(RX_THRESH_QUARK_X1000_DFLT) | + QUARK_X1000_SSCR1_TxTresh(TX_THRESH_QUARK_X1000_DFLT); pxa2xx_spi_write(drv_data, SSCR1, tmp); /* using the Motorola SPI protocol and use 8 bit frame */ - pxa2xx_spi_write(drv_data, SSCR0, - QUARK_X1000_SSCR0_Motorola - | QUARK_X1000_SSCR0_DataSize(8)); + tmp = QUARK_X1000_SSCR0_Motorola | QUARK_X1000_SSCR0_DataSize(8); + pxa2xx_spi_write(drv_data, SSCR0, tmp); break; + case CE4100_SSP: + tmp = CE4100_SSCR1_RxTresh(RX_THRESH_CE4100_DFLT) | + CE4100_SSCR1_TxTresh(TX_THRESH_CE4100_DFLT); + pxa2xx_spi_write(drv_data, SSCR1, tmp); + tmp = SSCR0_SCR(2) | SSCR0_Motorola | SSCR0_DataSize(8); + pxa2xx_spi_write(drv_data, SSCR0, tmp); default: tmp = SSCR1_RxTresh(RX_THRESH_DFLT) | SSCR1_TxTresh(TX_THRESH_DFLT); diff --git a/include/linux/pxa2xx_ssp.h b/include/linux/pxa2xx_ssp.h index 2a097d176ba9..2d6f0c39ed68 100644 --- a/include/linux/pxa2xx_ssp.h +++ b/include/linux/pxa2xx_ssp.h @@ -83,7 +83,6 @@ #define SSSR_RFS (1 << 6) /* Receive FIFO Service Request */ #define SSSR_ROR (1 << 7) /* Receive FIFO Overrun */ -#ifdef CONFIG_ARCH_PXA #define RX_THRESH_DFLT 8 #define TX_THRESH_DFLT 8 @@ -95,19 +94,16 @@ #define SSCR1_RFT (0x00003c00) /* Receive FIFO Threshold (mask) */ #define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..16] */ -#else - -#define RX_THRESH_DFLT 2 -#define TX_THRESH_DFLT 2 +#define RX_THRESH_CE4100_DFLT 2 +#define TX_THRESH_CE4100_DFLT 2 -#define SSSR_TFL_MASK (0x3 << 8) /* Transmit FIFO Level mask */ -#define SSSR_RFL_MASK (0x3 << 12) /* Receive FIFO Level mask */ +#define CE4100_SSSR_TFL_MASK (0x3 << 8) /* Transmit FIFO Level mask */ +#define CE4100_SSSR_RFL_MASK (0x3 << 12) /* Receive FIFO Level mask */ -#define SSCR1_TFT (0x000000c0) /* Transmit FIFO Threshold (mask) */ -#define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..4] */ -#define SSCR1_RFT (0x00000c00) /* Receive FIFO Threshold (mask) */ -#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..4] */ -#endif +#define CE4100_SSCR1_TFT (0x000000c0) /* Transmit FIFO Threshold (mask) */ +#define CE4100_SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..4] */ +#define CE4100_SSCR1_RFT (0x00000c00) /* Receive FIFO Threshold (mask) */ +#define CE4100_SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..4] */ /* QUARK_X1000 SSCR0 bit definition */ #define QUARK_X1000_SSCR0_DSS (0x1F) /* Data Size Select (mask) */ -- cgit v1.2.3-59-g8ed1b From 323117ab60156d5ef021eeef260c4e7e0a7f520e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 13 Sep 2016 15:38:25 +0200 Subject: spi: core: Use spi_sync_transfer() in spi_write()/spi_read() Simplify spi_write() and spi_read() using the spi_sync_transfer() helper. This requires moving spi_sync_transfer() up. Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- include/linux/spi/spi.h | 58 ++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 32 deletions(-) (limited to 'include') diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 072cb2aa2413..74278c7d0f52 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -979,6 +979,30 @@ extern int spi_sync_locked(struct spi_device *spi, struct spi_message *message); extern int spi_bus_lock(struct spi_master *master); extern int spi_bus_unlock(struct spi_master *master); +/** + * spi_sync_transfer - synchronous SPI data transfer + * @spi: device with which data will be exchanged + * @xfers: An array of spi_transfers + * @num_xfers: Number of items in the xfer array + * Context: can sleep + * + * Does a synchronous SPI data transfer of the given spi_transfer array. + * + * For more specific semantics see spi_sync(). + * + * Return: Return: zero on success, else a negative error code. + */ +static inline int +spi_sync_transfer(struct spi_device *spi, struct spi_transfer *xfers, + unsigned int num_xfers) +{ + struct spi_message msg; + + spi_message_init_with_transfers(&msg, xfers, num_xfers); + + return spi_sync(spi, &msg); +} + /** * spi_write - SPI synchronous write * @spi: device to which data will be written @@ -998,11 +1022,8 @@ spi_write(struct spi_device *spi, const void *buf, size_t len) .tx_buf = buf, .len = len, }; - struct spi_message m; - spi_message_init(&m); - spi_message_add_tail(&t, &m); - return spi_sync(spi, &m); + return spi_sync_transfer(spi, &t, 1); } /** @@ -1024,35 +1045,8 @@ spi_read(struct spi_device *spi, void *buf, size_t len) .rx_buf = buf, .len = len, }; - struct spi_message m; - spi_message_init(&m); - spi_message_add_tail(&t, &m); - return spi_sync(spi, &m); -} - -/** - * spi_sync_transfer - synchronous SPI data transfer - * @spi: device with which data will be exchanged - * @xfers: An array of spi_transfers - * @num_xfers: Number of items in the xfer array - * Context: can sleep - * - * Does a synchronous SPI data transfer of the given spi_transfer array. - * - * For more specific semantics see spi_sync(). - * - * Return: Return: zero on success, else a negative error code. - */ -static inline int -spi_sync_transfer(struct spi_device *spi, struct spi_transfer *xfers, - unsigned int num_xfers) -{ - struct spi_message msg; - - spi_message_init_with_transfers(&msg, xfers, num_xfers); - - return spi_sync(spi, &msg); + return spi_sync_transfer(spi, &t, 1); } /* this copies txbuf and rxbuf data; for small transfers only! */ -- cgit v1.2.3-59-g8ed1b