diff options
| author | Mike Frysinger <vapier@gentoo.org> | 2010-06-02 06:13:50 -0400 | 
|---|---|---|
| committer | Mike Frysinger <vapier@gentoo.org> | 2010-07-13 17:50:50 -0400 | 
| commit | 37a4b75d4c30a37bda2bf8ae0c192446425b6f28 (patch) | |
| tree | d67af8a85b804120976044b6204ccd523dd433e1 /drivers/spi/bfin_spi.c | |
| parent | f3732edf46e8587972041e89aa15336b49f72ffe (diff) | |
| download | olio-uboot-2014.01-37a4b75d4c30a37bda2bf8ae0c192446425b6f28.tar.xz olio-uboot-2014.01-37a4b75d4c30a37bda2bf8ae0c192446425b6f28.zip | |
Blackfin: bfin_spi: support gpios as chip selects
Rather than only support the pins dedicated as chip selects, utilize the
gpio framework to support any gpio pin.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'drivers/spi/bfin_spi.c')
| -rw-r--r-- | drivers/spi/bfin_spi.c | 83 | 
1 files changed, 56 insertions, 27 deletions
| diff --git a/drivers/spi/bfin_spi.c b/drivers/spi/bfin_spi.c index 4e008a79b..e0ad0298d 100644 --- a/drivers/spi/bfin_spi.c +++ b/drivers/spi/bfin_spi.c @@ -13,6 +13,7 @@  #include <spi.h>  #include <asm/blackfin.h> +#include <asm/gpio.h>  #include <asm/portmux.h>  #include <asm/mach-common/bits/spi.h> @@ -34,48 +35,68 @@ MAKE_SPI_FUNC(SPI_BAUD, 0x14)  #define to_bfin_spi_slave(s) container_of(s, struct bfin_spi_slave, slave) -__attribute__((weak)) +#define MAX_CTRL_CS 7 + +#define gpio_cs(cs) ((cs) - MAX_CTRL_CS) +#ifdef CONFIG_BFIN_SPI_GPIO_CS +# define is_gpio_cs(cs) ((cs) > MAX_CTRL_CS) +#else +# define is_gpio_cs(cs) 0 +#endif +  int spi_cs_is_valid(unsigned int bus, unsigned int cs)  { -#if defined(__ADSPBF538__) || defined(__ADSPBF539__) -	/* The SPI1/SPI2 buses are weird ... only 1 CS */ -	if (bus > 0 && cs != 1) -		return 0; -#endif -	return (cs >= 1 && cs <= 7); +	if (is_gpio_cs(cs)) +		return gpio_is_valid(gpio_cs(cs)); +	else +		return (cs >= 1 && cs <= MAX_CTRL_CS);  } -__attribute__((weak))  void spi_cs_activate(struct spi_slave *slave)  {  	struct bfin_spi_slave *bss = to_bfin_spi_slave(slave); -	write_SPI_FLG(bss, -		(read_SPI_FLG(bss) & -		~((!bss->flg << 8) << slave->cs)) | -		(1 << slave->cs)); + +	if (is_gpio_cs(slave->cs)) { +		unsigned int cs = gpio_cs(slave->cs); +		gpio_set_value(cs, bss->flg); +		debug("%s: SPI_CS_GPIO:%x\n", __func__, gpio_get_value(cs)); +	} else { +		write_SPI_FLG(bss, +			(read_SPI_FLG(bss) & +			~((!bss->flg << 8) << slave->cs)) | +			(1 << slave->cs)); +		debug("%s: SPI_FLG:%x\n", __func__, read_SPI_FLG(bss)); +	} +  	SSYNC(); -	debug("%s: SPI_FLG:%x\n", __func__, read_SPI_FLG(bss));  } -__attribute__((weak))  void spi_cs_deactivate(struct spi_slave *slave)  {  	struct bfin_spi_slave *bss = to_bfin_spi_slave(slave); -	u16 flg; -	/* make sure we force the cs to deassert rather than let the -	 * pin float back up.  otherwise, exact timings may not be -	 * met some of the time leading to random behavior (ugh). -	 */ -	flg = read_SPI_FLG(bss) | ((!bss->flg << 8) << slave->cs); -	write_SPI_FLG(bss, flg); -	SSYNC(); -	debug("%s: SPI_FLG:%x\n", __func__, read_SPI_FLG(bss)); +	if (is_gpio_cs(slave->cs)) { +		unsigned int cs = gpio_cs(slave->cs); +		gpio_set_value(cs, !bss->flg); +		debug("%s: SPI_CS_GPIO:%x\n", __func__, gpio_get_value(cs)); +	} else { +		u16 flg; + +		/* make sure we force the cs to deassert rather than let the +		 * pin float back up.  otherwise, exact timings may not be +		 * met some of the time leading to random behavior (ugh). +		 */ +		flg = read_SPI_FLG(bss) | ((!bss->flg << 8) << slave->cs); +		write_SPI_FLG(bss, flg); +		SSYNC(); +		debug("%s: SPI_FLG:%x\n", __func__, read_SPI_FLG(bss)); + +		flg &= ~(1 << slave->cs); +		write_SPI_FLG(bss, flg); +		debug("%s: SPI_FLG:%x\n", __func__, read_SPI_FLG(bss)); +	} -	flg &= ~(1 << slave->cs); -	write_SPI_FLG(bss, flg);  	SSYNC(); -	debug("%s: SPI_FLG:%x\n", __func__, read_SPI_FLG(bss));  }  void spi_init() @@ -188,7 +209,13 @@ int spi_claim_bus(struct spi_slave *slave)  	debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs); -	pins[slave->bus][0] = cs_pins[slave->bus][slave->cs - 1]; +	if (is_gpio_cs(slave->cs)) { +		unsigned int cs = gpio_cs(slave->cs); +		gpio_request(cs, "bfin-spi"); +		gpio_direction_output(cs, !bss->flg); +		pins[slave->bus][0] = P_DONTCARE; +	} else +		pins[slave->bus][0] = cs_pins[slave->bus][slave->cs - 1];  	peripheral_request_list(pins[slave->bus], "bfin-spi");  	write_SPI_CTL(bss, bss->ctl); @@ -205,6 +232,8 @@ void spi_release_bus(struct spi_slave *slave)  	debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);  	peripheral_free_list(pins[slave->bus]); +	if (is_gpio_cs(slave->cs)) +		gpio_free(gpio_cs(slave->cs));  	write_SPI_CTL(bss, 0);  	SSYNC(); |