diff options
author | David Brownell <david-b@pacbell.net> | 2007-07-17 07:04:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-17 13:23:04 -0400 |
commit | dccd573bb02aa011a4a7146c02c409ac0bd722a0 (patch) | |
tree | 743eeca4fbbea8272ca4f341b806d776e404d704 | |
parent | ff294cba8a62fa8334b88692da6d48683900f015 (diff) |
SPI controller drivers: check for unsupported modes
Minor SPI controller driver updates: make the setup() methods reject
spi->mode bits they don't support, by masking aginst the inverse of bits
they *do* support. This insures against misbehavior later when new mode
bits get added.
Most controllers can't support SPI_LSB_FIRST; more handle SPI_CS_HIGH.
Support for all four SPI clock/transfer modes is routine.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/spi/atmel_spi.c | 1 | ||||
-rw-r--r-- | drivers/spi/au1550_spi.c | 9 | ||||
-rw-r--r-- | drivers/spi/mpc52xx_psc_spi.c | 9 | ||||
-rw-r--r-- | drivers/spi/omap_uwire.c | 9 | ||||
-rw-r--r-- | drivers/spi/pxa2xx_spi.c | 9 | ||||
-rw-r--r-- | drivers/spi/spi_bitbang.c | 8 | ||||
-rw-r--r-- | drivers/spi/spi_imx.c | 24 | ||||
-rw-r--r-- | drivers/spi/spi_mpc83xx.c | 9 | ||||
-rw-r--r-- | drivers/spi/spi_s3c24xx.c | 8 | ||||
-rw-r--r-- | include/linux/spi/spi_bitbang.h | 1 |
10 files changed, 66 insertions, 21 deletions
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 8b2601de3630..7524a84bdd50 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c | |||
@@ -350,6 +350,7 @@ atmel_spi_interrupt(int irq, void *dev_id) | |||
350 | return ret; | 350 | return ret; |
351 | } | 351 | } |
352 | 352 | ||
353 | /* the spi->mode bits understood by this driver: */ | ||
353 | #define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) | 354 | #define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) |
354 | 355 | ||
355 | static int atmel_spi_setup(struct spi_device *spi) | 356 | static int atmel_spi_setup(struct spi_device *spi) |
diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c index ae2b1af0dba4..c47a650183a1 100644 --- a/drivers/spi/au1550_spi.c +++ b/drivers/spi/au1550_spi.c | |||
@@ -280,6 +280,9 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t) | |||
280 | return 0; | 280 | return 0; |
281 | } | 281 | } |
282 | 282 | ||
283 | /* the spi->mode bits understood by this driver: */ | ||
284 | #define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST) | ||
285 | |||
283 | static int au1550_spi_setup(struct spi_device *spi) | 286 | static int au1550_spi_setup(struct spi_device *spi) |
284 | { | 287 | { |
285 | struct au1550_spi *hw = spi_master_get_devdata(spi->master); | 288 | struct au1550_spi *hw = spi_master_get_devdata(spi->master); |
@@ -292,6 +295,12 @@ static int au1550_spi_setup(struct spi_device *spi) | |||
292 | return -EINVAL; | 295 | return -EINVAL; |
293 | } | 296 | } |
294 | 297 | ||
298 | if (spi->mode & ~MODEBITS) { | ||
299 | dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", | ||
300 | spi->mode & ~MODEBITS); | ||
301 | return -EINVAL; | ||
302 | } | ||
303 | |||
295 | if (spi->max_speed_hz == 0) | 304 | if (spi->max_speed_hz == 0) |
296 | spi->max_speed_hz = hw->freq_max; | 305 | spi->max_speed_hz = hw->freq_max; |
297 | if (spi->max_speed_hz > hw->freq_max | 306 | if (spi->max_speed_hz > hw->freq_max |
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c index 11f36bef3057..d2a4b2bdb07b 100644 --- a/drivers/spi/mpc52xx_psc_spi.c +++ b/drivers/spi/mpc52xx_psc_spi.c | |||
@@ -270,6 +270,9 @@ static void mpc52xx_psc_spi_work(struct work_struct *work) | |||
270 | spin_unlock_irq(&mps->lock); | 270 | spin_unlock_irq(&mps->lock); |
271 | } | 271 | } |
272 | 272 | ||
273 | /* the spi->mode bits understood by this driver: */ | ||
274 | #define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST) | ||
275 | |||
273 | static int mpc52xx_psc_spi_setup(struct spi_device *spi) | 276 | static int mpc52xx_psc_spi_setup(struct spi_device *spi) |
274 | { | 277 | { |
275 | struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); | 278 | struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); |
@@ -279,6 +282,12 @@ static int mpc52xx_psc_spi_setup(struct spi_device *spi) | |||
279 | if (spi->bits_per_word%8) | 282 | if (spi->bits_per_word%8) |
280 | return -EINVAL; | 283 | return -EINVAL; |
281 | 284 | ||
285 | if (spi->mode & ~MODEBITS) { | ||
286 | dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", | ||
287 | spi->mode & ~MODEBITS); | ||
288 | return -EINVAL; | ||
289 | } | ||
290 | |||
282 | if (!cs) { | 291 | if (!cs) { |
283 | cs = kzalloc(sizeof *cs, GFP_KERNEL); | 292 | cs = kzalloc(sizeof *cs, GFP_KERNEL); |
284 | if (!cs) | 293 | if (!cs) |
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c index 95183e1df525..d275c615a73e 100644 --- a/drivers/spi/omap_uwire.c +++ b/drivers/spi/omap_uwire.c | |||
@@ -445,10 +445,19 @@ done: | |||
445 | return status; | 445 | return status; |
446 | } | 446 | } |
447 | 447 | ||
448 | /* the spi->mode bits understood by this driver: */ | ||
449 | #define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) | ||
450 | |||
448 | static int uwire_setup(struct spi_device *spi) | 451 | static int uwire_setup(struct spi_device *spi) |
449 | { | 452 | { |
450 | struct uwire_state *ust = spi->controller_state; | 453 | struct uwire_state *ust = spi->controller_state; |
451 | 454 | ||
455 | if (spi->mode & ~MODEBITS) { | ||
456 | dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", | ||
457 | spi->mode & ~MODEBITS); | ||
458 | return -EINVAL; | ||
459 | } | ||
460 | |||
452 | if (ust == NULL) { | 461 | if (ust == NULL) { |
453 | ust = kzalloc(sizeof(*ust), GFP_KERNEL); | 462 | ust = kzalloc(sizeof(*ust), GFP_KERNEL); |
454 | if (ust == NULL) | 463 | if (ust == NULL) |
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 9f2c887ffa04..e51311b2da0b 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c | |||
@@ -1067,6 +1067,9 @@ static int transfer(struct spi_device *spi, struct spi_message *msg) | |||
1067 | return 0; | 1067 | return 0; |
1068 | } | 1068 | } |
1069 | 1069 | ||
1070 | /* the spi->mode bits understood by this driver: */ | ||
1071 | #define MODEBITS (SPI_CPOL | SPI_CPHA) | ||
1072 | |||
1070 | static int setup(struct spi_device *spi) | 1073 | static int setup(struct spi_device *spi) |
1071 | { | 1074 | { |
1072 | struct pxa2xx_spi_chip *chip_info = NULL; | 1075 | struct pxa2xx_spi_chip *chip_info = NULL; |
@@ -1093,6 +1096,12 @@ static int setup(struct spi_device *spi) | |||
1093 | return -EINVAL; | 1096 | return -EINVAL; |
1094 | } | 1097 | } |
1095 | 1098 | ||
1099 | if (spi->mode & ~MODEBITS) { | ||
1100 | dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", | ||
1101 | spi->mode & ~MODEBITS); | ||
1102 | return -EINVAL; | ||
1103 | } | ||
1104 | |||
1096 | /* Only alloc on first setup */ | 1105 | /* Only alloc on first setup */ |
1097 | chip = spi_get_ctldata(spi); | 1106 | chip = spi_get_ctldata(spi); |
1098 | if (!chip) { | 1107 | if (!chip) { |
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index 88425e1af4d3..0c85c984ccb4 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c | |||
@@ -187,12 +187,10 @@ int spi_bitbang_setup(struct spi_device *spi) | |||
187 | 187 | ||
188 | bitbang = spi_master_get_devdata(spi->master); | 188 | bitbang = spi_master_get_devdata(spi->master); |
189 | 189 | ||
190 | /* REVISIT: some systems will want to support devices using lsb-first | 190 | /* Bitbangers can support SPI_CS_HIGH, SPI_3WIRE, and so on; |
191 | * bit encodings on the wire. In pure software that would be trivial, | 191 | * add those to master->flags, and provide the other support. |
192 | * just bitbang_txrx_le_cphaX() routines shifting the other way, and | ||
193 | * some hardware controllers also have this support. | ||
194 | */ | 192 | */ |
195 | if ((spi->mode & SPI_LSB_FIRST) != 0) | 193 | if ((spi->mode & ~(SPI_CPOL|SPI_CPHA|bitbang->flags)) != 0) |
196 | return -EINVAL; | 194 | return -EINVAL; |
197 | 195 | ||
198 | if (!cs) { | 196 | if (!cs) { |
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c index 656be4a5094a..aee9ad6f633c 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c | |||
@@ -1163,6 +1163,9 @@ msg_rejected: | |||
1163 | return -EINVAL; | 1163 | return -EINVAL; |
1164 | } | 1164 | } |
1165 | 1165 | ||
1166 | /* the spi->mode bits understood by this driver: */ | ||
1167 | #define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) | ||
1168 | |||
1166 | /* On first setup bad values must free chip_data memory since will cause | 1169 | /* On first setup bad values must free chip_data memory since will cause |
1167 | spi_new_device to fail. Bad value setup from protocol driver are simply not | 1170 | spi_new_device to fail. Bad value setup from protocol driver are simply not |
1168 | applied and notified to the calling driver. */ | 1171 | applied and notified to the calling driver. */ |
@@ -1174,6 +1177,12 @@ static int setup(struct spi_device *spi) | |||
1174 | u32 tmp; | 1177 | u32 tmp; |
1175 | int status = 0; | 1178 | int status = 0; |
1176 | 1179 | ||
1180 | if (spi->mode & ~MODEBITS) { | ||
1181 | dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", | ||
1182 | spi->mode & ~MODEBITS); | ||
1183 | return -EINVAL; | ||
1184 | } | ||
1185 | |||
1177 | /* Get controller data */ | 1186 | /* Get controller data */ |
1178 | chip_info = spi->controller_data; | 1187 | chip_info = spi->controller_data; |
1179 | 1188 | ||
@@ -1245,21 +1254,6 @@ static int setup(struct spi_device *spi) | |||
1245 | 1254 | ||
1246 | /* SPI mode */ | 1255 | /* SPI mode */ |
1247 | tmp = spi->mode; | 1256 | tmp = spi->mode; |
1248 | if (tmp & SPI_LSB_FIRST) { | ||
1249 | status = -EINVAL; | ||
1250 | if (first_setup) { | ||
1251 | dev_err(&spi->dev, | ||
1252 | "setup - " | ||
1253 | "HW doesn't support LSB first transfer\n"); | ||
1254 | goto err_first_setup; | ||
1255 | } else { | ||
1256 | dev_err(&spi->dev, | ||
1257 | "setup - " | ||
1258 | "HW doesn't support LSB first transfer, " | ||
1259 | "default to MSB first\n"); | ||
1260 | spi->mode &= ~SPI_LSB_FIRST; | ||
1261 | } | ||
1262 | } | ||
1263 | if (tmp & SPI_CS_HIGH) { | 1257 | if (tmp & SPI_CS_HIGH) { |
1264 | u32_EDIT(chip->control, | 1258 | u32_EDIT(chip->control, |
1265 | SPI_CONTROL_SSPOL, SPI_CONTROL_SSPOL_ACT_HIGH); | 1259 | SPI_CONTROL_SSPOL, SPI_CONTROL_SSPOL_ACT_HIGH); |
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c index e9798bf7b8c6..9cdbc12278e5 100644 --- a/drivers/spi/spi_mpc83xx.c +++ b/drivers/spi/spi_mpc83xx.c | |||
@@ -232,12 +232,21 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
232 | return 0; | 232 | return 0; |
233 | } | 233 | } |
234 | 234 | ||
235 | /* the spi->mode bits understood by this driver: */ | ||
236 | #define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) | ||
237 | |||
235 | static int mpc83xx_spi_setup(struct spi_device *spi) | 238 | static int mpc83xx_spi_setup(struct spi_device *spi) |
236 | { | 239 | { |
237 | struct spi_bitbang *bitbang; | 240 | struct spi_bitbang *bitbang; |
238 | struct mpc83xx_spi *mpc83xx_spi; | 241 | struct mpc83xx_spi *mpc83xx_spi; |
239 | int retval; | 242 | int retval; |
240 | 243 | ||
244 | if (spi->mode & ~MODEBITS) { | ||
245 | dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", | ||
246 | spi->mode & ~MODEBITS); | ||
247 | return -EINVAL; | ||
248 | } | ||
249 | |||
241 | if (!spi->max_speed_hz) | 250 | if (!spi->max_speed_hz) |
242 | return -EINVAL; | 251 | return -EINVAL; |
243 | 252 | ||
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index d5a710f6e445..7071ff8da63e 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c | |||
@@ -146,6 +146,9 @@ static int s3c24xx_spi_setupxfer(struct spi_device *spi, | |||
146 | return 0; | 146 | return 0; |
147 | } | 147 | } |
148 | 148 | ||
149 | /* the spi->mode bits understood by this driver: */ | ||
150 | #define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) | ||
151 | |||
149 | static int s3c24xx_spi_setup(struct spi_device *spi) | 152 | static int s3c24xx_spi_setup(struct spi_device *spi) |
150 | { | 153 | { |
151 | int ret; | 154 | int ret; |
@@ -153,8 +156,11 @@ static int s3c24xx_spi_setup(struct spi_device *spi) | |||
153 | if (!spi->bits_per_word) | 156 | if (!spi->bits_per_word) |
154 | spi->bits_per_word = 8; | 157 | spi->bits_per_word = 8; |
155 | 158 | ||
156 | if ((spi->mode & SPI_LSB_FIRST) != 0) | 159 | if (spi->mode & ~MODEBITS) { |
160 | dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", | ||
161 | spi->mode & ~MODEBITS); | ||
157 | return -EINVAL; | 162 | return -EINVAL; |
163 | } | ||
158 | 164 | ||
159 | ret = s3c24xx_spi_setupxfer(spi, NULL); | 165 | ret = s3c24xx_spi_setupxfer(spi, NULL); |
160 | if (ret < 0) { | 166 | if (ret < 0) { |
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h index 9dbca629dcfb..b8db32cea1de 100644 --- a/include/linux/spi/spi_bitbang.h +++ b/include/linux/spi/spi_bitbang.h | |||
@@ -26,6 +26,7 @@ struct spi_bitbang { | |||
26 | struct list_head queue; | 26 | struct list_head queue; |
27 | u8 busy; | 27 | u8 busy; |
28 | u8 use_dma; | 28 | u8 use_dma; |
29 | u8 flags; /* extra spi->mode support */ | ||
29 | 30 | ||
30 | struct spi_master *master; | 31 | struct spi_master *master; |
31 | 32 | ||