aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBarry Song <barry.song@analog.com>2009-11-17 04:45:59 -0500
committerMike Frysinger <vapier@gentoo.org>2010-10-18 02:49:36 -0400
commitd3cc71f71ae13596cb988e16bfa2b15f09fb7347 (patch)
tree6fcd5e9401931dbce719bcdfd1e5b4075f392598
parent0d2c6de2255cb299fdd77d4543738adee45f4f3f (diff)
spi/bfin_spi: redo GPIO CS handling
The common SPI layers take care of detecting CS conflicts and preventing two devices from claiming the same CS. This causes problems for the GPIO CS support we currently have as we are using CS0 to mean "GPIO CS". But if we have multiple devices using a GPIO CS, the common SPI layers see multiple devices using the virtual "CS0" and reject any such attempts. To make both work, we introduce an offset define. This represents the max number of hardware CS values that the SPI peripheral supports. If the CS is below this limit, we know we can use the hardware CS. If it's above, we treat it as a GPIO CS. This keeps the CS unique as seen by the common code and prevents conflicts. Signed-off-by: Barry Song <barry.song@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-rw-r--r--arch/blackfin/include/asm/bfin5xx_spi.h3
-rw-r--r--drivers/spi/spi_bfin5xx.c40
2 files changed, 23 insertions, 20 deletions
diff --git a/arch/blackfin/include/asm/bfin5xx_spi.h b/arch/blackfin/include/asm/bfin5xx_spi.h
index 126d25e2afa8..6f011dac378f 100644
--- a/arch/blackfin/include/asm/bfin5xx_spi.h
+++ b/arch/blackfin/include/asm/bfin5xx_spi.h
@@ -109,6 +109,8 @@
109#define CMD_SPI_GET_SYSTEMCLOCK 25 109#define CMD_SPI_GET_SYSTEMCLOCK 25
110#define CMD_SPI_SET_WRITECONTINUOUS 26 110#define CMD_SPI_SET_WRITECONTINUOUS 26
111 111
112#define MAX_CTRL_CS 8 /* cs in spi controller */
113
112/* device.platform_data for SSP controller devices */ 114/* device.platform_data for SSP controller devices */
113struct bfin5xx_spi_master { 115struct bfin5xx_spi_master {
114 u16 num_chipselect; 116 u16 num_chipselect;
@@ -124,7 +126,6 @@ struct bfin5xx_spi_chip {
124 u8 enable_dma; 126 u8 enable_dma;
125 u8 bits_per_word; 127 u8 bits_per_word;
126 u16 cs_chg_udelay; /* Some devices require 16-bit delays */ 128 u16 cs_chg_udelay; /* Some devices require 16-bit delays */
127 u32 cs_gpio;
128 /* Value to send if no TX value is supplied, usually 0x0 or 0xFFFF */ 129 /* Value to send if no TX value is supplied, usually 0x0 or 0xFFFF */
129 u16 idle_tx_val; 130 u16 idle_tx_val;
130 u8 pio_interrupt; /* Enable spi data irq */ 131 u8 pio_interrupt; /* Enable spi data irq */
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 07044d7db9a4..278fe0a612c2 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -183,7 +183,7 @@ static int bfin_spi_flush(struct master_data *drv_data)
183/* Chip select operation functions for cs_change flag */ 183/* Chip select operation functions for cs_change flag */
184static void bfin_spi_cs_active(struct master_data *drv_data, struct slave_data *chip) 184static void bfin_spi_cs_active(struct master_data *drv_data, struct slave_data *chip)
185{ 185{
186 if (likely(chip->chip_select_num)) { 186 if (likely(chip->chip_select_num < MAX_CTRL_CS)) {
187 u16 flag = read_FLAG(drv_data); 187 u16 flag = read_FLAG(drv_data);
188 188
189 flag &= ~chip->flag; 189 flag &= ~chip->flag;
@@ -196,7 +196,7 @@ static void bfin_spi_cs_active(struct master_data *drv_data, struct slave_data *
196 196
197static void bfin_spi_cs_deactive(struct master_data *drv_data, struct slave_data *chip) 197static void bfin_spi_cs_deactive(struct master_data *drv_data, struct slave_data *chip)
198{ 198{
199 if (likely(chip->chip_select_num)) { 199 if (likely(chip->chip_select_num < MAX_CTRL_CS)) {
200 u16 flag = read_FLAG(drv_data); 200 u16 flag = read_FLAG(drv_data);
201 201
202 flag |= chip->flag; 202 flag |= chip->flag;
@@ -214,20 +214,24 @@ static void bfin_spi_cs_deactive(struct master_data *drv_data, struct slave_data
214/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */ 214/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */
215static inline void bfin_spi_cs_enable(struct master_data *drv_data, struct slave_data *chip) 215static inline void bfin_spi_cs_enable(struct master_data *drv_data, struct slave_data *chip)
216{ 216{
217 u16 flag = read_FLAG(drv_data); 217 if (chip->chip_select_num < MAX_CTRL_CS) {
218 u16 flag = read_FLAG(drv_data);
218 219
219 flag |= (chip->flag >> 8); 220 flag |= (chip->flag >> 8);
220 221
221 write_FLAG(drv_data, flag); 222 write_FLAG(drv_data, flag);
223 }
222} 224}
223 225
224static inline void bfin_spi_cs_disable(struct master_data *drv_data, struct slave_data *chip) 226static inline void bfin_spi_cs_disable(struct master_data *drv_data, struct slave_data *chip)
225{ 227{
226 u16 flag = read_FLAG(drv_data); 228 if (chip->chip_select_num < MAX_CTRL_CS) {
229 u16 flag = read_FLAG(drv_data);
227 230
228 flag &= ~(chip->flag >> 8); 231 flag &= ~(chip->flag >> 8);
229 232
230 write_FLAG(drv_data, flag); 233 write_FLAG(drv_data, flag);
234 }
231} 235}
232 236
233/* stop controller and re-config current chip*/ 237/* stop controller and re-config current chip*/
@@ -1016,7 +1020,6 @@ static int bfin_spi_setup(struct spi_device *spi)
1016 chip->ctl_reg = chip_info->ctl_reg; 1020 chip->ctl_reg = chip_info->ctl_reg;
1017 chip->bits_per_word = chip_info->bits_per_word; 1021 chip->bits_per_word = chip_info->bits_per_word;
1018 chip->cs_chg_udelay = chip_info->cs_chg_udelay; 1022 chip->cs_chg_udelay = chip_info->cs_chg_udelay;
1019 chip->cs_gpio = chip_info->cs_gpio;
1020 chip->idle_tx_val = chip_info->idle_tx_val; 1023 chip->idle_tx_val = chip_info->idle_tx_val;
1021 chip->pio_interrupt = chip_info->pio_interrupt; 1024 chip->pio_interrupt = chip_info->pio_interrupt;
1022 } 1025 }
@@ -1036,8 +1039,11 @@ static int bfin_spi_setup(struct spi_device *spi)
1036 * SPI_BAUD, not the real baudrate 1039 * SPI_BAUD, not the real baudrate
1037 */ 1040 */
1038 chip->baud = hz_to_spi_baud(spi->max_speed_hz); 1041 chip->baud = hz_to_spi_baud(spi->max_speed_hz);
1039 chip->flag = (1 << (spi->chip_select)) << 8;
1040 chip->chip_select_num = spi->chip_select; 1042 chip->chip_select_num = spi->chip_select;
1043 if (chip->chip_select_num < MAX_CTRL_CS)
1044 chip->flag = (1 << spi->chip_select) << 8;
1045 else
1046 chip->cs_gpio = chip->chip_select_num - MAX_CTRL_CS;
1041 1047
1042 switch (chip->bits_per_word) { 1048 switch (chip->bits_per_word) {
1043 case 8: 1049 case 8:
@@ -1098,7 +1104,7 @@ static int bfin_spi_setup(struct spi_device *spi)
1098 disable_irq(drv_data->spi_irq); 1104 disable_irq(drv_data->spi_irq);
1099 } 1105 }
1100 1106
1101 if (chip->chip_select_num == 0) { 1107 if (chip->chip_select_num >= MAX_CTRL_CS) {
1102 ret = gpio_request(chip->cs_gpio, spi->modalias); 1108 ret = gpio_request(chip->cs_gpio, spi->modalias);
1103 if (ret) { 1109 if (ret) {
1104 dev_err(&spi->dev, "gpio_request() error\n"); 1110 dev_err(&spi->dev, "gpio_request() error\n");
@@ -1115,8 +1121,7 @@ static int bfin_spi_setup(struct spi_device *spi)
1115 spi_set_ctldata(spi, chip); 1121 spi_set_ctldata(spi, chip);
1116 1122
1117 dev_dbg(&spi->dev, "chip select number is %d\n", chip->chip_select_num); 1123 dev_dbg(&spi->dev, "chip select number is %d\n", chip->chip_select_num);
1118 if (chip->chip_select_num > 0 && 1124 if (chip->chip_select_num < MAX_CTRL_CS) {
1119 chip->chip_select_num <= spi->master->num_chipselect) {
1120 ret = peripheral_request(ssel[spi->master->bus_num] 1125 ret = peripheral_request(ssel[spi->master->bus_num]
1121 [chip->chip_select_num-1], spi->modalias); 1126 [chip->chip_select_num-1], spi->modalias);
1122 if (ret) { 1127 if (ret) {
@@ -1131,7 +1136,7 @@ static int bfin_spi_setup(struct spi_device *spi)
1131 return 0; 1136 return 0;
1132 1137
1133 pin_error: 1138 pin_error:
1134 if (chip->chip_select_num == 0) 1139 if (chip->chip_select_num >= MAX_CTRL_CS)
1135 gpio_free(chip->cs_gpio); 1140 gpio_free(chip->cs_gpio);
1136 else 1141 else
1137 peripheral_free(ssel[spi->master->bus_num] 1142 peripheral_free(ssel[spi->master->bus_num]
@@ -1162,14 +1167,11 @@ static void bfin_spi_cleanup(struct spi_device *spi)
1162 if (!chip) 1167 if (!chip)
1163 return; 1168 return;
1164 1169
1165 if ((chip->chip_select_num > 0) 1170 if (chip->chip_select_num < MAX_CTRL_CS) {
1166 && (chip->chip_select_num <= spi->master->num_chipselect)) {
1167 peripheral_free(ssel[spi->master->bus_num] 1171 peripheral_free(ssel[spi->master->bus_num]
1168 [chip->chip_select_num-1]); 1172 [chip->chip_select_num-1]);
1169 bfin_spi_cs_disable(drv_data, chip); 1173 bfin_spi_cs_disable(drv_data, chip);
1170 } 1174 } else
1171
1172 if (chip->chip_select_num == 0)
1173 gpio_free(chip->cs_gpio); 1175 gpio_free(chip->cs_gpio);
1174 1176
1175 kfree(chip); 1177 kfree(chip);