diff options
| author | Michal Marek <mmarek@suse.cz> | 2010-08-20 07:53:08 -0400 |
|---|---|---|
| committer | Michal Marek <mmarek@suse.cz> | 2010-08-20 07:53:08 -0400 |
| commit | e981b060767b3c4ac9393ad8d2558d648e35dfcb (patch) | |
| tree | 9c05eaec3072be3645dda61d35085d152b9d5954 /drivers/spi/spi_gpio.c | |
| parent | 3c955b407a084810f57260d61548cc92c14bc627 (diff) | |
| parent | da5cabf80e2433131bf0ed8993abc0f7ea618c73 (diff) | |
Merge commit 'v2.6.36-rc1' into kbuild/rc-fixes
Diffstat (limited to 'drivers/spi/spi_gpio.c')
| -rw-r--r-- | drivers/spi/spi_gpio.c | 109 |
1 files changed, 87 insertions, 22 deletions
diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c index 7edbd5807e0e..e24a63498acb 100644 --- a/drivers/spi/spi_gpio.c +++ b/drivers/spi/spi_gpio.c | |||
| @@ -146,25 +146,63 @@ static inline int getmiso(const struct spi_device *spi) | |||
| 146 | static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi, | 146 | static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi, |
| 147 | unsigned nsecs, u32 word, u8 bits) | 147 | unsigned nsecs, u32 word, u8 bits) |
| 148 | { | 148 | { |
| 149 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); | 149 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi, | 152 | static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi, |
| 153 | unsigned nsecs, u32 word, u8 bits) | 153 | unsigned nsecs, u32 word, u8 bits) |
| 154 | { | 154 | { |
| 155 | return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); | 155 | return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits); |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi, | 158 | static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi, |
| 159 | unsigned nsecs, u32 word, u8 bits) | 159 | unsigned nsecs, u32 word, u8 bits) |
| 160 | { | 160 | { |
| 161 | return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits); | 161 | return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits); |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi, | 164 | static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi, |
| 165 | unsigned nsecs, u32 word, u8 bits) | 165 | unsigned nsecs, u32 word, u8 bits) |
| 166 | { | 166 | { |
| 167 | return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits); | 167 | return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits); |
| 168 | } | ||
| 169 | |||
| 170 | /* | ||
| 171 | * These functions do not call setmosi or getmiso if respective flag | ||
| 172 | * (SPI_MASTER_NO_RX or SPI_MASTER_NO_TX) is set, so they are safe to | ||
| 173 | * call when such pin is not present or defined in the controller. | ||
| 174 | * A separate set of callbacks is defined to get highest possible | ||
| 175 | * speed in the generic case (when both MISO and MOSI lines are | ||
| 176 | * available), as optimiser will remove the checks when argument is | ||
| 177 | * constant. | ||
| 178 | */ | ||
| 179 | |||
| 180 | static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi, | ||
| 181 | unsigned nsecs, u32 word, u8 bits) | ||
| 182 | { | ||
| 183 | unsigned flags = spi->master->flags; | ||
| 184 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits); | ||
| 185 | } | ||
| 186 | |||
| 187 | static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi, | ||
| 188 | unsigned nsecs, u32 word, u8 bits) | ||
| 189 | { | ||
| 190 | unsigned flags = spi->master->flags; | ||
| 191 | return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits); | ||
| 192 | } | ||
| 193 | |||
| 194 | static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi, | ||
| 195 | unsigned nsecs, u32 word, u8 bits) | ||
| 196 | { | ||
| 197 | unsigned flags = spi->master->flags; | ||
| 198 | return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits); | ||
| 199 | } | ||
| 200 | |||
| 201 | static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi, | ||
| 202 | unsigned nsecs, u32 word, u8 bits) | ||
| 203 | { | ||
| 204 | unsigned flags = spi->master->flags; | ||
| 205 | return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits); | ||
| 168 | } | 206 | } |
| 169 | 207 | ||
| 170 | /*----------------------------------------------------------------------*/ | 208 | /*----------------------------------------------------------------------*/ |
| @@ -232,19 +270,30 @@ static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in) | |||
| 232 | } | 270 | } |
| 233 | 271 | ||
| 234 | static int __init | 272 | static int __init |
| 235 | spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label) | 273 | spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label, |
| 274 | u16 *res_flags) | ||
| 236 | { | 275 | { |
| 237 | int value; | 276 | int value; |
| 238 | 277 | ||
| 239 | /* NOTE: SPI_*_GPIO symbols may reference "pdata" */ | 278 | /* NOTE: SPI_*_GPIO symbols may reference "pdata" */ |
| 240 | 279 | ||
| 241 | value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false); | 280 | if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) { |
| 242 | if (value) | 281 | value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false); |
| 243 | goto done; | 282 | if (value) |
| 283 | goto done; | ||
| 284 | } else { | ||
| 285 | /* HW configuration without MOSI pin */ | ||
| 286 | *res_flags |= SPI_MASTER_NO_TX; | ||
| 287 | } | ||
| 244 | 288 | ||
| 245 | value = spi_gpio_alloc(SPI_MISO_GPIO, label, true); | 289 | if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) { |
| 246 | if (value) | 290 | value = spi_gpio_alloc(SPI_MISO_GPIO, label, true); |
| 247 | goto free_mosi; | 291 | if (value) |
| 292 | goto free_mosi; | ||
| 293 | } else { | ||
| 294 | /* HW configuration without MISO pin */ | ||
| 295 | *res_flags |= SPI_MASTER_NO_RX; | ||
| 296 | } | ||
| 248 | 297 | ||
| 249 | value = spi_gpio_alloc(SPI_SCK_GPIO, label, false); | 298 | value = spi_gpio_alloc(SPI_SCK_GPIO, label, false); |
| 250 | if (value) | 299 | if (value) |
| @@ -253,9 +302,11 @@ spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label) | |||
| 253 | goto done; | 302 | goto done; |
| 254 | 303 | ||
| 255 | free_miso: | 304 | free_miso: |
| 256 | gpio_free(SPI_MISO_GPIO); | 305 | if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) |
| 306 | gpio_free(SPI_MISO_GPIO); | ||
| 257 | free_mosi: | 307 | free_mosi: |
| 258 | gpio_free(SPI_MOSI_GPIO); | 308 | if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) |
| 309 | gpio_free(SPI_MOSI_GPIO); | ||
| 259 | done: | 310 | done: |
| 260 | return value; | 311 | return value; |
| 261 | } | 312 | } |
| @@ -266,6 +317,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) | |||
| 266 | struct spi_master *master; | 317 | struct spi_master *master; |
| 267 | struct spi_gpio *spi_gpio; | 318 | struct spi_gpio *spi_gpio; |
| 268 | struct spi_gpio_platform_data *pdata; | 319 | struct spi_gpio_platform_data *pdata; |
| 320 | u16 master_flags = 0; | ||
| 269 | 321 | ||
| 270 | pdata = pdev->dev.platform_data; | 322 | pdata = pdev->dev.platform_data; |
| 271 | #ifdef GENERIC_BITBANG | 323 | #ifdef GENERIC_BITBANG |
| @@ -273,7 +325,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) | |||
| 273 | return -ENODEV; | 325 | return -ENODEV; |
| 274 | #endif | 326 | #endif |
| 275 | 327 | ||
| 276 | status = spi_gpio_request(pdata, dev_name(&pdev->dev)); | 328 | status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags); |
| 277 | if (status < 0) | 329 | if (status < 0) |
| 278 | return status; | 330 | return status; |
| 279 | 331 | ||
| @@ -289,6 +341,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) | |||
| 289 | if (pdata) | 341 | if (pdata) |
| 290 | spi_gpio->pdata = *pdata; | 342 | spi_gpio->pdata = *pdata; |
| 291 | 343 | ||
| 344 | master->flags = master_flags; | ||
| 292 | master->bus_num = pdev->id; | 345 | master->bus_num = pdev->id; |
| 293 | master->num_chipselect = SPI_N_CHIPSEL; | 346 | master->num_chipselect = SPI_N_CHIPSEL; |
| 294 | master->setup = spi_gpio_setup; | 347 | master->setup = spi_gpio_setup; |
| @@ -296,10 +349,18 @@ static int __init spi_gpio_probe(struct platform_device *pdev) | |||
| 296 | 349 | ||
| 297 | spi_gpio->bitbang.master = spi_master_get(master); | 350 | spi_gpio->bitbang.master = spi_master_get(master); |
| 298 | spi_gpio->bitbang.chipselect = spi_gpio_chipselect; | 351 | spi_gpio->bitbang.chipselect = spi_gpio_chipselect; |
| 299 | spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0; | 352 | |
| 300 | spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1; | 353 | if ((master_flags & (SPI_MASTER_NO_RX | SPI_MASTER_NO_RX)) == 0) { |
| 301 | spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2; | 354 | spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0; |
| 302 | spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3; | 355 | spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1; |
| 356 | spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2; | ||
| 357 | spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3; | ||
| 358 | } else { | ||
| 359 | spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0; | ||
| 360 | spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1; | ||
| 361 | spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2; | ||
| 362 | spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3; | ||
| 363 | } | ||
| 303 | spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer; | 364 | spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer; |
| 304 | spi_gpio->bitbang.flags = SPI_CS_HIGH; | 365 | spi_gpio->bitbang.flags = SPI_CS_HIGH; |
| 305 | 366 | ||
| @@ -307,8 +368,10 @@ static int __init spi_gpio_probe(struct platform_device *pdev) | |||
| 307 | if (status < 0) { | 368 | if (status < 0) { |
| 308 | spi_master_put(spi_gpio->bitbang.master); | 369 | spi_master_put(spi_gpio->bitbang.master); |
| 309 | gpio_free: | 370 | gpio_free: |
| 310 | gpio_free(SPI_MISO_GPIO); | 371 | if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) |
| 311 | gpio_free(SPI_MOSI_GPIO); | 372 | gpio_free(SPI_MISO_GPIO); |
| 373 | if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) | ||
| 374 | gpio_free(SPI_MOSI_GPIO); | ||
| 312 | gpio_free(SPI_SCK_GPIO); | 375 | gpio_free(SPI_SCK_GPIO); |
| 313 | spi_master_put(master); | 376 | spi_master_put(master); |
| 314 | } | 377 | } |
| @@ -331,8 +394,10 @@ static int __exit spi_gpio_remove(struct platform_device *pdev) | |||
| 331 | 394 | ||
| 332 | platform_set_drvdata(pdev, NULL); | 395 | platform_set_drvdata(pdev, NULL); |
| 333 | 396 | ||
| 334 | gpio_free(SPI_MISO_GPIO); | 397 | if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) |
| 335 | gpio_free(SPI_MOSI_GPIO); | 398 | gpio_free(SPI_MISO_GPIO); |
| 399 | if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) | ||
| 400 | gpio_free(SPI_MOSI_GPIO); | ||
| 336 | gpio_free(SPI_SCK_GPIO); | 401 | gpio_free(SPI_SCK_GPIO); |
| 337 | 402 | ||
| 338 | return status; | 403 | return status; |
