Blackfin: bfin_spi: support gpios as chip selects
authorMike Frysinger <vapier@gentoo.org>
Wed, 2 Jun 2010 10:13:50 +0000 (06:13 -0400)
committerMike Frysinger <vapier@gentoo.org>
Tue, 13 Jul 2010 21:50:50 +0000 (17:50 -0400)
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>
drivers/spi/bfin_spi.c
include/configs/bfin_adi_common.h

index 4e008a79b6ad79e57242b407a9ce0e3d1bbd6a18..e0ad0298d8abd1b6574e9b5f59ed18bff895ea22 100644 (file)
@@ -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));
 
-       flg &= ~(1 << slave->cs);
-       write_SPI_FLG(bss, flg);
+       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));
+       }
+
        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();
index fa1e69486fd0c6ea8e7f24473bb8c6f9377075ec..82daeb1000646e9e6c4a14a4a83e8088f1c3e2c6 100644 (file)
 /*
  * Misc Settings
  */
+#define CONFIG_BFIN_SPI_GPIO_CS /* Only matters if BFIN_SPI is enabled */
 #define CONFIG_LZMA
 
 #endif