diff options
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi_gpio.c | 101 |
1 files changed, 83 insertions, 18 deletions
diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c index 82b480cc9637..e24a63498acb 100644 --- a/drivers/spi/spi_gpio.c +++ b/drivers/spi/spi_gpio.c | |||
@@ -167,6 +167,44 @@ static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi, | |||
167 | return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits); | 167 | return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits); |
168 | } | 168 | } |
169 | 169 | ||
170 | /* | ||
171 | * These functions do not call setmosi or getmiso if respective flag | ||
172 | * (SPI_MASTER_NO_RX or SPI_MASTER_NO_TX) is set, so they are safe to | ||
173 | * call when such pin is not present or defined in the controller. | ||
174 | * A separate set of callbacks is defined to get highest possible | ||
175 | * speed in the generic case (when both MISO and MOSI lines are | ||
176 | * available), as optimiser will remove the checks when argument is | ||
177 | * constant. | ||
178 | */ | ||
179 | |||
180 | static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi, | ||
181 | unsigned nsecs, u32 word, u8 bits) | ||
182 | { | ||
183 | unsigned flags = spi->master->flags; | ||
184 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits); | ||
185 | } | ||
186 | |||
187 | static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi, | ||
188 | unsigned nsecs, u32 word, u8 bits) | ||
189 | { | ||
190 | unsigned flags = spi->master->flags; | ||
191 | return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits); | ||
192 | } | ||
193 | |||
194 | static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi, | ||
195 | unsigned nsecs, u32 word, u8 bits) | ||
196 | { | ||
197 | unsigned flags = spi->master->flags; | ||
198 | return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits); | ||
199 | } | ||
200 | |||
201 | static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi, | ||
202 | unsigned nsecs, u32 word, u8 bits) | ||
203 | { | ||
204 | unsigned flags = spi->master->flags; | ||
205 | return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits); | ||
206 | } | ||
207 | |||
170 | /*----------------------------------------------------------------------*/ | 208 | /*----------------------------------------------------------------------*/ |
171 | 209 | ||
172 | static void spi_gpio_chipselect(struct spi_device *spi, int is_active) | 210 | static void spi_gpio_chipselect(struct spi_device *spi, int is_active) |
@@ -232,19 +270,30 @@ static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in) | |||
232 | } | 270 | } |
233 | 271 | ||
234 | static int __init | 272 | static int __init |
235 | spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label) | 273 | spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label, |
274 | u16 *res_flags) | ||
236 | { | 275 | { |
237 | int value; | 276 | int value; |
238 | 277 | ||
239 | /* NOTE: SPI_*_GPIO symbols may reference "pdata" */ | 278 | /* NOTE: SPI_*_GPIO symbols may reference "pdata" */ |
240 | 279 | ||
241 | value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false); | 280 | if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) { |
242 | if (value) | 281 | value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false); |
243 | goto done; | 282 | if (value) |
283 | goto done; | ||
284 | } else { | ||
285 | /* HW configuration without MOSI pin */ | ||
286 | *res_flags |= SPI_MASTER_NO_TX; | ||
287 | } | ||
244 | 288 | ||
245 | value = spi_gpio_alloc(SPI_MISO_GPIO, label, true); | 289 | if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) { |
246 | if (value) | 290 | value = spi_gpio_alloc(SPI_MISO_GPIO, label, true); |
247 | goto free_mosi; | 291 | if (value) |
292 | goto free_mosi; | ||
293 | } else { | ||
294 | /* HW configuration without MISO pin */ | ||
295 | *res_flags |= SPI_MASTER_NO_RX; | ||
296 | } | ||
248 | 297 | ||
249 | value = spi_gpio_alloc(SPI_SCK_GPIO, label, false); | 298 | value = spi_gpio_alloc(SPI_SCK_GPIO, label, false); |
250 | if (value) | 299 | if (value) |
@@ -253,9 +302,11 @@ spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label) | |||
253 | goto done; | 302 | goto done; |
254 | 303 | ||
255 | free_miso: | 304 | free_miso: |
256 | gpio_free(SPI_MISO_GPIO); | 305 | if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) |
306 | gpio_free(SPI_MISO_GPIO); | ||
257 | free_mosi: | 307 | free_mosi: |
258 | gpio_free(SPI_MOSI_GPIO); | 308 | if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) |
309 | gpio_free(SPI_MOSI_GPIO); | ||
259 | done: | 310 | done: |
260 | return value; | 311 | return value; |
261 | } | 312 | } |
@@ -266,6 +317,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) | |||
266 | struct spi_master *master; | 317 | struct spi_master *master; |
267 | struct spi_gpio *spi_gpio; | 318 | struct spi_gpio *spi_gpio; |
268 | struct spi_gpio_platform_data *pdata; | 319 | struct spi_gpio_platform_data *pdata; |
320 | u16 master_flags = 0; | ||
269 | 321 | ||
270 | pdata = pdev->dev.platform_data; | 322 | pdata = pdev->dev.platform_data; |
271 | #ifdef GENERIC_BITBANG | 323 | #ifdef GENERIC_BITBANG |
@@ -273,7 +325,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) | |||
273 | return -ENODEV; | 325 | return -ENODEV; |
274 | #endif | 326 | #endif |
275 | 327 | ||
276 | status = spi_gpio_request(pdata, dev_name(&pdev->dev)); | 328 | status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags); |
277 | if (status < 0) | 329 | if (status < 0) |
278 | return status; | 330 | return status; |
279 | 331 | ||
@@ -289,6 +341,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) | |||
289 | if (pdata) | 341 | if (pdata) |
290 | spi_gpio->pdata = *pdata; | 342 | spi_gpio->pdata = *pdata; |
291 | 343 | ||
344 | master->flags = master_flags; | ||
292 | master->bus_num = pdev->id; | 345 | master->bus_num = pdev->id; |
293 | master->num_chipselect = SPI_N_CHIPSEL; | 346 | master->num_chipselect = SPI_N_CHIPSEL; |
294 | master->setup = spi_gpio_setup; | 347 | master->setup = spi_gpio_setup; |
@@ -296,10 +349,18 @@ static int __init spi_gpio_probe(struct platform_device *pdev) | |||
296 | 349 | ||
297 | spi_gpio->bitbang.master = spi_master_get(master); | 350 | spi_gpio->bitbang.master = spi_master_get(master); |
298 | spi_gpio->bitbang.chipselect = spi_gpio_chipselect; | 351 | spi_gpio->bitbang.chipselect = spi_gpio_chipselect; |
299 | spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0; | 352 | |
300 | spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1; | 353 | if ((master_flags & (SPI_MASTER_NO_RX | SPI_MASTER_NO_RX)) == 0) { |
301 | spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2; | 354 | spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0; |
302 | spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3; | 355 | spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1; |
356 | spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2; | ||
357 | spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3; | ||
358 | } else { | ||
359 | spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0; | ||
360 | spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1; | ||
361 | spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2; | ||
362 | spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3; | ||
363 | } | ||
303 | spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer; | 364 | spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer; |
304 | spi_gpio->bitbang.flags = SPI_CS_HIGH; | 365 | spi_gpio->bitbang.flags = SPI_CS_HIGH; |
305 | 366 | ||
@@ -307,8 +368,10 @@ static int __init spi_gpio_probe(struct platform_device *pdev) | |||
307 | if (status < 0) { | 368 | if (status < 0) { |
308 | spi_master_put(spi_gpio->bitbang.master); | 369 | spi_master_put(spi_gpio->bitbang.master); |
309 | gpio_free: | 370 | gpio_free: |
310 | gpio_free(SPI_MISO_GPIO); | 371 | if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) |
311 | gpio_free(SPI_MOSI_GPIO); | 372 | gpio_free(SPI_MISO_GPIO); |
373 | if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) | ||
374 | gpio_free(SPI_MOSI_GPIO); | ||
312 | gpio_free(SPI_SCK_GPIO); | 375 | gpio_free(SPI_SCK_GPIO); |
313 | spi_master_put(master); | 376 | spi_master_put(master); |
314 | } | 377 | } |
@@ -331,8 +394,10 @@ static int __exit spi_gpio_remove(struct platform_device *pdev) | |||
331 | 394 | ||
332 | platform_set_drvdata(pdev, NULL); | 395 | platform_set_drvdata(pdev, NULL); |
333 | 396 | ||
334 | gpio_free(SPI_MISO_GPIO); | 397 | if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) |
335 | gpio_free(SPI_MOSI_GPIO); | 398 | gpio_free(SPI_MISO_GPIO); |
399 | if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) | ||
400 | gpio_free(SPI_MOSI_GPIO); | ||
336 | gpio_free(SPI_SCK_GPIO); | 401 | gpio_free(SPI_SCK_GPIO); |
337 | 402 | ||
338 | return status; | 403 | return status; |