diff options
Diffstat (limited to 'drivers/spi/pl022_spi.c')
| -rw-r--r-- | drivers/spi/pl022_spi.c | 51 | 
1 files changed, 44 insertions, 7 deletions
| diff --git a/drivers/spi/pl022_spi.c b/drivers/spi/pl022_spi.c index 828eab3d342..fc7388b379d 100644 --- a/drivers/spi/pl022_spi.c +++ b/drivers/spi/pl022_spi.c @@ -12,9 +12,11 @@  #include <clk.h>  #include <common.h>  #include <dm.h> -#include <dm/platform_data/spi_pl022.h> +#include <dm/device_compat.h> +#include <fdtdec.h>  #include <linux/io.h>  #include <asm/global_data.h> +#include <asm/gpio.h>  #include <spi.h>  #define SSP_CR0		0x000 @@ -66,6 +68,15 @@  #define SSP_SR_MASK_RFF		(0x1 << 3) /* Receive FIFO full */  #define SSP_SR_MASK_BSY		(0x1 << 4) /* Busy Flag */ +struct pl022_spi_pdata { +	fdt_addr_t addr; +	fdt_size_t size; +	unsigned int freq; +#if CONFIG_IS_ENABLED(DM_GPIO) +	struct gpio_desc cs_gpio; +#endif +}; +  struct pl022_spi_slave {  	void *base;  	unsigned int freq; @@ -107,7 +118,7 @@ static int pl022_spi_probe(struct udevice *bus)  	return 0;  } -static void flush(struct pl022_spi_slave *ps) +static void pl022_spi_flush(struct pl022_spi_slave *ps)  {  	do {  		while (readw(ps->base + SSP_SR) & SSP_SR_MASK_RNE) @@ -126,7 +137,7 @@ static int pl022_spi_claim_bus(struct udevice *dev)  	reg |= SSP_CR1_MASK_SSE;  	writew(reg, ps->base + SSP_CR1); -	flush(ps); +	pl022_spi_flush(ps);  	return 0;  } @@ -137,7 +148,7 @@ static int pl022_spi_release_bus(struct udevice *dev)  	struct pl022_spi_slave *ps = dev_get_priv(bus);  	u16 reg; -	flush(ps); +	pl022_spi_flush(ps);  	/* Disable the SPI hardware */  	reg = readw(ps->base + SSP_CR1); @@ -147,6 +158,17 @@ static int pl022_spi_release_bus(struct udevice *dev)  	return 0;  } +static void pl022_spi_set_cs(struct udevice *dev, bool on) +{ +#if CONFIG_IS_ENABLED(DM_GPIO) +	struct udevice *bus = dev->parent; +	struct pl022_spi_pdata *plat = dev_get_plat(bus); + +	if (dm_gpio_is_valid(&plat->cs_gpio)) +		dm_gpio_set_value(&plat->cs_gpio, on ? 1 : 0); +#endif +} +  static int pl022_spi_xfer(struct udevice *dev, unsigned int bitlen,  			  const void *dout, void *din, unsigned long flags)  { @@ -159,7 +181,7 @@ static int pl022_spi_xfer(struct udevice *dev, unsigned int bitlen,  	if (bitlen == 0)  		/* Finish any previously submitted transfers */ -		return 0; +		goto done;  	/*  	 * TODO: The controller can do non-multiple-of-8 bit @@ -172,9 +194,13 @@ static int pl022_spi_xfer(struct udevice *dev, unsigned int bitlen,  	if (bitlen % 8) {  		/* Errors always terminate an ongoing transfer */  		flags |= SPI_XFER_END; -		return -1; +		ret = -1; +		goto done;  	} +	if (flags & SPI_XFER_BEGIN) +		pl022_spi_set_cs(dev, true); +  	len = bitlen / 8;  	while (len_tx < len) { @@ -201,6 +227,10 @@ static int pl022_spi_xfer(struct udevice *dev, unsigned int bitlen,  		}  	} +done: +	if (flags & SPI_XFER_END) +		pl022_spi_set_cs(dev, false); +  	return ret;  } @@ -303,11 +333,18 @@ static int pl022_spi_of_to_plat(struct udevice *bus)  	plat->freq = clk_get_rate(&clkdev); +#if CONFIG_IS_ENABLED(DM_GPIO) +	ret = gpio_request_by_name(bus, "cs-gpios", 0, &plat->cs_gpio, +				   GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); +	if (ret < 0 && ret != -ENOENT) +		return ret; +#endif +  	return 0;  }  static const struct udevice_id pl022_spi_ids[] = { -	{ .compatible = "arm,pl022-spi" }, +	{ .compatible = "arm,pl022" },  	{ }  };  #endif | 
