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 | |
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.
...
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | arch/arm/mach-w90x900/include/mach/nuc900_spi.h | 35 | ||||
-rw-r--r-- | drivers/spi/Kconfig | 40 | ||||
-rw-r--r-- | drivers/spi/Makefile | 5 | ||||
-rw-r--r-- | drivers/spi/au1550_spi.c | 10 | ||||
-rw-r--r-- | drivers/spi/mpc52xx_spi.c | 86 | ||||
-rw-r--r-- | drivers/spi/omap_spi_100k.c | 635 | ||||
-rw-r--r-- | drivers/spi/spi_imx.c | 35 | ||||
-rw-r--r-- | drivers/spi/spi_mpc8xxx.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi_nuc900.c | 504 | ||||
-rw-r--r-- | drivers/spi/spi_sh_msiof.c | 691 | ||||
-rw-r--r-- | drivers/spi/spidev.c | 6 | ||||
-rw-r--r-- | drivers/spi/xilinx_spi.c | 355 | ||||
-rw-r--r-- | drivers/spi/xilinx_spi.h | 32 | ||||
-rw-r--r-- | drivers/spi/xilinx_spi_of.c | 134 | ||||
-rw-r--r-- | drivers/spi/xilinx_spi_pltfm.c | 102 | ||||
-rw-r--r-- | include/linux/spi/mpc52xx_spi.h | 10 | ||||
-rw-r--r-- | include/linux/spi/sh_msiof.h | 10 | ||||
-rw-r--r-- | include/linux/spi/xilinx_spi.h | 20 |
19 files changed, 2484 insertions, 229 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index cff133be42c6..1f21c34124db 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -5080,6 +5080,7 @@ F: drivers/char/specialix* | |||
5080 | 5080 | ||
5081 | SPI SUBSYSTEM | 5081 | SPI SUBSYSTEM |
5082 | M: David Brownell <dbrownell@users.sourceforge.net> | 5082 | M: David Brownell <dbrownell@users.sourceforge.net> |
5083 | M: Grant Likely <grant.likely@secretlab.ca> | ||
5083 | L: spi-devel-general@lists.sourceforge.net | 5084 | L: spi-devel-general@lists.sourceforge.net |
5084 | S: Maintained | 5085 | S: Maintained |
5085 | F: Documentation/spi/ | 5086 | F: Documentation/spi/ |
diff --git a/arch/arm/mach-w90x900/include/mach/nuc900_spi.h b/arch/arm/mach-w90x900/include/mach/nuc900_spi.h new file mode 100644 index 000000000000..bd94819e314f --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/nuc900_spi.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-w90x900/include/mach/nuc900_spi.h | ||
3 | * | ||
4 | * Copyright (c) 2009 Nuvoton technology corporation. | ||
5 | * | ||
6 | * Wan ZongShun <mcuos.com@gmail.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation;version 2 of the License. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #ifndef __ASM_ARCH_SPI_H | ||
15 | #define __ASM_ARCH_SPI_H | ||
16 | |||
17 | extern void mfp_set_groupg(struct device *dev); | ||
18 | |||
19 | struct nuc900_spi_info { | ||
20 | unsigned int num_cs; | ||
21 | unsigned int lsb; | ||
22 | unsigned int txneg; | ||
23 | unsigned int rxneg; | ||
24 | unsigned int divider; | ||
25 | unsigned int sleep; | ||
26 | unsigned int txnum; | ||
27 | unsigned int txbitlen; | ||
28 | int bus_num; | ||
29 | }; | ||
30 | |||
31 | struct nuc900_spi_chip { | ||
32 | unsigned char bits_per_word; | ||
33 | }; | ||
34 | |||
35 | #endif /* __ASM_ARCH_SPI_H */ | ||
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 28fce65b8594..2d9d70359360 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -169,6 +169,12 @@ config SPI_OMAP24XX | |||
169 | SPI master controller for OMAP24xx/OMAP34xx Multichannel SPI | 169 | SPI master controller for OMAP24xx/OMAP34xx Multichannel SPI |
170 | (McSPI) modules. | 170 | (McSPI) modules. |
171 | 171 | ||
172 | config SPI_OMAP_100K | ||
173 | tristate "OMAP SPI 100K" | ||
174 | depends on SPI_MASTER && (ARCH_OMAP850 || ARCH_OMAP730) | ||
175 | help | ||
176 | OMAP SPI 100K master controller for omap7xx boards. | ||
177 | |||
172 | config SPI_ORION | 178 | config SPI_ORION |
173 | tristate "Orion SPI master (EXPERIMENTAL)" | 179 | tristate "Orion SPI master (EXPERIMENTAL)" |
174 | depends on PLAT_ORION && EXPERIMENTAL | 180 | depends on PLAT_ORION && EXPERIMENTAL |
@@ -220,6 +226,13 @@ config SPI_S3C24XX_GPIO | |||
220 | the inbuilt hardware cannot provide the transfer mode, or | 226 | the inbuilt hardware cannot provide the transfer mode, or |
221 | where the board is using non hardware connected pins. | 227 | where the board is using non hardware connected pins. |
222 | 228 | ||
229 | config SPI_SH_MSIOF | ||
230 | tristate "SuperH MSIOF SPI controller" | ||
231 | depends on SUPERH && HAVE_CLK | ||
232 | select SPI_BITBANG | ||
233 | help | ||
234 | SPI driver for SuperH MSIOF blocks. | ||
235 | |||
223 | config SPI_SH_SCI | 236 | config SPI_SH_SCI |
224 | tristate "SuperH SCI SPI controller" | 237 | tristate "SuperH SCI SPI controller" |
225 | depends on SUPERH | 238 | depends on SUPERH |
@@ -240,15 +253,38 @@ config SPI_TXX9 | |||
240 | SPI driver for Toshiba TXx9 MIPS SoCs | 253 | SPI driver for Toshiba TXx9 MIPS SoCs |
241 | 254 | ||
242 | config SPI_XILINX | 255 | config SPI_XILINX |
243 | tristate "Xilinx SPI controller" | 256 | tristate "Xilinx SPI controller common module" |
244 | depends on (XILINX_VIRTEX || MICROBLAZE) && EXPERIMENTAL | 257 | depends on HAS_IOMEM && EXPERIMENTAL |
245 | select SPI_BITBANG | 258 | select SPI_BITBANG |
259 | select SPI_XILINX_OF if (XILINX_VIRTEX || MICROBLAZE) | ||
246 | help | 260 | help |
247 | This exposes the SPI controller IP from the Xilinx EDK. | 261 | This exposes the SPI controller IP from the Xilinx EDK. |
248 | 262 | ||
249 | See the "OPB Serial Peripheral Interface (SPI) (v1.00e)" | 263 | See the "OPB Serial Peripheral Interface (SPI) (v1.00e)" |
250 | Product Specification document (DS464) for hardware details. | 264 | Product Specification document (DS464) for hardware details. |
251 | 265 | ||
266 | Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)" | ||
267 | |||
268 | config SPI_XILINX_OF | ||
269 | tristate "Xilinx SPI controller OF device" | ||
270 | depends on SPI_XILINX && (XILINX_VIRTEX || MICROBLAZE) | ||
271 | help | ||
272 | This is the OF driver for the SPI controller IP from the Xilinx EDK. | ||
273 | |||
274 | config SPI_XILINX_PLTFM | ||
275 | tristate "Xilinx SPI controller platform device" | ||
276 | depends on SPI_XILINX | ||
277 | help | ||
278 | This is the platform driver for the SPI controller IP | ||
279 | from the Xilinx EDK. | ||
280 | |||
281 | config SPI_NUC900 | ||
282 | tristate "Nuvoton NUC900 series SPI" | ||
283 | depends on ARCH_W90X900 && EXPERIMENTAL | ||
284 | select SPI_BITBANG | ||
285 | help | ||
286 | SPI driver for Nuvoton NUC900 series ARM SoCs | ||
287 | |||
252 | # | 288 | # |
253 | # Add new SPI master controllers in alphabetical order above this line | 289 | # Add new SPI master controllers in alphabetical order above this line |
254 | # | 290 | # |
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index e3f092a9afa5..ed8c1675b52f 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile | |||
@@ -22,6 +22,7 @@ obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o | |||
22 | obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o | 22 | obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o |
23 | obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o | 23 | obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o |
24 | obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o | 24 | obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o |
25 | obj-$(CONFIG_SPI_OMAP_100K) += omap_spi_100k.o | ||
25 | obj-$(CONFIG_SPI_ORION) += orion_spi.o | 26 | obj-$(CONFIG_SPI_ORION) += orion_spi.o |
26 | obj-$(CONFIG_SPI_PL022) += amba-pl022.o | 27 | obj-$(CONFIG_SPI_PL022) += amba-pl022.o |
27 | obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o | 28 | obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o |
@@ -32,8 +33,12 @@ obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o | |||
32 | obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o | 33 | obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o |
33 | obj-$(CONFIG_SPI_TXX9) += spi_txx9.o | 34 | obj-$(CONFIG_SPI_TXX9) += spi_txx9.o |
34 | obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o | 35 | obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o |
36 | obj-$(CONFIG_SPI_XILINX_OF) += xilinx_spi_of.o | ||
37 | obj-$(CONFIG_SPI_XILINX_PLTFM) += xilinx_spi_pltfm.o | ||
35 | obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o | 38 | obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o |
39 | obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o | ||
36 | obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o | 40 | obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o |
41 | obj-$(CONFIG_SPI_NUC900) += spi_nuc900.o | ||
37 | # ... add above this line ... | 42 | # ... add above this line ... |
38 | 43 | ||
39 | # SPI protocol drivers (device/link on bus) | 44 | # SPI protocol drivers (device/link on bus) |
diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c index 76cbc1a66598..cfd5ff9508fa 100644 --- a/drivers/spi/au1550_spi.c +++ b/drivers/spi/au1550_spi.c | |||
@@ -237,8 +237,14 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t) | |||
237 | unsigned bpw, hz; | 237 | unsigned bpw, hz; |
238 | u32 cfg, stat; | 238 | u32 cfg, stat; |
239 | 239 | ||
240 | bpw = t ? t->bits_per_word : spi->bits_per_word; | 240 | bpw = spi->bits_per_word; |
241 | hz = t ? t->speed_hz : spi->max_speed_hz; | 241 | hz = spi->max_speed_hz; |
242 | if (t) { | ||
243 | if (t->bits_per_word) | ||
244 | bpw = t->bits_per_word; | ||
245 | if (t->speed_hz) | ||
246 | hz = t->speed_hz; | ||
247 | } | ||
242 | 248 | ||
243 | if (bpw < 4 || bpw > 24) { | 249 | if (bpw < 4 || bpw > 24) { |
244 | dev_err(&spi->dev, "setupxfer: invalid bits_per_word=%d\n", | 250 | dev_err(&spi->dev, "setupxfer: invalid bits_per_word=%d\n", |
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); |
diff --git a/drivers/spi/omap_spi_100k.c b/drivers/spi/omap_spi_100k.c new file mode 100644 index 000000000000..5355d90d1bee --- /dev/null +++ b/drivers/spi/omap_spi_100k.c | |||
@@ -0,0 +1,635 @@ | |||
1 | /* | ||
2 | * OMAP7xx SPI 100k controller driver | ||
3 | * Author: Fabrice Crohas <fcrohas@gmail.com> | ||
4 | * from original omap1_mcspi driver | ||
5 | * | ||
6 | * Copyright (C) 2005, 2006 Nokia Corporation | ||
7 | * Author: Samuel Ortiz <samuel.ortiz@nokia.com> and | ||
8 | * Juha Yrj�l� <juha.yrjola@nokia.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | * | ||
24 | */ | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/device.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/platform_device.h> | ||
32 | #include <linux/err.h> | ||
33 | #include <linux/clk.h> | ||
34 | #include <linux/io.h> | ||
35 | #include <linux/gpio.h> | ||
36 | |||
37 | #include <linux/spi/spi.h> | ||
38 | |||
39 | #include <plat/clock.h> | ||
40 | |||
41 | #define OMAP1_SPI100K_MAX_FREQ 48000000 | ||
42 | |||
43 | #define ICR_SPITAS (OMAP7XX_ICR_BASE + 0x12) | ||
44 | |||
45 | #define SPI_SETUP1 0x00 | ||
46 | #define SPI_SETUP2 0x02 | ||
47 | #define SPI_CTRL 0x04 | ||
48 | #define SPI_STATUS 0x06 | ||
49 | #define SPI_TX_LSB 0x08 | ||
50 | #define SPI_TX_MSB 0x0a | ||
51 | #define SPI_RX_LSB 0x0c | ||
52 | #define SPI_RX_MSB 0x0e | ||
53 | |||
54 | #define SPI_SETUP1_INT_READ_ENABLE (1UL << 5) | ||
55 | #define SPI_SETUP1_INT_WRITE_ENABLE (1UL << 4) | ||
56 | #define SPI_SETUP1_CLOCK_DIVISOR(x) ((x) << 1) | ||
57 | #define SPI_SETUP1_CLOCK_ENABLE (1UL << 0) | ||
58 | |||
59 | #define SPI_SETUP2_ACTIVE_EDGE_FALLING (0UL << 0) | ||
60 | #define SPI_SETUP2_ACTIVE_EDGE_RISING (1UL << 0) | ||
61 | #define SPI_SETUP2_NEGATIVE_LEVEL (0UL << 5) | ||
62 | #define SPI_SETUP2_POSITIVE_LEVEL (1UL << 5) | ||
63 | #define SPI_SETUP2_LEVEL_TRIGGER (0UL << 10) | ||
64 | #define SPI_SETUP2_EDGE_TRIGGER (1UL << 10) | ||
65 | |||
66 | #define SPI_CTRL_SEN(x) ((x) << 7) | ||
67 | #define SPI_CTRL_WORD_SIZE(x) (((x) - 1) << 2) | ||
68 | #define SPI_CTRL_WR (1UL << 1) | ||
69 | #define SPI_CTRL_RD (1UL << 0) | ||
70 | |||
71 | #define SPI_STATUS_WE (1UL << 1) | ||
72 | #define SPI_STATUS_RD (1UL << 0) | ||
73 | |||
74 | #define WRITE 0 | ||
75 | #define READ 1 | ||
76 | |||
77 | |||
78 | /* use PIO for small transfers, avoiding DMA setup/teardown overhead and | ||
79 | * cache operations; better heuristics consider wordsize and bitrate. | ||
80 | */ | ||
81 | #define DMA_MIN_BYTES 8 | ||
82 | |||
83 | #define SPI_RUNNING 0 | ||
84 | #define SPI_SHUTDOWN 1 | ||
85 | |||
86 | struct omap1_spi100k { | ||
87 | struct work_struct work; | ||
88 | |||
89 | /* lock protects queue and registers */ | ||
90 | spinlock_t lock; | ||
91 | struct list_head msg_queue; | ||
92 | struct spi_master *master; | ||
93 | struct clk *ick; | ||
94 | struct clk *fck; | ||
95 | |||
96 | /* Virtual base address of the controller */ | ||
97 | void __iomem *base; | ||
98 | |||
99 | /* State of the SPI */ | ||
100 | unsigned int state; | ||
101 | }; | ||
102 | |||
103 | struct omap1_spi100k_cs { | ||
104 | void __iomem *base; | ||
105 | int word_len; | ||
106 | }; | ||
107 | |||
108 | static struct workqueue_struct *omap1_spi100k_wq; | ||
109 | |||
110 | #define MOD_REG_BIT(val, mask, set) do { \ | ||
111 | if (set) \ | ||
112 | val |= mask; \ | ||
113 | else \ | ||
114 | val &= ~mask; \ | ||
115 | } while (0) | ||
116 | |||
117 | static void spi100k_enable_clock(struct spi_master *master) | ||
118 | { | ||
119 | unsigned int val; | ||
120 | struct omap1_spi100k *spi100k = spi_master_get_devdata(master); | ||
121 | |||
122 | /* enable SPI */ | ||
123 | val = readw(spi100k->base + SPI_SETUP1); | ||
124 | val |= SPI_SETUP1_CLOCK_ENABLE; | ||
125 | writew(val, spi100k->base + SPI_SETUP1); | ||
126 | } | ||
127 | |||
128 | static void spi100k_disable_clock(struct spi_master *master) | ||
129 | { | ||
130 | unsigned int val; | ||
131 | struct omap1_spi100k *spi100k = spi_master_get_devdata(master); | ||
132 | |||
133 | /* disable SPI */ | ||
134 | val = readw(spi100k->base + SPI_SETUP1); | ||
135 | val &= ~SPI_SETUP1_CLOCK_ENABLE; | ||
136 | writew(val, spi100k->base + SPI_SETUP1); | ||
137 | } | ||
138 | |||
139 | static void spi100k_write_data(struct spi_master *master, int len, int data) | ||
140 | { | ||
141 | struct omap1_spi100k *spi100k = spi_master_get_devdata(master); | ||
142 | |||
143 | /* write 16-bit word */ | ||
144 | spi100k_enable_clock(master); | ||
145 | writew( data , spi100k->base + SPI_TX_MSB); | ||
146 | |||
147 | writew(SPI_CTRL_SEN(0) | | ||
148 | SPI_CTRL_WORD_SIZE(len) | | ||
149 | SPI_CTRL_WR, | ||
150 | spi100k->base + SPI_CTRL); | ||
151 | |||
152 | /* Wait for bit ack send change */ | ||
153 | while((readw(spi100k->base + SPI_STATUS) & SPI_STATUS_WE) != SPI_STATUS_WE); | ||
154 | udelay(1000); | ||
155 | |||
156 | spi100k_disable_clock(master); | ||
157 | } | ||
158 | |||
159 | static int spi100k_read_data(struct spi_master *master, int len) | ||
160 | { | ||
161 | int dataH,dataL; | ||
162 | struct omap1_spi100k *spi100k = spi_master_get_devdata(master); | ||
163 | |||
164 | spi100k_enable_clock(master); | ||
165 | writew(SPI_CTRL_SEN(0) | | ||
166 | SPI_CTRL_WORD_SIZE(len) | | ||
167 | SPI_CTRL_RD, | ||
168 | spi100k->base + SPI_CTRL); | ||
169 | |||
170 | while((readw(spi100k->base + SPI_STATUS) & SPI_STATUS_RD) != SPI_STATUS_RD); | ||
171 | udelay(1000); | ||
172 | |||
173 | dataL = readw(spi100k->base + SPI_RX_LSB); | ||
174 | dataH = readw(spi100k->base + SPI_RX_MSB); | ||
175 | spi100k_disable_clock(master); | ||
176 | |||
177 | return dataL; | ||
178 | } | ||
179 | |||
180 | static void spi100k_open(struct spi_master *master) | ||
181 | { | ||
182 | /* get control of SPI */ | ||
183 | struct omap1_spi100k *spi100k = spi_master_get_devdata(master); | ||
184 | |||
185 | writew(SPI_SETUP1_INT_READ_ENABLE | | ||
186 | SPI_SETUP1_INT_WRITE_ENABLE | | ||
187 | SPI_SETUP1_CLOCK_DIVISOR(0), spi100k->base + SPI_SETUP1); | ||
188 | |||
189 | /* configure clock and interrupts */ | ||
190 | writew(SPI_SETUP2_ACTIVE_EDGE_FALLING | | ||
191 | SPI_SETUP2_NEGATIVE_LEVEL | | ||
192 | SPI_SETUP2_LEVEL_TRIGGER, spi100k->base + SPI_SETUP2); | ||
193 | } | ||
194 | |||
195 | static void omap1_spi100k_force_cs(struct omap1_spi100k *spi100k, int enable) | ||
196 | { | ||
197 | if (enable) | ||
198 | writew(0x05fc, spi100k->base + SPI_CTRL); | ||
199 | else | ||
200 | writew(0x05fd, spi100k->base + SPI_CTRL); | ||
201 | } | ||
202 | |||
203 | static unsigned | ||
204 | omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | ||
205 | { | ||
206 | struct omap1_spi100k *spi100k; | ||
207 | struct omap1_spi100k_cs *cs = spi->controller_state; | ||
208 | unsigned int count, c; | ||
209 | int word_len; | ||
210 | |||
211 | spi100k = spi_master_get_devdata(spi->master); | ||
212 | count = xfer->len; | ||
213 | c = count; | ||
214 | word_len = cs->word_len; | ||
215 | |||
216 | /* RX_ONLY mode needs dummy data in TX reg */ | ||
217 | if (xfer->tx_buf == NULL) | ||
218 | spi100k_write_data(spi->master,word_len, 0); | ||
219 | |||
220 | if (word_len <= 8) { | ||
221 | u8 *rx; | ||
222 | const u8 *tx; | ||
223 | |||
224 | rx = xfer->rx_buf; | ||
225 | tx = xfer->tx_buf; | ||
226 | do { | ||
227 | c-=1; | ||
228 | if (xfer->tx_buf != NULL) | ||
229 | spi100k_write_data(spi->master,word_len, *tx); | ||
230 | if (xfer->rx_buf != NULL) | ||
231 | *rx = spi100k_read_data(spi->master,word_len); | ||
232 | } while(c); | ||
233 | } else if (word_len <= 16) { | ||
234 | u16 *rx; | ||
235 | const u16 *tx; | ||
236 | |||
237 | rx = xfer->rx_buf; | ||
238 | tx = xfer->tx_buf; | ||
239 | do { | ||
240 | c-=2; | ||
241 | if (xfer->tx_buf != NULL) | ||
242 | spi100k_write_data(spi->master,word_len, *tx++); | ||
243 | if (xfer->rx_buf != NULL) | ||
244 | *rx++ = spi100k_read_data(spi->master,word_len); | ||
245 | } while(c); | ||
246 | } else if (word_len <= 32) { | ||
247 | u32 *rx; | ||
248 | const u32 *tx; | ||
249 | |||
250 | rx = xfer->rx_buf; | ||
251 | tx = xfer->tx_buf; | ||
252 | do { | ||
253 | c-=4; | ||
254 | if (xfer->tx_buf != NULL) | ||
255 | spi100k_write_data(spi->master,word_len, *tx); | ||
256 | if (xfer->rx_buf != NULL) | ||
257 | *rx = spi100k_read_data(spi->master,word_len); | ||
258 | } while(c); | ||
259 | } | ||
260 | return count - c; | ||
261 | } | ||
262 | |||
263 | /* called only when no transfer is active to this device */ | ||
264 | static int omap1_spi100k_setup_transfer(struct spi_device *spi, | ||
265 | struct spi_transfer *t) | ||
266 | { | ||
267 | struct omap1_spi100k *spi100k = spi_master_get_devdata(spi->master); | ||
268 | struct omap1_spi100k_cs *cs = spi->controller_state; | ||
269 | u8 word_len = spi->bits_per_word; | ||
270 | |||
271 | if (t != NULL && t->bits_per_word) | ||
272 | word_len = t->bits_per_word; | ||
273 | if (!word_len) | ||
274 | word_len = 8; | ||
275 | |||
276 | if (spi->bits_per_word > 32) | ||
277 | return -EINVAL; | ||
278 | cs->word_len = word_len; | ||
279 | |||
280 | /* SPI init before transfer */ | ||
281 | writew(0x3e , spi100k->base + SPI_SETUP1); | ||
282 | writew(0x00 , spi100k->base + SPI_STATUS); | ||
283 | writew(0x3e , spi100k->base + SPI_CTRL); | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | /* the spi->mode bits understood by this driver: */ | ||
289 | #define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) | ||
290 | |||
291 | static int omap1_spi100k_setup(struct spi_device *spi) | ||
292 | { | ||
293 | int ret; | ||
294 | struct omap1_spi100k *spi100k; | ||
295 | struct omap1_spi100k_cs *cs = spi->controller_state; | ||
296 | |||
297 | if (spi->bits_per_word < 4 || spi->bits_per_word > 32) { | ||
298 | dev_dbg(&spi->dev, "setup: unsupported %d bit words\n", | ||
299 | spi->bits_per_word); | ||
300 | return -EINVAL; | ||
301 | } | ||
302 | |||
303 | spi100k = spi_master_get_devdata(spi->master); | ||
304 | |||
305 | if (!cs) { | ||
306 | cs = kzalloc(sizeof *cs, GFP_KERNEL); | ||
307 | if (!cs) | ||
308 | return -ENOMEM; | ||
309 | cs->base = spi100k->base + spi->chip_select * 0x14; | ||
310 | spi->controller_state = cs; | ||
311 | } | ||
312 | |||
313 | spi100k_open(spi->master); | ||
314 | |||
315 | clk_enable(spi100k->ick); | ||
316 | clk_enable(spi100k->fck); | ||
317 | |||
318 | ret = omap1_spi100k_setup_transfer(spi, NULL); | ||
319 | |||
320 | clk_disable(spi100k->ick); | ||
321 | clk_disable(spi100k->fck); | ||
322 | |||
323 | return ret; | ||
324 | } | ||
325 | |||
326 | static void omap1_spi100k_work(struct work_struct *work) | ||
327 | { | ||
328 | struct omap1_spi100k *spi100k; | ||
329 | int status = 0; | ||
330 | |||
331 | spi100k = container_of(work, struct omap1_spi100k, work); | ||
332 | spin_lock_irq(&spi100k->lock); | ||
333 | |||
334 | clk_enable(spi100k->ick); | ||
335 | clk_enable(spi100k->fck); | ||
336 | |||
337 | /* We only enable one channel at a time -- the one whose message is | ||
338 | * at the head of the queue -- although this controller would gladly | ||
339 | * arbitrate among multiple channels. This corresponds to "single | ||
340 | * channel" master mode. As a side effect, we need to manage the | ||
341 | * chipselect with the FORCE bit ... CS != channel enable. | ||
342 | */ | ||
343 | while (!list_empty(&spi100k->msg_queue)) { | ||
344 | struct spi_message *m; | ||
345 | struct spi_device *spi; | ||
346 | struct spi_transfer *t = NULL; | ||
347 | int cs_active = 0; | ||
348 | struct omap1_spi100k_cs *cs; | ||
349 | int par_override = 0; | ||
350 | |||
351 | m = container_of(spi100k->msg_queue.next, struct spi_message, | ||
352 | queue); | ||
353 | |||
354 | list_del_init(&m->queue); | ||
355 | spin_unlock_irq(&spi100k->lock); | ||
356 | |||
357 | spi = m->spi; | ||
358 | cs = spi->controller_state; | ||
359 | |||
360 | list_for_each_entry(t, &m->transfers, transfer_list) { | ||
361 | if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { | ||
362 | status = -EINVAL; | ||
363 | break; | ||
364 | } | ||
365 | if (par_override || t->speed_hz || t->bits_per_word) { | ||
366 | par_override = 1; | ||
367 | status = omap1_spi100k_setup_transfer(spi, t); | ||
368 | if (status < 0) | ||
369 | break; | ||
370 | if (!t->speed_hz && !t->bits_per_word) | ||
371 | par_override = 0; | ||
372 | } | ||
373 | |||
374 | if (!cs_active) { | ||
375 | omap1_spi100k_force_cs(spi100k, 1); | ||
376 | cs_active = 1; | ||
377 | } | ||
378 | |||
379 | if (t->len) { | ||
380 | unsigned count; | ||
381 | |||
382 | /* RX_ONLY mode needs dummy data in TX reg */ | ||
383 | if (t->tx_buf == NULL) | ||
384 | spi100k_write_data(spi->master, 8, 0); | ||
385 | |||
386 | count = omap1_spi100k_txrx_pio(spi, t); | ||
387 | m->actual_length += count; | ||
388 | |||
389 | if (count != t->len) { | ||
390 | status = -EIO; | ||
391 | break; | ||
392 | } | ||
393 | } | ||
394 | |||
395 | if (t->delay_usecs) | ||
396 | udelay(t->delay_usecs); | ||
397 | |||
398 | /* ignore the "leave it on after last xfer" hint */ | ||
399 | |||
400 | if (t->cs_change) { | ||
401 | omap1_spi100k_force_cs(spi100k, 0); | ||
402 | cs_active = 0; | ||
403 | } | ||
404 | } | ||
405 | |||
406 | /* Restore defaults if they were overriden */ | ||
407 | if (par_override) { | ||
408 | par_override = 0; | ||
409 | status = omap1_spi100k_setup_transfer(spi, NULL); | ||
410 | } | ||
411 | |||
412 | if (cs_active) | ||
413 | omap1_spi100k_force_cs(spi100k, 0); | ||
414 | |||
415 | m->status = status; | ||
416 | m->complete(m->context); | ||
417 | |||
418 | spin_lock_irq(&spi100k->lock); | ||
419 | } | ||
420 | |||
421 | clk_disable(spi100k->ick); | ||
422 | clk_disable(spi100k->fck); | ||
423 | spin_unlock_irq(&spi100k->lock); | ||
424 | |||
425 | if (status < 0) | ||
426 | printk(KERN_WARNING "spi transfer failed with %d\n", status); | ||
427 | } | ||
428 | |||
429 | static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m) | ||
430 | { | ||
431 | struct omap1_spi100k *spi100k; | ||
432 | unsigned long flags; | ||
433 | struct spi_transfer *t; | ||
434 | |||
435 | m->actual_length = 0; | ||
436 | m->status = -EINPROGRESS; | ||
437 | |||
438 | spi100k = spi_master_get_devdata(spi->master); | ||
439 | |||
440 | /* Don't accept new work if we're shutting down */ | ||
441 | if (spi100k->state == SPI_SHUTDOWN) | ||
442 | return -ESHUTDOWN; | ||
443 | |||
444 | /* reject invalid messages and transfers */ | ||
445 | if (list_empty(&m->transfers) || !m->complete) | ||
446 | return -EINVAL; | ||
447 | |||
448 | list_for_each_entry(t, &m->transfers, transfer_list) { | ||
449 | const void *tx_buf = t->tx_buf; | ||
450 | void *rx_buf = t->rx_buf; | ||
451 | unsigned len = t->len; | ||
452 | |||
453 | if (t->speed_hz > OMAP1_SPI100K_MAX_FREQ | ||
454 | || (len && !(rx_buf || tx_buf)) | ||
455 | || (t->bits_per_word && | ||
456 | ( t->bits_per_word < 4 | ||
457 | || t->bits_per_word > 32))) { | ||
458 | dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n", | ||
459 | t->speed_hz, | ||
460 | len, | ||
461 | tx_buf ? "tx" : "", | ||
462 | rx_buf ? "rx" : "", | ||
463 | t->bits_per_word); | ||
464 | return -EINVAL; | ||
465 | } | ||
466 | |||
467 | if (t->speed_hz && t->speed_hz < OMAP1_SPI100K_MAX_FREQ/(1<<16)) { | ||
468 | dev_dbg(&spi->dev, "%d Hz max exceeds %d\n", | ||
469 | t->speed_hz, | ||
470 | OMAP1_SPI100K_MAX_FREQ/(1<<16)); | ||
471 | return -EINVAL; | ||
472 | } | ||
473 | |||
474 | } | ||
475 | |||
476 | spin_lock_irqsave(&spi100k->lock, flags); | ||
477 | list_add_tail(&m->queue, &spi100k->msg_queue); | ||
478 | queue_work(omap1_spi100k_wq, &spi100k->work); | ||
479 | spin_unlock_irqrestore(&spi100k->lock, flags); | ||
480 | |||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | static int __init omap1_spi100k_reset(struct omap1_spi100k *spi100k) | ||
485 | { | ||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | static int __devinit omap1_spi100k_probe(struct platform_device *pdev) | ||
490 | { | ||
491 | struct spi_master *master; | ||
492 | struct omap1_spi100k *spi100k; | ||
493 | int status = 0; | ||
494 | |||
495 | if (!pdev->id) | ||
496 | return -EINVAL; | ||
497 | |||
498 | master = spi_alloc_master(&pdev->dev, sizeof *spi100k); | ||
499 | if (master == NULL) { | ||
500 | dev_dbg(&pdev->dev, "master allocation failed\n"); | ||
501 | return -ENOMEM; | ||
502 | } | ||
503 | |||
504 | if (pdev->id != -1) | ||
505 | master->bus_num = pdev->id; | ||
506 | |||
507 | master->setup = omap1_spi100k_setup; | ||
508 | master->transfer = omap1_spi100k_transfer; | ||
509 | master->cleanup = NULL; | ||
510 | master->num_chipselect = 2; | ||
511 | master->mode_bits = MODEBITS; | ||
512 | |||
513 | dev_set_drvdata(&pdev->dev, master); | ||
514 | |||
515 | spi100k = spi_master_get_devdata(master); | ||
516 | spi100k->master = master; | ||
517 | |||
518 | /* | ||
519 | * The memory region base address is taken as the platform_data. | ||
520 | * You should allocate this with ioremap() before initializing | ||
521 | * the SPI. | ||
522 | */ | ||
523 | spi100k->base = (void __iomem *) pdev->dev.platform_data; | ||
524 | |||
525 | INIT_WORK(&spi100k->work, omap1_spi100k_work); | ||
526 | |||
527 | spin_lock_init(&spi100k->lock); | ||
528 | INIT_LIST_HEAD(&spi100k->msg_queue); | ||
529 | spi100k->ick = clk_get(&pdev->dev, "ick"); | ||
530 | if (IS_ERR(spi100k->ick)) { | ||
531 | dev_dbg(&pdev->dev, "can't get spi100k_ick\n"); | ||
532 | status = PTR_ERR(spi100k->ick); | ||
533 | goto err1; | ||
534 | } | ||
535 | |||
536 | spi100k->fck = clk_get(&pdev->dev, "fck"); | ||
537 | if (IS_ERR(spi100k->fck)) { | ||
538 | dev_dbg(&pdev->dev, "can't get spi100k_fck\n"); | ||
539 | status = PTR_ERR(spi100k->fck); | ||
540 | goto err2; | ||
541 | } | ||
542 | |||
543 | if (omap1_spi100k_reset(spi100k) < 0) | ||
544 | goto err3; | ||
545 | |||
546 | status = spi_register_master(master); | ||
547 | if (status < 0) | ||
548 | goto err3; | ||
549 | |||
550 | spi100k->state = SPI_RUNNING; | ||
551 | |||
552 | return status; | ||
553 | |||
554 | err3: | ||
555 | clk_put(spi100k->fck); | ||
556 | err2: | ||
557 | clk_put(spi100k->ick); | ||
558 | err1: | ||
559 | spi_master_put(master); | ||
560 | return status; | ||
561 | } | ||
562 | |||
563 | static int __exit omap1_spi100k_remove(struct platform_device *pdev) | ||
564 | { | ||
565 | struct spi_master *master; | ||
566 | struct omap1_spi100k *spi100k; | ||
567 | struct resource *r; | ||
568 | unsigned limit = 500; | ||
569 | unsigned long flags; | ||
570 | int status = 0; | ||
571 | |||
572 | master = dev_get_drvdata(&pdev->dev); | ||
573 | spi100k = spi_master_get_devdata(master); | ||
574 | |||
575 | spin_lock_irqsave(&spi100k->lock, flags); | ||
576 | |||
577 | spi100k->state = SPI_SHUTDOWN; | ||
578 | while (!list_empty(&spi100k->msg_queue) && limit--) { | ||
579 | spin_unlock_irqrestore(&spi100k->lock, flags); | ||
580 | msleep(10); | ||
581 | spin_lock_irqsave(&spi100k->lock, flags); | ||
582 | } | ||
583 | |||
584 | if (!list_empty(&spi100k->msg_queue)) | ||
585 | status = -EBUSY; | ||
586 | |||
587 | spin_unlock_irqrestore(&spi100k->lock, flags); | ||
588 | |||
589 | if (status != 0) | ||
590 | return status; | ||
591 | |||
592 | clk_put(spi100k->fck); | ||
593 | clk_put(spi100k->ick); | ||
594 | |||
595 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
596 | |||
597 | spi_unregister_master(master); | ||
598 | |||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | static struct platform_driver omap1_spi100k_driver = { | ||
603 | .driver = { | ||
604 | .name = "omap1_spi100k", | ||
605 | .owner = THIS_MODULE, | ||
606 | }, | ||
607 | .remove = __exit_p(omap1_spi100k_remove), | ||
608 | }; | ||
609 | |||
610 | |||
611 | static int __init omap1_spi100k_init(void) | ||
612 | { | ||
613 | omap1_spi100k_wq = create_singlethread_workqueue( | ||
614 | omap1_spi100k_driver.driver.name); | ||
615 | |||
616 | if (omap1_spi100k_wq == NULL) | ||
617 | return -1; | ||
618 | |||
619 | return platform_driver_probe(&omap1_spi100k_driver, omap1_spi100k_probe); | ||
620 | } | ||
621 | |||
622 | static void __exit omap1_spi100k_exit(void) | ||
623 | { | ||
624 | platform_driver_unregister(&omap1_spi100k_driver); | ||
625 | |||
626 | destroy_workqueue(omap1_spi100k_wq); | ||
627 | } | ||
628 | |||
629 | module_init(omap1_spi100k_init); | ||
630 | module_exit(omap1_spi100k_exit); | ||
631 | |||
632 | MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver"); | ||
633 | MODULE_AUTHOR("Fabrice Crohas <fcrohas@gmail.com>"); | ||
634 | MODULE_LICENSE("GPL"); | ||
635 | |||
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c index 89c22efedfb0..1893f1e96dc4 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c | |||
@@ -44,6 +44,9 @@ | |||
44 | #define MXC_CSPIINT 0x0c | 44 | #define MXC_CSPIINT 0x0c |
45 | #define MXC_RESET 0x1c | 45 | #define MXC_RESET 0x1c |
46 | 46 | ||
47 | #define MX3_CSPISTAT 0x14 | ||
48 | #define MX3_CSPISTAT_RR (1 << 3) | ||
49 | |||
47 | /* generic defines to abstract from the different register layouts */ | 50 | /* generic defines to abstract from the different register layouts */ |
48 | #define MXC_INT_RR (1 << 0) /* Receive data ready interrupt */ | 51 | #define MXC_INT_RR (1 << 0) /* Receive data ready interrupt */ |
49 | #define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */ | 52 | #define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */ |
@@ -205,7 +208,7 @@ static int mx31_config(struct spi_imx_data *spi_imx, | |||
205 | 208 | ||
206 | if (cpu_is_mx31()) | 209 | if (cpu_is_mx31()) |
207 | reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT; | 210 | reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT; |
208 | else if (cpu_is_mx35()) { | 211 | else if (cpu_is_mx25() || cpu_is_mx35()) { |
209 | reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT; | 212 | reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT; |
210 | reg |= MX31_CSPICTRL_SSCTL; | 213 | reg |= MX31_CSPICTRL_SSCTL; |
211 | } | 214 | } |
@@ -219,7 +222,7 @@ static int mx31_config(struct spi_imx_data *spi_imx, | |||
219 | if (config->cs < 0) { | 222 | if (config->cs < 0) { |
220 | if (cpu_is_mx31()) | 223 | if (cpu_is_mx31()) |
221 | reg |= (config->cs + 32) << MX31_CSPICTRL_CS_SHIFT; | 224 | reg |= (config->cs + 32) << MX31_CSPICTRL_CS_SHIFT; |
222 | else if (cpu_is_mx35()) | 225 | else if (cpu_is_mx25() || cpu_is_mx35()) |
223 | reg |= (config->cs + 32) << MX35_CSPICTRL_CS_SHIFT; | 226 | reg |= (config->cs + 32) << MX35_CSPICTRL_CS_SHIFT; |
224 | } | 227 | } |
225 | 228 | ||
@@ -481,7 +484,7 @@ static void spi_imx_cleanup(struct spi_device *spi) | |||
481 | { | 484 | { |
482 | } | 485 | } |
483 | 486 | ||
484 | static int __init spi_imx_probe(struct platform_device *pdev) | 487 | static int __devinit spi_imx_probe(struct platform_device *pdev) |
485 | { | 488 | { |
486 | struct spi_imx_master *mxc_platform_info; | 489 | struct spi_imx_master *mxc_platform_info; |
487 | struct spi_master *master; | 490 | struct spi_master *master; |
@@ -489,7 +492,7 @@ static int __init spi_imx_probe(struct platform_device *pdev) | |||
489 | struct resource *res; | 492 | struct resource *res; |
490 | int i, ret; | 493 | int i, ret; |
491 | 494 | ||
492 | mxc_platform_info = (struct spi_imx_master *)pdev->dev.platform_data; | 495 | mxc_platform_info = dev_get_platdata(&pdev->dev); |
493 | if (!mxc_platform_info) { | 496 | if (!mxc_platform_info) { |
494 | dev_err(&pdev->dev, "can't get the platform data\n"); | 497 | dev_err(&pdev->dev, "can't get the platform data\n"); |
495 | return -EINVAL; | 498 | return -EINVAL; |
@@ -513,11 +516,12 @@ static int __init spi_imx_probe(struct platform_device *pdev) | |||
513 | continue; | 516 | continue; |
514 | ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME); | 517 | ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME); |
515 | if (ret) { | 518 | if (ret) { |
516 | i--; | 519 | while (i > 0) { |
517 | while (i > 0) | 520 | i--; |
518 | if (spi_imx->chipselect[i] >= 0) | 521 | if (spi_imx->chipselect[i] >= 0) |
519 | gpio_free(spi_imx->chipselect[i--]); | 522 | gpio_free(spi_imx->chipselect[i]); |
520 | dev_err(&pdev->dev, "can't get cs gpios"); | 523 | } |
524 | dev_err(&pdev->dev, "can't get cs gpios\n"); | ||
521 | goto out_master_put; | 525 | goto out_master_put; |
522 | } | 526 | } |
523 | } | 527 | } |
@@ -551,7 +555,7 @@ static int __init spi_imx_probe(struct platform_device *pdev) | |||
551 | } | 555 | } |
552 | 556 | ||
553 | spi_imx->irq = platform_get_irq(pdev, 0); | 557 | spi_imx->irq = platform_get_irq(pdev, 0); |
554 | if (!spi_imx->irq) { | 558 | if (spi_imx->irq <= 0) { |
555 | ret = -EINVAL; | 559 | ret = -EINVAL; |
556 | goto out_iounmap; | 560 | goto out_iounmap; |
557 | } | 561 | } |
@@ -562,7 +566,7 @@ static int __init spi_imx_probe(struct platform_device *pdev) | |||
562 | goto out_iounmap; | 566 | goto out_iounmap; |
563 | } | 567 | } |
564 | 568 | ||
565 | if (cpu_is_mx31() || cpu_is_mx35()) { | 569 | if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35()) { |
566 | spi_imx->intctrl = mx31_intctrl; | 570 | spi_imx->intctrl = mx31_intctrl; |
567 | spi_imx->config = mx31_config; | 571 | spi_imx->config = mx31_config; |
568 | spi_imx->trigger = mx31_trigger; | 572 | spi_imx->trigger = mx31_trigger; |
@@ -590,9 +594,14 @@ static int __init spi_imx_probe(struct platform_device *pdev) | |||
590 | clk_enable(spi_imx->clk); | 594 | clk_enable(spi_imx->clk); |
591 | spi_imx->spi_clk = clk_get_rate(spi_imx->clk); | 595 | spi_imx->spi_clk = clk_get_rate(spi_imx->clk); |
592 | 596 | ||
593 | if (!cpu_is_mx31() || !cpu_is_mx35()) | 597 | if (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27()) |
594 | writel(1, spi_imx->base + MXC_RESET); | 598 | writel(1, spi_imx->base + MXC_RESET); |
595 | 599 | ||
600 | /* drain receive buffer */ | ||
601 | if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35()) | ||
602 | while (readl(spi_imx->base + MX3_CSPISTAT) & MX3_CSPISTAT_RR) | ||
603 | readl(spi_imx->base + MXC_CSPIRXDATA); | ||
604 | |||
596 | spi_imx->intctrl(spi_imx, 0); | 605 | spi_imx->intctrl(spi_imx, 0); |
597 | 606 | ||
598 | ret = spi_bitbang_start(&spi_imx->bitbang); | 607 | ret = spi_bitbang_start(&spi_imx->bitbang); |
@@ -625,7 +634,7 @@ out_master_put: | |||
625 | return ret; | 634 | return ret; |
626 | } | 635 | } |
627 | 636 | ||
628 | static int __exit spi_imx_remove(struct platform_device *pdev) | 637 | static int __devexit spi_imx_remove(struct platform_device *pdev) |
629 | { | 638 | { |
630 | struct spi_master *master = platform_get_drvdata(pdev); | 639 | struct spi_master *master = platform_get_drvdata(pdev); |
631 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 640 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -659,7 +668,7 @@ static struct platform_driver spi_imx_driver = { | |||
659 | .owner = THIS_MODULE, | 668 | .owner = THIS_MODULE, |
660 | }, | 669 | }, |
661 | .probe = spi_imx_probe, | 670 | .probe = spi_imx_probe, |
662 | .remove = __exit_p(spi_imx_remove), | 671 | .remove = __devexit_p(spi_imx_remove), |
663 | }; | 672 | }; |
664 | 673 | ||
665 | static int __init spi_imx_init(void) | 674 | static int __init spi_imx_init(void) |
diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c index 930135dc73ba..e9390d747bfc 100644 --- a/drivers/spi/spi_mpc8xxx.c +++ b/drivers/spi/spi_mpc8xxx.c | |||
@@ -1356,7 +1356,7 @@ static int __devexit plat_mpc8xxx_spi_remove(struct platform_device *pdev) | |||
1356 | MODULE_ALIAS("platform:mpc8xxx_spi"); | 1356 | MODULE_ALIAS("platform:mpc8xxx_spi"); |
1357 | static struct platform_driver mpc8xxx_spi_driver = { | 1357 | static struct platform_driver mpc8xxx_spi_driver = { |
1358 | .probe = plat_mpc8xxx_spi_probe, | 1358 | .probe = plat_mpc8xxx_spi_probe, |
1359 | .remove = __exit_p(plat_mpc8xxx_spi_remove), | 1359 | .remove = __devexit_p(plat_mpc8xxx_spi_remove), |
1360 | .driver = { | 1360 | .driver = { |
1361 | .name = "mpc8xxx_spi", | 1361 | .name = "mpc8xxx_spi", |
1362 | .owner = THIS_MODULE, | 1362 | .owner = THIS_MODULE, |
diff --git a/drivers/spi/spi_nuc900.c b/drivers/spi/spi_nuc900.c new file mode 100644 index 000000000000..b319f9bf9b9b --- /dev/null +++ b/drivers/spi/spi_nuc900.c | |||
@@ -0,0 +1,504 @@ | |||
1 | /* linux/drivers/spi/spi_nuc900.c | ||
2 | * | ||
3 | * Copyright (c) 2009 Nuvoton technology. | ||
4 | * Wan ZongShun <mcuos.com@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/spinlock.h> | ||
14 | #include <linux/workqueue.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/err.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/io.h> | ||
24 | |||
25 | #include <linux/spi/spi.h> | ||
26 | #include <linux/spi/spi_bitbang.h> | ||
27 | |||
28 | #include <mach/nuc900_spi.h> | ||
29 | |||
30 | /* usi registers offset */ | ||
31 | #define USI_CNT 0x00 | ||
32 | #define USI_DIV 0x04 | ||
33 | #define USI_SSR 0x08 | ||
34 | #define USI_RX0 0x10 | ||
35 | #define USI_TX0 0x10 | ||
36 | |||
37 | /* usi register bit */ | ||
38 | #define ENINT (0x01 << 17) | ||
39 | #define ENFLG (0x01 << 16) | ||
40 | #define TXNUM (0x03 << 8) | ||
41 | #define TXNEG (0x01 << 2) | ||
42 | #define RXNEG (0x01 << 1) | ||
43 | #define LSB (0x01 << 10) | ||
44 | #define SELECTLEV (0x01 << 2) | ||
45 | #define SELECTPOL (0x01 << 31) | ||
46 | #define SELECTSLAVE 0x01 | ||
47 | #define GOBUSY 0x01 | ||
48 | |||
49 | struct nuc900_spi { | ||
50 | struct spi_bitbang bitbang; | ||
51 | struct completion done; | ||
52 | void __iomem *regs; | ||
53 | int irq; | ||
54 | int len; | ||
55 | int count; | ||
56 | const unsigned char *tx; | ||
57 | unsigned char *rx; | ||
58 | struct clk *clk; | ||
59 | struct resource *ioarea; | ||
60 | struct spi_master *master; | ||
61 | struct spi_device *curdev; | ||
62 | struct device *dev; | ||
63 | struct nuc900_spi_info *pdata; | ||
64 | spinlock_t lock; | ||
65 | struct resource *res; | ||
66 | }; | ||
67 | |||
68 | static inline struct nuc900_spi *to_hw(struct spi_device *sdev) | ||
69 | { | ||
70 | return spi_master_get_devdata(sdev->master); | ||
71 | } | ||
72 | |||
73 | static void nuc900_slave_select(struct spi_device *spi, unsigned int ssr) | ||
74 | { | ||
75 | struct nuc900_spi *hw = to_hw(spi); | ||
76 | unsigned int val; | ||
77 | unsigned int cs = spi->mode & SPI_CS_HIGH ? 1 : 0; | ||
78 | unsigned int cpol = spi->mode & SPI_CPOL ? 1 : 0; | ||
79 | unsigned long flags; | ||
80 | |||
81 | spin_lock_irqsave(&hw->lock, flags); | ||
82 | |||
83 | val = __raw_readl(hw->regs + USI_SSR); | ||
84 | |||
85 | if (!cs) | ||
86 | val &= ~SELECTLEV; | ||
87 | else | ||
88 | val |= SELECTLEV; | ||
89 | |||
90 | if (!ssr) | ||
91 | val &= ~SELECTSLAVE; | ||
92 | else | ||
93 | val |= SELECTSLAVE; | ||
94 | |||
95 | __raw_writel(val, hw->regs + USI_SSR); | ||
96 | |||
97 | val = __raw_readl(hw->regs + USI_CNT); | ||
98 | |||
99 | if (!cpol) | ||
100 | val &= ~SELECTPOL; | ||
101 | else | ||
102 | val |= SELECTPOL; | ||
103 | |||
104 | __raw_writel(val, hw->regs + USI_CNT); | ||
105 | |||
106 | spin_unlock_irqrestore(&hw->lock, flags); | ||
107 | } | ||
108 | |||
109 | static void nuc900_spi_chipsel(struct spi_device *spi, int value) | ||
110 | { | ||
111 | switch (value) { | ||
112 | case BITBANG_CS_INACTIVE: | ||
113 | nuc900_slave_select(spi, 0); | ||
114 | break; | ||
115 | |||
116 | case BITBANG_CS_ACTIVE: | ||
117 | nuc900_slave_select(spi, 1); | ||
118 | break; | ||
119 | } | ||
120 | } | ||
121 | |||
122 | static void nuc900_spi_setup_txnum(struct nuc900_spi *hw, | ||
123 | unsigned int txnum) | ||
124 | { | ||
125 | unsigned int val; | ||
126 | unsigned long flags; | ||
127 | |||
128 | spin_lock_irqsave(&hw->lock, flags); | ||
129 | |||
130 | val = __raw_readl(hw->regs + USI_CNT); | ||
131 | |||
132 | if (!txnum) | ||
133 | val &= ~TXNUM; | ||
134 | else | ||
135 | val |= txnum << 0x08; | ||
136 | |||
137 | __raw_writel(val, hw->regs + USI_CNT); | ||
138 | |||
139 | spin_unlock_irqrestore(&hw->lock, flags); | ||
140 | |||
141 | } | ||
142 | |||
143 | static void nuc900_spi_setup_txbitlen(struct nuc900_spi *hw, | ||
144 | unsigned int txbitlen) | ||
145 | { | ||
146 | unsigned int val; | ||
147 | unsigned long flags; | ||
148 | |||
149 | spin_lock_irqsave(&hw->lock, flags); | ||
150 | |||
151 | val = __raw_readl(hw->regs + USI_CNT); | ||
152 | |||
153 | val |= (txbitlen << 0x03); | ||
154 | |||
155 | __raw_writel(val, hw->regs + USI_CNT); | ||
156 | |||
157 | spin_unlock_irqrestore(&hw->lock, flags); | ||
158 | } | ||
159 | |||
160 | static void nuc900_spi_gobusy(struct nuc900_spi *hw) | ||
161 | { | ||
162 | unsigned int val; | ||
163 | unsigned long flags; | ||
164 | |||
165 | spin_lock_irqsave(&hw->lock, flags); | ||
166 | |||
167 | val = __raw_readl(hw->regs + USI_CNT); | ||
168 | |||
169 | val |= GOBUSY; | ||
170 | |||
171 | __raw_writel(val, hw->regs + USI_CNT); | ||
172 | |||
173 | spin_unlock_irqrestore(&hw->lock, flags); | ||
174 | } | ||
175 | |||
176 | static int nuc900_spi_setupxfer(struct spi_device *spi, | ||
177 | struct spi_transfer *t) | ||
178 | { | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static int nuc900_spi_setup(struct spi_device *spi) | ||
183 | { | ||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static inline unsigned int hw_txbyte(struct nuc900_spi *hw, int count) | ||
188 | { | ||
189 | return hw->tx ? hw->tx[count] : 0; | ||
190 | } | ||
191 | |||
192 | static int nuc900_spi_txrx(struct spi_device *spi, struct spi_transfer *t) | ||
193 | { | ||
194 | struct nuc900_spi *hw = to_hw(spi); | ||
195 | |||
196 | hw->tx = t->tx_buf; | ||
197 | hw->rx = t->rx_buf; | ||
198 | hw->len = t->len; | ||
199 | hw->count = 0; | ||
200 | |||
201 | __raw_writel(hw_txbyte(hw, 0x0), hw->regs + USI_TX0); | ||
202 | |||
203 | nuc900_spi_gobusy(hw); | ||
204 | |||
205 | wait_for_completion(&hw->done); | ||
206 | |||
207 | return hw->count; | ||
208 | } | ||
209 | |||
210 | static irqreturn_t nuc900_spi_irq(int irq, void *dev) | ||
211 | { | ||
212 | struct nuc900_spi *hw = dev; | ||
213 | unsigned int status; | ||
214 | unsigned int count = hw->count; | ||
215 | |||
216 | status = __raw_readl(hw->regs + USI_CNT); | ||
217 | __raw_writel(status, hw->regs + USI_CNT); | ||
218 | |||
219 | if (status & ENFLG) { | ||
220 | hw->count++; | ||
221 | |||
222 | if (hw->rx) | ||
223 | hw->rx[count] = __raw_readl(hw->regs + USI_RX0); | ||
224 | count++; | ||
225 | |||
226 | if (count < hw->len) { | ||
227 | __raw_writel(hw_txbyte(hw, count), hw->regs + USI_TX0); | ||
228 | nuc900_spi_gobusy(hw); | ||
229 | } else { | ||
230 | complete(&hw->done); | ||
231 | } | ||
232 | |||
233 | return IRQ_HANDLED; | ||
234 | } | ||
235 | |||
236 | complete(&hw->done); | ||
237 | return IRQ_HANDLED; | ||
238 | } | ||
239 | |||
240 | static void nuc900_tx_edge(struct nuc900_spi *hw, unsigned int edge) | ||
241 | { | ||
242 | unsigned int val; | ||
243 | unsigned long flags; | ||
244 | |||
245 | spin_lock_irqsave(&hw->lock, flags); | ||
246 | |||
247 | val = __raw_readl(hw->regs + USI_CNT); | ||
248 | |||
249 | if (edge) | ||
250 | val |= TXNEG; | ||
251 | else | ||
252 | val &= ~TXNEG; | ||
253 | __raw_writel(val, hw->regs + USI_CNT); | ||
254 | |||
255 | spin_unlock_irqrestore(&hw->lock, flags); | ||
256 | } | ||
257 | |||
258 | static void nuc900_rx_edge(struct nuc900_spi *hw, unsigned int edge) | ||
259 | { | ||
260 | unsigned int val; | ||
261 | unsigned long flags; | ||
262 | |||
263 | spin_lock_irqsave(&hw->lock, flags); | ||
264 | |||
265 | val = __raw_readl(hw->regs + USI_CNT); | ||
266 | |||
267 | if (edge) | ||
268 | val |= RXNEG; | ||
269 | else | ||
270 | val &= ~RXNEG; | ||
271 | __raw_writel(val, hw->regs + USI_CNT); | ||
272 | |||
273 | spin_unlock_irqrestore(&hw->lock, flags); | ||
274 | } | ||
275 | |||
276 | static void nuc900_send_first(struct nuc900_spi *hw, unsigned int lsb) | ||
277 | { | ||
278 | unsigned int val; | ||
279 | unsigned long flags; | ||
280 | |||
281 | spin_lock_irqsave(&hw->lock, flags); | ||
282 | |||
283 | val = __raw_readl(hw->regs + USI_CNT); | ||
284 | |||
285 | if (lsb) | ||
286 | val |= LSB; | ||
287 | else | ||
288 | val &= ~LSB; | ||
289 | __raw_writel(val, hw->regs + USI_CNT); | ||
290 | |||
291 | spin_unlock_irqrestore(&hw->lock, flags); | ||
292 | } | ||
293 | |||
294 | static void nuc900_set_sleep(struct nuc900_spi *hw, unsigned int sleep) | ||
295 | { | ||
296 | unsigned int val; | ||
297 | unsigned long flags; | ||
298 | |||
299 | spin_lock_irqsave(&hw->lock, flags); | ||
300 | |||
301 | val = __raw_readl(hw->regs + USI_CNT); | ||
302 | |||
303 | if (sleep) | ||
304 | val |= (sleep << 12); | ||
305 | else | ||
306 | val &= ~(0x0f << 12); | ||
307 | __raw_writel(val, hw->regs + USI_CNT); | ||
308 | |||
309 | spin_unlock_irqrestore(&hw->lock, flags); | ||
310 | } | ||
311 | |||
312 | static void nuc900_enable_int(struct nuc900_spi *hw) | ||
313 | { | ||
314 | unsigned int val; | ||
315 | unsigned long flags; | ||
316 | |||
317 | spin_lock_irqsave(&hw->lock, flags); | ||
318 | |||
319 | val = __raw_readl(hw->regs + USI_CNT); | ||
320 | |||
321 | val |= ENINT; | ||
322 | |||
323 | __raw_writel(val, hw->regs + USI_CNT); | ||
324 | |||
325 | spin_unlock_irqrestore(&hw->lock, flags); | ||
326 | } | ||
327 | |||
328 | static void nuc900_set_divider(struct nuc900_spi *hw) | ||
329 | { | ||
330 | __raw_writel(hw->pdata->divider, hw->regs + USI_DIV); | ||
331 | } | ||
332 | |||
333 | static void nuc900_init_spi(struct nuc900_spi *hw) | ||
334 | { | ||
335 | clk_enable(hw->clk); | ||
336 | spin_lock_init(&hw->lock); | ||
337 | |||
338 | nuc900_tx_edge(hw, hw->pdata->txneg); | ||
339 | nuc900_rx_edge(hw, hw->pdata->rxneg); | ||
340 | nuc900_send_first(hw, hw->pdata->lsb); | ||
341 | nuc900_set_sleep(hw, hw->pdata->sleep); | ||
342 | nuc900_spi_setup_txbitlen(hw, hw->pdata->txbitlen); | ||
343 | nuc900_spi_setup_txnum(hw, hw->pdata->txnum); | ||
344 | nuc900_set_divider(hw); | ||
345 | nuc900_enable_int(hw); | ||
346 | } | ||
347 | |||
348 | static int __devinit nuc900_spi_probe(struct platform_device *pdev) | ||
349 | { | ||
350 | struct nuc900_spi *hw; | ||
351 | struct spi_master *master; | ||
352 | int err = 0; | ||
353 | |||
354 | master = spi_alloc_master(&pdev->dev, sizeof(struct nuc900_spi)); | ||
355 | if (master == NULL) { | ||
356 | dev_err(&pdev->dev, "No memory for spi_master\n"); | ||
357 | err = -ENOMEM; | ||
358 | goto err_nomem; | ||
359 | } | ||
360 | |||
361 | hw = spi_master_get_devdata(master); | ||
362 | memset(hw, 0, sizeof(struct nuc900_spi)); | ||
363 | |||
364 | hw->master = spi_master_get(master); | ||
365 | hw->pdata = pdev->dev.platform_data; | ||
366 | hw->dev = &pdev->dev; | ||
367 | |||
368 | if (hw->pdata == NULL) { | ||
369 | dev_err(&pdev->dev, "No platform data supplied\n"); | ||
370 | err = -ENOENT; | ||
371 | goto err_pdata; | ||
372 | } | ||
373 | |||
374 | platform_set_drvdata(pdev, hw); | ||
375 | init_completion(&hw->done); | ||
376 | |||
377 | master->mode_bits = SPI_MODE_0; | ||
378 | master->num_chipselect = hw->pdata->num_cs; | ||
379 | master->bus_num = hw->pdata->bus_num; | ||
380 | hw->bitbang.master = hw->master; | ||
381 | hw->bitbang.setup_transfer = nuc900_spi_setupxfer; | ||
382 | hw->bitbang.chipselect = nuc900_spi_chipsel; | ||
383 | hw->bitbang.txrx_bufs = nuc900_spi_txrx; | ||
384 | hw->bitbang.master->setup = nuc900_spi_setup; | ||
385 | |||
386 | hw->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
387 | if (hw->res == NULL) { | ||
388 | dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n"); | ||
389 | err = -ENOENT; | ||
390 | goto err_pdata; | ||
391 | } | ||
392 | |||
393 | hw->ioarea = request_mem_region(hw->res->start, | ||
394 | resource_size(hw->res), pdev->name); | ||
395 | |||
396 | if (hw->ioarea == NULL) { | ||
397 | dev_err(&pdev->dev, "Cannot reserve region\n"); | ||
398 | err = -ENXIO; | ||
399 | goto err_pdata; | ||
400 | } | ||
401 | |||
402 | hw->regs = ioremap(hw->res->start, resource_size(hw->res)); | ||
403 | if (hw->regs == NULL) { | ||
404 | dev_err(&pdev->dev, "Cannot map IO\n"); | ||
405 | err = -ENXIO; | ||
406 | goto err_iomap; | ||
407 | } | ||
408 | |||
409 | hw->irq = platform_get_irq(pdev, 0); | ||
410 | if (hw->irq < 0) { | ||
411 | dev_err(&pdev->dev, "No IRQ specified\n"); | ||
412 | err = -ENOENT; | ||
413 | goto err_irq; | ||
414 | } | ||
415 | |||
416 | err = request_irq(hw->irq, nuc900_spi_irq, 0, pdev->name, hw); | ||
417 | if (err) { | ||
418 | dev_err(&pdev->dev, "Cannot claim IRQ\n"); | ||
419 | goto err_irq; | ||
420 | } | ||
421 | |||
422 | hw->clk = clk_get(&pdev->dev, "spi"); | ||
423 | if (IS_ERR(hw->clk)) { | ||
424 | dev_err(&pdev->dev, "No clock for device\n"); | ||
425 | err = PTR_ERR(hw->clk); | ||
426 | goto err_clk; | ||
427 | } | ||
428 | |||
429 | mfp_set_groupg(&pdev->dev); | ||
430 | nuc900_init_spi(hw); | ||
431 | |||
432 | err = spi_bitbang_start(&hw->bitbang); | ||
433 | if (err) { | ||
434 | dev_err(&pdev->dev, "Failed to register SPI master\n"); | ||
435 | goto err_register; | ||
436 | } | ||
437 | |||
438 | return 0; | ||
439 | |||
440 | err_register: | ||
441 | clk_disable(hw->clk); | ||
442 | clk_put(hw->clk); | ||
443 | err_clk: | ||
444 | free_irq(hw->irq, hw); | ||
445 | err_irq: | ||
446 | iounmap(hw->regs); | ||
447 | err_iomap: | ||
448 | release_mem_region(hw->res->start, resource_size(hw->res)); | ||
449 | kfree(hw->ioarea); | ||
450 | err_pdata: | ||
451 | spi_master_put(hw->master);; | ||
452 | |||
453 | err_nomem: | ||
454 | return err; | ||
455 | } | ||
456 | |||
457 | static int __devexit nuc900_spi_remove(struct platform_device *dev) | ||
458 | { | ||
459 | struct nuc900_spi *hw = platform_get_drvdata(dev); | ||
460 | |||
461 | free_irq(hw->irq, hw); | ||
462 | |||
463 | platform_set_drvdata(dev, NULL); | ||
464 | |||
465 | spi_unregister_master(hw->master); | ||
466 | |||
467 | clk_disable(hw->clk); | ||
468 | clk_put(hw->clk); | ||
469 | |||
470 | iounmap(hw->regs); | ||
471 | |||
472 | release_mem_region(hw->res->start, resource_size(hw->res)); | ||
473 | kfree(hw->ioarea); | ||
474 | |||
475 | spi_master_put(hw->master); | ||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | static struct platform_driver nuc900_spi_driver = { | ||
480 | .probe = nuc900_spi_probe, | ||
481 | .remove = __devexit_p(nuc900_spi_remove), | ||
482 | .driver = { | ||
483 | .name = "nuc900-spi", | ||
484 | .owner = THIS_MODULE, | ||
485 | }, | ||
486 | }; | ||
487 | |||
488 | static int __init nuc900_spi_init(void) | ||
489 | { | ||
490 | return platform_driver_register(&nuc900_spi_driver); | ||
491 | } | ||
492 | |||
493 | static void __exit nuc900_spi_exit(void) | ||
494 | { | ||
495 | platform_driver_unregister(&nuc900_spi_driver); | ||
496 | } | ||
497 | |||
498 | module_init(nuc900_spi_init); | ||
499 | module_exit(nuc900_spi_exit); | ||
500 | |||
501 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | ||
502 | MODULE_DESCRIPTION("nuc900 spi driver!"); | ||
503 | MODULE_LICENSE("GPL"); | ||
504 | MODULE_ALIAS("platform:nuc900-spi"); | ||
diff --git a/drivers/spi/spi_sh_msiof.c b/drivers/spi/spi_sh_msiof.c new file mode 100644 index 000000000000..51e5e1dfa6e5 --- /dev/null +++ b/drivers/spi/spi_sh_msiof.c | |||
@@ -0,0 +1,691 @@ | |||
1 | /* | ||
2 | * SuperH MSIOF SPI Master Interface | ||
3 | * | ||
4 | * Copyright (c) 2009 Magnus Damm | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/completion.h> | ||
18 | #include <linux/pm_runtime.h> | ||
19 | #include <linux/gpio.h> | ||
20 | #include <linux/bitmap.h> | ||
21 | #include <linux/clk.h> | ||
22 | #include <linux/io.h> | ||
23 | |||
24 | #include <linux/spi/spi.h> | ||
25 | #include <linux/spi/spi_bitbang.h> | ||
26 | #include <linux/spi/sh_msiof.h> | ||
27 | |||
28 | #include <asm/spi.h> | ||
29 | #include <asm/unaligned.h> | ||
30 | |||
31 | struct sh_msiof_spi_priv { | ||
32 | struct spi_bitbang bitbang; /* must be first for spi_bitbang.c */ | ||
33 | void __iomem *mapbase; | ||
34 | struct clk *clk; | ||
35 | struct platform_device *pdev; | ||
36 | struct sh_msiof_spi_info *info; | ||
37 | struct completion done; | ||
38 | unsigned long flags; | ||
39 | int tx_fifo_size; | ||
40 | int rx_fifo_size; | ||
41 | }; | ||
42 | |||
43 | #define TMDR1 0x00 | ||
44 | #define TMDR2 0x04 | ||
45 | #define TMDR3 0x08 | ||
46 | #define RMDR1 0x10 | ||
47 | #define RMDR2 0x14 | ||
48 | #define RMDR3 0x18 | ||
49 | #define TSCR 0x20 | ||
50 | #define RSCR 0x22 | ||
51 | #define CTR 0x28 | ||
52 | #define FCTR 0x30 | ||
53 | #define STR 0x40 | ||
54 | #define IER 0x44 | ||
55 | #define TDR1 0x48 | ||
56 | #define TDR2 0x4c | ||
57 | #define TFDR 0x50 | ||
58 | #define RDR1 0x58 | ||
59 | #define RDR2 0x5c | ||
60 | #define RFDR 0x60 | ||
61 | |||
62 | #define CTR_TSCKE (1 << 15) | ||
63 | #define CTR_TFSE (1 << 14) | ||
64 | #define CTR_TXE (1 << 9) | ||
65 | #define CTR_RXE (1 << 8) | ||
66 | |||
67 | #define STR_TEOF (1 << 23) | ||
68 | #define STR_REOF (1 << 7) | ||
69 | |||
70 | static unsigned long sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs) | ||
71 | { | ||
72 | switch (reg_offs) { | ||
73 | case TSCR: | ||
74 | case RSCR: | ||
75 | return ioread16(p->mapbase + reg_offs); | ||
76 | default: | ||
77 | return ioread32(p->mapbase + reg_offs); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | static void sh_msiof_write(struct sh_msiof_spi_priv *p, int reg_offs, | ||
82 | unsigned long value) | ||
83 | { | ||
84 | switch (reg_offs) { | ||
85 | case TSCR: | ||
86 | case RSCR: | ||
87 | iowrite16(value, p->mapbase + reg_offs); | ||
88 | break; | ||
89 | default: | ||
90 | iowrite32(value, p->mapbase + reg_offs); | ||
91 | break; | ||
92 | } | ||
93 | } | ||
94 | |||
95 | static int sh_msiof_modify_ctr_wait(struct sh_msiof_spi_priv *p, | ||
96 | unsigned long clr, unsigned long set) | ||
97 | { | ||
98 | unsigned long mask = clr | set; | ||
99 | unsigned long data; | ||
100 | int k; | ||
101 | |||
102 | data = sh_msiof_read(p, CTR); | ||
103 | data &= ~clr; | ||
104 | data |= set; | ||
105 | sh_msiof_write(p, CTR, data); | ||
106 | |||
107 | for (k = 100; k > 0; k--) { | ||
108 | if ((sh_msiof_read(p, CTR) & mask) == set) | ||
109 | break; | ||
110 | |||
111 | udelay(10); | ||
112 | } | ||
113 | |||
114 | return k > 0 ? 0 : -ETIMEDOUT; | ||
115 | } | ||
116 | |||
117 | static irqreturn_t sh_msiof_spi_irq(int irq, void *data) | ||
118 | { | ||
119 | struct sh_msiof_spi_priv *p = data; | ||
120 | |||
121 | /* just disable the interrupt and wake up */ | ||
122 | sh_msiof_write(p, IER, 0); | ||
123 | complete(&p->done); | ||
124 | |||
125 | return IRQ_HANDLED; | ||
126 | } | ||
127 | |||
128 | static struct { | ||
129 | unsigned short div; | ||
130 | unsigned short scr; | ||
131 | } const sh_msiof_spi_clk_table[] = { | ||
132 | { 1, 0x0007 }, | ||
133 | { 2, 0x0000 }, | ||
134 | { 4, 0x0001 }, | ||
135 | { 8, 0x0002 }, | ||
136 | { 16, 0x0003 }, | ||
137 | { 32, 0x0004 }, | ||
138 | { 64, 0x1f00 }, | ||
139 | { 128, 0x1f01 }, | ||
140 | { 256, 0x1f02 }, | ||
141 | { 512, 0x1f03 }, | ||
142 | { 1024, 0x1f04 }, | ||
143 | }; | ||
144 | |||
145 | static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p, | ||
146 | unsigned long parent_rate, | ||
147 | unsigned long spi_hz) | ||
148 | { | ||
149 | unsigned long div = 1024; | ||
150 | size_t k; | ||
151 | |||
152 | if (!WARN_ON(!spi_hz || !parent_rate)) | ||
153 | div = parent_rate / spi_hz; | ||
154 | |||
155 | /* TODO: make more fine grained */ | ||
156 | |||
157 | for (k = 0; k < ARRAY_SIZE(sh_msiof_spi_clk_table); k++) { | ||
158 | if (sh_msiof_spi_clk_table[k].div >= div) | ||
159 | break; | ||
160 | } | ||
161 | |||
162 | k = min_t(int, k, ARRAY_SIZE(sh_msiof_spi_clk_table) - 1); | ||
163 | |||
164 | sh_msiof_write(p, TSCR, sh_msiof_spi_clk_table[k].scr); | ||
165 | sh_msiof_write(p, RSCR, sh_msiof_spi_clk_table[k].scr); | ||
166 | } | ||
167 | |||
168 | static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, | ||
169 | int cpol, int cpha, | ||
170 | int tx_hi_z, int lsb_first) | ||
171 | { | ||
172 | unsigned long tmp; | ||
173 | int edge; | ||
174 | |||
175 | /* | ||
176 | * CPOL CPHA TSCKIZ RSCKIZ TEDG REDG(!) | ||
177 | * 0 0 10 10 1 0 | ||
178 | * 0 1 10 10 0 1 | ||
179 | * 1 0 11 11 0 1 | ||
180 | * 1 1 11 11 1 0 | ||
181 | * | ||
182 | * (!) Note: REDG is inverted recommended data sheet setting | ||
183 | */ | ||
184 | |||
185 | sh_msiof_write(p, FCTR, 0); | ||
186 | sh_msiof_write(p, TMDR1, 0xe2000005 | (lsb_first << 24)); | ||
187 | sh_msiof_write(p, RMDR1, 0x22000005 | (lsb_first << 24)); | ||
188 | |||
189 | tmp = 0xa0000000; | ||
190 | tmp |= cpol << 30; /* TSCKIZ */ | ||
191 | tmp |= cpol << 28; /* RSCKIZ */ | ||
192 | |||
193 | edge = cpol ? cpha : !cpha; | ||
194 | |||
195 | tmp |= edge << 27; /* TEDG */ | ||
196 | tmp |= !edge << 26; /* REDG */ | ||
197 | tmp |= (tx_hi_z ? 2 : 0) << 22; /* TXDIZ */ | ||
198 | sh_msiof_write(p, CTR, tmp); | ||
199 | } | ||
200 | |||
201 | static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p, | ||
202 | const void *tx_buf, void *rx_buf, | ||
203 | int bits, int words) | ||
204 | { | ||
205 | unsigned long dr2; | ||
206 | |||
207 | dr2 = ((bits - 1) << 24) | ((words - 1) << 16); | ||
208 | |||
209 | if (tx_buf) | ||
210 | sh_msiof_write(p, TMDR2, dr2); | ||
211 | else | ||
212 | sh_msiof_write(p, TMDR2, dr2 | 1); | ||
213 | |||
214 | if (rx_buf) | ||
215 | sh_msiof_write(p, RMDR2, dr2); | ||
216 | |||
217 | sh_msiof_write(p, IER, STR_TEOF | STR_REOF); | ||
218 | } | ||
219 | |||
220 | static void sh_msiof_reset_str(struct sh_msiof_spi_priv *p) | ||
221 | { | ||
222 | sh_msiof_write(p, STR, sh_msiof_read(p, STR)); | ||
223 | } | ||
224 | |||
225 | static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p, | ||
226 | const void *tx_buf, int words, int fs) | ||
227 | { | ||
228 | const unsigned char *buf_8 = tx_buf; | ||
229 | int k; | ||
230 | |||
231 | for (k = 0; k < words; k++) | ||
232 | sh_msiof_write(p, TFDR, buf_8[k] << fs); | ||
233 | } | ||
234 | |||
235 | static void sh_msiof_spi_write_fifo_16(struct sh_msiof_spi_priv *p, | ||
236 | const void *tx_buf, int words, int fs) | ||
237 | { | ||
238 | const unsigned short *buf_16 = tx_buf; | ||
239 | int k; | ||
240 | |||
241 | for (k = 0; k < words; k++) | ||
242 | sh_msiof_write(p, TFDR, buf_16[k] << fs); | ||
243 | } | ||
244 | |||
245 | static void sh_msiof_spi_write_fifo_16u(struct sh_msiof_spi_priv *p, | ||
246 | const void *tx_buf, int words, int fs) | ||
247 | { | ||
248 | const unsigned short *buf_16 = tx_buf; | ||
249 | int k; | ||
250 | |||
251 | for (k = 0; k < words; k++) | ||
252 | sh_msiof_write(p, TFDR, get_unaligned(&buf_16[k]) << fs); | ||
253 | } | ||
254 | |||
255 | static void sh_msiof_spi_write_fifo_32(struct sh_msiof_spi_priv *p, | ||
256 | const void *tx_buf, int words, int fs) | ||
257 | { | ||
258 | const unsigned int *buf_32 = tx_buf; | ||
259 | int k; | ||
260 | |||
261 | for (k = 0; k < words; k++) | ||
262 | sh_msiof_write(p, TFDR, buf_32[k] << fs); | ||
263 | } | ||
264 | |||
265 | static void sh_msiof_spi_write_fifo_32u(struct sh_msiof_spi_priv *p, | ||
266 | const void *tx_buf, int words, int fs) | ||
267 | { | ||
268 | const unsigned int *buf_32 = tx_buf; | ||
269 | int k; | ||
270 | |||
271 | for (k = 0; k < words; k++) | ||
272 | sh_msiof_write(p, TFDR, get_unaligned(&buf_32[k]) << fs); | ||
273 | } | ||
274 | |||
275 | static void sh_msiof_spi_read_fifo_8(struct sh_msiof_spi_priv *p, | ||
276 | void *rx_buf, int words, int fs) | ||
277 | { | ||
278 | unsigned char *buf_8 = rx_buf; | ||
279 | int k; | ||
280 | |||
281 | for (k = 0; k < words; k++) | ||
282 | buf_8[k] = sh_msiof_read(p, RFDR) >> fs; | ||
283 | } | ||
284 | |||
285 | static void sh_msiof_spi_read_fifo_16(struct sh_msiof_spi_priv *p, | ||
286 | void *rx_buf, int words, int fs) | ||
287 | { | ||
288 | unsigned short *buf_16 = rx_buf; | ||
289 | int k; | ||
290 | |||
291 | for (k = 0; k < words; k++) | ||
292 | buf_16[k] = sh_msiof_read(p, RFDR) >> fs; | ||
293 | } | ||
294 | |||
295 | static void sh_msiof_spi_read_fifo_16u(struct sh_msiof_spi_priv *p, | ||
296 | void *rx_buf, int words, int fs) | ||
297 | { | ||
298 | unsigned short *buf_16 = rx_buf; | ||
299 | int k; | ||
300 | |||
301 | for (k = 0; k < words; k++) | ||
302 | put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_16[k]); | ||
303 | } | ||
304 | |||
305 | static void sh_msiof_spi_read_fifo_32(struct sh_msiof_spi_priv *p, | ||
306 | void *rx_buf, int words, int fs) | ||
307 | { | ||
308 | unsigned int *buf_32 = rx_buf; | ||
309 | int k; | ||
310 | |||
311 | for (k = 0; k < words; k++) | ||
312 | buf_32[k] = sh_msiof_read(p, RFDR) >> fs; | ||
313 | } | ||
314 | |||
315 | static void sh_msiof_spi_read_fifo_32u(struct sh_msiof_spi_priv *p, | ||
316 | void *rx_buf, int words, int fs) | ||
317 | { | ||
318 | unsigned int *buf_32 = rx_buf; | ||
319 | int k; | ||
320 | |||
321 | for (k = 0; k < words; k++) | ||
322 | put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_32[k]); | ||
323 | } | ||
324 | |||
325 | static int sh_msiof_spi_bits(struct spi_device *spi, struct spi_transfer *t) | ||
326 | { | ||
327 | int bits; | ||
328 | |||
329 | bits = t ? t->bits_per_word : 0; | ||
330 | bits = bits ? bits : spi->bits_per_word; | ||
331 | return bits; | ||
332 | } | ||
333 | |||
334 | static unsigned long sh_msiof_spi_hz(struct spi_device *spi, | ||
335 | struct spi_transfer *t) | ||
336 | { | ||
337 | unsigned long hz; | ||
338 | |||
339 | hz = t ? t->speed_hz : 0; | ||
340 | hz = hz ? hz : spi->max_speed_hz; | ||
341 | return hz; | ||
342 | } | ||
343 | |||
344 | static int sh_msiof_spi_setup_transfer(struct spi_device *spi, | ||
345 | struct spi_transfer *t) | ||
346 | { | ||
347 | int bits; | ||
348 | |||
349 | /* noting to check hz values against since parent clock is disabled */ | ||
350 | |||
351 | bits = sh_msiof_spi_bits(spi, t); | ||
352 | if (bits < 8) | ||
353 | return -EINVAL; | ||
354 | if (bits > 32) | ||
355 | return -EINVAL; | ||
356 | |||
357 | return spi_bitbang_setup_transfer(spi, t); | ||
358 | } | ||
359 | |||
360 | static void sh_msiof_spi_chipselect(struct spi_device *spi, int is_on) | ||
361 | { | ||
362 | struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master); | ||
363 | int value; | ||
364 | |||
365 | /* chip select is active low unless SPI_CS_HIGH is set */ | ||
366 | if (spi->mode & SPI_CS_HIGH) | ||
367 | value = (is_on == BITBANG_CS_ACTIVE) ? 1 : 0; | ||
368 | else | ||
369 | value = (is_on == BITBANG_CS_ACTIVE) ? 0 : 1; | ||
370 | |||
371 | if (is_on == BITBANG_CS_ACTIVE) { | ||
372 | if (!test_and_set_bit(0, &p->flags)) { | ||
373 | pm_runtime_get_sync(&p->pdev->dev); | ||
374 | clk_enable(p->clk); | ||
375 | } | ||
376 | |||
377 | /* Configure pins before asserting CS */ | ||
378 | sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL), | ||
379 | !!(spi->mode & SPI_CPHA), | ||
380 | !!(spi->mode & SPI_3WIRE), | ||
381 | !!(spi->mode & SPI_LSB_FIRST)); | ||
382 | } | ||
383 | |||
384 | /* use spi->controller data for CS (same strategy as spi_gpio) */ | ||
385 | gpio_set_value((unsigned)spi->controller_data, value); | ||
386 | |||
387 | if (is_on == BITBANG_CS_INACTIVE) { | ||
388 | if (test_and_clear_bit(0, &p->flags)) { | ||
389 | clk_disable(p->clk); | ||
390 | pm_runtime_put(&p->pdev->dev); | ||
391 | } | ||
392 | } | ||
393 | } | ||
394 | |||
395 | static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, | ||
396 | void (*tx_fifo)(struct sh_msiof_spi_priv *, | ||
397 | const void *, int, int), | ||
398 | void (*rx_fifo)(struct sh_msiof_spi_priv *, | ||
399 | void *, int, int), | ||
400 | const void *tx_buf, void *rx_buf, | ||
401 | int words, int bits) | ||
402 | { | ||
403 | int fifo_shift; | ||
404 | int ret; | ||
405 | |||
406 | /* limit maximum word transfer to rx/tx fifo size */ | ||
407 | if (tx_buf) | ||
408 | words = min_t(int, words, p->tx_fifo_size); | ||
409 | if (rx_buf) | ||
410 | words = min_t(int, words, p->rx_fifo_size); | ||
411 | |||
412 | /* the fifo contents need shifting */ | ||
413 | fifo_shift = 32 - bits; | ||
414 | |||
415 | /* setup msiof transfer mode registers */ | ||
416 | sh_msiof_spi_set_mode_regs(p, tx_buf, rx_buf, bits, words); | ||
417 | |||
418 | /* write tx fifo */ | ||
419 | if (tx_buf) | ||
420 | tx_fifo(p, tx_buf, words, fifo_shift); | ||
421 | |||
422 | /* setup clock and rx/tx signals */ | ||
423 | ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TSCKE); | ||
424 | if (rx_buf) | ||
425 | ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_RXE); | ||
426 | ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_TXE); | ||
427 | |||
428 | /* start by setting frame bit */ | ||
429 | INIT_COMPLETION(p->done); | ||
430 | ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_TFSE); | ||
431 | if (ret) { | ||
432 | dev_err(&p->pdev->dev, "failed to start hardware\n"); | ||
433 | goto err; | ||
434 | } | ||
435 | |||
436 | /* wait for tx fifo to be emptied / rx fifo to be filled */ | ||
437 | wait_for_completion(&p->done); | ||
438 | |||
439 | /* read rx fifo */ | ||
440 | if (rx_buf) | ||
441 | rx_fifo(p, rx_buf, words, fifo_shift); | ||
442 | |||
443 | /* clear status bits */ | ||
444 | sh_msiof_reset_str(p); | ||
445 | |||
446 | /* shut down frame, tx/tx and clock signals */ | ||
447 | ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0); | ||
448 | ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_TXE, 0); | ||
449 | if (rx_buf) | ||
450 | ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_RXE, 0); | ||
451 | ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_TSCKE, 0); | ||
452 | if (ret) { | ||
453 | dev_err(&p->pdev->dev, "failed to shut down hardware\n"); | ||
454 | goto err; | ||
455 | } | ||
456 | |||
457 | return words; | ||
458 | |||
459 | err: | ||
460 | sh_msiof_write(p, IER, 0); | ||
461 | return ret; | ||
462 | } | ||
463 | |||
464 | static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t) | ||
465 | { | ||
466 | struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master); | ||
467 | void (*tx_fifo)(struct sh_msiof_spi_priv *, const void *, int, int); | ||
468 | void (*rx_fifo)(struct sh_msiof_spi_priv *, void *, int, int); | ||
469 | int bits; | ||
470 | int bytes_per_word; | ||
471 | int bytes_done; | ||
472 | int words; | ||
473 | int n; | ||
474 | |||
475 | bits = sh_msiof_spi_bits(spi, t); | ||
476 | |||
477 | /* setup bytes per word and fifo read/write functions */ | ||
478 | if (bits <= 8) { | ||
479 | bytes_per_word = 1; | ||
480 | tx_fifo = sh_msiof_spi_write_fifo_8; | ||
481 | rx_fifo = sh_msiof_spi_read_fifo_8; | ||
482 | } else if (bits <= 16) { | ||
483 | bytes_per_word = 2; | ||
484 | if ((unsigned long)t->tx_buf & 0x01) | ||
485 | tx_fifo = sh_msiof_spi_write_fifo_16u; | ||
486 | else | ||
487 | tx_fifo = sh_msiof_spi_write_fifo_16; | ||
488 | |||
489 | if ((unsigned long)t->rx_buf & 0x01) | ||
490 | rx_fifo = sh_msiof_spi_read_fifo_16u; | ||
491 | else | ||
492 | rx_fifo = sh_msiof_spi_read_fifo_16; | ||
493 | } else { | ||
494 | bytes_per_word = 4; | ||
495 | if ((unsigned long)t->tx_buf & 0x03) | ||
496 | tx_fifo = sh_msiof_spi_write_fifo_32u; | ||
497 | else | ||
498 | tx_fifo = sh_msiof_spi_write_fifo_32; | ||
499 | |||
500 | if ((unsigned long)t->rx_buf & 0x03) | ||
501 | rx_fifo = sh_msiof_spi_read_fifo_32u; | ||
502 | else | ||
503 | rx_fifo = sh_msiof_spi_read_fifo_32; | ||
504 | } | ||
505 | |||
506 | /* setup clocks (clock already enabled in chipselect()) */ | ||
507 | sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk), | ||
508 | sh_msiof_spi_hz(spi, t)); | ||
509 | |||
510 | /* transfer in fifo sized chunks */ | ||
511 | words = t->len / bytes_per_word; | ||
512 | bytes_done = 0; | ||
513 | |||
514 | while (bytes_done < t->len) { | ||
515 | n = sh_msiof_spi_txrx_once(p, tx_fifo, rx_fifo, | ||
516 | t->tx_buf + bytes_done, | ||
517 | t->rx_buf + bytes_done, | ||
518 | words, bits); | ||
519 | if (n < 0) | ||
520 | break; | ||
521 | |||
522 | bytes_done += n * bytes_per_word; | ||
523 | words -= n; | ||
524 | } | ||
525 | |||
526 | return bytes_done; | ||
527 | } | ||
528 | |||
529 | static u32 sh_msiof_spi_txrx_word(struct spi_device *spi, unsigned nsecs, | ||
530 | u32 word, u8 bits) | ||
531 | { | ||
532 | BUG(); /* unused but needed by bitbang code */ | ||
533 | return 0; | ||
534 | } | ||
535 | |||
536 | static int sh_msiof_spi_probe(struct platform_device *pdev) | ||
537 | { | ||
538 | struct resource *r; | ||
539 | struct spi_master *master; | ||
540 | struct sh_msiof_spi_priv *p; | ||
541 | char clk_name[16]; | ||
542 | int i; | ||
543 | int ret; | ||
544 | |||
545 | master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv)); | ||
546 | if (master == NULL) { | ||
547 | dev_err(&pdev->dev, "failed to allocate spi master\n"); | ||
548 | ret = -ENOMEM; | ||
549 | goto err0; | ||
550 | } | ||
551 | |||
552 | p = spi_master_get_devdata(master); | ||
553 | |||
554 | platform_set_drvdata(pdev, p); | ||
555 | p->info = pdev->dev.platform_data; | ||
556 | init_completion(&p->done); | ||
557 | |||
558 | snprintf(clk_name, sizeof(clk_name), "msiof%d", pdev->id); | ||
559 | p->clk = clk_get(&pdev->dev, clk_name); | ||
560 | if (IS_ERR(p->clk)) { | ||
561 | dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); | ||
562 | ret = PTR_ERR(p->clk); | ||
563 | goto err1; | ||
564 | } | ||
565 | |||
566 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
567 | i = platform_get_irq(pdev, 0); | ||
568 | if (!r || i < 0) { | ||
569 | dev_err(&pdev->dev, "cannot get platform resources\n"); | ||
570 | ret = -ENOENT; | ||
571 | goto err2; | ||
572 | } | ||
573 | p->mapbase = ioremap_nocache(r->start, resource_size(r)); | ||
574 | if (!p->mapbase) { | ||
575 | dev_err(&pdev->dev, "unable to ioremap\n"); | ||
576 | ret = -ENXIO; | ||
577 | goto err2; | ||
578 | } | ||
579 | |||
580 | ret = request_irq(i, sh_msiof_spi_irq, IRQF_DISABLED, | ||
581 | dev_name(&pdev->dev), p); | ||
582 | if (ret) { | ||
583 | dev_err(&pdev->dev, "unable to request irq\n"); | ||
584 | goto err3; | ||
585 | } | ||
586 | |||
587 | p->pdev = pdev; | ||
588 | pm_runtime_enable(&pdev->dev); | ||
589 | |||
590 | /* The standard version of MSIOF use 64 word FIFOs */ | ||
591 | p->tx_fifo_size = 64; | ||
592 | p->rx_fifo_size = 64; | ||
593 | |||
594 | /* Platform data may override FIFO sizes */ | ||
595 | if (p->info->tx_fifo_override) | ||
596 | p->tx_fifo_size = p->info->tx_fifo_override; | ||
597 | if (p->info->rx_fifo_override) | ||
598 | p->rx_fifo_size = p->info->rx_fifo_override; | ||
599 | |||
600 | /* init master and bitbang code */ | ||
601 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; | ||
602 | master->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE; | ||
603 | master->flags = 0; | ||
604 | master->bus_num = pdev->id; | ||
605 | master->num_chipselect = p->info->num_chipselect; | ||
606 | master->setup = spi_bitbang_setup; | ||
607 | master->cleanup = spi_bitbang_cleanup; | ||
608 | |||
609 | p->bitbang.master = master; | ||
610 | p->bitbang.chipselect = sh_msiof_spi_chipselect; | ||
611 | p->bitbang.setup_transfer = sh_msiof_spi_setup_transfer; | ||
612 | p->bitbang.txrx_bufs = sh_msiof_spi_txrx; | ||
613 | p->bitbang.txrx_word[SPI_MODE_0] = sh_msiof_spi_txrx_word; | ||
614 | p->bitbang.txrx_word[SPI_MODE_1] = sh_msiof_spi_txrx_word; | ||
615 | p->bitbang.txrx_word[SPI_MODE_2] = sh_msiof_spi_txrx_word; | ||
616 | p->bitbang.txrx_word[SPI_MODE_3] = sh_msiof_spi_txrx_word; | ||
617 | |||
618 | ret = spi_bitbang_start(&p->bitbang); | ||
619 | if (ret == 0) | ||
620 | return 0; | ||
621 | |||
622 | pm_runtime_disable(&pdev->dev); | ||
623 | err3: | ||
624 | iounmap(p->mapbase); | ||
625 | err2: | ||
626 | clk_put(p->clk); | ||
627 | err1: | ||
628 | spi_master_put(master); | ||
629 | err0: | ||
630 | return ret; | ||
631 | } | ||
632 | |||
633 | static int sh_msiof_spi_remove(struct platform_device *pdev) | ||
634 | { | ||
635 | struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev); | ||
636 | int ret; | ||
637 | |||
638 | ret = spi_bitbang_stop(&p->bitbang); | ||
639 | if (!ret) { | ||
640 | pm_runtime_disable(&pdev->dev); | ||
641 | free_irq(platform_get_irq(pdev, 0), sh_msiof_spi_irq); | ||
642 | iounmap(p->mapbase); | ||
643 | clk_put(p->clk); | ||
644 | spi_master_put(p->bitbang.master); | ||
645 | } | ||
646 | return ret; | ||
647 | } | ||
648 | |||
649 | static int sh_msiof_spi_runtime_nop(struct device *dev) | ||
650 | { | ||
651 | /* Runtime PM callback shared between ->runtime_suspend() | ||
652 | * and ->runtime_resume(). Simply returns success. | ||
653 | * | ||
654 | * This driver re-initializes all registers after | ||
655 | * pm_runtime_get_sync() anyway so there is no need | ||
656 | * to save and restore registers here. | ||
657 | */ | ||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | static struct dev_pm_ops sh_msiof_spi_dev_pm_ops = { | ||
662 | .runtime_suspend = sh_msiof_spi_runtime_nop, | ||
663 | .runtime_resume = sh_msiof_spi_runtime_nop, | ||
664 | }; | ||
665 | |||
666 | static struct platform_driver sh_msiof_spi_drv = { | ||
667 | .probe = sh_msiof_spi_probe, | ||
668 | .remove = sh_msiof_spi_remove, | ||
669 | .driver = { | ||
670 | .name = "spi_sh_msiof", | ||
671 | .owner = THIS_MODULE, | ||
672 | .pm = &sh_msiof_spi_dev_pm_ops, | ||
673 | }, | ||
674 | }; | ||
675 | |||
676 | static int __init sh_msiof_spi_init(void) | ||
677 | { | ||
678 | return platform_driver_register(&sh_msiof_spi_drv); | ||
679 | } | ||
680 | module_init(sh_msiof_spi_init); | ||
681 | |||
682 | static void __exit sh_msiof_spi_exit(void) | ||
683 | { | ||
684 | platform_driver_unregister(&sh_msiof_spi_drv); | ||
685 | } | ||
686 | module_exit(sh_msiof_spi_exit); | ||
687 | |||
688 | MODULE_DESCRIPTION("SuperH MSIOF SPI Master Interface Driver"); | ||
689 | MODULE_AUTHOR("Magnus Damm"); | ||
690 | MODULE_LICENSE("GPL v2"); | ||
691 | MODULE_ALIAS("platform:spi_sh_msiof"); | ||
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 20d7322e2f71..9c446e6003d5 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c | |||
@@ -266,15 +266,15 @@ static int spidev_message(struct spidev_data *spidev, | |||
266 | k_tmp->delay_usecs = u_tmp->delay_usecs; | 266 | k_tmp->delay_usecs = u_tmp->delay_usecs; |
267 | k_tmp->speed_hz = u_tmp->speed_hz; | 267 | k_tmp->speed_hz = u_tmp->speed_hz; |
268 | #ifdef VERBOSE | 268 | #ifdef VERBOSE |
269 | dev_dbg(&spi->dev, | 269 | dev_dbg(&spidev->spi->dev, |
270 | " xfer len %zd %s%s%s%dbits %u usec %uHz\n", | 270 | " xfer len %zd %s%s%s%dbits %u usec %uHz\n", |
271 | u_tmp->len, | 271 | u_tmp->len, |
272 | u_tmp->rx_buf ? "rx " : "", | 272 | u_tmp->rx_buf ? "rx " : "", |
273 | u_tmp->tx_buf ? "tx " : "", | 273 | u_tmp->tx_buf ? "tx " : "", |
274 | u_tmp->cs_change ? "cs " : "", | 274 | u_tmp->cs_change ? "cs " : "", |
275 | u_tmp->bits_per_word ? : spi->bits_per_word, | 275 | u_tmp->bits_per_word ? : spidev->spi->bits_per_word, |
276 | u_tmp->delay_usecs, | 276 | u_tmp->delay_usecs, |
277 | u_tmp->speed_hz ? : spi->max_speed_hz); | 277 | u_tmp->speed_hz ? : spidev->spi->max_speed_hz); |
278 | #endif | 278 | #endif |
279 | spi_message_add_tail(k_tmp, &msg); | 279 | spi_message_add_tail(k_tmp, &msg); |
280 | } | 280 | } |
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index 5a143b9f6361..9f386379c169 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c | |||
@@ -14,22 +14,20 @@ | |||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/platform_device.h> | ||
18 | |||
19 | #include <linux/of_platform.h> | ||
20 | #include <linux/of_device.h> | ||
21 | #include <linux/of_spi.h> | ||
22 | 17 | ||
23 | #include <linux/spi/spi.h> | 18 | #include <linux/spi/spi.h> |
24 | #include <linux/spi/spi_bitbang.h> | 19 | #include <linux/spi/spi_bitbang.h> |
25 | #include <linux/io.h> | 20 | #include <linux/io.h> |
26 | 21 | ||
22 | #include "xilinx_spi.h" | ||
23 | #include <linux/spi/xilinx_spi.h> | ||
24 | |||
27 | #define XILINX_SPI_NAME "xilinx_spi" | 25 | #define XILINX_SPI_NAME "xilinx_spi" |
28 | 26 | ||
29 | /* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e) | 27 | /* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e) |
30 | * Product Specification", DS464 | 28 | * Product Specification", DS464 |
31 | */ | 29 | */ |
32 | #define XSPI_CR_OFFSET 0x62 /* 16-bit Control Register */ | 30 | #define XSPI_CR_OFFSET 0x60 /* Control Register */ |
33 | 31 | ||
34 | #define XSPI_CR_ENABLE 0x02 | 32 | #define XSPI_CR_ENABLE 0x02 |
35 | #define XSPI_CR_MASTER_MODE 0x04 | 33 | #define XSPI_CR_MASTER_MODE 0x04 |
@@ -40,8 +38,9 @@ | |||
40 | #define XSPI_CR_RXFIFO_RESET 0x40 | 38 | #define XSPI_CR_RXFIFO_RESET 0x40 |
41 | #define XSPI_CR_MANUAL_SSELECT 0x80 | 39 | #define XSPI_CR_MANUAL_SSELECT 0x80 |
42 | #define XSPI_CR_TRANS_INHIBIT 0x100 | 40 | #define XSPI_CR_TRANS_INHIBIT 0x100 |
41 | #define XSPI_CR_LSB_FIRST 0x200 | ||
43 | 42 | ||
44 | #define XSPI_SR_OFFSET 0x67 /* 8-bit Status Register */ | 43 | #define XSPI_SR_OFFSET 0x64 /* Status Register */ |
45 | 44 | ||
46 | #define XSPI_SR_RX_EMPTY_MASK 0x01 /* Receive FIFO is empty */ | 45 | #define XSPI_SR_RX_EMPTY_MASK 0x01 /* Receive FIFO is empty */ |
47 | #define XSPI_SR_RX_FULL_MASK 0x02 /* Receive FIFO is full */ | 46 | #define XSPI_SR_RX_FULL_MASK 0x02 /* Receive FIFO is full */ |
@@ -49,8 +48,8 @@ | |||
49 | #define XSPI_SR_TX_FULL_MASK 0x08 /* Transmit FIFO is full */ | 48 | #define XSPI_SR_TX_FULL_MASK 0x08 /* Transmit FIFO is full */ |
50 | #define XSPI_SR_MODE_FAULT_MASK 0x10 /* Mode fault error */ | 49 | #define XSPI_SR_MODE_FAULT_MASK 0x10 /* Mode fault error */ |
51 | 50 | ||
52 | #define XSPI_TXD_OFFSET 0x6b /* 8-bit Data Transmit Register */ | 51 | #define XSPI_TXD_OFFSET 0x68 /* Data Transmit Register */ |
53 | #define XSPI_RXD_OFFSET 0x6f /* 8-bit Data Receive Register */ | 52 | #define XSPI_RXD_OFFSET 0x6c /* Data Receive Register */ |
54 | 53 | ||
55 | #define XSPI_SSR_OFFSET 0x70 /* 32-bit Slave Select Register */ | 54 | #define XSPI_SSR_OFFSET 0x70 /* 32-bit Slave Select Register */ |
56 | 55 | ||
@@ -70,6 +69,7 @@ | |||
70 | #define XSPI_INTR_TX_UNDERRUN 0x08 /* TxFIFO was underrun */ | 69 | #define XSPI_INTR_TX_UNDERRUN 0x08 /* TxFIFO was underrun */ |
71 | #define XSPI_INTR_RX_FULL 0x10 /* RxFIFO is full */ | 70 | #define XSPI_INTR_RX_FULL 0x10 /* RxFIFO is full */ |
72 | #define XSPI_INTR_RX_OVERRUN 0x20 /* RxFIFO was overrun */ | 71 | #define XSPI_INTR_RX_OVERRUN 0x20 /* RxFIFO was overrun */ |
72 | #define XSPI_INTR_TX_HALF_EMPTY 0x40 /* TxFIFO is half empty */ | ||
73 | 73 | ||
74 | #define XIPIF_V123B_RESETR_OFFSET 0x40 /* IPIF reset register */ | 74 | #define XIPIF_V123B_RESETR_OFFSET 0x40 /* IPIF reset register */ |
75 | #define XIPIF_V123B_RESET_MASK 0x0a /* the value to write */ | 75 | #define XIPIF_V123B_RESET_MASK 0x0a /* the value to write */ |
@@ -78,35 +78,85 @@ struct xilinx_spi { | |||
78 | /* bitbang has to be first */ | 78 | /* bitbang has to be first */ |
79 | struct spi_bitbang bitbang; | 79 | struct spi_bitbang bitbang; |
80 | struct completion done; | 80 | struct completion done; |
81 | 81 | struct resource mem; /* phys mem */ | |
82 | void __iomem *regs; /* virt. address of the control registers */ | 82 | void __iomem *regs; /* virt. address of the control registers */ |
83 | 83 | ||
84 | u32 irq; | 84 | u32 irq; |
85 | 85 | ||
86 | u32 speed_hz; /* SCK has a fixed frequency of speed_hz Hz */ | ||
87 | |||
88 | u8 *rx_ptr; /* pointer in the Tx buffer */ | 86 | u8 *rx_ptr; /* pointer in the Tx buffer */ |
89 | const u8 *tx_ptr; /* pointer in the Rx buffer */ | 87 | const u8 *tx_ptr; /* pointer in the Rx buffer */ |
90 | int remaining_bytes; /* the number of bytes left to transfer */ | 88 | int remaining_bytes; /* the number of bytes left to transfer */ |
89 | u8 bits_per_word; | ||
90 | unsigned int (*read_fn) (void __iomem *); | ||
91 | void (*write_fn) (u32, void __iomem *); | ||
92 | void (*tx_fn) (struct xilinx_spi *); | ||
93 | void (*rx_fn) (struct xilinx_spi *); | ||
91 | }; | 94 | }; |
92 | 95 | ||
93 | static void xspi_init_hw(void __iomem *regs_base) | 96 | static void xspi_tx8(struct xilinx_spi *xspi) |
97 | { | ||
98 | xspi->write_fn(*xspi->tx_ptr, xspi->regs + XSPI_TXD_OFFSET); | ||
99 | xspi->tx_ptr++; | ||
100 | } | ||
101 | |||
102 | static void xspi_tx16(struct xilinx_spi *xspi) | ||
103 | { | ||
104 | xspi->write_fn(*(u16 *)(xspi->tx_ptr), xspi->regs + XSPI_TXD_OFFSET); | ||
105 | xspi->tx_ptr += 2; | ||
106 | } | ||
107 | |||
108 | static void xspi_tx32(struct xilinx_spi *xspi) | ||
109 | { | ||
110 | xspi->write_fn(*(u32 *)(xspi->tx_ptr), xspi->regs + XSPI_TXD_OFFSET); | ||
111 | xspi->tx_ptr += 4; | ||
112 | } | ||
113 | |||
114 | static void xspi_rx8(struct xilinx_spi *xspi) | ||
115 | { | ||
116 | u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET); | ||
117 | if (xspi->rx_ptr) { | ||
118 | *xspi->rx_ptr = data & 0xff; | ||
119 | xspi->rx_ptr++; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | static void xspi_rx16(struct xilinx_spi *xspi) | ||
94 | { | 124 | { |
125 | u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET); | ||
126 | if (xspi->rx_ptr) { | ||
127 | *(u16 *)(xspi->rx_ptr) = data & 0xffff; | ||
128 | xspi->rx_ptr += 2; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | static void xspi_rx32(struct xilinx_spi *xspi) | ||
133 | { | ||
134 | u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET); | ||
135 | if (xspi->rx_ptr) { | ||
136 | *(u32 *)(xspi->rx_ptr) = data; | ||
137 | xspi->rx_ptr += 4; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | static void xspi_init_hw(struct xilinx_spi *xspi) | ||
142 | { | ||
143 | void __iomem *regs_base = xspi->regs; | ||
144 | |||
95 | /* Reset the SPI device */ | 145 | /* Reset the SPI device */ |
96 | out_be32(regs_base + XIPIF_V123B_RESETR_OFFSET, | 146 | xspi->write_fn(XIPIF_V123B_RESET_MASK, |
97 | XIPIF_V123B_RESET_MASK); | 147 | regs_base + XIPIF_V123B_RESETR_OFFSET); |
98 | /* Disable all the interrupts just in case */ | 148 | /* Disable all the interrupts just in case */ |
99 | out_be32(regs_base + XIPIF_V123B_IIER_OFFSET, 0); | 149 | xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET); |
100 | /* Enable the global IPIF interrupt */ | 150 | /* Enable the global IPIF interrupt */ |
101 | out_be32(regs_base + XIPIF_V123B_DGIER_OFFSET, | 151 | xspi->write_fn(XIPIF_V123B_GINTR_ENABLE, |
102 | XIPIF_V123B_GINTR_ENABLE); | 152 | regs_base + XIPIF_V123B_DGIER_OFFSET); |
103 | /* Deselect the slave on the SPI bus */ | 153 | /* Deselect the slave on the SPI bus */ |
104 | out_be32(regs_base + XSPI_SSR_OFFSET, 0xffff); | 154 | xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET); |
105 | /* Disable the transmitter, enable Manual Slave Select Assertion, | 155 | /* Disable the transmitter, enable Manual Slave Select Assertion, |
106 | * put SPI controller into master mode, and enable it */ | 156 | * put SPI controller into master mode, and enable it */ |
107 | out_be16(regs_base + XSPI_CR_OFFSET, | 157 | xspi->write_fn(XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT | |
108 | XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT | 158 | XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE | XSPI_CR_TXFIFO_RESET | |
109 | | XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE); | 159 | XSPI_CR_RXFIFO_RESET, regs_base + XSPI_CR_OFFSET); |
110 | } | 160 | } |
111 | 161 | ||
112 | static void xilinx_spi_chipselect(struct spi_device *spi, int is_on) | 162 | static void xilinx_spi_chipselect(struct spi_device *spi, int is_on) |
@@ -115,16 +165,16 @@ static void xilinx_spi_chipselect(struct spi_device *spi, int is_on) | |||
115 | 165 | ||
116 | if (is_on == BITBANG_CS_INACTIVE) { | 166 | if (is_on == BITBANG_CS_INACTIVE) { |
117 | /* Deselect the slave on the SPI bus */ | 167 | /* Deselect the slave on the SPI bus */ |
118 | out_be32(xspi->regs + XSPI_SSR_OFFSET, 0xffff); | 168 | xspi->write_fn(0xffff, xspi->regs + XSPI_SSR_OFFSET); |
119 | } else if (is_on == BITBANG_CS_ACTIVE) { | 169 | } else if (is_on == BITBANG_CS_ACTIVE) { |
120 | /* Set the SPI clock phase and polarity */ | 170 | /* Set the SPI clock phase and polarity */ |
121 | u16 cr = in_be16(xspi->regs + XSPI_CR_OFFSET) | 171 | u16 cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) |
122 | & ~XSPI_CR_MODE_MASK; | 172 | & ~XSPI_CR_MODE_MASK; |
123 | if (spi->mode & SPI_CPHA) | 173 | if (spi->mode & SPI_CPHA) |
124 | cr |= XSPI_CR_CPHA; | 174 | cr |= XSPI_CR_CPHA; |
125 | if (spi->mode & SPI_CPOL) | 175 | if (spi->mode & SPI_CPOL) |
126 | cr |= XSPI_CR_CPOL; | 176 | cr |= XSPI_CR_CPOL; |
127 | out_be16(xspi->regs + XSPI_CR_OFFSET, cr); | 177 | xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); |
128 | 178 | ||
129 | /* We do not check spi->max_speed_hz here as the SPI clock | 179 | /* We do not check spi->max_speed_hz here as the SPI clock |
130 | * frequency is not software programmable (the IP block design | 180 | * frequency is not software programmable (the IP block design |
@@ -132,25 +182,27 @@ static void xilinx_spi_chipselect(struct spi_device *spi, int is_on) | |||
132 | */ | 182 | */ |
133 | 183 | ||
134 | /* Activate the chip select */ | 184 | /* Activate the chip select */ |
135 | out_be32(xspi->regs + XSPI_SSR_OFFSET, | 185 | xspi->write_fn(~(0x0001 << spi->chip_select), |
136 | ~(0x0001 << spi->chip_select)); | 186 | xspi->regs + XSPI_SSR_OFFSET); |
137 | } | 187 | } |
138 | } | 188 | } |
139 | 189 | ||
140 | /* spi_bitbang requires custom setup_transfer() to be defined if there is a | 190 | /* spi_bitbang requires custom setup_transfer() to be defined if there is a |
141 | * custom txrx_bufs(). We have nothing to setup here as the SPI IP block | 191 | * custom txrx_bufs(). We have nothing to setup here as the SPI IP block |
142 | * supports just 8 bits per word, and SPI clock can't be changed in software. | 192 | * supports 8 or 16 bits per word which cannot be changed in software. |
143 | * Check for 8 bits per word. Chip select delay calculations could be | 193 | * SPI clock can't be changed in software either. |
194 | * Check for correct bits per word. Chip select delay calculations could be | ||
144 | * added here as soon as bitbang_work() can be made aware of the delay value. | 195 | * added here as soon as bitbang_work() can be made aware of the delay value. |
145 | */ | 196 | */ |
146 | static int xilinx_spi_setup_transfer(struct spi_device *spi, | 197 | static int xilinx_spi_setup_transfer(struct spi_device *spi, |
147 | struct spi_transfer *t) | 198 | struct spi_transfer *t) |
148 | { | 199 | { |
200 | struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); | ||
149 | u8 bits_per_word; | 201 | u8 bits_per_word; |
150 | 202 | ||
151 | bits_per_word = (t && t->bits_per_word) | 203 | bits_per_word = (t && t->bits_per_word) |
152 | ? t->bits_per_word : spi->bits_per_word; | 204 | ? t->bits_per_word : spi->bits_per_word; |
153 | if (bits_per_word != 8) { | 205 | if (bits_per_word != xspi->bits_per_word) { |
154 | dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n", | 206 | dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n", |
155 | __func__, bits_per_word); | 207 | __func__, bits_per_word); |
156 | return -EINVAL; | 208 | return -EINVAL; |
@@ -161,17 +213,16 @@ static int xilinx_spi_setup_transfer(struct spi_device *spi, | |||
161 | 213 | ||
162 | static int xilinx_spi_setup(struct spi_device *spi) | 214 | static int xilinx_spi_setup(struct spi_device *spi) |
163 | { | 215 | { |
164 | struct spi_bitbang *bitbang; | 216 | /* always return 0, we can not check the number of bits. |
165 | struct xilinx_spi *xspi; | 217 | * There are cases when SPI setup is called before any driver is |
166 | int retval; | 218 | * there, in that case the SPI core defaults to 8 bits, which we |
167 | 219 | * do not support in some cases. But if we return an error, the | |
168 | xspi = spi_master_get_devdata(spi->master); | 220 | * SPI device would not be registered and no driver can get hold of it |
169 | bitbang = &xspi->bitbang; | 221 | * When the driver is there, it will call SPI setup again with the |
170 | 222 | * correct number of bits per transfer. | |
171 | retval = xilinx_spi_setup_transfer(spi, NULL); | 223 | * If a driver setups with the wrong bit number, it will fail when |
172 | if (retval < 0) | 224 | * it tries to do a transfer |
173 | return retval; | 225 | */ |
174 | |||
175 | return 0; | 226 | return 0; |
176 | } | 227 | } |
177 | 228 | ||
@@ -180,15 +231,14 @@ static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi) | |||
180 | u8 sr; | 231 | u8 sr; |
181 | 232 | ||
182 | /* Fill the Tx FIFO with as many bytes as possible */ | 233 | /* Fill the Tx FIFO with as many bytes as possible */ |
183 | sr = in_8(xspi->regs + XSPI_SR_OFFSET); | 234 | sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); |
184 | while ((sr & XSPI_SR_TX_FULL_MASK) == 0 && xspi->remaining_bytes > 0) { | 235 | while ((sr & XSPI_SR_TX_FULL_MASK) == 0 && xspi->remaining_bytes > 0) { |
185 | if (xspi->tx_ptr) { | 236 | if (xspi->tx_ptr) |
186 | out_8(xspi->regs + XSPI_TXD_OFFSET, *xspi->tx_ptr++); | 237 | xspi->tx_fn(xspi); |
187 | } else { | 238 | else |
188 | out_8(xspi->regs + XSPI_TXD_OFFSET, 0); | 239 | xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET); |
189 | } | 240 | xspi->remaining_bytes -= xspi->bits_per_word / 8; |
190 | xspi->remaining_bytes--; | 241 | sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); |
191 | sr = in_8(xspi->regs + XSPI_SR_OFFSET); | ||
192 | } | 242 | } |
193 | } | 243 | } |
194 | 244 | ||
@@ -210,18 +260,19 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) | |||
210 | /* Enable the transmit empty interrupt, which we use to determine | 260 | /* Enable the transmit empty interrupt, which we use to determine |
211 | * progress on the transmission. | 261 | * progress on the transmission. |
212 | */ | 262 | */ |
213 | ipif_ier = in_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET); | 263 | ipif_ier = xspi->read_fn(xspi->regs + XIPIF_V123B_IIER_OFFSET); |
214 | out_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET, | 264 | xspi->write_fn(ipif_ier | XSPI_INTR_TX_EMPTY, |
215 | ipif_ier | XSPI_INTR_TX_EMPTY); | 265 | xspi->regs + XIPIF_V123B_IIER_OFFSET); |
216 | 266 | ||
217 | /* Start the transfer by not inhibiting the transmitter any longer */ | 267 | /* Start the transfer by not inhibiting the transmitter any longer */ |
218 | cr = in_be16(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_TRANS_INHIBIT; | 268 | cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) & |
219 | out_be16(xspi->regs + XSPI_CR_OFFSET, cr); | 269 | ~XSPI_CR_TRANS_INHIBIT; |
270 | xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); | ||
220 | 271 | ||
221 | wait_for_completion(&xspi->done); | 272 | wait_for_completion(&xspi->done); |
222 | 273 | ||
223 | /* Disable the transmit empty interrupt */ | 274 | /* Disable the transmit empty interrupt */ |
224 | out_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET, ipif_ier); | 275 | xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET); |
225 | 276 | ||
226 | return t->len - xspi->remaining_bytes; | 277 | return t->len - xspi->remaining_bytes; |
227 | } | 278 | } |
@@ -238,8 +289,8 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) | |||
238 | u32 ipif_isr; | 289 | u32 ipif_isr; |
239 | 290 | ||
240 | /* Get the IPIF interrupts, and clear them immediately */ | 291 | /* Get the IPIF interrupts, and clear them immediately */ |
241 | ipif_isr = in_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET); | 292 | ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET); |
242 | out_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET, ipif_isr); | 293 | xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET); |
243 | 294 | ||
244 | if (ipif_isr & XSPI_INTR_TX_EMPTY) { /* Transmission completed */ | 295 | if (ipif_isr & XSPI_INTR_TX_EMPTY) { /* Transmission completed */ |
245 | u16 cr; | 296 | u16 cr; |
@@ -250,20 +301,15 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) | |||
250 | * transmitter while the Isr refills the transmit register/FIFO, | 301 | * transmitter while the Isr refills the transmit register/FIFO, |
251 | * or make sure it is stopped if we're done. | 302 | * or make sure it is stopped if we're done. |
252 | */ | 303 | */ |
253 | cr = in_be16(xspi->regs + XSPI_CR_OFFSET); | 304 | cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET); |
254 | out_be16(xspi->regs + XSPI_CR_OFFSET, | 305 | xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT, |
255 | cr | XSPI_CR_TRANS_INHIBIT); | 306 | xspi->regs + XSPI_CR_OFFSET); |
256 | 307 | ||
257 | /* Read out all the data from the Rx FIFO */ | 308 | /* Read out all the data from the Rx FIFO */ |
258 | sr = in_8(xspi->regs + XSPI_SR_OFFSET); | 309 | sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); |
259 | while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) { | 310 | while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) { |
260 | u8 data; | 311 | xspi->rx_fn(xspi); |
261 | 312 | sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); | |
262 | data = in_8(xspi->regs + XSPI_RXD_OFFSET); | ||
263 | if (xspi->rx_ptr) { | ||
264 | *xspi->rx_ptr++ = data; | ||
265 | } | ||
266 | sr = in_8(xspi->regs + XSPI_SR_OFFSET); | ||
267 | } | 313 | } |
268 | 314 | ||
269 | /* See if there is more data to send */ | 315 | /* See if there is more data to send */ |
@@ -272,7 +318,7 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) | |||
272 | /* Start the transfer by not inhibiting the | 318 | /* Start the transfer by not inhibiting the |
273 | * transmitter any longer | 319 | * transmitter any longer |
274 | */ | 320 | */ |
275 | out_be16(xspi->regs + XSPI_CR_OFFSET, cr); | 321 | xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); |
276 | } else { | 322 | } else { |
277 | /* No more data to send. | 323 | /* No more data to send. |
278 | * Indicate the transfer is completed. | 324 | * Indicate the transfer is completed. |
@@ -284,40 +330,22 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) | |||
284 | return IRQ_HANDLED; | 330 | return IRQ_HANDLED; |
285 | } | 331 | } |
286 | 332 | ||
287 | static int __init xilinx_spi_of_probe(struct of_device *ofdev, | 333 | struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, |
288 | const struct of_device_id *match) | 334 | u32 irq, s16 bus_num) |
289 | { | 335 | { |
290 | struct spi_master *master; | 336 | struct spi_master *master; |
291 | struct xilinx_spi *xspi; | 337 | struct xilinx_spi *xspi; |
292 | struct resource r_irq_struct; | 338 | struct xspi_platform_data *pdata = dev->platform_data; |
293 | struct resource r_mem_struct; | 339 | int ret; |
294 | |||
295 | struct resource *r_irq = &r_irq_struct; | ||
296 | struct resource *r_mem = &r_mem_struct; | ||
297 | int rc = 0; | ||
298 | const u32 *prop; | ||
299 | int len; | ||
300 | |||
301 | /* Get resources(memory, IRQ) associated with the device */ | ||
302 | master = spi_alloc_master(&ofdev->dev, sizeof(struct xilinx_spi)); | ||
303 | 340 | ||
304 | if (master == NULL) { | 341 | if (!pdata) { |
305 | return -ENOMEM; | 342 | dev_err(dev, "No platform data attached\n"); |
343 | return NULL; | ||
306 | } | 344 | } |
307 | 345 | ||
308 | dev_set_drvdata(&ofdev->dev, master); | 346 | master = spi_alloc_master(dev, sizeof(struct xilinx_spi)); |
309 | 347 | if (!master) | |
310 | rc = of_address_to_resource(ofdev->node, 0, r_mem); | 348 | return NULL; |
311 | if (rc) { | ||
312 | dev_warn(&ofdev->dev, "invalid address\n"); | ||
313 | goto put_master; | ||
314 | } | ||
315 | |||
316 | rc = of_irq_to_resource(ofdev->node, 0, r_irq); | ||
317 | if (rc == NO_IRQ) { | ||
318 | dev_warn(&ofdev->dev, "no IRQ found\n"); | ||
319 | goto put_master; | ||
320 | } | ||
321 | 349 | ||
322 | /* the spi->mode bits understood by this driver: */ | 350 | /* the spi->mode bits understood by this driver: */ |
323 | master->mode_bits = SPI_CPOL | SPI_CPHA; | 351 | master->mode_bits = SPI_CPOL | SPI_CPHA; |
@@ -330,128 +358,87 @@ static int __init xilinx_spi_of_probe(struct of_device *ofdev, | |||
330 | xspi->bitbang.master->setup = xilinx_spi_setup; | 358 | xspi->bitbang.master->setup = xilinx_spi_setup; |
331 | init_completion(&xspi->done); | 359 | init_completion(&xspi->done); |
332 | 360 | ||
333 | xspi->irq = r_irq->start; | 361 | if (!request_mem_region(mem->start, resource_size(mem), |
334 | 362 | XILINX_SPI_NAME)) | |
335 | if (!request_mem_region(r_mem->start, | ||
336 | r_mem->end - r_mem->start + 1, XILINX_SPI_NAME)) { | ||
337 | rc = -ENXIO; | ||
338 | dev_warn(&ofdev->dev, "memory request failure\n"); | ||
339 | goto put_master; | 363 | goto put_master; |
340 | } | ||
341 | 364 | ||
342 | xspi->regs = ioremap(r_mem->start, r_mem->end - r_mem->start + 1); | 365 | xspi->regs = ioremap(mem->start, resource_size(mem)); |
343 | if (xspi->regs == NULL) { | 366 | if (xspi->regs == NULL) { |
344 | rc = -ENOMEM; | 367 | dev_warn(dev, "ioremap failure\n"); |
345 | dev_warn(&ofdev->dev, "ioremap failure\n"); | 368 | goto map_failed; |
346 | goto release_mem; | ||
347 | } | 369 | } |
348 | xspi->irq = r_irq->start; | ||
349 | |||
350 | /* dynamic bus assignment */ | ||
351 | master->bus_num = -1; | ||
352 | 370 | ||
353 | /* number of slave select bits is required */ | 371 | master->bus_num = bus_num; |
354 | prop = of_get_property(ofdev->node, "xlnx,num-ss-bits", &len); | 372 | master->num_chipselect = pdata->num_chipselect; |
355 | if (!prop || len < sizeof(*prop)) { | 373 | |
356 | dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n"); | 374 | xspi->mem = *mem; |
357 | goto unmap_io; | 375 | xspi->irq = irq; |
376 | if (pdata->little_endian) { | ||
377 | xspi->read_fn = ioread32; | ||
378 | xspi->write_fn = iowrite32; | ||
379 | } else { | ||
380 | xspi->read_fn = ioread32be; | ||
381 | xspi->write_fn = iowrite32be; | ||
358 | } | 382 | } |
359 | master->num_chipselect = *prop; | 383 | xspi->bits_per_word = pdata->bits_per_word; |
384 | if (xspi->bits_per_word == 8) { | ||
385 | xspi->tx_fn = xspi_tx8; | ||
386 | xspi->rx_fn = xspi_rx8; | ||
387 | } else if (xspi->bits_per_word == 16) { | ||
388 | xspi->tx_fn = xspi_tx16; | ||
389 | xspi->rx_fn = xspi_rx16; | ||
390 | } else if (xspi->bits_per_word == 32) { | ||
391 | xspi->tx_fn = xspi_tx32; | ||
392 | xspi->rx_fn = xspi_rx32; | ||
393 | } else | ||
394 | goto unmap_io; | ||
395 | |||
360 | 396 | ||
361 | /* SPI controller initializations */ | 397 | /* SPI controller initializations */ |
362 | xspi_init_hw(xspi->regs); | 398 | xspi_init_hw(xspi); |
363 | 399 | ||
364 | /* Register for SPI Interrupt */ | 400 | /* Register for SPI Interrupt */ |
365 | rc = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi); | 401 | ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi); |
366 | if (rc != 0) { | 402 | if (ret) |
367 | dev_warn(&ofdev->dev, "irq request failure: %d\n", xspi->irq); | ||
368 | goto unmap_io; | 403 | goto unmap_io; |
369 | } | ||
370 | 404 | ||
371 | rc = spi_bitbang_start(&xspi->bitbang); | 405 | ret = spi_bitbang_start(&xspi->bitbang); |
372 | if (rc != 0) { | 406 | if (ret) { |
373 | dev_err(&ofdev->dev, "spi_bitbang_start FAILED\n"); | 407 | dev_err(dev, "spi_bitbang_start FAILED\n"); |
374 | goto free_irq; | 408 | goto free_irq; |
375 | } | 409 | } |
376 | 410 | ||
377 | dev_info(&ofdev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n", | 411 | dev_info(dev, "at 0x%08llX mapped to 0x%p, irq=%d\n", |
378 | (unsigned int)r_mem->start, (u32)xspi->regs, xspi->irq); | 412 | (unsigned long long)mem->start, xspi->regs, xspi->irq); |
379 | 413 | return master; | |
380 | /* Add any subnodes on the SPI bus */ | ||
381 | of_register_spi_devices(master, ofdev->node); | ||
382 | |||
383 | return rc; | ||
384 | 414 | ||
385 | free_irq: | 415 | free_irq: |
386 | free_irq(xspi->irq, xspi); | 416 | free_irq(xspi->irq, xspi); |
387 | unmap_io: | 417 | unmap_io: |
388 | iounmap(xspi->regs); | 418 | iounmap(xspi->regs); |
389 | release_mem: | 419 | map_failed: |
390 | release_mem_region(r_mem->start, resource_size(r_mem)); | 420 | release_mem_region(mem->start, resource_size(mem)); |
391 | put_master: | 421 | put_master: |
392 | spi_master_put(master); | 422 | spi_master_put(master); |
393 | return rc; | 423 | return NULL; |
394 | } | 424 | } |
425 | EXPORT_SYMBOL(xilinx_spi_init); | ||
395 | 426 | ||
396 | static int __devexit xilinx_spi_remove(struct of_device *ofdev) | 427 | void xilinx_spi_deinit(struct spi_master *master) |
397 | { | 428 | { |
398 | struct xilinx_spi *xspi; | 429 | struct xilinx_spi *xspi; |
399 | struct spi_master *master; | ||
400 | struct resource r_mem; | ||
401 | 430 | ||
402 | master = platform_get_drvdata(ofdev); | ||
403 | xspi = spi_master_get_devdata(master); | 431 | xspi = spi_master_get_devdata(master); |
404 | 432 | ||
405 | spi_bitbang_stop(&xspi->bitbang); | 433 | spi_bitbang_stop(&xspi->bitbang); |
406 | free_irq(xspi->irq, xspi); | 434 | free_irq(xspi->irq, xspi); |
407 | iounmap(xspi->regs); | 435 | iounmap(xspi->regs); |
408 | if (!of_address_to_resource(ofdev->node, 0, &r_mem)) | ||
409 | release_mem_region(r_mem.start, resource_size(&r_mem)); | ||
410 | dev_set_drvdata(&ofdev->dev, 0); | ||
411 | spi_master_put(xspi->bitbang.master); | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | /* work with hotplug and coldplug */ | ||
417 | MODULE_ALIAS("platform:" XILINX_SPI_NAME); | ||
418 | |||
419 | static int __exit xilinx_spi_of_remove(struct of_device *op) | ||
420 | { | ||
421 | return xilinx_spi_remove(op); | ||
422 | } | ||
423 | 436 | ||
424 | static struct of_device_id xilinx_spi_of_match[] = { | 437 | release_mem_region(xspi->mem.start, resource_size(&xspi->mem)); |
425 | { .compatible = "xlnx,xps-spi-2.00.a", }, | 438 | spi_master_put(xspi->bitbang.master); |
426 | { .compatible = "xlnx,xps-spi-2.00.b", }, | ||
427 | {} | ||
428 | }; | ||
429 | |||
430 | MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); | ||
431 | |||
432 | static struct of_platform_driver xilinx_spi_of_driver = { | ||
433 | .owner = THIS_MODULE, | ||
434 | .name = "xilinx-xps-spi", | ||
435 | .match_table = xilinx_spi_of_match, | ||
436 | .probe = xilinx_spi_of_probe, | ||
437 | .remove = __exit_p(xilinx_spi_of_remove), | ||
438 | .driver = { | ||
439 | .name = "xilinx-xps-spi", | ||
440 | .owner = THIS_MODULE, | ||
441 | }, | ||
442 | }; | ||
443 | |||
444 | static int __init xilinx_spi_init(void) | ||
445 | { | ||
446 | return of_register_platform_driver(&xilinx_spi_of_driver); | ||
447 | } | 439 | } |
448 | module_init(xilinx_spi_init); | 440 | EXPORT_SYMBOL(xilinx_spi_deinit); |
449 | 441 | ||
450 | static void __exit xilinx_spi_exit(void) | ||
451 | { | ||
452 | of_unregister_platform_driver(&xilinx_spi_of_driver); | ||
453 | } | ||
454 | module_exit(xilinx_spi_exit); | ||
455 | MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); | 442 | MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); |
456 | MODULE_DESCRIPTION("Xilinx SPI driver"); | 443 | MODULE_DESCRIPTION("Xilinx SPI driver"); |
457 | MODULE_LICENSE("GPL"); | 444 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/spi/xilinx_spi.h b/drivers/spi/xilinx_spi.h new file mode 100644 index 000000000000..d211accf68d2 --- /dev/null +++ b/drivers/spi/xilinx_spi.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Xilinx SPI device driver API and platform data header file | ||
3 | * | ||
4 | * Copyright (c) 2009 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef _XILINX_SPI_H_ | ||
21 | #define _XILINX_SPI_H_ | ||
22 | |||
23 | #include <linux/spi/spi.h> | ||
24 | #include <linux/spi/spi_bitbang.h> | ||
25 | |||
26 | #define XILINX_SPI_NAME "xilinx_spi" | ||
27 | |||
28 | struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, | ||
29 | u32 irq, s16 bus_num); | ||
30 | |||
31 | void xilinx_spi_deinit(struct spi_master *master); | ||
32 | #endif | ||
diff --git a/drivers/spi/xilinx_spi_of.c b/drivers/spi/xilinx_spi_of.c new file mode 100644 index 000000000000..71dc3adc0495 --- /dev/null +++ b/drivers/spi/xilinx_spi_of.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * Xilinx SPI OF device driver | ||
3 | * | ||
4 | * Copyright (c) 2009 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | /* Supports: | ||
21 | * Xilinx SPI devices as OF devices | ||
22 | * | ||
23 | * Inspired by xilinx_spi.c, 2002-2007 (c) MontaVista Software, Inc. | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/io.h> | ||
30 | |||
31 | #include <linux/of_platform.h> | ||
32 | #include <linux/of_device.h> | ||
33 | #include <linux/of_spi.h> | ||
34 | |||
35 | #include <linux/spi/xilinx_spi.h> | ||
36 | #include "xilinx_spi.h" | ||
37 | |||
38 | |||
39 | static int __devinit xilinx_spi_of_probe(struct of_device *ofdev, | ||
40 | const struct of_device_id *match) | ||
41 | { | ||
42 | struct spi_master *master; | ||
43 | struct xspi_platform_data *pdata; | ||
44 | struct resource r_mem; | ||
45 | struct resource r_irq; | ||
46 | int rc = 0; | ||
47 | const u32 *prop; | ||
48 | int len; | ||
49 | |||
50 | rc = of_address_to_resource(ofdev->node, 0, &r_mem); | ||
51 | if (rc) { | ||
52 | dev_warn(&ofdev->dev, "invalid address\n"); | ||
53 | return rc; | ||
54 | } | ||
55 | |||
56 | rc = of_irq_to_resource(ofdev->node, 0, &r_irq); | ||
57 | if (rc == NO_IRQ) { | ||
58 | dev_warn(&ofdev->dev, "no IRQ found\n"); | ||
59 | return -ENODEV; | ||
60 | } | ||
61 | |||
62 | ofdev->dev.platform_data = | ||
63 | kzalloc(sizeof(struct xspi_platform_data), GFP_KERNEL); | ||
64 | pdata = ofdev->dev.platform_data; | ||
65 | if (!pdata) | ||
66 | return -ENOMEM; | ||
67 | |||
68 | /* number of slave select bits is required */ | ||
69 | prop = of_get_property(ofdev->node, "xlnx,num-ss-bits", &len); | ||
70 | if (!prop || len < sizeof(*prop)) { | ||
71 | dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n"); | ||
72 | return -EINVAL; | ||
73 | } | ||
74 | pdata->num_chipselect = *prop; | ||
75 | pdata->bits_per_word = 8; | ||
76 | master = xilinx_spi_init(&ofdev->dev, &r_mem, r_irq.start, -1); | ||
77 | if (!master) | ||
78 | return -ENODEV; | ||
79 | |||
80 | dev_set_drvdata(&ofdev->dev, master); | ||
81 | |||
82 | /* Add any subnodes on the SPI bus */ | ||
83 | of_register_spi_devices(master, ofdev->node); | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static int __devexit xilinx_spi_remove(struct of_device *ofdev) | ||
89 | { | ||
90 | xilinx_spi_deinit(dev_get_drvdata(&ofdev->dev)); | ||
91 | dev_set_drvdata(&ofdev->dev, 0); | ||
92 | kfree(ofdev->dev.platform_data); | ||
93 | ofdev->dev.platform_data = NULL; | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static int __exit xilinx_spi_of_remove(struct of_device *op) | ||
98 | { | ||
99 | return xilinx_spi_remove(op); | ||
100 | } | ||
101 | |||
102 | static struct of_device_id xilinx_spi_of_match[] = { | ||
103 | { .compatible = "xlnx,xps-spi-2.00.a", }, | ||
104 | { .compatible = "xlnx,xps-spi-2.00.b", }, | ||
105 | {} | ||
106 | }; | ||
107 | |||
108 | MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); | ||
109 | |||
110 | static struct of_platform_driver xilinx_spi_of_driver = { | ||
111 | .match_table = xilinx_spi_of_match, | ||
112 | .probe = xilinx_spi_of_probe, | ||
113 | .remove = __exit_p(xilinx_spi_of_remove), | ||
114 | .driver = { | ||
115 | .name = "xilinx-xps-spi", | ||
116 | .owner = THIS_MODULE, | ||
117 | }, | ||
118 | }; | ||
119 | |||
120 | static int __init xilinx_spi_of_init(void) | ||
121 | { | ||
122 | return of_register_platform_driver(&xilinx_spi_of_driver); | ||
123 | } | ||
124 | module_init(xilinx_spi_of_init); | ||
125 | |||
126 | static void __exit xilinx_spi_of_exit(void) | ||
127 | { | ||
128 | of_unregister_platform_driver(&xilinx_spi_of_driver); | ||
129 | } | ||
130 | module_exit(xilinx_spi_of_exit); | ||
131 | |||
132 | MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>"); | ||
133 | MODULE_DESCRIPTION("Xilinx SPI platform driver"); | ||
134 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/spi/xilinx_spi_pltfm.c b/drivers/spi/xilinx_spi_pltfm.c new file mode 100644 index 000000000000..24debac646a9 --- /dev/null +++ b/drivers/spi/xilinx_spi_pltfm.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * Support for Xilinx SPI platform devices | ||
3 | * Copyright (c) 2009 Intel Corporation | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | /* Supports: | ||
20 | * Xilinx SPI devices as platform devices | ||
21 | * | ||
22 | * Inspired by xilinx_spi.c, 2002-2007 (c) MontaVista Software, Inc. | ||
23 | */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | |||
31 | #include <linux/spi/spi.h> | ||
32 | #include <linux/spi/spi_bitbang.h> | ||
33 | #include <linux/spi/xilinx_spi.h> | ||
34 | |||
35 | #include "xilinx_spi.h" | ||
36 | |||
37 | static int __devinit xilinx_spi_probe(struct platform_device *dev) | ||
38 | { | ||
39 | struct xspi_platform_data *pdata; | ||
40 | struct resource *r; | ||
41 | int irq; | ||
42 | struct spi_master *master; | ||
43 | u8 i; | ||
44 | |||
45 | pdata = dev->dev.platform_data; | ||
46 | if (!pdata) | ||
47 | return -ENODEV; | ||
48 | |||
49 | r = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
50 | if (!r) | ||
51 | return -ENODEV; | ||
52 | |||
53 | irq = platform_get_irq(dev, 0); | ||
54 | if (irq < 0) | ||
55 | return -ENXIO; | ||
56 | |||
57 | master = xilinx_spi_init(&dev->dev, r, irq, dev->id); | ||
58 | if (!master) | ||
59 | return -ENODEV; | ||
60 | |||
61 | for (i = 0; i < pdata->num_devices; i++) | ||
62 | spi_new_device(master, pdata->devices + i); | ||
63 | |||
64 | platform_set_drvdata(dev, master); | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static int __devexit xilinx_spi_remove(struct platform_device *dev) | ||
69 | { | ||
70 | xilinx_spi_deinit(platform_get_drvdata(dev)); | ||
71 | platform_set_drvdata(dev, 0); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | /* work with hotplug and coldplug */ | ||
77 | MODULE_ALIAS("platform:" XILINX_SPI_NAME); | ||
78 | |||
79 | static struct platform_driver xilinx_spi_driver = { | ||
80 | .probe = xilinx_spi_probe, | ||
81 | .remove = __devexit_p(xilinx_spi_remove), | ||
82 | .driver = { | ||
83 | .name = XILINX_SPI_NAME, | ||
84 | .owner = THIS_MODULE, | ||
85 | }, | ||
86 | }; | ||
87 | |||
88 | static int __init xilinx_spi_pltfm_init(void) | ||
89 | { | ||
90 | return platform_driver_register(&xilinx_spi_driver); | ||
91 | } | ||
92 | module_init(xilinx_spi_pltfm_init); | ||
93 | |||
94 | static void __exit xilinx_spi_pltfm_exit(void) | ||
95 | { | ||
96 | platform_driver_unregister(&xilinx_spi_driver); | ||
97 | } | ||
98 | module_exit(xilinx_spi_pltfm_exit); | ||
99 | |||
100 | MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>"); | ||
101 | MODULE_DESCRIPTION("Xilinx SPI platform driver"); | ||
102 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/include/linux/spi/mpc52xx_spi.h b/include/linux/spi/mpc52xx_spi.h deleted file mode 100644 index d1004cf09241..000000000000 --- a/include/linux/spi/mpc52xx_spi.h +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | |||
2 | #ifndef INCLUDE_MPC5200_SPI_H | ||
3 | #define INCLUDE_MPC5200_SPI_H | ||
4 | |||
5 | extern void mpc52xx_spi_set_premessage_hook(struct spi_master *master, | ||
6 | void (*hook)(struct spi_message *m, | ||
7 | void *context), | ||
8 | void *hook_context); | ||
9 | |||
10 | #endif | ||
diff --git a/include/linux/spi/sh_msiof.h b/include/linux/spi/sh_msiof.h new file mode 100644 index 000000000000..2e8db3d2d2e5 --- /dev/null +++ b/include/linux/spi/sh_msiof.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef __SPI_SH_MSIOF_H__ | ||
2 | #define __SPI_SH_MSIOF_H__ | ||
3 | |||
4 | struct sh_msiof_spi_info { | ||
5 | int tx_fifo_override; | ||
6 | int rx_fifo_override; | ||
7 | u16 num_chipselect; | ||
8 | }; | ||
9 | |||
10 | #endif /* __SPI_SH_MSIOF_H__ */ | ||
diff --git a/include/linux/spi/xilinx_spi.h b/include/linux/spi/xilinx_spi.h new file mode 100644 index 000000000000..6f17278810b0 --- /dev/null +++ b/include/linux/spi/xilinx_spi.h | |||
@@ -0,0 +1,20 @@ | |||
1 | #ifndef __LINUX_SPI_XILINX_SPI_H | ||
2 | #define __LINUX_SPI_XILINX_SPI_H | ||
3 | |||
4 | /** | ||
5 | * struct xspi_platform_data - Platform data of the Xilinx SPI driver | ||
6 | * @num_chipselect: Number of chip select by the IP. | ||
7 | * @little_endian: If registers should be accessed little endian or not. | ||
8 | * @bits_per_word: Number of bits per word. | ||
9 | * @devices: Devices to add when the driver is probed. | ||
10 | * @num_devices: Number of devices in the devices array. | ||
11 | */ | ||
12 | struct xspi_platform_data { | ||
13 | u16 num_chipselect; | ||
14 | bool little_endian; | ||
15 | u8 bits_per_word; | ||
16 | struct spi_board_info *devices; | ||
17 | u8 num_devices; | ||
18 | }; | ||
19 | |||
20 | #endif /* __LINUX_SPI_XILINX_SPI_H */ | ||