diff options
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/Kconfig | 4 | ||||
-rw-r--r-- | drivers/spi/spi-fsl-spi.c | 98 | ||||
-rw-r--r-- | drivers/spi/spi-fsl-spi.h | 13 |
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 | ||
238 | config SPI_FSL_SPI | 238 | config 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 | ||
248 | config SPI_FSL_ESPI | 250 | config 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 | ||
44 | struct fsl_spi_match_data { | 49 | struct 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 | ||
57 | static struct fsl_spi_match_data of_fsl_spi_grlib_config = { | ||
58 | .type = TYPE_GRLIB, | ||
59 | }; | ||
60 | |||
52 | static struct of_device_id of_fsl_spi_match[] = { | 61 | static 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 | }; |
59 | MODULE_DEVICE_TABLE(of, of_fsl_spi_match); | 72 | MODULE_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 | ||
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 | |||
144 | 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, |
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 | ||
525 | static 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(®_base->slvsel); | ||
533 | slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs)); | ||
534 | mpc8xxx_spi_write_reg(®_base->slvsel, slvsel); | ||
535 | } | ||
536 | |||
537 | static 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(®_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(®_base->slvsel, 0xffffffff); | ||
557 | } | ||
558 | pdata->cs_control = fsl_spi_grlib_cs_control; | ||
559 | } | ||
560 | |||
497 | static struct spi_master * fsl_spi_probe(struct device *dev, | 561 | static 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 | ||
738 | err: | 808 | err: |
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 | ||
743 | static int of_fsl_spi_remove(struct platform_device *ofdev) | 814 | static 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 */ |
23 | struct fsl_spi_reg { | 27 | struct 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 |