Commit e5aeced6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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 {
union {
u8 mode; /* PSC + 0x00 */ 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));
......
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