summaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-octeon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-octeon.c')
-rw-r--r--drivers/spi/spi-octeon.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/drivers/spi/spi-octeon.c b/drivers/spi/spi-octeon.c
index e72204089a88..209eddcc19b6 100644
--- a/drivers/spi/spi-octeon.c
+++ b/drivers/spi/spi-octeon.c
@@ -17,22 +17,30 @@
17#include <asm/octeon/octeon.h> 17#include <asm/octeon/octeon.h>
18#include <asm/octeon/cvmx-mpi-defs.h> 18#include <asm/octeon/cvmx-mpi-defs.h>
19 19
20#define OCTEON_SPI_CFG 0
21#define OCTEON_SPI_STS 0x08
22#define OCTEON_SPI_TX 0x10
23#define OCTEON_SPI_DAT0 0x80
24
25#define OCTEON_SPI_MAX_BYTES 9 20#define OCTEON_SPI_MAX_BYTES 9
26 21
27#define OCTEON_SPI_MAX_CLOCK_HZ 16000000 22#define OCTEON_SPI_MAX_CLOCK_HZ 16000000
28 23
24struct octeon_spi_regs {
25 int config;
26 int status;
27 int tx;
28 int data;
29};
30
29struct octeon_spi { 31struct octeon_spi {
30 void __iomem *register_base; 32 void __iomem *register_base;
31 u64 last_cfg; 33 u64 last_cfg;
32 u64 cs_enax; 34 u64 cs_enax;
33 int sys_freq; 35 int sys_freq;
36 struct octeon_spi_regs regs;
34}; 37};
35 38
39#define OCTEON_SPI_CFG(x) (x->regs.config)
40#define OCTEON_SPI_STS(x) (x->regs.status)
41#define OCTEON_SPI_TX(x) (x->regs.tx)
42#define OCTEON_SPI_DAT0(x) (x->regs.data)
43
36static void octeon_spi_wait_ready(struct octeon_spi *p) 44static void octeon_spi_wait_ready(struct octeon_spi *p)
37{ 45{
38 union cvmx_mpi_sts mpi_sts; 46 union cvmx_mpi_sts mpi_sts;
@@ -41,7 +49,7 @@ static void octeon_spi_wait_ready(struct octeon_spi *p)
41 do { 49 do {
42 if (loops++) 50 if (loops++)
43 __delay(500); 51 __delay(500);
44 mpi_sts.u64 = readq(p->register_base + OCTEON_SPI_STS); 52 mpi_sts.u64 = readq(p->register_base + OCTEON_SPI_STS(p));
45 } while (mpi_sts.s.busy); 53 } while (mpi_sts.s.busy);
46} 54}
47 55
@@ -83,7 +91,7 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
83 91
84 if (mpi_cfg.u64 != p->last_cfg) { 92 if (mpi_cfg.u64 != p->last_cfg) {
85 p->last_cfg = mpi_cfg.u64; 93 p->last_cfg = mpi_cfg.u64;
86 writeq(mpi_cfg.u64, p->register_base + OCTEON_SPI_CFG); 94 writeq(mpi_cfg.u64, p->register_base + OCTEON_SPI_CFG(p));
87 } 95 }
88 tx_buf = xfer->tx_buf; 96 tx_buf = xfer->tx_buf;
89 rx_buf = xfer->rx_buf; 97 rx_buf = xfer->rx_buf;
@@ -95,19 +103,19 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
95 d = *tx_buf++; 103 d = *tx_buf++;
96 else 104 else
97 d = 0; 105 d = 0;
98 writeq(d, p->register_base + OCTEON_SPI_DAT0 + (8 * i)); 106 writeq(d, p->register_base + OCTEON_SPI_DAT0(p) + (8 * i));
99 } 107 }
100 mpi_tx.u64 = 0; 108 mpi_tx.u64 = 0;
101 mpi_tx.s.csid = spi->chip_select; 109 mpi_tx.s.csid = spi->chip_select;
102 mpi_tx.s.leavecs = 1; 110 mpi_tx.s.leavecs = 1;
103 mpi_tx.s.txnum = tx_buf ? OCTEON_SPI_MAX_BYTES : 0; 111 mpi_tx.s.txnum = tx_buf ? OCTEON_SPI_MAX_BYTES : 0;
104 mpi_tx.s.totnum = OCTEON_SPI_MAX_BYTES; 112 mpi_tx.s.totnum = OCTEON_SPI_MAX_BYTES;
105 writeq(mpi_tx.u64, p->register_base + OCTEON_SPI_TX); 113 writeq(mpi_tx.u64, p->register_base + OCTEON_SPI_TX(p));
106 114
107 octeon_spi_wait_ready(p); 115 octeon_spi_wait_ready(p);
108 if (rx_buf) 116 if (rx_buf)
109 for (i = 0; i < OCTEON_SPI_MAX_BYTES; i++) { 117 for (i = 0; i < OCTEON_SPI_MAX_BYTES; i++) {
110 u64 v = readq(p->register_base + OCTEON_SPI_DAT0 + (8 * i)); 118 u64 v = readq(p->register_base + OCTEON_SPI_DAT0(p) + (8 * i));
111 *rx_buf++ = (u8)v; 119 *rx_buf++ = (u8)v;
112 } 120 }
113 len -= OCTEON_SPI_MAX_BYTES; 121 len -= OCTEON_SPI_MAX_BYTES;
@@ -119,7 +127,7 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
119 d = *tx_buf++; 127 d = *tx_buf++;
120 else 128 else
121 d = 0; 129 d = 0;
122 writeq(d, p->register_base + OCTEON_SPI_DAT0 + (8 * i)); 130 writeq(d, p->register_base + OCTEON_SPI_DAT0(p) + (8 * i));
123 } 131 }
124 132
125 mpi_tx.u64 = 0; 133 mpi_tx.u64 = 0;
@@ -130,12 +138,12 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
130 mpi_tx.s.leavecs = !xfer->cs_change; 138 mpi_tx.s.leavecs = !xfer->cs_change;
131 mpi_tx.s.txnum = tx_buf ? len : 0; 139 mpi_tx.s.txnum = tx_buf ? len : 0;
132 mpi_tx.s.totnum = len; 140 mpi_tx.s.totnum = len;
133 writeq(mpi_tx.u64, p->register_base + OCTEON_SPI_TX); 141 writeq(mpi_tx.u64, p->register_base + OCTEON_SPI_TX(p));
134 142
135 octeon_spi_wait_ready(p); 143 octeon_spi_wait_ready(p);
136 if (rx_buf) 144 if (rx_buf)
137 for (i = 0; i < len; i++) { 145 for (i = 0; i < len; i++) {
138 u64 v = readq(p->register_base + OCTEON_SPI_DAT0 + (8 * i)); 146 u64 v = readq(p->register_base + OCTEON_SPI_DAT0(p) + (8 * i));
139 *rx_buf++ = (u8)v; 147 *rx_buf++ = (u8)v;
140 } 148 }
141 149
@@ -194,6 +202,11 @@ static int octeon_spi_probe(struct platform_device *pdev)
194 p->register_base = reg_base; 202 p->register_base = reg_base;
195 p->sys_freq = octeon_get_io_clock_rate(); 203 p->sys_freq = octeon_get_io_clock_rate();
196 204
205 p->regs.config = 0;
206 p->regs.status = 0x08;
207 p->regs.tx = 0x10;
208 p->regs.data = 0x80;
209
197 master->num_chipselect = 4; 210 master->num_chipselect = 4;
198 master->mode_bits = SPI_CPHA | 211 master->mode_bits = SPI_CPHA |
199 SPI_CPOL | 212 SPI_CPOL |
@@ -226,7 +239,7 @@ static int octeon_spi_remove(struct platform_device *pdev)
226 struct octeon_spi *p = spi_master_get_devdata(master); 239 struct octeon_spi *p = spi_master_get_devdata(master);
227 240
228 /* Clear the CSENA* and put everything in a known state. */ 241 /* Clear the CSENA* and put everything in a known state. */
229 writeq(0, p->register_base + OCTEON_SPI_CFG); 242 writeq(0, p->register_base + OCTEON_SPI_CFG(p));
230 243
231 return 0; 244 return 0;
232} 245}