diff options
Diffstat (limited to 'drivers/spi')
39 files changed, 1571 insertions, 1091 deletions
| diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 60f2b41c7310..213b5cbb9dcc 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -91,8 +91,8 @@ config SPI_BFIN5XX  	help  	  This is the SPI controller master driver for Blackfin 5xx processor. -config SPI_BFIN_V3 -	tristate "SPI controller v3 for Blackfin" +config SPI_ADI_V3 +	tristate "SPI controller v3 for ADI"  	depends on BF60x  	help  	  This is the SPI controller v3 master driver @@ -148,6 +148,13 @@ config SPI_BUTTERFLY  	  inexpensive battery powered microcontroller evaluation board.  	  This same cable can be used to flash new firmware. +config SPI_CADENCE +	tristate "Cadence SPI controller" +	depends on ARM +	help +	  This selects the Cadence SPI controller master driver +	  used by Xilinx Zynq. +  config SPI_CLPS711X  	tristate "CLPS711X host SPI controller"  	depends on ARCH_CLPS711X || COMPILE_TEST @@ -505,7 +512,7 @@ config SPI_TEGRA20_SLINK  config SPI_TOPCLIFF_PCH  	tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) SPI" -	depends on PCI +	depends on PCI && (X86_32 || COMPILE_TEST)  	help  	  SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus  	  used in some x86 embedded processors. diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index bd792669e563..929c9f5eac01 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -18,10 +18,11 @@ obj-$(CONFIG_SPI_BCM2835)		+= spi-bcm2835.o  obj-$(CONFIG_SPI_BCM63XX)		+= spi-bcm63xx.o  obj-$(CONFIG_SPI_BCM63XX_HSSPI)		+= spi-bcm63xx-hsspi.o  obj-$(CONFIG_SPI_BFIN5XX)		+= spi-bfin5xx.o -obj-$(CONFIG_SPI_BFIN_V3)               += spi-bfin-v3.o +obj-$(CONFIG_SPI_ADI_V3)                += spi-adi-v3.o  obj-$(CONFIG_SPI_BFIN_SPORT)		+= spi-bfin-sport.o  obj-$(CONFIG_SPI_BITBANG)		+= spi-bitbang.o  obj-$(CONFIG_SPI_BUTTERFLY)		+= spi-butterfly.o +obj-$(CONFIG_SPI_CADENCE)		+= spi-cadence.o  obj-$(CONFIG_SPI_CLPS711X)		+= spi-clps711x.o  obj-$(CONFIG_SPI_COLDFIRE_QSPI)		+= spi-coldfire-qspi.o  obj-$(CONFIG_SPI_DAVINCI)		+= spi-davinci.o diff --git a/drivers/spi/spi-bfin-v3.c b/drivers/spi/spi-adi-v3.c index 4089d0e0d84e..dcb2287c7f8a 100644 --- a/drivers/spi/spi-bfin-v3.c +++ b/drivers/spi/spi-adi-v3.c @@ -1,7 +1,7 @@  /*   * Analog Devices SPI3 controller driver   * - * Copyright (c) 2013 Analog Devices Inc. + * Copyright (c) 2014 Analog Devices Inc.   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License version 2 as @@ -13,6 +13,7 @@   * GNU General Public License for more details.   */ +#include <linux/clk.h>  #include <linux/delay.h>  #include <linux/device.h>  #include <linux/dma-mapping.h> @@ -26,35 +27,34 @@  #include <linux/platform_device.h>  #include <linux/slab.h>  #include <linux/spi/spi.h> +#include <linux/spi/adi_spi3.h>  #include <linux/types.h> -#include <asm/bfin_spi3.h> -#include <asm/cacheflush.h>  #include <asm/dma.h>  #include <asm/portmux.h> -enum bfin_spi_state { +enum adi_spi_state {  	START_STATE,  	RUNNING_STATE,  	DONE_STATE,  	ERROR_STATE  }; -struct bfin_spi_master; +struct adi_spi_master; -struct bfin_spi_transfer_ops { -	void (*write) (struct bfin_spi_master *); -	void (*read) (struct bfin_spi_master *); -	void (*duplex) (struct bfin_spi_master *); +struct adi_spi_transfer_ops { +	void (*write) (struct adi_spi_master *); +	void (*read) (struct adi_spi_master *); +	void (*duplex) (struct adi_spi_master *);  };  /* runtime info for spi master */ -struct bfin_spi_master { +struct adi_spi_master {  	/* SPI framework hookup */  	struct spi_master *master;  	/* Regs base of SPI controller */ -	struct bfin_spi_regs __iomem *regs; +	struct adi_spi_regs __iomem *regs;  	/* Pin request list */  	u16 *pin_req; @@ -65,7 +65,7 @@ struct bfin_spi_master {  	/* Current message transfer state info */  	struct spi_message *cur_msg;  	struct spi_transfer *cur_transfer; -	struct bfin_spi_device *cur_chip; +	struct adi_spi_device *cur_chip;  	unsigned transfer_len;  	/* transfer buffer */ @@ -90,12 +90,12 @@ struct bfin_spi_master {  	u32 ssel;  	unsigned long sclk; -	enum bfin_spi_state state; +	enum adi_spi_state state; -	const struct bfin_spi_transfer_ops *ops; +	const struct adi_spi_transfer_ops *ops;  }; -struct bfin_spi_device { +struct adi_spi_device {  	u32 control;  	u32 clock;  	u32 ssel; @@ -105,17 +105,25 @@ struct bfin_spi_device {  	u32 cs_gpio;  	u32 tx_dummy_val; /* tx value for rx only transfer */  	bool enable_dma; -	const struct bfin_spi_transfer_ops *ops; +	const struct adi_spi_transfer_ops *ops;  }; -static void bfin_spi_enable(struct bfin_spi_master *drv_data) +static void adi_spi_enable(struct adi_spi_master *drv_data)  { -	bfin_write_or(&drv_data->regs->control, SPI_CTL_EN); +	u32 ctl; + +	ctl = ioread32(&drv_data->regs->control); +	ctl |= SPI_CTL_EN; +	iowrite32(ctl, &drv_data->regs->control);  } -static void bfin_spi_disable(struct bfin_spi_master *drv_data) +static void adi_spi_disable(struct adi_spi_master *drv_data)  { -	bfin_write_and(&drv_data->regs->control, ~SPI_CTL_EN); +	u32 ctl; + +	ctl = ioread32(&drv_data->regs->control); +	ctl &= ~SPI_CTL_EN; +	iowrite32(ctl, &drv_data->regs->control);  }  /* Caculate the SPI_CLOCK register value based on input HZ */ @@ -128,35 +136,43 @@ static u32 hz_to_spi_clock(u32 sclk, u32 speed_hz)  	return spi_clock;  } -static int bfin_spi_flush(struct bfin_spi_master *drv_data) +static int adi_spi_flush(struct adi_spi_master *drv_data)  {  	unsigned long limit = loops_per_jiffy << 1;  	/* wait for stop and clear stat */ -	while (!(bfin_read(&drv_data->regs->status) & SPI_STAT_SPIF) && --limit) +	while (!(ioread32(&drv_data->regs->status) & SPI_STAT_SPIF) && --limit)  		cpu_relax(); -	bfin_write(&drv_data->regs->status, 0xFFFFFFFF); +	iowrite32(0xFFFFFFFF, &drv_data->regs->status);  	return limit;  }  /* Chip select operation functions for cs_change flag */ -static void bfin_spi_cs_active(struct bfin_spi_master *drv_data, struct bfin_spi_device *chip) +static void adi_spi_cs_active(struct adi_spi_master *drv_data, struct adi_spi_device *chip)  { -	if (likely(chip->cs < MAX_CTRL_CS)) -		bfin_write_and(&drv_data->regs->ssel, ~chip->ssel); -	else +	if (likely(chip->cs < MAX_CTRL_CS)) { +		u32 reg; +		reg = ioread32(&drv_data->regs->ssel); +		reg &= ~chip->ssel; +		iowrite32(reg, &drv_data->regs->ssel); +	} else {  		gpio_set_value(chip->cs_gpio, 0); +	}  } -static void bfin_spi_cs_deactive(struct bfin_spi_master *drv_data, -				struct bfin_spi_device *chip) +static void adi_spi_cs_deactive(struct adi_spi_master *drv_data, +				struct adi_spi_device *chip)  { -	if (likely(chip->cs < MAX_CTRL_CS)) -		bfin_write_or(&drv_data->regs->ssel, chip->ssel); -	else +	if (likely(chip->cs < MAX_CTRL_CS)) { +		u32 reg; +		reg = ioread32(&drv_data->regs->ssel); +		reg |= chip->ssel; +		iowrite32(reg, &drv_data->regs->ssel); +	} else {  		gpio_set_value(chip->cs_gpio, 1); +	}  	/* Move delay here for consistency */  	if (chip->cs_chg_udelay) @@ -164,187 +180,192 @@ static void bfin_spi_cs_deactive(struct bfin_spi_master *drv_data,  }  /* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */ -static inline void bfin_spi_cs_enable(struct bfin_spi_master *drv_data, -					struct bfin_spi_device *chip) +static inline void adi_spi_cs_enable(struct adi_spi_master *drv_data, +					struct adi_spi_device *chip)  { -	if (chip->cs < MAX_CTRL_CS) -		bfin_write_or(&drv_data->regs->ssel, chip->ssel >> 8); +	if (chip->cs < MAX_CTRL_CS) { +		u32 reg; +		reg = ioread32(&drv_data->regs->ssel); +		reg |= chip->ssel >> 8; +		iowrite32(reg, &drv_data->regs->ssel); +	}  } -static inline void bfin_spi_cs_disable(struct bfin_spi_master *drv_data, -					struct bfin_spi_device *chip) +static inline void adi_spi_cs_disable(struct adi_spi_master *drv_data, +					struct adi_spi_device *chip)  { -	if (chip->cs < MAX_CTRL_CS) -		bfin_write_and(&drv_data->regs->ssel, ~(chip->ssel >> 8)); +	if (chip->cs < MAX_CTRL_CS) { +		u32 reg; +		reg = ioread32(&drv_data->regs->ssel); +		reg &= ~(chip->ssel >> 8); +		iowrite32(reg, &drv_data->regs->ssel); +	}  }  /* stop controller and re-config current chip*/ -static void bfin_spi_restore_state(struct bfin_spi_master *drv_data) +static void adi_spi_restore_state(struct adi_spi_master *drv_data)  { -	struct bfin_spi_device *chip = drv_data->cur_chip; +	struct adi_spi_device *chip = drv_data->cur_chip;  	/* Clear status and disable clock */ -	bfin_write(&drv_data->regs->status, 0xFFFFFFFF); -	bfin_write(&drv_data->regs->rx_control, 0x0); -	bfin_write(&drv_data->regs->tx_control, 0x0); -	bfin_spi_disable(drv_data); - -	SSYNC(); +	iowrite32(0xFFFFFFFF, &drv_data->regs->status); +	iowrite32(0x0, &drv_data->regs->rx_control); +	iowrite32(0x0, &drv_data->regs->tx_control); +	adi_spi_disable(drv_data);  	/* Load the registers */ -	bfin_write(&drv_data->regs->control, chip->control); -	bfin_write(&drv_data->regs->clock, chip->clock); +	iowrite32(chip->control, &drv_data->regs->control); +	iowrite32(chip->clock, &drv_data->regs->clock); -	bfin_spi_enable(drv_data); +	adi_spi_enable(drv_data);  	drv_data->tx_num = drv_data->rx_num = 0;  	/* we always choose tx transfer initiate */ -	bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN); -	bfin_write(&drv_data->regs->tx_control, -			SPI_TXCTL_TEN | SPI_TXCTL_TTI); -	bfin_spi_cs_active(drv_data, chip); +	iowrite32(SPI_RXCTL_REN, &drv_data->regs->rx_control); +	iowrite32(SPI_TXCTL_TEN | SPI_TXCTL_TTI, &drv_data->regs->tx_control); +	adi_spi_cs_active(drv_data, chip);  }  /* discard invalid rx data and empty rfifo */ -static inline void dummy_read(struct bfin_spi_master *drv_data) +static inline void dummy_read(struct adi_spi_master *drv_data)  { -	while (!(bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)) -		bfin_read(&drv_data->regs->rfifo); +	while (!(ioread32(&drv_data->regs->status) & SPI_STAT_RFE)) +		ioread32(&drv_data->regs->rfifo);  } -static void bfin_spi_u8_write(struct bfin_spi_master *drv_data) +static void adi_spi_u8_write(struct adi_spi_master *drv_data)  {  	dummy_read(drv_data);  	while (drv_data->tx < drv_data->tx_end) { -		bfin_write(&drv_data->regs->tfifo, (*(u8 *)(drv_data->tx++))); -		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) +		iowrite32(*(u8 *)(drv_data->tx++), &drv_data->regs->tfifo); +		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)  			cpu_relax(); -		bfin_read(&drv_data->regs->rfifo); +		ioread32(&drv_data->regs->rfifo);  	}  } -static void bfin_spi_u8_read(struct bfin_spi_master *drv_data) +static void adi_spi_u8_read(struct adi_spi_master *drv_data)  {  	u32 tx_val = drv_data->cur_chip->tx_dummy_val;  	dummy_read(drv_data);  	while (drv_data->rx < drv_data->rx_end) { -		bfin_write(&drv_data->regs->tfifo, tx_val); -		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) +		iowrite32(tx_val, &drv_data->regs->tfifo); +		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)  			cpu_relax(); -		*(u8 *)(drv_data->rx++) = bfin_read(&drv_data->regs->rfifo); +		*(u8 *)(drv_data->rx++) = ioread32(&drv_data->regs->rfifo);  	}  } -static void bfin_spi_u8_duplex(struct bfin_spi_master *drv_data) +static void adi_spi_u8_duplex(struct adi_spi_master *drv_data)  {  	dummy_read(drv_data);  	while (drv_data->rx < drv_data->rx_end) { -		bfin_write(&drv_data->regs->tfifo, (*(u8 *)(drv_data->tx++))); -		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) +		iowrite32(*(u8 *)(drv_data->tx++), &drv_data->regs->tfifo); +		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)  			cpu_relax(); -		*(u8 *)(drv_data->rx++) = bfin_read(&drv_data->regs->rfifo); +		*(u8 *)(drv_data->rx++) = ioread32(&drv_data->regs->rfifo);  	}  } -static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u8 = { -	.write  = bfin_spi_u8_write, -	.read   = bfin_spi_u8_read, -	.duplex = bfin_spi_u8_duplex, +static const struct adi_spi_transfer_ops adi_spi_transfer_ops_u8 = { +	.write  = adi_spi_u8_write, +	.read   = adi_spi_u8_read, +	.duplex = adi_spi_u8_duplex,  }; -static void bfin_spi_u16_write(struct bfin_spi_master *drv_data) +static void adi_spi_u16_write(struct adi_spi_master *drv_data)  {  	dummy_read(drv_data);  	while (drv_data->tx < drv_data->tx_end) { -		bfin_write(&drv_data->regs->tfifo, (*(u16 *)drv_data->tx)); +		iowrite32(*(u16 *)drv_data->tx, &drv_data->regs->tfifo);  		drv_data->tx += 2; -		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) +		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)  			cpu_relax(); -		bfin_read(&drv_data->regs->rfifo); +		ioread32(&drv_data->regs->rfifo);  	}  } -static void bfin_spi_u16_read(struct bfin_spi_master *drv_data) +static void adi_spi_u16_read(struct adi_spi_master *drv_data)  {  	u32 tx_val = drv_data->cur_chip->tx_dummy_val;  	dummy_read(drv_data);  	while (drv_data->rx < drv_data->rx_end) { -		bfin_write(&drv_data->regs->tfifo, tx_val); -		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) +		iowrite32(tx_val, &drv_data->regs->tfifo); +		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)  			cpu_relax(); -		*(u16 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo); +		*(u16 *)drv_data->rx = ioread32(&drv_data->regs->rfifo);  		drv_data->rx += 2;  	}  } -static void bfin_spi_u16_duplex(struct bfin_spi_master *drv_data) +static void adi_spi_u16_duplex(struct adi_spi_master *drv_data)  {  	dummy_read(drv_data);  	while (drv_data->rx < drv_data->rx_end) { -		bfin_write(&drv_data->regs->tfifo, (*(u16 *)drv_data->tx)); +		iowrite32(*(u16 *)drv_data->tx, &drv_data->regs->tfifo);  		drv_data->tx += 2; -		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) +		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)  			cpu_relax(); -		*(u16 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo); +		*(u16 *)drv_data->rx = ioread32(&drv_data->regs->rfifo);  		drv_data->rx += 2;  	}  } -static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u16 = { -	.write  = bfin_spi_u16_write, -	.read   = bfin_spi_u16_read, -	.duplex = bfin_spi_u16_duplex, +static const struct adi_spi_transfer_ops adi_spi_transfer_ops_u16 = { +	.write  = adi_spi_u16_write, +	.read   = adi_spi_u16_read, +	.duplex = adi_spi_u16_duplex,  }; -static void bfin_spi_u32_write(struct bfin_spi_master *drv_data) +static void adi_spi_u32_write(struct adi_spi_master *drv_data)  {  	dummy_read(drv_data);  	while (drv_data->tx < drv_data->tx_end) { -		bfin_write(&drv_data->regs->tfifo, (*(u32 *)drv_data->tx)); +		iowrite32(*(u32 *)drv_data->tx, &drv_data->regs->tfifo);  		drv_data->tx += 4; -		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) +		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)  			cpu_relax(); -		bfin_read(&drv_data->regs->rfifo); +		ioread32(&drv_data->regs->rfifo);  	}  } -static void bfin_spi_u32_read(struct bfin_spi_master *drv_data) +static void adi_spi_u32_read(struct adi_spi_master *drv_data)  {  	u32 tx_val = drv_data->cur_chip->tx_dummy_val;  	dummy_read(drv_data);  	while (drv_data->rx < drv_data->rx_end) { -		bfin_write(&drv_data->regs->tfifo, tx_val); -		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) +		iowrite32(tx_val, &drv_data->regs->tfifo); +		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)  			cpu_relax(); -		*(u32 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo); +		*(u32 *)drv_data->rx = ioread32(&drv_data->regs->rfifo);  		drv_data->rx += 4;  	}  } -static void bfin_spi_u32_duplex(struct bfin_spi_master *drv_data) +static void adi_spi_u32_duplex(struct adi_spi_master *drv_data)  {  	dummy_read(drv_data);  	while (drv_data->rx < drv_data->rx_end) { -		bfin_write(&drv_data->regs->tfifo, (*(u32 *)drv_data->tx)); +		iowrite32(*(u32 *)drv_data->tx, &drv_data->regs->tfifo);  		drv_data->tx += 4; -		while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) +		while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)  			cpu_relax(); -		*(u32 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo); +		*(u32 *)drv_data->rx = ioread32(&drv_data->regs->rfifo);  		drv_data->rx += 4;  	}  } -static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u32 = { -	.write  = bfin_spi_u32_write, -	.read   = bfin_spi_u32_read, -	.duplex = bfin_spi_u32_duplex, +static const struct adi_spi_transfer_ops adi_spi_transfer_ops_u32 = { +	.write  = adi_spi_u32_write, +	.read   = adi_spi_u32_read, +	.duplex = adi_spi_u32_duplex,  };  /* test if there is more transfer to be done */ -static void bfin_spi_next_transfer(struct bfin_spi_master *drv) +static void adi_spi_next_transfer(struct adi_spi_master *drv)  {  	struct spi_message *msg = drv->cur_msg;  	struct spi_transfer *t = drv->cur_transfer; @@ -360,15 +381,15 @@ static void bfin_spi_next_transfer(struct bfin_spi_master *drv)  	}  } -static void bfin_spi_giveback(struct bfin_spi_master *drv_data) +static void adi_spi_giveback(struct adi_spi_master *drv_data)  { -	struct bfin_spi_device *chip = drv_data->cur_chip; +	struct adi_spi_device *chip = drv_data->cur_chip; -	bfin_spi_cs_deactive(drv_data, chip); +	adi_spi_cs_deactive(drv_data, chip);  	spi_finalize_current_message(drv_data->master);  } -static int bfin_spi_setup_transfer(struct bfin_spi_master *drv) +static int adi_spi_setup_transfer(struct adi_spi_master *drv)  {  	struct spi_transfer *t = drv->cur_transfer;  	u32 cr, cr_width; @@ -393,34 +414,33 @@ static int bfin_spi_setup_transfer(struct bfin_spi_master *drv)  	switch (t->bits_per_word) {  	case 8:  		cr_width = SPI_CTL_SIZE08; -		drv->ops = &bfin_bfin_spi_transfer_ops_u8; +		drv->ops = &adi_spi_transfer_ops_u8;  		break;  	case 16:  		cr_width = SPI_CTL_SIZE16; -		drv->ops = &bfin_bfin_spi_transfer_ops_u16; +		drv->ops = &adi_spi_transfer_ops_u16;  		break;  	case 32:  		cr_width = SPI_CTL_SIZE32; -		drv->ops = &bfin_bfin_spi_transfer_ops_u32; +		drv->ops = &adi_spi_transfer_ops_u32;  		break;  	default:  		return -EINVAL;  	} -	cr = bfin_read(&drv->regs->control) & ~SPI_CTL_SIZE; +	cr = ioread32(&drv->regs->control) & ~SPI_CTL_SIZE;  	cr |= cr_width; -	bfin_write(&drv->regs->control, cr); +	iowrite32(cr, &drv->regs->control);  	/* speed setup */ -	bfin_write(&drv->regs->clock, -			hz_to_spi_clock(drv->sclk, t->speed_hz)); +	iowrite32(hz_to_spi_clock(drv->sclk, t->speed_hz), &drv->regs->clock);  	return 0;  } -static int bfin_spi_dma_xfer(struct bfin_spi_master *drv_data) +static int adi_spi_dma_xfer(struct adi_spi_master *drv_data)  {  	struct spi_transfer *t = drv_data->cur_transfer;  	struct spi_message *msg = drv_data->cur_msg; -	struct bfin_spi_device *chip = drv_data->cur_chip; +	struct adi_spi_device *chip = drv_data->cur_chip;  	u32 dma_config;  	unsigned long word_count, word_size;  	void *tx_buf, *rx_buf; @@ -498,17 +518,16 @@ static int bfin_spi_dma_xfer(struct bfin_spi_master *drv_data)  	set_dma_config(drv_data->rx_dma, dma_config | WNR);  	enable_dma(drv_data->tx_dma);  	enable_dma(drv_data->rx_dma); -	SSYNC(); -	bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN | SPI_RXCTL_RDR_NE); -	SSYNC(); -	bfin_write(&drv_data->regs->tx_control, -			SPI_TXCTL_TEN | SPI_TXCTL_TTI | SPI_TXCTL_TDR_NF); +	iowrite32(SPI_RXCTL_REN | SPI_RXCTL_RDR_NE, +			&drv_data->regs->rx_control); +	iowrite32(SPI_TXCTL_TEN | SPI_TXCTL_TTI | SPI_TXCTL_TDR_NF, +			&drv_data->regs->tx_control);  	return 0;  } -static int bfin_spi_pio_xfer(struct bfin_spi_master *drv_data) +static int adi_spi_pio_xfer(struct adi_spi_master *drv_data)  {  	struct spi_message *msg = drv_data->cur_msg; @@ -529,19 +548,19 @@ static int bfin_spi_pio_xfer(struct bfin_spi_master *drv_data)  			return -EIO;  	} -	if (!bfin_spi_flush(drv_data)) +	if (!adi_spi_flush(drv_data))  		return -EIO;  	msg->actual_length += drv_data->transfer_len;  	tasklet_schedule(&drv_data->pump_transfers);  	return 0;  } -static void bfin_spi_pump_transfers(unsigned long data) +static void adi_spi_pump_transfers(unsigned long data)  { -	struct bfin_spi_master *drv_data = (struct bfin_spi_master *)data; +	struct adi_spi_master *drv_data = (struct adi_spi_master *)data;  	struct spi_message *msg = NULL;  	struct spi_transfer *t = NULL; -	struct bfin_spi_device *chip = NULL; +	struct adi_spi_device *chip = NULL;  	int ret;  	/* Get current state information */ @@ -552,7 +571,7 @@ static void bfin_spi_pump_transfers(unsigned long data)  	/* Handle for abort */  	if (drv_data->state == ERROR_STATE) {  		msg->status = -EIO; -		bfin_spi_giveback(drv_data); +		adi_spi_giveback(drv_data);  		return;  	} @@ -560,14 +579,14 @@ static void bfin_spi_pump_transfers(unsigned long data)  		if (t->delay_usecs)  			udelay(t->delay_usecs);  		if (t->cs_change) -			bfin_spi_cs_deactive(drv_data, chip); -		bfin_spi_next_transfer(drv_data); +			adi_spi_cs_deactive(drv_data, chip); +		adi_spi_next_transfer(drv_data);  		t = drv_data->cur_transfer;  	}  	/* Handle end of message */  	if (drv_data->state == DONE_STATE) {  		msg->status = 0; -		bfin_spi_giveback(drv_data); +		adi_spi_giveback(drv_data);  		return;  	} @@ -577,34 +596,34 @@ static void bfin_spi_pump_transfers(unsigned long data)  		return;  	} -	ret = bfin_spi_setup_transfer(drv_data); +	ret = adi_spi_setup_transfer(drv_data);  	if (ret) {  		msg->status = ret; -		bfin_spi_giveback(drv_data); +		adi_spi_giveback(drv_data);  	} -	bfin_write(&drv_data->regs->status, 0xFFFFFFFF); -	bfin_spi_cs_active(drv_data, chip); +	iowrite32(0xFFFFFFFF, &drv_data->regs->status); +	adi_spi_cs_active(drv_data, chip);  	drv_data->state = RUNNING_STATE;  	if (chip->enable_dma) -		ret = bfin_spi_dma_xfer(drv_data); +		ret = adi_spi_dma_xfer(drv_data);  	else -		ret = bfin_spi_pio_xfer(drv_data); +		ret = adi_spi_pio_xfer(drv_data);  	if (ret) {  		msg->status = ret; -		bfin_spi_giveback(drv_data); +		adi_spi_giveback(drv_data);  	}  } -static int bfin_spi_transfer_one_message(struct spi_master *master, +static int adi_spi_transfer_one_message(struct spi_master *master,  					struct spi_message *m)  { -	struct bfin_spi_master *drv_data = spi_master_get_devdata(master); +	struct adi_spi_master *drv_data = spi_master_get_devdata(master);  	drv_data->cur_msg = m;  	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); -	bfin_spi_restore_state(drv_data); +	adi_spi_restore_state(drv_data);  	drv_data->state = START_STATE;  	drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next, @@ -630,15 +649,15 @@ static const u16 ssel[][MAX_SPI_SSEL] = {  	P_SPI2_SSEL6, P_SPI2_SSEL7},  }; -static int bfin_spi_setup(struct spi_device *spi) +static int adi_spi_setup(struct spi_device *spi)  { -	struct bfin_spi_master *drv_data = spi_master_get_devdata(spi->master); -	struct bfin_spi_device *chip = spi_get_ctldata(spi); -	u32 bfin_ctl_reg = SPI_CTL_ODM | SPI_CTL_PSSE; +	struct adi_spi_master *drv_data = spi_master_get_devdata(spi->master); +	struct adi_spi_device *chip = spi_get_ctldata(spi); +	u32 ctl_reg = SPI_CTL_ODM | SPI_CTL_PSSE;  	int ret = -EINVAL;  	if (!chip) { -		struct bfin_spi3_chip *chip_info = spi->controller_data; +		struct adi_spi3_chip *chip_info = spi->controller_data;  		chip = kzalloc(sizeof(*chip), GFP_KERNEL);  		if (!chip) { @@ -646,7 +665,7 @@ static int bfin_spi_setup(struct spi_device *spi)  			return -ENOMEM;  		}  		if (chip_info) { -			if (chip_info->control & ~bfin_ctl_reg) { +			if (chip_info->control & ~ctl_reg) {  				dev_err(&spi->dev,  					"do not set bits that the SPI framework manages\n");  				goto error; @@ -657,6 +676,7 @@ static int bfin_spi_setup(struct spi_device *spi)  			chip->enable_dma = chip_info->enable_dma;  		}  		chip->cs = spi->chip_select; +  		if (chip->cs < MAX_CTRL_CS) {  			chip->ssel = (1 << chip->cs) << 8;  			ret = peripheral_request(ssel[spi->master->bus_num] @@ -678,7 +698,7 @@ static int bfin_spi_setup(struct spi_device *spi)  	}  	/* force a default base state */ -	chip->control &= bfin_ctl_reg; +	chip->control &= ctl_reg;  	if (spi->mode & SPI_CPOL)  		chip->control |= SPI_CTL_CPOL; @@ -692,8 +712,8 @@ static int bfin_spi_setup(struct spi_device *spi)  	chip->clock = hz_to_spi_clock(drv_data->sclk, spi->max_speed_hz); -	bfin_spi_cs_enable(drv_data, chip); -	bfin_spi_cs_deactive(drv_data, chip); +	adi_spi_cs_enable(drv_data, chip); +	adi_spi_cs_deactive(drv_data, chip);  	return 0;  error: @@ -705,10 +725,10 @@ error:  	return ret;  } -static void bfin_spi_cleanup(struct spi_device *spi) +static void adi_spi_cleanup(struct spi_device *spi)  { -	struct bfin_spi_device *chip = spi_get_ctldata(spi); -	struct bfin_spi_master *drv_data = spi_master_get_devdata(spi->master); +	struct adi_spi_device *chip = spi_get_ctldata(spi); +	struct adi_spi_master *drv_data = spi_master_get_devdata(spi->master);  	if (!chip)  		return; @@ -716,7 +736,7 @@ static void bfin_spi_cleanup(struct spi_device *spi)  	if (chip->cs < MAX_CTRL_CS) {  		peripheral_free(ssel[spi->master->bus_num]  					[chip->cs-1]); -		bfin_spi_cs_disable(drv_data, chip); +		adi_spi_cs_disable(drv_data, chip);  	} else {  		gpio_free(chip->cs_gpio);  	} @@ -725,10 +745,11 @@ static void bfin_spi_cleanup(struct spi_device *spi)  	spi_set_ctldata(spi, NULL);  } -static irqreturn_t bfin_spi_tx_dma_isr(int irq, void *dev_id) +static irqreturn_t adi_spi_tx_dma_isr(int irq, void *dev_id)  { -	struct bfin_spi_master *drv_data = dev_id; +	struct adi_spi_master *drv_data = dev_id;  	u32 dma_stat = get_dma_curr_irqstat(drv_data->tx_dma); +	u32 tx_ctl;  	clear_dma_irqstat(drv_data->tx_dma);  	if (dma_stat & DMA_DONE) { @@ -739,13 +760,15 @@ static irqreturn_t bfin_spi_tx_dma_isr(int irq, void *dev_id)  		if (drv_data->tx)  			drv_data->state = ERROR_STATE;  	} -	bfin_write_and(&drv_data->regs->tx_control, ~SPI_TXCTL_TDR_NF); +	tx_ctl = ioread32(&drv_data->regs->tx_control); +	tx_ctl &= ~SPI_TXCTL_TDR_NF; +	iowrite32(tx_ctl, &drv_data->regs->tx_control);  	return IRQ_HANDLED;  } -static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id) +static irqreturn_t adi_spi_rx_dma_isr(int irq, void *dev_id)  { -	struct bfin_spi_master *drv_data = dev_id; +	struct adi_spi_master *drv_data = dev_id;  	struct spi_message *msg = drv_data->cur_msg;  	u32 dma_stat = get_dma_curr_irqstat(drv_data->rx_dma); @@ -760,8 +783,8 @@ static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id)  		dev_err(&drv_data->master->dev,  				"spi rx dma error: %d\n", dma_stat);  	} -	bfin_write(&drv_data->regs->tx_control, 0); -	bfin_write(&drv_data->regs->rx_control, 0); +	iowrite32(0, &drv_data->regs->tx_control); +	iowrite32(0, &drv_data->regs->rx_control);  	if (drv_data->rx_num != drv_data->tx_num)  		dev_dbg(&drv_data->master->dev,  				"dma interrupt missing: tx=%d,rx=%d\n", @@ -770,15 +793,15 @@ static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id)  	return IRQ_HANDLED;  } -static int bfin_spi_probe(struct platform_device *pdev) +static int adi_spi_probe(struct platform_device *pdev)  {  	struct device *dev = &pdev->dev; -	struct bfin_spi3_master *info = dev_get_platdata(dev); +	struct adi_spi3_master *info = dev_get_platdata(dev);  	struct spi_master *master; -	struct bfin_spi_master *drv_data; +	struct adi_spi_master *drv_data;  	struct resource *mem, *res;  	unsigned int tx_dma, rx_dma; -	unsigned long sclk; +	struct clk *sclk;  	int ret;  	if (!info) { @@ -786,10 +809,10 @@ static int bfin_spi_probe(struct platform_device *pdev)  		return -ENODEV;  	} -	sclk = get_sclk1(); -	if (!sclk) { -		dev_err(dev, "can not get sclk1\n"); -		return -ENXIO; +	sclk = devm_clk_get(dev, "spi"); +	if (IS_ERR(sclk)) { +		dev_err(dev, "can not get spi clock\n"); +		return PTR_ERR(sclk);  	}  	res = platform_get_resource(pdev, IORESOURCE_DMA, 0); @@ -819,9 +842,9 @@ static int bfin_spi_probe(struct platform_device *pdev)  	master->bus_num = pdev->id;  	master->num_chipselect = info->num_chipselect; -	master->cleanup = bfin_spi_cleanup; -	master->setup = bfin_spi_setup; -	master->transfer_one_message = bfin_spi_transfer_one_message; +	master->cleanup = adi_spi_cleanup; +	master->setup = adi_spi_setup; +	master->transfer_one_message = adi_spi_transfer_one_message;  	master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) |  				     SPI_BPW_MASK(8); @@ -830,7 +853,7 @@ static int bfin_spi_probe(struct platform_device *pdev)  	drv_data->tx_dma = tx_dma;  	drv_data->rx_dma = rx_dma;  	drv_data->pin_req = info->pin_req; -	drv_data->sclk = sclk; +	drv_data->sclk = clk_get_rate(sclk);  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	drv_data->regs = devm_ioremap_resource(dev, mem); @@ -845,28 +868,28 @@ static int bfin_spi_probe(struct platform_device *pdev)  		dev_err(dev, "can not request SPI TX DMA channel\n");  		goto err_put_master;  	} -	set_dma_callback(tx_dma, bfin_spi_tx_dma_isr, drv_data); +	set_dma_callback(tx_dma, adi_spi_tx_dma_isr, drv_data);  	ret = request_dma(rx_dma, "SPI_RX_DMA");  	if (ret) {  		dev_err(dev, "can not request SPI RX DMA channel\n");  		goto err_free_tx_dma;  	} -	set_dma_callback(drv_data->rx_dma, bfin_spi_rx_dma_isr, drv_data); +	set_dma_callback(drv_data->rx_dma, adi_spi_rx_dma_isr, drv_data);  	/* request CLK, MOSI and MISO */ -	ret = peripheral_request_list(drv_data->pin_req, "bfin-spi3"); +	ret = peripheral_request_list(drv_data->pin_req, "adi-spi3");  	if (ret < 0) {  		dev_err(dev, "can not request spi pins\n");  		goto err_free_rx_dma;  	} -	bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA); -	bfin_write(&drv_data->regs->ssel, 0x0000FE00); -	bfin_write(&drv_data->regs->delay, 0x0); +	iowrite32(SPI_CTL_MSTR | SPI_CTL_CPHA, &drv_data->regs->control); +	iowrite32(0x0000FE00, &drv_data->regs->ssel); +	iowrite32(0x0, &drv_data->regs->delay);  	tasklet_init(&drv_data->pump_transfers, -			bfin_spi_pump_transfers, (unsigned long)drv_data); +			adi_spi_pump_transfers, (unsigned long)drv_data);  	/* register with the SPI framework */  	ret = devm_spi_register_master(dev, master);  	if (ret) { @@ -888,43 +911,41 @@ err_put_master:  	return ret;  } -static int bfin_spi_remove(struct platform_device *pdev) +static int adi_spi_remove(struct platform_device *pdev)  {  	struct spi_master *master = platform_get_drvdata(pdev); -	struct bfin_spi_master *drv_data = spi_master_get_devdata(master); - -	bfin_spi_disable(drv_data); +	struct adi_spi_master *drv_data = spi_master_get_devdata(master); +	adi_spi_disable(drv_data);  	peripheral_free_list(drv_data->pin_req);  	free_dma(drv_data->rx_dma);  	free_dma(drv_data->tx_dma); -  	return 0;  }  #ifdef CONFIG_PM -static int bfin_spi_suspend(struct device *dev) +static int adi_spi_suspend(struct device *dev)  {  	struct spi_master *master = dev_get_drvdata(dev); -	struct bfin_spi_master *drv_data = spi_master_get_devdata(master); +	struct adi_spi_master *drv_data = spi_master_get_devdata(master);  	spi_master_suspend(master); -	drv_data->control = bfin_read(&drv_data->regs->control); -	drv_data->ssel = bfin_read(&drv_data->regs->ssel); +	drv_data->control = ioread32(&drv_data->regs->control); +	drv_data->ssel = ioread32(&drv_data->regs->ssel); -	bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA); -	bfin_write(&drv_data->regs->ssel, 0x0000FE00); +	iowrite32(SPI_CTL_MSTR | SPI_CTL_CPHA, &drv_data->regs->control); +	iowrite32(0x0000FE00, &drv_data->regs->ssel);  	dma_disable_irq(drv_data->rx_dma);  	dma_disable_irq(drv_data->tx_dma);  	return 0;  } -static int bfin_spi_resume(struct device *dev) +static int adi_spi_resume(struct device *dev)  {  	struct spi_master *master = dev_get_drvdata(dev); -	struct bfin_spi_master *drv_data = spi_master_get_devdata(master); +	struct adi_spi_master *drv_data = spi_master_get_devdata(master);  	int ret = 0;  	/* bootrom may modify spi and dma status when resume in spi boot mode */ @@ -932,8 +953,8 @@ static int bfin_spi_resume(struct device *dev)  	dma_enable_irq(drv_data->rx_dma);  	dma_enable_irq(drv_data->tx_dma); -	bfin_write(&drv_data->regs->control, drv_data->control); -	bfin_write(&drv_data->regs->ssel, drv_data->ssel); +	iowrite32(drv_data->control, &drv_data->regs->control); +	iowrite32(drv_data->ssel, &drv_data->regs->ssel);  	ret = spi_master_resume(master);  	if (ret) { @@ -944,21 +965,21 @@ static int bfin_spi_resume(struct device *dev)  	return ret;  }  #endif -static const struct dev_pm_ops bfin_spi_pm_ops = { -	SET_SYSTEM_SLEEP_PM_OPS(bfin_spi_suspend, bfin_spi_resume) +static const struct dev_pm_ops adi_spi_pm_ops = { +	SET_SYSTEM_SLEEP_PM_OPS(adi_spi_suspend, adi_spi_resume)  }; -MODULE_ALIAS("platform:bfin-spi3"); -static struct platform_driver bfin_spi_driver = { +MODULE_ALIAS("platform:adi-spi3"); +static struct platform_driver adi_spi_driver = {  	.driver	= { -		.name	= "bfin-spi3", +		.name	= "adi-spi3",  		.owner	= THIS_MODULE, -		.pm     = &bfin_spi_pm_ops, +		.pm     = &adi_spi_pm_ops,  	}, -	.remove		= bfin_spi_remove, +	.remove		= adi_spi_remove,  }; -module_platform_driver_probe(bfin_spi_driver, bfin_spi_probe); +module_platform_driver_probe(adi_spi_driver, adi_spi_probe);  MODULE_DESCRIPTION("Analog Devices SPI3 controller driver");  MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index 3898b0b9ee77..058db0fe8dc7 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -16,7 +16,6 @@  #include <linux/module.h>  #include <linux/delay.h>  #include <linux/spinlock.h> -#include <linux/workqueue.h>  #include <linux/platform_device.h>  #include <linux/io.h>  #include <linux/spi/spi.h> diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 079e6b1b0cdb..92a6f0d93233 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -224,7 +224,7 @@ struct atmel_spi {  	struct platform_device	*pdev;  	struct spi_transfer	*current_transfer; -	unsigned long		current_remaining_bytes; +	int			current_remaining_bytes;  	int			done_status;  	struct completion	xfer_completion; @@ -874,8 +874,9 @@ atmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer)  		spi_readl(as, RDR);  	}  	if (xfer->bits_per_word > 8) { -		as->current_remaining_bytes -= 2; -		if (as->current_remaining_bytes < 0) +		if (as->current_remaining_bytes > 2) +			as->current_remaining_bytes -= 2; +		else  			as->current_remaining_bytes = 0;  	} else {  		as->current_remaining_bytes--; @@ -1110,6 +1111,8 @@ static int atmel_spi_one_transfer(struct spi_master *master,  				atmel_spi_next_xfer_pio(master, xfer);  			} else {  				as->current_remaining_bytes -= len; +				if (as->current_remaining_bytes < 0) +					as->current_remaining_bytes = 0;  			}  		} else {  			atmel_spi_next_xfer_pio(master, xfer); diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 5a211e98383b..86f5a98aa7a2 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -18,7 +18,6 @@  #include <linux/err.h>  #include <linux/interrupt.h>  #include <linux/spi/spi.h> -#include <linux/workqueue.h>  #include <linux/mutex.h>  #define HSSPI_GLOBAL_CTRL_REG			0x0 diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 0250fa721cea..8510400e7867 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -29,7 +29,6 @@  #include <linux/spi/spi.h>  #include <linux/completion.h>  #include <linux/err.h> -#include <linux/workqueue.h>  #include <linux/pm_runtime.h>  #include <bcm63xx_dev_spi.h> diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c new file mode 100644 index 000000000000..bb758978465d --- /dev/null +++ b/drivers/spi/spi-cadence.c @@ -0,0 +1,673 @@ +/* + * Cadence SPI controller driver (master mode only) + * + * Copyright (C) 2008 - 2014 Xilinx, Inc. + * + * based on Blackfin On-Chip SPI Driver (spi_bfin5xx.c) + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_irq.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <linux/spi/spi.h> + +/* Name of this driver */ +#define CDNS_SPI_NAME		"cdns-spi" + +/* Register offset definitions */ +#define CDNS_SPI_CR_OFFSET	0x00 /* Configuration  Register, RW */ +#define CDNS_SPI_ISR_OFFSET	0x04 /* Interrupt Status Register, RO */ +#define CDNS_SPI_IER_OFFSET	0x08 /* Interrupt Enable Register, WO */ +#define CDNS_SPI_IDR_OFFSET	0x0c /* Interrupt Disable Register, WO */ +#define CDNS_SPI_IMR_OFFSET	0x10 /* Interrupt Enabled Mask Register, RO */ +#define CDNS_SPI_ER_OFFSET	0x14 /* Enable/Disable Register, RW */ +#define CDNS_SPI_DR_OFFSET	0x18 /* Delay Register, RW */ +#define CDNS_SPI_TXD_OFFSET	0x1C /* Data Transmit Register, WO */ +#define CDNS_SPI_RXD_OFFSET	0x20 /* Data Receive Register, RO */ +#define CDNS_SPI_SICR_OFFSET	0x24 /* Slave Idle Count Register, RW */ +#define CDNS_SPI_THLD_OFFSET	0x28 /* Transmit FIFO Watermark Register,RW */ + +/* + * SPI Configuration Register bit Masks + * + * This register contains various control bits that affect the operation + * of the SPI controller + */ +#define CDNS_SPI_CR_MANSTRT_MASK	0x00010000 /* Manual TX Start */ +#define CDNS_SPI_CR_CPHA_MASK		0x00000004 /* Clock Phase Control */ +#define CDNS_SPI_CR_CPOL_MASK		0x00000002 /* Clock Polarity Control */ +#define CDNS_SPI_CR_SSCTRL_MASK		0x00003C00 /* Slave Select Mask */ +#define CDNS_SPI_CR_BAUD_DIV_MASK	0x00000038 /* Baud Rate Divisor Mask */ +#define CDNS_SPI_CR_MSTREN_MASK		0x00000001 /* Master Enable Mask */ +#define CDNS_SPI_CR_MANSTRTEN_MASK	0x00008000 /* Manual TX Enable Mask */ +#define CDNS_SPI_CR_SSFORCE_MASK	0x00004000 /* Manual SS Enable Mask */ +#define CDNS_SPI_CR_BAUD_DIV_4_MASK	0x00000008 /* Default Baud Div Mask */ +#define CDNS_SPI_CR_DEFAULT_MASK	(CDNS_SPI_CR_MSTREN_MASK | \ +					CDNS_SPI_CR_SSCTRL_MASK | \ +					CDNS_SPI_CR_SSFORCE_MASK | \ +					CDNS_SPI_CR_BAUD_DIV_4_MASK) + +/* + * SPI Configuration Register - Baud rate and slave select + * + * These are the values used in the calculation of baud rate divisor and + * setting the slave select. + */ + +#define CDNS_SPI_BAUD_DIV_MAX		7 /* Baud rate divisor maximum */ +#define CDNS_SPI_BAUD_DIV_MIN		1 /* Baud rate divisor minimum */ +#define CDNS_SPI_BAUD_DIV_SHIFT		3 /* Baud rate divisor shift in CR */ +#define CDNS_SPI_SS_SHIFT		10 /* Slave Select field shift in CR */ +#define CDNS_SPI_SS0			0x1 /* Slave Select zero */ + +/* + * SPI Interrupt Registers bit Masks + * + * All the four interrupt registers (Status/Mask/Enable/Disable) have the same + * bit definitions. + */ +#define CDNS_SPI_IXR_TXOW_MASK	0x00000004 /* SPI TX FIFO Overwater */ +#define CDNS_SPI_IXR_MODF_MASK	0x00000002 /* SPI Mode Fault */ +#define CDNS_SPI_IXR_RXNEMTY_MASK 0x00000010 /* SPI RX FIFO Not Empty */ +#define CDNS_SPI_IXR_DEFAULT_MASK	(CDNS_SPI_IXR_TXOW_MASK | \ +					CDNS_SPI_IXR_MODF_MASK) +#define CDNS_SPI_IXR_TXFULL_MASK	0x00000008 /* SPI TX Full */ +#define CDNS_SPI_IXR_ALL_MASK	0x0000007F /* SPI all interrupts */ + +/* + * SPI Enable Register bit Masks + * + * This register is used to enable or disable the SPI controller + */ +#define CDNS_SPI_ER_ENABLE_MASK	0x00000001 /* SPI Enable Bit Mask */ +#define CDNS_SPI_ER_DISABLE_MASK	0x0 /* SPI Disable Bit Mask */ + +/* SPI FIFO depth in bytes */ +#define CDNS_SPI_FIFO_DEPTH	128 + +/* Default number of chip select lines */ +#define CDNS_SPI_DEFAULT_NUM_CS		4 + +/** + * struct cdns_spi - This definition defines spi driver instance + * @regs:		Virtual address of the SPI controller registers + * @ref_clk:		Pointer to the peripheral clock + * @pclk:		Pointer to the APB clock + * @speed_hz:		Current SPI bus clock speed in Hz + * @txbuf:		Pointer	to the TX buffer + * @rxbuf:		Pointer to the RX buffer + * @tx_bytes:		Number of bytes left to transfer + * @rx_bytes:		Number of bytes requested + * @dev_busy:		Device busy flag + * @is_decoded_cs:	Flag for decoder property set or not + */ +struct cdns_spi { +	void __iomem *regs; +	struct clk *ref_clk; +	struct clk *pclk; +	u32 speed_hz; +	const u8 *txbuf; +	u8 *rxbuf; +	int tx_bytes; +	int rx_bytes; +	u8 dev_busy; +	u32 is_decoded_cs; +}; + +/* Macros for the SPI controller read/write */ +static inline u32 cdns_spi_read(struct cdns_spi *xspi, u32 offset) +{ +	return readl_relaxed(xspi->regs + offset); +} + +static inline void cdns_spi_write(struct cdns_spi *xspi, u32 offset, u32 val) +{ +	writel_relaxed(val, xspi->regs + offset); +} + +/** + * 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_chipselect - Select or deselect the chip select line + * @spi:	Pointer to the spi_device structure + * @is_on:	Select(0) or deselect (1) the chip select line + */ +static void cdns_spi_chipselect(struct spi_device *spi, bool is_high) +{ +	struct cdns_spi *xspi = spi_master_get_devdata(spi->master); +	u32 ctrl_reg; + +	ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET); + +	if (is_high) { +		/* Deselect the slave */ +		ctrl_reg |= CDNS_SPI_CR_SSCTRL_MASK; +	} else { +		/* Select the slave */ +		ctrl_reg &= ~CDNS_SPI_CR_SSCTRL_MASK; +		if (!(xspi->is_decoded_cs)) +			ctrl_reg |= ((~(CDNS_SPI_SS0 << spi->chip_select)) << +				     CDNS_SPI_SS_SHIFT) & +				     CDNS_SPI_CR_SSCTRL_MASK; +		else +			ctrl_reg |= (spi->chip_select << CDNS_SPI_SS_SHIFT) & +				     CDNS_SPI_CR_SSCTRL_MASK; +	} + +	cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, 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; + +	ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET); + +	/* Set the SPI clock phase and clock polarity */ +	ctrl_reg &= ~(CDNS_SPI_CR_CPHA_MASK | CDNS_SPI_CR_CPOL_MASK); +	if (spi->mode & SPI_CPHA) +		ctrl_reg |= CDNS_SPI_CR_CPHA_MASK; +	if (spi->mode & SPI_CPOL) +		ctrl_reg |= CDNS_SPI_CR_CPOL_MASK; + +	cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg); +} + +/** + * 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_OFFSET); + +	/* 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_MASK; +		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_OFFSET, ctrl_reg); +} + +/** + * cdns_spi_setup_transfer - Configure SPI controller for specified transfer + * @spi:	Pointer to the spi_device structure + * @transfer:	Pointer to the spi_transfer structure which provides + *		information about next transfer setup parameters + * + * Sets the operational mode of SPI controller for the next SPI transfer and + * sets the requested clock frequency. + * + * Return:	Always 0 + */ +static int cdns_spi_setup_transfer(struct spi_device *spi, +				   struct spi_transfer *transfer) +{ +	struct cdns_spi *xspi = spi_master_get_devdata(spi->master); + +	cdns_spi_config_clock_freq(spi, transfer); + +	dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u clock speed\n", +		__func__, spi->mode, spi->bits_per_word, +		xspi->speed_hz); + +	return 0; +} + +/** + * 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)) { +		if (xspi->txbuf) +			cdns_spi_write(xspi, CDNS_SPI_TXD_OFFSET, +				       *xspi->txbuf++); +		else +			cdns_spi_write(xspi, CDNS_SPI_TXD_OFFSET, 0); + +		xspi->tx_bytes--; +		trans_cnt++; +	} +} + +/** + * 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_transfer_one - Initiates the SPI transfer + * @master:	Pointer to spi_master structure + * @spi:	Pointer to the spi_device structure + * @transfer:	Pointer to the spi_transfer structure which provides + *		information about next transfer parameters + * + * This function fills the TX FIFO, starts the SPI transfer and + * returns a positive transfer count so that core will wait for completion. + * + * Return:	Number of bytes transferred in the last transfer + */ +static int cdns_transfer_one(struct spi_master *master, +			     struct spi_device *spi, +			     struct spi_transfer *transfer) +{ +	struct cdns_spi *xspi = spi_master_get_devdata(master); + +	xspi->txbuf = transfer->tx_buf; +	xspi->rxbuf = transfer->rx_buf; +	xspi->tx_bytes = transfer->len; +	xspi->rx_bytes = transfer->len; + +	cdns_spi_setup_transfer(spi, transfer); + +	cdns_spi_fill_tx_fifo(xspi); + +	cdns_spi_write(xspi, CDNS_SPI_IER_OFFSET, +		       CDNS_SPI_IXR_DEFAULT_MASK); +	return transfer->len; +} + +/** + * cdns_prepare_transfer_hardware - Prepares hardware for transfer. + * @master:	Pointer to the spi_master structure which provides + *		information about the controller. + * + * This function enables SPI master controller. + * + * Return:	0 always + */ +static int cdns_prepare_transfer_hardware(struct spi_master *master) +{ +	struct cdns_spi *xspi = spi_master_get_devdata(master); + +	cdns_spi_config_clock_mode(master->cur_msg->spi); + +	cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, +		       CDNS_SPI_ER_ENABLE_MASK); + +	return 0; +} + +/** + * cdns_unprepare_transfer_hardware - Relaxes hardware after transfer + * @master:	Pointer to the spi_master structure which provides + *		information about the controller. + * + * This function disables the SPI master controller. + * + * Return:	0 always + */ +static int cdns_unprepare_transfer_hardware(struct spi_master *master) +{ +	struct cdns_spi *xspi = spi_master_get_devdata(master); + +	cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, +		       CDNS_SPI_ER_DISABLE_MASK); + +	return 0; +} + +/** + * cdns_spi_probe - Probe method for the SPI driver + * @pdev:	Pointer to the platform_device structure + * + * This function initializes the driver data structures and the hardware. + * + * Return:	0 on success and error value on error + */ +static int cdns_spi_probe(struct platform_device *pdev) +{ +	int ret = 0, irq; +	struct spi_master *master; +	struct cdns_spi *xspi; +	struct resource *res; +	u32 num_cs; + +	master = spi_alloc_master(&pdev->dev, sizeof(*xspi)); +	if (master == NULL) +		return -ENOMEM; + +	xspi = spi_master_get_devdata(master); +	master->dev.of_node = pdev->dev.of_node; +	platform_set_drvdata(pdev, master); + +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	xspi->regs = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(xspi->regs)) { +		ret = PTR_ERR(xspi->regs); +		goto remove_master; +	} + +	xspi->pclk = devm_clk_get(&pdev->dev, "pclk"); +	if (IS_ERR(xspi->pclk)) { +		dev_err(&pdev->dev, "pclk clock not found.\n"); +		ret = PTR_ERR(xspi->pclk); +		goto remove_master; +	} + +	xspi->ref_clk = devm_clk_get(&pdev->dev, "ref_clk"); +	if (IS_ERR(xspi->ref_clk)) { +		dev_err(&pdev->dev, "ref_clk clock not found.\n"); +		ret = PTR_ERR(xspi->ref_clk); +		goto remove_master; +	} + +	ret = clk_prepare_enable(xspi->pclk); +	if (ret) { +		dev_err(&pdev->dev, "Unable to enable APB clock.\n"); +		goto remove_master; +	} + +	ret = clk_prepare_enable(xspi->ref_clk); +	if (ret) { +		dev_err(&pdev->dev, "Unable to enable device clock.\n"); +		goto clk_dis_apb; +	} + +	/* SPI controller initializations */ +	cdns_spi_init_hw(xspi); + +	irq = platform_get_irq(pdev, 0); +	if (irq <= 0) { +		ret = -ENXIO; +		dev_err(&pdev->dev, "irq number is invalid\n"); +		goto remove_master; +	} + +	ret = devm_request_irq(&pdev->dev, irq, cdns_spi_irq, +			       0, pdev->name, master); +	if (ret != 0) { +		ret = -ENXIO; +		dev_err(&pdev->dev, "request_irq failed\n"); +		goto remove_master; +	} + +	ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs); + +	if (ret < 0) +		master->num_chipselect = CDNS_SPI_DEFAULT_NUM_CS; +	else +		master->num_chipselect = num_cs; + +	ret = of_property_read_u32(pdev->dev.of_node, "is-decoded-cs", +				   &xspi->is_decoded_cs); + +	if (ret < 0) +		xspi->is_decoded_cs = 0; + +	master->prepare_transfer_hardware = cdns_prepare_transfer_hardware; +	master->transfer_one = cdns_transfer_one; +	master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware; +	master->set_cs = cdns_spi_chipselect; +	master->mode_bits = SPI_CPOL | SPI_CPHA; + +	/* Set to default valid value */ +	master->max_speed_hz = clk_get_rate(xspi->ref_clk) / 4; +	xspi->speed_hz = master->max_speed_hz; + +	master->bits_per_word_mask = SPI_BPW_MASK(8); + +	ret = spi_register_master(master); +	if (ret) { +		dev_err(&pdev->dev, "spi_register_master failed\n"); +		goto clk_dis_all; +	} + +	return ret; + +clk_dis_all: +	clk_disable_unprepare(xspi->ref_clk); +clk_dis_apb: +	clk_disable_unprepare(xspi->pclk); +remove_master: +	spi_master_put(master); +	return ret; +} + +/** + * cdns_spi_remove - Remove method for the SPI driver + * @pdev:	Pointer to the platform_device structure + * + * This function is called if a device is physically removed from the system or + * if the driver module is being unloaded. It frees all resources allocated to + * the device. + * + * Return:	0 on success and error value on error + */ +static int cdns_spi_remove(struct platform_device *pdev) +{ +	struct spi_master *master = platform_get_drvdata(pdev); +	struct cdns_spi *xspi = spi_master_get_devdata(master); + +	cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, +		       CDNS_SPI_ER_DISABLE_MASK); + +	clk_disable_unprepare(xspi->ref_clk); +	clk_disable_unprepare(xspi->pclk); + +	spi_unregister_master(master); + +	return 0; +} + +/** + * cdns_spi_suspend - Suspend method for the SPI driver + * @dev:	Address of the platform_device structure + * + * This function disables the SPI controller and + * changes the driver state to "suspend" + * + * Return:	Always 0 + */ +static int __maybe_unused cdns_spi_suspend(struct device *dev) +{ +	struct platform_device *pdev = container_of(dev, +			struct platform_device, dev); +	struct spi_master *master = platform_get_drvdata(pdev); +	struct cdns_spi *xspi = spi_master_get_devdata(master); + +	spi_master_suspend(master); + +	clk_disable_unprepare(xspi->ref_clk); + +	clk_disable_unprepare(xspi->pclk); + +	return 0; +} + +/** + * cdns_spi_resume - Resume method for the SPI driver + * @dev:	Address of the platform_device structure + * + * This function changes the driver state to "ready" + * + * Return:	0 on success and error value on error + */ +static int __maybe_unused cdns_spi_resume(struct device *dev) +{ +	struct platform_device *pdev = container_of(dev, +			struct platform_device, dev); +	struct spi_master *master = platform_get_drvdata(pdev); +	struct cdns_spi *xspi = spi_master_get_devdata(master); +	int ret = 0; + +	ret = clk_prepare_enable(xspi->pclk); +	if (ret) { +		dev_err(dev, "Cannot enable APB clock.\n"); +		return ret; +	} + +	ret = clk_prepare_enable(xspi->ref_clk); +	if (ret) { +		dev_err(dev, "Cannot enable device clock.\n"); +		clk_disable(xspi->pclk); +		return ret; +	} +	spi_master_resume(master); + +	return 0; +} + +static SIMPLE_DEV_PM_OPS(cdns_spi_dev_pm_ops, cdns_spi_suspend, +			 cdns_spi_resume); + +static struct of_device_id cdns_spi_of_match[] = { +	{ .compatible = "xlnx,zynq-spi-r1p6" }, +	{ .compatible = "cdns,spi-r1p6" }, +	{ /* end of table */ } +}; +MODULE_DEVICE_TABLE(of, cdns_spi_of_match); + +/* cdns_spi_driver - This structure defines the SPI subsystem platform driver */ +static struct platform_driver cdns_spi_driver = { +	.probe	= cdns_spi_probe, +	.remove	= cdns_spi_remove, +	.driver = { +		.name = CDNS_SPI_NAME, +		.owner = THIS_MODULE, +		.of_match_table = cdns_spi_of_match, +		.pm = &cdns_spi_dev_pm_ops, +	}, +}; + +module_platform_driver(cdns_spi_driver); + +MODULE_AUTHOR("Xilinx, Inc."); +MODULE_DESCRIPTION("Cadence SPI driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 1492f5ee9aaa..a5cba14ac3d2 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -16,6 +16,7 @@  #include <linux/spi/spi.h>  #include <linux/scatterlist.h>  #include <linux/module.h> +#include <linux/of_gpio.h>  #include "spi-dw.h" @@ -70,6 +71,27 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)  	dws->num_cs = 4;  	dws->max_freq = clk_get_rate(dwsmmio->clk); +	if (pdev->dev.of_node) { +		int i; + +		for (i = 0; i < dws->num_cs; i++) { +			int cs_gpio = of_get_named_gpio(pdev->dev.of_node, +					"cs-gpios", i); + +			if (cs_gpio == -EPROBE_DEFER) { +				ret = cs_gpio; +				goto out; +			} + +			if (gpio_is_valid(cs_gpio)) { +				ret = devm_gpio_request(&pdev->dev, cs_gpio, +						dev_name(&pdev->dev)); +				if (ret) +					goto out; +			} +		} +	} +  	ret = dw_spi_add_host(&pdev->dev, dws);  	if (ret)  		goto out; diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 712ac5629cd4..29f33143b795 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -24,6 +24,7 @@  #include <linux/delay.h>  #include <linux/slab.h>  #include <linux/spi/spi.h> +#include <linux/gpio.h>  #include "spi-dw.h" @@ -36,12 +37,6 @@  #define DONE_STATE	((void *)2)  #define ERROR_STATE	((void *)-1) -#define QUEUE_RUNNING	0 -#define QUEUE_STOPPED	1 - -#define MRST_SPI_DEASSERT	0 -#define MRST_SPI_ASSERT		1 -  /* Slave spi_dev related */  struct chip_data {  	u16 cr0; @@ -263,28 +258,22 @@ static int map_dma_buffers(struct dw_spi *dws)  static void giveback(struct dw_spi *dws)  {  	struct spi_transfer *last_transfer; -	unsigned long flags;  	struct spi_message *msg; -	spin_lock_irqsave(&dws->lock, flags);  	msg = dws->cur_msg;  	dws->cur_msg = NULL;  	dws->cur_transfer = NULL;  	dws->prev_chip = dws->cur_chip;  	dws->cur_chip = NULL;  	dws->dma_mapped = 0; -	queue_work(dws->workqueue, &dws->pump_messages); -	spin_unlock_irqrestore(&dws->lock, flags);  	last_transfer = list_last_entry(&msg->transfers, struct spi_transfer,  					transfer_list); -	if (!last_transfer->cs_change && dws->cs_control) -		dws->cs_control(MRST_SPI_DEASSERT); +	if (!last_transfer->cs_change) +		spi_chip_sel(dws, dws->cur_msg->spi, 0); -	msg->state = NULL; -	if (msg->complete) -		msg->complete(msg->context); +	spi_finalize_current_message(dws->master);  }  static void int_error_stop(struct dw_spi *dws, const char *msg) @@ -502,7 +491,7 @@ static void pump_transfers(unsigned long data)  			dw_writew(dws, DW_SPI_CTRL0, cr0);  		spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); -		spi_chip_sel(dws, spi->chip_select); +		spi_chip_sel(dws, spi, 1);  		/* Set the interrupt mask, for poll mode just disable all int */  		spi_mask_intr(dws, 0xff); @@ -529,30 +518,12 @@ early_exit:  	return;  } -static void pump_messages(struct work_struct *work) +static int dw_spi_transfer_one_message(struct spi_master *master, +		struct spi_message *msg)  { -	struct dw_spi *dws = -		container_of(work, struct dw_spi, pump_messages); -	unsigned long flags; - -	/* Lock queue and check for queue work */ -	spin_lock_irqsave(&dws->lock, flags); -	if (list_empty(&dws->queue) || dws->run == QUEUE_STOPPED) { -		dws->busy = 0; -		spin_unlock_irqrestore(&dws->lock, flags); -		return; -	} - -	/* Make sure we are not already running a message */ -	if (dws->cur_msg) { -		spin_unlock_irqrestore(&dws->lock, flags); -		return; -	} - -	/* Extract head of queue */ -	dws->cur_msg = list_entry(dws->queue.next, struct spi_message, queue); -	list_del_init(&dws->cur_msg->queue); +	struct dw_spi *dws = spi_master_get_devdata(master); +	dws->cur_msg = msg;  	/* Initial message state*/  	dws->cur_msg->state = START_STATE;  	dws->cur_transfer = list_entry(dws->cur_msg->transfers.next, @@ -560,46 +531,9 @@ static void pump_messages(struct work_struct *work)  						transfer_list);  	dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi); -	/* Mark as busy and launch transfers */ +	/* Launch transfers */  	tasklet_schedule(&dws->pump_transfers); -	dws->busy = 1; -	spin_unlock_irqrestore(&dws->lock, flags); -} - -/* spi_device use this to queue in their spi_msg */ -static int dw_spi_transfer(struct spi_device *spi, struct spi_message *msg) -{ -	struct dw_spi *dws = spi_master_get_devdata(spi->master); -	unsigned long flags; - -	spin_lock_irqsave(&dws->lock, flags); - -	if (dws->run == QUEUE_STOPPED) { -		spin_unlock_irqrestore(&dws->lock, flags); -		return -ESHUTDOWN; -	} - -	msg->actual_length = 0; -	msg->status = -EINPROGRESS; -	msg->state = START_STATE; - -	list_add_tail(&msg->queue, &dws->queue); - -	if (dws->run == QUEUE_RUNNING && !dws->busy) { - -		if (dws->cur_transfer || dws->cur_msg) -			queue_work(dws->workqueue, -					&dws->pump_messages); -		else { -			/* If no other data transaction in air, just go */ -			spin_unlock_irqrestore(&dws->lock, flags); -			pump_messages(&dws->pump_messages); -			return 0; -		} -	} - -	spin_unlock_irqrestore(&dws->lock, flags);  	return 0;  } @@ -608,6 +542,7 @@ static int dw_spi_setup(struct spi_device *spi)  {  	struct dw_spi_chip *chip_info = NULL;  	struct chip_data *chip; +	int ret;  	/* Only alloc on first setup */  	chip = spi_get_ctldata(spi); @@ -661,81 +596,13 @@ static int dw_spi_setup(struct spi_device *spi)  			| (spi->mode  << SPI_MODE_OFFSET)  			| (chip->tmode << SPI_TMOD_OFFSET); -	return 0; -} - -static int init_queue(struct dw_spi *dws) -{ -	INIT_LIST_HEAD(&dws->queue); -	spin_lock_init(&dws->lock); - -	dws->run = QUEUE_STOPPED; -	dws->busy = 0; - -	tasklet_init(&dws->pump_transfers, -			pump_transfers,	(unsigned long)dws); - -	INIT_WORK(&dws->pump_messages, pump_messages); -	dws->workqueue = create_singlethread_workqueue( -					dev_name(dws->master->dev.parent)); -	if (dws->workqueue == NULL) -		return -EBUSY; - -	return 0; -} - -static int start_queue(struct dw_spi *dws) -{ -	unsigned long flags; - -	spin_lock_irqsave(&dws->lock, flags); - -	if (dws->run == QUEUE_RUNNING || dws->busy) { -		spin_unlock_irqrestore(&dws->lock, flags); -		return -EBUSY; +	if (gpio_is_valid(spi->cs_gpio)) { +		ret = gpio_direction_output(spi->cs_gpio, +				!(spi->mode & SPI_CS_HIGH)); +		if (ret) +			return ret;  	} -	dws->run = QUEUE_RUNNING; -	dws->cur_msg = NULL; -	dws->cur_transfer = NULL; -	dws->cur_chip = NULL; -	dws->prev_chip = NULL; -	spin_unlock_irqrestore(&dws->lock, flags); - -	queue_work(dws->workqueue, &dws->pump_messages); - -	return 0; -} - -static int stop_queue(struct dw_spi *dws) -{ -	unsigned long flags; -	unsigned limit = 50; -	int status = 0; - -	spin_lock_irqsave(&dws->lock, flags); -	dws->run = QUEUE_STOPPED; -	while ((!list_empty(&dws->queue) || dws->busy) && limit--) { -		spin_unlock_irqrestore(&dws->lock, flags); -		msleep(10); -		spin_lock_irqsave(&dws->lock, flags); -	} - -	if (!list_empty(&dws->queue) || dws->busy) -		status = -EBUSY; -	spin_unlock_irqrestore(&dws->lock, flags); - -	return status; -} - -static int destroy_queue(struct dw_spi *dws) -{ -	int status; - -	status = stop_queue(dws); -	if (status != 0) -		return status; -	destroy_workqueue(dws->workqueue);  	return 0;  } @@ -794,7 +661,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)  	master->bus_num = dws->bus_num;  	master->num_chipselect = dws->num_cs;  	master->setup = dw_spi_setup; -	master->transfer = dw_spi_transfer; +	master->transfer_one_message = dw_spi_transfer_one_message;  	master->max_speed_hz = dws->max_freq;  	/* Basic HW init */ @@ -808,33 +675,21 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)  		}  	} -	/* Initial and start queue */ -	ret = init_queue(dws); -	if (ret) { -		dev_err(&master->dev, "problem initializing queue\n"); -		goto err_diable_hw; -	} -	ret = start_queue(dws); -	if (ret) { -		dev_err(&master->dev, "problem starting queue\n"); -		goto err_diable_hw; -	} +	tasklet_init(&dws->pump_transfers, pump_transfers, (unsigned long)dws);  	spi_master_set_devdata(master, dws);  	ret = devm_spi_register_master(dev, master);  	if (ret) {  		dev_err(&master->dev, "problem registering spi master\n"); -		goto err_queue_alloc; +		goto err_dma_exit;  	}  	mrst_spi_debugfs_init(dws);  	return 0; -err_queue_alloc: -	destroy_queue(dws); +err_dma_exit:  	if (dws->dma_ops && dws->dma_ops->dma_exit)  		dws->dma_ops->dma_exit(dws); -err_diable_hw:  	spi_enable_chip(dws, 0);  err_free_master:  	spi_master_put(master); @@ -844,18 +699,10 @@ EXPORT_SYMBOL_GPL(dw_spi_add_host);  void dw_spi_remove_host(struct dw_spi *dws)  { -	int status = 0; -  	if (!dws)  		return;  	mrst_spi_debugfs_remove(dws); -	/* Remove the queue */ -	status = destroy_queue(dws); -	if (status != 0) -		dev_err(&dws->master->dev, -			"dw_spi_remove: workqueue will not complete, message memory not freed\n"); -  	if (dws->dma_ops && dws->dma_ops->dma_exit)  		dws->dma_ops->dma_exit(dws);  	spi_enable_chip(dws, 0); @@ -868,7 +715,7 @@ int dw_spi_suspend_host(struct dw_spi *dws)  {  	int ret = 0; -	ret = stop_queue(dws); +	ret = spi_master_suspend(dws->master);  	if (ret)  		return ret;  	spi_enable_chip(dws, 0); @@ -882,7 +729,7 @@ int dw_spi_resume_host(struct dw_spi *dws)  	int ret;  	spi_hw_init(dws); -	ret = start_queue(dws); +	ret = spi_master_resume(dws->master);  	if (ret)  		dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret);  	return ret; diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h index 587643dae11e..6d2acad34f64 100644 --- a/drivers/spi/spi-dw.h +++ b/drivers/spi/spi-dw.h @@ -3,6 +3,7 @@  #include <linux/io.h>  #include <linux/scatterlist.h> +#include <linux/gpio.h>  /* Register offsets */  #define DW_SPI_CTRL0			0x00 @@ -104,14 +105,6 @@ struct dw_spi {  	u16			bus_num;  	u16			num_cs;		/* supported slave numbers */ -	/* Driver message queue */ -	struct workqueue_struct	*workqueue; -	struct work_struct	pump_messages; -	spinlock_t		lock; -	struct list_head	queue; -	int			busy; -	int			run; -  	/* Message Transfer pump */  	struct tasklet_struct	pump_transfers; @@ -186,15 +179,20 @@ static inline void spi_set_clk(struct dw_spi *dws, u16 div)  	dw_writel(dws, DW_SPI_BAUDR, div);  } -static inline void spi_chip_sel(struct dw_spi *dws, u16 cs) +static inline void spi_chip_sel(struct dw_spi *dws, struct spi_device *spi, +		int active)  { -	if (cs > dws->num_cs) -		return; +	u16 cs = spi->chip_select; +	int gpio_val = active ? (spi->mode & SPI_CS_HIGH) : +		!(spi->mode & SPI_CS_HIGH);  	if (dws->cs_control) -		dws->cs_control(1); +		dws->cs_control(active); +	if (gpio_is_valid(spi->cs_gpio)) +		gpio_set_value(spi->cs_gpio, gpio_val); -	dw_writel(dws, DW_SPI_SER, 1 << cs); +	if (active) +		dw_writel(dws, DW_SPI_SER, 1 << cs);  }  /* Disable IRQ bits */ diff --git a/drivers/spi/spi-falcon.c b/drivers/spi/spi-falcon.c index 09965f069a1c..ba441ad9a007 100644 --- a/drivers/spi/spi-falcon.c +++ b/drivers/spi/spi-falcon.c @@ -11,7 +11,6 @@  #include <linux/platform_device.h>  #include <linux/spi/spi.h>  #include <linux/delay.h> -#include <linux/workqueue.h>  #include <linux/of.h>  #include <linux/of_platform.h> diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index d565eeee3bd8..5021ddf03f60 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -406,7 +406,7 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)  	return IRQ_HANDLED;  } -static struct of_device_id fsl_dspi_dt_ids[] = { +static const struct of_device_id fsl_dspi_dt_ids[] = {  	{ .compatible = "fsl,vf610-dspi", .data = NULL, },  	{ /* sentinel */ }  }; diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index e767f5831b9c..8ebd724e4c59 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -348,7 +348,7 @@ static void fsl_espi_cmd_trans(struct spi_message *m,  	}  	espi_trans->tx_buf = local_buf; -	espi_trans->rx_buf = local_buf + espi_trans->n_tx; +	espi_trans->rx_buf = local_buf;  	fsl_espi_do_trans(m, espi_trans);  	espi_trans->actual_length = espi_trans->len; @@ -397,7 +397,7 @@ static void fsl_espi_rw_trans(struct spi_message *m,  		espi_trans->n_rx = trans_len;  		espi_trans->len = trans_len + n_tx;  		espi_trans->tx_buf = local_buf; -		espi_trans->rx_buf = local_buf + n_tx; +		espi_trans->rx_buf = local_buf;  		fsl_espi_do_trans(m, espi_trans);  		memcpy(rx_buf + pos, espi_trans->rx_buf + n_tx, trans_len); @@ -458,7 +458,7 @@ static int fsl_espi_setup(struct spi_device *spi)  		return -EINVAL;  	if (!cs) { -		cs = kzalloc(sizeof *cs, GFP_KERNEL); +		cs = devm_kzalloc(&spi->dev, sizeof(*cs), GFP_KERNEL);  		if (!cs)  			return -ENOMEM;  		spi->controller_state = cs; @@ -586,8 +586,10 @@ static struct spi_master * fsl_espi_probe(struct device *dev,  	struct spi_master *master;  	struct mpc8xxx_spi *mpc8xxx_spi;  	struct fsl_espi_reg *reg_base; -	u32 regval; -	int i, ret = 0; +	struct device_node *nc; +	const __be32 *prop; +	u32 regval, csmode; +	int i, len, ret = 0;  	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));  	if (!master) { @@ -634,8 +636,32 @@ static struct spi_master * fsl_espi_probe(struct device *dev,  	mpc8xxx_spi_write_reg(®_base->event, 0xffffffff);  	/* Init eSPI CS mode register */ -	for (i = 0; i < pdata->max_chipselect; i++) -		mpc8xxx_spi_write_reg(®_base->csmode[i], CSMODE_INIT_VAL); +	for_each_available_child_of_node(master->dev.of_node, nc) { +		/* get chip select */ +		prop = of_get_property(nc, "reg", &len); +		if (!prop || len < sizeof(*prop)) +			continue; +		i = be32_to_cpup(prop); +		if (i < 0 || i >= pdata->max_chipselect) +			continue; + +		csmode = CSMODE_INIT_VAL; +		/* check if CSBEF is set in device tree */ +		prop = of_get_property(nc, "fsl,csbef", &len); +		if (prop && len >= sizeof(*prop)) { +			csmode &= ~(CSMODE_BEF(0xf)); +			csmode |= CSMODE_BEF(be32_to_cpup(prop)); +		} +		/* check if CSAFT is set in device tree */ +		prop = of_get_property(nc, "fsl,csaft", &len); +		if (prop && len >= sizeof(*prop)) { +			csmode &= ~(CSMODE_AFT(0xf)); +			csmode |= CSMODE_AFT(be32_to_cpup(prop)); +		} +		mpc8xxx_spi_write_reg(®_base->csmode[i], csmode); + +		dev_info(dev, "cs=%d, init_csmode=0x%x\n", i, csmode); +	}  	/* Enable SPI interface */  	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE; diff --git a/drivers/spi/spi-fsl-lib.c b/drivers/spi/spi-fsl-lib.c index e5d45fca3551..95212ea96c8d 100644 --- a/drivers/spi/spi-fsl-lib.c +++ b/drivers/spi/spi-fsl-lib.c @@ -99,11 +99,6 @@ int mpc8xxx_spi_transfer(struct spi_device *spi,  	return 0;  } -void mpc8xxx_spi_cleanup(struct spi_device *spi) -{ -	kfree(spi->controller_state); -} -  const char *mpc8xxx_spi_strmode(unsigned int flags)  {  	if (flags & SPI_QE_CPU_MODE) { @@ -134,7 +129,6 @@ int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,  			| SPI_LSB_FIRST | SPI_LOOP;  	master->transfer = mpc8xxx_spi_transfer; -	master->cleanup = mpc8xxx_spi_cleanup;  	master->dev.of_node = dev->of_node;  	mpc8xxx_spi = spi_master_get_devdata(master); diff --git a/drivers/spi/spi-fsl-lib.h b/drivers/spi/spi-fsl-lib.h index 52db6936778e..2fcbfd01d109 100644 --- a/drivers/spi/spi-fsl-lib.h +++ b/drivers/spi/spi-fsl-lib.h @@ -124,7 +124,6 @@ extern struct mpc8xxx_spi_probe_info *to_of_pinfo(  extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi,  		struct spi_transfer *t, unsigned int len);  extern int mpc8xxx_spi_transfer(struct spi_device *spi, struct spi_message *m); -extern void mpc8xxx_spi_cleanup(struct spi_device *spi);  extern const char *mpc8xxx_spi_strmode(unsigned int flags);  extern int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,  		unsigned int irq); diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index b3e7775034db..98ccd231bf00 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -431,7 +431,7 @@ static int fsl_spi_setup(struct spi_device *spi)  		return -EINVAL;  	if (!cs) { -		cs = kzalloc(sizeof *cs, GFP_KERNEL); +		cs = devm_kzalloc(&spi->dev, sizeof(*cs), GFP_KERNEL);  		if (!cs)  			return -ENOMEM;  		spi->controller_state = cs; diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 09823076df88..9f595535cf27 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -340,7 +340,7 @@ done:  }  #ifdef CONFIG_OF -static struct of_device_id spi_gpio_dt_ids[] = { +static const struct of_device_id spi_gpio_dt_ids[] = {  	{ .compatible = "spi-gpio" },  	{}  }; diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c index 16e30de650b0..73e91d5a43df 100644 --- a/drivers/spi/spi-nuc900.c +++ b/drivers/spi/spi-nuc900.c @@ -10,7 +10,6 @@  #include <linux/module.h>  #include <linux/spinlock.h> -#include <linux/workqueue.h>  #include <linux/interrupt.h>  #include <linux/delay.h>  #include <linux/errno.h> diff --git a/drivers/spi/spi-omap-uwire.c b/drivers/spi/spi-omap-uwire.c index be2a2e108e2f..0f5a0aa3b871 100644 --- a/drivers/spi/spi-omap-uwire.c +++ b/drivers/spi/spi-omap-uwire.c @@ -37,7 +37,6 @@  #include <linux/init.h>  #include <linux/delay.h>  #include <linux/platform_device.h> -#include <linux/workqueue.h>  #include <linux/interrupt.h>  #include <linux/err.h>  #include <linux/clk.h> diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 51d99779682f..66d2ae21e78e 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -1111,10 +1111,8 @@ static int pl022_dma_probe(struct pl022 *pl022)  	}  	pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL); -	if (!pl022->dummypage) { -		dev_dbg(&pl022->adev->dev, "no DMA dummypage!\n"); +	if (!pl022->dummypage)  		goto err_no_dummypage; -	}  	dev_info(&pl022->adev->dev, "setup for DMA on RX %s, TX %s\n",  		 dma_chan_name(pl022->dma_rx_channel), @@ -1809,11 +1807,8 @@ static int pl022_setup(struct spi_device *spi)  	if (chip == NULL) {  		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); -		if (!chip) { -			dev_err(&spi->dev, -				"cannot allocate controller state\n"); +		if (!chip)  			return -ENOMEM; -		}  		dev_dbg(&spi->dev,  			"allocated memory for controller's runtime state\n");  	} @@ -2050,10 +2045,8 @@ pl022_platform_data_dt_get(struct device *dev)  	}  	pd = devm_kzalloc(dev, sizeof(struct pl022_ssp_controller), GFP_KERNEL); -	if (!pd) { -		dev_err(dev, "cannot allocate platform data memory\n"); +	if (!pd)  		return NULL; -	}  	pd->bus_id = -1;  	pd->enable_dma = 1; diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c index 713af4806f26..f6759dc0153b 100644 --- a/drivers/spi/spi-pxa2xx-dma.c +++ b/drivers/spi/spi-pxa2xx-dma.c @@ -29,18 +29,6 @@ static int pxa2xx_spi_map_dma_buffer(struct driver_data *drv_data,  	struct sg_table *sgt;  	void *buf, *pbuf; -	/* -	 * Some DMA controllers have problems transferring buffers that are -	 * not multiple of 4 bytes. So we truncate the transfer so that it -	 * is suitable for such controllers, and handle the trailing bytes -	 * manually after the DMA completes. -	 * -	 * REVISIT: It would be better if this information could be -	 * retrieved directly from the DMA device in a similar way than -	 * ->copy_align etc. is done. -	 */ -	len = ALIGN(drv_data->len, 4); -  	if (dir == DMA_TO_DEVICE) {  		dmadev = drv_data->tx_chan->device->dev;  		sgt = &drv_data->tx_sgt; @@ -144,12 +132,8 @@ static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data,  		if (!error) {  			pxa2xx_spi_unmap_dma_buffers(drv_data); -			/* Handle the last bytes of unaligned transfer */  			drv_data->tx += drv_data->tx_map_len; -			drv_data->write(drv_data); -  			drv_data->rx += drv_data->rx_map_len; -			drv_data->read(drv_data);  			msg->actual_length += drv_data->len;  			msg->state = pxa2xx_spi_next_transfer(drv_data); diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index 3f006d3ed2a8..c1865c92ccb9 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c @@ -8,7 +8,43 @@  #include <linux/module.h>  #include <linux/spi/pxa2xx_spi.h> -static int ce4100_spi_probe(struct pci_dev *dev, +enum { +	PORT_CE4100, +	PORT_BYT, +}; + +struct pxa_spi_info { +	enum pxa_ssp_type type; +	int port_id; +	int num_chipselect; +	int tx_slave_id; +	int tx_chan_id; +	int rx_slave_id; +	int rx_chan_id; +}; + +static struct pxa_spi_info spi_info_configs[] = { +	[PORT_CE4100] = { +		.type = PXA25x_SSP, +		.port_id =  -1, +		.num_chipselect = -1, +		.tx_slave_id = -1, +		.tx_chan_id = -1, +		.rx_slave_id = -1, +		.rx_chan_id = -1, +	}, +	[PORT_BYT] = { +		.type = LPSS_SSP, +		.port_id = 0, +		.num_chipselect = 1, +		.tx_slave_id = 0, +		.tx_chan_id = 0, +		.rx_slave_id = 1, +		.rx_chan_id = 1, +	}, +}; + +static int pxa2xx_spi_pci_probe(struct pci_dev *dev,  		const struct pci_device_id *ent)  {  	struct platform_device_info pi; @@ -16,6 +52,7 @@ static int ce4100_spi_probe(struct pci_dev *dev,  	struct platform_device *pdev;  	struct pxa2xx_spi_master spi_pdata;  	struct ssp_device *ssp; +	struct pxa_spi_info *c;  	ret = pcim_enable_device(dev);  	if (ret) @@ -25,8 +62,16 @@ static int ce4100_spi_probe(struct pci_dev *dev,  	if (ret)  		return ret; +	c = &spi_info_configs[ent->driver_data]; +  	memset(&spi_pdata, 0, sizeof(spi_pdata)); -	spi_pdata.num_chipselect = dev->devfn; +	spi_pdata.num_chipselect = (c->num_chipselect > 0) ? +					c->num_chipselect : dev->devfn; +	spi_pdata.tx_slave_id = c->tx_slave_id; +	spi_pdata.tx_chan_id = c->tx_chan_id; +	spi_pdata.rx_slave_id = c->rx_slave_id; +	spi_pdata.rx_chan_id = c->rx_chan_id; +	spi_pdata.enable_dma = c->rx_slave_id >= 0 && c->tx_slave_id >= 0;  	ssp = &spi_pdata.ssp;  	ssp->phys_base = pci_resource_start(dev, 0); @@ -36,8 +81,8 @@ static int ce4100_spi_probe(struct pci_dev *dev,  		return -EIO;  	}  	ssp->irq = dev->irq; -	ssp->port_id = dev->devfn; -	ssp->type = PXA25x_SSP; +	ssp->port_id = (c->port_id >= 0) ? c->port_id : dev->devfn; +	ssp->type = c->type;  	memset(&pi, 0, sizeof(pi));  	pi.parent = &dev->dev; @@ -55,28 +100,29 @@ static int ce4100_spi_probe(struct pci_dev *dev,  	return 0;  } -static void ce4100_spi_remove(struct pci_dev *dev) +static void pxa2xx_spi_pci_remove(struct pci_dev *dev)  {  	struct platform_device *pdev = pci_get_drvdata(dev);  	platform_device_unregister(pdev);  } -static const struct pci_device_id ce4100_spi_devices[] = { -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) }, +static const struct pci_device_id pxa2xx_spi_pci_devices[] = { +	{ PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 }, +	{ PCI_VDEVICE(INTEL, 0x0f0e), PORT_BYT },  	{ },  }; -MODULE_DEVICE_TABLE(pci, ce4100_spi_devices); +MODULE_DEVICE_TABLE(pci, pxa2xx_spi_pci_devices); -static struct pci_driver ce4100_spi_driver = { -	.name           = "ce4100_spi", -	.id_table       = ce4100_spi_devices, -	.probe          = ce4100_spi_probe, -	.remove         = ce4100_spi_remove, +static struct pci_driver pxa2xx_spi_pci_driver = { +	.name           = "pxa2xx_spi_pci", +	.id_table       = pxa2xx_spi_pci_devices, +	.probe          = pxa2xx_spi_pci_probe, +	.remove         = pxa2xx_spi_pci_remove,  }; -module_pci_driver(ce4100_spi_driver); +module_pci_driver(pxa2xx_spi_pci_driver); -MODULE_DESCRIPTION("CE4100 PCI-SPI glue code for PXA's driver"); +MODULE_DESCRIPTION("CE4100/LPSS PCI-SPI glue code for PXA's driver");  MODULE_LICENSE("GPL v2");  MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>"); diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 41185d0557fa..a98df7eeb42d 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -27,7 +27,6 @@  #include <linux/platform_device.h>  #include <linux/spi/pxa2xx_spi.h>  #include <linux/spi/spi.h> -#include <linux/workqueue.h>  #include <linux/delay.h>  #include <linux/gpio.h>  #include <linux/slab.h> @@ -886,11 +885,8 @@ static int setup(struct spi_device *spi)  	chip = spi_get_ctldata(spi);  	if (!chip) {  		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); -		if (!chip) { -			dev_err(&spi->dev, -				"failed setup: can't allocate chip data\n"); +		if (!chip)  			return -ENOMEM; -		}  		if (drv_data->ssp_type == CE4100_SSP) {  			if (spi->chip_select > 4) { @@ -1037,11 +1033,8 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)  		return NULL;  	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); -	if (!pdata) { -		dev_err(&pdev->dev, -			"failed to allocate memory for platform data\n"); +	if (!pdata)  		return NULL; -	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!res) @@ -1202,6 +1195,11 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)  	tasklet_init(&drv_data->pump_transfers, pump_transfers,  		     (unsigned long)drv_data); +	pm_runtime_set_autosuspend_delay(&pdev->dev, 50); +	pm_runtime_use_autosuspend(&pdev->dev); +	pm_runtime_set_active(&pdev->dev); +	pm_runtime_enable(&pdev->dev); +  	/* Register with the SPI framework */  	platform_set_drvdata(pdev, drv_data);  	status = devm_spi_register_master(&pdev->dev, master); @@ -1210,11 +1208,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)  		goto out_error_clock_enabled;  	} -	pm_runtime_set_autosuspend_delay(&pdev->dev, 50); -	pm_runtime_use_autosuspend(&pdev->dev); -	pm_runtime_set_active(&pdev->dev); -	pm_runtime_enable(&pdev->dev); -  	return status;  out_error_clock_enabled: diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index b032e8885e24..fc1de86d3c8a 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -287,7 +287,7 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)  	writel_relaxed(opflags, controller->base + QUP_OPERATIONAL);  	if (!xfer) { -		dev_err_ratelimited(controller->dev, "unexpected irq %x08 %x08 %x08\n", +		dev_err_ratelimited(controller->dev, "unexpected irq %08x %08x %08x\n",  				    qup_err, spi_err, opflags);  		return IRQ_HANDLED;  	} @@ -366,7 +366,7 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)  	n_words = xfer->len / w_size;  	controller->w_size = w_size; -	if (n_words <= controller->in_fifo_sz) { +	if (n_words <= (controller->in_fifo_sz / sizeof(u32))) {  		mode = QUP_IO_M_MODE_FIFO;  		writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT);  		writel_relaxed(n_words, controller->base + QUP_MX_WRITE_CNT); @@ -734,7 +734,7 @@ static int spi_qup_remove(struct platform_device *pdev)  	int ret;  	ret = pm_runtime_get_sync(&pdev->dev); -	if (ret) +	if (ret < 0)  		return ret;  	ret = spi_qup_set_state(controller, QUP_STATE_RESET); @@ -749,7 +749,7 @@ static int spi_qup_remove(struct platform_device *pdev)  	return 0;  } -static struct of_device_id spi_qup_dt_match[] = { +static const struct of_device_id spi_qup_dt_match[] = {  	{ .compatible = "qcom,spi-qup-v2.1.1", },  	{ .compatible = "qcom,spi-qup-v2.2.1", },  	{ } diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 1fb0ad213324..10112745bb17 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -183,8 +183,6 @@  #define SPBFCR_TXTRG_MASK	0x30	/* Transmit Buffer Data Triggering Number */  #define SPBFCR_RXTRG_MASK	0x07	/* Receive Buffer Data Triggering Number */ -#define DUMMY_DATA		0x00 -  struct rspi_data {  	void __iomem *addr;  	u32 max_speed_hz; @@ -197,11 +195,6 @@ struct rspi_data {  	int rx_irq, tx_irq;  	const struct spi_ops *ops; -	/* for dmaengine */ -	struct dma_chan *chan_tx; -	struct dma_chan *chan_rx; - -	unsigned dma_width_16bit:1;  	unsigned dma_callbacked:1;  	unsigned byte_access:1;  }; @@ -253,6 +246,8 @@ struct spi_ops {  	int (*transfer_one)(struct spi_master *master, struct spi_device *spi,  			    struct spi_transfer *xfer);  	u16 mode_bits; +	u16 flags; +	u16 fifo_size;  };  /* @@ -266,7 +261,8 @@ static int rspi_set_config_register(struct rspi_data *rspi, int access_size)  	rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);  	/* Sets transfer bit rate */ -	spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1; +	spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), +			    2 * rspi->max_speed_hz) - 1;  	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);  	/* Disable dummy transmission, set 16-bit word access, 1 frame */ @@ -302,7 +298,8 @@ static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size)  	rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);  	/* Sets transfer bit rate */ -	spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1; +	spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), +			    2 * rspi->max_speed_hz) - 1;  	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);  	/* Disable dummy transmission, set byte access */ @@ -335,7 +332,7 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size)  	rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);  	/* Sets transfer bit rate */ -	spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz); +	spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), 2 * rspi->max_speed_hz);  	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);  	/* Disable dummy transmission, set byte access */ @@ -403,11 +400,22 @@ static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,  	return 0;  } +static inline int rspi_wait_for_tx_empty(struct rspi_data *rspi) +{ +	return rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE); +} + +static inline int rspi_wait_for_rx_full(struct rspi_data *rspi) +{ +	return rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE); +} +  static int rspi_data_out(struct rspi_data *rspi, u8 data)  { -	if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) { +	int error = rspi_wait_for_tx_empty(rspi); +	if (error < 0) {  		dev_err(&rspi->master->dev, "transmit timeout\n"); -		return -ETIMEDOUT; +		return error;  	}  	rspi_write_data(rspi, data);  	return 0; @@ -415,25 +423,36 @@ static int rspi_data_out(struct rspi_data *rspi, u8 data)  static int rspi_data_in(struct rspi_data *rspi)  { +	int error;  	u8 data; -	if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) { +	error = rspi_wait_for_rx_full(rspi); +	if (error < 0) {  		dev_err(&rspi->master->dev, "receive timeout\n"); -		return -ETIMEDOUT; +		return error;  	}  	data = rspi_read_data(rspi);  	return data;  } -static int rspi_data_out_in(struct rspi_data *rspi, u8 data) +static int rspi_pio_transfer(struct rspi_data *rspi, const u8 *tx, u8 *rx, +			     unsigned int n)  { -	int ret; - -	ret = rspi_data_out(rspi, data); -	if (ret < 0) -		return ret; +	while (n-- > 0) { +		if (tx) { +			int ret = rspi_data_out(rspi, *tx++); +			if (ret < 0) +				return ret; +		} +		if (rx) { +			int ret = rspi_data_in(rspi); +			if (ret < 0) +				return ret; +			*rx++ = ret; +		} +	} -	return rspi_data_in(rspi); +	return 0;  }  static void rspi_dma_complete(void *arg) @@ -444,97 +463,67 @@ static void rspi_dma_complete(void *arg)  	wake_up_interruptible(&rspi->wait);  } -static int rspi_dma_map_sg(struct scatterlist *sg, const void *buf, -			   unsigned len, struct dma_chan *chan, -			   enum dma_transfer_direction dir) -{ -	sg_init_table(sg, 1); -	sg_set_buf(sg, buf, len); -	sg_dma_len(sg) = len; -	return dma_map_sg(chan->device->dev, sg, 1, dir); -} - -static void rspi_dma_unmap_sg(struct scatterlist *sg, struct dma_chan *chan, -			      enum dma_transfer_direction dir) +static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, +			     struct sg_table *rx)  { -	dma_unmap_sg(chan->device->dev, sg, 1, dir); -} - -static void rspi_memory_to_8bit(void *buf, const void *data, unsigned len) -{ -	u16 *dst = buf; -	const u8 *src = data; - -	while (len) { -		*dst++ = (u16)(*src++); -		len--; -	} -} - -static void rspi_memory_from_8bit(void *buf, const void *data, unsigned len) -{ -	u8 *dst = buf; -	const u16 *src = data; - -	while (len) { -		*dst++ = (u8)*src++; -		len--; -	} -} +	struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL; +	u8 irq_mask = 0; +	unsigned int other_irq = 0; +	dma_cookie_t cookie; +	int ret; -static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t) -{ -	struct scatterlist sg; -	const void *buf = NULL; -	struct dma_async_tx_descriptor *desc; -	unsigned int len; -	int ret = 0; - -	if (rspi->dma_width_16bit) { -		void *tmp; -		/* -		 * If DMAC bus width is 16-bit, the driver allocates a dummy -		 * buffer. And, the driver converts original data into the -		 * DMAC data as the following format: -		 *  original data: 1st byte, 2nd byte ... -		 *  DMAC data:     1st byte, dummy, 2nd byte, dummy ... -		 */ -		len = t->len * 2; -		tmp = kmalloc(len, GFP_KERNEL); -		if (!tmp) -			return -ENOMEM; -		rspi_memory_to_8bit(tmp, t->tx_buf, t->len); -		buf = tmp; -	} else { -		len = t->len; -		buf = t->tx_buf; -	} +	if (tx) { +		desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx, +					tx->sgl, tx->nents, DMA_TO_DEVICE, +					DMA_PREP_INTERRUPT | DMA_CTRL_ACK); +		if (!desc_tx) +			return -EIO; -	if (!rspi_dma_map_sg(&sg, buf, len, rspi->chan_tx, DMA_TO_DEVICE)) { -		ret = -EFAULT; -		goto end_nomap; +		irq_mask |= SPCR_SPTIE;  	} -	desc = dmaengine_prep_slave_sg(rspi->chan_tx, &sg, 1, DMA_TO_DEVICE, -				       DMA_PREP_INTERRUPT | DMA_CTRL_ACK); -	if (!desc) { -		ret = -EIO; -		goto end; +	if (rx) { +		desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx, +					rx->sgl, rx->nents, DMA_FROM_DEVICE, +					DMA_PREP_INTERRUPT | DMA_CTRL_ACK); +		if (!desc_rx) +			return -EIO; + +		irq_mask |= SPCR_SPRIE;  	}  	/* -	 * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be +	 * DMAC needs SPxIE, but if SPxIE is set, the IRQ routine will be  	 * called. So, this driver disables the IRQ while DMA transfer.  	 */ -	disable_irq(rspi->tx_irq); +	if (tx) +		disable_irq(other_irq = rspi->tx_irq); +	if (rx && rspi->rx_irq != other_irq) +		disable_irq(rspi->rx_irq); -	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD, RSPI_SPCR); -	rspi_enable_irq(rspi, SPCR_SPTIE); +	rspi_enable_irq(rspi, irq_mask);  	rspi->dma_callbacked = 0; -	desc->callback = rspi_dma_complete; -	desc->callback_param = rspi; -	dmaengine_submit(desc); -	dma_async_issue_pending(rspi->chan_tx); +	if (rx) { +		desc_rx->callback = rspi_dma_complete; +		desc_rx->callback_param = rspi; +		cookie = dmaengine_submit(desc_rx); +		if (dma_submit_error(cookie)) +			return cookie; +		dma_async_issue_pending(rspi->master->dma_rx); +	} +	if (tx) { +		if (rx) { +			/* No callback */ +			desc_tx->callback = NULL; +		} else { +			desc_tx->callback = rspi_dma_complete; +			desc_tx->callback_param = rspi; +		} +		cookie = dmaengine_submit(desc_tx); +		if (dma_submit_error(cookie)) +			return cookie; +		dma_async_issue_pending(rspi->master->dma_tx); +	}  	ret = wait_event_interruptible_timeout(rspi->wait,  					       rspi->dma_callbacked, HZ); @@ -542,15 +531,13 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)  		ret = 0;  	else if (!ret)  		ret = -ETIMEDOUT; -	rspi_disable_irq(rspi, SPCR_SPTIE); -	enable_irq(rspi->tx_irq); +	rspi_disable_irq(rspi, irq_mask); -end: -	rspi_dma_unmap_sg(&sg, rspi->chan_tx, DMA_TO_DEVICE); -end_nomap: -	if (rspi->dma_width_16bit) -		kfree(buf); +	if (tx) +		enable_irq(rspi->tx_irq); +	if (rx && rspi->rx_irq != other_irq) +		enable_irq(rspi->rx_irq);  	return ret;  } @@ -585,157 +572,37 @@ static void qspi_receive_init(const struct rspi_data *rspi)  	rspi_write8(rspi, 0, QSPI_SPBFCR);  } -static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t) +static bool __rspi_can_dma(const struct rspi_data *rspi, +			   const struct spi_transfer *xfer)  { -	struct scatterlist sg, sg_dummy; -	void *dummy = NULL, *rx_buf = NULL; -	struct dma_async_tx_descriptor *desc, *desc_dummy; -	unsigned int len; -	int ret = 0; - -	if (rspi->dma_width_16bit) { -		/* -		 * If DMAC bus width is 16-bit, the driver allocates a dummy -		 * buffer. And, finally the driver converts the DMAC data into -		 * actual data as the following format: -		 *  DMAC data:   1st byte, dummy, 2nd byte, dummy ... -		 *  actual data: 1st byte, 2nd byte ... -		 */ -		len = t->len * 2; -		rx_buf = kmalloc(len, GFP_KERNEL); -		if (!rx_buf) -			return -ENOMEM; -	 } else { -		len = t->len; -		rx_buf = t->rx_buf; -	} - -	/* prepare dummy transfer to generate SPI clocks */ -	dummy = kzalloc(len, GFP_KERNEL); -	if (!dummy) { -		ret = -ENOMEM; -		goto end_nomap; -	} -	if (!rspi_dma_map_sg(&sg_dummy, dummy, len, rspi->chan_tx, -			     DMA_TO_DEVICE)) { -		ret = -EFAULT; -		goto end_nomap; -	} -	desc_dummy = dmaengine_prep_slave_sg(rspi->chan_tx, &sg_dummy, 1, -			DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); -	if (!desc_dummy) { -		ret = -EIO; -		goto end_dummy_mapped; -	} - -	/* prepare receive transfer */ -	if (!rspi_dma_map_sg(&sg, rx_buf, len, rspi->chan_rx, -			     DMA_FROM_DEVICE)) { -		ret = -EFAULT; -		goto end_dummy_mapped; - -	} -	desc = dmaengine_prep_slave_sg(rspi->chan_rx, &sg, 1, DMA_FROM_DEVICE, -				       DMA_PREP_INTERRUPT | DMA_CTRL_ACK); -	if (!desc) { -		ret = -EIO; -		goto end; -	} - -	rspi_receive_init(rspi); - -	/* -	 * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be -	 * called. So, this driver disables the IRQ while DMA transfer. -	 */ -	disable_irq(rspi->tx_irq); -	if (rspi->rx_irq != rspi->tx_irq) -		disable_irq(rspi->rx_irq); - -	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD, RSPI_SPCR); -	rspi_enable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE); -	rspi->dma_callbacked = 0; - -	desc->callback = rspi_dma_complete; -	desc->callback_param = rspi; -	dmaengine_submit(desc); -	dma_async_issue_pending(rspi->chan_rx); - -	desc_dummy->callback = NULL;	/* No callback */ -	dmaengine_submit(desc_dummy); -	dma_async_issue_pending(rspi->chan_tx); - -	ret = wait_event_interruptible_timeout(rspi->wait, -					       rspi->dma_callbacked, HZ); -	if (ret > 0 && rspi->dma_callbacked) -		ret = 0; -	else if (!ret) -		ret = -ETIMEDOUT; -	rspi_disable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE); - -	enable_irq(rspi->tx_irq); -	if (rspi->rx_irq != rspi->tx_irq) -		enable_irq(rspi->rx_irq); - -end: -	rspi_dma_unmap_sg(&sg, rspi->chan_rx, DMA_FROM_DEVICE); -end_dummy_mapped: -	rspi_dma_unmap_sg(&sg_dummy, rspi->chan_tx, DMA_TO_DEVICE); -end_nomap: -	if (rspi->dma_width_16bit) { -		if (!ret) -			rspi_memory_from_8bit(t->rx_buf, rx_buf, t->len); -		kfree(rx_buf); -	} -	kfree(dummy); - -	return ret; +	return xfer->len > rspi->ops->fifo_size;  } -static int rspi_is_dma(const struct rspi_data *rspi, struct spi_transfer *t) +static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi, +			 struct spi_transfer *xfer)  { -	if (t->tx_buf && rspi->chan_tx) -		return 1; -	/* If the module receives data by DMAC, it also needs TX DMAC */ -	if (t->rx_buf && rspi->chan_tx && rspi->chan_rx) -		return 1; +	struct rspi_data *rspi = spi_master_get_devdata(master); -	return 0; +	return __rspi_can_dma(rspi, xfer);  } -static int rspi_transfer_out_in(struct rspi_data *rspi, +static int rspi_common_transfer(struct rspi_data *rspi,  				struct spi_transfer *xfer)  { -	int remain = xfer->len, ret; -	const u8 *tx_buf = xfer->tx_buf; -	u8 *rx_buf = xfer->rx_buf; -	u8 spcr, data; - -	rspi_receive_init(rspi); - -	spcr = rspi_read8(rspi, RSPI_SPCR); -	if (rx_buf) -		spcr &= ~SPCR_TXMD; -	else -		spcr |= SPCR_TXMD; -	rspi_write8(rspi, spcr, RSPI_SPCR); +	int ret; -	while (remain > 0) { -		data = tx_buf ? *tx_buf++ : DUMMY_DATA; -		ret = rspi_data_out(rspi, data); -		if (ret < 0) -			return ret; -		if (rx_buf) { -			ret = rspi_data_in(rspi); -			if (ret < 0) -				return ret; -			*rx_buf++ = ret; -		} -		remain--; +	if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) { +		/* rx_buf can be NULL on RSPI on SH in TX-only Mode */ +		return rspi_dma_transfer(rspi, &xfer->tx_sg, +					 xfer->rx_buf ? &xfer->rx_sg : NULL);  	} +	ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len); +	if (ret < 0) +		return ret; +  	/* Wait for the last transmission */ -	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE); +	rspi_wait_for_tx_empty(rspi);  	return 0;  } @@ -744,46 +611,18 @@ static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,  			     struct spi_transfer *xfer)  {  	struct rspi_data *rspi = spi_master_get_devdata(master); -	int ret; +	u8 spcr; -	if (!rspi_is_dma(rspi, xfer)) -		return rspi_transfer_out_in(rspi, xfer); - -	if (xfer->tx_buf) { -		ret = rspi_send_dma(rspi, xfer); -		if (ret < 0) -			return ret; -	} -	if (xfer->rx_buf) -		return rspi_receive_dma(rspi, xfer); - -	return 0; -} - -static int rspi_rz_transfer_out_in(struct rspi_data *rspi, -				   struct spi_transfer *xfer) -{ -	int remain = xfer->len, ret; -	const u8 *tx_buf = xfer->tx_buf; -	u8 *rx_buf = xfer->rx_buf; -	u8 data; - -	rspi_rz_receive_init(rspi); - -	while (remain > 0) { -		data = tx_buf ? *tx_buf++ : DUMMY_DATA; -		ret = rspi_data_out_in(rspi, data); -		if (ret < 0) -			return ret; -		if (rx_buf) -			*rx_buf++ = ret; -		remain--; +	spcr = rspi_read8(rspi, RSPI_SPCR); +	if (xfer->rx_buf) { +		rspi_receive_init(rspi); +		spcr &= ~SPCR_TXMD; +	} else { +		spcr |= SPCR_TXMD;  	} +	rspi_write8(rspi, spcr, RSPI_SPCR); -	/* Wait for the last transmission */ -	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE); - -	return 0; +	return rspi_common_transfer(rspi, xfer);  }  static int rspi_rz_transfer_one(struct spi_master *master, @@ -791,68 +630,44 @@ static int rspi_rz_transfer_one(struct spi_master *master,  				struct spi_transfer *xfer)  {  	struct rspi_data *rspi = spi_master_get_devdata(master); +	int ret; -	return rspi_rz_transfer_out_in(rspi, xfer); +	rspi_rz_receive_init(rspi); + +	return rspi_common_transfer(rspi, xfer);  }  static int qspi_transfer_out_in(struct rspi_data *rspi,  				struct spi_transfer *xfer)  { -	int remain = xfer->len, ret; -	const u8 *tx_buf = xfer->tx_buf; -	u8 *rx_buf = xfer->rx_buf; -	u8 data; -  	qspi_receive_init(rspi); -	while (remain > 0) { -		data = tx_buf ? *tx_buf++ : DUMMY_DATA; -		ret = rspi_data_out_in(rspi, data); -		if (ret < 0) -			return ret; -		if (rx_buf) -			*rx_buf++ = ret; -		remain--; -	} - -	/* Wait for the last transmission */ -	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE); - -	return 0; +	return rspi_common_transfer(rspi, xfer);  }  static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)  { -	const u8 *buf = xfer->tx_buf; -	unsigned int i;  	int ret; -	for (i = 0; i < xfer->len; i++) { -		ret = rspi_data_out(rspi, *buf++); -		if (ret < 0) -			return ret; -	} +	if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) +		return rspi_dma_transfer(rspi, &xfer->tx_sg, NULL); + +	ret = rspi_pio_transfer(rspi, xfer->tx_buf, NULL, xfer->len); +	if (ret < 0) +		return ret;  	/* Wait for the last transmission */ -	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE); +	rspi_wait_for_tx_empty(rspi);  	return 0;  }  static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)  { -	u8 *buf = xfer->rx_buf; -	unsigned int i; -	int ret; - -	for (i = 0; i < xfer->len; i++) { -		ret = rspi_data_in(rspi); -		if (ret < 0) -			return ret; -		*buf++ = ret; -	} +	if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) +		return rspi_dma_transfer(rspi, NULL, &xfer->rx_sg); -	return 0; +	return rspi_pio_transfer(rspi, NULL, xfer->rx_buf, xfer->len);  }  static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi, @@ -862,10 +677,10 @@ static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi,  	if (spi->mode & SPI_LOOP) {  		return qspi_transfer_out_in(rspi, xfer); -	} else if (xfer->tx_buf && xfer->tx_nbits > SPI_NBITS_SINGLE) { +	} else if (xfer->tx_nbits > SPI_NBITS_SINGLE) {  		/* Quad or Dual SPI Write */  		return qspi_transfer_out(rspi, xfer); -	} else if (xfer->rx_buf && xfer->rx_nbits > SPI_NBITS_SINGLE) { +	} else if (xfer->rx_nbits > SPI_NBITS_SINGLE) {  		/* Quad or Dual SPI Read */  		return qspi_transfer_in(rspi, xfer);  	} else { @@ -1046,65 +861,78 @@ static irqreturn_t rspi_irq_tx(int irq, void *_sr)  	return 0;  } -static int rspi_request_dma(struct rspi_data *rspi, -				      struct platform_device *pdev) +static struct dma_chan *rspi_request_dma_chan(struct device *dev, +					      enum dma_transfer_direction dir, +					      unsigned int id, +					      dma_addr_t port_addr)  { -	const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev); -	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	dma_cap_mask_t mask; +	struct dma_chan *chan;  	struct dma_slave_config cfg;  	int ret; -	if (!res || !rspi_pd) -		return 0;	/* The driver assumes no error. */ +	dma_cap_zero(mask); +	dma_cap_set(DMA_SLAVE, mask); -	rspi->dma_width_16bit = rspi_pd->dma_width_16bit; - -	/* If the module receives data by DMAC, it also needs TX DMAC */ -	if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) { -		dma_cap_zero(mask); -		dma_cap_set(DMA_SLAVE, mask); -		rspi->chan_rx = dma_request_channel(mask, shdma_chan_filter, -						    (void *)rspi_pd->dma_rx_id); -		if (rspi->chan_rx) { -			cfg.slave_id = rspi_pd->dma_rx_id; -			cfg.direction = DMA_DEV_TO_MEM; -			cfg.dst_addr = 0; -			cfg.src_addr = res->start + RSPI_SPDR; -			ret = dmaengine_slave_config(rspi->chan_rx, &cfg); -			if (!ret) -				dev_info(&pdev->dev, "Use DMA when rx.\n"); -			else -				return ret; -		} +	chan = dma_request_channel(mask, shdma_chan_filter, +				   (void *)(unsigned long)id); +	if (!chan) { +		dev_warn(dev, "dma_request_channel failed\n"); +		return NULL;  	} -	if (rspi_pd->dma_tx_id) { -		dma_cap_zero(mask); -		dma_cap_set(DMA_SLAVE, mask); -		rspi->chan_tx = dma_request_channel(mask, shdma_chan_filter, -						    (void *)rspi_pd->dma_tx_id); -		if (rspi->chan_tx) { -			cfg.slave_id = rspi_pd->dma_tx_id; -			cfg.direction = DMA_MEM_TO_DEV; -			cfg.dst_addr = res->start + RSPI_SPDR; -			cfg.src_addr = 0; -			ret = dmaengine_slave_config(rspi->chan_tx, &cfg); -			if (!ret) -				dev_info(&pdev->dev, "Use DMA when tx\n"); -			else -				return ret; -		} + +	memset(&cfg, 0, sizeof(cfg)); +	cfg.slave_id = id; +	cfg.direction = dir; +	if (dir == DMA_MEM_TO_DEV) +		cfg.dst_addr = port_addr; +	else +		cfg.src_addr = port_addr; + +	ret = dmaengine_slave_config(chan, &cfg); +	if (ret) { +		dev_warn(dev, "dmaengine_slave_config failed %d\n", ret); +		dma_release_channel(chan); +		return NULL;  	} +	return chan; +} + +static int rspi_request_dma(struct device *dev, struct spi_master *master, +			    const struct resource *res) +{ +	const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev); + +	if (!rspi_pd || !rspi_pd->dma_rx_id || !rspi_pd->dma_tx_id) +		return 0;	/* The driver assumes no error. */ + +	master->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM, +					       rspi_pd->dma_rx_id, +					       res->start + RSPI_SPDR); +	if (!master->dma_rx) +		return -ENODEV; + +	master->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV, +					       rspi_pd->dma_tx_id, +					       res->start + RSPI_SPDR); +	if (!master->dma_tx) { +		dma_release_channel(master->dma_rx); +		master->dma_rx = NULL; +		return -ENODEV; +	} + +	master->can_dma = rspi_can_dma; +	dev_info(dev, "DMA available");  	return 0;  }  static void rspi_release_dma(struct rspi_data *rspi)  { -	if (rspi->chan_tx) -		dma_release_channel(rspi->chan_tx); -	if (rspi->chan_rx) -		dma_release_channel(rspi->chan_rx); +	if (rspi->master->dma_tx) +		dma_release_channel(rspi->master->dma_tx); +	if (rspi->master->dma_rx) +		dma_release_channel(rspi->master->dma_rx);  }  static int rspi_remove(struct platform_device *pdev) @@ -1118,23 +946,29 @@ 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, +	.set_config_register =	rspi_set_config_register, +	.transfer_one =		rspi_transfer_one, +	.mode_bits =		SPI_CPHA | SPI_CPOL | SPI_LOOP, +	.flags =		SPI_MASTER_MUST_TX, +	.fifo_size =		8,  };  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, +	.set_config_register =	rspi_rz_set_config_register, +	.transfer_one =		rspi_rz_transfer_one, +	.mode_bits =		SPI_CPHA | SPI_CPOL | SPI_LOOP, +	.flags =		SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX, +	.fifo_size =		8,	/* 8 for TX, 32 for RX */  };  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 | -					SPI_RX_DUAL | SPI_RX_QUAD, +	.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 | +				SPI_RX_DUAL | SPI_RX_QUAD, +	.flags =		SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX, +	.fifo_size =		32,  };  #ifdef CONFIG_OF @@ -1254,6 +1088,7 @@ static int rspi_probe(struct platform_device *pdev)  	master->prepare_message = rspi_prepare_message;  	master->unprepare_message = rspi_unprepare_message;  	master->mode_bits = ops->mode_bits; +	master->flags = ops->flags;  	master->dev.of_node = pdev->dev.of_node;  	ret = platform_get_irq_byname(pdev, "rx"); @@ -1291,11 +1126,9 @@ static int rspi_probe(struct platform_device *pdev)  		goto error2;  	} -	ret = rspi_request_dma(rspi, pdev); -	if (ret < 0) { -		dev_err(&pdev->dev, "rspi_request_dma failed.\n"); -		goto error3; -	} +	ret = rspi_request_dma(&pdev->dev, master, res); +	if (ret < 0) +		dev_warn(&pdev->dev, "DMA not available, using PIO\n");  	ret = devm_spi_register_master(&pdev->dev, master);  	if (ret < 0) { diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c index bed23384dfab..e713737d784f 100644 --- a/drivers/spi/spi-s3c24xx.c +++ b/drivers/spi/spi-s3c24xx.c @@ -10,7 +10,6 @@  */  #include <linux/spinlock.h> -#include <linux/workqueue.h>  #include <linux/interrupt.h>  #include <linux/delay.h>  #include <linux/errno.h> @@ -183,11 +182,11 @@ static int s3c24xx_spi_setup(struct spi_device *spi)  	/* allocate settings on the first call */  	if (!cs) { -		cs = kzalloc(sizeof(struct s3c24xx_spi_devstate), GFP_KERNEL); -		if (!cs) { -			dev_err(&spi->dev, "no memory for controller state\n"); +		cs = devm_kzalloc(&spi->dev, +				  sizeof(struct s3c24xx_spi_devstate), +				  GFP_KERNEL); +		if (!cs)  			return -ENOMEM; -		}  		cs->spcon = SPCON_DEFAULT;  		cs->hz = -1; @@ -209,11 +208,6 @@ static int s3c24xx_spi_setup(struct spi_device *spi)  	return 0;  } -static void s3c24xx_spi_cleanup(struct spi_device *spi) -{ -	kfree(spi->controller_state); -} -  static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count)  {  	return hw->tx ? hw->tx[count] : 0; @@ -543,7 +537,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)  	hw->bitbang.txrx_bufs      = s3c24xx_spi_txrx;  	hw->master->setup  = s3c24xx_spi_setup; -	hw->master->cleanup = s3c24xx_spi_cleanup;  	dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang); diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index f19cd97855e8..75a56968b14c 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -19,7 +19,6 @@  #include <linux/init.h>  #include <linux/module.h> -#include <linux/workqueue.h>  #include <linux/interrupt.h>  #include <linux/delay.h>  #include <linux/clk.h> @@ -773,7 +772,6 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(  	cs = kzalloc(sizeof(*cs), GFP_KERNEL);  	if (!cs) { -		dev_err(&spi->dev, "could not allocate memory for controller data\n");  		of_node_put(data_np);  		return ERR_PTR(-ENOMEM);  	} @@ -987,10 +985,8 @@ static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev)  	u32 temp;  	sci = devm_kzalloc(dev, sizeof(*sci), GFP_KERNEL); -	if (!sci) { -		dev_err(dev, "memory allocation for spi_info failed\n"); +	if (!sci)  		return ERR_PTR(-ENOMEM); -	}  	if (of_property_read_u32(dev->of_node, "samsung,spi-src-clk", &temp)) {  		dev_warn(dev, "spi bus clock parent not specified, using clock at index 0 as parent\n"); diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index e850d03e7190..45b09142afe2 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -642,10 +642,8 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev)  	u32 num_cs = 1;  	info = devm_kzalloc(dev, sizeof(struct sh_msiof_spi_info), GFP_KERNEL); -	if (!info) { -		dev_err(dev, "failed to allocate setup data\n"); +	if (!info)  		return NULL; -	}  	/* Parse the MSIOF properties */  	of_property_read_u32(np, "num-cs", &num_cs); diff --git a/drivers/spi/spi-sh-sci.c b/drivers/spi/spi-sh-sci.c index 8b44b71f5024..1f56ef651d1a 100644 --- a/drivers/spi/spi-sh-sci.c +++ b/drivers/spi/spi-sh-sci.c @@ -16,7 +16,6 @@  #include <linux/kernel.h>  #include <linux/delay.h>  #include <linux/spinlock.h> -#include <linux/workqueue.h>  #include <linux/platform_device.h>  #include <linux/spi/spi.h> diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index 67d8909dcf39..95ac276eaafe 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -10,6 +10,7 @@  #include <linux/kernel.h>  #include <linux/slab.h>  #include <linux/clk.h> +#include <linux/completion.h>  #include <linux/interrupt.h>  #include <linux/io.h>  #include <linux/of.h> @@ -85,6 +86,7 @@  #define SIRFSOC_SPI_TX_DONE		BIT(1)  #define SIRFSOC_SPI_RX_OFLOW		BIT(2)  #define SIRFSOC_SPI_TX_UFLOW		BIT(3) +#define SIRFSOC_SPI_RX_IO_DMA		BIT(4)  #define SIRFSOC_SPI_RX_FIFO_FULL	BIT(6)  #define SIRFSOC_SPI_TXFIFO_EMPTY	BIT(7)  #define SIRFSOC_SPI_RXFIFO_THD_REACH	BIT(8) @@ -264,41 +266,34 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)  {  	struct sirfsoc_spi *sspi = dev_id;  	u32 spi_stat = readl(sspi->base + SIRFSOC_SPI_INT_STATUS); - -	writel(spi_stat, sspi->base + SIRFSOC_SPI_INT_STATUS); -  	if (sspi->tx_by_cmd && (spi_stat & SIRFSOC_SPI_FRM_END)) {  		complete(&sspi->tx_done);  		writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); +		writel(SIRFSOC_SPI_INT_MASK_ALL, +				sspi->base + SIRFSOC_SPI_INT_STATUS);  		return IRQ_HANDLED;  	}  	/* Error Conditions */  	if (spi_stat & SIRFSOC_SPI_RX_OFLOW ||  			spi_stat & SIRFSOC_SPI_TX_UFLOW) { +		complete(&sspi->tx_done);  		complete(&sspi->rx_done);  		writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); +		writel(SIRFSOC_SPI_INT_MASK_ALL, +				sspi->base + SIRFSOC_SPI_INT_STATUS); +		return IRQ_HANDLED;  	} +	if (spi_stat & SIRFSOC_SPI_TXFIFO_EMPTY) +		complete(&sspi->tx_done); +	while (!(readl(sspi->base + SIRFSOC_SPI_INT_STATUS) & +		SIRFSOC_SPI_RX_IO_DMA)) +		cpu_relax(); +	complete(&sspi->rx_done); +	writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); +	writel(SIRFSOC_SPI_INT_MASK_ALL, +			sspi->base + SIRFSOC_SPI_INT_STATUS); -	if (spi_stat & (SIRFSOC_SPI_FRM_END -			| SIRFSOC_SPI_RXFIFO_THD_REACH)) -		while (!((readl(sspi->base + SIRFSOC_SPI_RXFIFO_STATUS) -				& SIRFSOC_SPI_FIFO_EMPTY)) && -				sspi->left_rx_word) -			sspi->rx_word(sspi); - -	if (spi_stat & (SIRFSOC_SPI_TXFIFO_EMPTY | -			SIRFSOC_SPI_TXFIFO_THD_REACH)) -		while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS) -				& SIRFSOC_SPI_FIFO_FULL)) && -				sspi->left_tx_word) -			sspi->tx_word(sspi); - -	/* Received all words */ -	if ((sspi->left_rx_word == 0) && (sspi->left_tx_word == 0)) { -		complete(&sspi->rx_done); -		writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); -	}  	return IRQ_HANDLED;  } @@ -309,59 +304,51 @@ static void spi_sirfsoc_dma_fini_callback(void *data)  	complete(dma_complete);  } -static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t) +static int spi_sirfsoc_cmd_transfer(struct spi_device *spi, +	struct spi_transfer *t)  {  	struct sirfsoc_spi *sspi;  	int timeout = t->len * 10; -	sspi = spi_master_get_devdata(spi->master); +	u32 cmd; -	sspi->tx = t->tx_buf ? t->tx_buf : sspi->dummypage; -	sspi->rx = t->rx_buf ? t->rx_buf : sspi->dummypage; -	sspi->left_tx_word = sspi->left_rx_word = t->len / sspi->word_width; -	reinit_completion(&sspi->rx_done); -	reinit_completion(&sspi->tx_done); - -	writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS); - -	/* -	 * fill tx_buf into command register and wait for its completion -	 */ -	if (sspi->tx_by_cmd) { -		u32 cmd; -		memcpy(&cmd, sspi->tx, t->len); - -		if (sspi->word_width == 1 && !(spi->mode & SPI_LSB_FIRST)) -			cmd = cpu_to_be32(cmd) >> -				((SIRFSOC_MAX_CMD_BYTES - t->len) * 8); -		if (sspi->word_width == 2 && t->len == 4 && -				(!(spi->mode & SPI_LSB_FIRST))) -			cmd = ((cmd & 0xffff) << 16) | (cmd >> 16); - -		writel(cmd, sspi->base + SIRFSOC_SPI_CMD); -		writel(SIRFSOC_SPI_FRM_END_INT_EN, -			sspi->base + SIRFSOC_SPI_INT_EN); -		writel(SIRFSOC_SPI_CMD_TX_EN, -			sspi->base + SIRFSOC_SPI_TX_RX_EN); +	sspi = spi_master_get_devdata(spi->master); +	memcpy(&cmd, sspi->tx, t->len); +	if (sspi->word_width == 1 && !(spi->mode & SPI_LSB_FIRST)) +		cmd = cpu_to_be32(cmd) >> +			((SIRFSOC_MAX_CMD_BYTES - t->len) * 8); +	if (sspi->word_width == 2 && t->len == 4 && +			(!(spi->mode & SPI_LSB_FIRST))) +		cmd = ((cmd & 0xffff) << 16) | (cmd >> 16); +	writel(cmd, sspi->base + SIRFSOC_SPI_CMD); +	writel(SIRFSOC_SPI_FRM_END_INT_EN, +		sspi->base + SIRFSOC_SPI_INT_EN); +	writel(SIRFSOC_SPI_CMD_TX_EN, +		sspi->base + SIRFSOC_SPI_TX_RX_EN); +	if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) { +		dev_err(&spi->dev, "cmd transfer timeout\n"); +		return 0; +	} -		if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) { -			dev_err(&spi->dev, "transfer timeout\n"); -			return 0; -		} +	return t->len; +} -		return t->len; -	} +static void spi_sirfsoc_dma_transfer(struct spi_device *spi, +	struct spi_transfer *t) +{ +	struct sirfsoc_spi *sspi; +	struct dma_async_tx_descriptor *rx_desc, *tx_desc; +	int timeout = t->len * 10; -	if (sspi->left_tx_word == 1) { -		writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | -			SIRFSOC_SPI_ENA_AUTO_CLR, -			sspi->base + SIRFSOC_SPI_CTRL); -		writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN); -		writel(0, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN); -	} else if ((sspi->left_tx_word > 1) && (sspi->left_tx_word < -				SIRFSOC_SPI_DAT_FRM_LEN_MAX)) { +	sspi = spi_master_get_devdata(spi->master); +	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP); +	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP); +	writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP); +	writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP); +	writel(0, sspi->base + SIRFSOC_SPI_INT_EN); +	writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS); +	if (sspi->left_tx_word < SIRFSOC_SPI_DAT_FRM_LEN_MAX) {  		writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | -				SIRFSOC_SPI_MUL_DAT_MODE | -				SIRFSOC_SPI_ENA_AUTO_CLR, +			SIRFSOC_SPI_ENA_AUTO_CLR | SIRFSOC_SPI_MUL_DAT_MODE,  			sspi->base + SIRFSOC_SPI_CTRL);  		writel(sspi->left_tx_word - 1,  				sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN); @@ -373,76 +360,122 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)  		writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN);  		writel(0, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN);  	} - -	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP); -	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP); -	writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP); -	writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP); - -	if (IS_DMA_VALID(t)) { -		struct dma_async_tx_descriptor *rx_desc, *tx_desc; - -		sspi->dst_start = dma_map_single(&spi->dev, sspi->rx, t->len, DMA_FROM_DEVICE); -		rx_desc = dmaengine_prep_slave_single(sspi->rx_chan, -			sspi->dst_start, t->len, DMA_DEV_TO_MEM, -			DMA_PREP_INTERRUPT | DMA_CTRL_ACK); -		rx_desc->callback = spi_sirfsoc_dma_fini_callback; -		rx_desc->callback_param = &sspi->rx_done; - -		sspi->src_start = dma_map_single(&spi->dev, (void *)sspi->tx, t->len, DMA_TO_DEVICE); -		tx_desc = dmaengine_prep_slave_single(sspi->tx_chan, -			sspi->src_start, t->len, DMA_MEM_TO_DEV, -			DMA_PREP_INTERRUPT | DMA_CTRL_ACK); -		tx_desc->callback = spi_sirfsoc_dma_fini_callback; -		tx_desc->callback_param = &sspi->tx_done; - -		dmaengine_submit(tx_desc); -		dmaengine_submit(rx_desc); -		dma_async_issue_pending(sspi->tx_chan); -		dma_async_issue_pending(sspi->rx_chan); -	} else { -		/* Send the first word to trigger the whole tx/rx process */ -		sspi->tx_word(sspi); - -		writel(SIRFSOC_SPI_RX_OFLOW_INT_EN | SIRFSOC_SPI_TX_UFLOW_INT_EN | -			SIRFSOC_SPI_RXFIFO_THD_INT_EN | SIRFSOC_SPI_TXFIFO_THD_INT_EN | -			SIRFSOC_SPI_FRM_END_INT_EN | SIRFSOC_SPI_RXFIFO_FULL_INT_EN | -			SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN, sspi->base + SIRFSOC_SPI_INT_EN); -	} - -	writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN, sspi->base + SIRFSOC_SPI_TX_RX_EN); - -	if (!IS_DMA_VALID(t)) { /* for PIO */ -		if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0) -			dev_err(&spi->dev, "transfer timeout\n"); -	} else if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0) { +	sspi->dst_start = dma_map_single(&spi->dev, sspi->rx, t->len, +					(t->tx_buf != t->rx_buf) ? +					DMA_FROM_DEVICE : DMA_BIDIRECTIONAL); +	rx_desc = dmaengine_prep_slave_single(sspi->rx_chan, +		sspi->dst_start, t->len, DMA_DEV_TO_MEM, +		DMA_PREP_INTERRUPT | DMA_CTRL_ACK); +	rx_desc->callback = spi_sirfsoc_dma_fini_callback; +	rx_desc->callback_param = &sspi->rx_done; + +	sspi->src_start = dma_map_single(&spi->dev, (void *)sspi->tx, t->len, +					(t->tx_buf != t->rx_buf) ? +					DMA_TO_DEVICE : DMA_BIDIRECTIONAL); +	tx_desc = dmaengine_prep_slave_single(sspi->tx_chan, +		sspi->src_start, t->len, DMA_MEM_TO_DEV, +		DMA_PREP_INTERRUPT | DMA_CTRL_ACK); +	tx_desc->callback = spi_sirfsoc_dma_fini_callback; +	tx_desc->callback_param = &sspi->tx_done; + +	dmaengine_submit(tx_desc); +	dmaengine_submit(rx_desc); +	dma_async_issue_pending(sspi->tx_chan); +	dma_async_issue_pending(sspi->rx_chan); +	writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN, +			sspi->base + SIRFSOC_SPI_TX_RX_EN); +	if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0) {  		dev_err(&spi->dev, "transfer timeout\n");  		dmaengine_terminate_all(sspi->rx_chan);  	} else  		sspi->left_rx_word = 0; -  	/*  	 * we only wait tx-done event if transferring by DMA. for PIO,  	 * we get rx data by writing tx data, so if rx is done, tx has  	 * done earlier  	 */ -	if (IS_DMA_VALID(t)) { -		if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) { -			dev_err(&spi->dev, "transfer timeout\n"); -			dmaengine_terminate_all(sspi->tx_chan); -		} -	} - -	if (IS_DMA_VALID(t)) { -		dma_unmap_single(&spi->dev, sspi->src_start, t->len, DMA_TO_DEVICE); -		dma_unmap_single(&spi->dev, sspi->dst_start, t->len, DMA_FROM_DEVICE); +	if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) { +		dev_err(&spi->dev, "transfer timeout\n"); +		dmaengine_terminate_all(sspi->tx_chan);  	} - +	dma_unmap_single(&spi->dev, sspi->src_start, t->len, DMA_TO_DEVICE); +	dma_unmap_single(&spi->dev, sspi->dst_start, t->len, DMA_FROM_DEVICE);  	/* TX, RX FIFO stop */  	writel(0, sspi->base + SIRFSOC_SPI_RXFIFO_OP);  	writel(0, sspi->base + SIRFSOC_SPI_TXFIFO_OP); -	writel(0, sspi->base + SIRFSOC_SPI_TX_RX_EN); -	writel(0, sspi->base + SIRFSOC_SPI_INT_EN); +	if (sspi->left_tx_word >= SIRFSOC_SPI_DAT_FRM_LEN_MAX) +		writel(0, sspi->base + SIRFSOC_SPI_TX_RX_EN); +} + +static void spi_sirfsoc_pio_transfer(struct spi_device *spi, +		struct spi_transfer *t) +{ +	struct sirfsoc_spi *sspi; +	int timeout = t->len * 10; + +	sspi = spi_master_get_devdata(spi->master); +	do { +		writel(SIRFSOC_SPI_FIFO_RESET, +			sspi->base + SIRFSOC_SPI_RXFIFO_OP); +		writel(SIRFSOC_SPI_FIFO_RESET, +			sspi->base + SIRFSOC_SPI_TXFIFO_OP); +		writel(SIRFSOC_SPI_FIFO_START, +			sspi->base + SIRFSOC_SPI_RXFIFO_OP); +		writel(SIRFSOC_SPI_FIFO_START, +			sspi->base + SIRFSOC_SPI_TXFIFO_OP); +		writel(0, sspi->base + SIRFSOC_SPI_INT_EN); +		writel(SIRFSOC_SPI_INT_MASK_ALL, +			sspi->base + SIRFSOC_SPI_INT_STATUS); +		writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | +			SIRFSOC_SPI_MUL_DAT_MODE | SIRFSOC_SPI_ENA_AUTO_CLR, +			sspi->base + SIRFSOC_SPI_CTRL); +		writel(min(sspi->left_tx_word, (u32)(256 / sspi->word_width)) +				- 1, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN); +		writel(min(sspi->left_rx_word, (u32)(256 / sspi->word_width)) +				- 1, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN); +		while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS) +			& SIRFSOC_SPI_FIFO_FULL)) && sspi->left_tx_word) +			sspi->tx_word(sspi); +		writel(SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN | +			SIRFSOC_SPI_TX_UFLOW_INT_EN | +			SIRFSOC_SPI_RX_OFLOW_INT_EN, +			sspi->base + SIRFSOC_SPI_INT_EN); +		writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN, +			sspi->base + SIRFSOC_SPI_TX_RX_EN); +		if (!wait_for_completion_timeout(&sspi->tx_done, timeout) || +			!wait_for_completion_timeout(&sspi->rx_done, timeout)) { +			dev_err(&spi->dev, "transfer timeout\n"); +			break; +		} +		while (!((readl(sspi->base + SIRFSOC_SPI_RXFIFO_STATUS) +			& SIRFSOC_SPI_FIFO_EMPTY)) && sspi->left_rx_word) +			sspi->rx_word(sspi); +		writel(0, sspi->base + SIRFSOC_SPI_RXFIFO_OP); +		writel(0, sspi->base + SIRFSOC_SPI_TXFIFO_OP); +	} while (sspi->left_tx_word != 0 || sspi->left_rx_word != 0); +} + +static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t) +{ +	struct sirfsoc_spi *sspi; +	sspi = spi_master_get_devdata(spi->master); + +	sspi->tx = t->tx_buf ? t->tx_buf : sspi->dummypage; +	sspi->rx = t->rx_buf ? t->rx_buf : sspi->dummypage; +	sspi->left_tx_word = sspi->left_rx_word = t->len / sspi->word_width; +	reinit_completion(&sspi->rx_done); +	reinit_completion(&sspi->tx_done); +	/* +	 * in the transfer, if transfer data using command register with rx_buf +	 * null, just fill command data into command register and wait for its +	 * completion. +	 */ +	if (sspi->tx_by_cmd) +		spi_sirfsoc_cmd_transfer(spi, t); +	else if (IS_DMA_VALID(t)) +		spi_sirfsoc_dma_transfer(spi, t); +	else +		spi_sirfsoc_pio_transfer(spi, t);  	return t->len - sspi->left_rx_word * sspi->word_width;  } @@ -512,7 +545,8 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)  		break;  	case 12:  	case 16: -		regval |= (bits_per_word ==  12) ? SIRFSOC_SPI_TRAN_DAT_FORMAT_12 : +		regval |= (bits_per_word ==  12) ? +			SIRFSOC_SPI_TRAN_DAT_FORMAT_12 :  			SIRFSOC_SPI_TRAN_DAT_FORMAT_16;  		sspi->rx_word = spi_sirfsoc_rx_word_u16;  		sspi->tx_word = spi_sirfsoc_tx_word_u16; @@ -540,8 +574,8 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)  		regval |= SIRFSOC_SPI_CLK_IDLE_STAT;  	/* -	 * Data should be driven at least 1/2 cycle before the fetch edge to make -	 * sure that data gets stable at the fetch edge. +	 * Data should be driven at least 1/2 cycle before the fetch edge +	 * to make sure that data gets stable at the fetch edge.  	 */  	if (((spi->mode & SPI_CPOL) && (spi->mode & SPI_CPHA)) ||  	    (!(spi->mode & SPI_CPOL) && !(spi->mode & SPI_CPHA))) @@ -578,11 +612,14 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)  	if (IS_DMA_VALID(t)) {  		/* Enable DMA mode for RX, TX */  		writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL); -		writel(SIRFSOC_SPI_RX_DMA_FLUSH, sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL); +		writel(SIRFSOC_SPI_RX_DMA_FLUSH, +			sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL);  	} else {  		/* Enable IO mode for RX, TX */ -		writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL); -		writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL); +		writel(SIRFSOC_SPI_IO_MODE_SEL, +			sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL); +		writel(SIRFSOC_SPI_IO_MODE_SEL, +			sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL);  	}  	return 0; @@ -612,7 +649,8 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)  		goto err_cs;  	} -	master = spi_alloc_master(&pdev->dev, sizeof(*sspi) + sizeof(int) * num_cs); +	master = spi_alloc_master(&pdev->dev, +			sizeof(*sspi) + sizeof(int) * num_cs);  	if (!master) {  		dev_err(&pdev->dev, "Unable to allocate SPI master\n");  		return -ENOMEM; @@ -808,8 +846,7 @@ static struct platform_driver spi_sirfsoc_driver = {  	.remove = spi_sirfsoc_remove,  };  module_platform_driver(spi_sirfsoc_driver); -  MODULE_DESCRIPTION("SiRF SoC SPI master driver"); -MODULE_AUTHOR("Zhiwu Song <Zhiwu.Song@csr.com>, " -		"Barry Song <Baohua.Song@csr.com>"); +MODULE_AUTHOR("Zhiwu Song <Zhiwu.Song@csr.com>"); +MODULE_AUTHOR("Barry Song <Baohua.Song@csr.com>");  MODULE_LICENSE("GPL v2"); diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c index d266a8702067..85204c93f3d3 100644 --- a/drivers/spi/spi-sun4i.c +++ b/drivers/spi/spi-sun4i.c @@ -19,7 +19,6 @@  #include <linux/module.h>  #include <linux/platform_device.h>  #include <linux/pm_runtime.h> -#include <linux/workqueue.h>  #include <linux/spi/spi.h> diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index b3e3498a7e6f..bd24093f4038 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c @@ -20,7 +20,6 @@  #include <linux/platform_device.h>  #include <linux/pm_runtime.h>  #include <linux/reset.h> -#include <linux/workqueue.h>  #include <linux/spi/spi.h> diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 400649595505..e4a85ada861d 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -1012,7 +1012,7 @@ static irqreturn_t tegra_spi_isr(int irq, void *context_data)  	return IRQ_WAKE_THREAD;  } -static struct of_device_id tegra_spi_of_match[] = { +static const struct of_device_id tegra_spi_of_match[] = {  	{ .compatible = "nvidia,tegra114-spi", },  	{}  }; diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index 47869ea636e1..3548ce25c08f 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -419,7 +419,7 @@ static irqreturn_t tegra_sflash_isr(int irq, void *context_data)  	return handle_cpu_based_xfer(tsd);  } -static struct of_device_id tegra_sflash_of_match[] = { +static const struct of_device_id tegra_sflash_of_match[] = {  	{ .compatible = "nvidia,tegra20-sflash", },  	{}  }; diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index e3c1b93e45d1..0b9e32e9f493 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -1001,7 +1001,7 @@ static const struct tegra_slink_chip_data tegra20_spi_cdata = {  	.cs_hold_time = false,  }; -static struct of_device_id tegra_slink_of_match[] = { +static const struct of_device_id tegra_slink_of_match[] = {  	{ .compatible = "nvidia,tegra30-slink", .data = &tegra30_spi_cdata, },  	{ .compatible = "nvidia,tegra20-slink", .data = &tegra20_spi_cdata, },  	{} diff --git a/drivers/spi/spi-tle62x0.c b/drivers/spi/spi-tle62x0.c index 2d4010d80824..daf5aa1c24c3 100644 --- a/drivers/spi/spi-tle62x0.c +++ b/drivers/spi/spi-tle62x0.c @@ -253,10 +253,8 @@ static int tle62x0_probe(struct spi_device *spi)  	}  	st = kzalloc(sizeof(struct tle62x0_state), GFP_KERNEL); -	if (st == NULL) { -		dev_err(&spi->dev, "no memory for device state\n"); +	if (st == NULL)  		return -ENOMEM; -	}  	st->us = spi;  	st->nr_gpio = pdata->gpio_count; diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index f406b30af961..f05abf89c067 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1578,14 +1578,11 @@ static int pch_spi_probe(struct pci_dev *pdev, const struct pci_device_id *id)  	struct pch_pd_dev_save *pd_dev_save;  	pd_dev_save = kzalloc(sizeof(struct pch_pd_dev_save), GFP_KERNEL); -	if (!pd_dev_save) { -		dev_err(&pdev->dev, "%s Can't allocate pd_dev_sav\n", __func__); +	if (!pd_dev_save)  		return -ENOMEM; -	}  	board_dat = kzalloc(sizeof(struct pch_spi_board_data), GFP_KERNEL);  	if (!board_dat) { -		dev_err(&pdev->dev, "%s Can't allocate board_dat\n", __func__);  		retval = -ENOMEM;  		goto err_no_mem;  	} diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 4eb9bf02996c..d4f9670b51bc 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -580,6 +580,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable)  		spi->master->set_cs(spi, !enable);  } +#ifdef CONFIG_HAS_DMA  static int spi_map_buf(struct spi_master *master, struct device *dev,  		       struct sg_table *sgt, void *buf, size_t len,  		       enum dma_data_direction dir) @@ -637,55 +638,12 @@ static void spi_unmap_buf(struct spi_master *master, struct device *dev,  	}  } -static int spi_map_msg(struct spi_master *master, struct spi_message *msg) +static int __spi_map_msg(struct spi_master *master, struct spi_message *msg)  {  	struct device *tx_dev, *rx_dev;  	struct spi_transfer *xfer; -	void *tmp; -	unsigned int max_tx, max_rx;  	int ret; -	if (master->flags & (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX)) { -		max_tx = 0; -		max_rx = 0; - -		list_for_each_entry(xfer, &msg->transfers, transfer_list) { -			if ((master->flags & SPI_MASTER_MUST_TX) && -			    !xfer->tx_buf) -				max_tx = max(xfer->len, max_tx); -			if ((master->flags & SPI_MASTER_MUST_RX) && -			    !xfer->rx_buf) -				max_rx = max(xfer->len, max_rx); -		} - -		if (max_tx) { -			tmp = krealloc(master->dummy_tx, max_tx, -				       GFP_KERNEL | GFP_DMA); -			if (!tmp) -				return -ENOMEM; -			master->dummy_tx = tmp; -			memset(tmp, 0, max_tx); -		} - -		if (max_rx) { -			tmp = krealloc(master->dummy_rx, max_rx, -				       GFP_KERNEL | GFP_DMA); -			if (!tmp) -				return -ENOMEM; -			master->dummy_rx = tmp; -		} - -		if (max_tx || max_rx) { -			list_for_each_entry(xfer, &msg->transfers, -					    transfer_list) { -				if (!xfer->tx_buf) -					xfer->tx_buf = master->dummy_tx; -				if (!xfer->rx_buf) -					xfer->rx_buf = master->dummy_rx; -			} -		} -	} -  	if (!master->can_dma)  		return 0; @@ -742,6 +700,69 @@ static int spi_unmap_msg(struct spi_master *master, struct spi_message *msg)  	return 0;  } +#else /* !CONFIG_HAS_DMA */ +static inline int __spi_map_msg(struct spi_master *master, +				struct spi_message *msg) +{ +	return 0; +} + +static inline int spi_unmap_msg(struct spi_master *master, +				struct spi_message *msg) +{ +	return 0; +} +#endif /* !CONFIG_HAS_DMA */ + +static int spi_map_msg(struct spi_master *master, struct spi_message *msg) +{ +	struct spi_transfer *xfer; +	void *tmp; +	unsigned int max_tx, max_rx; + +	if (master->flags & (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX)) { +		max_tx = 0; +		max_rx = 0; + +		list_for_each_entry(xfer, &msg->transfers, transfer_list) { +			if ((master->flags & SPI_MASTER_MUST_TX) && +			    !xfer->tx_buf) +				max_tx = max(xfer->len, max_tx); +			if ((master->flags & SPI_MASTER_MUST_RX) && +			    !xfer->rx_buf) +				max_rx = max(xfer->len, max_rx); +		} + +		if (max_tx) { +			tmp = krealloc(master->dummy_tx, max_tx, +				       GFP_KERNEL | GFP_DMA); +			if (!tmp) +				return -ENOMEM; +			master->dummy_tx = tmp; +			memset(tmp, 0, max_tx); +		} + +		if (max_rx) { +			tmp = krealloc(master->dummy_rx, max_rx, +				       GFP_KERNEL | GFP_DMA); +			if (!tmp) +				return -ENOMEM; +			master->dummy_rx = tmp; +		} + +		if (max_tx || max_rx) { +			list_for_each_entry(xfer, &msg->transfers, +					    transfer_list) { +				if (!xfer->tx_buf) +					xfer->tx_buf = master->dummy_tx; +				if (!xfer->rx_buf) +					xfer->rx_buf = master->dummy_rx; +			} +		} +	} + +	return __spi_map_msg(master, msg); +}  /*   * spi_transfer_one_message - Default implementation of transfer_one_message() @@ -775,7 +796,7 @@ static int spi_transfer_one_message(struct spi_master *master,  		if (ret > 0) {  			ret = 0;  			ms = xfer->len * 8 * 1000 / xfer->speed_hz; -			ms += 10; /* some tolerance */ +			ms += ms + 100; /* some tolerance */  			ms = wait_for_completion_timeout(&master->xfer_completion,  							 msecs_to_jiffies(ms)); @@ -1151,7 +1172,6 @@ static int spi_master_initialize_queue(struct spi_master *master)  {  	int ret; -	master->queued = true;  	master->transfer = spi_queued_transfer;  	if (!master->transfer_one_message)  		master->transfer_one_message = spi_transfer_one_message; @@ -1162,6 +1182,7 @@ static int spi_master_initialize_queue(struct spi_master *master)  		dev_err(&master->dev, "problem initializing queue\n");  		goto err_init_queue;  	} +	master->queued = true;  	ret = spi_start_queue(master);  	if (ret) {  		dev_err(&master->dev, "problem starting queue\n"); @@ -1171,8 +1192,8 @@ static int spi_master_initialize_queue(struct spi_master *master)  	return 0;  err_start_queue: -err_init_queue:  	spi_destroy_queue(master); +err_init_queue:  	return ret;  } @@ -1234,6 +1255,8 @@ static void of_register_spi_devices(struct spi_master *master)  			spi->mode |= SPI_CS_HIGH;  		if (of_find_property(nc, "spi-3wire", NULL))  			spi->mode |= SPI_3WIRE; +		if (of_find_property(nc, "spi-lsb-first", NULL)) +			spi->mode |= SPI_LSB_FIRST;  		/* Device DUAL/QUAD mode */  		if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) { @@ -1247,11 +1270,10 @@ static void of_register_spi_devices(struct spi_master *master)  				spi->mode |= SPI_TX_QUAD;  				break;  			default: -				dev_err(&master->dev, -					"spi-tx-bus-width %d not supported\n", -					value); -				spi_dev_put(spi); -				continue; +				dev_warn(&master->dev, +					 "spi-tx-bus-width %d not supported\n", +					 value); +				break;  			}  		} @@ -1266,11 +1288,10 @@ static void of_register_spi_devices(struct spi_master *master)  				spi->mode |= SPI_RX_QUAD;  				break;  			default: -				dev_err(&master->dev, -					"spi-rx-bus-width %d not supported\n", -					value); -				spi_dev_put(spi); -				continue; +				dev_warn(&master->dev, +					 "spi-rx-bus-width %d not supported\n", +					 value); +				break;  			}  		} @@ -1756,7 +1777,7 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master);   */  int spi_setup(struct spi_device *spi)  { -	unsigned	bad_bits; +	unsigned	bad_bits, ugly_bits;  	int		status = 0;  	/* check mode to prevent that DUAL and QUAD set at the same time @@ -1776,6 +1797,15 @@ int spi_setup(struct spi_device *spi)  	 * that aren't supported with their current master  	 */  	bad_bits = spi->mode & ~spi->master->mode_bits; +	ugly_bits = bad_bits & +		    (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD); +	if (ugly_bits) { +		dev_warn(&spi->dev, +			 "setup: ignoring unsupported mode bits %x\n", +			 ugly_bits); +		spi->mode &= ~ugly_bits; +		bad_bits &= ~ugly_bits; +	}  	if (bad_bits) {  		dev_err(&spi->dev, "setup: unsupported mode bits %x\n",  			bad_bits); | 
