[ar71xx] refresh 3.2 patches
[openwrt.git] / target / linux / ar71xx / patches-3.2 / 207-spi-ath79-make-chipselect-logic-more-flexible.patch
1 From b875f877d06acb852342636db4c3d1e6c9fe01ba Mon Sep 17 00:00:00 2001
2 From: Gabor Juhos <juhosg@openwrt.org>
3 Date: Wed, 11 Jan 2012 22:25:11 +0100
4 Subject: [PATCH 7/7] spi/ath79: make chipselect logic more flexible
5
6 Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
7 ---
8  .../include/asm/mach-ath79/ath79_spi_platform.h    |    8 ++-
9  drivers/spi/spi-ath79.c                            |   65 +++++++++++--------
10  2 files changed, 45 insertions(+), 28 deletions(-)
11
12 --- a/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
13 +++ b/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
14 @@ -16,8 +16,14 @@ struct ath79_spi_platform_data {
15         unsigned        num_chipselect;
16  };
17  
18 +enum ath79_spi_cs_type {
19 +       ATH79_SPI_CS_TYPE_INTERNAL,
20 +       ATH79_SPI_CS_TYPE_GPIO,
21 +};
22 +
23  struct ath79_spi_controller_data {
24 -       unsigned        gpio;
25 +       enum ath79_spi_cs_type cs_type;
26 +       unsigned cs_line;
27  };
28  
29  #endif /* _ATH79_SPI_PLATFORM_H */
30 --- a/drivers/spi/spi-ath79.c
31 +++ b/drivers/spi/spi-ath79.c
32 @@ -30,6 +30,8 @@
33  
34  #define DRV_NAME       "ath79-spi"
35  
36 +#define ATH79_SPI_CS_LINE_MAX  2
37 +
38  struct ath79_spi {
39         struct spi_bitbang      bitbang;
40         u32                     ioc_base;
41 @@ -62,6 +64,7 @@ static void ath79_spi_chipselect(struct
42  {
43         struct ath79_spi *sp = ath79_spidev_to_sp(spi);
44         int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active;
45 +       struct ath79_spi_controller_data *cdata = spi->controller_data;
46  
47         if (is_active) {
48                 /* set initial clock polarity */
49 @@ -73,20 +76,21 @@ static void ath79_spi_chipselect(struct
50                 ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
51         }
52  
53 -       if (spi->chip_select) {
54 -               struct ath79_spi_controller_data *cdata = spi->controller_data;
55 -
56 -               /* SPI is normally active-low */
57 -               gpio_set_value(cdata->gpio, cs_high);
58 -       } else {
59 +       switch (cdata->cs_type) {
60 +       case ATH79_SPI_CS_TYPE_INTERNAL:
61                 if (cs_high)
62 -                       sp->ioc_base |= AR71XX_SPI_IOC_CS0;
63 +                       sp->ioc_base |= AR71XX_SPI_IOC_CS(cdata->cs_line);
64                 else
65 -                       sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
66 +                       sp->ioc_base &= ~AR71XX_SPI_IOC_CS(cdata->cs_line);
67  
68                 ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
69 -       }
70 +               break;
71  
72 +       case ATH79_SPI_CS_TYPE_GPIO:
73 +               /* SPI is normally active-low */
74 +               gpio_set_value(cdata->cs_line, cs_high);
75 +               break;
76 +       }
77  }
78  
79  static void ath79_spi_enable(struct ath79_spi *sp)
80 @@ -114,24 +118,30 @@ static int ath79_spi_setup_cs(struct spi
81  {
82         struct ath79_spi *sp = ath79_spidev_to_sp(spi);
83         struct ath79_spi_controller_data *cdata;
84 +       unsigned long flags;
85         int status;
86  
87         cdata = spi->controller_data;
88 -       if (spi->chip_select && !cdata)
89 +       if (!cdata)
90                 return -EINVAL;
91  
92         status = 0;
93 -       if (spi->chip_select) {
94 -               unsigned long flags;
95 +       switch (cdata->cs_type) {
96 +       case ATH79_SPI_CS_TYPE_INTERNAL:
97 +               if (cdata->cs_line > ATH79_SPI_CS_LINE_MAX)
98 +                       status = -EINVAL;
99 +               break;
100  
101 +       case ATH79_SPI_CS_TYPE_GPIO:
102                 flags = GPIOF_DIR_OUT;
103                 if (spi->mode & SPI_CS_HIGH)
104                         flags |= GPIOF_INIT_HIGH;
105                 else
106                         flags |= GPIOF_INIT_LOW;
107  
108 -               status = gpio_request_one(cdata->gpio, flags,
109 +               status = gpio_request_one(cdata->cs_line, flags,
110                                           dev_name(&spi->dev));
111 +               break;
112         }
113  
114         return status;
115 @@ -139,11 +149,15 @@ static int ath79_spi_setup_cs(struct spi
116  
117  static void ath79_spi_cleanup_cs(struct spi_device *spi)
118  {
119 -       struct ath79_spi *sp = ath79_spidev_to_sp(spi);
120 +       struct ath79_spi_controller_data *cdata = spi->controller_data;
121  
122 -       if (spi->chip_select) {
123 -               struct ath79_spi_controller_data *cdata = spi->controller_data;
124 -               gpio_free(cdata->gpio);
125 +       switch (cdata->cs_type) {
126 +       case ATH79_SPI_CS_TYPE_INTERNAL:
127 +               /* nothing to do */
128 +               break;
129 +       case ATH79_SPI_CS_TYPE_GPIO:
130 +               gpio_free(cdata->cs_line);
131 +               break;
132         }
133  }
134  
135 @@ -209,6 +223,10 @@ static __devinit int ath79_spi_probe(str
136         struct resource *r;
137         int ret;
138  
139 +       pdata = pdev->dev.platform_data;
140 +       if (!pdata)
141 +               return -EINVAL;
142 +
143         master = spi_alloc_master(&pdev->dev, sizeof(*sp));
144         if (master == NULL) {
145                 dev_err(&pdev->dev, "failed to allocate spi master\n");
146 @@ -218,17 +236,10 @@ static __devinit int ath79_spi_probe(str
147         sp = spi_master_get_devdata(master);
148         platform_set_drvdata(pdev, sp);
149  
150 -       pdata = pdev->dev.platform_data;
151 -
152         master->setup = ath79_spi_setup;
153         master->cleanup = ath79_spi_cleanup;
154 -       if (pdata) {
155 -               master->bus_num = pdata->bus_num;
156 -               master->num_chipselect = pdata->num_chipselect;
157 -       } else {
158 -               master->bus_num = -1;
159 -               master->num_chipselect = 1;
160 -       }
161 +       master->bus_num = pdata->bus_num;
162 +       master->num_chipselect = pdata->num_chipselect;
163  
164         sp->bitbang.master = spi_master_get(master);
165         sp->bitbang.chipselect = ath79_spi_chipselect;