ar71xx: make AR8327 LEDs working on the DB120 board
[openwrt.git] / target / linux / ar71xx / patches-3.3 / 206-spi-ath79-make-chipselect-logic-more-flexible.patch
1 From 16535fe56591ff85acd6776f53ff515799b037ba 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 47/47] spi/ath79: make chipselect logic more flexible
5
6 Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
7 ---
8  arch/mips/ath79/mach-ap121.c                       |    6 ++
9  arch/mips/ath79/mach-ap81.c                        |    6 ++
10  arch/mips/ath79/mach-db120.c                       |    6 ++
11  arch/mips/ath79/mach-pb44.c                        |    6 ++
12  arch/mips/ath79/mach-ubnt-xm.c                     |    6 ++
13  .../include/asm/mach-ath79/ath79_spi_platform.h    |    8 ++-
14  drivers/spi/spi-ath79.c                            |   70 +++++++++++++-------
15  7 files changed, 82 insertions(+), 26 deletions(-)
16
17 --- a/arch/mips/ath79/mach-ap121.c
18 +++ b/arch/mips/ath79/mach-ap121.c
19 @@ -58,12 +58,18 @@ static struct gpio_keys_button ap121_gpi
20         }
21  };
22  
23 +static struct ath79_spi_controller_data ap121_spi0_data = {
24 +       .cs_type = ATH79_SPI_CS_TYPE_INTERNAL,
25 +       .cs_line = 0,
26 +};
27 +
28  static struct spi_board_info ap121_spi_info[] = {
29         {
30                 .bus_num        = 0,
31                 .chip_select    = 0,
32                 .max_speed_hz   = 25000000,
33                 .modalias       = "mx25l1606e",
34 +               .controller_data = &ap121_spi0_data,
35         }
36  };
37  
38 --- a/arch/mips/ath79/mach-ap81.c
39 +++ b/arch/mips/ath79/mach-ap81.c
40 @@ -67,12 +67,18 @@ static struct gpio_keys_button ap81_gpio
41         }
42  };
43  
44 +static struct ath79_spi_controller_data ap81_spi0_data = {
45 +       .cs_type = ATH79_SPI_CS_TYPE_INTERNAL,
46 +       .cs_line = 0,
47 +};
48 +
49  static struct spi_board_info ap81_spi_info[] = {
50         {
51                 .bus_num        = 0,
52                 .chip_select    = 0,
53                 .max_speed_hz   = 25000000,
54                 .modalias       = "m25p64",
55 +               .controller_data = &ap81_spi0_data,
56         }
57  };
58  
59 --- a/arch/mips/ath79/mach-db120.c
60 +++ b/arch/mips/ath79/mach-db120.c
61 @@ -76,12 +76,18 @@ static struct gpio_keys_button db120_gpi
62         },
63  };
64  
65 +static struct ath79_spi_controller_data db120_spi0_data = {
66 +       .cs_type = ATH79_SPI_CS_TYPE_INTERNAL,
67 +       .cs_line = 0,
68 +};
69 +
70  static struct spi_board_info db120_spi_info[] = {
71         {
72                 .bus_num        = 0,
73                 .chip_select    = 0,
74                 .max_speed_hz   = 25000000,
75                 .modalias       = "s25sl064a",
76 +               .controller_data = &db120_spi0_data,
77         }
78  };
79  
80 --- a/arch/mips/ath79/mach-pb44.c
81 +++ b/arch/mips/ath79/mach-pb44.c
82 @@ -87,12 +87,18 @@ static struct gpio_keys_button pb44_gpio
83         }
84  };
85  
86 +static struct ath79_spi_controller_data pb44_spi0_data = {
87 +       .cs_type = ATH79_SPI_CS_TYPE_INTERNAL,
88 +       .cs_line = 0,
89 +};
90 +
91  static struct spi_board_info pb44_spi_info[] = {
92         {
93                 .bus_num        = 0,
94                 .chip_select    = 0,
95                 .max_speed_hz   = 25000000,
96                 .modalias       = "m25p64",
97 +               .controller_data = &pb44_spi0_data,
98         },
99  };
100  
101 --- a/arch/mips/ath79/mach-ubnt-xm.c
102 +++ b/arch/mips/ath79/mach-ubnt-xm.c
103 @@ -65,12 +65,18 @@ static struct gpio_keys_button ubnt_xm_g
104         }
105  };
106  
107 +static struct ath79_spi_controller_data ubnt_xm_spi0_data = {
108 +       .cs_type = ATH79_SPI_CS_TYPE_INTERNAL,
109 +       .cs_line = 0,
110 +};
111 +
112  static struct spi_board_info ubnt_xm_spi_info[] = {
113         {
114                 .bus_num        = 0,
115                 .chip_select    = 0,
116                 .max_speed_hz   = 25000000,
117                 .modalias       = "mx25l6405d",
118 +               .controller_data = &ubnt_xm_spi0_data,
119         }
120  };
121  
122 --- a/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
123 +++ b/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
124 @@ -16,8 +16,14 @@ struct ath79_spi_platform_data {
125         unsigned        num_chipselect;
126  };
127  
128 +enum ath79_spi_cs_type {
129 +       ATH79_SPI_CS_TYPE_INTERNAL,
130 +       ATH79_SPI_CS_TYPE_GPIO,
131 +};
132 +
133  struct ath79_spi_controller_data {
134 -       unsigned        gpio;
135 +       enum ath79_spi_cs_type cs_type;
136 +       unsigned cs_line;
137  };
138  
139  #endif /* _ATH79_SPI_PLATFORM_H */
140 --- a/drivers/spi/spi-ath79.c
141 +++ b/drivers/spi/spi-ath79.c
142 @@ -35,6 +35,8 @@
143  #define ATH79_SPI_RRW_DELAY_FACTOR     12000
144  #define MHZ                            (1000 * 1000)
145  
146 +#define ATH79_SPI_CS_LINE_MAX          2
147 +
148  struct ath79_spi {
149         struct spi_bitbang      bitbang;
150         u32                     ioc_base;
151 @@ -69,6 +71,7 @@ static void ath79_spi_chipselect(struct
152  {
153         struct ath79_spi *sp = ath79_spidev_to_sp(spi);
154         int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active;
155 +       struct ath79_spi_controller_data *cdata = spi->controller_data;
156  
157         if (is_active) {
158                 /* set initial clock polarity */
159 @@ -80,20 +83,21 @@ static void ath79_spi_chipselect(struct
160                 ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
161         }
162  
163 -       if (spi->chip_select) {
164 -               struct ath79_spi_controller_data *cdata = spi->controller_data;
165 -
166 -               /* SPI is normally active-low */
167 -               gpio_set_value(cdata->gpio, cs_high);
168 -       } else {
169 +       switch (cdata->cs_type) {
170 +       case ATH79_SPI_CS_TYPE_INTERNAL:
171                 if (cs_high)
172 -                       sp->ioc_base |= AR71XX_SPI_IOC_CS0;
173 +                       sp->ioc_base |= AR71XX_SPI_IOC_CS(cdata->cs_line);
174                 else
175 -                       sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
176 +                       sp->ioc_base &= ~AR71XX_SPI_IOC_CS(cdata->cs_line);
177  
178                 ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
179 -       }
180 +               break;
181  
182 +       case ATH79_SPI_CS_TYPE_GPIO:
183 +               /* SPI is normally active-low */
184 +               gpio_set_value(cdata->cs_line, cs_high);
185 +               break;
186 +       }
187  }
188  
189  static void ath79_spi_enable(struct ath79_spi *sp)
190 @@ -120,24 +124,30 @@ static void ath79_spi_disable(struct ath
191  static int ath79_spi_setup_cs(struct spi_device *spi)
192  {
193         struct ath79_spi_controller_data *cdata;
194 +       unsigned long flags;
195         int status;
196  
197         cdata = spi->controller_data;
198 -       if (spi->chip_select && !cdata)
199 +       if (!cdata)
200                 return -EINVAL;
201  
202         status = 0;
203 -       if (spi->chip_select) {
204 -               unsigned long flags;
205 +       switch (cdata->cs_type) {
206 +       case ATH79_SPI_CS_TYPE_INTERNAL:
207 +               if (cdata->cs_line > ATH79_SPI_CS_LINE_MAX)
208 +                       status = -EINVAL;
209 +               break;
210  
211 +       case ATH79_SPI_CS_TYPE_GPIO:
212                 flags = GPIOF_DIR_OUT;
213                 if (spi->mode & SPI_CS_HIGH)
214                         flags |= GPIOF_INIT_HIGH;
215                 else
216                         flags |= GPIOF_INIT_LOW;
217  
218 -               status = gpio_request_one(cdata->gpio, flags,
219 +               status = gpio_request_one(cdata->cs_line, flags,
220                                           dev_name(&spi->dev));
221 +               break;
222         }
223  
224         return status;
225 @@ -145,9 +155,19 @@ static int ath79_spi_setup_cs(struct spi
226  
227  static void ath79_spi_cleanup_cs(struct spi_device *spi)
228  {
229 -       if (spi->chip_select) {
230 -               struct ath79_spi_controller_data *cdata = spi->controller_data;
231 -               gpio_free(cdata->gpio);
232 +       struct ath79_spi_controller_data *cdata;
233 +
234 +       cdata = spi->controller_data;
235 +       if (!cdata)
236 +               return;
237 +
238 +       switch (cdata->cs_type) {
239 +       case ATH79_SPI_CS_TYPE_INTERNAL:
240 +               /* nothing to do */
241 +               break;
242 +       case ATH79_SPI_CS_TYPE_GPIO:
243 +               gpio_free(cdata->cs_line);
244 +               break;
245         }
246  }
247  
248 @@ -155,6 +175,9 @@ static int ath79_spi_setup(struct spi_de
249  {
250         int status = 0;
251  
252 +       if (spi->controller_data == NULL)
253 +               return -EINVAL;
254 +
255         if (spi->bits_per_word > 32)
256                 return -EINVAL;
257  
258 @@ -215,6 +238,10 @@ static __devinit int ath79_spi_probe(str
259         unsigned long rate;
260         int ret;
261  
262 +       pdata = pdev->dev.platform_data;
263 +       if (!pdata)
264 +               return -EINVAL;
265 +
266         master = spi_alloc_master(&pdev->dev, sizeof(*sp));
267         if (master == NULL) {
268                 dev_err(&pdev->dev, "failed to allocate spi master\n");
269 @@ -224,17 +251,10 @@ static __devinit int ath79_spi_probe(str
270         sp = spi_master_get_devdata(master);
271         platform_set_drvdata(pdev, sp);
272  
273 -       pdata = pdev->dev.platform_data;
274 -
275         master->setup = ath79_spi_setup;
276         master->cleanup = ath79_spi_cleanup;
277 -       if (pdata) {
278 -               master->bus_num = pdata->bus_num;
279 -               master->num_chipselect = pdata->num_chipselect;
280 -       } else {
281 -               master->bus_num = -1;
282 -               master->num_chipselect = 1;
283 -       }
284 +       master->bus_num = pdata->bus_num;
285 +       master->num_chipselect = pdata->num_chipselect;
286  
287         sp->bitbang.master = spi_master_get(master);
288         sp->bitbang.chipselect = ath79_spi_chipselect;