diff options
Diffstat (limited to 'drivers/spi/spi-fsl-spi.c')
-rw-r--r-- | drivers/spi/spi-fsl-spi.c | 601 |
1 files changed, 183 insertions, 418 deletions
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 086a9eef2e05..14e202ee7036 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c | |||
@@ -10,6 +10,10 @@ | |||
10 | * Copyright (c) 2009 MontaVista Software, Inc. | 10 | * Copyright (c) 2009 MontaVista Software, Inc. |
11 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> | 11 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> |
12 | * | 12 | * |
13 | * GRLIB support: | ||
14 | * Copyright (c) 2012 Aeroflex Gaisler AB. | ||
15 | * Author: Andreas Larsson <andreas@gaisler.com> | ||
16 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | 17 | * This program is free software; you can redistribute it and/or modify it |
14 | * under the terms of the GNU General Public License as published by the | 18 | * under the terms of the GNU General Public License as published by the |
15 | * Free Software Foundation; either version 2 of the License, or (at your | 19 | * Free Software Foundation; either version 2 of the License, or (at your |
@@ -30,75 +34,54 @@ | |||
30 | #include <linux/mutex.h> | 34 | #include <linux/mutex.h> |
31 | #include <linux/of.h> | 35 | #include <linux/of.h> |
32 | #include <linux/of_platform.h> | 36 | #include <linux/of_platform.h> |
37 | #include <linux/of_address.h> | ||
38 | #include <linux/of_irq.h> | ||
33 | #include <linux/gpio.h> | 39 | #include <linux/gpio.h> |
34 | #include <linux/of_gpio.h> | 40 | #include <linux/of_gpio.h> |
35 | 41 | ||
36 | #include <sysdev/fsl_soc.h> | ||
37 | #include <asm/cpm.h> | ||
38 | #include <asm/qe.h> | ||
39 | |||
40 | #include "spi-fsl-lib.h" | 42 | #include "spi-fsl-lib.h" |
43 | #include "spi-fsl-cpm.h" | ||
44 | #include "spi-fsl-spi.h" | ||
41 | 45 | ||
42 | /* CPM1 and CPM2 are mutually exclusive. */ | 46 | #define TYPE_FSL 0 |
43 | #ifdef CONFIG_CPM1 | 47 | #define TYPE_GRLIB 1 |
44 | #include <asm/cpm1.h> | ||
45 | #define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0) | ||
46 | #else | ||
47 | #include <asm/cpm2.h> | ||
48 | #define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0) | ||
49 | #endif | ||
50 | |||
51 | /* SPI Controller registers */ | ||
52 | struct fsl_spi_reg { | ||
53 | u8 res1[0x20]; | ||
54 | __be32 mode; | ||
55 | __be32 event; | ||
56 | __be32 mask; | ||
57 | __be32 command; | ||
58 | __be32 transmit; | ||
59 | __be32 receive; | ||
60 | }; | ||
61 | |||
62 | /* SPI Controller mode register definitions */ | ||
63 | #define SPMODE_LOOP (1 << 30) | ||
64 | #define SPMODE_CI_INACTIVEHIGH (1 << 29) | ||
65 | #define SPMODE_CP_BEGIN_EDGECLK (1 << 28) | ||
66 | #define SPMODE_DIV16 (1 << 27) | ||
67 | #define SPMODE_REV (1 << 26) | ||
68 | #define SPMODE_MS (1 << 25) | ||
69 | #define SPMODE_ENABLE (1 << 24) | ||
70 | #define SPMODE_LEN(x) ((x) << 20) | ||
71 | #define SPMODE_PM(x) ((x) << 16) | ||
72 | #define SPMODE_OP (1 << 14) | ||
73 | #define SPMODE_CG(x) ((x) << 7) | ||
74 | 48 | ||
75 | /* | 49 | struct fsl_spi_match_data { |
76 | * Default for SPI Mode: | 50 | int type; |
77 | * SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk | 51 | }; |
78 | */ | ||
79 | #define SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \ | ||
80 | SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf)) | ||
81 | |||
82 | /* SPIE register values */ | ||
83 | #define SPIE_NE 0x00000200 /* Not empty */ | ||
84 | #define SPIE_NF 0x00000100 /* Not full */ | ||
85 | 52 | ||
86 | /* SPIM register values */ | 53 | static struct fsl_spi_match_data of_fsl_spi_fsl_config = { |
87 | #define SPIM_NE 0x00000200 /* Not empty */ | 54 | .type = TYPE_FSL, |
88 | #define SPIM_NF 0x00000100 /* Not full */ | 55 | }; |
89 | 56 | ||
90 | #define SPIE_TXB 0x00000200 /* Last char is written to tx fifo */ | 57 | static struct fsl_spi_match_data of_fsl_spi_grlib_config = { |
91 | #define SPIE_RXB 0x00000100 /* Last char is written to rx buf */ | 58 | .type = TYPE_GRLIB, |
59 | }; | ||
92 | 60 | ||
93 | /* SPCOM register values */ | 61 | static struct of_device_id of_fsl_spi_match[] = { |
94 | #define SPCOM_STR (1 << 23) /* Start transmit */ | 62 | { |
63 | .compatible = "fsl,spi", | ||
64 | .data = &of_fsl_spi_fsl_config, | ||
65 | }, | ||
66 | { | ||
67 | .compatible = "aeroflexgaisler,spictrl", | ||
68 | .data = &of_fsl_spi_grlib_config, | ||
69 | }, | ||
70 | {} | ||
71 | }; | ||
72 | MODULE_DEVICE_TABLE(of, of_fsl_spi_match); | ||
95 | 73 | ||
96 | #define SPI_PRAM_SIZE 0x100 | 74 | static int fsl_spi_get_type(struct device *dev) |
97 | #define SPI_MRBLR ((unsigned int)PAGE_SIZE) | 75 | { |
76 | const struct of_device_id *match; | ||
98 | 77 | ||
99 | static void *fsl_dummy_rx; | 78 | if (dev->of_node) { |
100 | static DEFINE_MUTEX(fsl_dummy_rx_lock); | 79 | match = of_match_node(of_fsl_spi_match, dev->of_node); |
101 | static int fsl_dummy_rx_refcnt; | 80 | if (match && match->data) |
81 | return ((struct fsl_spi_match_data *)match->data)->type; | ||
82 | } | ||
83 | return TYPE_FSL; | ||
84 | } | ||
102 | 85 | ||
103 | static void fsl_spi_change_mode(struct spi_device *spi) | 86 | static void fsl_spi_change_mode(struct spi_device *spi) |
104 | { | 87 | { |
@@ -119,18 +102,7 @@ static void fsl_spi_change_mode(struct spi_device *spi) | |||
119 | 102 | ||
120 | /* When in CPM mode, we need to reinit tx and rx. */ | 103 | /* When in CPM mode, we need to reinit tx and rx. */ |
121 | if (mspi->flags & SPI_CPM_MODE) { | 104 | if (mspi->flags & SPI_CPM_MODE) { |
122 | if (mspi->flags & SPI_QE) { | 105 | fsl_spi_cpm_reinit_txrx(mspi); |
123 | qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock, | ||
124 | QE_CR_PROTOCOL_UNSPECIFIED, 0); | ||
125 | } else { | ||
126 | cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX); | ||
127 | if (mspi->flags & SPI_CPM1) { | ||
128 | out_be16(&mspi->pram->rbptr, | ||
129 | in_be16(&mspi->pram->rbase)); | ||
130 | out_be16(&mspi->pram->tbptr, | ||
131 | in_be16(&mspi->pram->tbase)); | ||
132 | } | ||
133 | } | ||
134 | } | 106 | } |
135 | mpc8xxx_spi_write_reg(mode, cs->hw_mode); | 107 | mpc8xxx_spi_write_reg(mode, cs->hw_mode); |
136 | local_irq_restore(flags); | 108 | local_irq_restore(flags); |
@@ -163,6 +135,40 @@ static void fsl_spi_chipselect(struct spi_device *spi, int value) | |||
163 | } | 135 | } |
164 | } | 136 | } |
165 | 137 | ||
138 | static void fsl_spi_qe_cpu_set_shifts(u32 *rx_shift, u32 *tx_shift, | ||
139 | int bits_per_word, int msb_first) | ||
140 | { | ||
141 | *rx_shift = 0; | ||
142 | *tx_shift = 0; | ||
143 | if (msb_first) { | ||
144 | if (bits_per_word <= 8) { | ||
145 | *rx_shift = 16; | ||
146 | *tx_shift = 24; | ||
147 | } else if (bits_per_word <= 16) { | ||
148 | *rx_shift = 16; | ||
149 | *tx_shift = 16; | ||
150 | } | ||
151 | } else { | ||
152 | if (bits_per_word <= 8) | ||
153 | *rx_shift = 8; | ||
154 | } | ||
155 | } | ||
156 | |||
157 | static void fsl_spi_grlib_set_shifts(u32 *rx_shift, u32 *tx_shift, | ||
158 | int bits_per_word, int msb_first) | ||
159 | { | ||
160 | *rx_shift = 0; | ||
161 | *tx_shift = 0; | ||
162 | if (bits_per_word <= 16) { | ||
163 | if (msb_first) { | ||
164 | *rx_shift = 16; /* LSB in bit 16 */ | ||
165 | *tx_shift = 32 - bits_per_word; /* MSB in bit 31 */ | ||
166 | } else { | ||
167 | *rx_shift = 16 - bits_per_word; /* MSB in bit 15 */ | ||
168 | } | ||
169 | } | ||
170 | } | ||
171 | |||
166 | static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs, | 172 | static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs, |
167 | struct spi_device *spi, | 173 | struct spi_device *spi, |
168 | struct mpc8xxx_spi *mpc8xxx_spi, | 174 | struct mpc8xxx_spi *mpc8xxx_spi, |
@@ -173,31 +179,20 @@ static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs, | |||
173 | if (bits_per_word <= 8) { | 179 | if (bits_per_word <= 8) { |
174 | cs->get_rx = mpc8xxx_spi_rx_buf_u8; | 180 | cs->get_rx = mpc8xxx_spi_rx_buf_u8; |
175 | cs->get_tx = mpc8xxx_spi_tx_buf_u8; | 181 | cs->get_tx = mpc8xxx_spi_tx_buf_u8; |
176 | if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { | ||
177 | cs->rx_shift = 16; | ||
178 | cs->tx_shift = 24; | ||
179 | } | ||
180 | } else if (bits_per_word <= 16) { | 182 | } else if (bits_per_word <= 16) { |
181 | cs->get_rx = mpc8xxx_spi_rx_buf_u16; | 183 | cs->get_rx = mpc8xxx_spi_rx_buf_u16; |
182 | cs->get_tx = mpc8xxx_spi_tx_buf_u16; | 184 | cs->get_tx = mpc8xxx_spi_tx_buf_u16; |
183 | if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { | ||
184 | cs->rx_shift = 16; | ||
185 | cs->tx_shift = 16; | ||
186 | } | ||
187 | } else if (bits_per_word <= 32) { | 185 | } else if (bits_per_word <= 32) { |
188 | cs->get_rx = mpc8xxx_spi_rx_buf_u32; | 186 | cs->get_rx = mpc8xxx_spi_rx_buf_u32; |
189 | cs->get_tx = mpc8xxx_spi_tx_buf_u32; | 187 | cs->get_tx = mpc8xxx_spi_tx_buf_u32; |
190 | } else | 188 | } else |
191 | return -EINVAL; | 189 | return -EINVAL; |
192 | 190 | ||
193 | if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE && | 191 | if (mpc8xxx_spi->set_shifts) |
194 | spi->mode & SPI_LSB_FIRST) { | 192 | mpc8xxx_spi->set_shifts(&cs->rx_shift, &cs->tx_shift, |
195 | cs->tx_shift = 0; | 193 | bits_per_word, |
196 | if (bits_per_word <= 8) | 194 | !(spi->mode & SPI_LSB_FIRST)); |
197 | cs->rx_shift = 8; | 195 | |
198 | else | ||
199 | cs->rx_shift = 0; | ||
200 | } | ||
201 | mpc8xxx_spi->rx_shift = cs->rx_shift; | 196 | mpc8xxx_spi->rx_shift = cs->rx_shift; |
202 | mpc8xxx_spi->tx_shift = cs->tx_shift; | 197 | mpc8xxx_spi->tx_shift = cs->tx_shift; |
203 | mpc8xxx_spi->get_rx = cs->get_rx; | 198 | mpc8xxx_spi->get_rx = cs->get_rx; |
@@ -246,7 +241,8 @@ static int fsl_spi_setup_transfer(struct spi_device *spi, | |||
246 | 241 | ||
247 | /* Make sure its a bit width we support [4..16, 32] */ | 242 | /* Make sure its a bit width we support [4..16, 32] */ |
248 | if ((bits_per_word < 4) | 243 | if ((bits_per_word < 4) |
249 | || ((bits_per_word > 16) && (bits_per_word != 32))) | 244 | || ((bits_per_word > 16) && (bits_per_word != 32)) |
245 | || (bits_per_word > mpc8xxx_spi->max_bits_per_word)) | ||
250 | return -EINVAL; | 246 | return -EINVAL; |
251 | 247 | ||
252 | if (!hz) | 248 | if (!hz) |
@@ -295,112 +291,6 @@ static int fsl_spi_setup_transfer(struct spi_device *spi, | |||
295 | return 0; | 291 | return 0; |
296 | } | 292 | } |
297 | 293 | ||
298 | static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi) | ||
299 | { | ||
300 | struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd; | ||
301 | struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd; | ||
302 | unsigned int xfer_len = min(mspi->count, SPI_MRBLR); | ||
303 | unsigned int xfer_ofs; | ||
304 | struct fsl_spi_reg *reg_base = mspi->reg_base; | ||
305 | |||
306 | xfer_ofs = mspi->xfer_in_progress->len - mspi->count; | ||
307 | |||
308 | if (mspi->rx_dma == mspi->dma_dummy_rx) | ||
309 | out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma); | ||
310 | else | ||
311 | out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs); | ||
312 | out_be16(&rx_bd->cbd_datlen, 0); | ||
313 | out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP); | ||
314 | |||
315 | if (mspi->tx_dma == mspi->dma_dummy_tx) | ||
316 | out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma); | ||
317 | else | ||
318 | out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs); | ||
319 | out_be16(&tx_bd->cbd_datlen, xfer_len); | ||
320 | out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP | | ||
321 | BD_SC_LAST); | ||
322 | |||
323 | /* start transfer */ | ||
324 | mpc8xxx_spi_write_reg(®_base->command, SPCOM_STR); | ||
325 | } | ||
326 | |||
327 | static int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi, | ||
328 | struct spi_transfer *t, bool is_dma_mapped) | ||
329 | { | ||
330 | struct device *dev = mspi->dev; | ||
331 | struct fsl_spi_reg *reg_base = mspi->reg_base; | ||
332 | |||
333 | if (is_dma_mapped) { | ||
334 | mspi->map_tx_dma = 0; | ||
335 | mspi->map_rx_dma = 0; | ||
336 | } else { | ||
337 | mspi->map_tx_dma = 1; | ||
338 | mspi->map_rx_dma = 1; | ||
339 | } | ||
340 | |||
341 | if (!t->tx_buf) { | ||
342 | mspi->tx_dma = mspi->dma_dummy_tx; | ||
343 | mspi->map_tx_dma = 0; | ||
344 | } | ||
345 | |||
346 | if (!t->rx_buf) { | ||
347 | mspi->rx_dma = mspi->dma_dummy_rx; | ||
348 | mspi->map_rx_dma = 0; | ||
349 | } | ||
350 | |||
351 | if (mspi->map_tx_dma) { | ||
352 | void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */ | ||
353 | |||
354 | mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len, | ||
355 | DMA_TO_DEVICE); | ||
356 | if (dma_mapping_error(dev, mspi->tx_dma)) { | ||
357 | dev_err(dev, "unable to map tx dma\n"); | ||
358 | return -ENOMEM; | ||
359 | } | ||
360 | } else if (t->tx_buf) { | ||
361 | mspi->tx_dma = t->tx_dma; | ||
362 | } | ||
363 | |||
364 | if (mspi->map_rx_dma) { | ||
365 | mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len, | ||
366 | DMA_FROM_DEVICE); | ||
367 | if (dma_mapping_error(dev, mspi->rx_dma)) { | ||
368 | dev_err(dev, "unable to map rx dma\n"); | ||
369 | goto err_rx_dma; | ||
370 | } | ||
371 | } else if (t->rx_buf) { | ||
372 | mspi->rx_dma = t->rx_dma; | ||
373 | } | ||
374 | |||
375 | /* enable rx ints */ | ||
376 | mpc8xxx_spi_write_reg(®_base->mask, SPIE_RXB); | ||
377 | |||
378 | mspi->xfer_in_progress = t; | ||
379 | mspi->count = t->len; | ||
380 | |||
381 | /* start CPM transfers */ | ||
382 | fsl_spi_cpm_bufs_start(mspi); | ||
383 | |||
384 | return 0; | ||
385 | |||
386 | err_rx_dma: | ||
387 | if (mspi->map_tx_dma) | ||
388 | dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE); | ||
389 | return -ENOMEM; | ||
390 | } | ||
391 | |||
392 | static void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi) | ||
393 | { | ||
394 | struct device *dev = mspi->dev; | ||
395 | struct spi_transfer *t = mspi->xfer_in_progress; | ||
396 | |||
397 | if (mspi->map_tx_dma) | ||
398 | dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE); | ||
399 | if (mspi->map_rx_dma) | ||
400 | dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE); | ||
401 | mspi->xfer_in_progress = NULL; | ||
402 | } | ||
403 | |||
404 | static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi, | 294 | static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi, |
405 | struct spi_transfer *t, unsigned int len) | 295 | struct spi_transfer *t, unsigned int len) |
406 | { | 296 | { |
@@ -565,31 +455,45 @@ static int fsl_spi_setup(struct spi_device *spi) | |||
565 | cs->hw_mode = hw_mode; /* Restore settings */ | 455 | cs->hw_mode = hw_mode; /* Restore settings */ |
566 | return retval; | 456 | return retval; |
567 | } | 457 | } |
568 | return 0; | ||
569 | } | ||
570 | 458 | ||
571 | static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events) | 459 | if (mpc8xxx_spi->type == TYPE_GRLIB) { |
572 | { | 460 | if (gpio_is_valid(spi->cs_gpio)) { |
573 | u16 len; | 461 | int desel; |
574 | struct fsl_spi_reg *reg_base = mspi->reg_base; | ||
575 | 462 | ||
576 | dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__, | 463 | retval = gpio_request(spi->cs_gpio, |
577 | in_be16(&mspi->rx_bd->cbd_datlen), mspi->count); | 464 | dev_name(&spi->dev)); |
465 | if (retval) | ||
466 | return retval; | ||
578 | 467 | ||
579 | len = in_be16(&mspi->rx_bd->cbd_datlen); | 468 | desel = !(spi->mode & SPI_CS_HIGH); |
580 | if (len > mspi->count) { | 469 | retval = gpio_direction_output(spi->cs_gpio, desel); |
581 | WARN_ON(1); | 470 | if (retval) { |
582 | len = mspi->count; | 471 | gpio_free(spi->cs_gpio); |
472 | return retval; | ||
473 | } | ||
474 | } else if (spi->cs_gpio != -ENOENT) { | ||
475 | if (spi->cs_gpio < 0) | ||
476 | return spi->cs_gpio; | ||
477 | return -EINVAL; | ||
478 | } | ||
479 | /* When spi->cs_gpio == -ENOENT, a hole in the phandle list | ||
480 | * indicates to use native chipselect if present, or allow for | ||
481 | * an always selected chip | ||
482 | */ | ||
583 | } | 483 | } |
584 | 484 | ||
585 | /* Clear the events */ | 485 | /* Initialize chipselect - might be active for SPI_CS_HIGH mode */ |
586 | mpc8xxx_spi_write_reg(®_base->event, events); | 486 | fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE); |
587 | 487 | ||
588 | mspi->count -= len; | 488 | return 0; |
589 | if (mspi->count) | 489 | } |
590 | fsl_spi_cpm_bufs_start(mspi); | 490 | |
591 | else | 491 | static void fsl_spi_cleanup(struct spi_device *spi) |
592 | complete(&mspi->done); | 492 | { |
493 | struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); | ||
494 | |||
495 | if (mpc8xxx_spi->type == TYPE_GRLIB && gpio_is_valid(spi->cs_gpio)) | ||
496 | gpio_free(spi->cs_gpio); | ||
593 | } | 497 | } |
594 | 498 | ||
595 | static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) | 499 | static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) |
@@ -646,201 +550,51 @@ static irqreturn_t fsl_spi_irq(s32 irq, void *context_data) | |||
646 | return ret; | 550 | return ret; |
647 | } | 551 | } |
648 | 552 | ||
649 | static void *fsl_spi_alloc_dummy_rx(void) | 553 | static void fsl_spi_remove(struct mpc8xxx_spi *mspi) |
650 | { | ||
651 | mutex_lock(&fsl_dummy_rx_lock); | ||
652 | |||
653 | if (!fsl_dummy_rx) | ||
654 | fsl_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL); | ||
655 | if (fsl_dummy_rx) | ||
656 | fsl_dummy_rx_refcnt++; | ||
657 | |||
658 | mutex_unlock(&fsl_dummy_rx_lock); | ||
659 | |||
660 | return fsl_dummy_rx; | ||
661 | } | ||
662 | |||
663 | static void fsl_spi_free_dummy_rx(void) | ||
664 | { | 554 | { |
665 | mutex_lock(&fsl_dummy_rx_lock); | 555 | iounmap(mspi->reg_base); |
666 | 556 | fsl_spi_cpm_free(mspi); | |
667 | switch (fsl_dummy_rx_refcnt) { | ||
668 | case 0: | ||
669 | WARN_ON(1); | ||
670 | break; | ||
671 | case 1: | ||
672 | kfree(fsl_dummy_rx); | ||
673 | fsl_dummy_rx = NULL; | ||
674 | /* fall through */ | ||
675 | default: | ||
676 | fsl_dummy_rx_refcnt--; | ||
677 | break; | ||
678 | } | ||
679 | |||
680 | mutex_unlock(&fsl_dummy_rx_lock); | ||
681 | } | 557 | } |
682 | 558 | ||
683 | static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi) | 559 | static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on) |
684 | { | 560 | { |
685 | struct device *dev = mspi->dev; | 561 | struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); |
686 | struct device_node *np = dev->of_node; | 562 | struct fsl_spi_reg *reg_base = mpc8xxx_spi->reg_base; |
687 | const u32 *iprop; | 563 | u32 slvsel; |
688 | int size; | 564 | u16 cs = spi->chip_select; |
689 | void __iomem *spi_base; | ||
690 | unsigned long pram_ofs = -ENOMEM; | ||
691 | |||
692 | /* Can't use of_address_to_resource(), QE muram isn't at 0. */ | ||
693 | iprop = of_get_property(np, "reg", &size); | ||
694 | |||
695 | /* QE with a fixed pram location? */ | ||
696 | if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4) | ||
697 | return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE); | ||
698 | |||
699 | /* QE but with a dynamic pram location? */ | ||
700 | if (mspi->flags & SPI_QE) { | ||
701 | pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64); | ||
702 | qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock, | ||
703 | QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs); | ||
704 | return pram_ofs; | ||
705 | } | ||
706 | |||
707 | spi_base = of_iomap(np, 1); | ||
708 | if (spi_base == NULL) | ||
709 | return -EINVAL; | ||
710 | 565 | ||
711 | if (mspi->flags & SPI_CPM2) { | 566 | if (gpio_is_valid(spi->cs_gpio)) { |
712 | pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64); | 567 | gpio_set_value(spi->cs_gpio, on); |
713 | out_be16(spi_base, pram_ofs); | 568 | } else if (cs < mpc8xxx_spi->native_chipselects) { |
714 | } else { | 569 | slvsel = mpc8xxx_spi_read_reg(®_base->slvsel); |
715 | struct spi_pram __iomem *pram = spi_base; | 570 | slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs)); |
716 | u16 rpbase = in_be16(&pram->rpbase); | 571 | mpc8xxx_spi_write_reg(®_base->slvsel, slvsel); |
717 | |||
718 | /* Microcode relocation patch applied? */ | ||
719 | if (rpbase) | ||
720 | pram_ofs = rpbase; | ||
721 | else { | ||
722 | pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64); | ||
723 | out_be16(spi_base, pram_ofs); | ||
724 | } | ||
725 | } | 572 | } |
726 | |||
727 | iounmap(spi_base); | ||
728 | return pram_ofs; | ||
729 | } | 573 | } |
730 | 574 | ||
731 | static int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi) | 575 | static void fsl_spi_grlib_probe(struct device *dev) |
732 | { | 576 | { |
733 | struct device *dev = mspi->dev; | 577 | struct fsl_spi_platform_data *pdata = dev->platform_data; |
734 | struct device_node *np = dev->of_node; | 578 | struct spi_master *master = dev_get_drvdata(dev); |
735 | const u32 *iprop; | 579 | struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); |
736 | int size; | 580 | struct fsl_spi_reg *reg_base = mpc8xxx_spi->reg_base; |
737 | unsigned long pram_ofs; | 581 | int mbits; |
738 | unsigned long bds_ofs; | 582 | u32 capabilities; |
739 | |||
740 | if (!(mspi->flags & SPI_CPM_MODE)) | ||
741 | return 0; | ||
742 | |||
743 | if (!fsl_spi_alloc_dummy_rx()) | ||
744 | return -ENOMEM; | ||
745 | |||
746 | if (mspi->flags & SPI_QE) { | ||
747 | iprop = of_get_property(np, "cell-index", &size); | ||
748 | if (iprop && size == sizeof(*iprop)) | ||
749 | mspi->subblock = *iprop; | ||
750 | |||
751 | switch (mspi->subblock) { | ||
752 | default: | ||
753 | dev_warn(dev, "cell-index unspecified, assuming SPI1"); | ||
754 | /* fall through */ | ||
755 | case 0: | ||
756 | mspi->subblock = QE_CR_SUBBLOCK_SPI1; | ||
757 | break; | ||
758 | case 1: | ||
759 | mspi->subblock = QE_CR_SUBBLOCK_SPI2; | ||
760 | break; | ||
761 | } | ||
762 | } | ||
763 | |||
764 | pram_ofs = fsl_spi_cpm_get_pram(mspi); | ||
765 | if (IS_ERR_VALUE(pram_ofs)) { | ||
766 | dev_err(dev, "can't allocate spi parameter ram\n"); | ||
767 | goto err_pram; | ||
768 | } | ||
769 | 583 | ||
770 | bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) + | 584 | capabilities = mpc8xxx_spi_read_reg(®_base->cap); |
771 | sizeof(*mspi->rx_bd), 8); | ||
772 | if (IS_ERR_VALUE(bds_ofs)) { | ||
773 | dev_err(dev, "can't allocate bds\n"); | ||
774 | goto err_bds; | ||
775 | } | ||
776 | 585 | ||
777 | mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE, | 586 | mpc8xxx_spi->set_shifts = fsl_spi_grlib_set_shifts; |
778 | DMA_TO_DEVICE); | 587 | mbits = SPCAP_MAXWLEN(capabilities); |
779 | if (dma_mapping_error(dev, mspi->dma_dummy_tx)) { | 588 | if (mbits) |
780 | dev_err(dev, "unable to map dummy tx buffer\n"); | 589 | mpc8xxx_spi->max_bits_per_word = mbits + 1; |
781 | goto err_dummy_tx; | ||
782 | } | ||
783 | 590 | ||
784 | mspi->dma_dummy_rx = dma_map_single(dev, fsl_dummy_rx, SPI_MRBLR, | 591 | mpc8xxx_spi->native_chipselects = 0; |
785 | DMA_FROM_DEVICE); | 592 | if (SPCAP_SSEN(capabilities)) { |
786 | if (dma_mapping_error(dev, mspi->dma_dummy_rx)) { | 593 | mpc8xxx_spi->native_chipselects = SPCAP_SSSZ(capabilities); |
787 | dev_err(dev, "unable to map dummy rx buffer\n"); | 594 | mpc8xxx_spi_write_reg(®_base->slvsel, 0xffffffff); |
788 | goto err_dummy_rx; | ||
789 | } | 595 | } |
790 | 596 | master->num_chipselect = mpc8xxx_spi->native_chipselects; | |
791 | mspi->pram = cpm_muram_addr(pram_ofs); | 597 | pdata->cs_control = fsl_spi_grlib_cs_control; |
792 | |||
793 | mspi->tx_bd = cpm_muram_addr(bds_ofs); | ||
794 | mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd)); | ||
795 | |||
796 | /* Initialize parameter ram. */ | ||
797 | out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd)); | ||
798 | out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd)); | ||
799 | out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL); | ||
800 | out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL); | ||
801 | out_be16(&mspi->pram->mrblr, SPI_MRBLR); | ||
802 | out_be32(&mspi->pram->rstate, 0); | ||
803 | out_be32(&mspi->pram->rdp, 0); | ||
804 | out_be16(&mspi->pram->rbptr, 0); | ||
805 | out_be16(&mspi->pram->rbc, 0); | ||
806 | out_be32(&mspi->pram->rxtmp, 0); | ||
807 | out_be32(&mspi->pram->tstate, 0); | ||
808 | out_be32(&mspi->pram->tdp, 0); | ||
809 | out_be16(&mspi->pram->tbptr, 0); | ||
810 | out_be16(&mspi->pram->tbc, 0); | ||
811 | out_be32(&mspi->pram->txtmp, 0); | ||
812 | |||
813 | return 0; | ||
814 | |||
815 | err_dummy_rx: | ||
816 | dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE); | ||
817 | err_dummy_tx: | ||
818 | cpm_muram_free(bds_ofs); | ||
819 | err_bds: | ||
820 | cpm_muram_free(pram_ofs); | ||
821 | err_pram: | ||
822 | fsl_spi_free_dummy_rx(); | ||
823 | return -ENOMEM; | ||
824 | } | ||
825 | |||
826 | static void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi) | ||
827 | { | ||
828 | struct device *dev = mspi->dev; | ||
829 | |||
830 | if (!(mspi->flags & SPI_CPM_MODE)) | ||
831 | return; | ||
832 | |||
833 | dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE); | ||
834 | dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE); | ||
835 | cpm_muram_free(cpm_muram_offset(mspi->tx_bd)); | ||
836 | cpm_muram_free(cpm_muram_offset(mspi->pram)); | ||
837 | fsl_spi_free_dummy_rx(); | ||
838 | } | ||
839 | |||
840 | static void fsl_spi_remove(struct mpc8xxx_spi *mspi) | ||
841 | { | ||
842 | iounmap(mspi->reg_base); | ||
843 | fsl_spi_cpm_free(mspi); | ||
844 | } | 598 | } |
845 | 599 | ||
846 | static struct spi_master * fsl_spi_probe(struct device *dev, | 600 | static struct spi_master * fsl_spi_probe(struct device *dev, |
@@ -866,27 +620,35 @@ static struct spi_master * fsl_spi_probe(struct device *dev, | |||
866 | goto err_probe; | 620 | goto err_probe; |
867 | 621 | ||
868 | master->setup = fsl_spi_setup; | 622 | master->setup = fsl_spi_setup; |
623 | master->cleanup = fsl_spi_cleanup; | ||
869 | 624 | ||
870 | mpc8xxx_spi = spi_master_get_devdata(master); | 625 | mpc8xxx_spi = spi_master_get_devdata(master); |
871 | mpc8xxx_spi->spi_do_one_msg = fsl_spi_do_one_msg; | 626 | mpc8xxx_spi->spi_do_one_msg = fsl_spi_do_one_msg; |
872 | mpc8xxx_spi->spi_remove = fsl_spi_remove; | 627 | mpc8xxx_spi->spi_remove = fsl_spi_remove; |
873 | 628 | mpc8xxx_spi->max_bits_per_word = 32; | |
629 | mpc8xxx_spi->type = fsl_spi_get_type(dev); | ||
874 | 630 | ||
875 | ret = fsl_spi_cpm_init(mpc8xxx_spi); | 631 | ret = fsl_spi_cpm_init(mpc8xxx_spi); |
876 | if (ret) | 632 | if (ret) |
877 | goto err_cpm_init; | 633 | goto err_cpm_init; |
878 | 634 | ||
879 | if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { | ||
880 | mpc8xxx_spi->rx_shift = 16; | ||
881 | mpc8xxx_spi->tx_shift = 24; | ||
882 | } | ||
883 | |||
884 | mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem)); | 635 | mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem)); |
885 | if (mpc8xxx_spi->reg_base == NULL) { | 636 | if (mpc8xxx_spi->reg_base == NULL) { |
886 | ret = -ENOMEM; | 637 | ret = -ENOMEM; |
887 | goto err_ioremap; | 638 | goto err_ioremap; |
888 | } | 639 | } |
889 | 640 | ||
641 | if (mpc8xxx_spi->type == TYPE_GRLIB) | ||
642 | fsl_spi_grlib_probe(dev); | ||
643 | |||
644 | if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) | ||
645 | mpc8xxx_spi->set_shifts = fsl_spi_qe_cpu_set_shifts; | ||
646 | |||
647 | if (mpc8xxx_spi->set_shifts) | ||
648 | /* 8 bits per word and MSB first */ | ||
649 | mpc8xxx_spi->set_shifts(&mpc8xxx_spi->rx_shift, | ||
650 | &mpc8xxx_spi->tx_shift, 8, 1); | ||
651 | |||
890 | /* Register for SPI Interrupt */ | 652 | /* Register for SPI Interrupt */ |
891 | ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq, | 653 | ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq, |
892 | 0, "fsl_spi", mpc8xxx_spi); | 654 | 0, "fsl_spi", mpc8xxx_spi); |
@@ -904,6 +666,10 @@ static struct spi_master * fsl_spi_probe(struct device *dev, | |||
904 | 666 | ||
905 | /* Enable SPI interface */ | 667 | /* Enable SPI interface */ |
906 | regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE; | 668 | regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE; |
669 | if (mpc8xxx_spi->max_bits_per_word < 8) { | ||
670 | regval &= ~SPMODE_LEN(0xF); | ||
671 | regval |= SPMODE_LEN(mpc8xxx_spi->max_bits_per_word - 1); | ||
672 | } | ||
907 | if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) | 673 | if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) |
908 | regval |= SPMODE_OP; | 674 | regval |= SPMODE_OP; |
909 | 675 | ||
@@ -1047,28 +813,31 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) | |||
1047 | struct device_node *np = ofdev->dev.of_node; | 813 | struct device_node *np = ofdev->dev.of_node; |
1048 | struct spi_master *master; | 814 | struct spi_master *master; |
1049 | struct resource mem; | 815 | struct resource mem; |
1050 | struct resource irq; | 816 | int irq, type; |
1051 | int ret = -ENOMEM; | 817 | int ret = -ENOMEM; |
1052 | 818 | ||
1053 | ret = of_mpc8xxx_spi_probe(ofdev); | 819 | ret = of_mpc8xxx_spi_probe(ofdev); |
1054 | if (ret) | 820 | if (ret) |
1055 | return ret; | 821 | return ret; |
1056 | 822 | ||
1057 | ret = of_fsl_spi_get_chipselects(dev); | 823 | type = fsl_spi_get_type(&ofdev->dev); |
1058 | if (ret) | 824 | if (type == TYPE_FSL) { |
1059 | goto err; | 825 | ret = of_fsl_spi_get_chipselects(dev); |
826 | if (ret) | ||
827 | goto err; | ||
828 | } | ||
1060 | 829 | ||
1061 | ret = of_address_to_resource(np, 0, &mem); | 830 | ret = of_address_to_resource(np, 0, &mem); |
1062 | if (ret) | 831 | if (ret) |
1063 | goto err; | 832 | goto err; |
1064 | 833 | ||
1065 | ret = of_irq_to_resource(np, 0, &irq); | 834 | irq = irq_of_parse_and_map(np, 0); |
1066 | if (!ret) { | 835 | if (!irq) { |
1067 | ret = -EINVAL; | 836 | ret = -EINVAL; |
1068 | goto err; | 837 | goto err; |
1069 | } | 838 | } |
1070 | 839 | ||
1071 | master = fsl_spi_probe(dev, &mem, irq.start); | 840 | master = fsl_spi_probe(dev, &mem, irq); |
1072 | if (IS_ERR(master)) { | 841 | if (IS_ERR(master)) { |
1073 | ret = PTR_ERR(master); | 842 | ret = PTR_ERR(master); |
1074 | goto err; | 843 | goto err; |
@@ -1077,27 +846,25 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) | |||
1077 | return 0; | 846 | return 0; |
1078 | 847 | ||
1079 | err: | 848 | err: |
1080 | of_fsl_spi_free_chipselects(dev); | 849 | if (type == TYPE_FSL) |
850 | of_fsl_spi_free_chipselects(dev); | ||
1081 | return ret; | 851 | return ret; |
1082 | } | 852 | } |
1083 | 853 | ||
1084 | static int of_fsl_spi_remove(struct platform_device *ofdev) | 854 | static int of_fsl_spi_remove(struct platform_device *ofdev) |
1085 | { | 855 | { |
856 | struct spi_master *master = dev_get_drvdata(&ofdev->dev); | ||
857 | struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); | ||
1086 | int ret; | 858 | int ret; |
1087 | 859 | ||
1088 | ret = mpc8xxx_spi_remove(&ofdev->dev); | 860 | ret = mpc8xxx_spi_remove(&ofdev->dev); |
1089 | if (ret) | 861 | if (ret) |
1090 | return ret; | 862 | return ret; |
1091 | of_fsl_spi_free_chipselects(&ofdev->dev); | 863 | if (mpc8xxx_spi->type == TYPE_FSL) |
864 | of_fsl_spi_free_chipselects(&ofdev->dev); | ||
1092 | return 0; | 865 | return 0; |
1093 | } | 866 | } |
1094 | 867 | ||
1095 | static const struct of_device_id of_fsl_spi_match[] = { | ||
1096 | { .compatible = "fsl,spi" }, | ||
1097 | {} | ||
1098 | }; | ||
1099 | MODULE_DEVICE_TABLE(of, of_fsl_spi_match); | ||
1100 | |||
1101 | static struct platform_driver of_fsl_spi_driver = { | 868 | static struct platform_driver of_fsl_spi_driver = { |
1102 | .driver = { | 869 | .driver = { |
1103 | .name = "fsl_spi", | 870 | .name = "fsl_spi", |
@@ -1134,9 +901,7 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev) | |||
1134 | return -EINVAL; | 901 | return -EINVAL; |
1135 | 902 | ||
1136 | master = fsl_spi_probe(&pdev->dev, mem, irq); | 903 | master = fsl_spi_probe(&pdev->dev, mem, irq); |
1137 | if (IS_ERR(master)) | 904 | return PTR_RET(master); |
1138 | return PTR_ERR(master); | ||
1139 | return 0; | ||
1140 | } | 905 | } |
1141 | 906 | ||
1142 | static int plat_mpc8xxx_spi_remove(struct platform_device *pdev) | 907 | static int plat_mpc8xxx_spi_remove(struct platform_device *pdev) |