ar71xx: Add Gainstrong MiniBox v1.0 support to trunk
[openwrt/openwrt.git] / target / linux / ar71xx / patches-4.1 / 206-spi-ath79-make-chipselect-logic-more-flexible.patch
1 From 7008284716403237f6bc7d7590b3ed073555bd56 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 34/34] spi/ath79: make chipselect logic more flexible
5
6 Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
7 ---
8 arch/mips/ath79/mach-pb44.c | 6 ++
9 .../include/asm/mach-ath79/ath79_spi_platform.h | 8 ++-
10 drivers/spi/spi-ath79.c | 67 +++++++++++++-------
11 8 files changed, 88 insertions(+), 23 deletions(-)
12
13 --- a/arch/mips/ath79/mach-pb44.c
14 +++ b/arch/mips/ath79/mach-pb44.c
15 @@ -87,12 +87,18 @@ static struct gpio_keys_button pb44_gpio
16 }
17 };
18
19 +static struct ath79_spi_controller_data pb44_spi0_data = {
20 + .cs_type = ATH79_SPI_CS_TYPE_INTERNAL,
21 + .cs_line = 0,
22 +};
23 +
24 static struct spi_board_info pb44_spi_info[] = {
25 {
26 .bus_num = 0,
27 .chip_select = 0,
28 .max_speed_hz = 25000000,
29 .modalias = "m25p64",
30 + .controller_data = &pb44_spi0_data,
31 },
32 };
33
34 --- a/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
35 +++ b/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
36 @@ -16,8 +16,14 @@ struct ath79_spi_platform_data {
37 unsigned num_chipselect;
38 };
39
40 +enum ath79_spi_cs_type {
41 + ATH79_SPI_CS_TYPE_INTERNAL,
42 + ATH79_SPI_CS_TYPE_GPIO,
43 +};
44 +
45 struct ath79_spi_controller_data {
46 - unsigned gpio;
47 + enum ath79_spi_cs_type cs_type;
48 + unsigned cs_line;
49 };
50
51 #endif /* _ATH79_SPI_PLATFORM_H */
52 --- a/drivers/spi/spi-ath79.c
53 +++ b/drivers/spi/spi-ath79.c
54 @@ -33,6 +33,8 @@
55 #define ATH79_SPI_RRW_DELAY_FACTOR 12000
56 #define MHZ (1000 * 1000)
57
58 +#define ATH79_SPI_CS_LINE_MAX 2
59 +
60 struct ath79_spi {
61 struct spi_bitbang bitbang;
62 u32 ioc_base;
63 @@ -67,6 +69,7 @@ static void ath79_spi_chipselect(struct
64 {
65 struct ath79_spi *sp = ath79_spidev_to_sp(spi);
66 int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active;
67 + struct ath79_spi_controller_data *cdata = spi->controller_data;
68
69 if (is_active) {
70 /* set initial clock polarity */
71 @@ -78,20 +81,24 @@ static void ath79_spi_chipselect(struct
72 ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
73 }
74
75 - if (spi->chip_select) {
76 - struct ath79_spi_controller_data *cdata = spi->controller_data;
77 -
78 - /* SPI is normally active-low */
79 - gpio_set_value(cdata->gpio, cs_high);
80 - } else {
81 + switch (cdata->cs_type) {
82 + case ATH79_SPI_CS_TYPE_INTERNAL:
83 if (cs_high)
84 - sp->ioc_base |= AR71XX_SPI_IOC_CS0;
85 + sp->ioc_base |= AR71XX_SPI_IOC_CS(cdata->cs_line);
86 else
87 - sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
88 + sp->ioc_base &= ~AR71XX_SPI_IOC_CS(cdata->cs_line);
89
90 ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
91 - }
92 + break;
93
94 + case ATH79_SPI_CS_TYPE_GPIO:
95 + /* SPI is normally active-low */
96 + if (gpio_cansleep(cdata->cs_line))
97 + gpio_set_value_cansleep(cdata->cs_line, cs_high);
98 + else
99 + gpio_set_value(cdata->cs_line, cs_high);
100 + break;
101 + }
102 }
103
104 static void ath79_spi_enable(struct ath79_spi *sp)
105 @@ -118,24 +125,30 @@ static void ath79_spi_disable(struct ath
106 static int ath79_spi_setup_cs(struct spi_device *spi)
107 {
108 struct ath79_spi_controller_data *cdata;
109 + unsigned long flags;
110 int status;
111
112 cdata = spi->controller_data;
113 - if (spi->chip_select && !cdata)
114 + if (!cdata)
115 return -EINVAL;
116
117 status = 0;
118 - if (spi->chip_select) {
119 - unsigned long flags;
120 + switch (cdata->cs_type) {
121 + case ATH79_SPI_CS_TYPE_INTERNAL:
122 + if (cdata->cs_line > ATH79_SPI_CS_LINE_MAX)
123 + status = -EINVAL;
124 + break;
125
126 + case ATH79_SPI_CS_TYPE_GPIO:
127 flags = GPIOF_DIR_OUT;
128 if (spi->mode & SPI_CS_HIGH)
129 flags |= GPIOF_INIT_LOW;
130 else
131 flags |= GPIOF_INIT_HIGH;
132
133 - status = gpio_request_one(cdata->gpio, flags,
134 + status = gpio_request_one(cdata->cs_line, flags,
135 dev_name(&spi->dev));
136 + break;
137 }
138
139 return status;
140 @@ -143,9 +156,19 @@ static int ath79_spi_setup_cs(struct spi
141
142 static void ath79_spi_cleanup_cs(struct spi_device *spi)
143 {
144 - if (spi->chip_select) {
145 - struct ath79_spi_controller_data *cdata = spi->controller_data;
146 - gpio_free(cdata->gpio);
147 + struct ath79_spi_controller_data *cdata;
148 +
149 + cdata = spi->controller_data;
150 + if (!cdata)
151 + return;
152 +
153 + switch (cdata->cs_type) {
154 + case ATH79_SPI_CS_TYPE_INTERNAL:
155 + /* nothing to do */
156 + break;
157 + case ATH79_SPI_CS_TYPE_GPIO:
158 + gpio_free(cdata->cs_line);
159 + break;
160 }
161 }
162
163 @@ -210,6 +233,10 @@ static int ath79_spi_probe(struct platfo
164 unsigned long rate;
165 int ret;
166
167 + pdata = pdev->dev.platform_data;
168 + if (!pdata)
169 + return -EINVAL;
170 +
171 master = spi_alloc_master(&pdev->dev, sizeof(*sp));
172 if (master == NULL) {
173 dev_err(&pdev->dev, "failed to allocate spi master\n");
174 @@ -219,15 +246,11 @@ static int ath79_spi_probe(struct platfo
175 sp = spi_master_get_devdata(master);
176 platform_set_drvdata(pdev, sp);
177
178 - pdata = dev_get_platdata(&pdev->dev);
179 -
180 master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
181 master->setup = ath79_spi_setup;
182 master->cleanup = ath79_spi_cleanup;
183 - if (pdata) {
184 - master->bus_num = pdata->bus_num;
185 - master->num_chipselect = pdata->num_chipselect;
186 - }
187 + master->bus_num = pdata->bus_num;
188 + master->num_chipselect = pdata->num_chipselect;
189
190 sp->bitbang.master = master;
191 sp->bitbang.chipselect = ath79_spi_chipselect;