aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChao Fu <B44548@freescale.com>2014-02-12 02:29:05 -0500
committerMark Brown <broonie@linaro.org>2014-02-15 20:15:23 -0500
commit1acbdeb92c87fc18eade0815dedc257fe45b88b7 (patch)
tree8e4b34fade904bbd4e01c94f90212d9ad6654eba
parent38dbfb59d1175ef458d006556061adeaa8751b72 (diff)
spi/fsl-dspi: Convert to use regmap and add big-endian support
Freescale DSPI module will have two endianess in different platform, but ARM is little endian. So when DSPI in big endian, core in little endian, readl and writel can not adjust R/W register in this condition. This patch will remove general readl/writel, and import regmap mechanism. Data endian will be transfered in regmap APIs. Documents: dspi add bool "big-endian" in dts node if DSPI module work in big endian. Signed-off-by: Chao Fu <b44548@freescale.com> Reviewed-by: Xiubo Li <Li.Xiubo@freescale.com> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt2
-rw-r--r--drivers/spi/Kconfig1
-rw-r--r--drivers/spi/spi-fsl-dspi.c80
3 files changed, 56 insertions, 27 deletions
diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
index a1fb3035a42b..5376de40f10b 100644
--- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
+++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
@@ -10,6 +10,7 @@ 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.
13Example: 14Example:
14 15
15dspi0@4002c000 { 16dspi0@4002c000 {
@@ -24,6 +25,7 @@ dspi0@4002c000 {
24 bus-num = <0>; 25 bus-num = <0>;
25 pinctrl-names = "default"; 26 pinctrl-names = "default";
26 pinctrl-0 = <&pinctrl_dspi0_1>; 27 pinctrl-0 = <&pinctrl_dspi0_1>;
28 big-endian;
27 status = "okay"; 29 status = "okay";
28 30
29 sflash: at26df081a@0 { 31 sflash: at26df081a@0 {
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index ba9310bc9acb..00e951045aac 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -270,6 +270,7 @@ config SPI_FSL_SPI
270config SPI_FSL_DSPI 270config SPI_FSL_DSPI
271 tristate "Freescale DSPI controller" 271 tristate "Freescale DSPI controller"
272 select SPI_BITBANG 272 select SPI_BITBANG
273 select REGMAP_MMIO
273 depends on SOC_VF610 || COMPILE_TEST 274 depends on SOC_VF610 || COMPILE_TEST
274 help 275 help
275 This enables support for the Freescale DSPI controller in master 276 This enables support for the Freescale DSPI controller in master
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index ec79f726672a..fb16575d233f 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -18,6 +18,7 @@
18#include <linux/interrupt.h> 18#include <linux/interrupt.h>
19#include <linux/errno.h> 19#include <linux/errno.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/regmap.h>
21#include <linux/sched.h> 22#include <linux/sched.h>
22#include <linux/delay.h> 23#include <linux/delay.h>
23#include <linux/io.h> 24#include <linux/io.h>
@@ -108,7 +109,7 @@ struct fsl_dspi {
108 struct spi_bitbang bitbang; 109 struct spi_bitbang bitbang;
109 struct platform_device *pdev; 110 struct platform_device *pdev;
110 111
111 void __iomem *base; 112 struct regmap *regmap;
112 int irq; 113 int irq;
113 struct clk *clk; 114 struct clk *clk;
114 115
@@ -129,18 +130,11 @@ struct fsl_dspi {
129 130
130static inline int is_double_byte_mode(struct fsl_dspi *dspi) 131static inline int is_double_byte_mode(struct fsl_dspi *dspi)
131{ 132{
132 return ((readl(dspi->base + SPI_CTAR(dspi->cs)) & SPI_FRAME_BITS_MASK) 133 unsigned int val;
133 == SPI_FRAME_BITS(8)) ? 0 : 1;
134}
135 134
136static void set_bit_mode(struct fsl_dspi *dspi, unsigned char bits) 135 regmap_read(dspi->regmap, SPI_CTAR(dspi->cs), &val);
137{
138 u32 temp;
139 136
140 temp = readl(dspi->base + SPI_CTAR(dspi->cs)); 137 return ((val & SPI_FRAME_BITS_MASK) == SPI_FRAME_BITS(8)) ? 0 : 1;
141 temp &= ~SPI_FRAME_BITS_MASK;
142 temp |= SPI_FRAME_BITS(bits);
143 writel(temp, dspi->base + SPI_CTAR(dspi->cs));
144} 138}
145 139
146static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, 140static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
@@ -188,7 +182,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi)
188 */ 182 */
189 if (tx_word && (dspi->len == 1)) { 183 if (tx_word && (dspi->len == 1)) {
190 dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM; 184 dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM;
191 set_bit_mode(dspi, 8); 185 regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs),
186 SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8));
192 tx_word = 0; 187 tx_word = 0;
193 } 188 }
194 189
@@ -238,7 +233,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi)
238 dspi_pushr |= SPI_PUSHR_CTCNT; /* clear counter */ 233 dspi_pushr |= SPI_PUSHR_CTCNT; /* clear counter */
239 } 234 }
240 235
241 writel(dspi_pushr, dspi->base + SPI_PUSHR); 236 regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr);
237
242 tx_count++; 238 tx_count++;
243 } 239 }
244 240
@@ -253,17 +249,23 @@ static int dspi_transfer_read(struct fsl_dspi *dspi)
253 while ((dspi->rx < dspi->rx_end) 249 while ((dspi->rx < dspi->rx_end)
254 && (rx_count < DSPI_FIFO_SIZE)) { 250 && (rx_count < DSPI_FIFO_SIZE)) {
255 if (rx_word) { 251 if (rx_word) {
252 unsigned int val;
253
256 if ((dspi->rx_end - dspi->rx) == 1) 254 if ((dspi->rx_end - dspi->rx) == 1)
257 break; 255 break;
258 256
259 d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR)); 257 regmap_read(dspi->regmap, SPI_POPR, &val);
258 d = SPI_POPR_RXDATA(val);
260 259
261 if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) 260 if (!(dspi->dataflags & TRAN_STATE_RX_VOID))
262 *(u16 *)dspi->rx = d; 261 *(u16 *)dspi->rx = d;
263 dspi->rx += 2; 262 dspi->rx += 2;
264 263
265 } else { 264 } else {
266 d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR)); 265 unsigned int val;
266
267 regmap_read(dspi->regmap, SPI_POPR, &val);
268 d = SPI_POPR_RXDATA(val);
267 if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) 269 if (!(dspi->dataflags & TRAN_STATE_RX_VOID))
268 *(u8 *)dspi->rx = d; 270 *(u8 *)dspi->rx = d;
269 dspi->rx++; 271 dspi->rx++;
@@ -295,13 +297,13 @@ static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t)
295 if (!dspi->tx) 297 if (!dspi->tx)
296 dspi->dataflags |= TRAN_STATE_TX_VOID; 298 dspi->dataflags |= TRAN_STATE_TX_VOID;
297 299
298 writel(dspi->cur_chip->mcr_val, dspi->base + SPI_MCR); 300 regmap_write(dspi->regmap, SPI_MCR, dspi->cur_chip->mcr_val);
299 writel(dspi->cur_chip->ctar_val, dspi->base + SPI_CTAR(dspi->cs)); 301 regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), dspi->cur_chip->ctar_val);
300 writel(SPI_RSER_EOQFE, dspi->base + SPI_RSER); 302 regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE);
301 303
302 if (t->speed_hz) 304 if (t->speed_hz)
303 writel(dspi->cur_chip->ctar_val, 305 regmap_write(dspi->regmap, SPI_CTAR(dspi->cs),
304 dspi->base + SPI_CTAR(dspi->cs)); 306 dspi->cur_chip->ctar_val);
305 307
306 dspi_transfer_write(dspi); 308 dspi_transfer_write(dspi);
307 309
@@ -315,7 +317,9 @@ static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t)
315static void dspi_chipselect(struct spi_device *spi, int value) 317static void dspi_chipselect(struct spi_device *spi, int value)
316{ 318{
317 struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); 319 struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
318 u32 pushr = readl(dspi->base + SPI_PUSHR); 320 unsigned int pushr;
321
322 regmap_read(dspi->regmap, SPI_PUSHR, &pushr);
319 323
320 switch (value) { 324 switch (value) {
321 case BITBANG_CS_ACTIVE: 325 case BITBANG_CS_ACTIVE:
@@ -326,7 +330,7 @@ static void dspi_chipselect(struct spi_device *spi, int value)
326 break; 330 break;
327 } 331 }
328 332
329 writel(pushr, dspi->base + SPI_PUSHR); 333 regmap_write(dspi->regmap, SPI_PUSHR, pushr);
330} 334}
331 335
332static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) 336static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
@@ -382,13 +386,15 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)
382{ 386{
383 struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; 387 struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id;
384 388
385 writel(SPI_SR_EOQF, dspi->base + SPI_SR); 389 regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF);
386 390
387 dspi_transfer_read(dspi); 391 dspi_transfer_read(dspi);
388 392
389 if (!dspi->len) { 393 if (!dspi->len) {
390 if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) 394 if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM)
391 set_bit_mode(dspi, 16); 395 regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs),
396 SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(16));
397
392 dspi->waitflags = 1; 398 dspi->waitflags = 1;
393 wake_up_interruptible(&dspi->waitq); 399 wake_up_interruptible(&dspi->waitq);
394 } else { 400 } else {
@@ -435,12 +441,20 @@ static const struct dev_pm_ops dspi_pm = {
435 SET_SYSTEM_SLEEP_PM_OPS(dspi_suspend, dspi_resume) 441 SET_SYSTEM_SLEEP_PM_OPS(dspi_suspend, dspi_resume)
436}; 442};
437 443
444static struct regmap_config dspi_regmap_config = {
445 .reg_bits = 32,
446 .val_bits = 32,
447 .reg_stride = 4,
448 .max_register = 0x88,
449};
450
438static int dspi_probe(struct platform_device *pdev) 451static int dspi_probe(struct platform_device *pdev)
439{ 452{
440 struct device_node *np = pdev->dev.of_node; 453 struct device_node *np = pdev->dev.of_node;
441 struct spi_master *master; 454 struct spi_master *master;
442 struct fsl_dspi *dspi; 455 struct fsl_dspi *dspi;
443 struct resource *res; 456 struct resource *res;
457 void __iomem *base;
444 int ret = 0, cs_num, bus_num; 458 int ret = 0, cs_num, bus_num;
445 459
446 master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); 460 master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi));
@@ -475,12 +489,24 @@ static int dspi_probe(struct platform_device *pdev)
475 master->bus_num = bus_num; 489 master->bus_num = bus_num;
476 490
477 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 491 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
478 dspi->base = devm_ioremap_resource(&pdev->dev, res); 492 base = devm_ioremap_resource(&pdev->dev, res);
479 if (IS_ERR(dspi->base)) { 493 if (IS_ERR(base)) {
480 ret = PTR_ERR(dspi->base); 494 ret = PTR_ERR(base);
481 goto out_master_put; 495 goto out_master_put;
482 } 496 }
483 497
498 dspi_regmap_config.lock_arg = dspi;
499 dspi_regmap_config.val_format_endian =
500 of_property_read_bool(np, "big-endian")
501 ? REGMAP_ENDIAN_BIG : REGMAP_ENDIAN_DEFAULT;
502 dspi->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "dspi", base,
503 &dspi_regmap_config);
504 if (IS_ERR(dspi->regmap)) {
505 dev_err(&pdev->dev, "failed to init regmap: %ld\n",
506 PTR_ERR(dspi->regmap));
507 return PTR_ERR(dspi->regmap);
508 }
509
484 dspi->irq = platform_get_irq(pdev, 0); 510 dspi->irq = platform_get_irq(pdev, 0);
485 if (dspi->irq < 0) { 511 if (dspi->irq < 0) {
486 dev_err(&pdev->dev, "can't get platform irq\n"); 512 dev_err(&pdev->dev, "can't get platform irq\n");