Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Andreas Larsson and committed by
Grant Likely
447b0c7b 8922a366

+103 -15
+1 -1
Documentation/devicetree/bindings/spi/fsl-spi.txt
··· 4 4 - cell-index : QE SPI subblock index. 5 5 0: QE subblock SPI1 6 6 1: QE subblock SPI2 7 - - compatible : should be "fsl,spi". 7 + - compatible : should be "fsl,spi" or "aeroflexgaisler,spictrl". 8 8 - mode : the SPI operation mode, it can be "cpu" or "cpu-qe". 9 9 - reg : Offset and length of the register set for the device 10 10 - interrupts : <a b> where a is the interrupt number and b is a
+1
Documentation/devicetree/bindings/vendor-prefixes.txt
··· 5 5 6 6 ad Avionic Design GmbH 7 7 adi Analog Devices, Inc. 8 + aeroflexgaisler Aeroflex Gaisler AB 8 9 ak Asahi Kasei Corp. 9 10 amcc Applied Micro Circuits Corporation (APM, formally AMCC) 10 11 apm Applied Micro Circuits Corporation (APM)
+3 -1
drivers/spi/Kconfig
··· 236 236 depends on FSL_SOC 237 237 238 238 config SPI_FSL_SPI 239 - bool "Freescale SPI controller" 239 + bool "Freescale SPI controller and Aeroflex Gaisler GRLIB SPI controller" 240 240 depends on OF 241 241 select SPI_FSL_LIB 242 242 select SPI_FSL_CPM if FSL_SOC ··· 244 244 This enables using the Freescale SPI controllers in master mode. 245 245 MPC83xx platform uses the controller in cpu mode or CPM/QE mode. 246 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 250 config SPI_FSL_ESPI 249 251 bool "Freescale eSPI controller"
+86 -12
drivers/spi/spi-fsl-spi.c
··· 10 10 * Copyright (c) 2009 MontaVista Software, Inc. 11 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 17 * This program is free software; you can redistribute it and/or modify it 14 18 * under the terms of the GNU General Public License as published by the 15 19 * Free Software Foundation; either version 2 of the License, or (at your ··· 44 40 #include "spi-fsl-spi.h" 45 41 46 42 #define TYPE_FSL 0 43 + #define TYPE_GRLIB 1 47 44 48 45 struct fsl_spi_match_data { 49 46 int type; ··· 54 49 .type = TYPE_FSL, 55 50 }; 56 51 52 + static struct fsl_spi_match_data of_fsl_spi_grlib_config = { 53 + .type = TYPE_GRLIB, 54 + }; 55 + 57 56 static struct of_device_id of_fsl_spi_match[] = { 58 57 { 59 58 .compatible = "fsl,spi", 60 59 .data = &of_fsl_spi_fsl_config, 60 + }, 61 + { 62 + .compatible = "aeroflexgaisler,spictrl", 63 + .data = &of_fsl_spi_grlib_config, 61 64 }, 62 65 {} 63 66 }; ··· 151 138 } else { 152 139 if (bits_per_word <= 8) 153 140 *rx_shift = 8; 141 + } 142 + } 143 + 144 + static void fsl_spi_grlib_set_shifts(u32 *rx_shift, u32 *tx_shift, 145 + int bits_per_word, int msb_first) 146 + { 147 + *rx_shift = 0; 148 + *tx_shift = 0; 149 + if (bits_per_word <= 16) { 150 + if (msb_first) { 151 + *rx_shift = 16; /* LSB in bit 16 */ 152 + *tx_shift = 32 - bits_per_word; /* MSB in bit 31 */ 153 + } else { 154 + *rx_shift = 16 - bits_per_word; /* MSB in bit 15 */ 155 + } 154 156 } 155 157 } 156 158 ··· 522 494 fsl_spi_cpm_free(mspi); 523 495 } 524 496 497 + static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on) 498 + { 499 + struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); 500 + struct fsl_spi_reg *reg_base = mpc8xxx_spi->reg_base; 501 + u32 slvsel; 502 + u16 cs = spi->chip_select; 503 + 504 + slvsel = mpc8xxx_spi_read_reg(&reg_base->slvsel); 505 + slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs)); 506 + mpc8xxx_spi_write_reg(&reg_base->slvsel, slvsel); 507 + } 508 + 509 + static void fsl_spi_grlib_probe(struct device *dev) 510 + { 511 + struct fsl_spi_platform_data *pdata = dev->platform_data; 512 + struct spi_master *master = dev_get_drvdata(dev); 513 + struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); 514 + struct fsl_spi_reg *reg_base = mpc8xxx_spi->reg_base; 515 + int mbits; 516 + u32 capabilities; 517 + 518 + capabilities = mpc8xxx_spi_read_reg(&reg_base->cap); 519 + 520 + mpc8xxx_spi->set_shifts = fsl_spi_grlib_set_shifts; 521 + mbits = SPCAP_MAXWLEN(capabilities); 522 + if (mbits) 523 + mpc8xxx_spi->max_bits_per_word = mbits + 1; 524 + 525 + master->num_chipselect = 1; /* Allow for an always selected chip */ 526 + if (SPCAP_SSEN(capabilities)) { 527 + master->num_chipselect = SPCAP_SSSZ(capabilities); 528 + mpc8xxx_spi_write_reg(&reg_base->slvsel, 0xffffffff); 529 + } 530 + pdata->cs_control = fsl_spi_grlib_cs_control; 531 + } 532 + 525 533 static struct spi_master * fsl_spi_probe(struct device *dev, 526 534 struct resource *mem, unsigned int irq) 527 535 { ··· 592 528 if (ret) 593 529 goto err_cpm_init; 594 530 531 + mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem)); 532 + if (mpc8xxx_spi->reg_base == NULL) { 533 + ret = -ENOMEM; 534 + goto err_ioremap; 535 + } 536 + 537 + if (mpc8xxx_spi->type == TYPE_GRLIB) 538 + fsl_spi_grlib_probe(dev); 539 + 595 540 if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) 596 541 mpc8xxx_spi->set_shifts = fsl_spi_qe_cpu_set_shifts; 597 542 ··· 608 535 /* 8 bits per word and MSB first */ 609 536 mpc8xxx_spi->set_shifts(&mpc8xxx_spi->rx_shift, 610 537 &mpc8xxx_spi->tx_shift, 8, 1); 611 - 612 - mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem)); 613 - if (mpc8xxx_spi->reg_base == NULL) { 614 - ret = -ENOMEM; 615 - goto err_ioremap; 616 - } 617 538 618 539 /* Register for SPI Interrupt */ 619 540 ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq, ··· 773 706 struct device_node *np = ofdev->dev.of_node; 774 707 struct spi_master *master; 775 708 struct resource mem; 776 - int irq; 709 + int irq, type; 777 710 int ret = -ENOMEM; 778 711 779 712 ret = of_mpc8xxx_spi_probe(ofdev); 780 713 if (ret) 781 714 return ret; 782 715 783 - ret = of_fsl_spi_get_chipselects(dev); 784 - if (ret) 785 - goto err; 716 + type = fsl_spi_get_type(&ofdev->dev); 717 + if (type == TYPE_FSL) { 718 + ret = of_fsl_spi_get_chipselects(dev); 719 + if (ret) 720 + goto err; 721 + } 786 722 787 723 ret = of_address_to_resource(np, 0, &mem); 788 724 if (ret) ··· 806 736 return 0; 807 737 808 738 err: 809 - of_fsl_spi_free_chipselects(dev); 739 + if (type == TYPE_FSL) 740 + of_fsl_spi_free_chipselects(dev); 810 741 return ret; 811 742 } 812 743 813 744 static int of_fsl_spi_remove(struct platform_device *ofdev) 814 745 { 746 + struct spi_master *master = dev_get_drvdata(&ofdev->dev); 747 + struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); 815 748 int ret; 816 749 817 750 ret = mpc8xxx_spi_remove(&ofdev->dev); 818 751 if (ret) 819 752 return ret; 820 - of_fsl_spi_free_chipselects(&ofdev->dev); 753 + if (mpc8xxx_spi->type == TYPE_FSL) 754 + of_fsl_spi_free_chipselects(&ofdev->dev); 821 755 return 0; 822 756 } 823 757
+12 -1
drivers/spi/spi-fsl-spi.h
··· 10 10 * Copyright (c) 2009 MontaVista Software, Inc. 11 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 17 * This program is free software; you can redistribute it and/or modify it 14 18 * under the terms of the GNU General Public License as published by the 15 19 * Free Software Foundation; either version 2 of the License, or (at your ··· 25 21 26 22 /* SPI Controller registers */ 27 23 struct fsl_spi_reg { 28 - u8 res1[0x20]; 24 + __be32 cap; /* TYPE_GRLIB specific */ 25 + u8 res1[0x1C]; 29 26 __be32 mode; 30 27 __be32 event; 31 28 __be32 mask; 32 29 __be32 command; 33 30 __be32 transmit; 34 31 __be32 receive; 32 + __be32 slvsel; /* TYPE_GRLIB specific */ 35 33 }; 36 34 37 35 /* SPI Controller mode register definitions */ ··· 48 42 #define SPMODE_PM(x) ((x) << 16) 49 43 #define SPMODE_OP (1 << 14) 50 44 #define SPMODE_CG(x) ((x) << 7) 45 + 46 + /* TYPE_GRLIB SPI Controller capability register definitions */ 47 + #define SPCAP_SSEN(x) (((x) >> 16) & 0x1) 48 + #define SPCAP_SSSZ(x) (((x) >> 24) & 0xff) 49 + #define SPCAP_MAXWLEN(x) (((x) >> 20) & 0xf) 51 50 52 51 /* 53 52 * Default for SPI Mode: