diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-14 13:22:11 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-14 13:22:11 -0500 |
commit | 478e4e9d7a618379676b17e64583ff3622f2fec5 (patch) | |
tree | 1f25c96499abbb0d0b47f75aa92134209fcc4ee8 /drivers/spi/mpc52xx_spi.c | |
parent | 2205afa7d13ec716935dfd4b8ff71059ee7aeb0c (diff) | |
parent | 965346e3b99e2c5f51bd1325ddd0257227000355 (diff) |
Merge branch 'next-spi' of git://git.secretlab.ca/git/linux-2.6
* 'next-spi' of git://git.secretlab.ca/git/linux-2.6: (23 commits)
spi: fix probe/remove section markings
Add OMAP spi100k driver
spi-imx: don't access struct device directly but use dev_get_platdata
spi-imx: Add mx25 support
spi-imx: use positive logic to distinguish cpu variants
spi-imx: correct check for platform_get_irq failing
ARM: NUC900: Add spi driver support for nuc900
spi: SuperH MSIOF SPI Master driver V2
spi: fix spidev compilation failure when VERBOSE is defined
spi/au1550_spi: fix setupxfer not to override cfg with zeros
spi/mpc8xxx: don't use __exit_p to wrap plat_mpc8xxx_spi_remove
spi/i.MX: fix broken error handling for gpio_request
spi/i.mx: drain MXC SPI transfer buffer when probing device
MAINTAINERS: add SPI co-maintainer.
spi/xilinx_spi: fix incorrect casting
spi/mpc52xx-spi: minor cleanups
xilinx_spi: add a platform driver using the xilinx_spi common module.
xilinx_spi: add support for the DS570 IP.
xilinx_spi: Switch to iomem functions and support little endian.
xilinx_spi: Split into of driver and generic part.
...
Diffstat (limited to 'drivers/spi/mpc52xx_spi.c')
-rw-r--r-- | drivers/spi/mpc52xx_spi.c | 86 |
1 files changed, 72 insertions, 14 deletions
diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/mpc52xx_spi.c index ef8379b2c172..45bfe6458173 100644 --- a/drivers/spi/mpc52xx_spi.c +++ b/drivers/spi/mpc52xx_spi.c | |||
@@ -18,9 +18,9 @@ | |||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
21 | #include <linux/spi/mpc52xx_spi.h> | ||
22 | #include <linux/of_spi.h> | 21 | #include <linux/of_spi.h> |
23 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/of_gpio.h> | ||
24 | #include <asm/time.h> | 24 | #include <asm/time.h> |
25 | #include <asm/mpc52xx.h> | 25 | #include <asm/mpc52xx.h> |
26 | 26 | ||
@@ -53,7 +53,7 @@ MODULE_LICENSE("GPL"); | |||
53 | /* FSM state return values */ | 53 | /* FSM state return values */ |
54 | #define FSM_STOP 0 /* Nothing more for the state machine to */ | 54 | #define FSM_STOP 0 /* Nothing more for the state machine to */ |
55 | /* do. If something interesting happens */ | 55 | /* do. If something interesting happens */ |
56 | /* then and IRQ will be received */ | 56 | /* then an IRQ will be received */ |
57 | #define FSM_POLL 1 /* need to poll for completion, an IRQ is */ | 57 | #define FSM_POLL 1 /* need to poll for completion, an IRQ is */ |
58 | /* not expected */ | 58 | /* not expected */ |
59 | #define FSM_CONTINUE 2 /* Keep iterating the state machine */ | 59 | #define FSM_CONTINUE 2 /* Keep iterating the state machine */ |
@@ -61,13 +61,12 @@ MODULE_LICENSE("GPL"); | |||
61 | /* Driver internal data */ | 61 | /* Driver internal data */ |
62 | struct mpc52xx_spi { | 62 | struct mpc52xx_spi { |
63 | struct spi_master *master; | 63 | struct spi_master *master; |
64 | u32 sysclk; | ||
65 | void __iomem *regs; | 64 | void __iomem *regs; |
66 | int irq0; /* MODF irq */ | 65 | int irq0; /* MODF irq */ |
67 | int irq1; /* SPIF irq */ | 66 | int irq1; /* SPIF irq */ |
68 | int ipb_freq; | 67 | unsigned int ipb_freq; |
69 | 68 | ||
70 | /* Statistics */ | 69 | /* Statistics; not used now, but will be reintroduced for debugfs */ |
71 | int msg_count; | 70 | int msg_count; |
72 | int wcol_count; | 71 | int wcol_count; |
73 | int wcol_ticks; | 72 | int wcol_ticks; |
@@ -79,7 +78,6 @@ struct mpc52xx_spi { | |||
79 | spinlock_t lock; | 78 | spinlock_t lock; |
80 | struct work_struct work; | 79 | struct work_struct work; |
81 | 80 | ||
82 | |||
83 | /* Details of current transfer (length, and buffer pointers) */ | 81 | /* Details of current transfer (length, and buffer pointers) */ |
84 | struct spi_message *message; /* current message */ | 82 | struct spi_message *message; /* current message */ |
85 | struct spi_transfer *transfer; /* current transfer */ | 83 | struct spi_transfer *transfer; /* current transfer */ |
@@ -89,6 +87,8 @@ struct mpc52xx_spi { | |||
89 | u8 *rx_buf; | 87 | u8 *rx_buf; |
90 | const u8 *tx_buf; | 88 | const u8 *tx_buf; |
91 | int cs_change; | 89 | int cs_change; |
90 | int gpio_cs_count; | ||
91 | unsigned int *gpio_cs; | ||
92 | }; | 92 | }; |
93 | 93 | ||
94 | /* | 94 | /* |
@@ -96,7 +96,13 @@ struct mpc52xx_spi { | |||
96 | */ | 96 | */ |
97 | static void mpc52xx_spi_chipsel(struct mpc52xx_spi *ms, int value) | 97 | static void mpc52xx_spi_chipsel(struct mpc52xx_spi *ms, int value) |
98 | { | 98 | { |
99 | out_8(ms->regs + SPI_PORTDATA, value ? 0 : 0x08); | 99 | int cs; |
100 | |||
101 | if (ms->gpio_cs_count > 0) { | ||
102 | cs = ms->message->spi->chip_select; | ||
103 | gpio_set_value(ms->gpio_cs[cs], value ? 0 : 1); | ||
104 | } else | ||
105 | out_8(ms->regs + SPI_PORTDATA, value ? 0 : 0x08); | ||
100 | } | 106 | } |
101 | 107 | ||
102 | /* | 108 | /* |
@@ -221,7 +227,7 @@ static int mpc52xx_spi_fsmstate_transfer(int irq, struct mpc52xx_spi *ms, | |||
221 | ms->wcol_tx_timestamp = get_tbl(); | 227 | ms->wcol_tx_timestamp = get_tbl(); |
222 | data = 0; | 228 | data = 0; |
223 | if (ms->tx_buf) | 229 | if (ms->tx_buf) |
224 | data = *(ms->tx_buf-1); | 230 | data = *(ms->tx_buf - 1); |
225 | out_8(ms->regs + SPI_DATA, data); /* try again */ | 231 | out_8(ms->regs + SPI_DATA, data); /* try again */ |
226 | return FSM_CONTINUE; | 232 | return FSM_CONTINUE; |
227 | } else if (status & SPI_STATUS_MODF) { | 233 | } else if (status & SPI_STATUS_MODF) { |
@@ -390,7 +396,9 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op, | |||
390 | struct spi_master *master; | 396 | struct spi_master *master; |
391 | struct mpc52xx_spi *ms; | 397 | struct mpc52xx_spi *ms; |
392 | void __iomem *regs; | 398 | void __iomem *regs; |
393 | int rc; | 399 | u8 ctrl1; |
400 | int rc, i = 0; | ||
401 | int gpio_cs; | ||
394 | 402 | ||
395 | /* MMIO registers */ | 403 | /* MMIO registers */ |
396 | dev_dbg(&op->dev, "probing mpc5200 SPI device\n"); | 404 | dev_dbg(&op->dev, "probing mpc5200 SPI device\n"); |
@@ -399,7 +407,8 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op, | |||
399 | return -ENODEV; | 407 | return -ENODEV; |
400 | 408 | ||
401 | /* initialize the device */ | 409 | /* initialize the device */ |
402 | out_8(regs+SPI_CTRL1, SPI_CTRL1_SPIE | SPI_CTRL1_SPE | SPI_CTRL1_MSTR); | 410 | ctrl1 = SPI_CTRL1_SPIE | SPI_CTRL1_SPE | SPI_CTRL1_MSTR; |
411 | out_8(regs + SPI_CTRL1, ctrl1); | ||
403 | out_8(regs + SPI_CTRL2, 0x0); | 412 | out_8(regs + SPI_CTRL2, 0x0); |
404 | out_8(regs + SPI_DATADIR, 0xe); /* Set output pins */ | 413 | out_8(regs + SPI_DATADIR, 0xe); /* Set output pins */ |
405 | out_8(regs + SPI_PORTDATA, 0x8); /* Deassert /SS signal */ | 414 | out_8(regs + SPI_PORTDATA, 0x8); /* Deassert /SS signal */ |
@@ -409,6 +418,8 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op, | |||
409 | * on the SPI bus. This fault will also occur if the SPI signals | 418 | * on the SPI bus. This fault will also occur if the SPI signals |
410 | * are not connected to any pins (port_config setting) */ | 419 | * are not connected to any pins (port_config setting) */ |
411 | in_8(regs + SPI_STATUS); | 420 | in_8(regs + SPI_STATUS); |
421 | out_8(regs + SPI_CTRL1, ctrl1); | ||
422 | |||
412 | in_8(regs + SPI_DATA); | 423 | in_8(regs + SPI_DATA); |
413 | if (in_8(regs + SPI_STATUS) & SPI_STATUS_MODF) { | 424 | if (in_8(regs + SPI_STATUS) & SPI_STATUS_MODF) { |
414 | dev_err(&op->dev, "mode fault; is port_config correct?\n"); | 425 | dev_err(&op->dev, "mode fault; is port_config correct?\n"); |
@@ -422,10 +433,12 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op, | |||
422 | rc = -ENOMEM; | 433 | rc = -ENOMEM; |
423 | goto err_alloc; | 434 | goto err_alloc; |
424 | } | 435 | } |
436 | |||
425 | master->bus_num = -1; | 437 | master->bus_num = -1; |
426 | master->num_chipselect = 1; | ||
427 | master->setup = mpc52xx_spi_setup; | 438 | master->setup = mpc52xx_spi_setup; |
428 | master->transfer = mpc52xx_spi_transfer; | 439 | master->transfer = mpc52xx_spi_transfer; |
440 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; | ||
441 | |||
429 | dev_set_drvdata(&op->dev, master); | 442 | dev_set_drvdata(&op->dev, master); |
430 | 443 | ||
431 | ms = spi_master_get_devdata(master); | 444 | ms = spi_master_get_devdata(master); |
@@ -435,16 +448,51 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op, | |||
435 | ms->irq1 = irq_of_parse_and_map(op->node, 1); | 448 | ms->irq1 = irq_of_parse_and_map(op->node, 1); |
436 | ms->state = mpc52xx_spi_fsmstate_idle; | 449 | ms->state = mpc52xx_spi_fsmstate_idle; |
437 | ms->ipb_freq = mpc5xxx_get_bus_frequency(op->node); | 450 | ms->ipb_freq = mpc5xxx_get_bus_frequency(op->node); |
451 | ms->gpio_cs_count = of_gpio_count(op->node); | ||
452 | if (ms->gpio_cs_count > 0) { | ||
453 | master->num_chipselect = ms->gpio_cs_count; | ||
454 | ms->gpio_cs = kmalloc(ms->gpio_cs_count * sizeof(unsigned int), | ||
455 | GFP_KERNEL); | ||
456 | if (!ms->gpio_cs) { | ||
457 | rc = -ENOMEM; | ||
458 | goto err_alloc; | ||
459 | } | ||
460 | |||
461 | for (i = 0; i < ms->gpio_cs_count; i++) { | ||
462 | gpio_cs = of_get_gpio(op->node, i); | ||
463 | if (gpio_cs < 0) { | ||
464 | dev_err(&op->dev, | ||
465 | "could not parse the gpio field " | ||
466 | "in oftree\n"); | ||
467 | rc = -ENODEV; | ||
468 | goto err_gpio; | ||
469 | } | ||
470 | |||
471 | rc = gpio_request(gpio_cs, dev_name(&op->dev)); | ||
472 | if (rc) { | ||
473 | dev_err(&op->dev, | ||
474 | "can't request spi cs gpio #%d " | ||
475 | "on gpio line %d\n", i, gpio_cs); | ||
476 | goto err_gpio; | ||
477 | } | ||
478 | |||
479 | gpio_direction_output(gpio_cs, 1); | ||
480 | ms->gpio_cs[i] = gpio_cs; | ||
481 | } | ||
482 | } else { | ||
483 | master->num_chipselect = 1; | ||
484 | } | ||
485 | |||
438 | spin_lock_init(&ms->lock); | 486 | spin_lock_init(&ms->lock); |
439 | INIT_LIST_HEAD(&ms->queue); | 487 | INIT_LIST_HEAD(&ms->queue); |
440 | INIT_WORK(&ms->work, mpc52xx_spi_wq); | 488 | INIT_WORK(&ms->work, mpc52xx_spi_wq); |
441 | 489 | ||
442 | /* Decide if interrupts can be used */ | 490 | /* Decide if interrupts can be used */ |
443 | if (ms->irq0 && ms->irq1) { | 491 | if (ms->irq0 && ms->irq1) { |
444 | rc = request_irq(ms->irq0, mpc52xx_spi_irq, IRQF_SAMPLE_RANDOM, | 492 | rc = request_irq(ms->irq0, mpc52xx_spi_irq, 0, |
445 | "mpc5200-spi-modf", ms); | 493 | "mpc5200-spi-modf", ms); |
446 | rc |= request_irq(ms->irq1, mpc52xx_spi_irq, IRQF_SAMPLE_RANDOM, | 494 | rc |= request_irq(ms->irq1, mpc52xx_spi_irq, 0, |
447 | "mpc5200-spi-spiF", ms); | 495 | "mpc5200-spi-spif", ms); |
448 | if (rc) { | 496 | if (rc) { |
449 | free_irq(ms->irq0, ms); | 497 | free_irq(ms->irq0, ms); |
450 | free_irq(ms->irq1, ms); | 498 | free_irq(ms->irq1, ms); |
@@ -471,6 +519,11 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op, | |||
471 | err_register: | 519 | err_register: |
472 | dev_err(&ms->master->dev, "initialization failed\n"); | 520 | dev_err(&ms->master->dev, "initialization failed\n"); |
473 | spi_master_put(master); | 521 | spi_master_put(master); |
522 | err_gpio: | ||
523 | while (i-- > 0) | ||
524 | gpio_free(ms->gpio_cs[i]); | ||
525 | |||
526 | kfree(ms->gpio_cs); | ||
474 | err_alloc: | 527 | err_alloc: |
475 | err_init: | 528 | err_init: |
476 | iounmap(regs); | 529 | iounmap(regs); |
@@ -481,10 +534,15 @@ static int __devexit mpc52xx_spi_remove(struct of_device *op) | |||
481 | { | 534 | { |
482 | struct spi_master *master = dev_get_drvdata(&op->dev); | 535 | struct spi_master *master = dev_get_drvdata(&op->dev); |
483 | struct mpc52xx_spi *ms = spi_master_get_devdata(master); | 536 | struct mpc52xx_spi *ms = spi_master_get_devdata(master); |
537 | int i; | ||
484 | 538 | ||
485 | free_irq(ms->irq0, ms); | 539 | free_irq(ms->irq0, ms); |
486 | free_irq(ms->irq1, ms); | 540 | free_irq(ms->irq1, ms); |
487 | 541 | ||
542 | for (i = 0; i < ms->gpio_cs_count; i++) | ||
543 | gpio_free(ms->gpio_cs[i]); | ||
544 | |||
545 | kfree(ms->gpio_cs); | ||
488 | spi_unregister_master(master); | 546 | spi_unregister_master(master); |
489 | spi_master_put(master); | 547 | spi_master_put(master); |
490 | iounmap(ms->regs); | 548 | iounmap(ms->regs); |