Commit e5aeced6 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'spi-v4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi

Pull spi updates from Mark Brown:
 "A few core tweaks this time together with the usual collection of
  driver specific updates and fixes plus a larger than average selection
  of new device support:

   - fix DMA mapping of unaligned vmalloc() buffers

   - statistics tracking transfer volumes exposed via sysfs

   - new drivers for Freescale MPC5125, Intel Sunrise Point, Mediatek
     SoCs, and Netlogic XLP SoCs"

* tag 'spi-v4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (66 commits)
  spi: sh-msiof: Fix FIFO size to 64 word from 256 word
  spi: fsl-(e)spi: Fix checking return value of devm_ioremap_resource
  spi: Add DT bindings documentation for Netlogic XLP SPI controller
  spi/xlp: SPI controller driver for Netlogic XLP SoCs
  spi: fsl-espi: add runtime PM
  spi: fsl-(e)spi: simplify cleanup code
  spi: fsl-(e)spi: migrate to using devm_ functions to simplify cleanup
  spi: mediatek: fix SPI_CMD_PAUSE_IE macro error
  spi: check bits_per_word in spi_setup
  spi: mediatek: replace *_time name
  spi: mediatek: add PM clk_prepare_enable fail flow
  spi: mediatek: replace int with u32, delete TAB and define MTK_SPI_PAUSE_INT_STATUS marco
  spi: mediatek: add linux/io.h include file
  spi/bcm63xx-hsspi: add support for dual spi read/write
  spi: dw: Allow interface drivers to limit data I/O to word sizes
  dt: snps,dw-apb-ssi: Document new I/O data register width property
  spi: Fall back to master maximum speed if no slave speed specified
  spi: mediatek: use BIT() to instead of SPI_CMD_*_OFFSET
  spi: medaitek: revise quirks compatibility style
  spi: mediatek: fix spi incorrect endian usage
  ...
