Commit d4820b7496219edd9a7055022681364d304525f7

Authored by Wenyou Yang
Committed by Mark Brown
1 parent faa98f7ea6

spi/spi-atmel: detect the capabilities of SPI core by reading the VERSION register.

The "has_dma_support" needed for future use with dmaengine driver.

[Fixed some unneded ternery operators -- broonie]

Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

Showing 1 changed file with 50 additions and 16 deletions Side-by-side Diff

drivers/spi/spi-atmel.c
... ... @@ -22,9 +22,8 @@
22 22 #include <linux/platform_data/atmel.h>
23 23 #include <linux/of.h>
24 24  
25   -#include <asm/io.h>
26   -#include <asm/gpio.h>
27   -#include <mach/cpu.h>
  25 +#include <linux/io.h>
  26 +#include <linux/gpio.h>
28 27  
29 28 /* SPI register offsets */
30 29 #define SPI_CR 0x0000
... ... @@ -39,6 +38,7 @@
39 38 #define SPI_CSR1 0x0034
40 39 #define SPI_CSR2 0x0038
41 40 #define SPI_CSR3 0x003c
  41 +#define SPI_VERSION 0x00fc
42 42 #define SPI_RPR 0x0100
43 43 #define SPI_RCR 0x0104
44 44 #define SPI_TPR 0x0108
... ... @@ -71,6 +71,8 @@
71 71 #define SPI_FDIV_SIZE 1
72 72 #define SPI_MODFDIS_OFFSET 4
73 73 #define SPI_MODFDIS_SIZE 1
  74 +#define SPI_WDRBT_OFFSET 5
  75 +#define SPI_WDRBT_SIZE 1
74 76 #define SPI_LLB_OFFSET 7
75 77 #define SPI_LLB_SIZE 1
76 78 #define SPI_PCS_OFFSET 16
... ... @@ -180,6 +182,11 @@
180 182 #define spi_writel(port,reg,value) \
181 183 __raw_writel((value), (port)->regs + SPI_##reg)
182 184  
  185 +struct atmel_spi_caps {
  186 + bool is_spi2;
  187 + bool has_wdrbt;
  188 + bool has_dma_support;
  189 +};
183 190  
184 191 /*
185 192 * The core SPI transfer engine just talks to a register bank to set up
... ... @@ -204,6 +211,8 @@
204 211  
205 212 void *buffer;
206 213 dma_addr_t buffer_dma;
  214 +
  215 + struct atmel_spi_caps caps;
207 216 };
208 217  
209 218 /* Controller-specific per-slave state */
210 219  
211 220  
... ... @@ -222,14 +231,10 @@
222 231 * - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs)
223 232 * - SPI_CSRx.CSAAT
224 233 * - SPI_CSRx.SBCR allows faster clocking
225   - *
226   - * We can determine the controller version by reading the VERSION
227   - * register, but I haven't checked that it exists on all chips, and
228   - * this is cheaper anyway.
229 234 */
230   -static bool atmel_spi_is_v2(void)
  235 +static bool atmel_spi_is_v2(struct atmel_spi *as)
231 236 {
232   - return !cpu_is_at91rm9200();
  237 + return as->caps.is_spi2;
233 238 }
234 239  
235 240 /*
236 241  
237 242  
... ... @@ -263,15 +268,20 @@
263 268 unsigned active = spi->mode & SPI_CS_HIGH;
264 269 u32 mr;
265 270  
266   - if (atmel_spi_is_v2()) {
  271 + if (atmel_spi_is_v2(as)) {
267 272 /*
268 273 * Always use CSR0. This ensures that the clock
269 274 * switches to the correct idle polarity before we
270 275 * toggle the CS.
271 276 */
272 277 spi_writel(as, CSR0, asd->csr);
273   - spi_writel(as, MR, SPI_BF(PCS, 0x0e) | SPI_BIT(MODFDIS)
  278 + if (as->caps.has_wdrbt) {
  279 + spi_writel(as, MR, SPI_BF(PCS, 0x0e) | SPI_BIT(WDRBT)
  280 + | SPI_BIT(MODFDIS) | SPI_BIT(MSTR));
  281 + } else {
  282 + spi_writel(as, MR, SPI_BF(PCS, 0x0e) | SPI_BIT(MODFDIS)
274 283 | SPI_BIT(MSTR));
  284 + }
275 285 mr = spi_readl(as, MR);
276 286 gpio_set_value(asd->npcs_pin, active);
277 287 } else {
... ... @@ -318,7 +328,7 @@
318 328 asd->npcs_pin, active ? " (low)" : "",
319 329 mr);
320 330  
321   - if (atmel_spi_is_v2() || spi->chip_select != 0)
  331 + if (atmel_spi_is_v2(as) || spi->chip_select != 0)
