diff options
author | Michael Hennerich <michael.hennerich@analog.com> | 2009-04-06 22:00:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-07 11:31:06 -0400 |
commit | 42c78b2bf51bafb4cfa98dfecc28dd9b8bcd04b0 (patch) | |
tree | 12960b010ec28ff6e5cfeb4a640681464781f51e /drivers/spi/spi_bfin5xx.c | |
parent | e7d02e3c9577f070bc77354763bed7f24713dc53 (diff) |
Blackfin SPI Driver: Add GPIO controlled SPI Slave Select support
Add support for GPIO controlled SPI Chip Selects. To make use of this
feature, set chip_select = 0 and add a proper cs_gpio to your
controller_data.
struct spi_board_info
.chip_select = 0
struct bfin5xx_spi_chip
.cs_gpio = GPIO_P###
There are various SPI devices that require SPI MODE_0, and need to have
the Chip Selects asserted during the entire transfer. Consider using
SPI_MODE_3 (SPI_CPHA | SPI_CPOL) if your device allows it.
Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/spi/spi_bfin5xx.c')
-rw-r--r-- | drivers/spi/spi_bfin5xx.c | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index 53819c961a31..6aa084e445e6 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c | |||
@@ -111,6 +111,7 @@ struct chip_data { | |||
111 | u8 bits_per_word; /* 8 or 16 */ | 111 | u8 bits_per_word; /* 8 or 16 */ |
112 | u8 cs_change_per_word; | 112 | u8 cs_change_per_word; |
113 | u16 cs_chg_udelay; /* Some devices require > 255usec delay */ | 113 | u16 cs_chg_udelay; /* Some devices require > 255usec delay */ |
114 | u32 cs_gpio; | ||
114 | void (*write) (struct driver_data *); | 115 | void (*write) (struct driver_data *); |
115 | void (*read) (struct driver_data *); | 116 | void (*read) (struct driver_data *); |
116 | void (*duplex) (struct driver_data *); | 117 | void (*duplex) (struct driver_data *); |
@@ -177,22 +178,30 @@ static int bfin_spi_flush(struct driver_data *drv_data) | |||
177 | /* Chip select operation functions for cs_change flag */ | 178 | /* Chip select operation functions for cs_change flag */ |
178 | static void bfin_spi_cs_active(struct driver_data *drv_data, struct chip_data *chip) | 179 | static void bfin_spi_cs_active(struct driver_data *drv_data, struct chip_data *chip) |
179 | { | 180 | { |
180 | u16 flag = read_FLAG(drv_data); | 181 | if (likely(chip->chip_select_num)) { |
182 | u16 flag = read_FLAG(drv_data); | ||
181 | 183 | ||
182 | flag |= chip->flag; | 184 | flag |= chip->flag; |
183 | flag &= ~(chip->flag << 8); | 185 | flag &= ~(chip->flag << 8); |
184 | 186 | ||
185 | write_FLAG(drv_data, flag); | 187 | write_FLAG(drv_data, flag); |
188 | } else { | ||
189 | gpio_set_value(chip->cs_gpio, 0); | ||
190 | } | ||
186 | } | 191 | } |
187 | 192 | ||
188 | static void bfin_spi_cs_deactive(struct driver_data *drv_data, struct chip_data *chip) | 193 | static void bfin_spi_cs_deactive(struct driver_data *drv_data, struct chip_data *chip) |
189 | { | 194 | { |
190 | u16 flag = read_FLAG(drv_data); | 195 | if (likely(chip->chip_select_num)) { |
196 | u16 flag = read_FLAG(drv_data); | ||
191 | 197 | ||
192 | flag &= ~chip->flag; | 198 | flag &= ~chip->flag; |
193 | flag |= (chip->flag << 8); | 199 | flag |= (chip->flag << 8); |
194 | 200 | ||
195 | write_FLAG(drv_data, flag); | 201 | write_FLAG(drv_data, flag); |
202 | } else { | ||
203 | gpio_set_value(chip->cs_gpio, 1); | ||
204 | } | ||
196 | 205 | ||
197 | /* Move delay here for consistency */ | 206 | /* Move delay here for consistency */ |
198 | if (chip->cs_chg_udelay) | 207 | if (chip->cs_chg_udelay) |
@@ -1036,6 +1045,7 @@ static int bfin_spi_setup(struct spi_device *spi) | |||
1036 | struct bfin5xx_spi_chip *chip_info = NULL; | 1045 | struct bfin5xx_spi_chip *chip_info = NULL; |
1037 | struct chip_data *chip; | 1046 | struct chip_data *chip; |
1038 | struct driver_data *drv_data = spi_master_get_devdata(spi->master); | 1047 | struct driver_data *drv_data = spi_master_get_devdata(spi->master); |
1048 | int ret; | ||
1039 | 1049 | ||
1040 | /* Abort device setup if requested features are not supported */ | 1050 | /* Abort device setup if requested features are not supported */ |
1041 | if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) { | 1051 | if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) { |
@@ -1081,6 +1091,7 @@ static int bfin_spi_setup(struct spi_device *spi) | |||
1081 | chip->bits_per_word = chip_info->bits_per_word; | 1091 | chip->bits_per_word = chip_info->bits_per_word; |
1082 | chip->cs_change_per_word = chip_info->cs_change_per_word; | 1092 | chip->cs_change_per_word = chip_info->cs_change_per_word; |
1083 | chip->cs_chg_udelay = chip_info->cs_chg_udelay; | 1093 | chip->cs_chg_udelay = chip_info->cs_chg_udelay; |
1094 | chip->cs_gpio = chip_info->cs_gpio; | ||
1084 | } | 1095 | } |
1085 | 1096 | ||
1086 | /* translate common spi framework into our register */ | 1097 | /* translate common spi framework into our register */ |
@@ -1121,6 +1132,16 @@ static int bfin_spi_setup(struct spi_device *spi) | |||
1121 | chip->flag = 1 << (spi->chip_select); | 1132 | chip->flag = 1 << (spi->chip_select); |
1122 | chip->chip_select_num = spi->chip_select; | 1133 | chip->chip_select_num = spi->chip_select; |
1123 | 1134 | ||
1135 | if (chip->chip_select_num == 0) { | ||
1136 | ret = gpio_request(chip->cs_gpio, spi->modalias); | ||
1137 | if (ret) { | ||
1138 | if (drv_data->dma_requested) | ||
1139 | free_dma(drv_data->dma_channel); | ||
1140 | return ret; | ||
1141 | } | ||
1142 | gpio_direction_output(chip->cs_gpio, 1); | ||
1143 | } | ||
1144 | |||
1124 | switch (chip->bits_per_word) { | 1145 | switch (chip->bits_per_word) { |
1125 | case 8: | 1146 | case 8: |
1126 | chip->n_bytes = 1; | 1147 | chip->n_bytes = 1; |
@@ -1186,6 +1207,9 @@ static void bfin_spi_cleanup(struct spi_device *spi) | |||
1186 | peripheral_free(ssel[spi->master->bus_num] | 1207 | peripheral_free(ssel[spi->master->bus_num] |
1187 | [chip->chip_select_num-1]); | 1208 | [chip->chip_select_num-1]); |
1188 | 1209 | ||
1210 | if (chip->chip_select_num == 0) | ||
1211 | gpio_free(chip->cs_gpio); | ||
1212 | |||
1189 | kfree(chip); | 1213 | kfree(chip); |
1190 | } | 1214 | } |
1191 | 1215 | ||