diff options
-rw-r--r-- | Documentation/devicetree/bindings/regmap/regmap.txt | 47 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt | 5 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt | 7 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/spi/spi-orion.txt | 2 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-i2c.c | 2 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-spi.c | 2 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 74 | ||||
-rw-r--r-- | drivers/spi/spi-fsl-dspi.c | 4 | ||||
-rw-r--r-- | drivers/spi/spi-imx.c | 286 | ||||
-rw-r--r-- | drivers/spi/spi-mxs.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi-omap-100k.c | 4 | ||||
-rw-r--r-- | drivers/spi/spi-orion.c | 116 |
12 files changed, 501 insertions, 50 deletions
diff --git a/Documentation/devicetree/bindings/regmap/regmap.txt b/Documentation/devicetree/bindings/regmap/regmap.txt new file mode 100644 index 000000000000..b494f8b8ef72 --- /dev/null +++ b/Documentation/devicetree/bindings/regmap/regmap.txt | |||
@@ -0,0 +1,47 @@ | |||
1 | Device-Tree binding for regmap | ||
2 | |||
3 | The endianness mode of CPU & Device scenarios: | ||
4 | Index Device Endianness properties | ||
5 | --------------------------------------------------- | ||
6 | 1 BE 'big-endian' | ||
7 | 2 LE 'little-endian' | ||
8 | |||
9 | For one device driver, which will run in different scenarios above | ||
10 | on different SoCs using the devicetree, we need one way to simplify | ||
11 | this. | ||
12 | |||
13 | Required properties: | ||
14 | - {big,little}-endian: these are boolean properties, if absent | ||
15 | meaning that the CPU and the Device are in the same endianness mode, | ||
16 | these properties are for register values and all the buffers only. | ||
17 | |||
18 | Examples: | ||
19 | Scenario 1 : CPU in LE mode & device in LE mode. | ||
20 | dev: dev@40031000 { | ||
21 | compatible = "name"; | ||
22 | reg = <0x40031000 0x1000>; | ||
23 | ... | ||
24 | }; | ||
25 | |||
26 | Scenario 2 : CPU in LE mode & device in BE mode. | ||
27 | dev: dev@40031000 { | ||
28 | compatible = "name"; | ||
29 | reg = <0x40031000 0x1000>; | ||
30 | ... | ||
31 | big-endian; | ||
32 | }; | ||
33 | |||
34 | Scenario 3 : CPU in BE mode & device in BE mode. | ||
35 | dev: dev@40031000 { | ||
36 | compatible = "name"; | ||
37 | reg = <0x40031000 0x1000>; | ||
38 | ... | ||
39 | }; | ||
40 | |||
41 | Scenario 4 : CPU in BE mode & device in LE mode. | ||
42 | dev: dev@40031000 { | ||
43 | compatible = "name"; | ||
44 | reg = <0x40031000 0x1000>; | ||
45 | ... | ||
46 | little-endian; | ||
47 | }; | ||
diff --git a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt index 4256a6df9b79..aad527b357a0 100644 --- a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt +++ b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt | |||
@@ -7,6 +7,9 @@ Required properties: | |||
7 | - interrupts : Should contain CSPI/eCSPI interrupt | 7 | - interrupts : Should contain CSPI/eCSPI interrupt |
8 | - fsl,spi-num-chipselects : Contains the number of the chipselect | 8 | - fsl,spi-num-chipselects : Contains the number of the chipselect |
9 | - cs-gpios : Specifies the gpio pins to be used for chipselects. | 9 | - cs-gpios : Specifies the gpio pins to be used for chipselects. |
10 | - dmas: DMA specifiers for tx and rx dma. See the DMA client binding, | ||
11 | Documentation/devicetree/bindings/dma/dma.txt | ||
12 | - dma-names: DMA request names should include "tx" and "rx" if present. | ||
10 | 13 | ||
11 | Example: | 14 | Example: |
12 | 15 | ||
@@ -19,4 +22,6 @@ ecspi@70010000 { | |||
19 | fsl,spi-num-chipselects = <2>; | 22 | fsl,spi-num-chipselects = <2>; |
20 | cs-gpios = <&gpio3 24 0>, /* GPIO3_24 */ | 23 | cs-gpios = <&gpio3 24 0>, /* GPIO3_24 */ |
21 | <&gpio3 25 0>; /* GPIO3_25 */ | 24 | <&gpio3 25 0>; /* GPIO3_25 */ |
25 | dmas = <&sdma 3 7 1>, <&sdma 4 7 2>; | ||
26 | dma-names = "rx", "tx"; | ||
22 | }; | 27 | }; |
diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt index 5376de40f10b..cbbe16ed3874 100644 --- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt +++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt | |||
@@ -10,7 +10,12 @@ Required properties: | |||
10 | - pinctrl-names: must contain a "default" entry. | 10 | - pinctrl-names: must contain a "default" entry. |
11 | - spi-num-chipselects : the number of the chipselect signals. | 11 | - spi-num-chipselects : the number of the chipselect signals. |
12 | - bus-num : the slave chip chipselect signal number. | 12 | - bus-num : the slave chip chipselect signal number. |
13 | - big-endian : if DSPI modudle is big endian, the bool will be set in node. | 13 | |
14 | Optional property: | ||
15 | - big-endian: If present the dspi device's registers are implemented | ||
16 | in big endian mode, otherwise in native mode(same with CPU), for more | ||
17 | detail please see: Documentation/devicetree/bindings/regmap/regmap.txt. | ||
18 | |||
14 | Example: | 19 | Example: |
15 | 20 | ||
16 | dspi0@4002c000 { | 21 | dspi0@4002c000 { |
diff --git a/Documentation/devicetree/bindings/spi/spi-orion.txt b/Documentation/devicetree/bindings/spi/spi-orion.txt index a3ff50fc76fb..50c3a3de61c1 100644 --- a/Documentation/devicetree/bindings/spi/spi-orion.txt +++ b/Documentation/devicetree/bindings/spi/spi-orion.txt | |||
@@ -1,7 +1,7 @@ | |||
1 | Marvell Orion SPI device | 1 | Marvell Orion SPI device |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible : should be "marvell,orion-spi". | 4 | - compatible : should be "marvell,orion-spi" or "marvell,armada-370-spi". |
5 | - reg : offset and length of the register set for the device | 5 | - reg : offset and length of the register set for the device |
6 | - cell-index : Which of multiple SPI controllers is this. | 6 | - cell-index : Which of multiple SPI controllers is this. |
7 | Optional properties: | 7 | Optional properties: |
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c index ca193d1ef47c..053150a7f9f2 100644 --- a/drivers/base/regmap/regmap-i2c.c +++ b/drivers/base/regmap/regmap-i2c.c | |||
@@ -168,6 +168,8 @@ static struct regmap_bus regmap_i2c = { | |||
168 | .write = regmap_i2c_write, | 168 | .write = regmap_i2c_write, |
169 | .gather_write = regmap_i2c_gather_write, | 169 | .gather_write = regmap_i2c_gather_write, |
170 | .read = regmap_i2c_read, | 170 | .read = regmap_i2c_read, |
171 | .reg_format_endian_default = REGMAP_ENDIAN_BIG, | ||
172 | .val_format_endian_default = REGMAP_ENDIAN_BIG, | ||
171 | }; | 173 | }; |
172 | 174 | ||
173 | static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c, | 175 | static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c, |
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c index 0eb3097c0d76..53d1148e80a0 100644 --- a/drivers/base/regmap/regmap-spi.c +++ b/drivers/base/regmap/regmap-spi.c | |||
@@ -109,6 +109,8 @@ static struct regmap_bus regmap_spi = { | |||
109 | .async_alloc = regmap_spi_async_alloc, | 109 | .async_alloc = regmap_spi_async_alloc, |
110 | .read = regmap_spi_read, | 110 | .read = regmap_spi_read, |
111 | .read_flag_mask = 0x80, | 111 | .read_flag_mask = 0x80, |
112 | .reg_format_endian_default = REGMAP_ENDIAN_BIG, | ||
113 | .val_format_endian_default = REGMAP_ENDIAN_BIG, | ||
112 | }; | 114 | }; |
113 | 115 | ||
114 | /** | 116 | /** |
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 1cf427bc0d4a..f2281af24ec6 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/export.h> | 15 | #include <linux/export.h> |
16 | #include <linux/mutex.h> | 16 | #include <linux/mutex.h> |
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <linux/of.h> | ||
18 | #include <linux/rbtree.h> | 19 | #include <linux/rbtree.h> |
19 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
20 | 21 | ||
@@ -448,6 +449,66 @@ int regmap_attach_dev(struct device *dev, struct regmap *map, | |||
448 | } | 449 | } |
449 | EXPORT_SYMBOL_GPL(regmap_attach_dev); | 450 | EXPORT_SYMBOL_GPL(regmap_attach_dev); |
450 | 451 | ||
452 | static enum regmap_endian regmap_get_reg_endian(const struct regmap_bus *bus, | ||
453 | const struct regmap_config *config) | ||
454 | { | ||
455 | enum regmap_endian endian; | ||
456 | |||
457 | /* Retrieve the endianness specification from the regmap config */ | ||
458 | endian = config->reg_format_endian; | ||
459 | |||
460 | /* If the regmap config specified a non-default value, use that */ | ||
461 | if (endian != REGMAP_ENDIAN_DEFAULT) | ||
462 | return endian; | ||
463 | |||
464 | /* Retrieve the endianness specification from the bus config */ | ||
465 | if (bus && bus->reg_format_endian_default) | ||
466 | endian = bus->reg_format_endian_default; | ||
467 | |||
468 | /* If the bus specified a non-default value, use that */ | ||
469 | if (endian != REGMAP_ENDIAN_DEFAULT) | ||
470 | return endian; | ||
471 | |||
472 | /* Use this if no other value was found */ | ||
473 | return REGMAP_ENDIAN_BIG; | ||
474 | } | ||
475 | |||
476 | static enum regmap_endian regmap_get_val_endian(struct device *dev, | ||
477 | const struct regmap_bus *bus, | ||
478 | const struct regmap_config *config) | ||
479 | { | ||
480 | struct device_node *np = dev->of_node; | ||
481 | enum regmap_endian endian; | ||
482 | |||
483 | /* Retrieve the endianness specification from the regmap config */ | ||
484 | endian = config->val_format_endian; | ||
485 | |||
486 | /* If the regmap config specified a non-default value, use that */ | ||
487 | if (endian != REGMAP_ENDIAN_DEFAULT) | ||
488 | return endian; | ||
489 | |||
490 | /* Parse the device's DT node for an endianness specification */ | ||
491 | if (of_property_read_bool(np, "big-endian")) | ||
492 | endian = REGMAP_ENDIAN_BIG; | ||
493 | else if (of_property_read_bool(np, "little-endian")) | ||
494 | endian = REGMAP_ENDIAN_LITTLE; | ||
495 | |||
496 | /* If the endianness was specified in DT, use that */ | ||
497 | if (endian != REGMAP_ENDIAN_DEFAULT) | ||
498 | return endian; | ||
499 | |||
500 | /* Retrieve the endianness specification from the bus config */ | ||
501 | if (bus && bus->val_format_endian_default) | ||
502 | endian = bus->val_format_endian_default; | ||
503 | |||
504 | /* If the bus specified a non-default value, use that */ | ||
505 | if (endian != REGMAP_ENDIAN_DEFAULT) | ||
506 | return endian; | ||
507 | |||
508 | /* Use this if no other value was found */ | ||
509 | return REGMAP_ENDIAN_BIG; | ||
510 | } | ||
511 | |||
451 | /** | 512 | /** |
452 | * regmap_init(): Initialise register map | 513 | * regmap_init(): Initialise register map |
453 | * | 514 | * |
@@ -551,17 +612,8 @@ struct regmap *regmap_init(struct device *dev, | |||
551 | map->reg_read = _regmap_bus_read; | 612 | map->reg_read = _regmap_bus_read; |
552 | } | 613 | } |
553 | 614 | ||
554 | reg_endian = config->reg_format_endian; | 615 | reg_endian = regmap_get_reg_endian(bus, config); |
555 | if (reg_endian == REGMAP_ENDIAN_DEFAULT) | 616 | val_endian = regmap_get_val_endian(dev, bus, config); |
556 | reg_endian = bus->reg_format_endian_default; | ||
557 | if (reg_endian == REGMAP_ENDIAN_DEFAULT) | ||
558 | reg_endian = REGMAP_ENDIAN_BIG; | ||
559 | |||
560 | val_endian = config->val_format_endian; | ||
561 | if (val_endian == REGMAP_ENDIAN_DEFAULT) | ||
562 | val_endian = bus->val_format_endian_default; | ||
563 | if (val_endian == REGMAP_ENDIAN_DEFAULT) | ||
564 | val_endian = REGMAP_ENDIAN_BIG; | ||
565 | 617 | ||
566 | switch (config->reg_bits + map->reg_shift) { | 618 | switch (config->reg_bits + map->reg_shift) { |
567 | case 2: | 619 | case 2: |
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 63c3859d24cf..448216025ce8 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c | |||
@@ -493,9 +493,6 @@ static int dspi_probe(struct platform_device *pdev) | |||
493 | } | 493 | } |
494 | 494 | ||
495 | dspi_regmap_config.lock_arg = dspi; | 495 | dspi_regmap_config.lock_arg = dspi; |
496 | dspi_regmap_config.val_format_endian = | ||
497 | of_property_read_bool(np, "big-endian") | ||
498 | ? REGMAP_ENDIAN_BIG : REGMAP_ENDIAN_DEFAULT; | ||
499 | dspi->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "dspi", base, | 496 | dspi->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "dspi", base, |
500 | &dspi_regmap_config); | 497 | &dspi_regmap_config); |
501 | if (IS_ERR(dspi->regmap)) { | 498 | if (IS_ERR(dspi->regmap)) { |
@@ -535,7 +532,6 @@ static int dspi_probe(struct platform_device *pdev) | |||
535 | goto out_clk_put; | 532 | goto out_clk_put; |
536 | } | 533 | } |
537 | 534 | ||
538 | pr_info(KERN_INFO "Freescale DSPI master initialized\n"); | ||
539 | return ret; | 535 | return ret; |
540 | 536 | ||
541 | out_clk_put: | 537 | out_clk_put: |
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 5daff2054ae4..3637847b5370 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/clk.h> | 21 | #include <linux/clk.h> |
22 | #include <linux/completion.h> | 22 | #include <linux/completion.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/dmaengine.h> | ||
25 | #include <linux/dma-mapping.h> | ||
24 | #include <linux/err.h> | 26 | #include <linux/err.h> |
25 | #include <linux/gpio.h> | 27 | #include <linux/gpio.h> |
26 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
@@ -37,6 +39,7 @@ | |||
37 | #include <linux/of_device.h> | 39 | #include <linux/of_device.h> |
38 | #include <linux/of_gpio.h> | 40 | #include <linux/of_gpio.h> |
39 | 41 | ||
42 | #include <linux/platform_data/dma-imx.h> | ||
40 | #include <linux/platform_data/spi-imx.h> | 43 | #include <linux/platform_data/spi-imx.h> |
41 | 44 | ||
42 | #define DRIVER_NAME "spi_imx" | 45 | #define DRIVER_NAME "spi_imx" |
@@ -51,6 +54,9 @@ | |||
51 | #define MXC_INT_RR (1 << 0) /* Receive data ready interrupt */ | 54 | #define MXC_INT_RR (1 << 0) /* Receive data ready interrupt */ |
52 | #define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */ | 55 | #define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */ |
53 | 56 | ||
57 | /* The maximum bytes that a sdma BD can transfer.*/ | ||
58 | #define MAX_SDMA_BD_BYTES (1 << 15) | ||
59 | #define IMX_DMA_TIMEOUT (msecs_to_jiffies(3000)) | ||
54 | struct spi_imx_config { | 60 | struct spi_imx_config { |
55 | unsigned int speed_hz; | 61 | unsigned int speed_hz; |
56 | unsigned int bpw; | 62 | unsigned int bpw; |
@@ -95,6 +101,16 @@ struct spi_imx_data { | |||
95 | const void *tx_buf; | 101 | const void *tx_buf; |
96 | unsigned int txfifo; /* number of words pushed in tx FIFO */ | 102 | unsigned int txfifo; /* number of words pushed in tx FIFO */ |
97 | 103 | ||
104 | /* DMA */ | ||
105 | unsigned int dma_is_inited; | ||
106 | unsigned int dma_finished; | ||
107 | bool usedma; | ||
108 | u32 rx_wml; | ||
109 | u32 tx_wml; | ||
110 | u32 rxt_wml; | ||
111 | struct completion dma_rx_completion; | ||
112 | struct completion dma_tx_completion; | ||
113 | |||
98 | const struct spi_imx_devtype_data *devtype_data; | 114 | const struct spi_imx_devtype_data *devtype_data; |
99 | int chipselect[0]; | 115 | int chipselect[0]; |
100 | }; | 116 | }; |
@@ -181,9 +197,21 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin, | |||
181 | return 7; | 197 | return 7; |
182 | } | 198 | } |
183 | 199 | ||
200 | static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, | ||
201 | struct spi_transfer *transfer) | ||
202 | { | ||
203 | struct spi_imx_data *spi_imx = spi_master_get_devdata(master); | ||
204 | |||
205 | if (spi_imx->dma_is_inited && (transfer->len > spi_imx->rx_wml) | ||
206 | && (transfer->len > spi_imx->tx_wml)) | ||
207 | return true; | ||
208 | return false; | ||
209 | } | ||
210 | |||
184 | #define MX51_ECSPI_CTRL 0x08 | 211 | #define MX51_ECSPI_CTRL 0x08 |
185 | #define MX51_ECSPI_CTRL_ENABLE (1 << 0) | 212 | #define MX51_ECSPI_CTRL_ENABLE (1 << 0) |
186 | #define MX51_ECSPI_CTRL_XCH (1 << 2) | 213 | #define MX51_ECSPI_CTRL_XCH (1 << 2) |
214 | #define MX51_ECSPI_CTRL_SMC (1 << 3) | ||
187 | #define MX51_ECSPI_CTRL_MODE_MASK (0xf << 4) | 215 | #define MX51_ECSPI_CTRL_MODE_MASK (0xf << 4) |
188 | #define MX51_ECSPI_CTRL_POSTDIV_OFFSET 8 | 216 | #define MX51_ECSPI_CTRL_POSTDIV_OFFSET 8 |
189 | #define MX51_ECSPI_CTRL_PREDIV_OFFSET 12 | 217 | #define MX51_ECSPI_CTRL_PREDIV_OFFSET 12 |
@@ -201,6 +229,18 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin, | |||
201 | #define MX51_ECSPI_INT_TEEN (1 << 0) | 229 | #define MX51_ECSPI_INT_TEEN (1 << 0) |
202 | #define MX51_ECSPI_INT_RREN (1 << 3) | 230 | #define MX51_ECSPI_INT_RREN (1 << 3) |
203 | 231 | ||
232 | #define MX51_ECSPI_DMA 0x14 | ||
233 | #define MX51_ECSPI_DMA_TX_WML_OFFSET 0 | ||
234 | #define MX51_ECSPI_DMA_TX_WML_MASK 0x3F | ||
235 | #define MX51_ECSPI_DMA_RX_WML_OFFSET 16 | ||
236 | #define MX51_ECSPI_DMA_RX_WML_MASK (0x3F << 16) | ||
237 | #define MX51_ECSPI_DMA_RXT_WML_OFFSET 24 | ||
238 | #define MX51_ECSPI_DMA_RXT_WML_MASK (0x3F << 24) | ||
239 | |||
240 | #define MX51_ECSPI_DMA_TEDEN_OFFSET 7 | ||
241 | #define MX51_ECSPI_DMA_RXDEN_OFFSET 23 | ||
242 | #define MX51_ECSPI_DMA_RXTDEN_OFFSET 31 | ||
243 | |||
204 | #define MX51_ECSPI_STAT 0x18 | 244 | #define MX51_ECSPI_STAT 0x18 |
205 | #define MX51_ECSPI_STAT_RR (1 << 3) | 245 | #define MX51_ECSPI_STAT_RR (1 << 3) |
206 | 246 | ||
@@ -257,17 +297,22 @@ static void __maybe_unused mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int | |||
257 | 297 | ||
258 | static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx) | 298 | static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx) |
259 | { | 299 | { |
260 | u32 reg; | 300 | u32 reg = readl(spi_imx->base + MX51_ECSPI_CTRL); |
261 | 301 | ||
262 | reg = readl(spi_imx->base + MX51_ECSPI_CTRL); | 302 | if (!spi_imx->usedma) |
263 | reg |= MX51_ECSPI_CTRL_XCH; | 303 | reg |= MX51_ECSPI_CTRL_XCH; |
304 | else if (!spi_imx->dma_finished) | ||
305 | reg |= MX51_ECSPI_CTRL_SMC; | ||
306 | else | ||
307 | reg &= ~MX51_ECSPI_CTRL_SMC; | ||
264 | writel(reg, spi_imx->base + MX51_ECSPI_CTRL); | 308 | writel(reg, spi_imx->base + MX51_ECSPI_CTRL); |
265 | } | 309 | } |
266 | 310 | ||
267 | static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, | 311 | static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, |
268 | struct spi_imx_config *config) | 312 | struct spi_imx_config *config) |
269 | { | 313 | { |
270 | u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0; | 314 | u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0; |
315 | u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg; | ||
271 | u32 clk = config->speed_hz, delay; | 316 | u32 clk = config->speed_hz, delay; |
272 | 317 | ||
273 | /* | 318 | /* |
@@ -319,6 +364,30 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, | |||
319 | else /* SCLK is _very_ slow */ | 364 | else /* SCLK is _very_ slow */ |
320 | usleep_range(delay, delay + 10); | 365 | usleep_range(delay, delay + 10); |
321 | 366 | ||
367 | /* | ||
368 | * Configure the DMA register: setup the watermark | ||
369 | * and enable DMA request. | ||
370 | */ | ||
371 | if (spi_imx->dma_is_inited) { | ||
372 | dma = readl(spi_imx->base + MX51_ECSPI_DMA); | ||
373 | |||
374 | spi_imx->tx_wml = spi_imx_get_fifosize(spi_imx) / 2; | ||
375 | spi_imx->rx_wml = spi_imx_get_fifosize(spi_imx) / 2; | ||
376 | spi_imx->rxt_wml = spi_imx_get_fifosize(spi_imx) / 2; | ||
377 | rx_wml_cfg = spi_imx->rx_wml << MX51_ECSPI_DMA_RX_WML_OFFSET; | ||
378 | tx_wml_cfg = spi_imx->tx_wml << MX51_ECSPI_DMA_TX_WML_OFFSET; | ||
379 | rxt_wml_cfg = spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET; | ||
380 | dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK | ||
381 | & ~MX51_ECSPI_DMA_RX_WML_MASK | ||
382 | & ~MX51_ECSPI_DMA_RXT_WML_MASK) | ||
383 | | rx_wml_cfg | tx_wml_cfg | rxt_wml_cfg | ||
384 | |(1 << MX51_ECSPI_DMA_TEDEN_OFFSET) | ||
385 | |(1 << MX51_ECSPI_DMA_RXDEN_OFFSET) | ||
386 | |(1 << MX51_ECSPI_DMA_RXTDEN_OFFSET); | ||
387 | |||
388 | writel(dma, spi_imx->base + MX51_ECSPI_DMA); | ||
389 | } | ||
390 | |||
322 | return 0; | 391 | return 0; |
323 | } | 392 | } |
324 | 393 | ||
@@ -730,7 +799,186 @@ static int spi_imx_setupxfer(struct spi_device *spi, | |||
730 | return 0; | 799 | return 0; |
731 | } | 800 | } |
732 | 801 | ||
733 | static int spi_imx_transfer(struct spi_device *spi, | 802 | static void spi_imx_sdma_exit(struct spi_imx_data *spi_imx) |
803 | { | ||
804 | struct spi_master *master = spi_imx->bitbang.master; | ||
805 | |||
806 | if (master->dma_rx) { | ||
807 | dma_release_channel(master->dma_rx); | ||
808 | master->dma_rx = NULL; | ||
809 | } | ||
810 | |||
811 | if (master->dma_tx) { | ||
812 | dma_release_channel(master->dma_tx); | ||
813 | master->dma_tx = NULL; | ||
814 | } | ||
815 | |||
816 | spi_imx->dma_is_inited = 0; | ||
817 | } | ||
818 | |||
819 | static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, | ||
820 | struct spi_master *master, | ||
821 | const struct resource *res) | ||
822 | { | ||
823 | struct dma_slave_config slave_config = {}; | ||
824 | int ret; | ||
825 | |||
826 | /* Prepare for TX DMA: */ | ||
827 | master->dma_tx = dma_request_slave_channel(dev, "tx"); | ||
828 | if (!master->dma_tx) { | ||
829 | dev_err(dev, "cannot get the TX DMA channel!\n"); | ||
830 | ret = -EINVAL; | ||
831 | goto err; | ||
832 | } | ||
833 | |||
834 | slave_config.direction = DMA_MEM_TO_DEV; | ||
835 | slave_config.dst_addr = res->start + MXC_CSPITXDATA; | ||
836 | slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | ||
837 | slave_config.dst_maxburst = spi_imx_get_fifosize(spi_imx) / 2; | ||
838 | ret = dmaengine_slave_config(master->dma_tx, &slave_config); | ||
839 | if (ret) { | ||
840 | dev_err(dev, "error in TX dma configuration.\n"); | ||
841 | goto err; | ||
842 | } | ||
843 | |||
844 | /* Prepare for RX : */ | ||
845 | master->dma_rx = dma_request_slave_channel(dev, "rx"); | ||
846 | if (!master->dma_rx) { | ||
847 | dev_dbg(dev, "cannot get the DMA channel.\n"); | ||
848 | ret = -EINVAL; | ||
849 | goto err; | ||
850 | } | ||
851 | |||
852 | slave_config.direction = DMA_DEV_TO_MEM; | ||
853 | slave_config.src_addr = res->start + MXC_CSPIRXDATA; | ||
854 | slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | ||
855 | slave_config.src_maxburst = spi_imx_get_fifosize(spi_imx) / 2; | ||
856 | ret = dmaengine_slave_config(master->dma_rx, &slave_config); | ||
857 | if (ret) { | ||
858 | dev_err(dev, "error in RX dma configuration.\n"); | ||
859 | goto err; | ||
860 | } | ||
861 | |||
862 | init_completion(&spi_imx->dma_rx_completion); | ||
863 | init_completion(&spi_imx->dma_tx_completion); | ||
864 | master->can_dma = spi_imx_can_dma; | ||
865 | master->max_dma_len = MAX_SDMA_BD_BYTES; | ||
866 | spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX | | ||
867 | SPI_MASTER_MUST_TX; | ||
868 | spi_imx->dma_is_inited = 1; | ||
869 | |||
870 | return 0; | ||
871 | err: | ||
872 | spi_imx_sdma_exit(spi_imx); | ||
873 | return ret; | ||
874 | } | ||
875 | |||
876 | static void spi_imx_dma_rx_callback(void *cookie) | ||
877 | { | ||
878 | struct spi_imx_data *spi_imx = (struct spi_imx_data *)cookie; | ||
879 | |||
880 | complete(&spi_imx->dma_rx_completion); | ||
881 | } | ||
882 | |||
883 | static void spi_imx_dma_tx_callback(void *cookie) | ||
884 | { | ||
885 | struct spi_imx_data *spi_imx = (struct spi_imx_data *)cookie; | ||
886 | |||
887 | complete(&spi_imx->dma_tx_completion); | ||
888 | } | ||
889 | |||
890 | static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, | ||
891 | struct spi_transfer *transfer) | ||
892 | { | ||
893 | struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL; | ||
894 | int ret; | ||
895 | u32 dma; | ||
896 | int left; | ||
897 | struct spi_master *master = spi_imx->bitbang.master; | ||
898 | struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg; | ||
899 | |||
900 | if (tx) { | ||
901 | desc_tx = dmaengine_prep_slave_sg(master->dma_tx, | ||
902 | tx->sgl, tx->nents, DMA_TO_DEVICE, | ||
903 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
904 | if (!desc_tx) | ||
905 | goto no_dma; | ||
906 | |||
907 | desc_tx->callback = spi_imx_dma_tx_callback; | ||
908 | desc_tx->callback_param = (void *)spi_imx; | ||
909 | dmaengine_submit(desc_tx); | ||
910 | } | ||
911 | |||
912 | if (rx) { | ||
913 | desc_rx = dmaengine_prep_slave_sg(master->dma_rx, | ||
914 | rx->sgl, rx->nents, DMA_FROM_DEVICE, | ||
915 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
916 | if (!desc_rx) | ||
917 | goto no_dma; | ||
918 | |||
919 | desc_rx->callback = spi_imx_dma_rx_callback; | ||
920 | desc_rx->callback_param = (void *)spi_imx; | ||
921 | dmaengine_submit(desc_rx); | ||
922 | } | ||
923 | |||
924 | reinit_completion(&spi_imx->dma_rx_completion); | ||
925 | reinit_completion(&spi_imx->dma_tx_completion); | ||
926 | |||
927 | /* Trigger the cspi module. */ | ||
928 | spi_imx->dma_finished = 0; | ||
929 | |||
930 | dma = readl(spi_imx->base + MX51_ECSPI_DMA); | ||
931 | dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK); | ||
932 | /* Change RX_DMA_LENGTH trigger dma fetch tail data */ | ||
933 | left = transfer->len % spi_imx->rxt_wml; | ||
934 | if (left) | ||
935 | writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET), | ||
936 | spi_imx->base + MX51_ECSPI_DMA); | ||
937 | spi_imx->devtype_data->trigger(spi_imx); | ||
938 | |||
939 | dma_async_issue_pending(master->dma_tx); | ||
940 | dma_async_issue_pending(master->dma_rx); | ||
941 | /* Wait SDMA to finish the data transfer.*/ | ||
942 | ret = wait_for_completion_timeout(&spi_imx->dma_tx_completion, | ||
943 | IMX_DMA_TIMEOUT); | ||
944 | if (!ret) { | ||
945 | pr_warn("%s %s: I/O Error in DMA TX\n", | ||
946 | dev_driver_string(&master->dev), | ||
947 | dev_name(&master->dev)); | ||
948 | dmaengine_terminate_all(master->dma_tx); | ||
949 | } else { | ||
950 | ret = wait_for_completion_timeout(&spi_imx->dma_rx_completion, | ||
951 | IMX_DMA_TIMEOUT); | ||
952 | if (!ret) { | ||
953 | pr_warn("%s %s: I/O Error in DMA RX\n", | ||
954 | dev_driver_string(&master->dev), | ||
955 | dev_name(&master->dev)); | ||
956 | spi_imx->devtype_data->reset(spi_imx); | ||
957 | dmaengine_terminate_all(master->dma_rx); | ||
958 | } | ||
959 | writel(dma | | ||
960 | spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET, | ||
961 | spi_imx->base + MX51_ECSPI_DMA); | ||
962 | } | ||
963 | |||
964 | spi_imx->dma_finished = 1; | ||
965 | spi_imx->devtype_data->trigger(spi_imx); | ||
966 | |||
967 | if (!ret) | ||
968 | ret = -ETIMEDOUT; | ||
969 | else if (ret > 0) | ||
970 | ret = transfer->len; | ||
971 | |||
972 | return ret; | ||
973 | |||
974 | no_dma: | ||
975 | pr_warn_once("%s %s: DMA not available, falling back to PIO\n", | ||
976 | dev_driver_string(&master->dev), | ||
977 | dev_name(&master->dev)); | ||
978 | return -EAGAIN; | ||
979 | } | ||
980 | |||
981 | static int spi_imx_pio_transfer(struct spi_device *spi, | ||
734 | struct spi_transfer *transfer) | 982 | struct spi_transfer *transfer) |
735 | { | 983 | { |
736 | struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); | 984 | struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); |
@@ -751,6 +999,24 @@ static int spi_imx_transfer(struct spi_device *spi, | |||
751 | return transfer->len; | 999 | return transfer->len; |
752 | } | 1000 | } |
753 | 1001 | ||
1002 | static int spi_imx_transfer(struct spi_device *spi, | ||
1003 | struct spi_transfer *transfer) | ||
1004 | { | ||
1005 | int ret; | ||
1006 | struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); | ||
1007 | |||
1008 | if (spi_imx->bitbang.master->can_dma && | ||
1009 | spi_imx_can_dma(spi_imx->bitbang.master, spi, transfer)) { | ||
1010 | spi_imx->usedma = true; | ||
1011 | ret = spi_imx_dma_transfer(spi_imx, transfer); | ||
1012 | if (ret != -EAGAIN) | ||
1013 | return ret; | ||
1014 | } | ||
1015 | spi_imx->usedma = false; | ||
1016 | |||
1017 | return spi_imx_pio_transfer(spi, transfer); | ||
1018 | } | ||
1019 | |||
754 | static int spi_imx_setup(struct spi_device *spi) | 1020 | static int spi_imx_setup(struct spi_device *spi) |
755 | { | 1021 | { |
756 | struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); | 1022 | struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); |
@@ -911,6 +1177,13 @@ static int spi_imx_probe(struct platform_device *pdev) | |||
911 | goto out_put_per; | 1177 | goto out_put_per; |
912 | 1178 | ||
913 | spi_imx->spi_clk = clk_get_rate(spi_imx->clk_per); | 1179 | spi_imx->spi_clk = clk_get_rate(spi_imx->clk_per); |
1180 | /* | ||
1181 | * Only validated on i.mx6 now, can remove the constrain if validated on | ||
1182 | * other chips. | ||
1183 | */ | ||
1184 | if (spi_imx->devtype_data == &imx51_ecspi_devtype_data | ||
1185 | && spi_imx_sdma_init(&pdev->dev, spi_imx, master, res)) | ||
1186 | dev_err(&pdev->dev, "dma setup error,use pio instead\n"); | ||
914 | 1187 | ||
915 | spi_imx->devtype_data->reset(spi_imx); | 1188 | spi_imx->devtype_data->reset(spi_imx); |
916 | 1189 | ||
@@ -949,6 +1222,7 @@ static int spi_imx_remove(struct platform_device *pdev) | |||
949 | writel(0, spi_imx->base + MXC_CSPICTRL); | 1222 | writel(0, spi_imx->base + MXC_CSPICTRL); |
950 | clk_unprepare(spi_imx->clk_ipg); | 1223 | clk_unprepare(spi_imx->clk_ipg); |
951 | clk_unprepare(spi_imx->clk_per); | 1224 | clk_unprepare(spi_imx->clk_per); |
1225 | spi_imx_sdma_exit(spi_imx); | ||
952 | spi_master_put(master); | 1226 | spi_master_put(master); |
953 | 1227 | ||
954 | return 0; | 1228 | return 0; |
diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index c3f8d3a22472..51460878af04 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c | |||
@@ -85,7 +85,7 @@ static int mxs_spi_setup_transfer(struct spi_device *dev, | |||
85 | mxs_ssp_set_clk_rate(ssp, hz); | 85 | mxs_ssp_set_clk_rate(ssp, hz); |
86 | /* | 86 | /* |
87 | * Save requested rate, hz, rather than the actual rate, | 87 | * Save requested rate, hz, rather than the actual rate, |
88 | * ssp->clk_rate. Otherwise we would set the rate every trasfer | 88 | * ssp->clk_rate. Otherwise we would set the rate every transfer |
89 | * when the actual rate is not quite the same as requested rate. | 89 | * when the actual rate is not quite the same as requested rate. |
90 | */ | 90 | */ |
91 | spi->sck = hz; | 91 | spi->sck = hz; |
diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index 5e91858f6f01..fb522765ce5a 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c | |||
@@ -70,10 +70,6 @@ | |||
70 | #define SPI_STATUS_WE (1UL << 1) | 70 | #define SPI_STATUS_WE (1UL << 1) |
71 | #define SPI_STATUS_RD (1UL << 0) | 71 | #define SPI_STATUS_RD (1UL << 0) |
72 | 72 | ||
73 | #define WRITE 0 | ||
74 | #define READ 1 | ||
75 | |||
76 | |||
77 | /* use PIO for small transfers, avoiding DMA setup/teardown overhead and | 73 | /* use PIO for small transfers, avoiding DMA setup/teardown overhead and |
78 | * cache operations; better heuristics consider wordsize and bitrate. | 74 | * cache operations; better heuristics consider wordsize and bitrate. |
79 | */ | 75 | */ |
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 345e7d61c399..835cdda6f4f5 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/pm_runtime.h> | 19 | #include <linux/pm_runtime.h> |
20 | #include <linux/of.h> | 20 | #include <linux/of.h> |
21 | #include <linux/of_device.h> | ||
21 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
22 | #include <linux/sizes.h> | 23 | #include <linux/sizes.h> |
23 | #include <asm/unaligned.h> | 24 | #include <asm/unaligned.h> |
@@ -40,13 +41,27 @@ | |||
40 | #define ORION_SPI_MODE_CPHA (1 << 12) | 41 | #define ORION_SPI_MODE_CPHA (1 << 12) |
41 | #define ORION_SPI_IF_8_16_BIT_MODE (1 << 5) | 42 | #define ORION_SPI_IF_8_16_BIT_MODE (1 << 5) |
42 | #define ORION_SPI_CLK_PRESCALE_MASK 0x1F | 43 | #define ORION_SPI_CLK_PRESCALE_MASK 0x1F |
44 | #define ARMADA_SPI_CLK_PRESCALE_MASK 0xDF | ||
43 | #define ORION_SPI_MODE_MASK (ORION_SPI_MODE_CPOL | \ | 45 | #define ORION_SPI_MODE_MASK (ORION_SPI_MODE_CPOL | \ |
44 | ORION_SPI_MODE_CPHA) | 46 | ORION_SPI_MODE_CPHA) |
45 | 47 | ||
48 | enum orion_spi_type { | ||
49 | ORION_SPI, | ||
50 | ARMADA_SPI, | ||
51 | }; | ||
52 | |||
53 | struct orion_spi_dev { | ||
54 | enum orion_spi_type typ; | ||
55 | unsigned int min_divisor; | ||
56 | unsigned int max_divisor; | ||
57 | u32 prescale_mask; | ||
58 | }; | ||
59 | |||
46 | struct orion_spi { | 60 | struct orion_spi { |
47 | struct spi_master *master; | 61 | struct spi_master *master; |
48 | void __iomem *base; | 62 | void __iomem *base; |
49 | struct clk *clk; | 63 | struct clk *clk; |
64 | const struct orion_spi_dev *devdata; | ||
50 | }; | 65 | }; |
51 | 66 | ||
52 | static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg) | 67 | static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg) |
@@ -83,30 +98,66 @@ static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed) | |||
83 | u32 prescale; | 98 | u32 prescale; |
84 | u32 reg; | 99 | u32 reg; |
85 | struct orion_spi *orion_spi; | 100 | struct orion_spi *orion_spi; |
101 | const struct orion_spi_dev *devdata; | ||
86 | 102 | ||
87 | orion_spi = spi_master_get_devdata(spi->master); | 103 | orion_spi = spi_master_get_devdata(spi->master); |
104 | devdata = orion_spi->devdata; | ||
88 | 105 | ||
89 | tclk_hz = clk_get_rate(orion_spi->clk); | 106 | tclk_hz = clk_get_rate(orion_spi->clk); |
90 | 107 | ||
91 | /* | 108 | if (devdata->typ == ARMADA_SPI) { |
92 | * the supported rates are: 4,6,8...30 | 109 | unsigned int clk, spr, sppr, sppr2, err; |
93 | * round up as we look for equal or less speed | 110 | unsigned int best_spr, best_sppr, best_err; |
94 | */ | 111 | |
95 | rate = DIV_ROUND_UP(tclk_hz, speed); | 112 | best_err = speed; |
96 | rate = roundup(rate, 2); | 113 | best_spr = 0; |
114 | best_sppr = 0; | ||
115 | |||
116 | /* Iterate over the valid range looking for best fit */ | ||
117 | for (sppr = 0; sppr < 8; sppr++) { | ||
118 | sppr2 = 0x1 << sppr; | ||
119 | |||
120 | spr = tclk_hz / sppr2; | ||
121 | spr = DIV_ROUND_UP(spr, speed); | ||
122 | if ((spr == 0) || (spr > 15)) | ||
123 | continue; | ||
97 | 124 | ||
98 | /* check if requested speed is too small */ | 125 | clk = tclk_hz / (spr * sppr2); |
99 | if (rate > 30) | 126 | err = speed - clk; |
100 | return -EINVAL; | ||
101 | 127 | ||
102 | if (rate < 4) | 128 | if (err < best_err) { |
103 | rate = 4; | 129 | best_spr = spr; |
130 | best_sppr = sppr; | ||
131 | best_err = err; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | if ((best_sppr == 0) && (best_spr == 0)) | ||
136 | return -EINVAL; | ||
137 | |||
138 | prescale = ((best_sppr & 0x6) << 5) | | ||
139 | ((best_sppr & 0x1) << 4) | best_spr; | ||
140 | } else { | ||
141 | /* | ||
142 | * the supported rates are: 4,6,8...30 | ||
143 | * round up as we look for equal or less speed | ||
144 | */ | ||
145 | rate = DIV_ROUND_UP(tclk_hz, speed); | ||
146 | rate = roundup(rate, 2); | ||
147 | |||
148 | /* check if requested speed is too small */ | ||
149 | if (rate > 30) | ||
150 | return -EINVAL; | ||
104 | 151 | ||
105 | /* Convert the rate to SPI clock divisor value. */ | 152 | if (rate < 4) |
106 | prescale = 0x10 + rate/2; | 153 | rate = 4; |
154 | |||
155 | /* Convert the rate to SPI clock divisor value. */ | ||
156 | prescale = 0x10 + rate/2; | ||
157 | } | ||
107 | 158 | ||
108 | reg = readl(spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG)); | 159 | reg = readl(spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG)); |
109 | reg = ((reg & ~ORION_SPI_CLK_PRESCALE_MASK) | prescale); | 160 | reg = ((reg & ~devdata->prescale_mask) | prescale); |
110 | writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG)); | 161 | writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG)); |
111 | 162 | ||
112 | return 0; | 163 | return 0; |
@@ -342,8 +393,31 @@ static int orion_spi_reset(struct orion_spi *orion_spi) | |||
342 | return 0; | 393 | return 0; |
343 | } | 394 | } |
344 | 395 | ||
396 | static const struct orion_spi_dev orion_spi_dev_data = { | ||
397 | .typ = ORION_SPI, | ||
398 | .min_divisor = 4, | ||
399 | .max_divisor = 30, | ||
400 | .prescale_mask = ORION_SPI_CLK_PRESCALE_MASK, | ||
401 | }; | ||
402 | |||
403 | static const struct orion_spi_dev armada_spi_dev_data = { | ||
404 | .typ = ARMADA_SPI, | ||
405 | .min_divisor = 1, | ||
406 | .max_divisor = 1920, | ||
407 | .prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK, | ||
408 | }; | ||
409 | |||
410 | static const struct of_device_id orion_spi_of_match_table[] = { | ||
411 | { .compatible = "marvell,orion-spi", .data = &orion_spi_dev_data, }, | ||
412 | { .compatible = "marvell,armada-370-spi", .data = &armada_spi_dev_data, }, | ||
413 | {} | ||
414 | }; | ||
415 | MODULE_DEVICE_TABLE(of, orion_spi_of_match_table); | ||
416 | |||
345 | static int orion_spi_probe(struct platform_device *pdev) | 417 | static int orion_spi_probe(struct platform_device *pdev) |
346 | { | 418 | { |
419 | const struct of_device_id *of_id; | ||
420 | const struct orion_spi_dev *devdata; | ||
347 | struct spi_master *master; | 421 | struct spi_master *master; |
348 | struct orion_spi *spi; | 422 | struct orion_spi *spi; |
349 | struct resource *r; | 423 | struct resource *r; |
@@ -379,6 +453,10 @@ static int orion_spi_probe(struct platform_device *pdev) | |||
379 | spi = spi_master_get_devdata(master); | 453 | spi = spi_master_get_devdata(master); |
380 | spi->master = master; | 454 | spi->master = master; |
381 | 455 | ||
456 | of_id = of_match_device(orion_spi_of_match_table, &pdev->dev); | ||
457 | devdata = of_id->data; | ||
458 | spi->devdata = devdata; | ||
459 | |||
382 | spi->clk = devm_clk_get(&pdev->dev, NULL); | 460 | spi->clk = devm_clk_get(&pdev->dev, NULL); |
383 | if (IS_ERR(spi->clk)) { | 461 | if (IS_ERR(spi->clk)) { |
384 | status = PTR_ERR(spi->clk); | 462 | status = PTR_ERR(spi->clk); |
@@ -390,8 +468,8 @@ static int orion_spi_probe(struct platform_device *pdev) | |||
390 | goto out; | 468 | goto out; |
391 | 469 | ||
392 | tclk_hz = clk_get_rate(spi->clk); | 470 | tclk_hz = clk_get_rate(spi->clk); |
393 | master->max_speed_hz = DIV_ROUND_UP(tclk_hz, 4); | 471 | master->max_speed_hz = DIV_ROUND_UP(tclk_hz, devdata->min_divisor); |
394 | master->min_speed_hz = DIV_ROUND_UP(tclk_hz, 30); | 472 | master->min_speed_hz = DIV_ROUND_UP(tclk_hz, devdata->max_divisor); |
395 | 473 | ||
396 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 474 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
397 | spi->base = devm_ioremap_resource(&pdev->dev, r); | 475 | spi->base = devm_ioremap_resource(&pdev->dev, r); |
@@ -470,12 +548,6 @@ static const struct dev_pm_ops orion_spi_pm_ops = { | |||
470 | NULL) | 548 | NULL) |
471 | }; | 549 | }; |
472 | 550 | ||
473 | static const struct of_device_id orion_spi_of_match_table[] = { | ||
474 | { .compatible = "marvell,orion-spi", }, | ||
475 | {} | ||
476 | }; | ||
477 | MODULE_DEVICE_TABLE(of, orion_spi_of_match_table); | ||
478 | |||
479 | static struct platform_driver orion_spi_driver = { | 551 | static struct platform_driver orion_spi_driver = { |
480 | .driver = { | 552 | .driver = { |
481 | .name = DRIVER_NAME, | 553 | .name = DRIVER_NAME, |