diff options
author | Eric Miao <eric.miao@marvell.com> | 2009-04-06 22:00:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-07 11:31:07 -0400 |
commit | a7bb3909b3293d503211d7f6af8ed62c1644b686 (patch) | |
tree | 7e3cc012c12ff689194333b2ac9988be16df9c55 /drivers/spi/pxa2xx_spi.c | |
parent | c8fc657e6a114fadf78fdf8103e289a169c91c5d (diff) |
spi: pxa2xx_spi: introduce chipselect GPIO to simplify the common cases
Most SPI peripherals use GPIOs as their chip selects, introduce .gpio_cs
for this.
Signed-off-by: Eric Miao <eric.miao@marvell.com>
Cc: David Brownell <david-b@pacbell.net>
Cc: Russell King <rmk@arm.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/spi/pxa2xx_spi.c')
-rw-r--r-- | drivers/spi/pxa2xx_spi.c | 96 |
1 files changed, 78 insertions, 18 deletions
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 33fcef3150d4..70ff0072cb8a 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/workqueue.h> | 28 | #include <linux/workqueue.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
31 | #include <linux/gpio.h> | ||
31 | 32 | ||
32 | #include <asm/io.h> | 33 | #include <asm/io.h> |
33 | #include <asm/irq.h> | 34 | #include <asm/irq.h> |
@@ -166,6 +167,8 @@ struct chip_data { | |||
166 | u8 enable_dma; | 167 | u8 enable_dma; |
167 | u8 bits_per_word; | 168 | u8 bits_per_word; |
168 | u32 speed_hz; | 169 | u32 speed_hz; |
170 | int gpio_cs; | ||
171 | int gpio_cs_inverted; | ||
169 | int (*write)(struct driver_data *drv_data); | 172 | int (*write)(struct driver_data *drv_data); |
170 | int (*read)(struct driver_data *drv_data); | 173 | int (*read)(struct driver_data *drv_data); |
171 | void (*cs_control)(u32 command); | 174 | void (*cs_control)(u32 command); |
@@ -173,6 +176,32 @@ struct chip_data { | |||
173 | 176 | ||
174 | static void pump_messages(struct work_struct *work); | 177 | static void pump_messages(struct work_struct *work); |
175 | 178 | ||
179 | static void cs_assert(struct driver_data *drv_data) | ||
180 | { | ||
181 | struct chip_data *chip = drv_data->cur_chip; | ||
182 | |||
183 | if (chip->cs_control) { | ||
184 | chip->cs_control(PXA2XX_CS_ASSERT); | ||
185 | return; | ||
186 | } | ||
187 | |||
188 | if (gpio_is_valid(chip->gpio_cs)) | ||
189 | gpio_set_value(chip->gpio_cs, chip->gpio_cs_inverted); | ||
190 | } | ||
191 | |||
192 | static void cs_deassert(struct driver_data *drv_data) | ||
193 | { | ||
194 | struct chip_data *chip = drv_data->cur_chip; | ||
195 | |||
196 | if (chip->cs_control) { | ||
197 | chip->cs_control(PXA2XX_CS_ASSERT); | ||
198 | return; | ||
199 | } | ||
200 | |||
201 | if (gpio_is_valid(chip->gpio_cs)) | ||
202 | gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted); | ||
203 | } | ||
204 | |||
176 | static int flush(struct driver_data *drv_data) | 205 | static int flush(struct driver_data *drv_data) |
177 | { | 206 | { |
178 | unsigned long limit = loops_per_jiffy << 1; | 207 | unsigned long limit = loops_per_jiffy << 1; |
@@ -189,10 +218,6 @@ static int flush(struct driver_data *drv_data) | |||
189 | return limit; | 218 | return limit; |
190 | } | 219 | } |
191 | 220 | ||
192 | static void null_cs_control(u32 command) | ||
193 | { | ||
194 | } | ||
195 | |||
196 | static int null_writer(struct driver_data *drv_data) | 221 | static int null_writer(struct driver_data *drv_data) |
197 | { | 222 | { |
198 | void __iomem *reg = drv_data->ioaddr; | 223 | void __iomem *reg = drv_data->ioaddr; |
@@ -400,7 +425,6 @@ static void giveback(struct driver_data *drv_data) | |||
400 | msg = drv_data->cur_msg; | 425 | msg = drv_data->cur_msg; |
401 | drv_data->cur_msg = NULL; | 426 | drv_data->cur_msg = NULL; |
402 | drv_data->cur_transfer = NULL; | 427 | drv_data->cur_transfer = NULL; |
403 | drv_data->cur_chip = NULL; | ||
404 | queue_work(drv_data->workqueue, &drv_data->pump_messages); | 428 | queue_work(drv_data->workqueue, &drv_data->pump_messages); |
405 | spin_unlock_irqrestore(&drv_data->lock, flags); | 429 | spin_unlock_irqrestore(&drv_data->lock, flags); |
406 | 430 | ||
@@ -416,7 +440,7 @@ static void giveback(struct driver_data *drv_data) | |||
416 | * a message with an error, or next message is for another chip | 440 | * a message with an error, or next message is for another chip |
417 | */ | 441 | */ |
418 | if (!last_transfer->cs_change) | 442 | if (!last_transfer->cs_change) |
419 | drv_data->cs_control(PXA2XX_CS_DEASSERT); | 443 | cs_deassert(drv_data); |
420 | else { | 444 | else { |
421 | struct spi_message *next_msg; | 445 | struct spi_message *next_msg; |
422 | 446 | ||
@@ -445,12 +469,14 @@ static void giveback(struct driver_data *drv_data) | |||
445 | if (next_msg && next_msg->spi != msg->spi) | 469 | if (next_msg && next_msg->spi != msg->spi) |
446 | next_msg = NULL; | 470 | next_msg = NULL; |
447 | if (!next_msg || msg->state == ERROR_STATE) | 471 | if (!next_msg || msg->state == ERROR_STATE) |
448 | drv_data->cs_control(PXA2XX_CS_DEASSERT); | 472 | cs_deassert(drv_data); |
449 | } | 473 | } |
450 | 474 | ||
451 | msg->state = NULL; | 475 | msg->state = NULL; |
452 | if (msg->complete) | 476 | if (msg->complete) |
453 | msg->complete(msg->context); | 477 | msg->complete(msg->context); |
478 | |||
479 | drv_data->cur_chip = NULL; | ||
454 | } | 480 | } |
455 | 481 | ||
456 | static int wait_ssp_rx_stall(void const __iomem *ioaddr) | 482 | static int wait_ssp_rx_stall(void const __iomem *ioaddr) |
@@ -887,7 +913,7 @@ static void pump_transfers(unsigned long data) | |||
887 | 913 | ||
888 | /* Drop chip select only if cs_change is requested */ | 914 | /* Drop chip select only if cs_change is requested */ |
889 | if (previous->cs_change) | 915 | if (previous->cs_change) |
890 | drv_data->cs_control(PXA2XX_CS_DEASSERT); | 916 | cs_deassert(drv_data); |
891 | } | 917 | } |
892 | 918 | ||
893 | /* Check for transfers that need multiple DMA segments */ | 919 | /* Check for transfers that need multiple DMA segments */ |
@@ -922,7 +948,6 @@ static void pump_transfers(unsigned long data) | |||
922 | } | 948 | } |
923 | drv_data->n_bytes = chip->n_bytes; | 949 | drv_data->n_bytes = chip->n_bytes; |
924 | drv_data->dma_width = chip->dma_width; | 950 | drv_data->dma_width = chip->dma_width; |
925 | drv_data->cs_control = chip->cs_control; | ||
926 | drv_data->tx = (void *)transfer->tx_buf; | 951 | drv_data->tx = (void *)transfer->tx_buf; |
927 | drv_data->tx_end = drv_data->tx + transfer->len; | 952 | drv_data->tx_end = drv_data->tx + transfer->len; |
928 | drv_data->rx = transfer->rx_buf; | 953 | drv_data->rx = transfer->rx_buf; |
@@ -1084,11 +1109,7 @@ static void pump_transfers(unsigned long data) | |||
1084 | write_SSTO(chip->timeout, reg); | 1109 | write_SSTO(chip->timeout, reg); |
1085 | } | 1110 | } |
1086 | 1111 | ||
1087 | /* FIXME, need to handle cs polarity, | 1112 | cs_assert(drv_data); |
1088 | * this driver uses struct pxa2xx_spi_chip.cs_control to | ||
1089 | * specify a CS handling function, and it ignores most | ||
1090 | * struct spi_device.mode[s], including SPI_CS_HIGH */ | ||
1091 | drv_data->cs_control(PXA2XX_CS_ASSERT); | ||
1092 | 1113 | ||
1093 | /* after chip select, release the data by enabling service | 1114 | /* after chip select, release the data by enabling service |
1094 | * requests and interrupts, without changing any mode bits */ | 1115 | * requests and interrupts, without changing any mode bits */ |
@@ -1166,6 +1187,44 @@ static int transfer(struct spi_device *spi, struct spi_message *msg) | |||
1166 | /* the spi->mode bits understood by this driver: */ | 1187 | /* the spi->mode bits understood by this driver: */ |
1167 | #define MODEBITS (SPI_CPOL | SPI_CPHA) | 1188 | #define MODEBITS (SPI_CPOL | SPI_CPHA) |
1168 | 1189 | ||
1190 | static int setup_cs(struct spi_device *spi, struct chip_data *chip, | ||
1191 | struct pxa2xx_spi_chip *chip_info) | ||
1192 | { | ||
1193 | int err = 0; | ||
1194 | |||
1195 | if (chip == NULL || chip_info == NULL) | ||
1196 | return 0; | ||
1197 | |||
1198 | /* NOTE: setup() can be called multiple times, possibly with | ||
1199 | * different chip_info, release previously requested GPIO | ||
1200 | */ | ||
1201 | if (gpio_is_valid(chip->gpio_cs)) | ||
1202 | gpio_free(chip->gpio_cs); | ||
1203 | |||
1204 | /* If (*cs_control) is provided, ignore GPIO chip select */ | ||
1205 | if (chip_info->cs_control) { | ||
1206 | chip->cs_control = chip_info->cs_control; | ||
1207 | return 0; | ||
1208 | } | ||
1209 | |||
1210 | if (gpio_is_valid(chip_info->gpio_cs)) { | ||
1211 | err = gpio_request(chip_info->gpio_cs, "SPI_CS"); | ||
1212 | if (err) { | ||
1213 | dev_err(&spi->dev, "failed to request chip select " | ||
1214 | "GPIO%d\n", chip_info->gpio_cs); | ||
1215 | return err; | ||
1216 | } | ||
1217 | |||
1218 | chip->gpio_cs = chip_info->gpio_cs; | ||
1219 | chip->gpio_cs_inverted = spi->mode & SPI_CS_HIGH; | ||
1220 | |||
1221 | err = gpio_direction_output(chip->gpio_cs, | ||
1222 | !chip->gpio_cs_inverted); | ||
1223 | } | ||
1224 | |||
1225 | return err; | ||
1226 | } | ||
1227 | |||
1169 | static int setup(struct spi_device *spi) | 1228 | static int setup(struct spi_device *spi) |
1170 | { | 1229 | { |
1171 | struct pxa2xx_spi_chip *chip_info = NULL; | 1230 | struct pxa2xx_spi_chip *chip_info = NULL; |
@@ -1211,7 +1270,7 @@ static int setup(struct spi_device *spi) | |||
1211 | return -ENOMEM; | 1270 | return -ENOMEM; |
1212 | } | 1271 | } |
1213 | 1272 | ||
1214 | chip->cs_control = null_cs_control; | 1273 | chip->gpio_cs = -1; |
1215 | chip->enable_dma = 0; | 1274 | chip->enable_dma = 0; |
1216 | chip->timeout = TIMOUT_DFLT; | 1275 | chip->timeout = TIMOUT_DFLT; |
1217 | chip->dma_burst_size = drv_data->master_info->enable_dma ? | 1276 | chip->dma_burst_size = drv_data->master_info->enable_dma ? |
@@ -1225,8 +1284,6 @@ static int setup(struct spi_device *spi) | |||
1225 | /* chip_info isn't always needed */ | 1284 | /* chip_info isn't always needed */ |
1226 | chip->cr1 = 0; | 1285 | chip->cr1 = 0; |
1227 | if (chip_info) { | 1286 | if (chip_info) { |
1228 | if (chip_info->cs_control) | ||
1229 | chip->cs_control = chip_info->cs_control; | ||
1230 | if (chip_info->timeout) | 1287 | if (chip_info->timeout) |
1231 | chip->timeout = chip_info->timeout; | 1288 | chip->timeout = chip_info->timeout; |
1232 | if (chip_info->tx_threshold) | 1289 | if (chip_info->tx_threshold) |
@@ -1308,13 +1365,16 @@ static int setup(struct spi_device *spi) | |||
1308 | 1365 | ||
1309 | spi_set_ctldata(spi, chip); | 1366 | spi_set_ctldata(spi, chip); |
1310 | 1367 | ||
1311 | return 0; | 1368 | return setup_cs(spi, chip, chip_info); |
1312 | } | 1369 | } |
1313 | 1370 | ||
1314 | static void cleanup(struct spi_device *spi) | 1371 | static void cleanup(struct spi_device *spi) |
1315 | { | 1372 | { |
1316 | struct chip_data *chip = spi_get_ctldata(spi); | 1373 | struct chip_data *chip = spi_get_ctldata(spi); |
1317 | 1374 | ||
1375 | if (gpio_is_valid(chip->gpio_cs)) | ||
1376 | gpio_free(chip->gpio_cs); | ||
1377 | |||
1318 | kfree(chip); | 1378 | kfree(chip); |
1319 | } | 1379 | } |
1320 | 1380 | ||