322 332 gpio_set_value(asd->npcs_pin, !active);
323 333 }
324 334  
... ... @@ -719,7 +729,7 @@
719 729 }
720 730  
721 731 /* see notes above re chipselect */
722   - if (!atmel_spi_is_v2()
  732 + if (!atmel_spi_is_v2(as)
723 733 && spi->chip_select == 0
724 734 && (spi->mode & SPI_CS_HIGH)) {
725 735 dev_dbg(&spi->dev, "setup: can't be active-high\n");
... ... @@ -728,7 +738,7 @@
728 738  
729 739 /* v1 chips start out at half the peripheral bus speed. */
730 740 bus_hz = clk_get_rate(as->clk);
731   - if (!atmel_spi_is_v2())
  741 + if (!atmel_spi_is_v2(as))
732 742 bus_hz /= 2;
733 743  
734 744 if (spi->max_speed_hz) {
... ... @@ -804,7 +814,7 @@
804 814 "setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n",
805 815 bus_hz / scbr, bits, spi->mode, spi->chip_select, csr);
806 816  
807   - if (!atmel_spi_is_v2())
  817 + if (!atmel_spi_is_v2(as))
808 818 spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
809 819  
810 820 return 0;
... ... @@ -910,6 +920,23 @@
910 920 kfree(asd);
911 921 }
912 922  
  923 +static inline unsigned int atmel_get_version(struct atmel_spi *as)
  924 +{
  925 + return spi_readl(as, VERSION) & 0x00000fff;
  926 +}
  927 +
  928 +static void atmel_get_caps(struct atmel_spi *as)
  929 +{
  930 + unsigned int version;
  931 +
  932 + version = atmel_get_version(as);
  933 + dev_info(&as->pdev->dev, "version: 0x%x\n", version);
  934 +
  935 + as->caps.is_spi2 = version > 0x121;
  936 + as->caps.has_wdrbt = version >= 0x210;
  937 + as->caps.has_dma_support = version >= 0x212;
  938 +}
  939 +
913 940 /*-------------------------------------------------------------------------*/
914 941  
915 942 static int atmel_spi_probe(struct platform_device *pdev)
... ... @@ -970,6 +997,8 @@
970 997 as->irq = irq;
971 998 as->clk = clk;
972 999  
  1000 + atmel_get_caps(as);
  1001 +
973 1002 ret = request_irq(irq, atmel_spi_interrupt, 0,
974 1003 dev_name(&pdev->dev), master);
975 1004 if (ret)
... ... @@ -979,7 +1008,12 @@
979 1008 clk_enable(clk);
980 1009 spi_writel(as, CR, SPI_BIT(SWRST));
981 1010 spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
982   - spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS));
  1011 + if (as->caps.has_wdrbt) {
  1012 + spi_writel(as, MR, SPI_BIT(WDRBT) | SPI_BIT(MODFDIS)
  1013 + | SPI_BIT(MSTR));
  1014 + } else {
  1015 + spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS));
  1016 + }
983 1017 spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
984 1018 spi_writel(as, CR, SPI_BIT(SPIEN));
985 1019