aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorAndreas Larsson <andreas@gaisler.com>2013-02-15 10:52:26 -0500
committerGrant Likely <grant.likely@secretlab.ca>2013-04-07 05:07:56 -0400
commit447b0c7b939f1d9e4024edf07a471ce7b1bcf002 (patch)
treeba1118bd6bbf30af8fe4622f8c7d9ad103c9f566 /drivers/spi
parent8922a366ddd20964e3542e12f0315a8a88b3a638 (diff)
spi/spi-fsl-spi: Add support for Aeroflex Gaisler GRLIB cores normally running on SPARC
This adds support for the mostly register-compatible SPICTRL cores from the GRLIB VHDL IP core library from Aeroflex Gaisler. They are normally running on SPARC. A different entry in of_fsl_spi_match matches this core and indicates a different hardware type that is used to set up different function pointers and special cases. The GRLIB core operates in cpu mode. The number of bits per word might be limited. There might be native chipselects selected via a slave select register. These differences to the FSL type cores, if present, are indicated by a capabilities register. Other register and function differences exists but are not relevant to the driver. Acked-by: Anton Vorontsov <anton@enomsg.org> Signed-off-by: Andreas Larsson <andreas@gaisler.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/Kconfig4
-rw-r--r--drivers/spi/spi-fsl-spi.c98
-rw-r--r--drivers/spi/spi-fsl-spi.h13
3 files changed, 101 insertions, 14 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 3524bec5ae5b..2946ab4736f6 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -236,7 +236,7 @@ config SPI_FSL_CPM
236 depends on FSL_SOC 236 depends on FSL_SOC
237 237
238config SPI_FSL_SPI 238config SPI_FSL_SPI
239 bool "Freescale SPI controller" 239 bool "Freescale SPI controller and Aeroflex Gaisler GRLIB SPI controller"
240 depends on OF 240 depends on OF
241 select SPI_FSL_LIB 241 select SPI_FSL_LIB
242 select SPI_FSL_CPM if FSL_SOC 242 select SPI_FSL_CPM if FSL_SOC
@@ -244,6 +244,8 @@ config SPI_FSL_SPI
244 This enables using the Freescale SPI controllers in master mode. 244 This enables using the Freescale SPI controllers in master mode.
245 MPC83xx platform uses the controller in cpu mode or CPM/QE mode. 245 MPC83xx platform uses the controller in cpu mode or CPM/QE mode.
246 MPC8569 uses the controller in QE mode, MPC8610 in cpu mode. 246 MPC8569 uses the controller in QE mode, MPC8610 in cpu mode.
247 This also enables using the Aeroflex Gaisler GRLIB SPI controller in
248 master mode.
247 249
248config SPI_FSL_ESPI 250config SPI_FSL_ESPI
249 bool "Freescale eSPI controller" 251 bool "Freescale eSPI controller"
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index 7eff63a284ff..6846459e5c9d 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
@@ -40,6 +44,7 @@
40#include "spi-fsl-spi.h" 44#include "spi-fsl-spi.h"
41 45
42#define TYPE_FSL 0 46#define TYPE_FSL 0
47#define TYPE_GRLIB 1
43 48
44struct fsl_spi_match_data { 49struct fsl_spi_match_data {
45 int type; 50 int type;
@@ -49,11 +54,19 @@ static struct fsl_spi_match_data of_fsl_spi_fsl_config = {
49 .type = TYPE_FSL, 54 .type = TYPE_FSL,
50}; 55};
51 56
57static struct fsl_spi_match_data of_fsl_spi_grlib_config = {
58 .type = TYPE_GRLIB,
59};
60
52static struct of_device_id of_fsl_spi_match[] = { 61static struct of_device_id of_fsl_spi_match[] = {
53 { 62 {
54 .compatible = "fsl,spi", 63 .compatible = "fsl,spi",
55 .data = &of_fsl_spi_fsl_config, 64 .data = &of_fsl_spi_fsl_config,
56 }, 65 },
66 {
67 .compatible = "aeroflexgaisler,spictrl",
68 .data = &of_fsl_spi_grlib_config,
69 },
57 {} 70 {}
58}; 71};
59MODULE_DEVICE_TABLE(of, of_fsl_spi_match); 72MODULE_DEVICE_TABLE(of, of_fsl_spi_match);
@@ -141,6 +154,21 @@ static void fsl_spi_qe_cpu_set_shifts(u32 *rx_shift, u32 *tx_shift,
141 } 154 }
142} 155}
143 156
157static 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
144static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs, 172static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
145 struct spi_device *spi, 173 struct spi_device *spi,
146 struct mpc8xxx_spi *mpc8xxx_spi, 174 struct mpc8xxx_spi *mpc8xxx_spi,
@@ -494,6 +522,42 @@ static void fsl_spi_remove(struct mpc8xxx_spi *mspi)
494 fsl_spi_cpm_free(mspi); 522 fsl_spi_cpm_free(mspi);
495} 523}
496 524
525static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
526{
527 struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
528 struct fsl_spi_reg *reg_base = mpc8xxx_spi->reg_base;
529 u32 slvsel;
530 u16 cs = spi->chip_select;
531
532 slvsel = mpc8xxx_spi_read_reg(&reg_base->slvsel);
533 slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs));
534 mpc8xxx_spi_write_reg(&reg_base->slvsel, slvsel);
535}
536
537static void fsl_spi_grlib_probe(struct device *dev)
538{
539 struct fsl_spi_platform_data *pdata = dev->platform_data;
540 struct spi_master *master = dev_get_drvdata(dev);
541 struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
542 struct fsl_spi_reg *reg_base = mpc8xxx_spi->reg_base;
543 int mbits;
544 u32 capabilities;
545
546 capabilities = mpc8xxx_spi_read_reg(&reg_base->cap);
547
548 mpc8xxx_spi->set_shifts = fsl_spi_grlib_set_shifts;
549 mbits = SPCAP_MAXWLEN(capabilities);
550 if (mbits)
551 mpc8xxx_spi->max_bits_per_word = mbits + 1;
552
553 master->num_chipselect = 1; /* Allow for an always selected chip */
554 if (SPCAP_SSEN(capabilities)) {
555 master->num_chipselect = SPCAP_SSSZ(capabilities);
556 mpc8xxx_spi_write_reg(&reg_base->slvsel, 0xffffffff);
557 }
558 pdata->cs_control = fsl_spi_grlib_cs_control;
559}
560
497static struct spi_master * fsl_spi_probe(struct device *dev, 561static struct spi_master * fsl_spi_probe(struct device *dev,
498 struct resource *mem, unsigned int irq) 562 struct resource *mem, unsigned int irq)
499{ 563{
@@ -528,6 +592,15 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
528 if (ret) 592 if (ret)
529 goto err_cpm_init; 593 goto err_cpm_init;
530 594
595 mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
596 if (mpc8xxx_spi->reg_base == NULL) {
597 ret = -ENOMEM;
598 goto err_ioremap;
599 }
600
601 if (mpc8xxx_spi->type == TYPE_GRLIB)
602 fsl_spi_grlib_probe(dev);
603
531 if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) 604 if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
532 mpc8xxx_spi->set_shifts = fsl_spi_qe_cpu_set_shifts; 605 mpc8xxx_spi->set_shifts = fsl_spi_qe_cpu_set_shifts;
533 606
@@ -536,12 +609,6 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
536 mpc8xxx_spi->set_shifts(&mpc8xxx_spi->rx_shift, 609 mpc8xxx_spi->set_shifts(&mpc8xxx_spi->rx_shift,
537 &mpc8xxx_spi->tx_shift, 8, 1); 610 &mpc8xxx_spi->tx_shift, 8, 1);
538 611
539 mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
540 if (mpc8xxx_spi->reg_base == NULL) {
541 ret = -ENOMEM;
542 goto err_ioremap;
543 }
544
545 /* Register for SPI Interrupt */ 612 /* Register for SPI Interrupt */
546 ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq, 613 ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq,
547 0, "fsl_spi", mpc8xxx_spi); 614 0, "fsl_spi", mpc8xxx_spi);
@@ -706,16 +773,19 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
706 struct device_node *np = ofdev->dev.of_node; 773 struct device_node *np = ofdev->dev.of_node;
707 struct spi_master *master; 774 struct spi_master *master;
708 struct resource mem; 775 struct resource mem;
709 int irq; 776 int irq, type;
710 int ret = -ENOMEM; 777 int ret = -ENOMEM;
711 778
712 ret = of_mpc8xxx_spi_probe(ofdev); 779 ret = of_mpc8xxx_spi_probe(ofdev);
713 if (ret) 780 if (ret)
714 return ret; 781 return ret;
715 782
716 ret = of_fsl_spi_get_chipselects(dev); 783 type = fsl_spi_get_type(&ofdev->dev);
717 if (ret) 784 if (type == TYPE_FSL) {
718 goto err; 785 ret = of_fsl_spi_get_chipselects(dev);
786 if (ret)
787 goto err;
788 }
719 789
720 ret = of_address_to_resource(np, 0, &mem); 790 ret = of_address_to_resource(np, 0, &mem);
721 if (ret) 791 if (ret)
@@ -736,18 +806,22 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
736 return 0; 806 return 0;
737 807
738err: 808err:
739 of_fsl_spi_free_chipselects(dev); 809 if (type == TYPE_FSL)
810 of_fsl_spi_free_chipselects(dev);
740 return ret; 811 return ret;
741} 812}
742 813
743static int of_fsl_spi_remove(struct platform_device *ofdev) 814static int of_fsl_spi_remove(struct platform_device *ofdev)
744{ 815{
816 struct spi_master *master = dev_get_drvdata(&ofdev->dev);
817 struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
745 int ret; 818 int ret;
746 819
747 ret = mpc8xxx_spi_remove(&ofdev->dev); 820 ret = mpc8xxx_spi_remove(&ofdev->dev);
748 if (ret) 821 if (ret)
749 return ret; 822 return ret;
750 of_fsl_spi_free_chipselects(&ofdev->dev); 823 if (mpc8xxx_spi->type == TYPE_FSL)
824 of_fsl_spi_free_chipselects(&ofdev->dev);
751 return 0; 825 return 0;
752} 826}
753 827
diff --git a/drivers/spi/spi-fsl-spi.h b/drivers/spi/spi-fsl-spi.h
index 8bd73a4318ef..9a6dae00e3f3 100644
--- a/drivers/spi/spi-fsl-spi.h
+++ b/drivers/spi/spi-fsl-spi.h
@@ -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
@@ -21,13 +25,15 @@
21 25
22/* SPI Controller registers */ 26/* SPI Controller registers */
23struct fsl_spi_reg { 27struct fsl_spi_reg {
24 u8 res1[0x20]; 28 __be32 cap; /* TYPE_GRLIB specific */
29 u8 res1[0x1C];
25 __be32 mode; 30 __be32 mode;
26 __be32 event; 31 __be32 event;
27 __be32 mask; 32 __be32 mask;
28 __be32 command; 33 __be32 command;
29 __be32 transmit; 34 __be32 transmit;
30 __be32 receive; 35 __be32 receive;
36 __be32 slvsel; /* TYPE_GRLIB specific */
31}; 37};
32 38
33/* SPI Controller mode register definitions */ 39/* SPI Controller mode register definitions */
@@ -43,6 +49,11 @@ struct fsl_spi_reg {
43#define SPMODE_OP (1 << 14) 49#define SPMODE_OP (1 << 14)
44#define SPMODE_CG(x) ((x) << 7) 50#define SPMODE_CG(x) ((x) << 7)
45 51
52/* TYPE_GRLIB SPI Controller capability register definitions */
53#define SPCAP_SSEN(x) (((x) >> 16) & 0x1)
54#define SPCAP_SSSZ(x) (((x) >> 24) & 0xff)
55#define SPCAP_MAXWLEN(x) (((x) >> 20) & 0xf)
56
46/* 57/*
47 * Default for SPI Mode: 58 * Default for SPI Mode:
48 * SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk 59 * SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk