ar71xx: add linux 3.10
[openwrt.git] / target / linux / ar71xx / patches-3.10 / 206-spi-ath79-make-chipselect-logic-more-flexible.patch
diff --git a/target/linux/ar71xx/patches-3.10/206-spi-ath79-make-chipselect-logic-more-flexible.patch b/target/linux/ar71xx/patches-3.10/206-spi-ath79-make-chipselect-logic-more-flexible.patch
new file mode 100644 (file)
index 0000000..993fcdd
--- /dev/null
@@ -0,0 +1,310 @@
+From 7008284716403237f6bc7d7590b3ed073555bd56 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Wed, 11 Jan 2012 22:25:11 +0100
+Subject: [PATCH 34/34] spi/ath79: make chipselect logic more flexible
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ arch/mips/ath79/mach-ap121.c                       |    6 ++
+ arch/mips/ath79/mach-ap136.c                       |    6 ++
+ arch/mips/ath79/mach-ap81.c                        |    6 ++
+ arch/mips/ath79/mach-db120.c                       |    6 ++
+ arch/mips/ath79/mach-pb44.c                        |    6 ++
+ arch/mips/ath79/mach-ubnt-xm.c                     |    6 ++
+ .../include/asm/mach-ath79/ath79_spi_platform.h    |    8 ++-
+ drivers/spi/spi-ath79.c                            |   67 +++++++++++++-------
+ 8 files changed, 88 insertions(+), 23 deletions(-)
+
+--- a/arch/mips/ath79/mach-ap121.c
++++ b/arch/mips/ath79/mach-ap121.c
+@@ -58,12 +58,18 @@ static struct gpio_keys_button ap121_gpi
+       }
+ };
++static struct ath79_spi_controller_data ap121_spi0_data = {
++      .cs_type = ATH79_SPI_CS_TYPE_INTERNAL,
++      .cs_line = 0,
++};
++
+ static struct spi_board_info ap121_spi_info[] = {
+       {
+               .bus_num        = 0,
+               .chip_select    = 0,
+               .max_speed_hz   = 25000000,
+               .modalias       = "mx25l1606e",
++              .controller_data = &ap121_spi0_data,
+       }
+ };
+--- a/arch/mips/ath79/mach-ap136.c
++++ b/arch/mips/ath79/mach-ap136.c
+@@ -98,12 +98,18 @@ static struct gpio_keys_button ap136_gpi
+       },
+ };
++static struct ath79_spi_controller_data ap136_spi0_data = {
++      .cs_type = ATH79_SPI_CS_TYPE_INTERNAL,
++      .cs_line = 0,
++};
++
+ static struct spi_board_info ap136_spi_info[] = {
+       {
+               .bus_num        = 0,
+               .chip_select    = 0,
+               .max_speed_hz   = 25000000,
+               .modalias       = "mx25l6405d",
++              .controller_data = &ap136_spi0_data,
+       }
+ };
+--- a/arch/mips/ath79/mach-ap81.c
++++ b/arch/mips/ath79/mach-ap81.c
+@@ -67,12 +67,18 @@ static struct gpio_keys_button ap81_gpio
+       }
+ };
++static struct ath79_spi_controller_data ap81_spi0_data = {
++      .cs_type = ATH79_SPI_CS_TYPE_INTERNAL,
++      .cs_line = 0,
++};
++
+ static struct spi_board_info ap81_spi_info[] = {
+       {
+               .bus_num        = 0,
+               .chip_select    = 0,
+               .max_speed_hz   = 25000000,
+               .modalias       = "m25p64",
++              .controller_data = &ap81_spi0_data,
+       }
+ };
+--- a/arch/mips/ath79/mach-db120.c
++++ b/arch/mips/ath79/mach-db120.c
+@@ -76,12 +76,18 @@ static struct gpio_keys_button db120_gpi
+       },
+ };
++static struct ath79_spi_controller_data db120_spi0_data = {
++      .cs_type = ATH79_SPI_CS_TYPE_INTERNAL,
++      .cs_line = 0,
++};
++
+ static struct spi_board_info db120_spi_info[] = {
+       {
+               .bus_num        = 0,
+               .chip_select    = 0,
+               .max_speed_hz   = 25000000,
+               .modalias       = "s25sl064a",
++              .controller_data = &db120_spi0_data,
+       }
+ };
+--- a/arch/mips/ath79/mach-pb44.c
++++ b/arch/mips/ath79/mach-pb44.c
+@@ -87,12 +87,18 @@ static struct gpio_keys_button pb44_gpio
+       }
+ };
++static struct ath79_spi_controller_data pb44_spi0_data = {
++      .cs_type = ATH79_SPI_CS_TYPE_INTERNAL,
++      .cs_line = 0,
++};
++
+ static struct spi_board_info pb44_spi_info[] = {
+       {
+               .bus_num        = 0,
+               .chip_select    = 0,
+               .max_speed_hz   = 25000000,
+               .modalias       = "m25p64",
++              .controller_data = &pb44_spi0_data,
+       },
+ };
+--- a/arch/mips/ath79/mach-ubnt-xm.c
++++ b/arch/mips/ath79/mach-ubnt-xm.c
+@@ -65,12 +65,18 @@ static struct gpio_keys_button ubnt_xm_g
+       }
+ };
++static struct ath79_spi_controller_data ubnt_xm_spi0_data = {
++      .cs_type = ATH79_SPI_CS_TYPE_INTERNAL,
++      .cs_line = 0,
++};
++
+ static struct spi_board_info ubnt_xm_spi_info[] = {
+       {
+               .bus_num        = 0,
+               .chip_select    = 0,
+               .max_speed_hz   = 25000000,
+               .modalias       = "mx25l6405d",
++              .controller_data = &ubnt_xm_spi0_data,
+       }
+ };
+--- a/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
++++ b/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
+@@ -16,8 +16,14 @@ struct ath79_spi_platform_data {
+       unsigned        num_chipselect;
+ };
++enum ath79_spi_cs_type {
++      ATH79_SPI_CS_TYPE_INTERNAL,
++      ATH79_SPI_CS_TYPE_GPIO,
++};
++
+ struct ath79_spi_controller_data {
+-      unsigned        gpio;
++      enum ath79_spi_cs_type cs_type;
++      unsigned cs_line;
+ };
+ #endif /* _ATH79_SPI_PLATFORM_H */
+--- a/drivers/spi/spi-ath79.c
++++ b/drivers/spi/spi-ath79.c
+@@ -35,6 +35,8 @@
+ #define ATH79_SPI_RRW_DELAY_FACTOR    12000
+ #define MHZ                           (1000 * 1000)
++#define ATH79_SPI_CS_LINE_MAX         2
++
+ struct ath79_spi {
+       struct spi_bitbang      bitbang;
+       u32                     ioc_base;
+@@ -69,6 +71,7 @@ static void ath79_spi_chipselect(struct 
+ {
+       struct ath79_spi *sp = ath79_spidev_to_sp(spi);
+       int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active;
++      struct ath79_spi_controller_data *cdata = spi->controller_data;
+       if (is_active) {
+               /* set initial clock polarity */
+@@ -80,20 +83,24 @@ static void ath79_spi_chipselect(struct 
+               ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
+       }
+-      if (spi->chip_select) {
+-              struct ath79_spi_controller_data *cdata = spi->controller_data;
+-
+-              /* SPI is normally active-low */
+-              gpio_set_value(cdata->gpio, cs_high);
+-      } else {
++      switch (cdata->cs_type) {
++      case ATH79_SPI_CS_TYPE_INTERNAL:
+               if (cs_high)
+-                      sp->ioc_base |= AR71XX_SPI_IOC_CS0;
++                      sp->ioc_base |= AR71XX_SPI_IOC_CS(cdata->cs_line);
+               else
+-                      sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
++                      sp->ioc_base &= ~AR71XX_SPI_IOC_CS(cdata->cs_line);
+               ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
+-      }
++              break;
++      case ATH79_SPI_CS_TYPE_GPIO:
++              /* SPI is normally active-low */
++              if (gpio_cansleep(cdata->cs_line))
++                      gpio_set_value_cansleep(cdata->cs_line, cs_high);
++              else
++                      gpio_set_value(cdata->cs_line, cs_high);
++              break;
++      }
+ }
+ static void ath79_spi_enable(struct ath79_spi *sp)
+@@ -120,24 +127,30 @@ static void ath79_spi_disable(struct ath
+ static int ath79_spi_setup_cs(struct spi_device *spi)
+ {
+       struct ath79_spi_controller_data *cdata;
++      unsigned long flags;
+       int status;
+       cdata = spi->controller_data;
+-      if (spi->chip_select && !cdata)
++      if (!cdata)
+               return -EINVAL;
+       status = 0;
+-      if (spi->chip_select) {
+-              unsigned long flags;
++      switch (cdata->cs_type) {
++      case ATH79_SPI_CS_TYPE_INTERNAL:
++              if (cdata->cs_line > ATH79_SPI_CS_LINE_MAX)
++                      status = -EINVAL;
++              break;
++      case ATH79_SPI_CS_TYPE_GPIO:
+               flags = GPIOF_DIR_OUT;
+               if (spi->mode & SPI_CS_HIGH)
+                       flags |= GPIOF_INIT_HIGH;
+               else
+                       flags |= GPIOF_INIT_LOW;
+-              status = gpio_request_one(cdata->gpio, flags,
++              status = gpio_request_one(cdata->cs_line, flags,
+                                         dev_name(&spi->dev));
++              break;
+       }
+       return status;
+@@ -145,9 +158,19 @@ static int ath79_spi_setup_cs(struct spi
+ static void ath79_spi_cleanup_cs(struct spi_device *spi)
+ {
+-      if (spi->chip_select) {
+-              struct ath79_spi_controller_data *cdata = spi->controller_data;
+-              gpio_free(cdata->gpio);
++      struct ath79_spi_controller_data *cdata;
++
++      cdata = spi->controller_data;
++      if (!cdata)
++              return;
++
++      switch (cdata->cs_type) {
++      case ATH79_SPI_CS_TYPE_INTERNAL:
++              /* nothing to do */
++              break;
++      case ATH79_SPI_CS_TYPE_GPIO:
++              gpio_free(cdata->cs_line);
++              break;
+       }
+ }
+@@ -155,6 +178,9 @@ static int ath79_spi_setup(struct spi_de
+ {
+       int status = 0;
++      if (spi->controller_data == NULL)
++              return -EINVAL;
++
+       if (spi->bits_per_word > 32)
+               return -EINVAL;
+@@ -215,6 +241,10 @@ static int ath79_spi_probe(struct platfo
+       unsigned long rate;
+       int ret;
++      pdata = pdev->dev.platform_data;
++      if (!pdata)
++              return -EINVAL;
++
+       master = spi_alloc_master(&pdev->dev, sizeof(*sp));
+       if (master == NULL) {
+               dev_err(&pdev->dev, "failed to allocate spi master\n");
+@@ -224,14 +254,10 @@ static int ath79_spi_probe(struct platfo
+       sp = spi_master_get_devdata(master);
+       platform_set_drvdata(pdev, sp);
+-      pdata = pdev->dev.platform_data;
+-
+       master->setup = ath79_spi_setup;
+       master->cleanup = ath79_spi_cleanup;
+-      if (pdata) {
+-              master->bus_num = pdata->bus_num;
+-              master->num_chipselect = pdata->num_chipselect;
+-      }
++      master->bus_num = pdata->bus_num;
++      master->num_chipselect = pdata->num_chipselect;
+       sp->bitbang.master = spi_master_get(master);
+       sp->bitbang.chipselect = ath79_spi_chipselect;