Commit dccd573bb02aa011a4a7146c02c409ac0bd722a0
Committed by
Linus Torvalds
1 parent
ff294cba8a
Exists in
master
and in
20 other branches
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>
Showing 10 changed files with 66 additions and 21 deletions Side-by-side Diff
drivers/spi/atmel_spi.c
drivers/spi/au1550_spi.c
... | ... | @@ -280,6 +280,9 @@ |
280 | 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 | 286 | static int au1550_spi_setup(struct spi_device *spi) |
284 | 287 | { |
285 | 288 | struct au1550_spi *hw = spi_master_get_devdata(spi->master); |
... | ... | @@ -289,6 +292,12 @@ |
289 | 292 | if (spi->bits_per_word < 4 || spi->bits_per_word > 24) { |
290 | 293 | dev_err(&spi->dev, "setup: invalid bits_per_word=%d\n", |
291 | 294 | spi->bits_per_word); |
295 | + return -EINVAL; | |
296 | + } | |
297 | + | |
298 | + if (spi->mode & ~MODEBITS) { | |
299 | + dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", | |
300 | + spi->mode & ~MODEBITS); | |
292 | 301 | return -EINVAL; |
293 | 302 | } |
294 | 303 |
drivers/spi/mpc52xx_psc_spi.c
... | ... | @@ -270,6 +270,9 @@ |
270 | 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 | 276 | static int mpc52xx_psc_spi_setup(struct spi_device *spi) |
274 | 277 | { |
275 | 278 | struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); |
... | ... | @@ -278,6 +281,12 @@ |
278 | 281 | |
279 | 282 | if (spi->bits_per_word%8) |
280 | 283 | return -EINVAL; |
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 | + } | |
281 | 290 | |
282 | 291 | if (!cs) { |
283 | 292 | cs = kzalloc(sizeof *cs, GFP_KERNEL); |
drivers/spi/omap_uwire.c
... | ... | @@ -445,9 +445,18 @@ |
445 | 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 | 451 | static int uwire_setup(struct spi_device *spi) |
449 | 452 | { |
450 | 453 | struct uwire_state *ust = spi->controller_state; |
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 | + } | |
451 | 460 | |
452 | 461 | if (ust == NULL) { |
453 | 462 | ust = kzalloc(sizeof(*ust), GFP_KERNEL); |
drivers/spi/pxa2xx_spi.c
... | ... | @@ -1067,6 +1067,9 @@ |
1067 | 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 | 1073 | static int setup(struct spi_device *spi) |
1071 | 1074 | { |
1072 | 1075 | struct pxa2xx_spi_chip *chip_info = NULL; |
... | ... | @@ -1090,6 +1093,12 @@ |
1090 | 1093 | dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d " |
1091 | 1094 | "b/w not 4-16 for type PXA25x_SSP\n", |
1092 | 1095 | drv_data->ssp_type, spi->bits_per_word); |
1096 | + return -EINVAL; | |
1097 | + } | |
1098 | + | |
1099 | + if (spi->mode & ~MODEBITS) { | |
1100 | + dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", | |
1101 | + spi->mode & ~MODEBITS); | |
1093 | 1102 | return -EINVAL; |
1094 | 1103 | } |
1095 | 1104 |
drivers/spi/spi_bitbang.c
... | ... | @@ -187,12 +187,10 @@ |
187 | 187 | |
188 | 188 | bitbang = spi_master_get_devdata(spi->master); |
189 | 189 | |
190 | - /* REVISIT: some systems will want to support devices using lsb-first | |
191 | - * bit encodings on the wire. In pure software that would be trivial, | |
192 | - * just bitbang_txrx_le_cphaX() routines shifting the other way, and | |
193 | - * some hardware controllers also have this support. | |
190 | + /* Bitbangers can support SPI_CS_HIGH, SPI_3WIRE, and so on; | |
191 | + * add those to master->flags, and provide the other support. | |
194 | 192 | */ |
195 | - if ((spi->mode & SPI_LSB_FIRST) != 0) | |
193 | + if ((spi->mode & ~(SPI_CPOL|SPI_CPHA|bitbang->flags)) != 0) | |
196 | 194 | return -EINVAL; |
197 | 195 | |
198 | 196 | if (!cs) { |
drivers/spi/spi_imx.c
... | ... | @@ -1163,6 +1163,9 @@ |
1163 | 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 | 1169 | /* On first setup bad values must free chip_data memory since will cause |
1167 | 1170 | spi_new_device to fail. Bad value setup from protocol driver are simply not |
1168 | 1171 | applied and notified to the calling driver. */ |
... | ... | @@ -1174,6 +1177,12 @@ |
1174 | 1177 | u32 tmp; |
1175 | 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 | 1186 | /* Get controller data */ |
1178 | 1187 | chip_info = spi->controller_data; |
1179 | 1188 | |
... | ... | @@ -1245,21 +1254,6 @@ |
1245 | 1254 | |
1246 | 1255 | /* SPI mode */ |
1247 | 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 | 1257 | if (tmp & SPI_CS_HIGH) { |
1264 | 1258 | u32_EDIT(chip->control, |
1265 | 1259 | SPI_CONTROL_SSPOL, SPI_CONTROL_SSPOL_ACT_HIGH); |
drivers/spi/spi_mpc83xx.c
... | ... | @@ -232,11 +232,20 @@ |
232 | 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 | 238 | static int mpc83xx_spi_setup(struct spi_device *spi) |
236 | 239 | { |
237 | 240 | struct spi_bitbang *bitbang; |
238 | 241 | struct mpc83xx_spi *mpc83xx_spi; |
239 | 242 | int retval; |
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 | + } | |
240 | 249 | |
241 | 250 | if (!spi->max_speed_hz) |
242 | 251 | return -EINVAL; |
drivers/spi/spi_s3c24xx.c
... | ... | @@ -146,6 +146,9 @@ |
146 | 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 | 152 | static int s3c24xx_spi_setup(struct spi_device *spi) |
150 | 153 | { |
151 | 154 | int ret; |
152 | 155 | |
... | ... | @@ -153,8 +156,11 @@ |
153 | 156 | if (!spi->bits_per_word) |
154 | 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 | 162 | return -EINVAL; |
163 | + } | |
158 | 164 | |
159 | 165 | ret = s3c24xx_spi_setupxfer(spi, NULL); |
160 | 166 | if (ret < 0) { |