diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2010-12-29 03:05:14 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2010-12-29 03:05:50 -0500 |
commit | 94a544a4e8d05a027613443c529c399c39cc3371 (patch) | |
tree | edada38e93a958a918b5826eaef173b1b92079d1 /drivers/spi | |
parent | 496a2e360a34e1f41c336d23947f800216cb9bdf (diff) | |
parent | 21486af0f34d03b813b023d7a2b887b329f60486 (diff) |
Merge branch 'spi' of git://git.linutronix.de/users/bigeasy/soda into spi/next
* 'spi' of git://git.linutronix.de/users/bigeasy/soda into spi/next
spi/pxa2xx: register driver properly
spi/pxa2xx: add support for shared IRQ handler
spi/pxa2xx: Use define for SSSR_TFL_MASK instead of plain numbers
arm/pxa2xx: reorgazine SSP and SPI header files
spi/pxa2xx: Add CE4100 support
spi/pxa2xx: Consider CE4100's FIFO depth
spi/pxa2xx: Add chipselect support for Sodaville
spi/pxa2xx: Modify RX-Tresh instead of busy-loop for the remaining RX bytes.
spi/pxa2xx: pass of_node to spi device and set a parent device
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/Kconfig | 13 | ||||
-rw-r--r-- | drivers/spi/Makefile | 1 | ||||
-rw-r--r-- | drivers/spi/pxa2xx_spi.c | 190 | ||||
-rw-r--r-- | drivers/spi/pxa2xx_spi_pci.c | 201 |
4 files changed, 344 insertions, 61 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 6efac5fd439d..1906840c1113 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -270,12 +270,15 @@ config SPI_PPC4xx | |||
270 | 270 | ||
271 | config SPI_PXA2XX | 271 | config SPI_PXA2XX |
272 | tristate "PXA2xx SSP SPI master" | 272 | tristate "PXA2xx SSP SPI master" |
273 | depends on ARCH_PXA && EXPERIMENTAL | 273 | depends on (ARCH_PXA || (X86_32 && PCI)) && EXPERIMENTAL |
274 | select PXA_SSP | 274 | select PXA_SSP if ARCH_PXA |
275 | help | 275 | help |
276 | This enables using a PXA2xx SSP port as a SPI master controller. | 276 | This enables using a PXA2xx or Sodaville SSP port as a SPI master |
277 | The driver can be configured to use any SSP port and additional | 277 | controller. The driver can be configured to use any SSP port and |
278 | documentation can be found a Documentation/spi/pxa2xx. | 278 | additional documentation can be found a Documentation/spi/pxa2xx. |
279 | |||
280 | config SPI_PXA2XX_PCI | ||
281 | def_bool SPI_PXA2XX && X86_32 && PCI | ||
279 | 282 | ||
280 | config SPI_S3C24XX | 283 | config SPI_S3C24XX |
281 | tristate "Samsung S3C24XX series SPI" | 284 | tristate "Samsung S3C24XX series SPI" |
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 7ec375b6c0c3..3a42463c92a4 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile | |||
@@ -25,6 +25,7 @@ obj-$(CONFIG_SPI_GPIO) += spi_gpio.o | |||
25 | obj-$(CONFIG_SPI_IMX) += spi_imx.o | 25 | obj-$(CONFIG_SPI_IMX) += spi_imx.o |
26 | obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o | 26 | obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o |
27 | obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o | 27 | obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o |
28 | obj-$(CONFIG_SPI_PXA2XX_PCI) += pxa2xx_spi_pci.o | ||
28 | obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o | 29 | obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o |
29 | obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o | 30 | obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o |
30 | obj-$(CONFIG_SPI_OMAP_100K) += omap_spi_100k.o | 31 | obj-$(CONFIG_SPI_OMAP_100K) += omap_spi_100k.o |
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index e76b1afafe07..95928833855b 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c | |||
@@ -23,11 +23,11 @@ | |||
23 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/spi/pxa2xx_spi.h> | ||
26 | #include <linux/dma-mapping.h> | 27 | #include <linux/dma-mapping.h> |
27 | #include <linux/spi/spi.h> | 28 | #include <linux/spi/spi.h> |
28 | #include <linux/workqueue.h> | 29 | #include <linux/workqueue.h> |
29 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
30 | #include <linux/clk.h> | ||
31 | #include <linux/gpio.h> | 31 | #include <linux/gpio.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | 33 | ||
@@ -35,9 +35,6 @@ | |||
35 | #include <asm/irq.h> | 35 | #include <asm/irq.h> |
36 | #include <asm/delay.h> | 36 | #include <asm/delay.h> |
37 | 37 | ||
38 | #include <mach/dma.h> | ||
39 | #include <plat/ssp.h> | ||
40 | #include <mach/pxa2xx_spi.h> | ||
41 | 38 | ||
42 | MODULE_AUTHOR("Stephen Street"); | 39 | MODULE_AUTHOR("Stephen Street"); |
43 | MODULE_DESCRIPTION("PXA2xx SSP SPI Controller"); | 40 | MODULE_DESCRIPTION("PXA2xx SSP SPI Controller"); |
@@ -46,8 +43,6 @@ MODULE_ALIAS("platform:pxa2xx-spi"); | |||
46 | 43 | ||
47 | #define MAX_BUSES 3 | 44 | #define MAX_BUSES 3 |
48 | 45 | ||
49 | #define RX_THRESH_DFLT 8 | ||
50 | #define TX_THRESH_DFLT 8 | ||
51 | #define TIMOUT_DFLT 1000 | 46 | #define TIMOUT_DFLT 1000 |
52 | 47 | ||
53 | #define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR) | 48 | #define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR) |
@@ -168,7 +163,10 @@ struct chip_data { | |||
168 | u8 enable_dma; | 163 | u8 enable_dma; |
169 | u8 bits_per_word; | 164 | u8 bits_per_word; |
170 | u32 speed_hz; | 165 | u32 speed_hz; |
171 | int gpio_cs; | 166 | union { |
167 | int gpio_cs; | ||
168 | unsigned int frm; | ||
169 | }; | ||
172 | int gpio_cs_inverted; | 170 | int gpio_cs_inverted; |
173 | int (*write)(struct driver_data *drv_data); | 171 | int (*write)(struct driver_data *drv_data); |
174 | int (*read)(struct driver_data *drv_data); | 172 | int (*read)(struct driver_data *drv_data); |
@@ -181,6 +179,11 @@ static void cs_assert(struct driver_data *drv_data) | |||
181 | { | 179 | { |
182 | struct chip_data *chip = drv_data->cur_chip; | 180 | struct chip_data *chip = drv_data->cur_chip; |
183 | 181 | ||
182 | if (drv_data->ssp_type == CE4100_SSP) { | ||
183 | write_SSSR(drv_data->cur_chip->frm, drv_data->ioaddr); | ||
184 | return; | ||
185 | } | ||
186 | |||
184 | if (chip->cs_control) { | 187 | if (chip->cs_control) { |
185 | chip->cs_control(PXA2XX_CS_ASSERT); | 188 | chip->cs_control(PXA2XX_CS_ASSERT); |
186 | return; | 189 | return; |
@@ -194,6 +197,9 @@ static void cs_deassert(struct driver_data *drv_data) | |||
194 | { | 197 | { |
195 | struct chip_data *chip = drv_data->cur_chip; | 198 | struct chip_data *chip = drv_data->cur_chip; |
196 | 199 | ||
200 | if (drv_data->ssp_type == CE4100_SSP) | ||
201 | return; | ||
202 | |||
197 | if (chip->cs_control) { | 203 | if (chip->cs_control) { |
198 | chip->cs_control(PXA2XX_CS_DEASSERT); | 204 | chip->cs_control(PXA2XX_CS_DEASSERT); |
199 | return; | 205 | return; |
@@ -203,6 +209,25 @@ static void cs_deassert(struct driver_data *drv_data) | |||
203 | gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted); | 209 | gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted); |
204 | } | 210 | } |
205 | 211 | ||
212 | static void write_SSSR_CS(struct driver_data *drv_data, u32 val) | ||
213 | { | ||
214 | void __iomem *reg = drv_data->ioaddr; | ||
215 | |||
216 | if (drv_data->ssp_type == CE4100_SSP) | ||
217 | val |= read_SSSR(reg) & SSSR_ALT_FRM_MASK; | ||
218 | |||
219 | write_SSSR(val, reg); | ||
220 | } | ||
221 | |||
222 | static int pxa25x_ssp_comp(struct driver_data *drv_data) | ||
223 | { | ||
224 | if (drv_data->ssp_type == PXA25x_SSP) | ||
225 | return 1; | ||
226 | if (drv_data->ssp_type == CE4100_SSP) | ||
227 | return 1; | ||
228 | return 0; | ||
229 | } | ||
230 | |||
206 | static int flush(struct driver_data *drv_data) | 231 | static int flush(struct driver_data *drv_data) |
207 | { | 232 | { |
208 | unsigned long limit = loops_per_jiffy << 1; | 233 | unsigned long limit = loops_per_jiffy << 1; |
@@ -214,7 +239,7 @@ static int flush(struct driver_data *drv_data) | |||
214 | read_SSDR(reg); | 239 | read_SSDR(reg); |
215 | } | 240 | } |
216 | } while ((read_SSSR(reg) & SSSR_BSY) && --limit); | 241 | } while ((read_SSSR(reg) & SSSR_BSY) && --limit); |
217 | write_SSSR(SSSR_ROR, reg); | 242 | write_SSSR_CS(drv_data, SSSR_ROR); |
218 | 243 | ||
219 | return limit; | 244 | return limit; |
220 | } | 245 | } |
@@ -224,7 +249,7 @@ static int null_writer(struct driver_data *drv_data) | |||
224 | void __iomem *reg = drv_data->ioaddr; | 249 | void __iomem *reg = drv_data->ioaddr; |
225 | u8 n_bytes = drv_data->n_bytes; | 250 | u8 n_bytes = drv_data->n_bytes; |
226 | 251 | ||
227 | if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00) | 252 | if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK) |
228 | || (drv_data->tx == drv_data->tx_end)) | 253 | || (drv_data->tx == drv_data->tx_end)) |
229 | return 0; | 254 | return 0; |
230 | 255 | ||
@@ -252,7 +277,7 @@ static int u8_writer(struct driver_data *drv_data) | |||
252 | { | 277 | { |
253 | void __iomem *reg = drv_data->ioaddr; | 278 | void __iomem *reg = drv_data->ioaddr; |
254 | 279 | ||
255 | if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00) | 280 | if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK) |
256 | || (drv_data->tx == drv_data->tx_end)) | 281 | || (drv_data->tx == drv_data->tx_end)) |
257 | return 0; | 282 | return 0; |
258 | 283 | ||
@@ -279,7 +304,7 @@ static int u16_writer(struct driver_data *drv_data) | |||
279 | { | 304 | { |
280 | void __iomem *reg = drv_data->ioaddr; | 305 | void __iomem *reg = drv_data->ioaddr; |
281 | 306 | ||
282 | if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00) | 307 | if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK) |
283 | || (drv_data->tx == drv_data->tx_end)) | 308 | || (drv_data->tx == drv_data->tx_end)) |
284 | return 0; | 309 | return 0; |
285 | 310 | ||
@@ -306,7 +331,7 @@ static int u32_writer(struct driver_data *drv_data) | |||
306 | { | 331 | { |
307 | void __iomem *reg = drv_data->ioaddr; | 332 | void __iomem *reg = drv_data->ioaddr; |
308 | 333 | ||
309 | if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00) | 334 | if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK) |
310 | || (drv_data->tx == drv_data->tx_end)) | 335 | || (drv_data->tx == drv_data->tx_end)) |
311 | return 0; | 336 | return 0; |
312 | 337 | ||
@@ -507,9 +532,9 @@ static void dma_error_stop(struct driver_data *drv_data, const char *msg) | |||
507 | /* Stop and reset */ | 532 | /* Stop and reset */ |
508 | DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; | 533 | DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; |
509 | DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; | 534 | DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; |
510 | write_SSSR(drv_data->clear_sr, reg); | 535 | write_SSSR_CS(drv_data, drv_data->clear_sr); |
511 | write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); | 536 | write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); |
512 | if (drv_data->ssp_type != PXA25x_SSP) | 537 | if (!pxa25x_ssp_comp(drv_data)) |
513 | write_SSTO(0, reg); | 538 | write_SSTO(0, reg); |
514 | flush(drv_data); | 539 | flush(drv_data); |
515 | write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); | 540 | write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); |
@@ -529,7 +554,7 @@ static void dma_transfer_complete(struct driver_data *drv_data) | |||
529 | 554 | ||
530 | /* Clear and disable interrupts on SSP and DMA channels*/ | 555 | /* Clear and disable interrupts on SSP and DMA channels*/ |
531 | write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); | 556 | write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); |
532 | write_SSSR(drv_data->clear_sr, reg); | 557 | write_SSSR_CS(drv_data, drv_data->clear_sr); |
533 | DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; | 558 | DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; |
534 | DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; | 559 | DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; |
535 | 560 | ||
@@ -622,7 +647,7 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data) | |||
622 | 647 | ||
623 | /* Clear and disable timeout interrupt, do the rest in | 648 | /* Clear and disable timeout interrupt, do the rest in |
624 | * dma_transfer_complete */ | 649 | * dma_transfer_complete */ |
625 | if (drv_data->ssp_type != PXA25x_SSP) | 650 | if (!pxa25x_ssp_comp(drv_data)) |
626 | write_SSTO(0, reg); | 651 | write_SSTO(0, reg); |
627 | 652 | ||
628 | /* finish this transfer, start the next */ | 653 | /* finish this transfer, start the next */ |
@@ -635,14 +660,26 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data) | |||
635 | return IRQ_NONE; | 660 | return IRQ_NONE; |
636 | } | 661 | } |
637 | 662 | ||
663 | static void reset_sccr1(struct driver_data *drv_data) | ||
664 | { | ||
665 | void __iomem *reg = drv_data->ioaddr; | ||
666 | struct chip_data *chip = drv_data->cur_chip; | ||
667 | u32 sccr1_reg; | ||
668 | |||
669 | sccr1_reg = read_SSCR1(reg) & ~drv_data->int_cr1; | ||
670 | sccr1_reg &= ~SSCR1_RFT; | ||
671 | sccr1_reg |= chip->threshold; | ||
672 | write_SSCR1(sccr1_reg, reg); | ||
673 | } | ||
674 | |||
638 | static void int_error_stop(struct driver_data *drv_data, const char* msg) | 675 | static void int_error_stop(struct driver_data *drv_data, const char* msg) |
639 | { | 676 | { |
640 | void __iomem *reg = drv_data->ioaddr; | 677 | void __iomem *reg = drv_data->ioaddr; |
641 | 678 | ||
642 | /* Stop and reset SSP */ | 679 | /* Stop and reset SSP */ |
643 | write_SSSR(drv_data->clear_sr, reg); | 680 | write_SSSR_CS(drv_data, drv_data->clear_sr); |
644 | write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); | 681 | reset_sccr1(drv_data); |
645 | if (drv_data->ssp_type != PXA25x_SSP) | 682 | if (!pxa25x_ssp_comp(drv_data)) |
646 | write_SSTO(0, reg); | 683 | write_SSTO(0, reg); |
647 | flush(drv_data); | 684 | flush(drv_data); |
648 | write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); | 685 | write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); |
@@ -658,9 +695,9 @@ static void int_transfer_complete(struct driver_data *drv_data) | |||
658 | void __iomem *reg = drv_data->ioaddr; | 695 | void __iomem *reg = drv_data->ioaddr; |
659 | 696 | ||
660 | /* Stop SSP */ | 697 | /* Stop SSP */ |
661 | write_SSSR(drv_data->clear_sr, reg); | 698 | write_SSSR_CS(drv_data, drv_data->clear_sr); |
662 | write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); | 699 | reset_sccr1(drv_data); |
663 | if (drv_data->ssp_type != PXA25x_SSP) | 700 | if (!pxa25x_ssp_comp(drv_data)) |
664 | write_SSTO(0, reg); | 701 | write_SSTO(0, reg); |
665 | 702 | ||
666 | /* Update total byte transfered return count actual bytes read */ | 703 | /* Update total byte transfered return count actual bytes read */ |
@@ -714,24 +751,34 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data) | |||
714 | } | 751 | } |
715 | 752 | ||
716 | if (drv_data->tx == drv_data->tx_end) { | 753 | if (drv_data->tx == drv_data->tx_end) { |
717 | write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg); | 754 | u32 bytes_left; |
718 | /* PXA25x_SSP has no timeout, read trailing bytes */ | 755 | u32 sccr1_reg; |
719 | if (drv_data->ssp_type == PXA25x_SSP) { | 756 | |
720 | if (!wait_ssp_rx_stall(reg)) | 757 | sccr1_reg = read_SSCR1(reg); |
721 | { | 758 | sccr1_reg &= ~SSCR1_TIE; |
722 | int_error_stop(drv_data, "interrupt_transfer: " | 759 | |
723 | "rx stall failed"); | 760 | /* |
724 | return IRQ_HANDLED; | 761 | * PXA25x_SSP has no timeout, set up rx threshould for the |
725 | } | 762 | * remaing RX bytes. |
726 | if (!drv_data->read(drv_data)) | 763 | */ |
727 | { | 764 | if (pxa25x_ssp_comp(drv_data)) { |
728 | int_error_stop(drv_data, | 765 | |
729 | "interrupt_transfer: " | 766 | sccr1_reg &= ~SSCR1_RFT; |
730 | "trailing byte read failed"); | 767 | |
731 | return IRQ_HANDLED; | 768 | bytes_left = drv_data->rx_end - drv_data->rx; |
769 | switch (drv_data->n_bytes) { | ||
770 | case 4: | ||
771 | bytes_left >>= 1; | ||
772 | case 2: | ||
773 | bytes_left >>= 1; | ||
732 | } | 774 | } |
733 | int_transfer_complete(drv_data); | 775 | |
776 | if (bytes_left > RX_THRESH_DFLT) | ||
777 | bytes_left = RX_THRESH_DFLT; | ||
778 | |||
779 | sccr1_reg |= SSCR1_RxTresh(bytes_left); | ||
734 | } | 780 | } |
781 | write_SSCR1(sccr1_reg, reg); | ||
735 | } | 782 | } |
736 | 783 | ||
737 | /* We did something */ | 784 | /* We did something */ |
@@ -742,14 +789,26 @@ static irqreturn_t ssp_int(int irq, void *dev_id) | |||
742 | { | 789 | { |
743 | struct driver_data *drv_data = dev_id; | 790 | struct driver_data *drv_data = dev_id; |
744 | void __iomem *reg = drv_data->ioaddr; | 791 | void __iomem *reg = drv_data->ioaddr; |
792 | u32 sccr1_reg = read_SSCR1(reg); | ||
793 | u32 mask = drv_data->mask_sr; | ||
794 | u32 status; | ||
795 | |||
796 | status = read_SSSR(reg); | ||
797 | |||
798 | /* Ignore possible writes if we don't need to write */ | ||
799 | if (!(sccr1_reg & SSCR1_TIE)) | ||
800 | mask &= ~SSSR_TFS; | ||
801 | |||
802 | if (!(status & mask)) | ||
803 | return IRQ_NONE; | ||
745 | 804 | ||
746 | if (!drv_data->cur_msg) { | 805 | if (!drv_data->cur_msg) { |
747 | 806 | ||
748 | write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); | 807 | write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); |
749 | write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); | 808 | write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); |
750 | if (drv_data->ssp_type != PXA25x_SSP) | 809 | if (!pxa25x_ssp_comp(drv_data)) |
751 | write_SSTO(0, reg); | 810 | write_SSTO(0, reg); |
752 | write_SSSR(drv_data->clear_sr, reg); | 811 | write_SSSR_CS(drv_data, drv_data->clear_sr); |
753 | 812 | ||
754 | dev_err(&drv_data->pdev->dev, "bad message state " | 813 | dev_err(&drv_data->pdev->dev, "bad message state " |
755 | "in interrupt handler\n"); | 814 | "in interrupt handler\n"); |
@@ -862,7 +921,7 @@ static unsigned int ssp_get_clk_div(struct ssp_device *ssp, int rate) | |||
862 | { | 921 | { |
863 | unsigned long ssp_clk = clk_get_rate(ssp->clk); | 922 | unsigned long ssp_clk = clk_get_rate(ssp->clk); |
864 | 923 | ||
865 | if (ssp->type == PXA25x_SSP) | 924 | if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP) |
866 | return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8; | 925 | return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8; |
867 | else | 926 | else |
868 | return ((ssp_clk / rate - 1) & 0xfff) << 8; | 927 | return ((ssp_clk / rate - 1) & 0xfff) << 8; |
@@ -1088,7 +1147,7 @@ static void pump_transfers(unsigned long data) | |||
1088 | 1147 | ||
1089 | /* Clear status */ | 1148 | /* Clear status */ |
1090 | cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1; | 1149 | cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1; |
1091 | write_SSSR(drv_data->clear_sr, reg); | 1150 | write_SSSR_CS(drv_data, drv_data->clear_sr); |
1092 | } | 1151 | } |
1093 | 1152 | ||
1094 | /* see if we need to reload the config registers */ | 1153 | /* see if we need to reload the config registers */ |
@@ -1098,7 +1157,7 @@ static void pump_transfers(unsigned long data) | |||
1098 | 1157 | ||
1099 | /* stop the SSP, and update the other bits */ | 1158 | /* stop the SSP, and update the other bits */ |
1100 | write_SSCR0(cr0 & ~SSCR0_SSE, reg); | 1159 | write_SSCR0(cr0 & ~SSCR0_SSE, reg); |
1101 | if (drv_data->ssp_type != PXA25x_SSP) | 1160 | if (!pxa25x_ssp_comp(drv_data)) |
1102 | write_SSTO(chip->timeout, reg); | 1161 | write_SSTO(chip->timeout, reg); |
1103 | /* first set CR1 without interrupt and service enables */ | 1162 | /* first set CR1 without interrupt and service enables */ |
1104 | write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg); | 1163 | write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg); |
@@ -1106,7 +1165,7 @@ static void pump_transfers(unsigned long data) | |||
1106 | write_SSCR0(cr0, reg); | 1165 | write_SSCR0(cr0, reg); |
1107 | 1166 | ||
1108 | } else { | 1167 | } else { |
1109 | if (drv_data->ssp_type != PXA25x_SSP) | 1168 | if (!pxa25x_ssp_comp(drv_data)) |
1110 | write_SSTO(chip->timeout, reg); | 1169 | write_SSTO(chip->timeout, reg); |
1111 | } | 1170 | } |
1112 | 1171 | ||
@@ -1233,14 +1292,13 @@ static int setup(struct spi_device *spi) | |||
1233 | uint tx_thres = TX_THRESH_DFLT; | 1292 | uint tx_thres = TX_THRESH_DFLT; |
1234 | uint rx_thres = RX_THRESH_DFLT; | 1293 | uint rx_thres = RX_THRESH_DFLT; |
1235 | 1294 | ||
1236 | if (drv_data->ssp_type != PXA25x_SSP | 1295 | if (!pxa25x_ssp_comp(drv_data) |
1237 | && (spi->bits_per_word < 4 || spi->bits_per_word > 32)) { | 1296 | && (spi->bits_per_word < 4 || spi->bits_per_word > 32)) { |
1238 | dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d " | 1297 | dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d " |
1239 | "b/w not 4-32 for type non-PXA25x_SSP\n", | 1298 | "b/w not 4-32 for type non-PXA25x_SSP\n", |
1240 | drv_data->ssp_type, spi->bits_per_word); | 1299 | drv_data->ssp_type, spi->bits_per_word); |
1241 | return -EINVAL; | 1300 | return -EINVAL; |
1242 | } | 1301 | } else if (pxa25x_ssp_comp(drv_data) |
1243 | else if (drv_data->ssp_type == PXA25x_SSP | ||
1244 | && (spi->bits_per_word < 4 | 1302 | && (spi->bits_per_word < 4 |
1245 | || spi->bits_per_word > 16)) { | 1303 | || spi->bits_per_word > 16)) { |
1246 | dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d " | 1304 | dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d " |
@@ -1259,7 +1317,17 @@ static int setup(struct spi_device *spi) | |||
1259 | return -ENOMEM; | 1317 | return -ENOMEM; |
1260 | } | 1318 | } |
1261 | 1319 | ||
1262 | chip->gpio_cs = -1; | 1320 | if (drv_data->ssp_type == CE4100_SSP) { |
1321 | if (spi->chip_select > 4) { | ||
1322 | dev_err(&spi->dev, "failed setup: " | ||
1323 | "cs number must not be > 4.\n"); | ||
1324 | kfree(chip); | ||
1325 | return -EINVAL; | ||
1326 | } | ||
1327 | |||
1328 | chip->frm = spi->chip_select; | ||
1329 | } else | ||
1330 | chip->gpio_cs = -1; | ||
1263 | chip->enable_dma = 0; | 1331 | chip->enable_dma = 0; |
1264 | chip->timeout = TIMOUT_DFLT; | 1332 | chip->timeout = TIMOUT_DFLT; |
1265 | chip->dma_burst_size = drv_data->master_info->enable_dma ? | 1333 | chip->dma_burst_size = drv_data->master_info->enable_dma ? |
@@ -1315,7 +1383,7 @@ static int setup(struct spi_device *spi) | |||
1315 | | (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0); | 1383 | | (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0); |
1316 | 1384 | ||
1317 | /* NOTE: PXA25x_SSP _could_ use external clocking ... */ | 1385 | /* NOTE: PXA25x_SSP _could_ use external clocking ... */ |
1318 | if (drv_data->ssp_type != PXA25x_SSP) | 1386 | if (!pxa25x_ssp_comp(drv_data)) |
1319 | dev_dbg(&spi->dev, "%ld Hz actual, %s\n", | 1387 | dev_dbg(&spi->dev, "%ld Hz actual, %s\n", |
1320 | clk_get_rate(ssp->clk) | 1388 | clk_get_rate(ssp->clk) |
1321 | / (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)), | 1389 | / (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)), |
@@ -1350,23 +1418,27 @@ static int setup(struct spi_device *spi) | |||
1350 | 1418 | ||
1351 | spi_set_ctldata(spi, chip); | 1419 | spi_set_ctldata(spi, chip); |
1352 | 1420 | ||
1421 | if (drv_data->ssp_type == CE4100_SSP) | ||
1422 | return 0; | ||
1423 | |||
1353 | return setup_cs(spi, chip, chip_info); | 1424 | return setup_cs(spi, chip, chip_info); |
1354 | } | 1425 | } |
1355 | 1426 | ||
1356 | static void cleanup(struct spi_device *spi) | 1427 | static void cleanup(struct spi_device *spi) |
1357 | { | 1428 | { |
1358 | struct chip_data *chip = spi_get_ctldata(spi); | 1429 | struct chip_data *chip = spi_get_ctldata(spi); |
1430 | struct driver_data *drv_data = spi_master_get_devdata(spi->master); | ||
1359 | 1431 | ||
1360 | if (!chip) | 1432 | if (!chip) |
1361 | return; | 1433 | return; |
1362 | 1434 | ||
1363 | if (gpio_is_valid(chip->gpio_cs)) | 1435 | if (drv_data->ssp_type != CE4100_SSP && gpio_is_valid(chip->gpio_cs)) |
1364 | gpio_free(chip->gpio_cs); | 1436 | gpio_free(chip->gpio_cs); |
1365 | 1437 | ||
1366 | kfree(chip); | 1438 | kfree(chip); |
1367 | } | 1439 | } |
1368 | 1440 | ||
1369 | static int __init init_queue(struct driver_data *drv_data) | 1441 | static int __devinit init_queue(struct driver_data *drv_data) |
1370 | { | 1442 | { |
1371 | INIT_LIST_HEAD(&drv_data->queue); | 1443 | INIT_LIST_HEAD(&drv_data->queue); |
1372 | spin_lock_init(&drv_data->lock); | 1444 | spin_lock_init(&drv_data->lock); |
@@ -1454,7 +1526,7 @@ static int destroy_queue(struct driver_data *drv_data) | |||
1454 | return 0; | 1526 | return 0; |
1455 | } | 1527 | } |
1456 | 1528 | ||
1457 | static int __init pxa2xx_spi_probe(struct platform_device *pdev) | 1529 | static int __devinit pxa2xx_spi_probe(struct platform_device *pdev) |
1458 | { | 1530 | { |
1459 | struct device *dev = &pdev->dev; | 1531 | struct device *dev = &pdev->dev; |
1460 | struct pxa2xx_spi_master *platform_info; | 1532 | struct pxa2xx_spi_master *platform_info; |
@@ -1484,6 +1556,10 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
1484 | drv_data->pdev = pdev; | 1556 | drv_data->pdev = pdev; |
1485 | drv_data->ssp = ssp; | 1557 | drv_data->ssp = ssp; |
1486 | 1558 | ||
1559 | master->dev.parent = &pdev->dev; | ||
1560 | #ifdef CONFIG_OF | ||
1561 | master->dev.of_node = pdev->dev.of_node; | ||
1562 | #endif | ||
1487 | /* the spi->mode bits understood by this driver: */ | 1563 | /* the spi->mode bits understood by this driver: */ |
1488 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; | 1564 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; |
1489 | 1565 | ||
@@ -1500,7 +1576,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
1500 | 1576 | ||
1501 | drv_data->ioaddr = ssp->mmio_base; | 1577 | drv_data->ioaddr = ssp->mmio_base; |
1502 | drv_data->ssdr_physical = ssp->phys_base + SSDR; | 1578 | drv_data->ssdr_physical = ssp->phys_base + SSDR; |
1503 | if (ssp->type == PXA25x_SSP) { | 1579 | if (pxa25x_ssp_comp(drv_data)) { |
1504 | drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE; | 1580 | drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE; |
1505 | drv_data->dma_cr1 = 0; | 1581 | drv_data->dma_cr1 = 0; |
1506 | drv_data->clear_sr = SSSR_ROR; | 1582 | drv_data->clear_sr = SSSR_ROR; |
@@ -1512,7 +1588,8 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
1512 | drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR; | 1588 | drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR; |
1513 | } | 1589 | } |
1514 | 1590 | ||
1515 | status = request_irq(ssp->irq, ssp_int, 0, dev_name(dev), drv_data); | 1591 | status = request_irq(ssp->irq, ssp_int, IRQF_SHARED, dev_name(dev), |
1592 | drv_data); | ||
1516 | if (status < 0) { | 1593 | if (status < 0) { |
1517 | dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq); | 1594 | dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq); |
1518 | goto out_error_master_alloc; | 1595 | goto out_error_master_alloc; |
@@ -1561,7 +1638,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
1561 | | SSCR0_Motorola | 1638 | | SSCR0_Motorola |
1562 | | SSCR0_DataSize(8), | 1639 | | SSCR0_DataSize(8), |
1563 | drv_data->ioaddr); | 1640 | drv_data->ioaddr); |
1564 | if (drv_data->ssp_type != PXA25x_SSP) | 1641 | if (!pxa25x_ssp_comp(drv_data)) |
1565 | write_SSTO(0, drv_data->ioaddr); | 1642 | write_SSTO(0, drv_data->ioaddr); |
1566 | write_SSPSP(0, drv_data->ioaddr); | 1643 | write_SSPSP(0, drv_data->ioaddr); |
1567 | 1644 | ||
@@ -1723,13 +1800,14 @@ static struct platform_driver driver = { | |||
1723 | .pm = &pxa2xx_spi_pm_ops, | 1800 | .pm = &pxa2xx_spi_pm_ops, |
1724 | #endif | 1801 | #endif |
1725 | }, | 1802 | }, |
1803 | .probe = pxa2xx_spi_probe, | ||
1726 | .remove = pxa2xx_spi_remove, | 1804 | .remove = pxa2xx_spi_remove, |
1727 | .shutdown = pxa2xx_spi_shutdown, | 1805 | .shutdown = pxa2xx_spi_shutdown, |
1728 | }; | 1806 | }; |
1729 | 1807 | ||
1730 | static int __init pxa2xx_spi_init(void) | 1808 | static int __init pxa2xx_spi_init(void) |
1731 | { | 1809 | { |
1732 | return platform_driver_probe(&driver, pxa2xx_spi_probe); | 1810 | return platform_driver_register(&driver); |
1733 | } | 1811 | } |
1734 | subsys_initcall(pxa2xx_spi_init); | 1812 | subsys_initcall(pxa2xx_spi_init); |
1735 | 1813 | ||
diff --git a/drivers/spi/pxa2xx_spi_pci.c b/drivers/spi/pxa2xx_spi_pci.c new file mode 100644 index 000000000000..351d8a375b57 --- /dev/null +++ b/drivers/spi/pxa2xx_spi_pci.c | |||
@@ -0,0 +1,201 @@ | |||
1 | /* | ||
2 | * CE4100's SPI device is more or less the same one as found on PXA | ||
3 | * | ||
4 | */ | ||
5 | #include <linux/pci.h> | ||
6 | #include <linux/platform_device.h> | ||
7 | #include <linux/of_device.h> | ||
8 | #include <linux/spi/pxa2xx_spi.h> | ||
9 | |||
10 | struct awesome_struct { | ||
11 | struct ssp_device ssp; | ||
12 | struct platform_device spi_pdev; | ||
13 | struct pxa2xx_spi_master spi_pdata; | ||
14 | }; | ||
15 | |||
16 | static DEFINE_MUTEX(ssp_lock); | ||
17 | static LIST_HEAD(ssp_list); | ||
18 | |||
19 | struct ssp_device *pxa_ssp_request(int port, const char *label) | ||
20 | { | ||
21 | struct ssp_device *ssp = NULL; | ||
22 | |||
23 | mutex_lock(&ssp_lock); | ||
24 | |||
25 | list_for_each_entry(ssp, &ssp_list, node) { | ||
26 | if (ssp->port_id == port && ssp->use_count == 0) { | ||
27 | ssp->use_count++; | ||
28 | ssp->label = label; | ||
29 | break; | ||
30 | } | ||
31 | } | ||
32 | |||
33 | mutex_unlock(&ssp_lock); | ||
34 | |||
35 | if (&ssp->node == &ssp_list) | ||
36 | return NULL; | ||
37 | |||
38 | return ssp; | ||
39 | } | ||
40 | EXPORT_SYMBOL_GPL(pxa_ssp_request); | ||
41 | |||
42 | void pxa_ssp_free(struct ssp_device *ssp) | ||
43 | { | ||
44 | mutex_lock(&ssp_lock); | ||
45 | if (ssp->use_count) { | ||
46 | ssp->use_count--; | ||
47 | ssp->label = NULL; | ||
48 | } else | ||
49 | dev_err(&ssp->pdev->dev, "device already free\n"); | ||
50 | mutex_unlock(&ssp_lock); | ||
51 | } | ||
52 | EXPORT_SYMBOL_GPL(pxa_ssp_free); | ||
53 | |||
54 | static void plat_dev_release(struct device *dev) | ||
55 | { | ||
56 | struct awesome_struct *as = container_of(dev, | ||
57 | struct awesome_struct, spi_pdev.dev); | ||
58 | |||
59 | of_device_node_put(&as->spi_pdev.dev); | ||
60 | } | ||
61 | |||
62 | static int __devinit ce4100_spi_probe(struct pci_dev *dev, | ||
63 | const struct pci_device_id *ent) | ||
64 | { | ||
65 | int ret; | ||
66 | resource_size_t phys_beg; | ||
67 | resource_size_t phys_len; | ||
68 | struct awesome_struct *spi_info; | ||
69 | struct platform_device *pdev; | ||
70 | struct pxa2xx_spi_master *spi_pdata; | ||
71 | struct ssp_device *ssp; | ||
72 | |||
73 | ret = pci_enable_device(dev); | ||
74 | if (ret) | ||
75 | return ret; | ||
76 | |||
77 | phys_beg = pci_resource_start(dev, 0); | ||
78 | phys_len = pci_resource_len(dev, 0); | ||
79 | |||
80 | if (!request_mem_region(phys_beg, phys_len, | ||
81 | "CE4100 SPI")) { | ||
82 | dev_err(&dev->dev, "Can't request register space.\n"); | ||
83 | ret = -EBUSY; | ||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | spi_info = kzalloc(sizeof(*spi_info), GFP_KERNEL); | ||
88 | if (!spi_info) { | ||
89 | ret = -ENOMEM; | ||
90 | goto err_kz; | ||
91 | } | ||
92 | ssp = &spi_info->ssp; | ||
93 | pdev = &spi_info->spi_pdev; | ||
94 | spi_pdata = &spi_info->spi_pdata; | ||
95 | |||
96 | pdev->name = "pxa2xx-spi"; | ||
97 | pdev->id = dev->devfn; | ||
98 | pdev->dev.parent = &dev->dev; | ||
99 | pdev->dev.platform_data = &spi_info->spi_pdata; | ||
100 | |||
101 | #ifdef CONFIG_OF | ||
102 | pdev->dev.of_node = dev->dev.of_node; | ||
103 | #endif | ||
104 | pdev->dev.release = plat_dev_release; | ||
105 | |||
106 | spi_pdata->num_chipselect = dev->devfn; | ||
107 | |||
108 | ssp->phys_base = pci_resource_start(dev, 0); | ||
109 | ssp->mmio_base = ioremap(phys_beg, phys_len); | ||
110 | if (!ssp->mmio_base) { | ||
111 | dev_err(&pdev->dev, "failed to ioremap() registers\n"); | ||
112 | ret = -EIO; | ||
113 | goto err_remap; | ||
114 | } | ||
115 | ssp->irq = dev->irq; | ||
116 | ssp->port_id = pdev->id; | ||
117 | ssp->type = PXA25x_SSP; | ||
118 | |||
119 | mutex_lock(&ssp_lock); | ||
120 | list_add(&ssp->node, &ssp_list); | ||
121 | mutex_unlock(&ssp_lock); | ||
122 | |||
123 | pci_set_drvdata(dev, spi_info); | ||
124 | |||
125 | ret = platform_device_register(pdev); | ||
126 | if (ret) | ||
127 | goto err_dev_add; | ||
128 | |||
129 | return ret; | ||
130 | |||
131 | err_dev_add: | ||
132 | pci_set_drvdata(dev, NULL); | ||
133 | mutex_lock(&ssp_lock); | ||
134 | list_del(&ssp->node); | ||
135 | mutex_unlock(&ssp_lock); | ||
136 | iounmap(ssp->mmio_base); | ||
137 | |||
138 | err_remap: | ||
139 | kfree(spi_info); | ||
140 | |||
141 | err_kz: | ||
142 | release_mem_region(phys_beg, phys_len); | ||
143 | |||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | static void __devexit ce4100_spi_remove(struct pci_dev *dev) | ||
148 | { | ||
149 | struct awesome_struct *spi_info; | ||
150 | struct platform_device *pdev; | ||
151 | struct ssp_device *ssp; | ||
152 | |||
153 | spi_info = pci_get_drvdata(dev); | ||
154 | |||
155 | ssp = &spi_info->ssp; | ||
156 | pdev = &spi_info->spi_pdev; | ||
157 | |||
158 | platform_device_unregister(pdev); | ||
159 | |||
160 | iounmap(ssp->mmio_base); | ||
161 | release_mem_region(pci_resource_start(dev, 0), | ||
162 | pci_resource_len(dev, 0)); | ||
163 | |||
164 | mutex_lock(&ssp_lock); | ||
165 | list_del(&ssp->node); | ||
166 | mutex_unlock(&ssp_lock); | ||
167 | |||
168 | pci_set_drvdata(dev, NULL); | ||
169 | pci_disable_device(dev); | ||
170 | kfree(spi_info); | ||
171 | } | ||
172 | |||
173 | static struct pci_device_id ce4100_spi_devices[] __devinitdata = { | ||
174 | |||
175 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) }, | ||
176 | { }, | ||
177 | }; | ||
178 | MODULE_DEVICE_TABLE(pci, ce4100_spi_devices); | ||
179 | |||
180 | static struct pci_driver ce4100_spi_driver = { | ||
181 | .name = "ce4100_spi", | ||
182 | .id_table = ce4100_spi_devices, | ||
183 | .probe = ce4100_spi_probe, | ||
184 | .remove = __devexit_p(ce4100_spi_remove), | ||
185 | }; | ||
186 | |||
187 | static int __init ce4100_spi_init(void) | ||
188 | { | ||
189 | return pci_register_driver(&ce4100_spi_driver); | ||
190 | } | ||
191 | module_init(ce4100_spi_init); | ||
192 | |||
193 | static void __exit ce4100_spi_exit(void) | ||
194 | { | ||
195 | pci_unregister_driver(&ce4100_spi_driver); | ||
196 | } | ||
197 | module_exit(ce4100_spi_exit); | ||
198 | |||
199 | MODULE_DESCRIPTION("CE4100 PCI-SPI glue code for PXA's driver"); | ||
200 | MODULE_LICENSE("GPL v2"); | ||
201 | MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>"); | ||