parents cf9d615f c5992f61
...@@ -6,14 +6,14 @@ PSC in UART mode ...@@ -6,14 +6,14 @@ PSC in UART mode
For PSC in UART mode the needed PSC serial devices For PSC in UART mode the needed PSC serial devices
are specified by fsl,mpc5121-psc-uart nodes in the are specified by fsl,mpc5121-psc-uart nodes in the
fsl,mpc5121-immr SoC node. Additionally the PSC FIFO fsl,mpc5121-immr SoC node. Additionally the PSC FIFO
Controller node fsl,mpc5121-psc-fifo is requered there: Controller node fsl,mpc5121-psc-fifo is required there:
fsl,mpc5121-psc-uart nodes fsl,mpc512x-psc-uart nodes
-------------------------- --------------------------
Required properties : Required properties :
- compatible : Should contain "fsl,mpc5121-psc-uart" and "fsl,mpc5121-psc" - compatible : Should contain "fsl,<soc>-psc-uart" and "fsl,<soc>-psc"
- cell-index : Index of the PSC in hardware Supported <soc>s: mpc5121, mpc5125
- reg : Offset and length of the register set for the PSC device - reg : Offset and length of the register set for the PSC device
- interrupts : <a b> where a is the interrupt number of the - interrupts : <a b> where a is the interrupt number of the
PSC FIFO Controller and b is a field that represents an PSC FIFO Controller and b is a field that represents an
...@@ -25,12 +25,21 @@ Recommended properties : ...@@ -25,12 +25,21 @@ Recommended properties :
- fsl,rx-fifo-size : the size of the RX fifo slice (a multiple of 4) - fsl,rx-fifo-size : the size of the RX fifo slice (a multiple of 4)
- fsl,tx-fifo-size : the size of the TX fifo slice (a multiple of 4) - fsl,tx-fifo-size : the size of the TX fifo slice (a multiple of 4)
PSC in SPI mode
---------------
fsl,mpc5121-psc-fifo node Similar to the UART mode a PSC can be operated in SPI mode. The compatible used
for that is fsl,mpc5121-psc-spi. It requires a fsl,mpc5121-psc-fifo as well.
The required and recommended properties are identical to the
fsl,mpc5121-psc-uart nodes, just use spi instead of uart in the compatible
string.
fsl,mpc512x-psc-fifo node
------------------------- -------------------------
Required properties : Required properties :
- compatible : Should be "fsl,mpc5121-psc-fifo" - compatible : Should be "fsl,<soc>-psc-fifo"
Supported <soc>s: mpc5121, mpc5125
- reg : Offset and length of the register set for the PSC - reg : Offset and length of the register set for the PSC
FIFO Controller FIFO Controller
- interrupts : <a b> where a is the interrupt number of the - interrupts : <a b> where a is the interrupt number of the
...@@ -39,6 +48,9 @@ Required properties : ...@@ -39,6 +48,9 @@ Required properties :
- interrupt-parent : the phandle for the interrupt controller that - interrupt-parent : the phandle for the interrupt controller that
services interrupts for this device. services interrupts for this device.
Recommended properties :
- clocks : specifies the clock needed to operate the fifo controller
- clock-names : name(s) for the clock(s) listed in clocks
Example for a board using PSC0 and PSC1 devices in serial mode: Example for a board using PSC0 and PSC1 devices in serial mode:
......
...@@ -10,6 +10,8 @@ Required properties: ...@@ -10,6 +10,8 @@ Required properties:
Optional properties: Optional properties:
- cs-gpios : Specifies the gpio pis to be used for chipselects. - cs-gpios : Specifies the gpio pis to be used for chipselects.
- num-cs : The number of chipselects. If omitted, this will default to 4. - num-cs : The number of chipselects. If omitted, this will default to 4.
- reg-io-width : The I/O register width (in bytes) implemented by this
device. Supported values are 2 or 4 (the default).
Child nodes as per the generic SPI binding. Child nodes as per the generic SPI binding.
......
...@@ -12,6 +12,8 @@ Required properties: ...@@ -12,6 +12,8 @@ Required properties:
- compatible: - compatible:
- "ti,dm6441-spi" for SPI used similar to that on DM644x SoC family - "ti,dm6441-spi" for SPI used similar to that on DM644x SoC family
- "ti,da830-spi" for SPI used similar to that on DA8xx SoC family - "ti,da830-spi" for SPI used similar to that on DA8xx SoC family
- "ti,keystone-spi" for SPI used similar to that on Keystone2 SoC
family
- reg: Offset and length of SPI controller register space - reg: Offset and length of SPI controller register space
- num-cs: Number of chip selects. This includes internal as well as - num-cs: Number of chip selects. This includes internal as well as
GPIO chip selects. GPIO chip selects.
......
...@@ -21,6 +21,7 @@ Required properties: ...@@ -21,6 +21,7 @@ Required properties:
Optional properties: Optional properties:
- img,supports-quad-mode: Should be set if the interface supports quad mode - img,supports-quad-mode: Should be set if the interface supports quad mode
SPI transfers. SPI transfers.
- spfi-max-frequency: Maximum speed supported by the spfi block.
Example: Example:
......
Binding for MTK SPI controller
Required properties:
- compatible: should be one of the following.
- mediatek,mt8173-spi: for mt8173 platforms
- mediatek,mt8135-spi: for mt8135 platforms
- mediatek,mt6589-spi: for mt6589 platforms
- #address-cells: should be 1.
- #size-cells: should be 0.
- reg: Address and length of the register set for the device
- interrupts: Should contain spi interrupt
- clocks: phandles to input clocks.
The first should be <&topckgen CLK_TOP_SPI_SEL>.
The second should be one of the following.
- <&clk26m>: specify parent clock 26MHZ.
- <&topckgen CLK_TOP_SYSPLL3_D2>: specify parent clock 109MHZ.
It's the default one.
- <&topckgen CLK_TOP_SYSPLL4_D2>: specify parent clock 78MHZ.
- <&topckgen CLK_TOP_UNIVPLL2_D4>: specify parent clock 104MHZ.
- <&topckgen CLK_TOP_UNIVPLL1_D8>: specify parent clock 78MHZ.
- clock-names: shall be "spi-clk" for the controller clock, and
"parent-clk" for the parent clock.
Optional properties:
- mediatek,pad-select: specify which pins group(ck/mi/mo/cs) spi
controller used, this value should be 0~3, only required for MT8173.
0: specify GPIO69,70,71,72 for spi pins.
1: specify GPIO102,103,104,105 for spi pins.
2: specify GPIO128,129,130,131 for spi pins.
3: specify GPIO5,6,7,8 for spi pins.
Example:
- SoC Specific Portion:
spi: spi@1100a000 {
compatible = "mediatek,mt8173-spi";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x1100a000 0 0x1000>;
interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_LOW>;
clocks = <&topckgen CLK_TOP_SPI_SEL>, <&topckgen CLK_TOP_SYSPLL3_D2>;
clock-names = "spi-clk", "parent-clk";
mediatek,pad-select = <0>;
status = "disabled";
};
SPI Master controller for Netlogic XLP MIPS64 SOCs
==================================================
Currently this SPI controller driver is supported for the following
Netlogic XLP SoCs:
XLP832, XLP316, XLP208, XLP980, XLP532
Required properties:
- compatible : Should be "netlogic,xlp832-spi".
- #address-cells : Number of cells required to define a chip select address
on the SPI bus.
- #size-cells : Should be zero.
- reg : Should contain register location and length.
- clocks : Phandle of the spi clock
- interrupts : Interrupt number used by this controller.
- interrupt-parent : Phandle of the parent interrupt controller.
SPI slave nodes must be children of the SPI master node and can contain
properties described in Documentation/devicetree/bindings/spi/spi-bus.txt.
Example:
spi: xlp_spi@3a100 {
compatible = "netlogic,xlp832-spi";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x3a100 0x100>;
clocks = <&spi_clk>;
interrupts = <34>;
interrupt-parent = <&pic>;
spi_nor@1 {
compatible = "spansion,s25sl12801";
#address-cells = <1>;
#size-cells = <1>;
reg = <1>; /* Chip Select */
spi-max-frequency = <40000000>;
};
};
...@@ -1010,11 +1010,13 @@ static struct davinci_spi_platform_data da8xx_spi_pdata[] = { ...@@ -1010,11 +1010,13 @@ static struct davinci_spi_platform_data da8xx_spi_pdata[] = {
.version = SPI_VERSION_2, .version = SPI_VERSION_2,
.intr_line = 1, .intr_line = 1,
.dma_event_q = EVENTQ_0, .dma_event_q = EVENTQ_0,
.prescaler_limit = 2,
}, },
[1] = { [1] = {
.version = SPI_VERSION_2, .version = SPI_VERSION_2,
.intr_line = 1, .intr_line = 1,
.dma_event_q = EVENTQ_0, .dma_event_q = EVENTQ_0,
.prescaler_limit = 2,
}, },
}; };
......
...@@ -411,6 +411,7 @@ static struct davinci_spi_platform_data dm355_spi0_pdata = { ...@@ -411,6 +411,7 @@ static struct davinci_spi_platform_data dm355_spi0_pdata = {
.num_chipselect = 2, .num_chipselect = 2,
.cshold_bug = true, .cshold_bug = true,
.dma_event_q = EVENTQ_1, .dma_event_q = EVENTQ_1,
.prescaler_limit = 1,
}; };
static struct platform_device dm355_spi0_device = { static struct platform_device dm355_spi0_device = {
.name = "spi_davinci", .name = "spi_davinci",
......
...@@ -646,6 +646,7 @@ static struct davinci_spi_platform_data dm365_spi0_pdata = { ...@@ -646,6 +646,7 @@ static struct davinci_spi_platform_data dm365_spi0_pdata = {
.version = SPI_VERSION_1, .version = SPI_VERSION_1,
.num_chipselect = 2, .num_chipselect = 2,
.dma_event_q = EVENTQ_3, .dma_event_q = EVENTQ_3,
.prescaler_limit = 1,
}; };
static struct resource dm365_spi0_resources[] = { static struct resource dm365_spi0_resources[] = {
......
...@@ -150,7 +150,10 @@ ...@@ -150,7 +150,10 @@
/* Structure of the hardware registers */ /* Structure of the hardware registers */
struct mpc52xx_psc { struct mpc52xx_psc {
u8 mode; /* PSC + 0x00 */ union {
u8 mode; /* PSC + 0x00 */
u8 mr2;
};
u8 reserved0[3]; u8 reserved0[3];
union { /* PSC + 0x04 */ union { /* PSC + 0x04 */
u16 status; u16 status;
......
...@@ -326,6 +326,15 @@ config SPI_MESON_SPIFC ...@@ -326,6 +326,15 @@ config SPI_MESON_SPIFC
This enables master mode support for the SPIFC (SPI flash This enables master mode support for the SPIFC (SPI flash
controller) available in Amlogic Meson SoCs. controller) available in Amlogic Meson SoCs.
config SPI_MT65XX
tristate "MediaTek SPI controller"
depends on ARCH_MEDIATEK || COMPILE_TEST
help
This selects the MediaTek(R) SPI bus driver.
If you want to use MediaTek(R) SPI interface,
say Y or M here.If you are not sure, say N.
SPI drivers for Mediatek MT65XX and MT81XX 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
...@@ -598,6 +607,17 @@ config SPI_XILINX ...@@ -598,6 +607,17 @@ config SPI_XILINX
Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)" Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)"
config SPI_XLP
tristate "Netlogic XLP SPI controller driver"
depends on CPU_XLP || COMPILE_TEST
help
Enable support for the SPI controller on the Netlogic XLP SoCs.
Currently supported XLP variants are XLP8XX, XLP3XX, XLP2XX, XLP9XX
and XLP5XX.
If you have a Netlogic XLP platform say Y here.
If unsure, say N.
config SPI_XTENSA_XTFPGA config SPI_XTENSA_XTFPGA
tristate "Xtensa SPI controller for xtfpga" tristate "Xtensa SPI controller for xtfpga"
depends on (XTENSA && XTENSA_PLATFORM_XTFPGA) || COMPILE_TEST depends on (XTENSA && XTENSA_PLATFORM_XTFPGA) || COMPILE_TEST
......
...@@ -48,6 +48,7 @@ obj-$(CONFIG_SPI_MESON_SPIFC) += spi-meson-spifc.o ...@@ -48,6 +48,7 @@ obj-$(CONFIG_SPI_MESON_SPIFC) += spi-meson-spifc.o
obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o
obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o
obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o
obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o
obj-$(CONFIG_SPI_MXS) += spi-mxs.o obj-$(CONFIG_SPI_MXS) += spi-mxs.o
obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o
obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o
...@@ -88,5 +89,6 @@ obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o ...@@ -88,5 +89,6 @@ obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o
obj-$(CONFIG_SPI_TXX9) += spi-txx9.o obj-$(CONFIG_SPI_TXX9) += spi-txx9.o
obj-$(CONFIG_SPI_XCOMM) += spi-xcomm.o obj-$(CONFIG_SPI_XCOMM) += spi-xcomm.o
obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o
obj-$(CONFIG_SPI_XLP) += spi-xlp.o
obj-$(CONFIG_SPI_XTENSA_XTFPGA) += spi-xtensa-xtfpga.o obj-$(CONFIG_SPI_XTENSA_XTFPGA) += spi-xtensa-xtfpga.o
obj-$(CONFIG_SPI_ZYNQMP_GQSPI) += spi-zynqmp-gqspi.o obj-$(CONFIG_SPI_ZYNQMP_GQSPI) += spi-zynqmp-gqspi.o
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/platform_data/atmel.h>
#include <linux/platform_data/dma-atmel.h> #include <linux/platform_data/dma-atmel.h>
#include <linux/of.h> #include <linux/of.h>
......
...@@ -480,7 +480,7 @@ static int bcm2835_spi_transfer_one_poll(struct spi_master *master, ...@@ -480,7 +480,7 @@ static int bcm2835_spi_transfer_one_poll(struct spi_master *master,
struct spi_device *spi, struct spi_device *spi,
struct spi_transfer *tfr, struct spi_transfer *tfr,
u32 cs, u32 cs,
unsigned long xfer_time_us) unsigned long long xfer_time_us)
{ {
struct bcm2835_spi *bs = spi_master_get_devdata(master); struct bcm2835_spi *bs = spi_master_get_devdata(master);
unsigned long timeout; unsigned long timeout;
...@@ -531,7 +531,8 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, ...@@ -531,7 +531,8 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
{ {
struct bcm2835_spi *bs = spi_master_get_devdata(master); struct bcm2835_spi *bs = spi_master_get_devdata(master);
unsigned long spi_hz, clk_hz, cdiv; unsigned long spi_hz, clk_hz, cdiv;
unsigned long spi_used_hz, xfer_time_us; unsigned long spi_used_hz;
unsigned long long xfer_time_us;
u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
/* set clock */ /* set clock */
...@@ -553,13 +554,11 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, ...@@ -553,13 +554,11 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
spi_used_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536); spi_used_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536);
bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);
/* handle all the modes */ /* handle all the 3-wire mode */
if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf)) if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf))
cs |= BCM2835_SPI_CS_REN; cs |= BCM2835_SPI_CS_REN;
if (spi->mode & SPI_CPOL) else
cs |= BCM2835_SPI_CS_CPOL; cs &= ~BCM2835_SPI_CS_REN;
if (spi->mode & SPI_CPHA)
cs |= BCM2835_SPI_CS_CPHA;
/* for gpio_cs set dummy CS so that no HW-CS get changed /* for gpio_cs set dummy CS so that no HW-CS get changed
* we can not run this in bcm2835_spi_set_cs, as it does * we can not run this in bcm2835_spi_set_cs, as it does
...@@ -575,9 +574,10 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, ...@@ -575,9 +574,10 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
bs->rx_len = tfr->len; bs->rx_len = tfr->len;
/* calculate the estimated time in us the transfer runs */ /* calculate the estimated time in us the transfer runs */
xfer_time_us = tfr->len xfer_time_us = (unsigned long long)tfr->len
* 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */ * 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */
* 1000000 / spi_used_hz; * 1000000;
do_div(xfer_time_us, spi_used_hz);
/* for short requests run polling*/ /* for short requests run polling*/
if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US) if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US)
...@@ -592,6 +592,25 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, ...@@ -592,6 +592,25 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
return bcm2835_spi_transfer_one_irq(master, spi, tfr, cs); return bcm2835_spi_transfer_one_irq(master, spi, tfr, cs);
} }
static int bcm2835_spi_prepare_message(struct spi_master *master,
struct spi_message *msg)
{
struct spi_device *spi = msg->spi;
struct bcm2835_spi *bs = spi_master_get_devdata(master);
u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA);
if (spi->mode & SPI_CPOL)
cs |= BCM2835_SPI_CS_CPOL;
if (spi->mode & SPI_CPHA)
cs |= BCM2835_SPI_CS_CPHA;
bcm2835_wr(bs, BCM2835_SPI_CS, cs);
return 0;
}
static void bcm2835_spi_handle_err(struct spi_master *master, static void bcm2835_spi_handle_err(struct spi_master *master,
struct spi_message *msg) struct spi_message *msg)
{ {
...@@ -739,6 +758,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) ...@@ -739,6 +758,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
master->set_cs = bcm2835_spi_set_cs; master->set_cs = bcm2835_spi_set_cs;
master->transfer_one = bcm2835_spi_transfer_one; master->transfer_one = bcm2835_spi_transfer_one;
master->handle_err = bcm2835_spi_handle_err; master->handle_err = bcm2835_spi_handle_err;
master->prepare_message = bcm2835_spi_prepare_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);
......
...@@ -76,6 +76,7 @@ ...@@ -76,6 +76,7 @@
#define HSSPI_FIFO_REG(x) (0x200 + (x) * 0x200) #define HSSPI_FIFO_REG(x) (0x200 + (x) * 0x200)
#define HSSPI_OP_MULTIBIT BIT(11)
#define HSSPI_OP_CODE_SHIFT 13 #define HSSPI_OP_CODE_SHIFT 13
#define HSSPI_OP_SLEEP (0 << HSSPI_OP_CODE_SHIFT) #define HSSPI_OP_SLEEP (0 << HSSPI_OP_CODE_SHIFT)
#define HSSPI_OP_READ_WRITE (1 << HSSPI_OP_CODE_SHIFT) #define HSSPI_OP_READ_WRITE (1 << HSSPI_OP_CODE_SHIFT)
...@@ -171,9 +172,12 @@ static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t) ...@@ -171,9 +172,12 @@ static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)
if (opcode != HSSPI_OP_READ) if (opcode != HSSPI_OP_READ)
step_size -= HSSPI_OPCODE_LEN; step_size -= HSSPI_OPCODE_LEN;
__raw_writel(0 << MODE_CTRL_PREPENDBYTE_CNT_SHIFT | if ((opcode == HSSPI_OP_READ && t->rx_nbits == SPI_NBITS_DUAL) ||
2 << MODE_CTRL_MULTIDATA_WR_STRT_SHIFT | (opcode == HSSPI_OP_WRITE && t->tx_nbits == SPI_NBITS_DUAL))
2 << MODE_CTRL_MULTIDATA_RD_STRT_SHIFT | 0xff, opcode |= HSSPI_OP_MULTIBIT;
__raw_writel(1 << MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT |
1 << MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT | 0xff,
bs->regs + HSSPI_PROFILE_MODE_CTRL_REG(chip_select)); bs->regs + HSSPI_PROFILE_MODE_CTRL_REG(chip_select));
while (pending > 0) { while (pending > 0) {
...@@ -374,7 +378,8 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) ...@@ -374,7 +378,8 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
master->num_chipselect = 8; master->num_chipselect = 8;
master->setup = bcm63xx_hsspi_setup; master->setup = bcm63xx_hsspi_setup;
master->transfer_one_message = bcm63xx_hsspi_transfer_one; master->transfer_one_message = bcm63xx_hsspi_transfer_one;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
SPI_RX_DUAL | SPI_TX_DUAL;
master->bits_per_word_mask = SPI_BPW_MASK(8); master->bits_per_word_mask = SPI_BPW_MASK(8);
master->auto_runtime_pm = true; master->auto_runtime_pm = true;
......
...@@ -49,7 +49,7 @@ bitbang_txrx_be_cpha0(struct spi_device *spi, ...@@ -49,7 +49,7 @@ bitbang_txrx_be_cpha0(struct spi_device *spi,
{ {
/* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
bool oldbit = !(word & 1); u32 oldbit = (!(word & (1<<(bits-1)))) << 31;
/* clock starts at inactive polarity */ /* clock starts at inactive polarity */
for (word <<= (32 - bits); likely(bits); bits--) { for (word <<= (32 - bits); likely(bits); bits--) {
...@@ -81,7 +81,7 @@ bitbang_txrx_be_cpha1(struct spi_device *spi, ...@@ -81,7 +81,7 @@ bitbang_txrx_be_cpha1(struct spi_device *spi,
{ {
/* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */ /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
bool oldbit = !(word & (1 << 31)); u32 oldbit = (!(word & (1<<(bits-1)))) << 31;
/* clock starts at inactive polarity */ /* clock starts at inactive polarity */
for (word <<= (32 - bits); likely(bits); bits--) { for (word <<= (32 - bits); likely(bits); bits--) {
......
...@@ -139,6 +139,8 @@ struct davinci_spi { ...@@ -139,6 +139,8 @@ struct davinci_spi {
u32 (*get_tx)(struct davinci_spi *); u32 (*get_tx)(struct davinci_spi *);
u8 *bytes_per_word; u8 *bytes_per_word;
u8 prescaler_limit;
}; };
static struct davinci_spi_config davinci_spi_default_cfg; static struct davinci_spi_config davinci_spi_default_cfg;
...@@ -255,7 +257,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) ...@@ -255,7 +257,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
* This function calculates the prescale value that generates a clock rate * This function calculates the prescale value that generates a clock rate
* less than or equal to the specified maximum. * less than or equal to the specified maximum.
* *
* Returns: calculated prescale - 1 for easy programming into SPI registers * Returns: calculated prescale value for easy programming into SPI registers
* or negative error number if valid prescalar cannot be updated. * or negative error number if valid prescalar cannot be updated.
*/ */
static inline int davinci_spi_get_prescale(struct davinci_spi *dspi, static inline int davinci_spi_get_prescale(struct davinci_spi *dspi,
...@@ -263,12 +265,13 @@ static inline int davinci_spi_get_prescale(struct davinci_spi *dspi, ...@@ -263,12 +265,13 @@ static inline int davinci_spi_get_prescale(struct davinci_spi *dspi,
{ {
int ret; int ret;
ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz); /* Subtract 1 to match what will be programmed into SPI register. */
ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz) - 1;
if (ret < 1 || ret > 256) if (ret < dspi->prescaler_limit || ret > 255)
return -EINVAL; return -EINVAL;
return ret - 1; return ret;
} }
/** /**
...@@ -832,13 +835,40 @@ static int davinci_spi_request_dma(struct davinci_spi *dspi) ...@@ -832,13 +835,40 @@ static int davinci_spi_request_dma(struct davinci_spi *dspi)
} }
#if defined(CONFIG_OF) #if defined(CONFIG_OF)
/* OF SPI data structure */
struct davinci_spi_of_data {
u8 version;
u8 prescaler_limit;
};
static const struct davinci_spi_of_data dm6441_spi_data = {
.version = SPI_VERSION_1,
.prescaler_limit = 2,
};
static const struct davinci_spi_of_data da830_spi_data = {
.version = SPI_VERSION_2,
.prescaler_limit = 2,
};
static const struct davinci_spi_of_data keystone_spi_data = {
.version = SPI_VERSION_1,
.prescaler_limit = 0,
};
static const struct of_device_id davinci_spi_of_match[] = { static const struct of_device_id davinci_spi_of_match[] = {
{ {
.compatible = "ti,dm6441-spi", .compatible = "ti,dm6441-spi",
.data = &dm6441_spi_data,
}, },
{ {
.compatible = "ti,da830-spi", .compatible = "ti,da830-spi",
.data = (void *)SPI_VERSION_2, .data = &da830_spi_data,
},
{
.compatible = "ti,keystone-spi",
.data = &keystone_spi_data,
}, },
{ }, { },
}; };
...@@ -857,21 +887,21 @@ static int spi_davinci_get_pdata(struct platform_device *pdev, ...@@ -857,21 +887,21 @@ static int spi_davinci_get_pdata(struct platform_device *pdev,
struct davinci_spi *dspi) struct davinci_spi *dspi)
{ {
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
struct davinci_spi_of_data *spi_data;
struct davinci_spi_platform_data *pdata; struct davinci_spi_platform_data *pdata;
unsigned int num_cs, intr_line = 0; unsigned int num_cs, intr_line = 0;
const struct of_device_id *match; const struct of_device_id *match;
pdata = &dspi->pdata; pdata = &dspi->pdata;
pdata->version = SPI_VERSION_1;
match = of_match_device(davinci_spi_of_match, &pdev->dev); match = of_match_device(davinci_spi_of_match, &pdev->dev);
if (!match) if (!match)
return -ENODEV; return -ENODEV;
/* match data has the SPI version number for SPI_VERSION_2 */ spi_data = (struct davinci_spi_of_data *)match->data;
if (match->data == (void *)SPI_VERSION_2)
pdata->version = SPI_VERSION_2;
pdata->version = spi_data->version;
pdata->prescaler_limit = spi_data->prescaler_limit;
/* /*
* default num_cs is 1 and all chipsel are internal to the chip * default num_cs is 1 and all chipsel are internal to the chip
* indicated by chip_sel being NULL or cs_gpios being NULL or * indicated by chip_sel being NULL or cs_gpios being NULL or
...@@ -991,7 +1021,7 @@ static int davinci_spi_probe(struct platform_device *pdev) ...@@ -991,7 +1021,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
dspi->bitbang.chipselect = davinci_spi_chipselect; dspi->bitbang.chipselect = davinci_spi_chipselect;
dspi->bitbang.setup_transfer = davinci_spi_setup_transfer; dspi->bitbang.setup_transfer = davinci_spi_setup_transfer;
dspi->prescaler_limit = pdata->prescaler_limit;
dspi->version = pdata->version; dspi->version = pdata->version;
dspi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP; dspi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP;
......
...@@ -74,6 +74,9 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) ...@@ -74,6 +74,9 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
dws->max_freq = clk_get_rate(dwsmmio->clk); dws->max_freq = clk_get_rate(dwsmmio->clk);
of_property_read_u32(pdev->dev.of_node, "reg-io-width",
&dws->reg_io_width);
num_cs = 4; num_cs = 4;
if (pdev->dev.of_node) if (pdev->dev.of_node)
......
...@@ -194,7 +194,7 @@ static void dw_writer(struct dw_spi *dws) ...@@ -194,7 +194,7 @@ static void dw_writer(struct dw_spi *dws)
else else
txw = *(u16 *)(dws->tx); txw = *(u16 *)(dws->tx);
} }
dw_writel(dws, DW_SPI_DR, txw); dw_write_io_reg(dws, DW_SPI_DR, txw);
dws->tx += dws->n_bytes; dws->tx += dws->n_bytes;
} }
} }
...@@ -205,7 +205,7 @@ static void dw_reader(struct dw_spi *dws) ...@@ -205,7 +205,7 @@ static void dw_reader(struct dw_spi *dws)
u16 rxw; u16 rxw;
while (max--) { while (max--) {
rxw = dw_readl(dws, DW_SPI_DR); rxw = dw_read_io_reg(dws, DW_SPI_DR);
/* Care rx only if the transfer's original "rx" is not null */ /* Care rx only if the transfer's original "rx" is not null */
if (dws->rx_end - dws->len) { if (dws->rx_end - dws->len) {
if (dws->n_bytes == 1) if (dws->n_bytes == 1)
......
...@@ -109,6 +109,7 @@ struct dw_spi { ...@@ -109,6 +109,7 @@ struct dw_spi {
u32 fifo_len; /* depth of the FIFO buffer */ u32 fifo_len; /* depth of the FIFO buffer */
u32 max_freq; /* max bus freq supported */ u32 max_freq; /* max bus freq supported */
u32 reg_io_width; /* DR I/O width in bytes */
u16 bus_num; u16 bus_num;
u16 num_cs; /* supported slave numbers */ u16 num_cs; /* supported slave numbers */
...@@ -145,11 +146,45 @@ static inline u32 dw_readl(struct dw_spi *dws, u32 offset) ...@@ -145,11 +146,45 @@ static inline u32 dw_readl(struct dw_spi *dws, u32 offset)
return __raw_readl(dws->regs + offset); return __raw_readl(dws->regs + offset);
} }
static inline u16 dw_readw(struct dw_spi *dws, u32 offset)
{
return __raw_readw(dws->regs + offset);
}
static inline void dw_writel(struct dw_spi *dws, u32 offset, u32 val) static inline void dw_writel(struct dw_spi *dws, u32 offset, u32 val)
{ {
__raw_writel(val, dws->regs + offset); __raw_writel(val, dws->regs + offset);
} }
static inline void dw_writew(struct dw_spi *dws, u32 offset, u16 val)
{
__raw_writew(val, dws->regs + offset);
}
static inline u32 dw_read_io_reg(struct dw_spi *dws, u32 offset)
{
switch (dws->reg_io_width) {
case 2:
return dw_readw(dws, offset);
case 4:
default:
return dw_readl(dws, offset);
}
}
static inline void dw_write_io_reg(struct dw_spi *dws, u32 offset, u32 val)
{
switch (dws->reg_io_width) {
case 2:
dw_writew(dws, offset, val);
break;
case 4:
default:
dw_writel(dws, offset, val);
break;
}
}
static inline void spi_enable_chip(struct dw_spi *dws, int enable) static inline void spi_enable_chip(struct dw_spi *dws, int enable)
{ {
dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0)); dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0));
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/pm_runtime.h>
#include <sysdev/fsl_soc.h> #include <sysdev/fsl_soc.h>
#include "spi-fsl-lib.h" #include "spi-fsl-lib.h"
...@@ -85,6 +86,8 @@ struct fsl_espi_transfer { ...@@ -85,6 +86,8 @@ struct fsl_espi_transfer {
#define SPCOM_TRANLEN(x) ((x) << 0) #define SPCOM_TRANLEN(x) ((x) << 0)
#define SPCOM_TRANLEN_MAX 0xFFFF /* Max transaction length */ #define SPCOM_TRANLEN_MAX 0xFFFF /* Max transaction length */
#define AUTOSUSPEND_TIMEOUT 2000
static void fsl_espi_change_mode(struct spi_device *spi) static void fsl_espi_change_mode(struct spi_device *spi)
{ {
struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master); struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
...@@ -485,6 +488,8 @@ static int fsl_espi_setup(struct spi_device *spi) ...@@ -485,6 +488,8 @@ static int fsl_espi_setup(struct spi_device *spi)
mpc8xxx_spi = spi_master_get_devdata(spi->master); mpc8xxx_spi = spi_master_get_devdata(spi->master);
reg_base = mpc8xxx_spi->reg_base; reg_base = mpc8xxx_spi->reg_base;
pm_runtime_get_sync(mpc8xxx_spi->dev);
hw_mode = cs->hw_mode; /* Save original settings */ hw_mode = cs->hw_mode; /* Save original settings */
cs->hw_mode = mpc8xxx_spi_read_reg( cs->hw_mode = mpc8xxx_spi_read_reg(
&reg_base->csmode[spi->chip_select]); &reg_base->csmode[spi->chip_select]);
...@@ -507,6 +512,10 @@ static int fsl_espi_setup(struct spi_device *spi) ...@@ -507,6 +512,10 @@ static int fsl_espi_setup(struct spi_device *spi)
mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode); mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode);
retval = fsl_espi_setup_transfer(spi, NULL); retval = fsl_espi_setup_transfer(spi, NULL);
pm_runtime_mark_last_busy(mpc8xxx_spi->dev);
pm_runtime_put_autosuspend(mpc8xxx_spi->dev);
if (retval < 0) { if (retval < 0) {
cs->hw_mode = hw_mode; /* Restore settings */ cs->hw_mode = hw_mode; /* Restore settings */
return retval; return retval;
...@@ -604,20 +613,14 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data) ...@@ -604,20 +613,14 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
return ret; return ret;
} }
static void fsl_espi_remove(struct mpc8xxx_spi *mspi) #ifdef CONFIG_PM
static int fsl_espi_runtime_suspend(struct device *dev)
{ {
iounmap(mspi->reg_base); struct spi_master *master = dev_get_drvdata(dev);
} struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
static int fsl_espi_suspend(struct spi_master *master)
{
struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_espi_reg *reg_base;
u32 regval; u32 regval;
mpc8xxx_spi = spi_master_get_devdata(master);
reg_base = mpc8xxx_spi->reg_base;
regval = mpc8xxx_spi_read_reg(&reg_base->mode); regval = mpc8xxx_spi_read_reg(&reg_base->mode);
regval &= ~SPMODE_ENABLE; regval &= ~SPMODE_ENABLE;
mpc8xxx_spi_write_reg(&reg_base->mode, regval); mpc8xxx_spi_write_reg(&reg_base->mode, regval);
...@@ -625,21 +628,20 @@ static int fsl_espi_suspend(struct spi_master *master) ...@@ -625,21 +628,20 @@ static int fsl_espi_suspend(struct spi_master *master)
return 0; return 0;
} }
static int fsl_espi_resume(struct spi_master *master) static int fsl_espi_runtime_resume(struct device *dev)
{ {
struct mpc8xxx_spi *mpc8xxx_spi; struct spi_master *master = dev_get_drvdata(dev);
struct fsl_espi_reg *reg_base; struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
u32 regval; u32 regval;
mpc8xxx_spi = spi_master_get_devdata(master);
reg_base = mpc8xxx_spi->reg_base;
regval = mpc8xxx_spi_read_reg(&reg_base->mode); regval = mpc8xxx_spi_read_reg(&reg_base->mode);
regval |= SPMODE_ENABLE; regval |= SPMODE_ENABLE;
mpc8xxx_spi_write_reg(&reg_base->mode, regval); mpc8xxx_spi_write_reg(&reg_base->mode, regval);
return 0; return 0;
} }
#endif
static struct spi_master * fsl_espi_probe(struct device *dev, static struct spi_master * fsl_espi_probe(struct device *dev,
struct resource *mem, unsigned int irq) struct resource *mem, unsigned int irq)
...@@ -667,25 +669,23 @@ static struct spi_master * fsl_espi_probe(struct device *dev, ...@@ -667,25 +669,23 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
master->setup = fsl_espi_setup; master->setup = fsl_espi_setup;
master->cleanup = fsl_espi_cleanup; master->cleanup = fsl_espi_cleanup;
master->transfer_one_message = fsl_espi_do_one_msg; master->transfer_one_message = fsl_espi_do_one_msg;
master->prepare_transfer_hardware = fsl_espi_resume; master->auto_runtime_pm = true;
master->unprepare_transfer_hardware = fsl_espi_suspend;
mpc8xxx_spi = spi_master_get_devdata(master); mpc8xxx_spi = spi_master_get_devdata(master);
mpc8xxx_spi->spi_remove = fsl_espi_remove;
mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem)); mpc8xxx_spi->reg_base = devm_ioremap_resource(dev, mem);
if (!mpc8xxx_spi->reg_base) { if (IS_ERR(mpc8xxx_spi->reg_base)) {
ret = -ENOMEM; ret = PTR_ERR(mpc8xxx_spi->reg_base);
goto err_probe; goto err_probe;
} }
reg_base = mpc8xxx_spi->reg_base; reg_base = mpc8xxx_spi->reg_base;
/* Register for SPI Interrupt */ /* Register for SPI Interrupt */
ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq, ret = devm_request_irq(dev, mpc8xxx_spi->irq, fsl_espi_irq,
0, "fsl_espi", mpc8xxx_spi); 0, "fsl_espi", mpc8xxx_spi);
if (ret) if (ret)
goto free_irq; goto err_probe;
if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
mpc8xxx_spi->rx_shift = 16; mpc8xxx_spi->rx_shift = 16;
...@@ -731,18 +731,27 @@ static struct spi_master * fsl_espi_probe(struct device *dev, ...@@ -731,18 +731,27 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
mpc8xxx_spi_write_reg(&reg_base->mode, regval); mpc8xxx_spi_write_reg(&reg_base->mode, regval);
ret = spi_register_master(master); pm_runtime_set_autosuspend_delay(dev, AUTOSUSPEND_TIMEOUT);
pm_runtime_use_autosuspend(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
ret = devm_spi_register_master(dev, master);
if (ret < 0) if (ret < 0)
goto unreg_master; goto err_pm;
dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq); dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq);
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return master; return master;
unreg_master: err_pm:
free_irq(mpc8xxx_spi->irq, mpc8xxx_spi); pm_runtime_put_noidle(dev);
free_irq: pm_runtime_disable(dev);
iounmap(mpc8xxx_spi->reg_base); pm_runtime_set_suspended(dev);
err_probe: err_probe:
spi_master_put(master); spi_master_put(master);
err: err:
...@@ -809,7 +818,9 @@ static int of_fsl_espi_probe(struct platform_device *ofdev) ...@@ -809,7 +818,9 @@ static int of_fsl_espi_probe(struct platform_device *ofdev)
static int of_fsl_espi_remove(struct platform_device *dev) static int of_fsl_espi_remove(struct platform_device *dev)
{ {
return mpc8xxx_spi_remove(&dev->dev); pm_runtime_disable(&dev->dev);
return 0;
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
...@@ -824,7 +835,11 @@ static int of_fsl_espi_suspend(struct device *dev) ...@@ -824,7 +835,11 @@ static int of_fsl_espi_suspend(struct device *dev)
return ret; return ret;
} }
return fsl_espi_suspend(master); ret = pm_runtime_force_suspend(dev);
if (ret < 0)
return ret;
return 0;
} }
static int of_fsl_espi_resume(struct device *dev) static int of_fsl_espi_resume(struct device *dev)
...@@ -834,7 +849,7 @@ static int of_fsl_espi_resume(struct device *dev) ...@@ -834,7 +849,7 @@ static int of_fsl_espi_resume(struct device *dev)
struct mpc8xxx_spi *mpc8xxx_spi; struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_espi_reg *reg_base; struct fsl_espi_reg *reg_base;
u32 regval; u32 regval;
int i; int i, ret;
mpc8xxx_spi = spi_master_get_devdata(master); mpc8xxx_spi = spi_master_get_devdata(master);
reg_base = mpc8xxx_spi->reg_base; reg_base = mpc8xxx_spi->reg_base;
...@@ -854,11 +869,17 @@ static int of_fsl_espi_resume(struct device *dev) ...@@ -854,11 +869,17 @@ static int of_fsl_espi_resume(struct device *dev)
mpc8xxx_spi_write_reg(&reg_base->mode, regval); mpc8xxx_spi_write_reg(&reg_base->mode, regval);
ret = pm_runtime_force_resume(dev);
if (ret < 0)
return ret;
return spi_master_resume(master); return spi_master_resume(master);
} }
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
static const struct dev_pm_ops espi_pm = { static const struct dev_pm_ops espi_pm = {
SET_RUNTIME_PM_OPS(fsl_espi_runtime_suspend,
fsl_espi_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume) SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume)
}; };
......
...@@ -114,25 +114,6 @@ void mpc8xxx_spi_probe(struct device *dev, struct resource *mem, ...@@ -114,25 +114,6 @@ void mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
} }
EXPORT_SYMBOL_GPL(mpc8xxx_spi_probe); EXPORT_SYMBOL_GPL(mpc8xxx_spi_probe);
int mpc8xxx_spi_remove(struct device *dev)
{
struct mpc8xxx_spi *mpc8xxx_spi;
struct spi_master *master;
master = dev_get_drvdata(dev);
mpc8xxx_spi = spi_master_get_devdata(master);
spi_unregister_master(master);
free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
if (mpc8xxx_spi->spi_remove)
mpc8xxx_spi->spi_remove(mpc8xxx_spi);
return 0;
}
EXPORT_SYMBOL_GPL(mpc8xxx_spi_remove);
int of_mpc8xxx_spi_probe(struct platform_device *ofdev) int of_mpc8xxx_spi_probe(struct platform_device *ofdev)
{ {
struct device *dev = &ofdev->dev; struct device *dev = &ofdev->dev;
......
...@@ -54,9 +54,6 @@ struct mpc8xxx_spi { ...@@ -54,9 +54,6 @@ struct mpc8xxx_spi {
void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *); void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
u32(*get_tx) (struct mpc8xxx_spi *); u32(*get_tx) (struct mpc8xxx_spi *);
/* hooks for different controller driver */
void (*spi_remove) (struct mpc8xxx_spi *mspi);
unsigned int count; unsigned int count;
unsigned int irq; unsigned int irq;
......
...@@ -559,12 +559,6 @@ static irqreturn_t fsl_spi_irq(s32 irq, void *context_data) ...@@ -559,12 +559,6 @@ static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
return ret; return ret;
} }
static void fsl_spi_remove(struct mpc8xxx_spi *mspi)
{
iounmap(mspi->reg_base);
fsl_spi_cpm_free(mspi);
}
static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on) static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
{ {
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
...@@ -631,7 +625,6 @@ static struct spi_master * fsl_spi_probe(struct device *dev, ...@@ -631,7 +625,6 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
master->transfer_one_message = fsl_spi_do_one_msg; master->transfer_one_message = fsl_spi_do_one_msg;
mpc8xxx_spi = spi_master_get_devdata(master); mpc8xxx_spi = spi_master_get_devdata(master);
mpc8xxx_spi->spi_remove = fsl_spi_remove;
mpc8xxx_spi->max_bits_per_word = 32; mpc8xxx_spi->max_bits_per_word = 32;
mpc8xxx_spi->type = fsl_spi_get_type(dev); mpc8xxx_spi->type = fsl_spi_get_type(dev);
...@@ -639,10 +632,10 @@ static struct spi_master * fsl_spi_probe(struct device *dev, ...@@ -639,10 +632,10 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
if (ret) if (ret)
goto err_cpm_init; goto err_cpm_init;
mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem)); mpc8xxx_spi->reg_base = devm_ioremap_resource(dev, mem);
if (mpc8xxx_spi->reg_base == NULL) { if (IS_ERR(mpc8xxx_spi->reg_base)) {
ret = -ENOMEM; ret = PTR_ERR(mpc8xxx_spi->reg_base);
goto err_ioremap; goto err_probe;
} }
if (mpc8xxx_spi->type == TYPE_GRLIB) if (mpc8xxx_spi->type == TYPE_GRLIB)
...@@ -661,11 +654,11 @@ static struct spi_master * fsl_spi_probe(struct device *dev, ...@@ -661,11 +654,11 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
&mpc8xxx_spi->tx_shift, 8, 1); &mpc8xxx_spi->tx_shift, 8, 1);
/* Register for SPI Interrupt */ /* Register for SPI Interrupt */
ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq, ret = devm_request_irq(dev, mpc8xxx_spi->irq, fsl_spi_irq,
0, "fsl_spi", mpc8xxx_spi); 0, "fsl_spi", mpc8xxx_spi);
if (ret != 0) if (ret != 0)
goto free_irq; goto err_probe;
reg_base = mpc8xxx_spi->reg_base; reg_base = mpc8xxx_spi->reg_base;
...@@ -686,20 +679,16 @@ static struct spi_master * fsl_spi_probe(struct device *dev, ...@@ -686,20 +679,16 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
mpc8xxx_spi_write_reg(&reg_base->mode, regval); mpc8xxx_spi_write_reg(&reg_base->mode, regval);
ret = spi_register_master(master); ret = devm_spi_register_master(dev, master);
if (ret < 0) if (ret < 0)
goto unreg_master; goto err_probe;
dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base, dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base,
mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags)); mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
return master; return master;
unreg_master: err_probe:
free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
free_irq:
iounmap(mpc8xxx_spi->reg_base);
err_ioremap:
fsl_spi_cpm_free(mpc8xxx_spi); fsl_spi_cpm_free(mpc8xxx_spi);
err_cpm_init: err_cpm_init:
spi_master_put(master); spi_master_put(master);
...@@ -866,11 +855,8 @@ static int of_fsl_spi_remove(struct platform_device *ofdev) ...@@ -866,11 +855,8 @@ static int of_fsl_spi_remove(struct platform_device *ofdev)
{ {
struct spi_master *master = platform_get_drvdata(ofdev); struct spi_master *master = platform_get_drvdata(ofdev);
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
int ret;
ret = mpc8xxx_spi_remove(&ofdev->dev); fsl_spi_cpm_free(mpc8xxx_spi);
if (ret)
return ret;
if (mpc8xxx_spi->type == TYPE_FSL) if (mpc8xxx_spi->type == TYPE_FSL)
of_fsl_spi_free_chipselects(&ofdev->dev); of_fsl_spi_free_chipselects(&ofdev->dev);
return 0; return 0;
...@@ -916,7 +902,12 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev) ...@@ -916,7 +902,12 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev)
static int plat_mpc8xxx_spi_remove(struct platform_device *pdev) static int plat_mpc8xxx_spi_remove(struct platform_device *pdev)
{ {
return mpc8xxx_spi_remove(&pdev->dev); struct spi_master *master = platform_get_drvdata(pdev);
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
fsl_spi_cpm_free(mpc8xxx_spi);
return 0;
} }
MODULE_ALIAS("platform:mpc8xxx_spi"); MODULE_ALIAS("platform:mpc8xxx_spi");
......
...@@ -105,6 +105,10 @@ struct img_spfi { ...@@ -105,6 +105,10 @@ struct img_spfi {
bool rx_dma_busy; bool rx_dma_busy;
}; };
struct img_spfi_device_data {
bool gpio_requested;
};
static inline u32 spfi_readl(struct img_spfi *spfi, u32 reg) static inline u32 spfi_readl(struct img_spfi *spfi, u32 reg)
{ {
return readl(spfi->regs + reg); return readl(spfi->regs + reg);
...@@ -267,15 +271,15 @@ static int img_spfi_start_pio(struct spi_master *master, ...@@ -267,15 +271,15 @@ static int img_spfi_start_pio(struct spi_master *master,
cpu_relax(); cpu_relax();
} }
ret = spfi_wait_all_done(spfi);
if (ret < 0)
return ret;
if (rx_bytes > 0 || tx_bytes > 0) { if (rx_bytes > 0 || tx_bytes > 0) {
dev_err(spfi->dev, "PIO transfer timed out\n"); dev_err(spfi->dev, "PIO transfer timed out\n");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
ret = spfi_wait_all_done(spfi);
if (ret < 0)
return ret;
return 0; return 0;
} }
...@@ -440,21 +444,50 @@ static int img_spfi_unprepare(struct spi_master *master, ...@@ -440,21 +444,50 @@ static int img_spfi_unprepare(struct spi_master *master,
static int img_spfi_setup(struct spi_device *spi) static int img_spfi_setup(struct spi_device *spi)
{ {
int ret; int ret = -EINVAL;
struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi);
ret = gpio_request_one(spi->cs_gpio, (spi->mode & SPI_CS_HIGH) ?
GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, if (!spfi_data) {
dev_name(&spi->dev)); spfi_data = kzalloc(sizeof(*spfi_data), GFP_KERNEL);
if (ret) if (!spfi_data)
dev_err(&spi->dev, "can't request chipselect gpio %d\n", return -ENOMEM;
spfi_data->gpio_requested = false;
spi_set_ctldata(spi, spfi_data);
}
if (!spfi_data->gpio_requested) {
ret = gpio_request_one(spi->cs_gpio,
(spi->mode & SPI_CS_HIGH) ?
GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
dev_name(&spi->dev));
if (ret)
dev_err(&spi->dev, "can't request chipselect gpio %d\n",
spi->cs_gpio); spi->cs_gpio);
else
spfi_data->gpio_requested = true;
} else {
if (gpio_is_valid(spi->cs_gpio)) {
int mode = ((spi->mode & SPI_CS_HIGH) ?
GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH);
ret = gpio_direction_output(spi->cs_gpio, mode);
if (ret)
dev_err(&spi->dev, "chipselect gpio %d setup failed (%d)\n",
spi->cs_gpio, ret);
}
}
return ret; return ret;
} }
static void img_spfi_cleanup(struct spi_device *spi) static void img_spfi_cleanup(struct spi_device *spi)
{ {
gpio_free(spi->cs_gpio); struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi);
if (spfi_data) {
if (spfi_data->gpio_requested)
gpio_free(spi->cs_gpio);
kfree(spfi_data);
spi_set_ctldata(spi, NULL);
}
} }
static void img_spfi_config(struct spi_master *master, struct spi_device *spi, static void img_spfi_config(struct spi_master *master, struct spi_device *spi,
...@@ -548,6 +581,7 @@ static int img_spfi_probe(struct platform_device *pdev) ...@@ -548,6 +581,7 @@ static int img_spfi_probe(struct platform_device *pdev)
struct img_spfi *spfi; struct img_spfi *spfi;
struct resource *res; struct resource *res;
int ret; int ret;
u32 max_speed_hz;
master = spi_alloc_master(&pdev->dev, sizeof(*spfi)); master = spi_alloc_master(&pdev->dev, sizeof(*spfi));
if (!master) if (!master)
...@@ -612,6 +646,19 @@ static int img_spfi_probe(struct platform_device *pdev) ...@@ -612,6 +646,19 @@ static int img_spfi_probe(struct platform_device *pdev)
master->max_speed_hz = clk_get_rate(spfi->spfi_clk) / 4; master->max_speed_hz = clk_get_rate(spfi->spfi_clk) / 4;
master->min_speed_hz = clk_get_rate(spfi->spfi_clk) / 512; master->min_speed_hz = clk_get_rate(spfi->spfi_clk) / 512;
/*
* Maximum speed supported by spfi is limited to the lower value
* between 1/4 of the SPFI clock or to "spfi-max-frequency"
* defined in the device tree.
* If no value is defined in the device tree assume the maximum
* speed supported to be 1/4 of the SPFI clock.
*/
if (!of_property_read_u32(spfi->dev->of_node, "spfi-max-frequency",
&max_speed_hz)) {
if (master->max_speed_hz > max_speed_hz)
master->max_speed_hz = max_speed_hz;
}
master->setup = img_spfi_setup; master->setup = img_spfi_setup;
master->cleanup = img_spfi_cleanup; master->cleanup = img_spfi_cleanup;
master->transfer_one = img_spfi_transfer_one; master->transfer_one = img_spfi_transfer_one;
......
...@@ -30,11 +30,37 @@ ...@@ -30,11 +30,37 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <asm/mpc52xx_psc.h> #include <asm/mpc52xx_psc.h>
enum {
TYPE_MPC5121,
TYPE_MPC5125,
};
/*
* This macro abstracts the differences in the PSC register layout between
* MPC5121 (which uses a struct mpc52xx_psc) and MPC5125 (using mpc5125_psc).
*/
#define psc_addr(mps, regname) ({ \
void *__ret = NULL; \
switch (mps->type) { \
case TYPE_MPC5121: { \
struct mpc52xx_psc __iomem *psc = mps->psc; \
__ret = &psc->regname; \
}; \
break; \
case TYPE_MPC5125: { \
struct mpc5125_psc __iomem *psc = mps->psc; \
__ret = &psc->regname; \
}; \
break; \
} \
__ret; })
struct mpc512x_psc_spi { struct mpc512x_psc_spi {
void (*cs_control)(struct spi_device *spi, bool on); void (*cs_control)(struct spi_device *spi, bool on);
/* driver internal data */ /* driver internal data */
struct mpc52xx_psc __iomem *psc; int type;
void __iomem *psc;
struct mpc512x_psc_fifo __iomem *fifo; struct mpc512x_psc_fifo __iomem *fifo;
unsigned int irq; unsigned int irq;
u8 bits_per_word; u8 bits_per_word;
...@@ -71,13 +97,12 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi) ...@@ -71,13 +97,12 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
{ {
struct mpc512x_psc_spi_cs *cs = spi->controller_state; struct mpc512x_psc_spi_cs *cs = spi->controller_state;
struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master); struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
struct mpc52xx_psc __iomem *psc = mps->psc;
u32 sicr; u32 sicr;
u32 ccr; u32 ccr;
int speed; int speed;
u16 bclkdiv; u16 bclkdiv;
sicr = in_be32(&psc->sicr); sicr = in_be32(psc_addr(mps, sicr));
/* Set clock phase and polarity */ /* Set clock phase and polarity */
if (spi->mode & SPI_CPHA) if (spi->mode & SPI_CPHA)
...@@ -94,9 +119,9 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi) ...@@ -94,9 +119,9 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
sicr |= 0x10000000; sicr |= 0x10000000;
else else
sicr &= ~0x10000000; sicr &= ~0x10000000;
out_be32(&psc->sicr, sicr); out_be32(psc_addr(mps, sicr), sicr);
ccr = in_be32(&psc->ccr); ccr = in_be32(psc_addr(mps, ccr));
ccr &= 0xFF000000; ccr &= 0xFF000000;
speed = cs->speed_hz; speed = cs->speed_hz;
if (!speed) if (!speed)
...@@ -104,7 +129,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi) ...@@ -104,7 +129,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
bclkdiv = (mps->mclk_rate / speed) - 1; bclkdiv = (mps->mclk_rate / speed) - 1;
ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8)); ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
out_be32(&psc->ccr, ccr); out_be32(psc_addr(mps, ccr), ccr);
mps->bits_per_word = cs->bits_per_word; mps->bits_per_word = cs->bits_per_word;
if (mps->cs_control && gpio_is_valid(spi->cs_gpio)) if (mps->cs_control && gpio_is_valid(spi->cs_gpio))
...@@ -315,16 +340,15 @@ static int mpc512x_psc_spi_msg_xfer(struct spi_master *master, ...@@ -315,16 +340,15 @@ static int mpc512x_psc_spi_msg_xfer(struct spi_master *master,
static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master) static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master)
{ {
struct mpc512x_psc_spi *mps = spi_master_get_devdata(master); struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
struct mpc52xx_psc __iomem *psc = mps->psc;
dev_dbg(&master->dev, "%s()\n", __func__); dev_dbg(&master->dev, "%s()\n", __func__);
/* Zero MR2 */ /* Zero MR2 */
in_8(&psc->mode); in_8(psc_addr(mps, mr2));
out_8(&psc->mode, 0x0); out_8(psc_addr(mps, mr2), 0x0);
/* enable transmitter/receiver */ /* enable transmitter/receiver */
out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); out_8(psc_addr(mps, command), MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
return 0; return 0;
} }
...@@ -332,13 +356,12 @@ static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master) ...@@ -332,13 +356,12 @@ static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master)
static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_master *master) static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_master *master)
{ {
struct mpc512x_psc_spi *mps = spi_master_get_devdata(master); struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
struct mpc52xx_psc __iomem *psc = mps->psc;
struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
dev_dbg(&master->dev, "%s()\n", __func__); dev_dbg(&master->dev, "%s()\n", __func__);
/* disable transmitter/receiver and fifo interrupt */ /* disable transmitter/receiver and fifo interrupt */
out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); out_8(psc_addr(mps, command), MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
out_be32(&fifo->tximr, 0); out_be32(&fifo->tximr, 0);
return 0; return 0;
...@@ -388,7 +411,6 @@ static void mpc512x_psc_spi_cleanup(struct spi_device *spi) ...@@ -388,7 +411,6 @@ static void mpc512x_psc_spi_cleanup(struct spi_device *spi)
static int mpc512x_psc_spi_port_config(struct spi_master *master, static int mpc512x_psc_spi_port_config(struct spi_master *master,
struct mpc512x_psc_spi *mps) struct mpc512x_psc_spi *mps)
{ {
struct mpc52xx_psc __iomem *psc = mps->psc;
struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
u32 sicr; u32 sicr;
u32 ccr; u32 ccr;
...@@ -396,12 +418,12 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master, ...@@ -396,12 +418,12 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
u16 bclkdiv; u16 bclkdiv;
/* Reset the PSC into a known state */ /* Reset the PSC into a known state */
out_8(&psc->command, MPC52xx_PSC_RST_RX); out_8(psc_addr(mps, command), MPC52xx_PSC_RST_RX);
out_8(&psc->command, MPC52xx_PSC_RST_TX); out_8(psc_addr(mps, command), MPC52xx_PSC_RST_TX);
out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); out_8(psc_addr(mps, command), MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
/* Disable psc interrupts all useful interrupts are in fifo */ /* Disable psc interrupts all useful interrupts are in fifo */
out_be16(&psc->isr_imr.imr, 0); out_be16(psc_addr(mps, isr_imr.imr), 0);
/* Disable fifo interrupts, will be enabled later */ /* Disable fifo interrupts, will be enabled later */
out_be32(&fifo->tximr, 0); out_be32(&fifo->tximr, 0);
...@@ -417,18 +439,18 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master, ...@@ -417,18 +439,18 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
0x00004000 | /* MSTR = 1 -- SPI master */ 0x00004000 | /* MSTR = 1 -- SPI master */
0x00000800; /* UseEOF = 1 -- SS low until EOF */ 0x00000800; /* UseEOF = 1 -- SS low until EOF */
out_be32(&psc->sicr, sicr); out_be32(psc_addr(mps, sicr), sicr);
ccr = in_be32(&psc->ccr); ccr = in_be32(psc_addr(mps, ccr));
ccr &= 0xFF000000; ccr &= 0xFF000000;
speed = 1000000; /* default 1MHz */ speed = 1000000; /* default 1MHz */
bclkdiv = (mps->mclk_rate / speed) - 1; bclkdiv = (mps->mclk_rate / speed) - 1;
ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8)); ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
out_be32(&psc->ccr, ccr); out_be32(psc_addr(mps, ccr), ccr);
/* Set 2ms DTL delay */ /* Set 2ms DTL delay */
out_8(&psc->ctur, 0x00); out_8(psc_addr(mps, ctur), 0x00);
out_8(&psc->ctlr, 0x82); out_8(psc_addr(mps, ctlr), 0x82);
/* we don't use the alarms */ /* we don't use the alarms */
out_be32(&fifo->rxalarm, 0xfff); out_be32(&fifo->rxalarm, 0xfff);
...@@ -482,6 +504,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, ...@@ -482,6 +504,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
dev_set_drvdata(dev, master); dev_set_drvdata(dev, master);
mps = spi_master_get_devdata(master); mps = spi_master_get_devdata(master);
mps->type = (int)of_device_get_match_data(dev);
mps->irq = irq; mps->irq = irq;
if (pdata == NULL) { if (pdata == NULL) {
...@@ -589,7 +612,8 @@ static int mpc512x_psc_spi_of_remove(struct platform_device *op) ...@@ -589,7 +612,8 @@ static int mpc512x_psc_spi_of_remove(struct platform_device *op)
} }
static const struct of_device_id mpc512x_psc_spi_of_match[] = { static const struct of_device_id mpc512x_psc_spi_of_match[] = {
{ .compatible = "fsl,mpc5121-psc-spi", }, { .compatible = "fsl,mpc5121-psc-spi", .data = (void *)TYPE_MPC5121 },
{ .compatible = "fsl,mpc5125-psc-spi", .data = (void *)TYPE_MPC5125 },
{}, {},
}; };
......
This diff is collapsed.
...@@ -245,6 +245,7 @@ static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable) ...@@ -245,6 +245,7 @@ static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable) static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
{ {
struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
u32 l; u32 l;
/* The controller handles the inverted chip selects /* The controller handles the inverted chip selects
...@@ -255,6 +256,12 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable) ...@@ -255,6 +256,12 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
enable = !enable; enable = !enable;
if (spi->controller_state) { if (spi->controller_state) {
int err = pm_runtime_get_sync(mcspi->dev);
if (err < 0) {
dev_err(mcspi->dev, "failed to get sync: %d\n", err);
return;
}
l = mcspi_cached_chconf0(spi); l = mcspi_cached_chconf0(spi);
if (enable) if (enable)
...@@ -263,6 +270,9 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable) ...@@ -263,6 +270,9 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
l |= OMAP2_MCSPI_CHCONF_FORCE; l |= OMAP2_MCSPI_CHCONF_FORCE;
mcspi_write_chconf0(spi, l); mcspi_write_chconf0(spi, l);
pm_runtime_mark_last_busy(mcspi->dev);
pm_runtime_put_autosuspend(mcspi->dev);
} }
} }
......
...@@ -41,6 +41,11 @@ ...@@ -41,6 +41,11 @@
#define ORION_SPI_DATA_OUT_REG 0x08 #define ORION_SPI_DATA_OUT_REG 0x08
#define ORION_SPI_DATA_IN_REG 0x0c #define ORION_SPI_DATA_IN_REG 0x0c
#define ORION_SPI_INT_CAUSE_REG 0x10 #define ORION_SPI_INT_CAUSE_REG 0x10
#define ORION_SPI_TIMING_PARAMS_REG 0x18
#define ORION_SPI_TMISO_SAMPLE_MASK (0x3 << 6)
#define ORION_SPI_TMISO_SAMPLE_1 (1 << 6)
#define ORION_SPI_TMISO_SAMPLE_2 (2 << 6)
#define ORION_SPI_MODE_CPOL (1 << 11) #define ORION_SPI_MODE_CPOL (1 << 11)
#define ORION_SPI_MODE_CPHA (1 << 12) #define ORION_SPI_MODE_CPHA (1 << 12)
...@@ -70,6 +75,7 @@ struct orion_spi_dev { ...@@ -70,6 +75,7 @@ struct orion_spi_dev {
unsigned int min_divisor; unsigned int min_divisor;
unsigned int max_divisor; unsigned int max_divisor;
u32 prescale_mask; u32 prescale_mask;
bool is_errata_50mhz_ac;
}; };
struct orion_spi { struct orion_spi {
...@@ -195,6 +201,41 @@ orion_spi_mode_set(struct spi_device *spi) ...@@ -195,6 +201,41 @@ orion_spi_mode_set(struct spi_device *spi)
writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG)); writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
} }
static void
orion_spi_50mhz_ac_timing_erratum(struct spi_device *spi, unsigned int speed)
{
u32 reg;
struct orion_spi *orion_spi;
orion_spi = spi_master_get_devdata(spi->master);
/*
* Erratum description: (Erratum NO. FE-9144572) The device
* SPI interface supports frequencies of up to 50 MHz.
* However, due to this erratum, when the device core clock is
* 250 MHz and the SPI interfaces is configured for 50MHz SPI
* clock and CPOL=CPHA=1 there might occur data corruption on
* reads from the SPI device.
* Erratum Workaround:
* Work in one of the following configurations:
* 1. Set CPOL=CPHA=0 in "SPI Interface Configuration
* Register".
* 2. Set TMISO_SAMPLE value to 0x2 in "SPI Timing Parameters 1
* Register" before setting the interface.
*/
reg = readl(spi_reg(orion_spi, ORION_SPI_TIMING_PARAMS_REG));
reg &= ~ORION_SPI_TMISO_SAMPLE_MASK;
if (clk_get_rate(orion_spi->clk) == 250000000 &&
speed == 50000000 && spi->mode & SPI_CPOL &&
spi->mode & SPI_CPHA)
reg |= ORION_SPI_TMISO_SAMPLE_2;
else
reg |= ORION_SPI_TMISO_SAMPLE_1; /* This is the default value */
writel(reg, spi_reg(orion_spi, ORION_SPI_TIMING_PARAMS_REG));
}
/* /*
* called only when no transfer is active on the bus * called only when no transfer is active on the bus
*/ */
...@@ -216,6 +257,9 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -216,6 +257,9 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
orion_spi_mode_set(spi); orion_spi_mode_set(spi);
if (orion_spi->devdata->is_errata_50mhz_ac)
orion_spi_50mhz_ac_timing_erratum(spi, speed);
rc = orion_spi_baudrate_set(spi, speed); rc = orion_spi_baudrate_set(spi, speed);
if (rc) if (rc)
return rc; return rc;
...@@ -413,6 +457,14 @@ static const struct orion_spi_dev armada_375_spi_dev_data = { ...@@ -413,6 +457,14 @@ static const struct orion_spi_dev armada_375_spi_dev_data = {
.prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK, .prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK,
}; };
static const struct orion_spi_dev armada_380_spi_dev_data = {
.typ = ARMADA_SPI,
.max_hz = 50000000,
.max_divisor = 1920,
.prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK,
.is_errata_50mhz_ac = true,
};
static const struct of_device_id orion_spi_of_match_table[] = { static const struct of_device_id orion_spi_of_match_table[] = {
{ {
.compatible = "marvell,orion-spi", .compatible = "marvell,orion-spi",
...@@ -428,7 +480,7 @@ static const struct of_device_id orion_spi_of_match_table[] = { ...@@ -428,7 +480,7 @@ static const struct of_device_id orion_spi_of_match_table[] = {
}, },
{ {
.compatible = "marvell,armada-380-spi", .compatible = "marvell,armada-380-spi",
.data = &armada_xp_spi_dev_data, .data = &armada_380_spi_dev_data,
}, },
{ {
.compatible = "marvell,armada-390-spi", .compatible = "marvell,armada-390-spi",
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/spi/pxa2xx_spi.h> #include <linux/spi/pxa2xx_spi.h>
#include <linux/clk.h>
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/pxa2xx_spi.h> #include <linux/spi/pxa2xx_spi.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
...@@ -97,6 +98,15 @@ static const struct lpss_config lpss_platforms[] = { ...@@ -97,6 +98,15 @@ static const struct lpss_config lpss_platforms[] = {
.tx_threshold_lo = 160, .tx_threshold_lo = 160,
.tx_threshold_hi = 224, .tx_threshold_hi = 224,
}, },
{ /* LPSS_SPT_SSP */
.offset = 0x200,
.reg_general = -1,
.reg_ssp = 0x20,
.reg_cs_ctrl = 0x24,
.rx_threshold = 1,
.tx_threshold_lo = 32,
.tx_threshold_hi = 56,
},
}; };
static inline const struct lpss_config static inline const struct lpss_config
...@@ -110,6 +120,7 @@ static bool is_lpss_ssp(const struct driver_data *drv_data) ...@@ -110,6 +120,7 @@ static bool is_lpss_ssp(const struct driver_data *drv_data)
switch (drv_data->ssp_type) { switch (drv_data->ssp_type) {
case LPSS_LPT_SSP: case LPSS_LPT_SSP:
case LPSS_BYT_SSP: case LPSS_BYT_SSP:
case LPSS_SPT_SSP:
return true; return true;
default: default:
return false; return false;
...@@ -1107,6 +1118,7 @@ static int setup(struct spi_device *spi) ...@@ -1107,6 +1118,7 @@ static int setup(struct spi_device *spi)
break; break;
case LPSS_LPT_SSP: case LPSS_LPT_SSP:
case LPSS_BYT_SSP: case LPSS_BYT_SSP:
case LPSS_SPT_SSP:
config = lpss_get_config(drv_data); config = lpss_get_config(drv_data);
tx_thres = config->tx_threshold_lo; tx_thres = config->tx_threshold_lo;
tx_hi_thres = config->tx_threshold_hi; tx_hi_thres = config->tx_threshold_hi;
...@@ -1276,6 +1288,31 @@ static const struct acpi_device_id pxa2xx_spi_acpi_match[] = { ...@@ -1276,6 +1288,31 @@ static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
}; };
MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match); MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
/*
* PCI IDs of compound devices that integrate both host controller and private
* integrated DMA engine. Please note these are not used in module
* autoloading and probing in this module but matching the LPSS SSP type.
*/
static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
/* SPT-LP */
{ PCI_VDEVICE(INTEL, 0x9d29), LPSS_SPT_SSP },
{ PCI_VDEVICE(INTEL, 0x9d2a), LPSS_SPT_SSP },
/* SPT-H */
{ PCI_VDEVICE(INTEL, 0xa129), LPSS_SPT_SSP },
{ PCI_VDEVICE(INTEL, 0xa12a), LPSS_SPT_SSP },
{ },
};
static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param)
{
struct device *dev = param;
if (dev != chan->device->dev->parent)
return false;
return true;
}
static struct pxa2xx_spi_master * static struct pxa2xx_spi_master *
pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
{ {
...@@ -1283,16 +1320,25 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) ...@@ -1283,16 +1320,25 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
struct acpi_device *adev; struct acpi_device *adev;
struct ssp_device *ssp; struct ssp_device *ssp;
struct resource *res; struct resource *res;
const struct acpi_device_id *id; const struct acpi_device_id *adev_id = NULL;
const struct pci_device_id *pcidev_id = NULL;
int devid, type; int devid, type;
if (!ACPI_HANDLE(&pdev->dev) || if (!ACPI_HANDLE(&pdev->dev) ||
acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev)) acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev))
return NULL; return NULL;
id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev); if (dev_is_pci(pdev->dev.parent))
if (id) pcidev_id = pci_match_id(pxa2xx_spi_pci_compound_match,
type = (int)id->driver_data; to_pci_dev(pdev->dev.parent));
else
adev_id = acpi_match_device(pdev->dev.driver->acpi_match_table,
&pdev->dev);
if (adev_id)
type = (int)adev_id->driver_data;
else if (pcidev_id)
type = (int)pcidev_id->driver_data;
else else
return NULL; return NULL;
...@@ -1311,6 +1357,12 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) ...@@ -1311,6 +1357,12 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
if (IS_ERR(ssp->mmio_base)) if (IS_ERR(ssp->mmio_base))
return NULL; return NULL;
if (pcidev_id) {
pdata->tx_param = pdev->dev.parent;
pdata->rx_param = pdev->dev.parent;
pdata->dma_filter = pxa2xx_spi_idma_filter;
}
ssp->clk = devm_clk_get(&pdev->dev, NULL); ssp->clk = devm_clk_get(&pdev->dev, NULL);
ssp->irq = platform_get_irq(pdev, 0); ssp->irq = platform_get_irq(pdev, 0);
ssp->type = type; ssp->type = type;
...@@ -1362,8 +1414,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1362,8 +1414,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
/* Allocate master with space for drv_data and null dma buffer */ master = spi_alloc_master(dev, sizeof(struct driver_data));
master = spi_alloc_master(dev, sizeof(struct driver_data) + 16);
if (!master) { if (!master) {
dev_err(&pdev->dev, "cannot alloc spi_master\n"); dev_err(&pdev->dev, "cannot alloc spi_master\n");
pxa_ssp_free(ssp); pxa_ssp_free(ssp);
...@@ -1390,7 +1441,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1390,7 +1441,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
master->auto_runtime_pm = true; master->auto_runtime_pm = true;
drv_data->ssp_type = ssp->type; drv_data->ssp_type = ssp->type;
drv_data->null_dma_buf = (u32 *)PTR_ALIGN(&drv_data[1], DMA_ALIGNMENT);
drv_data->ioaddr = ssp->mmio_base; drv_data->ioaddr = ssp->mmio_base;
drv_data->ssdr_physical = ssp->phys_base + SSDR; drv_data->ssdr_physical = ssp->phys_base + SSDR;
...@@ -1424,8 +1474,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1424,8 +1474,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
} }
/* Setup DMA if requested */ /* Setup DMA if requested */
drv_data->tx_channel = -1;
drv_data->rx_channel = -1;
if (platform_info->enable_dma) { if (platform_info->enable_dma) {
status = pxa2xx_spi_dma_setup(drv_data); status = pxa2xx_spi_dma_setup(drv_data);
if (status) { if (status) {
......
...@@ -36,11 +36,6 @@ struct driver_data { ...@@ -36,11 +36,6 @@ struct driver_data {
/* PXA hookup */ /* PXA hookup */
struct pxa2xx_spi_master *master_info; struct pxa2xx_spi_master *master_info;
/* PXA private DMA setup stuff */
int rx_channel;
int tx_channel;
u32 *null_dma_buf;
/* SSP register addresses */ /* SSP register addresses */
void __iomem *ioaddr; void __iomem *ioaddr;
u32 ssdr_physical; u32 ssdr_physical;
......
...@@ -645,7 +645,6 @@ static int rockchip_spi_probe(struct platform_device *pdev) ...@@ -645,7 +645,6 @@ static int rockchip_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
rs = spi_master_get_devdata(master); rs = spi_master_get_devdata(master);
memset(rs, 0, sizeof(struct rockchip_spi));
/* Get basic io resource and map it */ /* Get basic io resource and map it */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......
...@@ -383,7 +383,8 @@ static void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg) ...@@ -383,7 +383,8 @@ static void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg)
rspi_write8(rspi, data, reg); rspi_write8(rspi, data, reg);
} }
static int qspi_set_send_trigger(struct rspi_data *rspi, unsigned int len) static unsigned int qspi_set_send_trigger(struct rspi_data *rspi,
unsigned int len)
{ {
unsigned int n; unsigned int n;
...@@ -724,25 +725,25 @@ static int rspi_rz_transfer_one(struct spi_master *master, ...@@ -724,25 +725,25 @@ static int rspi_rz_transfer_one(struct spi_master *master,
static int qspi_trigger_transfer_out_in(struct rspi_data *rspi, const u8 *tx, static int qspi_trigger_transfer_out_in(struct rspi_data *rspi, const u8 *tx,
u8 *rx, unsigned int len) u8 *rx, unsigned int len)
{ {
int i, n, ret; unsigned int i, n;
int error; int ret;
while (len > 0) { while (len > 0) {
n = qspi_set_send_trigger(rspi, len); n = qspi_set_send_trigger(rspi, len);
qspi_set_receive_trigger(rspi, len); qspi_set_receive_trigger(rspi, len);
if (n == QSPI_BUFFER_SIZE) { if (n == QSPI_BUFFER_SIZE) {
error = rspi_wait_for_tx_empty(rspi); ret = rspi_wait_for_tx_empty(rspi);
if (error < 0) { if (ret < 0) {
dev_err(&rspi->master->dev, "transmit timeout\n"); dev_err(&rspi->master->dev, "transmit timeout\n");
return error; return ret;
} }
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
rspi_write_data(rspi, *tx++); rspi_write_data(rspi, *tx++);
error = rspi_wait_for_rx_full(rspi); ret = rspi_wait_for_rx_full(rspi);
if (error < 0) { if (ret < 0) {
dev_err(&rspi->master->dev, "receive timeout\n"); dev_err(&rspi->master->dev, "receive timeout\n");
return error; return ret;
} }
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
*rx++ = rspi_read_data(rspi); *rx++ = rspi_read_data(rspi);
......
...@@ -501,7 +501,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) ...@@ -501,7 +501,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
} }
hw = spi_master_get_devdata(master); hw = spi_master_get_devdata(master);
memset(hw, 0, sizeof(struct s3c24xx_spi));
hw->master = master; hw->master = master;
hw->pdata = pdata = dev_get_platdata(&pdev->dev); hw->pdata = pdata = dev_get_platdata(&pdev->dev);
......
...@@ -1191,8 +1191,8 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) ...@@ -1191,8 +1191,8 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Slaves attached\n", dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Slaves attached\n",
sdd->port_id, master->num_chipselect); sdd->port_id, master->num_chipselect);
dev_dbg(&pdev->dev, "\tIOmem=[%pR]\tDMA=[Rx-%d, Tx-%d]\n", dev_dbg(&pdev->dev, "\tIOmem=[%pR]\tFIFO %dbytes\tDMA=[Rx-%d, Tx-%d]\n",
mem_res, mem_res, (FIFO_LVL_MASK(sdd) >> 1) + 1,
sdd->rx_dma.dmach, sdd->tx_dma.dmach); sdd->rx_dma.dmach, sdd->tx_dma.dmach);
return 0; return 0;
......
...@@ -48,8 +48,8 @@ struct sh_msiof_spi_priv { ...@@ -48,8 +48,8 @@ struct sh_msiof_spi_priv {
const struct sh_msiof_chipdata *chipdata; const struct sh_msiof_chipdata *chipdata;
struct sh_msiof_spi_info *info; struct sh_msiof_spi_info *info;
struct completion done; struct completion done;
int tx_fifo_size; unsigned int tx_fifo_size;
int rx_fifo_size; unsigned int rx_fifo_size;
void *tx_dma_page; void *tx_dma_page;
void *rx_dma_page; void *rx_dma_page;
dma_addr_t tx_dma_addr; dma_addr_t tx_dma_addr;
...@@ -95,8 +95,6 @@ struct sh_msiof_spi_priv { ...@@ -95,8 +95,6 @@ struct sh_msiof_spi_priv {
#define MDR2_WDLEN1(i) (((i) - 1) << 16) /* Word Count (1-64/256 (SH, A1))) */ #define MDR2_WDLEN1(i) (((i) - 1) << 16) /* Word Count (1-64/256 (SH, A1))) */
#define MDR2_GRPMASK1 0x00000001 /* Group Output Mask 1 (SH, A1) */ #define MDR2_GRPMASK1 0x00000001 /* Group Output Mask 1 (SH, A1) */
#define MAX_WDLEN 256U
/* TSCR and RSCR */ /* TSCR and RSCR */
#define SCR_BRPS_MASK 0x1f00 /* Prescaler Setting (1-32) */ #define SCR_BRPS_MASK 0x1f00 /* Prescaler Setting (1-32) */
#define SCR_BRPS(i) (((i) - 1) << 8) #define SCR_BRPS(i) (((i) - 1) << 8)
...@@ -850,7 +848,12 @@ static int sh_msiof_transfer_one(struct spi_master *master, ...@@ -850,7 +848,12 @@ static int sh_msiof_transfer_one(struct spi_master *master,
* DMA supports 32-bit words only, hence pack 8-bit and 16-bit * DMA supports 32-bit words only, hence pack 8-bit and 16-bit
* words, with byte resp. word swapping. * words, with byte resp. word swapping.
*/ */
unsigned int l = min(len, MAX_WDLEN * 4); unsigned int l = 0;
if (tx_buf)
l = min(len, p->tx_fifo_size * 4);
if (rx_buf)
l = min(len, p->rx_fifo_size * 4);
if (bits <= 8) { if (bits <= 8) {
if (l & 3) if (l & 3)
...@@ -963,7 +966,7 @@ static const struct sh_msiof_chipdata sh_data = { ...@@ -963,7 +966,7 @@ static const struct sh_msiof_chipdata sh_data = {
static const struct sh_msiof_chipdata r8a779x_data = { static const struct sh_msiof_chipdata r8a779x_data = {
.tx_fifo_size = 64, .tx_fifo_size = 64,
.rx_fifo_size = 256, .rx_fifo_size = 64,
.master_flags = SPI_MASTER_MUST_TX, .master_flags = SPI_MASTER_MUST_TX,
}; };
...@@ -1265,11 +1268,6 @@ static int sh_msiof_spi_remove(struct platform_device *pdev) ...@@ -1265,11 +1268,6 @@ static int sh_msiof_spi_remove(struct platform_device *pdev)
static const struct platform_device_id spi_driver_ids[] = { static const struct platform_device_id spi_driver_ids[] = {
{ "spi_sh_msiof", (kernel_ulong_t)&sh_data }, { "spi_sh_msiof", (kernel_ulong_t)&sh_data },
{ "spi_r8a7790_msiof", (kernel_ulong_t)&r8a779x_data },
{ "spi_r8a7791_msiof", (kernel_ulong_t)&r8a779x_data },
{ "spi_r8a7792_msiof", (kernel_ulong_t)&r8a779x_data },
{ "spi_r8a7793_msiof", (kernel_ulong_t)&r8a779x_data },
{ "spi_r8a7794_msiof", (kernel_ulong_t)&r8a779x_data },
{}, {},
}; };
MODULE_DEVICE_TABLE(platform, spi_driver_ids); MODULE_DEVICE_TABLE(platform, spi_driver_ids);
......
...@@ -99,6 +99,8 @@ struct ti_qspi { ...@@ -99,6 +99,8 @@ struct ti_qspi {
#define QSPI_INVAL (4 << 16) #define QSPI_INVAL (4 << 16)
#define QSPI_WC_CMD_INT_EN (1 << 14) #define QSPI_WC_CMD_INT_EN (1 << 14)
#define QSPI_FLEN(n) ((n - 1) << 0) #define QSPI_FLEN(n) ((n - 1) << 0)
#define QSPI_WLEN_MAX_BITS 128
#define QSPI_WLEN_MAX_BYTES 16
/* STATUS REGISTER */ /* STATUS REGISTER */
#define BUSY 0x01 #define BUSY 0x01
...@@ -217,14 +219,16 @@ static inline u32 qspi_is_busy(struct ti_qspi *qspi) ...@@ -217,14 +219,16 @@ static inline u32 qspi_is_busy(struct ti_qspi *qspi)
static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t) static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
{ {
int wlen, count; int wlen, count, xfer_len;
unsigned int cmd; unsigned int cmd;
const u8 *txbuf; const u8 *txbuf;
u32 data;
txbuf = t->tx_buf; txbuf = t->tx_buf;
cmd = qspi->cmd | QSPI_WR_SNGL; cmd = qspi->cmd | QSPI_WR_SNGL;
count = t->len; count = t->len;
wlen = t->bits_per_word >> 3; /* in bytes */ wlen = t->bits_per_word >> 3; /* in bytes */
xfer_len = wlen;
while (count) { while (count) {
if (qspi_is_busy(qspi)) if (qspi_is_busy(qspi))
...@@ -234,7 +238,29 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t) ...@@ -234,7 +238,29 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
case 1: case 1:
dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %02x\n", dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %02x\n",
cmd, qspi->dc, *txbuf); cmd, qspi->dc, *txbuf);
writeb(*txbuf, qspi->base + QSPI_SPI_DATA_REG); if (count >= QSPI_WLEN_MAX_BYTES) {
u32 *txp = (u32 *)txbuf;
data = cpu_to_be32(*txp++);
writel(data, qspi->base +
QSPI_SPI_DATA_REG_3);
data = cpu_to_be32(*txp++);
writel(data, qspi->base +
QSPI_SPI_DATA_REG_2);
data = cpu_to_be32(*txp++);
writel(data, qspi->base +
QSPI_SPI_DATA_REG_1);
data = cpu_to_be32(*txp++);
writel(data, qspi->base +
QSPI_SPI_DATA_REG);
xfer_len = QSPI_WLEN_MAX_BYTES;
cmd |= QSPI_WLEN(QSPI_WLEN_MAX_BITS);
} else {
writeb(*txbuf, qspi->base + QSPI_SPI_DATA_REG);
cmd = qspi->cmd | QSPI_WR_SNGL;
xfer_len = wlen;
cmd |= QSPI_WLEN(wlen);
}
break; break;
case 2: case 2:
dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %04x\n", dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %04x\n",
...@@ -254,8 +280,8 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t) ...@@ -254,8 +280,8 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
dev_err(qspi->dev, "write timed out\n"); dev_err(qspi->dev, "write timed out\n");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
txbuf += wlen; txbuf += xfer_len;
count -= wlen; count -= xfer_len;
} }
return 0; return 0;
......
...@@ -237,11 +237,11 @@ static const struct i2c_device_id spi_xcomm_ids[] = { ...@@ -237,11 +237,11 @@ static const struct i2c_device_id spi_xcomm_ids[] = {
{ "spi-xcomm" }, { "spi-xcomm" },
{ }, { },
}; };
MODULE_DEVICE_TABLE(i2c, spi_xcomm_ids);
static struct i2c_driver spi_xcomm_driver = { static struct i2c_driver spi_xcomm_driver = {
.driver = { .driver = {
.name = "spi-xcomm", .name = "spi-xcomm",
.owner = THIS_MODULE,
}, },
.id_table = spi_xcomm_ids, .id_table = spi_xcomm_ids,
.probe = spi_xcomm_probe, .probe = spi_xcomm_probe,
......
...@@ -249,19 +249,23 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) ...@@ -249,19 +249,23 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
xspi->tx_ptr = t->tx_buf; xspi->tx_ptr = t->tx_buf;
xspi->rx_ptr = t->rx_buf; xspi->rx_ptr = t->rx_buf;
remaining_words = t->len / xspi->bytes_per_word; remaining_words = t->len / xspi->bytes_per_word;
reinit_completion(&xspi->done);
if (xspi->irq >= 0 && remaining_words > xspi->buffer_size) { if (xspi->irq >= 0 && remaining_words > xspi->buffer_size) {
u32 isr;
use_irq = true; use_irq = true;
xspi->write_fn(XSPI_INTR_TX_EMPTY,
xspi->regs + XIPIF_V123B_IISR_OFFSET);
/* Enable the global IPIF interrupt */
xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
xspi->regs + XIPIF_V123B_DGIER_OFFSET);
/* Inhibit irq to avoid spurious irqs on tx_empty*/ /* Inhibit irq to avoid spurious irqs on tx_empty*/
cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET); cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT, xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
xspi->regs + XSPI_CR_OFFSET); xspi->regs + XSPI_CR_OFFSET);
/* ACK old irqs (if any) */
isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
if (isr)
xspi->write_fn(isr,
xspi->regs + XIPIF_V123B_IISR_OFFSET);
/* Enable the global IPIF interrupt */
xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
xspi->regs + XIPIF_V123B_DGIER_OFFSET);
reinit_completion(&xspi->done);
} }
while (remaining_words) { while (remaining_words) {
...@@ -302,8 +306,10 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) ...@@ -302,8 +306,10 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
remaining_words -= n_words; remaining_words -= n_words;
} }
if (use_irq) if (use_irq) {
xspi->write_fn(0, xspi->regs + XIPIF_V123B_DGIER_OFFSET); xspi->write_fn(0, xspi->regs + XIPIF_V123B_DGIER_OFFSET);
xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
}
return t->len; return t->len;
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -602,11 +602,11 @@ static int spidev_open(struct inode *inode, struct file *filp) ...@@ -602,11 +602,11 @@ static int spidev_open(struct inode *inode, struct file *filp)
if (!spidev->tx_buffer) { if (!spidev->tx_buffer) {
spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL); spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL);
if (!spidev->tx_buffer) { if (!spidev->tx_buffer) {
dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
status = -ENOMEM; status = -ENOMEM;
goto err_find_dev; goto err_find_dev;
}
} }
}
if (!spidev->rx_buffer) { if (!spidev->rx_buffer) {
spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL); spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL);
...@@ -709,7 +709,7 @@ static int spidev_probe(struct spi_device *spi) ...@@ -709,7 +709,7 @@ static int spidev_probe(struct spi_device *spi)
/* /*
* spidev should never be referenced in DT without a specific * spidev should never be referenced in DT without a specific
* compatbile string, it is a Linux implementation thing * compatible string, it is a Linux implementation thing
* rather than a description of the hardware. * rather than a description of the hardware.
*/ */
if (spi->dev.of_node && !of_match_device(spidev_dt_ids, &spi->dev)) { if (spi->dev.of_node && !of_match_device(spidev_dt_ids, &spi->dev)) {
......
...@@ -49,6 +49,7 @@ struct davinci_spi_platform_data { ...@@ -49,6 +49,7 @@ struct davinci_spi_platform_data {
u8 num_chipselect; u8 num_chipselect;
u8 intr_line; u8 intr_line;
u8 *chip_sel; u8 *chip_sel;
u8 prescaler_limit;
bool cshold_bug; bool cshold_bug;
enum dma_event_q dma_event_q; enum dma_event_q dma_event_q;
}; };
......
/*
* MTK SPI bus driver definitions
*
* Copyright (c) 2015 MediaTek Inc.
* Author: Leilk Liu <leilk.liu@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef ____LINUX_PLATFORM_DATA_SPI_MTK_H
#define ____LINUX_PLATFORM_DATA_SPI_MTK_H
/* Board specific platform_data */
struct mtk_chip_config {
u32 tx_mlsb;
u32 rx_mlsb;
};
#endif
...@@ -197,6 +197,7 @@ enum pxa_ssp_type { ...@@ -197,6 +197,7 @@ enum pxa_ssp_type {
QUARK_X1000_SSP, QUARK_X1000_SSP,
LPSS_LPT_SSP, /* Keep LPSS types sorted with lpss_platforms[] */ LPSS_LPT_SSP, /* Keep LPSS types sorted with lpss_platforms[] */
LPSS_BYT_SSP, LPSS_BYT_SSP,
LPSS_SPT_SSP,
}; };
struct ssp_device { struct ssp_device {
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
struct dma_chan; struct dma_chan;
struct spi_master;
struct spi_transfer;
/* /*
* INTERFACES between SPI master-side drivers and SPI infrastructure. * INTERFACES between SPI master-side drivers and SPI infrastructure.
...@@ -30,6 +32,59 @@ struct dma_chan; ...@@ -30,6 +32,59 @@ struct dma_chan;
*/ */
extern struct bus_type spi_bus_type; extern struct bus_type spi_bus_type;
/**
* struct spi_statistics - statistics for spi transfers
* @clock: lock protecting this structure
*
* @messages: number of spi-messages handled
* @transfers: number of spi_transfers handled
* @errors: number of errors during spi_transfer
* @timedout: number of timeouts during spi_transfer
*
* @spi_sync: number of times spi_sync is used
* @spi_sync_immediate:
* number of times spi_sync is executed immediately
* in calling context without queuing and scheduling
* @spi_async: number of times spi_async is used
*
* @bytes: number of bytes transferred to/from device
* @bytes_tx: number of bytes sent to device
* @bytes_rx: number of bytes received from device
*
*/
struct spi_statistics {
spinlock_t lock; /* lock for the whole structure */
unsigned long messages;
unsigned long transfers;
unsigned long errors;
unsigned long timedout;
unsigned long spi_sync;
unsigned long spi_sync_immediate;
unsigned long spi_async;
unsigned long long bytes;
unsigned long long bytes_rx;
unsigned long long bytes_tx;
};
void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
struct spi_transfer *xfer,
struct spi_master *master);
#define SPI_STATISTICS_ADD_TO_FIELD(stats, field, count) \
do { \
unsigned long flags; \
spin_lock_irqsave(&(stats)->lock, flags); \
(stats)->field += count; \
spin_unlock_irqrestore(&(stats)->lock, flags); \
} while (0)
#define SPI_STATISTICS_INCREMENT_FIELD(stats, field) \
SPI_STATISTICS_ADD_TO_FIELD(stats, field, 1)
/** /**
* struct spi_device - Master side proxy for an SPI slave device * struct spi_device - Master side proxy for an SPI slave device
* @dev: Driver model representation of the device. * @dev: Driver model representation of the device.
...@@ -60,6 +115,8 @@ extern struct bus_type spi_bus_type; ...@@ -60,6 +115,8 @@ extern struct bus_type spi_bus_type;
* @cs_gpio: gpio number of the chipselect line (optional, -ENOENT when * @cs_gpio: gpio number of the chipselect line (optional, -ENOENT when
* when not using a GPIO line) * when not using a GPIO line)
* *
* @statistics: statistics for the spi_device
*
* A @spi_device is used to interchange data between an SPI slave * A @spi_device is used to interchange data between an SPI slave
* (usually a discrete chip) and CPU memory. * (usually a discrete chip) and CPU memory.
* *
...@@ -98,6 +155,9 @@ struct spi_device { ...@@ -98,6 +155,9 @@ struct spi_device {
char modalias[SPI_NAME_SIZE]; char modalias[SPI_NAME_SIZE];
int cs_gpio; /* chip select gpio */ int cs_gpio; /* chip select gpio */
/* the statistics */
struct spi_statistics statistics;
/* /*
* likely need more hooks for more protocol options affecting how * likely need more hooks for more protocol options affecting how
* the controller talks to each chip, like: * the controller talks to each chip, like:
...@@ -296,6 +356,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) ...@@ -296,6 +356,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
* @cs_gpios: Array of GPIOs to use as chip select lines; one per CS * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
* number. Any individual value may be -ENOENT for CS lines that * number. Any individual value may be -ENOENT for CS lines that
* are not GPIOs (driven by the SPI controller itself). * are not GPIOs (driven by the SPI controller itself).
* @statistics: statistics for the spi_master
* @dma_tx: DMA transmit channel * @dma_tx: DMA transmit channel
* @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
...@@ -452,6 +513,9 @@ struct spi_master { ...@@ -452,6 +513,9 @@ struct spi_master {
/* gpio chip select */ /* gpio chip select */
int *cs_gpios; int *cs_gpios;
/* statistics */
struct spi_statistics statistics;
/* DMA channels for use with core dmaengine helpers */ /* DMA channels for use with core dmaengine helpers */
struct dma_chan *dma_tx; struct dma_chan *dma_tx;
struct dma_chan *dma_rx; struct dma_chan *dma_rx;
......
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