diff options
author | Richard Röjfors <richard.rojfors@mocean-labs.com> | 2009-11-13 06:28:49 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2009-12-08 20:48:14 -0500 |
commit | 86fc593599c11b62a11c85b4d7b709089df15c29 (patch) | |
tree | aea08df21b6c9b7e6fe7b4a93c00ae56d8737140 /drivers/spi | |
parent | d5af91a1faca68e9a8cc493b85aa7b194b6128aa (diff) |
xilinx_spi: Switch to iomem functions and support little endian.
This patch changes the out_(be)(8|16|32) and in_(be)(8|16|32) calls to 32 bits ioread/iowrite.
The read and write function are attached to the internal struct as callbacks, callback
is selected depending on endianess.
This will also build on platforms not supporting the in/out calls for instance x86.
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Tested-by: John Linn <John.Linn@xilinx.com>
Signed-off-by: Richard Röjfors <richard.rojfors@mocean-labs.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/Kconfig | 2 | ||||
-rw-r--r-- | drivers/spi/xilinx_spi.c | 96 |
2 files changed, 55 insertions, 43 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index f34a2d16d18f..b528271c72ef 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -244,7 +244,7 @@ config SPI_TXX9 | |||
244 | 244 | ||
245 | config SPI_XILINX | 245 | config SPI_XILINX |
246 | tristate "Xilinx SPI controller" | 246 | tristate "Xilinx SPI controller" |
247 | depends on EXPERIMENTAL | 247 | depends on HAS_IOMEM && EXPERIMENTAL |
248 | select SPI_BITBANG | 248 | select SPI_BITBANG |
249 | select SPI_XILINX_OF if (XILINX_VIRTEX || MICROBLAZE) | 249 | select SPI_XILINX_OF if (XILINX_VIRTEX || MICROBLAZE) |
250 | help | 250 | help |
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index 69fa26d82ce4..135a3a5931a4 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c | |||
@@ -27,7 +27,7 @@ | |||
27 | /* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e) | 27 | /* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e) |
28 | * Product Specification", DS464 | 28 | * Product Specification", DS464 |
29 | */ | 29 | */ |
30 | #define XSPI_CR_OFFSET 0x62 /* 16-bit Control Register */ | 30 | #define XSPI_CR_OFFSET 0x60 /* 16-bit Control Register */ |
31 | 31 | ||
32 | #define XSPI_CR_ENABLE 0x02 | 32 | #define XSPI_CR_ENABLE 0x02 |
33 | #define XSPI_CR_MASTER_MODE 0x04 | 33 | #define XSPI_CR_MASTER_MODE 0x04 |
@@ -39,7 +39,7 @@ | |||
39 | #define XSPI_CR_MANUAL_SSELECT 0x80 | 39 | #define XSPI_CR_MANUAL_SSELECT 0x80 |
40 | #define XSPI_CR_TRANS_INHIBIT 0x100 | 40 | #define XSPI_CR_TRANS_INHIBIT 0x100 |
41 | 41 | ||
42 | #define XSPI_SR_OFFSET 0x67 /* 8-bit Status Register */ | 42 | #define XSPI_SR_OFFSET 0x64 /* 8-bit Status Register */ |
43 | 43 | ||
44 | #define XSPI_SR_RX_EMPTY_MASK 0x01 /* Receive FIFO is empty */ | 44 | #define XSPI_SR_RX_EMPTY_MASK 0x01 /* Receive FIFO is empty */ |
45 | #define XSPI_SR_RX_FULL_MASK 0x02 /* Receive FIFO is full */ | 45 | #define XSPI_SR_RX_FULL_MASK 0x02 /* Receive FIFO is full */ |
@@ -47,8 +47,8 @@ | |||
47 | #define XSPI_SR_TX_FULL_MASK 0x08 /* Transmit FIFO is full */ | 47 | #define XSPI_SR_TX_FULL_MASK 0x08 /* Transmit FIFO is full */ |
48 | #define XSPI_SR_MODE_FAULT_MASK 0x10 /* Mode fault error */ | 48 | #define XSPI_SR_MODE_FAULT_MASK 0x10 /* Mode fault error */ |
49 | 49 | ||
50 | #define XSPI_TXD_OFFSET 0x6b /* 8-bit Data Transmit Register */ | 50 | #define XSPI_TXD_OFFSET 0x68 /* 8-bit Data Transmit Register */ |
51 | #define XSPI_RXD_OFFSET 0x6f /* 8-bit Data Receive Register */ | 51 | #define XSPI_RXD_OFFSET 0x6c /* 8-bit Data Receive Register */ |
52 | 52 | ||
53 | #define XSPI_SSR_OFFSET 0x70 /* 32-bit Slave Select Register */ | 53 | #define XSPI_SSR_OFFSET 0x70 /* 32-bit Slave Select Register */ |
54 | 54 | ||
@@ -86,25 +86,29 @@ struct xilinx_spi { | |||
86 | u8 *rx_ptr; /* pointer in the Tx buffer */ | 86 | u8 *rx_ptr; /* pointer in the Tx buffer */ |
87 | const u8 *tx_ptr; /* pointer in the Rx buffer */ | 87 | const u8 *tx_ptr; /* pointer in the Rx buffer */ |
88 | int remaining_bytes; /* the number of bytes left to transfer */ | 88 | int remaining_bytes; /* the number of bytes left to transfer */ |
89 | unsigned int (*read_fn) (void __iomem *); | ||
90 | void (*write_fn) (u32, void __iomem *); | ||
89 | }; | 91 | }; |
90 | 92 | ||
91 | static void xspi_init_hw(void __iomem *regs_base) | 93 | static void xspi_init_hw(struct xilinx_spi *xspi) |
92 | { | 94 | { |
95 | void __iomem *regs_base = xspi->regs; | ||
96 | |||
93 | /* Reset the SPI device */ | 97 | /* Reset the SPI device */ |
94 | out_be32(regs_base + XIPIF_V123B_RESETR_OFFSET, | 98 | xspi->write_fn(XIPIF_V123B_RESET_MASK, |
95 | XIPIF_V123B_RESET_MASK); | 99 | regs_base + XIPIF_V123B_RESETR_OFFSET); |
96 | /* Disable all the interrupts just in case */ | 100 | /* Disable all the interrupts just in case */ |
97 | out_be32(regs_base + XIPIF_V123B_IIER_OFFSET, 0); | 101 | xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET); |
98 | /* Enable the global IPIF interrupt */ | 102 | /* Enable the global IPIF interrupt */ |
99 | out_be32(regs_base + XIPIF_V123B_DGIER_OFFSET, | 103 | xspi->write_fn(XIPIF_V123B_GINTR_ENABLE, |
100 | XIPIF_V123B_GINTR_ENABLE); | 104 | regs_base + XIPIF_V123B_DGIER_OFFSET); |
101 | /* Deselect the slave on the SPI bus */ | 105 | /* Deselect the slave on the SPI bus */ |
102 | out_be32(regs_base + XSPI_SSR_OFFSET, 0xffff); | 106 | xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET); |
103 | /* Disable the transmitter, enable Manual Slave Select Assertion, | 107 | /* Disable the transmitter, enable Manual Slave Select Assertion, |
104 | * put SPI controller into master mode, and enable it */ | 108 | * put SPI controller into master mode, and enable it */ |
105 | out_be16(regs_base + XSPI_CR_OFFSET, | 109 | xspi->write_fn(XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT | |
106 | XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT | 110 | XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE, |
107 | | XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE); | 111 | regs_base + XSPI_CR_OFFSET); |
108 | } | 112 | } |
109 | 113 | ||
110 | static void xilinx_spi_chipselect(struct spi_device *spi, int is_on) | 114 | static void xilinx_spi_chipselect(struct spi_device *spi, int is_on) |
@@ -113,16 +117,16 @@ static void xilinx_spi_chipselect(struct spi_device *spi, int is_on) | |||
113 | 117 | ||
114 | if (is_on == BITBANG_CS_INACTIVE) { | 118 | if (is_on == BITBANG_CS_INACTIVE) { |
115 | /* Deselect the slave on the SPI bus */ | 119 | /* Deselect the slave on the SPI bus */ |
116 | out_be32(xspi->regs + XSPI_SSR_OFFSET, 0xffff); | 120 | xspi->write_fn(0xffff, xspi->regs + XSPI_SSR_OFFSET); |
117 | } else if (is_on == BITBANG_CS_ACTIVE) { | 121 | } else if (is_on == BITBANG_CS_ACTIVE) { |
118 | /* Set the SPI clock phase and polarity */ | 122 | /* Set the SPI clock phase and polarity */ |
119 | u16 cr = in_be16(xspi->regs + XSPI_CR_OFFSET) | 123 | u16 cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) |
120 | & ~XSPI_CR_MODE_MASK; | 124 | & ~XSPI_CR_MODE_MASK; |
121 | if (spi->mode & SPI_CPHA) | 125 | if (spi->mode & SPI_CPHA) |
122 | cr |= XSPI_CR_CPHA; | 126 | cr |= XSPI_CR_CPHA; |
123 | if (spi->mode & SPI_CPOL) | 127 | if (spi->mode & SPI_CPOL) |
124 | cr |= XSPI_CR_CPOL; | 128 | cr |= XSPI_CR_CPOL; |
125 | out_be16(xspi->regs + XSPI_CR_OFFSET, cr); | 129 | xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); |
126 | 130 | ||
127 | /* We do not check spi->max_speed_hz here as the SPI clock | 131 | /* We do not check spi->max_speed_hz here as the SPI clock |
128 | * frequency is not software programmable (the IP block design | 132 | * frequency is not software programmable (the IP block design |
@@ -130,8 +134,8 @@ static void xilinx_spi_chipselect(struct spi_device *spi, int is_on) | |||
130 | */ | 134 | */ |
131 | 135 | ||
132 | /* Activate the chip select */ | 136 | /* Activate the chip select */ |
133 | out_be32(xspi->regs + XSPI_SSR_OFFSET, | 137 | xspi->write_fn(~(0x0001 << spi->chip_select), |
134 | ~(0x0001 << spi->chip_select)); | 138 | xspi->regs + XSPI_SSR_OFFSET); |
135 | } | 139 | } |
136 | } | 140 | } |
137 | 141 | ||
@@ -178,15 +182,15 @@ static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi) | |||
178 | u8 sr; | 182 | u8 sr; |
179 | 183 | ||
180 | /* Fill the Tx FIFO with as many bytes as possible */ | 184 | /* Fill the Tx FIFO with as many bytes as possible */ |
181 | sr = in_8(xspi->regs + XSPI_SR_OFFSET); | 185 | sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); |
182 | while ((sr & XSPI_SR_TX_FULL_MASK) == 0 && xspi->remaining_bytes > 0) { | 186 | while ((sr & XSPI_SR_TX_FULL_MASK) == 0 && xspi->remaining_bytes > 0) { |
183 | if (xspi->tx_ptr) { | 187 | if (xspi->tx_ptr) |
184 | out_8(xspi->regs + XSPI_TXD_OFFSET, *xspi->tx_ptr++); | 188 | xspi->write_fn(*xspi->tx_ptr++, |
185 | } else { | 189 | xspi->regs + XSPI_TXD_OFFSET); |
186 | out_8(xspi->regs + XSPI_TXD_OFFSET, 0); | 190 | else |
187 | } | 191 | xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET); |
188 | xspi->remaining_bytes--; | 192 | xspi->remaining_bytes--; |
189 | sr = in_8(xspi->regs + XSPI_SR_OFFSET); | 193 | sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); |
190 | } | 194 | } |
191 | } | 195 | } |
192 | 196 | ||
@@ -208,18 +212,19 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) | |||
208 | /* Enable the transmit empty interrupt, which we use to determine | 212 | /* Enable the transmit empty interrupt, which we use to determine |
209 | * progress on the transmission. | 213 | * progress on the transmission. |
210 | */ | 214 | */ |
211 | ipif_ier = in_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET); | 215 | ipif_ier = xspi->read_fn(xspi->regs + XIPIF_V123B_IIER_OFFSET); |
212 | out_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET, | 216 | xspi->write_fn(ipif_ier | XSPI_INTR_TX_EMPTY, |
213 | ipif_ier | XSPI_INTR_TX_EMPTY); | 217 | xspi->regs + XIPIF_V123B_IIER_OFFSET); |
214 | 218 | ||
215 | /* Start the transfer by not inhibiting the transmitter any longer */ | 219 | /* Start the transfer by not inhibiting the transmitter any longer */ |
216 | cr = in_be16(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_TRANS_INHIBIT; | 220 | cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) & |
217 | out_be16(xspi->regs + XSPI_CR_OFFSET, cr); | 221 | ~XSPI_CR_TRANS_INHIBIT; |
222 | xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); | ||
218 | 223 | ||
219 | wait_for_completion(&xspi->done); | 224 | wait_for_completion(&xspi->done); |
220 | 225 | ||
221 | /* Disable the transmit empty interrupt */ | 226 | /* Disable the transmit empty interrupt */ |
222 | out_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET, ipif_ier); | 227 | xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET); |
223 | 228 | ||
224 | return t->len - xspi->remaining_bytes; | 229 | return t->len - xspi->remaining_bytes; |
225 | } | 230 | } |
@@ -236,8 +241,8 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) | |||
236 | u32 ipif_isr; | 241 | u32 ipif_isr; |
237 | 242 | ||
238 | /* Get the IPIF interrupts, and clear them immediately */ | 243 | /* Get the IPIF interrupts, and clear them immediately */ |
239 | ipif_isr = in_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET); | 244 | ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET); |
240 | out_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET, ipif_isr); | 245 | xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET); |
241 | 246 | ||
242 | if (ipif_isr & XSPI_INTR_TX_EMPTY) { /* Transmission completed */ | 247 | if (ipif_isr & XSPI_INTR_TX_EMPTY) { /* Transmission completed */ |
243 | u16 cr; | 248 | u16 cr; |
@@ -248,20 +253,20 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) | |||
248 | * transmitter while the Isr refills the transmit register/FIFO, | 253 | * transmitter while the Isr refills the transmit register/FIFO, |
249 | * or make sure it is stopped if we're done. | 254 | * or make sure it is stopped if we're done. |
250 | */ | 255 | */ |
251 | cr = in_be16(xspi->regs + XSPI_CR_OFFSET); | 256 | cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET); |
252 | out_be16(xspi->regs + XSPI_CR_OFFSET, | 257 | xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT, |
253 | cr | XSPI_CR_TRANS_INHIBIT); | 258 | xspi->regs + XSPI_CR_OFFSET); |
254 | 259 | ||
255 | /* Read out all the data from the Rx FIFO */ | 260 | /* Read out all the data from the Rx FIFO */ |
256 | sr = in_8(xspi->regs + XSPI_SR_OFFSET); | 261 | sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); |
257 | while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) { | 262 | while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) { |
258 | u8 data; | 263 | u8 data; |
259 | 264 | ||
260 | data = in_8(xspi->regs + XSPI_RXD_OFFSET); | 265 | data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET); |
261 | if (xspi->rx_ptr) { | 266 | if (xspi->rx_ptr) { |
262 | *xspi->rx_ptr++ = data; | 267 | *xspi->rx_ptr++ = data; |
263 | } | 268 | } |
264 | sr = in_8(xspi->regs + XSPI_SR_OFFSET); | 269 | sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); |
265 | } | 270 | } |
266 | 271 | ||
267 | /* See if there is more data to send */ | 272 | /* See if there is more data to send */ |
@@ -270,7 +275,7 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) | |||
270 | /* Start the transfer by not inhibiting the | 275 | /* Start the transfer by not inhibiting the |
271 | * transmitter any longer | 276 | * transmitter any longer |
272 | */ | 277 | */ |
273 | out_be16(xspi->regs + XSPI_CR_OFFSET, cr); | 278 | xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); |
274 | } else { | 279 | } else { |
275 | /* No more data to send. | 280 | /* No more data to send. |
276 | * Indicate the transfer is completed. | 281 | * Indicate the transfer is completed. |
@@ -325,9 +330,16 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, | |||
325 | 330 | ||
326 | xspi->mem = *mem; | 331 | xspi->mem = *mem; |
327 | xspi->irq = irq; | 332 | xspi->irq = irq; |
333 | if (pdata->little_endian) { | ||
334 | xspi->read_fn = ioread32; | ||
335 | xspi->write_fn = iowrite32; | ||
336 | } else { | ||
337 | xspi->read_fn = ioread32be; | ||
338 | xspi->write_fn = iowrite32be; | ||
339 | } | ||
328 | 340 | ||
329 | /* SPI controller initializations */ | 341 | /* SPI controller initializations */ |
330 | xspi_init_hw(xspi->regs); | 342 | xspi_init_hw(xspi); |
331 | 343 | ||
332 | /* Register for SPI Interrupt */ | 344 | /* Register for SPI Interrupt */ |
333 | ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi); | 345 | ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi); |