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>
This commit is contained in:
parent
f3732edf46
commit
37a4b75d4c
|
@ -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();
|
||||
|
|
|
@ -254,6 +254,7 @@
|
|||
/*
|
||||
* Misc Settings
|
||||
*/
|
||||
#define CONFIG_BFIN_SPI_GPIO_CS /* Only matters if BFIN_SPI is enabled */
|
||||
#define CONFIG_LZMA
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue