aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-atmel.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-atmel.c')
-rw-r--r--drivers/spi/spi-atmel.c66
1 files changed, 50 insertions, 16 deletions
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 656d137db253..af3dbab600d5 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -22,9 +22,8 @@
22#include <linux/platform_data/atmel.h> 22#include <linux/platform_data/atmel.h>
23#include <linux/of.h> 23#include <linux/of.h>
24 24
25#include <asm/io.h> 25#include <linux/io.h>
26#include <asm/gpio.h> 26#include <linux/gpio.h>
27#include <mach/cpu.h>
28 27
29/* SPI register offsets */ 28/* SPI register offsets */
30#define SPI_CR 0x0000 29#define SPI_CR 0x0000
@@ -39,6 +38,7 @@
39#define SPI_CSR1 0x0034 38#define SPI_CSR1 0x0034
40#define SPI_CSR2 0x0038 39#define SPI_CSR2 0x0038
41#define SPI_CSR3 0x003c 40#define SPI_CSR3 0x003c
41#define SPI_VERSION 0x00fc
42#define SPI_RPR 0x0100 42#define SPI_RPR 0x0100
43#define SPI_RCR 0x0104 43#define SPI_RCR 0x0104
44#define SPI_TPR 0x0108 44#define SPI_TPR 0x0108
@@ -71,6 +71,8 @@
71#define SPI_FDIV_SIZE 1 71#define SPI_FDIV_SIZE 1
72#define SPI_MODFDIS_OFFSET 4 72#define SPI_MODFDIS_OFFSET 4
73#define SPI_MODFDIS_SIZE 1 73#define SPI_MODFDIS_SIZE 1
74#define SPI_WDRBT_OFFSET 5
75#define SPI_WDRBT_SIZE 1
74#define SPI_LLB_OFFSET 7 76#define SPI_LLB_OFFSET 7
75#define SPI_LLB_SIZE 1 77#define SPI_LLB_SIZE 1
76#define SPI_PCS_OFFSET 16 78#define SPI_PCS_OFFSET 16
@@ -180,6 +182,11 @@
180#define spi_writel(port,reg,value) \ 182#define spi_writel(port,reg,value) \
181 __raw_writel((value), (port)->regs + SPI_##reg) 183 __raw_writel((value), (port)->regs + SPI_##reg)
182 184
185struct atmel_spi_caps {
186 bool is_spi2;
187 bool has_wdrbt;
188 bool has_dma_support;
189};
183 190
184/* 191/*
185 * The core SPI transfer engine just talks to a register bank to set up 192 * The core SPI transfer engine just talks to a register bank to set up
@@ -204,6 +211,8 @@ struct atmel_spi {
204 211
205 void *buffer; 212 void *buffer;
206 dma_addr_t buffer_dma; 213 dma_addr_t buffer_dma;
214
215 struct atmel_spi_caps caps;
207}; 216};
208 217
209/* Controller-specific per-slave state */ 218/* Controller-specific per-slave state */
@@ -222,14 +231,10 @@ struct atmel_spi_device {
222 * - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs) 231 * - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs)
223 * - SPI_CSRx.CSAAT 232 * - SPI_CSRx.CSAAT
224 * - SPI_CSRx.SBCR allows faster clocking 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 */
230static bool atmel_spi_is_v2(void) 235static 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/*
@@ -263,15 +268,20 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
263 unsigned active = spi->mode & SPI_CS_HIGH; 268 unsigned active = spi->mode & SPI_CS_HIGH;
264 u32 mr; 269 u32 mr;
265 270
266 if (atmel_spi_is_v2()) { 271 if (atmel_spi_is_v2(as)) {
267 /* 272 /*
268 * Always use CSR0. This ensures that the clock 273 * Always use CSR0. This ensures that the clock
269 * switches to the correct idle polarity before we 274 * switches to the correct idle polarity before we
270 * toggle the CS. 275 * toggle the CS.
271 */ 276 */
272 spi_writel(as, CSR0, asd->csr); 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 | SPI_BIT(MSTR)); 283 | SPI_BIT(MSTR));
284 }
275 mr = spi_readl(as, MR); 285 mr = spi_readl(as, MR);
276 gpio_set_value(asd->npcs_pin, active); 286 gpio_set_value(asd->npcs_pin, active);
277 } else { 287 } else {
@@ -318,7 +328,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
318 asd->npcs_pin, active ? " (low)" : "", 328 asd->npcs_pin, active ? " (low)" : "",
319 mr); 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 gpio_set_value(asd->npcs_pin, !active); 332 gpio_set_value(asd->npcs_pin, !active);
323} 333}
324 334
@@ -719,7 +729,7 @@ static int atmel_spi_setup(struct spi_device *spi)
719 } 729 }
720 730
721 /* see notes above re chipselect */ 731 /* see notes above re chipselect */
722 if (!atmel_spi_is_v2() 732 if (!atmel_spi_is_v2(as)
723 && spi->chip_select == 0 733 && spi->chip_select == 0
724 && (spi->mode & SPI_CS_HIGH)) { 734 && (spi->mode & SPI_CS_HIGH)) {
725 dev_dbg(&spi->dev, "setup: can't be active-high\n"); 735 dev_dbg(&spi->dev, "setup: can't be active-high\n");
@@ -728,7 +738,7 @@ static int atmel_spi_setup(struct spi_device *spi)
728 738
729 /* v1 chips start out at half the peripheral bus speed. */ 739 /* v1 chips start out at half the peripheral bus speed. */
730 bus_hz = clk_get_rate(as->clk); 740 bus_hz = clk_get_rate(as->clk);
731 if (!atmel_spi_is_v2()) 741 if (!atmel_spi_is_v2(as))
732 bus_hz /= 2; 742 bus_hz /= 2;
733 743
734 if (spi->max_speed_hz) { 744 if (spi->max_speed_hz) {
@@ -804,7 +814,7 @@ static int atmel_spi_setup(struct spi_device *spi)
804 "setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n", 814 "setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n",
805 bus_hz / scbr, bits, spi->mode, spi->chip_select, csr); 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 spi_writel(as, CSR0 + 4 * spi->chip_select, csr); 818 spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
809 819
810 return 0; 820 return 0;
@@ -910,6 +920,23 @@ static void atmel_spi_cleanup(struct spi_device *spi)
910 kfree(asd); 920 kfree(asd);
911} 921}
912 922
923static inline unsigned int atmel_get_version(struct atmel_spi *as)
924{
925 return spi_readl(as, VERSION) & 0x00000fff;
926}
927
928static 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
915static int atmel_spi_probe(struct platform_device *pdev) 942static int atmel_spi_probe(struct platform_device *pdev)
@@ -970,6 +997,8 @@ static int atmel_spi_probe(struct platform_device *pdev)
970 as->irq = irq; 997 as->irq = irq;
971 as->clk = clk; 998 as->clk = clk;
972 999
1000 atmel_get_caps(as);
1001
973 ret = request_irq(irq, atmel_spi_interrupt, 0, 1002 ret = request_irq(irq, atmel_spi_interrupt, 0,
974 dev_name(&pdev->dev), master); 1003 dev_name(&pdev->dev), master);
975 if (ret) 1004 if (ret)
@@ -979,7 +1008,12 @@ static int atmel_spi_probe(struct platform_device *pdev)
979 clk_enable(clk); 1008 clk_enable(clk);
980 spi_writel(as, CR, SPI_BIT(SWRST)); 1009 spi_writel(as, CR, SPI_BIT(SWRST));
981 spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ 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 spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); 1017 spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
984 spi_writel(as, CR, SPI_BIT(SPIEN)); 1018 spi_writel(as, CR, SPI_BIT(SPIEN));
985 1019