e0863a4a02176ca2251d12a5e44c5230ca02b8bd
[openwrt/openwrt.git] / target / linux / ar71xx / patches-4.4 / 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 @@ -119,14 +126,15 @@ static int ath79_spi_setup_cs(struct spi
106 {
107 struct ath79_spi *sp = ath79_spidev_to_sp(spi);
108 struct ath79_spi_controller_data *cdata = spi->controller_data;
109 + unsigned long flags;
110 int status;
111
112 - if (spi->chip_select && (!cdata || !gpio_is_valid(cdata->gpio)))
113 + if (!cdata)
114 return -EINVAL;
115
116 status = 0;
117 - if (spi->chip_select) {
118 - unsigned long flags;
119 + switch (cdata->cs_type) {
120 + case ATH79_SPI_CS_TYPE_GPIO:
121
122 flags = GPIOF_DIR_OUT;
123 if (spi->mode & SPI_CS_HIGH)
124 @@ -134,15 +142,21 @@ static int ath79_spi_setup_cs(struct spi
125 else
126 flags |= GPIOF_INIT_HIGH;
127
128 - status = gpio_request_one(cdata->gpio, flags,
129 + status = gpio_request_one(cdata->cs_line, flags,
130 dev_name(&spi->dev));
131 - } else {
132 + break;
133 + case ATH79_SPI_CS_TYPE_INTERNAL:
134 + if (cdata->cs_line > ATH79_SPI_CS_LINE_MAX)
135 + status = -EINVAL;
136 + break;
137 +
138 if (spi->mode & SPI_CS_HIGH)
139 sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
140 else
141 sp->ioc_base |= AR71XX_SPI_IOC_CS0;
142
143 ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
144 + break;
145 }
146
147 return status;
148 @@ -150,9 +164,19 @@ static int ath79_spi_setup_cs(struct spi
149
150 static void ath79_spi_cleanup_cs(struct spi_device *spi)
151 {
152 - if (spi->chip_select) {
153 - struct ath79_spi_controller_data *cdata = spi->controller_data;
154 - gpio_free(cdata->gpio);
155 + struct ath79_spi_controller_data *cdata;
156 +
157 + cdata = spi->controller_data;
158 + if (!cdata)
159 + return;
160 +
161 + switch (cdata->cs_type) {
162 + case ATH79_SPI_CS_TYPE_INTERNAL:
163 + /* nothing to do */
164 + break;
165 + case ATH79_SPI_CS_TYPE_GPIO:
166 + gpio_free(cdata->cs_line);
167 + break;
168 }
169 }
170
171 @@ -217,6 +241,10 @@ static int ath79_spi_probe(struct platfo
172 unsigned long rate;
173 int ret;
174
175 + pdata = pdev->dev.platform_data;
176 + if (!pdata)
177 + return -EINVAL;
178 +
179 master = spi_alloc_master(&pdev->dev, sizeof(*sp));
180 if (master == NULL) {
181 dev_err(&pdev->dev, "failed to allocate spi master\n");
182 @@ -226,15 +254,11 @@ static int ath79_spi_probe(struct platfo
183 sp = spi_master_get_devdata(master);
184 platform_set_drvdata(pdev, sp);
185
186 - pdata = dev_get_platdata(&pdev->dev);
187 -
188 master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
189 master->setup = ath79_spi_setup;
190 master->cleanup = ath79_spi_cleanup;
191 - if (pdata) {
192 - master->bus_num = pdata->bus_num;
193 - master->num_chipselect = pdata->num_chipselect;
194 - }
195 + master->bus_num = pdata->bus_num;
196 + master->num_chipselect = pdata->num_chipselect;
197
198 sp->bitbang.master = master;
199 sp->bitbang.chipselect = ath79_spi_chipselect;