Commit 6beb9fec authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'spi/topic/acpi', 'spi/topic/axi-engine',...

Merge remote-tracking branches 'spi/topic/acpi', 'spi/topic/axi-engine', 'spi/topic/bcm2835' and 'spi/topic/bcm2835aux' into spi-next
Analog Devices AXI SPI Engine controller Device Tree Bindings
Required properties:
- compatible : Must be "adi,axi-spi-engine-1.00.a""
- reg : Physical base address and size of the register map.
- interrupts : Property with a value describing the interrupt
number.
- clock-names : List of input clock names - "s_axi_aclk", "spi_clk"
- clocks : Clock phandles and specifiers (See clock bindings for
details on clock-names and clocks).
- #address-cells : Must be <1>
- #size-cells : Must be <0>
Optional subnodes:
Subnodes are use to represent the SPI slave devices connected to the SPI
master. They follow the generic SPI bindings as outlined in spi-bus.txt.
Example:
spi@@44a00000 {
compatible = "adi,axi-spi-engine-1.00.a";
reg = <0x44a00000 0x1000>;
interrupts = <0 56 4>;
clocks = <&clkc 15 &clkc 15>;
clock-names = "s_axi_aclk", "spi_clk";
#address-cells = <1>;
#size-cells = <0>;
/* SPI devices */
};
...@@ -75,11 +75,26 @@ config SPI_ATMEL ...@@ -75,11 +75,26 @@ config SPI_ATMEL
This selects a driver for the Atmel SPI Controller, present on This selects a driver for the Atmel SPI Controller, present on
many AT32 (AVR32) and AT91 (ARM) chips. many AT32 (AVR32) and AT91 (ARM) chips.
config SPI_AU1550
tristate "Au1550/Au1200/Au1300 SPI Controller"
depends on MIPS_ALCHEMY
select SPI_BITBANG
help
If you say yes to this option, support will be included for the
PSC SPI controller found on Au1550, Au1200 and Au1300 series.
config SPI_AXI_SPI_ENGINE
tristate "Analog Devices AXI SPI Engine controller"
depends on HAS_IOMEM
help
This enables support for the Analog Devices AXI SPI Engine SPI controller.
It is part of the SPI Engine framework that is used in some Analog Devices
reference designs for FPGAs.
config SPI_BCM2835 config SPI_BCM2835
tristate "BCM2835 SPI controller" tristate "BCM2835 SPI controller"
depends on GPIOLIB depends on GPIOLIB
depends on ARCH_BCM2835 || COMPILE_TEST depends on ARCH_BCM2835 || COMPILE_TEST
depends on GPIOLIB
help help
This selects a driver for the Broadcom BCM2835 SPI master. This selects a driver for the Broadcom BCM2835 SPI master.
...@@ -90,8 +105,7 @@ config SPI_BCM2835 ...@@ -90,8 +105,7 @@ config SPI_BCM2835
config SPI_BCM2835AUX config SPI_BCM2835AUX
tristate "BCM2835 SPI auxiliary controller" tristate "BCM2835 SPI auxiliary controller"
depends on ARCH_BCM2835 || COMPILE_TEST depends on (ARCH_BCM2835 && GPIOLIB) || COMPILE_TEST
depends on GPIOLIB
help help
This selects a driver for the Broadcom BCM2835 SPI aux master. This selects a driver for the Broadcom BCM2835 SPI aux master.
...@@ -118,14 +132,6 @@ config SPI_BFIN_SPORT ...@@ -118,14 +132,6 @@ config SPI_BFIN_SPORT
help help
Enable support for a SPI bus via the Blackfin SPORT peripheral. Enable support for a SPI bus via the Blackfin SPORT peripheral.
config SPI_AU1550
tristate "Au1550/Au1200/Au1300 SPI Controller"
depends on MIPS_ALCHEMY
select SPI_BITBANG
help
If you say yes to this option, support will be included for the
PSC SPI controller found on Au1550, Au1200 and Au1300 series.
config SPI_BCM53XX config SPI_BCM53XX
tristate "Broadcom BCM53xx SPI controller" tristate "Broadcom BCM53xx SPI controller"
depends on ARCH_BCM_5301X depends on ARCH_BCM_5301X
...@@ -197,6 +203,23 @@ config SPI_DAVINCI ...@@ -197,6 +203,23 @@ config SPI_DAVINCI
help help
SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules. SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
config SPI_DESIGNWARE
tristate "DesignWare SPI controller core support"
help
general driver for SPI controller core from DesignWare
config SPI_DW_PCI
tristate "PCI interface driver for DW SPI core"
depends on SPI_DESIGNWARE && PCI
config SPI_DW_MID_DMA
bool "DMA support for DW SPI controller on Intel MID platform"
depends on SPI_DW_PCI && DW_DMAC_PCI
config SPI_DW_MMIO
tristate "Memory-mapped io interface driver for DW SPI core"
depends on SPI_DESIGNWARE
config SPI_DLN2 config SPI_DLN2
tristate "Diolan DLN-2 USB SPI adapter" tristate "Diolan DLN-2 USB SPI adapter"
depends on MFD_DLN2 depends on MFD_DLN2
...@@ -346,6 +369,13 @@ config SPI_MT65XX ...@@ -346,6 +369,13 @@ config SPI_MT65XX
say Y or M here.If you are not sure, say N. say Y or M here.If you are not sure, say N.
SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs. SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs.
config SPI_NUC900
tristate "Nuvoton NUC900 series SPI"
depends on ARCH_W90X900
select SPI_BITBANG
help
SPI driver for Nuvoton NUC900 series ARM SoCs
config SPI_OC_TINY config SPI_OC_TINY
tristate "OpenCores tiny SPI" tristate "OpenCores tiny SPI"
depends on GPIOLIB || COMPILE_TEST depends on GPIOLIB || COMPILE_TEST
...@@ -647,34 +677,10 @@ config SPI_ZYNQMP_GQSPI ...@@ -647,34 +677,10 @@ config SPI_ZYNQMP_GQSPI
help help
Enables Xilinx GQSPI controller driver for Zynq UltraScale+ MPSoC. Enables Xilinx GQSPI controller driver for Zynq UltraScale+ MPSoC.
config SPI_NUC900
tristate "Nuvoton NUC900 series SPI"
depends on ARCH_W90X900
select SPI_BITBANG
help
SPI driver for Nuvoton NUC900 series ARM SoCs
# #
# Add new SPI master controllers in alphabetical order above this line # Add new SPI master controllers in alphabetical order above this line
# #
config SPI_DESIGNWARE
tristate "DesignWare SPI controller core support"
help
general driver for SPI controller core from DesignWare
config SPI_DW_PCI
tristate "PCI interface driver for DW SPI core"
depends on SPI_DESIGNWARE && PCI
config SPI_DW_MID_DMA
bool "DMA support for DW SPI controller on Intel MID platform"
depends on SPI_DW_PCI && DW_DMAC_PCI
config SPI_DW_MMIO
tristate "Memory-mapped io interface driver for DW SPI core"
depends on SPI_DESIGNWARE
# #
# There are lots of SPI device types, with sensors and memory # There are lots of SPI device types, with sensors and memory
# being probably the most widely used ones. # being probably the most widely used ones.
......
...@@ -15,6 +15,7 @@ obj-$(CONFIG_SPI_ALTERA) += spi-altera.o ...@@ -15,6 +15,7 @@ obj-$(CONFIG_SPI_ALTERA) += spi-altera.o
obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o
obj-$(CONFIG_SPI_ATH79) += spi-ath79.o obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
obj-$(CONFIG_SPI_AU1550) += spi-au1550.o obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
obj-$(CONFIG_SPI_AXI_SPI_ENGINE) += spi-axi-spi-engine.o
obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o
obj-$(CONFIG_SPI_BCM2835AUX) += spi-bcm2835aux.o obj-$(CONFIG_SPI_BCM2835AUX) += spi-bcm2835aux.o
obj-$(CONFIG_SPI_BCM53XX) += spi-bcm53xx.o obj-$(CONFIG_SPI_BCM53XX) += spi-bcm53xx.o
......
This diff is collapsed.
...@@ -727,11 +727,6 @@ static int bcm2835_spi_setup(struct spi_device *spi) ...@@ -727,11 +727,6 @@ static int bcm2835_spi_setup(struct spi_device *spi)
spi->chip_select, spi->cs_gpio, err); spi->chip_select, spi->cs_gpio, err);
return err; return err;
} }
/* the implementation of pinctrl-bcm2835 currently does not
* set the GPIO value when using gpio_direction_output
* so we are setting it here explicitly
*/
gpio_set_value(spi->cs_gpio, (spi->mode & SPI_CS_HIGH) ? 0 : 1);
return 0; return 0;
} }
......
...@@ -64,9 +64,9 @@ ...@@ -64,9 +64,9 @@
#define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH 0x00004000 #define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH 0x00004000
#define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000 #define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000
#define BCM2835_AUX_SPI_CNTL0_ENABLE 0x00000800 #define BCM2835_AUX_SPI_CNTL0_ENABLE 0x00000800
#define BCM2835_AUX_SPI_CNTL0_CPHA_IN 0x00000400 #define BCM2835_AUX_SPI_CNTL0_IN_RISING 0x00000400
#define BCM2835_AUX_SPI_CNTL0_CLEARFIFO 0x00000200 #define BCM2835_AUX_SPI_CNTL0_CLEARFIFO 0x00000200
#define BCM2835_AUX_SPI_CNTL0_CPHA_OUT 0x00000100 #define BCM2835_AUX_SPI_CNTL0_OUT_RISING 0x00000100
#define BCM2835_AUX_SPI_CNTL0_CPOL 0x00000080 #define BCM2835_AUX_SPI_CNTL0_CPOL 0x00000080
#define BCM2835_AUX_SPI_CNTL0_MSBF_OUT 0x00000040 #define BCM2835_AUX_SPI_CNTL0_MSBF_OUT 0x00000040
#define BCM2835_AUX_SPI_CNTL0_SHIFTLEN 0x0000003F #define BCM2835_AUX_SPI_CNTL0_SHIFTLEN 0x0000003F
...@@ -92,9 +92,6 @@ ...@@ -92,9 +92,6 @@
#define BCM2835_AUX_SPI_POLLING_LIMIT_US 30 #define BCM2835_AUX_SPI_POLLING_LIMIT_US 30
#define BCM2835_AUX_SPI_POLLING_JIFFIES 2 #define BCM2835_AUX_SPI_POLLING_JIFFIES 2
#define BCM2835_AUX_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
| SPI_NO_CS)
struct bcm2835aux_spi { struct bcm2835aux_spi {
void __iomem *regs; void __iomem *regs;
struct clk *clk; struct clk *clk;
...@@ -212,9 +209,15 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id) ...@@ -212,9 +209,15 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
} }
/* and if rx_len is 0 then wake up completion and disable spi */ if (!bs->tx_len) {
/* disable tx fifo empty interrupt */
bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] |
BCM2835_AUX_SPI_CNTL1_IDLE);
}
/* and if rx_len is 0 then disable interrupts and wake up completion */
if (!bs->rx_len) { if (!bs->rx_len) {
bcm2835aux_spi_reset_hw(bs); bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
complete(&master->xfer_completion); complete(&master->xfer_completion);
} }
...@@ -307,9 +310,6 @@ static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master, ...@@ -307,9 +310,6 @@ static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master,
} }
} }
/* Transfer complete - reset SPI HW */
bcm2835aux_spi_reset_hw(bs);
/* and return without waiting for completion */ /* and return without waiting for completion */
return 0; return 0;
} }
...@@ -330,10 +330,6 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, ...@@ -330,10 +330,6 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
* resulting (potentially) in more interrupts when transferring * resulting (potentially) in more interrupts when transferring
* more than 12 bytes * more than 12 bytes
*/ */
bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE |
BCM2835_AUX_SPI_CNTL0_VAR_WIDTH |
BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN;
/* set clock */ /* set clock */
spi_hz = tfr->speed_hz; spi_hz = tfr->speed_hz;
...@@ -348,17 +344,13 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, ...@@ -348,17 +344,13 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
} else { /* the slowest we can go */ } else { /* the slowest we can go */
speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX; speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
} }
/* mask out old speed from previous spi_transfer */
bs->cntl[0] &= ~(BCM2835_AUX_SPI_CNTL0_SPEED);
/* set the new speed */
bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT; bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT;
spi_used_hz = clk_hz / (2 * (speed + 1)); spi_used_hz = clk_hz / (2 * (speed + 1));
/* handle all the modes */
if (spi->mode & SPI_CPOL)
bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL;
if (spi->mode & SPI_CPHA)
bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPHA_OUT |
BCM2835_AUX_SPI_CNTL0_CPHA_IN;
/* set transmit buffers and length */ /* set transmit buffers and length */
bs->tx_buf = tfr->tx_buf; bs->tx_buf = tfr->tx_buf;
bs->rx_buf = tfr->rx_buf; bs->rx_buf = tfr->rx_buf;
...@@ -382,6 +374,40 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, ...@@ -382,6 +374,40 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
return bcm2835aux_spi_transfer_one_irq(master, spi, tfr); return bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
} }
static int bcm2835aux_spi_prepare_message(struct spi_master *master,
struct spi_message *msg)
{
struct spi_device *spi = msg->spi;
struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE |
BCM2835_AUX_SPI_CNTL0_VAR_WIDTH |
BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN;
/* handle all the modes */
if (spi->mode & SPI_CPOL) {
bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL;
bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_OUT_RISING;
} else {
bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_IN_RISING;
}
bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
return 0;
}
static int bcm2835aux_spi_unprepare_message(struct spi_master *master,
struct spi_message *msg)
{
struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
bcm2835aux_spi_reset_hw(bs);
return 0;
}
static void bcm2835aux_spi_handle_err(struct spi_master *master, static void bcm2835aux_spi_handle_err(struct spi_master *master,
struct spi_message *msg) struct spi_message *msg)
{ {
...@@ -405,11 +431,13 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) ...@@ -405,11 +431,13 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
} }
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
master->mode_bits = BCM2835_AUX_SPI_MODE_BITS; master->mode_bits = (SPI_CPOL | SPI_CS_HIGH | SPI_NO_CS);
master->bits_per_word_mask = SPI_BPW_MASK(8); master->bits_per_word_mask = SPI_BPW_MASK(8);
master->num_chipselect = -1; master->num_chipselect = -1;
master->transfer_one = bcm2835aux_spi_transfer_one; master->transfer_one = bcm2835aux_spi_transfer_one;
master->handle_err = bcm2835aux_spi_handle_err; master->handle_err = bcm2835aux_spi_handle_err;
master->prepare_message = bcm2835aux_spi_prepare_message;
master->unprepare_message = bcm2835aux_spi_unprepare_message;
master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
bs = spi_master_get_devdata(master); bs = spi_master_get_devdata(master);
......
...@@ -1589,13 +1589,30 @@ static void of_register_spi_devices(struct spi_master *master) { } ...@@ -1589,13 +1589,30 @@ static void of_register_spi_devices(struct spi_master *master) { }
static int acpi_spi_add_resource(struct acpi_resource *ares, void *data) static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
{ {
struct spi_device *spi = data; struct spi_device *spi = data;
struct spi_master *master = spi->master;
if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
struct acpi_resource_spi_serialbus *sb; struct acpi_resource_spi_serialbus *sb;
sb = &ares->data.spi_serial_bus; sb = &ares->data.spi_serial_bus;
if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_SPI) { if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_SPI) {
/*
* ACPI DeviceSelection numbering is handled by the
* host controller driver in Windows and can vary
* from driver to driver. In Linux we always expect
* 0 .. max - 1 so we need to ask the driver to
* translate between the two schemes.
*/
if (master->fw_translate_cs) {
int cs = master->fw_translate_cs(master,
sb->device_selection);
if (cs < 0)
return cs;
spi->chip_select = cs;
} else {
spi->chip_select = sb->device_selection; spi->chip_select = sb->device_selection;
}
spi->max_speed_hz = sb->connection_speed; spi->max_speed_hz = sb->connection_speed;
if (sb->clock_phase == ACPI_SPI_SECOND_PHASE) if (sb->clock_phase == ACPI_SPI_SECOND_PHASE)
......
...@@ -372,6 +372,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) ...@@ -372,6 +372,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
* @dma_rx: DMA receive channel * @dma_rx: DMA receive channel
* @dummy_rx: dummy receive buffer for full-duplex devices * @dummy_rx: dummy receive buffer for full-duplex devices
* @dummy_tx: dummy transmit buffer for full-duplex devices * @dummy_tx: dummy transmit buffer for full-duplex devices
* @fw_translate_cs: If the boot firmware uses different numbering scheme
* what Linux expects, this optional hook can be used to translate
* between the two.
* *
* Each SPI master controller can communicate with one or more @spi_device * Each SPI master controller can communicate with one or more @spi_device
* children. These make a small bus, sharing MOSI, MISO and SCK signals * children. These make a small bus, sharing MOSI, MISO and SCK signals
...@@ -542,6 +545,8 @@ struct spi_master { ...@@ -542,6 +545,8 @@ struct spi_master {
/* dummy data for full duplex devices */ /* dummy data for full duplex devices */
void *dummy_rx; void *dummy_rx;
void *dummy_tx; void *dummy_tx;
int (*fw_translate_cs)(struct spi_master *master, unsigned cs);
}; };
static inline void *spi_master_get_devdata(struct spi_master *master) static inline void *spi_master_get_devdata(struct spi_master *master)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment