Commit d2f68a05 authored by Mark Brown's avatar Mark Brown

Merge tag 'spi-fix-v4.10-rc4' into spi-linus

spi: Fixes for v4.10

The usual small smattering of driver specific fixes.  A few bits that
stand out here:

 - The R-Car patches adding fallbacks are just adding new compatible
   strings to the driver so that device trees are written in a more
   robustly future proof fashion, this isn't strictly a fix but it's
   just new IDs and it's better to get it into mainline sooner to
   improve the ABI.
 - The DesignWare "switch to new API part 2" patch is actually a
   misleadingly titled fix for a bit that got missed in the original
   conversion.

# gpg: Signature made Thu 19 Jan 2017 14:54:15 GMT
# gpg:                using RSA key ADE668AA675718B59FE29FEA24D68B725D5487D0
# gpg:                issuer "broonie@kernel.org"
# gpg: key 0D9EACE2CD7BEEBC: no public key for trusted key - skipped
# gpg: key 0D9EACE2CD7BEEBC marked as ultimately trusted
# gpg: key CCB0A420AF88CD16: no public key for trusted key - skipped
# gpg: key CCB0A420AF88CD16 marked as ultimately trusted
# gpg: key 162614E316005C11: no public key for trusted key - skipped
# gpg: key 162614E316005C11 marked as ultimately trusted
# gpg: key A730C53A5621E907: no public key for trusted key - skipped
# gpg: key A730C53A5621E907 marked as ultimately trusted
# gpg: key 276568D75C6153AD: no public key for trusted key - skipped
# gpg: key 276568D75C6153AD marked as ultimately trusted
# gpg: Good signature from "Mark Brown <broonie@sirena.org.uk>" [ultimate]
# gpg:                 aka "Mark Brown <broonie@debian.org>" [ultimate]
# gpg:                 aka "Mark Brown <broonie@kernel.org>" [ultimate]
# gpg:                 aka "Mark Brown <broonie@tardis.ed.ac.uk>" [ultimate]
# gpg:                 aka "Mark Brown <broonie@linaro.org>" [ultimate]
# gpg:                 aka "Mark Brown <Mark.Brown@linaro.org>" [ultimate]
parents 69973b83 52cc720c
Renesas MSIOF spi controller Renesas MSIOF spi controller
Required properties: Required properties:
- compatible : "renesas,msiof-<soctype>" for SoCs, - compatible : "renesas,msiof-r8a7790" (R-Car H2)
"renesas,sh-msiof" for SuperH, or
"renesas,sh-mobile-msiof" for SH Mobile series.
Examples with soctypes are:
"renesas,msiof-r8a7790" (R-Car H2)
"renesas,msiof-r8a7791" (R-Car M2-W) "renesas,msiof-r8a7791" (R-Car M2-W)
"renesas,msiof-r8a7792" (R-Car V2H) "renesas,msiof-r8a7792" (R-Car V2H)
"renesas,msiof-r8a7793" (R-Car M2-N) "renesas,msiof-r8a7793" (R-Car M2-N)
"renesas,msiof-r8a7794" (R-Car E2) "renesas,msiof-r8a7794" (R-Car E2)
"renesas,msiof-r8a7796" (R-Car M3-W)
"renesas,msiof-sh73a0" (SH-Mobile AG5) "renesas,msiof-sh73a0" (SH-Mobile AG5)
"renesas,sh-mobile-msiof" (generic SH-Mobile compatibile device)
"renesas,rcar-gen2-msiof" (generic R-Car Gen2 compatible device)
"renesas,rcar-gen3-msiof" (generic R-Car Gen3 compatible device)
"renesas,sh-msiof" (deprecated)
When compatible with the generic version, nodes
must list the SoC-specific version corresponding
to the platform first followed by the generic
version.
- reg : A list of offsets and lengths of the register sets for - reg : A list of offsets and lengths of the register sets for
the device. the device.
If only one register set is present, it is to be used If only one register set is present, it is to be used
...@@ -60,7 +67,8 @@ Documentation/devicetree/bindings/pinctrl/renesas,*. ...@@ -60,7 +67,8 @@ Documentation/devicetree/bindings/pinctrl/renesas,*.
Example: Example:
msiof0: spi@e6e20000 { msiof0: spi@e6e20000 {
compatible = "renesas,msiof-r8a7791"; compatible = "renesas,msiof-r8a7791",
"renesas,rcar-gen2-msiof";
reg = <0 0xe6e20000 0 0x0064>; reg = <0 0xe6e20000 0 0x0064>;
interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>; clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>;
......
* Marvell Armada 3700 SPI Controller
Required Properties:
- compatible: should be "marvell,armada-3700-spi"
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: The interrupt number. The interrupt specifier format depends on
the interrupt controller and of its driver.
- clocks: Must contain the clock source, usually from the North Bridge clocks.
- num-cs: The number of chip selects that is supported by this SPI Controller
- #address-cells: should be 1.
- #size-cells: should be 0.
Example:
spi0: spi@10600 {
compatible = "marvell,armada-3700-spi";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x10600 0x5d>;
clocks = <&nb_perih_clk 7>;
interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
num-cs = <4>;
};
* Freescale Low Power SPI (LPSPI) for i.MX
Required properties:
- compatible :
- "fsl,imx7ulp-spi" for LPSPI compatible with the one integrated on i.MX7ULP soc
- reg : address and length of the lpspi master registers
- interrupt-parent : core interrupt controller
- interrupts : lpspi interrupt
- clocks : lpspi clock specifier
Examples:
lpspi2: lpspi@40290000 {
compatible = "fsl,imx7ulp-spi";
reg = <0x40290000 0x10000>;
interrupt-parent = <&intc>;
interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7ULP_CLK_LPSPI2>;
};
Allwinner A31 SPI controller Allwinner A31/H3 SPI controller
Required properties: Required properties:
- compatible: Should be "allwinner,sun6i-a31-spi". - compatible: Should be "allwinner,sun6i-a31-spi" or "allwinner,sun8i-h3-spi".
- reg: Should contain register location and length. - reg: Should contain register location and length.
- interrupts: Should contain interrupt. - interrupts: Should contain interrupt.
- clocks: phandle to the clocks feeding the SPI controller. Two are - clocks: phandle to the clocks feeding the SPI controller. Two are
...@@ -12,6 +12,11 @@ Required properties: ...@@ -12,6 +12,11 @@ Required properties:
- resets: phandle to the reset controller asserting this device in - resets: phandle to the reset controller asserting this device in
reset reset
Optional properties:
- dmas: DMA specifiers for rx and tx dma. See the DMA client binding,
Documentation/devicetree/bindings/dma/dma.txt
- dma-names: DMA request names should include "rx" and "tx" if present.
Example: Example:
spi1: spi@01c69000 { spi1: spi@01c69000 {
...@@ -22,3 +27,19 @@ spi1: spi@01c69000 { ...@@ -22,3 +27,19 @@ spi1: spi@01c69000 {
clock-names = "ahb", "mod"; clock-names = "ahb", "mod";
resets = <&ahb1_rst 21>; resets = <&ahb1_rst 21>;
}; };
spi0: spi@01c68000 {
compatible = "allwinner,sun8i-h3-spi";
reg = <0x01c68000 0x1000>;
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
clock-names = "ahb", "mod";
dmas = <&dma 23>, <&dma 23>;
dma-names = "rx", "tx";
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
resets = <&ccu RST_BUS_SPI0>;
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
};
...@@ -67,6 +67,13 @@ config SPI_ATH79 ...@@ -67,6 +67,13 @@ config SPI_ATH79
This enables support for the SPI controller present on the This enables support for the SPI controller present on the
Atheros AR71XX/AR724X/AR913X SoCs. Atheros AR71XX/AR724X/AR913X SoCs.
config SPI_ARMADA_3700
tristate "Marvell Armada 3700 SPI Controller"
depends on (ARCH_MVEBU && OF) || COMPILE_TEST
help
This enables support for the SPI controller present on the
Marvell Armada 3700 SoCs.
config SPI_ATMEL config SPI_ATMEL
tristate "Atmel SPI Controller" tristate "Atmel SPI Controller"
depends on HAS_DMA depends on HAS_DMA
...@@ -264,6 +271,12 @@ config SPI_FALCON ...@@ -264,6 +271,12 @@ config SPI_FALCON
has only been tested with m25p80 type chips. The hardware has no has only been tested with m25p80 type chips. The hardware has no
support for other types of SPI peripherals. support for other types of SPI peripherals.
config SPI_FSL_LPSPI
tristate "Freescale i.MX LPSPI controller"
depends on ARCH_MXC || COMPILE_TEST
help
This enables Freescale i.MX LPSPI controllers in master mode.
config SPI_GPIO config SPI_GPIO
tristate "GPIO-based bitbanging SPI Master" tristate "GPIO-based bitbanging SPI Master"
depends on GPIOLIB || COMPILE_TEST depends on GPIOLIB || COMPILE_TEST
...@@ -365,6 +378,7 @@ config SPI_FSL_SPI ...@@ -365,6 +378,7 @@ config SPI_FSL_SPI
config SPI_FSL_DSPI config SPI_FSL_DSPI
tristate "Freescale DSPI controller" tristate "Freescale DSPI controller"
select REGMAP_MMIO select REGMAP_MMIO
depends on HAS_DMA
depends on SOC_VF610 || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST depends on SOC_VF610 || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST
help help
This enables support for the Freescale DSPI controller in master This enables support for the Freescale DSPI controller in master
...@@ -373,7 +387,6 @@ config SPI_FSL_DSPI ...@@ -373,7 +387,6 @@ config SPI_FSL_DSPI
config SPI_FSL_ESPI config SPI_FSL_ESPI
tristate "Freescale eSPI controller" tristate "Freescale eSPI controller"
depends on FSL_SOC depends on FSL_SOC
select SPI_FSL_LIB
help help
This enables using the Freescale eSPI controllers in master mode. This enables using the Freescale eSPI controllers in master mode.
From MPC8536, 85xx platform uses the controller, and all P10xx, From MPC8536, 85xx platform uses the controller, and all P10xx,
...@@ -451,7 +464,8 @@ config SPI_ORION ...@@ -451,7 +464,8 @@ config SPI_ORION
tristate "Orion SPI master" tristate "Orion SPI master"
depends on PLAT_ORION || ARCH_MVEBU || COMPILE_TEST depends on PLAT_ORION || ARCH_MVEBU || COMPILE_TEST
help help
This enables using the SPI master controller on the Orion chips. This enables using the SPI master controller on the Orion
and MVEBU chips.
config SPI_PIC32 config SPI_PIC32
tristate "Microchip PIC32 series SPI" tristate "Microchip PIC32 series SPI"
...@@ -553,7 +567,7 @@ config SPI_S3C24XX_FIQ ...@@ -553,7 +567,7 @@ config SPI_S3C24XX_FIQ
config SPI_S3C64XX config SPI_S3C64XX
tristate "Samsung S3C64XX series type SPI" tristate "Samsung S3C64XX series type SPI"
depends on (PLAT_SAMSUNG || ARCH_EXYNOS) depends on (PLAT_SAMSUNG || ARCH_EXYNOS || COMPILE_TEST)
help help
SPI driver for Samsung S3C64XX and newer SoCs. SPI driver for Samsung S3C64XX and newer SoCs.
......
...@@ -12,6 +12,7 @@ obj-$(CONFIG_SPI_LOOPBACK_TEST) += spi-loopback-test.o ...@@ -12,6 +12,7 @@ obj-$(CONFIG_SPI_LOOPBACK_TEST) += spi-loopback-test.o
# SPI master controller drivers (bus) # SPI master controller drivers (bus)
obj-$(CONFIG_SPI_ALTERA) += spi-altera.o obj-$(CONFIG_SPI_ALTERA) += spi-altera.o
obj-$(CONFIG_SPI_ARMADA_3700) += spi-armada-3700.o
obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o
obj-$(CONFIG_SPI_ATH79) += spi-ath79.o obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
obj-$(CONFIG_SPI_AU1550) += spi-au1550.o obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
...@@ -43,6 +44,7 @@ obj-$(CONFIG_SPI_FSL_CPM) += spi-fsl-cpm.o ...@@ -43,6 +44,7 @@ obj-$(CONFIG_SPI_FSL_CPM) += spi-fsl-cpm.o
obj-$(CONFIG_SPI_FSL_DSPI) += spi-fsl-dspi.o obj-$(CONFIG_SPI_FSL_DSPI) += spi-fsl-dspi.o
obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o
obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o
obj-$(CONFIG_SPI_FSL_LPSPI) += spi-fsl-lpspi.o
obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
obj-$(CONFIG_SPI_GPIO) += spi-gpio.o obj-$(CONFIG_SPI_GPIO) += spi-gpio.o
obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o
......
This diff is collapsed.
...@@ -304,6 +304,7 @@ static const struct of_device_id ath79_spi_of_match[] = { ...@@ -304,6 +304,7 @@ static const struct of_device_id ath79_spi_of_match[] = {
{ .compatible = "qca,ar7100-spi", }, { .compatible = "qca,ar7100-spi", },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, ath79_spi_of_match);
static struct platform_driver ath79_spi_driver = { static struct platform_driver ath79_spi_driver = {
.probe = ath79_spi_probe, .probe = ath79_spi_probe,
......
This diff is collapsed.
...@@ -494,7 +494,8 @@ static int spi_engine_probe(struct platform_device *pdev) ...@@ -494,7 +494,8 @@ static int spi_engine_probe(struct platform_device *pdev)
SPI_ENGINE_VERSION_MAJOR(version), SPI_ENGINE_VERSION_MAJOR(version),
SPI_ENGINE_VERSION_MINOR(version), SPI_ENGINE_VERSION_MINOR(version),
SPI_ENGINE_VERSION_PATCH(version)); SPI_ENGINE_VERSION_PATCH(version));
return -ENODEV; ret = -ENODEV;
goto err_put_master;
} }
spi_engine->clk = devm_clk_get(&pdev->dev, "s_axi_aclk"); spi_engine->clk = devm_clk_get(&pdev->dev, "s_axi_aclk");
...@@ -574,6 +575,7 @@ static const struct of_device_id spi_engine_match_table[] = { ...@@ -574,6 +575,7 @@ static const struct of_device_id spi_engine_match_table[] = {
{ .compatible = "adi,axi-spi-engine-1.00.a" }, { .compatible = "adi,axi-spi-engine-1.00.a" },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, spi_engine_match_table);
static struct platform_driver spi_engine_driver = { static struct platform_driver spi_engine_driver = {
.probe = spi_engine_probe, .probe = spi_engine_probe,
......
...@@ -646,7 +646,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) ...@@ -646,7 +646,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
buf = t->rx_buf; buf = t->rx_buf;
t->rx_dma = dma_map_single(&spi->dev, buf, t->rx_dma = dma_map_single(&spi->dev, buf,
t->len, DMA_FROM_DEVICE); t->len, DMA_FROM_DEVICE);
if (!t->rx_dma) { if (dma_mapping_error(&spi->dev, !t->rx_dma)) {
ret = -EFAULT; ret = -EFAULT;
goto err_rx_map; goto err_rx_map;
} }
...@@ -660,7 +660,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) ...@@ -660,7 +660,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
buf = (void *)t->tx_buf; buf = (void *)t->tx_buf;
t->tx_dma = dma_map_single(&spi->dev, buf, t->tx_dma = dma_map_single(&spi->dev, buf,
t->len, DMA_TO_DEVICE); t->len, DMA_TO_DEVICE);
if (!t->tx_dma) { if (dma_mapping_error(&spi->dev, t->tx_dma)) {
ret = -EFAULT; ret = -EFAULT;
goto err_tx_map; goto err_tx_map;
} }
......
...@@ -274,11 +274,11 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, struct spi_transfer *xfer) ...@@ -274,11 +274,11 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, struct spi_transfer *xfer)
static void mid_spi_dma_stop(struct dw_spi *dws) static void mid_spi_dma_stop(struct dw_spi *dws)
{ {
if (test_bit(TX_BUSY, &dws->dma_chan_busy)) { if (test_bit(TX_BUSY, &dws->dma_chan_busy)) {
dmaengine_terminate_all(dws->txchan); dmaengine_terminate_sync(dws->txchan);
clear_bit(TX_BUSY, &dws->dma_chan_busy); clear_bit(TX_BUSY, &dws->dma_chan_busy);
} }
if (test_bit(RX_BUSY, &dws->dma_chan_busy)) { if (test_bit(RX_BUSY, &dws->dma_chan_busy)) {
dmaengine_terminate_all(dws->rxchan); dmaengine_terminate_sync(dws->rxchan);
clear_bit(RX_BUSY, &dws->dma_chan_busy); clear_bit(RX_BUSY, &dws->dma_chan_busy);
} }
} }
......
...@@ -107,7 +107,10 @@ static const struct file_operations dw_spi_regs_ops = { ...@@ -107,7 +107,10 @@ static const struct file_operations dw_spi_regs_ops = {
static int dw_spi_debugfs_init(struct dw_spi *dws) static int dw_spi_debugfs_init(struct dw_spi *dws)
{ {
dws->debugfs = debugfs_create_dir("dw_spi", NULL); char name[128];
snprintf(name, 128, "dw_spi-%s", dev_name(&dws->master->dev));
dws->debugfs = debugfs_create_dir(name, NULL);
if (!dws->debugfs) if (!dws->debugfs)
return -ENOMEM; return -ENOMEM;
...@@ -502,6 +505,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) ...@@ -502,6 +505,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
master->handle_err = dw_spi_handle_err; master->handle_err = dw_spi_handle_err;
master->max_speed_hz = dws->max_freq; master->max_speed_hz = dws->max_freq;
master->dev.of_node = dev->of_node; master->dev.of_node = dev->of_node;
master->flags = SPI_MASTER_GPIO_SS;
/* Basic HW init */ /* Basic HW init */
spi_hw_init(dev, dws); spi_hw_init(dev, dws);
......
This diff is collapsed.
This diff is collapsed.
...@@ -28,10 +28,6 @@ struct mpc8xxx_spi { ...@@ -28,10 +28,6 @@ struct mpc8xxx_spi {
/* rx & tx bufs from the spi_transfer */ /* rx & tx bufs from the spi_transfer */
const void *tx; const void *tx;
void *rx; void *rx;
#if IS_ENABLED(CONFIG_SPI_FSL_ESPI)
int len;
u8 *local_buf;
#endif
int subblock; int subblock;
struct spi_pram __iomem *pram; struct spi_pram __iomem *pram;
......
This diff is collapsed.
...@@ -173,15 +173,16 @@ static int mxc_clkdivs[] = {0, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, ...@@ -173,15 +173,16 @@ static int mxc_clkdivs[] = {0, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192,
/* MX21, MX27 */ /* MX21, MX27 */
static unsigned int spi_imx_clkdiv_1(unsigned int fin, static unsigned int spi_imx_clkdiv_1(unsigned int fin,
unsigned int fspi, unsigned int max) unsigned int fspi, unsigned int max, unsigned int *fres)
{ {
int i; int i;
for (i = 2; i < max; i++) for (i = 2; i < max; i++)
if (fspi * mxc_clkdivs[i] >= fin) if (fspi * mxc_clkdivs[i] >= fin)
return i; break;
return max; *fres = fin / mxc_clkdivs[i];
return i;
} }
/* MX1, MX31, MX35, MX51 CSPI */ /* MX1, MX31, MX35, MX51 CSPI */
...@@ -442,6 +443,7 @@ static void mx51_ecspi_reset(struct spi_imx_data *spi_imx) ...@@ -442,6 +443,7 @@ static void mx51_ecspi_reset(struct spi_imx_data *spi_imx)
#define MX31_CSPICTRL_ENABLE (1 << 0) #define MX31_CSPICTRL_ENABLE (1 << 0)
#define MX31_CSPICTRL_MASTER (1 << 1) #define MX31_CSPICTRL_MASTER (1 << 1)
#define MX31_CSPICTRL_XCH (1 << 2) #define MX31_CSPICTRL_XCH (1 << 2)
#define MX31_CSPICTRL_SMC (1 << 3)
#define MX31_CSPICTRL_POL (1 << 4) #define MX31_CSPICTRL_POL (1 << 4)
#define MX31_CSPICTRL_PHA (1 << 5) #define MX31_CSPICTRL_PHA (1 << 5)
#define MX31_CSPICTRL_SSCTL (1 << 6) #define MX31_CSPICTRL_SSCTL (1 << 6)
...@@ -452,6 +454,10 @@ static void mx51_ecspi_reset(struct spi_imx_data *spi_imx) ...@@ -452,6 +454,10 @@ static void mx51_ecspi_reset(struct spi_imx_data *spi_imx)
#define MX35_CSPICTRL_CS_SHIFT 12 #define MX35_CSPICTRL_CS_SHIFT 12
#define MX31_CSPICTRL_DR_SHIFT 16 #define MX31_CSPICTRL_DR_SHIFT 16
#define MX31_CSPI_DMAREG 0x10
#define MX31_DMAREG_RH_DEN (1<<4)
#define MX31_DMAREG_TH_DEN (1<<1)
#define MX31_CSPISTATUS 0x14 #define MX31_CSPISTATUS 0x14
#define MX31_STATUS_RR (1 << 3) #define MX31_STATUS_RR (1 << 3)
...@@ -511,6 +517,9 @@ static int mx31_config(struct spi_device *spi, struct spi_imx_config *config) ...@@ -511,6 +517,9 @@ static int mx31_config(struct spi_device *spi, struct spi_imx_config *config)
(is_imx35_cspi(spi_imx) ? MX35_CSPICTRL_CS_SHIFT : (is_imx35_cspi(spi_imx) ? MX35_CSPICTRL_CS_SHIFT :
MX31_CSPICTRL_CS_SHIFT); MX31_CSPICTRL_CS_SHIFT);
if (spi_imx->usedma)
reg |= MX31_CSPICTRL_SMC;
writel(reg, spi_imx->base + MXC_CSPICTRL); writel(reg, spi_imx->base + MXC_CSPICTRL);
reg = readl(spi_imx->base + MX31_CSPI_TESTREG); reg = readl(spi_imx->base + MX31_CSPI_TESTREG);
...@@ -520,6 +529,13 @@ static int mx31_config(struct spi_device *spi, struct spi_imx_config *config) ...@@ -520,6 +529,13 @@ static int mx31_config(struct spi_device *spi, struct spi_imx_config *config)
reg &= ~MX31_TEST_LBC; reg &= ~MX31_TEST_LBC;
writel(reg, spi_imx->base + MX31_CSPI_TESTREG); writel(reg, spi_imx->base + MX31_CSPI_TESTREG);
if (spi_imx->usedma) {
/* configure DMA requests when RXFIFO is half full and
when TXFIFO is half empty */
writel(MX31_DMAREG_RH_DEN | MX31_DMAREG_TH_DEN,
spi_imx->base + MX31_CSPI_DMAREG);
}
return 0; return 0;
} }
...@@ -574,9 +590,12 @@ static int mx21_config(struct spi_device *spi, struct spi_imx_config *config) ...@@ -574,9 +590,12 @@ static int mx21_config(struct spi_device *spi, struct spi_imx_config *config)
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
unsigned int reg = MX21_CSPICTRL_ENABLE | MX21_CSPICTRL_MASTER; unsigned int reg = MX21_CSPICTRL_ENABLE | MX21_CSPICTRL_MASTER;
unsigned int max = is_imx27_cspi(spi_imx) ? 16 : 18; unsigned int max = is_imx27_cspi(spi_imx) ? 16 : 18;
unsigned int clk;
reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz, max, &clk)
<< MX21_CSPICTRL_DR_SHIFT;
spi_imx->spi_bus_clk = clk;
reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz, max) <<
MX21_CSPICTRL_DR_SHIFT;
reg |= config->bpw - 1; reg |= config->bpw - 1;
if (spi->mode & SPI_CPHA) if (spi->mode & SPI_CPHA)
...@@ -1244,10 +1263,10 @@ static int spi_imx_probe(struct platform_device *pdev) ...@@ -1244,10 +1263,10 @@ static int spi_imx_probe(struct platform_device *pdev)
spi_imx->spi_clk = clk_get_rate(spi_imx->clk_per); spi_imx->spi_clk = clk_get_rate(spi_imx->clk_per);
/* /*
* Only validated on i.mx6 now, can remove the constrain if validated on * Only validated on i.mx35 and i.mx6 now, can remove the constraint
* other chips. * if validated on other chips.
*/ */
if (is_imx51_ecspi(spi_imx)) { if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx)) {
ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master); ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master);
if (ret == -EPROBE_DEFER) if (ret == -EPROBE_DEFER)
goto out_clk_put; goto out_clk_put;
......
...@@ -214,6 +214,7 @@ static const struct of_device_id jcore_spi_of_match[] = { ...@@ -214,6 +214,7 @@ static const struct of_device_id jcore_spi_of_match[] = {
{ .compatible = "jcore,spi2" }, { .compatible = "jcore,spi2" },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, jcore_spi_of_match);
static struct platform_driver jcore_spi_driver = { static struct platform_driver jcore_spi_driver = {
.probe = jcore_spi_probe, .probe = jcore_spi_probe,
......
...@@ -1386,20 +1386,13 @@ static int omap2_mcspi_probe(struct platform_device *pdev) ...@@ -1386,20 +1386,13 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
regs_offset = pdata->regs_offset; regs_offset = pdata->regs_offset;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (r == NULL) {
status = -ENODEV;
goto free_master;
}
r->start += regs_offset;
r->end += regs_offset;
mcspi->phys = r->start;
mcspi->base = devm_ioremap_resource(&pdev->dev, r); mcspi->base = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(mcspi->base)) { if (IS_ERR(mcspi->base)) {
status = PTR_ERR(mcspi->base); status = PTR_ERR(mcspi->base);
goto free_master; goto free_master;
} }
mcspi->phys = r->start + regs_offset;
mcspi->base += regs_offset;
mcspi->dev = &pdev->dev; mcspi->dev = &pdev->dev;
......
...@@ -138,37 +138,62 @@ static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed) ...@@ -138,37 +138,62 @@ static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
tclk_hz = clk_get_rate(orion_spi->clk); tclk_hz = clk_get_rate(orion_spi->clk);
if (devdata->typ == ARMADA_SPI) { if (devdata->typ == ARMADA_SPI) {
unsigned int clk, spr, sppr, sppr2, err; /*
unsigned int best_spr, best_sppr, best_err; * Given the core_clk (tclk_hz) and the target rate (speed) we
* determine the best values for SPR (in [0 .. 15]) and SPPR (in
best_err = speed; * [0..7]) such that
best_spr = 0; *
best_sppr = 0; * core_clk / (SPR * 2 ** SPPR)
*
/* Iterate over the valid range looking for best fit */ * is as big as possible but not bigger than speed.
for (sppr = 0; sppr < 8; sppr++) { */
sppr2 = 0x1 << sppr;
spr = tclk_hz / sppr2;
spr = DIV_ROUND_UP(spr, speed);
if ((spr == 0) || (spr > 15))
continue;
clk = tclk_hz / (spr * sppr2);
err = speed - clk;
if (err < best_err) {
best_spr = spr;
best_sppr = sppr;
best_err = err;
}
}
if ((best_sppr == 0) && (best_spr == 0)) /* best integer divider: */
return -EINVAL; unsigned divider = DIV_ROUND_UP(tclk_hz, speed);
unsigned spr, sppr;
if (divider < 16) {
/* This is the easy case, divider is less than 16 */
spr = divider;
sppr = 0;
} else {
unsigned two_pow_sppr;
/*
* Find the highest bit set in divider. This and the
* three next bits define SPR (apart from rounding).
* SPPR is then the number of zero bits that must be
* appended:
*/
sppr = fls(divider) - 4;
/*
* As SPR only has 4 bits, we have to round divider up
* to the next multiple of 2 ** sppr.
*/
two_pow_sppr = 1 << sppr;
divider = (divider + two_pow_sppr - 1) & -two_pow_sppr;
/*
* recalculate sppr as rounding up divider might have
* increased it enough to change the position of the
* highest set bit. In this case the bit that now
* doesn't make it into SPR is 0, so there is no need to
* round again.
*/
sppr = fls(divider) - 4;
spr = divider >> sppr;
/*
* Now do range checking. SPR is constructed to have a
* width of 4 bits, so this is fine for sure. So we
* still need to check for sppr to fit into 3 bits:
*/
if (sppr > 7)
return -EINVAL;
}
prescale = ((best_sppr & 0x6) << 5) | prescale = ((sppr & 0x6) << 5) | ((sppr & 0x1) << 4) | spr;
((best_sppr & 0x1) << 4) | best_spr;
} else { } else {
/* /*
* the supported rates are: 4,6,8...30 * the supported rates are: 4,6,8...30
......
...@@ -1690,6 +1690,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1690,6 +1690,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
pxa2xx_spi_write(drv_data, SSCR1, tmp); pxa2xx_spi_write(drv_data, SSCR1, tmp);
tmp = SSCR0_SCR(2) | SSCR0_Motorola | SSCR0_DataSize(8); tmp = SSCR0_SCR(2) | SSCR0_Motorola | SSCR0_DataSize(8);
pxa2xx_spi_write(drv_data, SSCR0, tmp); pxa2xx_spi_write(drv_data, SSCR0, tmp);
break;
default: default:
tmp = SSCR1_RxTresh(RX_THRESH_DFLT) | tmp = SSCR1_RxTresh(RX_THRESH_DFLT) |
SSCR1_TxTresh(TX_THRESH_DFLT); SSCR1_TxTresh(TX_THRESH_DFLT);
......
...@@ -109,7 +109,6 @@ static inline void pxa2xx_spi_write(const struct driver_data *drv_data, ...@@ -109,7 +109,6 @@ static inline void pxa2xx_spi_write(const struct driver_data *drv_data,
#define DONE_STATE ((void *)2) #define DONE_STATE ((void *)2)
#define ERROR_STATE ((void *)-1) #define ERROR_STATE ((void *)-1)
#define IS_DMA_ALIGNED(x) IS_ALIGNED((unsigned long)(x), DMA_ALIGNMENT)
#define DMA_ALIGNMENT 8 #define DMA_ALIGNMENT 8
static inline int pxa25x_ssp_comp(struct driver_data *drv_data) static inline int pxa25x_ssp_comp(struct driver_data *drv_data)
......
...@@ -413,7 +413,7 @@ static unsigned int qspi_set_send_trigger(struct rspi_data *rspi, ...@@ -413,7 +413,7 @@ static unsigned int qspi_set_send_trigger(struct rspi_data *rspi,
return n; return n;
} }
static void qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len) static int qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len)
{ {
unsigned int n; unsigned int n;
...@@ -428,6 +428,7 @@ static void qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len) ...@@ -428,6 +428,7 @@ static void qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len)
qspi_update(rspi, SPBFCR_RXTRG_MASK, qspi_update(rspi, SPBFCR_RXTRG_MASK,
SPBFCR_RXTRG_1B, QSPI_SPBFCR); SPBFCR_RXTRG_1B, QSPI_SPBFCR);
} }
return n;
} }
#define set_config_register(spi, n) spi->ops->set_config_register(spi, n) #define set_config_register(spi, n) spi->ops->set_config_register(spi, n)
...@@ -785,6 +786,9 @@ static int qspi_transfer_out_in(struct rspi_data *rspi, ...@@ -785,6 +786,9 @@ static int qspi_transfer_out_in(struct rspi_data *rspi,
static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
{ {
const u8 *tx = xfer->tx_buf;
unsigned int n = xfer->len;
unsigned int i, len;
int ret; int ret;
if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) { if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
...@@ -793,9 +797,23 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) ...@@ -793,9 +797,23 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
return ret; return ret;
} }
ret = rspi_pio_transfer(rspi, xfer->tx_buf, NULL, xfer->len); while (n > 0) {
if (ret < 0) len = qspi_set_send_trigger(rspi, n);
return ret; if (len == QSPI_BUFFER_SIZE) {
ret = rspi_wait_for_tx_empty(rspi);
if (ret < 0) {
dev_err(&rspi->master->dev, "transmit timeout\n");
return ret;
}
for (i = 0; i < len; i++)
rspi_write_data(rspi, *tx++);
} else {
ret = rspi_pio_transfer(rspi, tx, NULL, n);
if (ret < 0)
return ret;
}
n -= len;
}
/* Wait for the last transmission */ /* Wait for the last transmission */
rspi_wait_for_tx_empty(rspi); rspi_wait_for_tx_empty(rspi);
...@@ -805,13 +823,37 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) ...@@ -805,13 +823,37 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer) static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)
{ {
u8 *rx = xfer->rx_buf;
unsigned int n = xfer->len;
unsigned int i, len;
int ret;
if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) { if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
int ret = rspi_dma_transfer(rspi, NULL, &xfer->rx_sg); int ret = rspi_dma_transfer(rspi, NULL, &xfer->rx_sg);
if (ret != -EAGAIN) if (ret != -EAGAIN)
return ret; return ret;
} }
return rspi_pio_transfer(rspi, NULL, xfer->rx_buf, xfer->len); while (n > 0) {
len = qspi_set_receive_trigger(rspi, n);
if (len == QSPI_BUFFER_SIZE) {
ret = rspi_wait_for_rx_full(rspi);
if (ret < 0) {
dev_err(&rspi->master->dev, "receive timeout\n");
return ret;
}
for (i = 0; i < len; i++)
*rx++ = rspi_read_data(rspi);
} else {
ret = rspi_pio_transfer(rspi, NULL, rx, n);
if (ret < 0)
return ret;
*rx++ = ret;
}
n -= len;
}
return 0;
} }
static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi, static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi,
......
...@@ -973,13 +973,16 @@ static const struct sh_msiof_chipdata r8a779x_data = { ...@@ -973,13 +973,16 @@ static const struct sh_msiof_chipdata r8a779x_data = {
}; };
static const struct of_device_id sh_msiof_match[] = { static const struct of_device_id sh_msiof_match[] = {
{ .compatible = "renesas,sh-msiof", .data = &sh_data },
{ .compatible = "renesas,sh-mobile-msiof", .data = &sh_data }, { .compatible = "renesas,sh-mobile-msiof", .data = &sh_data },
{ .compatible = "renesas,msiof-r8a7790", .data = &r8a779x_data }, { .compatible = "renesas,msiof-r8a7790", .data = &r8a779x_data },
{ .compatible = "renesas,msiof-r8a7791", .data = &r8a779x_data }, { .compatible = "renesas,msiof-r8a7791", .data = &r8a779x_data },
{ .compatible = "renesas,msiof-r8a7792", .data = &r8a779x_data }, { .compatible = "renesas,msiof-r8a7792", .data = &r8a779x_data },
{ .compatible = "renesas,msiof-r8a7793", .data = &r8a779x_data }, { .compatible = "renesas,msiof-r8a7793", .data = &r8a779x_data },
{ .compatible = "renesas,msiof-r8a7794", .data = &r8a779x_data }, { .compatible = "renesas,msiof-r8a7794", .data = &r8a779x_data },
{ .compatible = "renesas,rcar-gen2-msiof", .data = &r8a779x_data },
{ .compatible = "renesas,msiof-r8a7796", .data = &r8a779x_data },
{ .compatible = "renesas,rcar-gen3-msiof", .data = &r8a779x_data },
{ .compatible = "renesas,sh-msiof", .data = &sh_data }, /* Deprecated */
{}, {},
}; };
MODULE_DEVICE_TABLE(of, sh_msiof_match); MODULE_DEVICE_TABLE(of, sh_msiof_match);
......
...@@ -46,6 +46,8 @@ ...@@ -46,6 +46,8 @@
#define SUN4I_CTL_TP BIT(18) #define SUN4I_CTL_TP BIT(18)
#define SUN4I_INT_CTL_REG 0x0c #define SUN4I_INT_CTL_REG 0x0c
#define SUN4I_INT_CTL_RF_F34 BIT(4)
#define SUN4I_INT_CTL_TF_E34 BIT(12)
#define SUN4I_INT_CTL_TC BIT(16) #define SUN4I_INT_CTL_TC BIT(16)
#define SUN4I_INT_STA_REG 0x10 #define SUN4I_INT_STA_REG 0x10
...@@ -61,11 +63,14 @@ ...@@ -61,11 +63,14 @@
#define SUN4I_CLK_CTL_CDR1(div) (((div) & SUN4I_CLK_CTL_CDR1_MASK) << 8) #define SUN4I_CLK_CTL_CDR1(div) (((div) & SUN4I_CLK_CTL_CDR1_MASK) << 8)
#define SUN4I_CLK_CTL_DRS BIT(12) #define SUN4I_CLK_CTL_DRS BIT(12)
#define SUN4I_MAX_XFER_SIZE 0xffffff
#define SUN4I_BURST_CNT_REG 0x20 #define SUN4I_BURST_CNT_REG 0x20
#define SUN4I_BURST_CNT(cnt) ((cnt) & 0xffffff) #define SUN4I_BURST_CNT(cnt) ((cnt) & SUN4I_MAX_XFER_SIZE)
#define SUN4I_XMIT_CNT_REG 0x24 #define SUN4I_XMIT_CNT_REG 0x24
#define SUN4I_XMIT_CNT(cnt) ((cnt) & 0xffffff) #define SUN4I_XMIT_CNT(cnt) ((cnt) & SUN4I_MAX_XFER_SIZE)
#define SUN4I_FIFO_STA_REG 0x28 #define SUN4I_FIFO_STA_REG 0x28
#define SUN4I_FIFO_STA_RF_CNT_MASK 0x7f #define SUN4I_FIFO_STA_RF_CNT_MASK 0x7f
...@@ -96,6 +101,31 @@ static inline void sun4i_spi_write(struct sun4i_spi *sspi, u32 reg, u32 value) ...@@ -96,6 +101,31 @@ static inline void sun4i_spi_write(struct sun4i_spi *sspi, u32 reg, u32 value)
writel(value, sspi->base_addr + reg); writel(value, sspi->base_addr + reg);
} }
static inline u32 sun4i_spi_get_tx_fifo_count(struct sun4i_spi *sspi)
{
u32 reg = sun4i_spi_read(sspi, SUN4I_FIFO_STA_REG);
reg >>= SUN4I_FIFO_STA_TF_CNT_BITS;
return reg & SUN4I_FIFO_STA_TF_CNT_MASK;
}
static inline void sun4i_spi_enable_interrupt(struct sun4i_spi *sspi, u32 mask)
{
u32 reg = sun4i_spi_read(sspi, SUN4I_INT_CTL_REG);
reg |= mask;
sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, reg);
}
static inline void sun4i_spi_disable_interrupt(struct sun4i_spi *sspi, u32 mask)
{
u32 reg = sun4i_spi_read(sspi, SUN4I_INT_CTL_REG);
reg &= ~mask;
sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, reg);
}
static inline void sun4i_spi_drain_fifo(struct sun4i_spi *sspi, int len) static inline void sun4i_spi_drain_fifo(struct sun4i_spi *sspi, int len)
{ {
u32 reg, cnt; u32 reg, cnt;
...@@ -118,10 +148,13 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi *sspi, int len) ...@@ -118,10 +148,13 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi *sspi, int len)
static inline void sun4i_spi_fill_fifo(struct sun4i_spi *sspi, int len) static inline void sun4i_spi_fill_fifo(struct sun4i_spi *sspi, int len)
{ {
u32 cnt;
u8 byte; u8 byte;
if (len > sspi->len) /* See how much data we can fit */
len = sspi->len; cnt = SUN4I_FIFO_DEPTH - sun4i_spi_get_tx_fifo_count(sspi);
len = min3(len, (int)cnt, sspi->len);
while (len--) { while (len--) {
byte = sspi->tx_buf ? *sspi->tx_buf++ : 0; byte = sspi->tx_buf ? *sspi->tx_buf++ : 0;
...@@ -184,10 +217,10 @@ static int sun4i_spi_transfer_one(struct spi_master *master, ...@@ -184,10 +217,10 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
u32 reg; u32 reg;
/* We don't support transfer larger than the FIFO */ /* We don't support transfer larger than the FIFO */
if (tfr->len > SUN4I_FIFO_DEPTH) if (tfr->len > SUN4I_MAX_XFER_SIZE)
return -EMSGSIZE; return -EMSGSIZE;
if (tfr->tx_buf && tfr->len >= SUN4I_FIFO_DEPTH) if (tfr->tx_buf && tfr->len >= SUN4I_MAX_XFER_SIZE)
return -EMSGSIZE; return -EMSGSIZE;
reinit_completion(&sspi->done); reinit_completion(&sspi->done);
...@@ -286,7 +319,11 @@ static int sun4i_spi_transfer_one(struct spi_master *master, ...@@ -286,7 +319,11 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH - 1); sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH - 1);
/* Enable the interrupts */ /* Enable the interrupts */
sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, SUN4I_INT_CTL_TC); sun4i_spi_enable_interrupt(sspi, SUN4I_INT_CTL_TC |
SUN4I_INT_CTL_RF_F34);
/* Only enable Tx FIFO interrupt if we really need it */
if (tx_len > SUN4I_FIFO_DEPTH)
sun4i_spi_enable_interrupt(sspi, SUN4I_INT_CTL_TF_E34);
/* Start the transfer */ /* Start the transfer */
reg = sun4i_spi_read(sspi, SUN4I_CTL_REG); reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
...@@ -306,7 +343,6 @@ static int sun4i_spi_transfer_one(struct spi_master *master, ...@@ -306,7 +343,6 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
goto out; goto out;
} }
sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH);
out: out:
sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, 0); sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, 0);
...@@ -322,10 +358,33 @@ static irqreturn_t sun4i_spi_handler(int irq, void *dev_id) ...@@ -322,10 +358,33 @@ static irqreturn_t sun4i_spi_handler(int irq, void *dev_id)
/* Transfer complete */ /* Transfer complete */
if (status & SUN4I_INT_CTL_TC) { if (status & SUN4I_INT_CTL_TC) {
sun4i_spi_write(sspi, SUN4I_INT_STA_REG, SUN4I_INT_CTL_TC); sun4i_spi_write(sspi, SUN4I_INT_STA_REG, SUN4I_INT_CTL_TC);
sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH);
complete(&sspi->done); complete(&sspi->done);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/* Receive FIFO 3/4 full */
if (status & SUN4I_INT_CTL_RF_F34) {
sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH);
/* Only clear the interrupt _after_ draining the FIFO */
sun4i_spi_write(sspi, SUN4I_INT_STA_REG, SUN4I_INT_CTL_RF_F34);
return IRQ_HANDLED;
}
/* Transmit FIFO 3/4 empty */
if (status & SUN4I_INT_CTL_TF_E34) {
sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH);
if (!sspi->len)
/* nothing left to transmit */
sun4i_spi_disable_interrupt(sspi, SUN4I_INT_CTL_TF_E34);
/* Only clear the interrupt _after_ re-seeding the FIFO */
sun4i_spi_write(sspi, SUN4I_INT_STA_REG, SUN4I_INT_CTL_TF_E34);
return IRQ_HANDLED;
}
return IRQ_NONE; return IRQ_NONE;
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/reset.h> #include <linux/reset.h>
...@@ -24,6 +25,7 @@ ...@@ -24,6 +25,7 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#define SUN6I_FIFO_DEPTH 128 #define SUN6I_FIFO_DEPTH 128
#define SUN8I_FIFO_DEPTH 64
#define SUN6I_GBL_CTL_REG 0x04 #define SUN6I_GBL_CTL_REG 0x04
#define SUN6I_GBL_CTL_BUS_ENABLE BIT(0) #define SUN6I_GBL_CTL_BUS_ENABLE BIT(0)
...@@ -90,6 +92,7 @@ struct sun6i_spi { ...@@ -90,6 +92,7 @@ struct sun6i_spi {
const u8 *tx_buf; const u8 *tx_buf;
u8 *rx_buf; u8 *rx_buf;
int len; int len;
unsigned long fifo_depth;
}; };
static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg) static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg)
...@@ -155,7 +158,9 @@ static void sun6i_spi_set_cs(struct spi_device *spi, bool enable) ...@@ -155,7 +158,9 @@ static void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
static size_t sun6i_spi_max_transfer_size(struct spi_device *spi) static size_t sun6i_spi_max_transfer_size(struct spi_device *spi)
{ {
return SUN6I_FIFO_DEPTH - 1; struct sun6i_spi *sspi = spi_master_get_devdata(spi->master);
return sspi->fifo_depth - 1;
} }
static int sun6i_spi_transfer_one(struct spi_master *master, static int sun6i_spi_transfer_one(struct spi_master *master,
...@@ -170,7 +175,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master, ...@@ -170,7 +175,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
u32 reg; u32 reg;
/* We don't support transfer larger than the FIFO */ /* We don't support transfer larger than the FIFO */
if (tfr->len > SUN6I_FIFO_DEPTH) if (tfr->len > sspi->fifo_depth)
return -EINVAL; return -EINVAL;
reinit_completion(&sspi->done); reinit_completion(&sspi->done);
...@@ -265,7 +270,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master, ...@@ -265,7 +270,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
SUN6I_BURST_CTL_CNT_STC(tx_len)); SUN6I_BURST_CTL_CNT_STC(tx_len));
/* Fill the TX FIFO */ /* Fill the TX FIFO */
sun6i_spi_fill_fifo(sspi, SUN6I_FIFO_DEPTH); sun6i_spi_fill_fifo(sspi, sspi->fifo_depth);
/* Enable the interrupts */ /* Enable the interrupts */
sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, SUN6I_INT_CTL_TC); sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, SUN6I_INT_CTL_TC);
...@@ -288,7 +293,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master, ...@@ -288,7 +293,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
goto out; goto out;
} }
sun6i_spi_drain_fifo(sspi, SUN6I_FIFO_DEPTH); sun6i_spi_drain_fifo(sspi, sspi->fifo_depth);
out: out:
sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0); sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0);
...@@ -398,6 +403,8 @@ static int sun6i_spi_probe(struct platform_device *pdev) ...@@ -398,6 +403,8 @@ static int sun6i_spi_probe(struct platform_device *pdev)
} }
sspi->master = master; sspi->master = master;
sspi->fifo_depth = (unsigned long)of_device_get_match_data(&pdev->dev);
master->max_speed_hz = 100 * 1000 * 1000; master->max_speed_hz = 100 * 1000 * 1000;
master->min_speed_hz = 3 * 1000; master->min_speed_hz = 3 * 1000;
master->set_cs = sun6i_spi_set_cs; master->set_cs = sun6i_spi_set_cs;
...@@ -470,7 +477,8 @@ static int sun6i_spi_remove(struct platform_device *pdev) ...@@ -470,7 +477,8 @@ static int sun6i_spi_remove(struct platform_device *pdev)
} }
static const struct of_device_id sun6i_spi_match[] = { static const struct of_device_id sun6i_spi_match[] = {
{ .compatible = "allwinner,sun6i-a31-spi", }, { .compatible = "allwinner,sun6i-a31-spi", .data = (void *)SUN6I_FIFO_DEPTH },
{ .compatible = "allwinner,sun8i-h3-spi", .data = (void *)SUN8I_FIFO_DEPTH },
{} {}
}; };
MODULE_DEVICE_TABLE(of, sun6i_spi_match); MODULE_DEVICE_TABLE(of, sun6i_spi_match);
......
...@@ -411,6 +411,7 @@ static int ti_qspi_dma_xfer(struct ti_qspi *qspi, dma_addr_t dma_dst, ...@@ -411,6 +411,7 @@ static int ti_qspi_dma_xfer(struct ti_qspi *qspi, dma_addr_t dma_dst,
tx->callback = ti_qspi_dma_callback; tx->callback = ti_qspi_dma_callback;
tx->callback_param = qspi; tx->callback_param = qspi;
cookie = tx->tx_submit(tx); cookie = tx->tx_submit(tx);
reinit_completion(&qspi->transfer_complete);
ret = dma_submit_error(cookie); ret = dma_submit_error(cookie);
if (ret) { if (ret) {
......
...@@ -1268,11 +1268,8 @@ static void pch_spi_free_resources(struct pch_spi_board_data *board_dat, ...@@ -1268,11 +1268,8 @@ static void pch_spi_free_resources(struct pch_spi_board_data *board_dat,
static int pch_spi_get_resources(struct pch_spi_board_data *board_dat, static int pch_spi_get_resources(struct pch_spi_board_data *board_dat,
struct pch_spi_data *data) struct pch_spi_data *data)
{ {
int retval = 0;
dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__); dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
/* reset PCH SPI h/w */ /* reset PCH SPI h/w */
pch_spi_reset(data->master); pch_spi_reset(data->master);
dev_dbg(&board_dat->pdev->dev, dev_dbg(&board_dat->pdev->dev,
...@@ -1280,15 +1277,7 @@ static int pch_spi_get_resources(struct pch_spi_board_data *board_dat, ...@@ -1280,15 +1277,7 @@ static int pch_spi_get_resources(struct pch_spi_board_data *board_dat,
dev_dbg(&board_dat->pdev->dev, "%s data->irq_reg_sts=true\n", __func__); dev_dbg(&board_dat->pdev->dev, "%s data->irq_reg_sts=true\n", __func__);
if (retval != 0) { return 0;
dev_err(&board_dat->pdev->dev,
"%s FAIL:invoking pch_spi_free_resources\n", __func__);
pch_spi_free_resources(board_dat, data);
}
dev_dbg(&board_dat->pdev->dev, "%s Return=%d\n", __func__, retval);
return retval;
} }
static void pch_free_dma_buf(struct pch_spi_board_data *board_dat, static void pch_free_dma_buf(struct pch_spi_board_data *board_dat,
......
...@@ -451,6 +451,7 @@ static const struct of_device_id xlp_spi_dt_id[] = { ...@@ -451,6 +451,7 @@ static const struct of_device_id xlp_spi_dt_id[] = {
{ .compatible = "netlogic,xlp832-spi" }, { .compatible = "netlogic,xlp832-spi" },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, xlp_spi_dt_id);
static struct platform_driver xlp_spi_driver = { static struct platform_driver xlp_spi_driver = {
.probe = xlp_spi_probe, .probe = xlp_spi_probe,
......
...@@ -697,10 +697,15 @@ static void spi_set_cs(struct spi_device *spi, bool enable) ...@@ -697,10 +697,15 @@ static void spi_set_cs(struct spi_device *spi, bool enable)
if (spi->mode & SPI_CS_HIGH) if (spi->mode & SPI_CS_HIGH)
enable = !enable; enable = !enable;
if (gpio_is_valid(spi->cs_gpio)) if (gpio_is_valid(spi->cs_gpio)) {
gpio_set_value(spi->cs_gpio, !enable); gpio_set_value(spi->cs_gpio, !enable);
else if (spi->master->set_cs) /* Some SPI masters need both GPIO CS & slave_select */
if ((spi->master->flags & SPI_MASTER_GPIO_SS) &&
spi->master->set_cs)
spi->master->set_cs(spi, !enable);
} else if (spi->master->set_cs) {
spi->master->set_cs(spi, !enable); spi->master->set_cs(spi, !enable);
}
} }
#ifdef CONFIG_HAS_DMA #ifdef CONFIG_HAS_DMA
...@@ -720,6 +725,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev, ...@@ -720,6 +725,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
int desc_len; int desc_len;
int sgs; int sgs;
struct page *vm_page; struct page *vm_page;
struct scatterlist *sg;
void *sg_buf; void *sg_buf;
size_t min; size_t min;
int i, ret; int i, ret;
...@@ -738,6 +744,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev, ...@@ -738,6 +744,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
if (ret != 0) if (ret != 0)
return ret; return ret;
sg = &sgt->sgl[0];
for (i = 0; i < sgs; i++) { for (i = 0; i < sgs; i++) {
if (vmalloced_buf || kmap_buf) { if (vmalloced_buf || kmap_buf) {
...@@ -751,16 +758,17 @@ static int spi_map_buf(struct spi_master *master, struct device *dev, ...@@ -751,16 +758,17 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
sg_free_table(sgt); sg_free_table(sgt);
return -ENOMEM; return -ENOMEM;
} }
sg_set_page(&sgt->sgl[i], vm_page, sg_set_page(sg, vm_page,
min, offset_in_page(buf)); min, offset_in_page(buf));
} else { } else {
min = min_t(size_t, len, desc_len); min = min_t(size_t, len, desc_len);
sg_buf = buf; sg_buf = buf;
sg_set_buf(&sgt->sgl[i], sg_buf, min); sg_set_buf(sg, sg_buf, min);
} }
buf += min; buf += min;
len -= min; len -= min;
sg = sg_next(sg);
} }
ret = dma_map_sg(dev, sgt->sgl, sgt->nents, dir); ret = dma_map_sg(dev, sgt->sgl, sgt->nents, dir);
...@@ -1034,8 +1042,14 @@ static int spi_transfer_one_message(struct spi_master *master, ...@@ -1034,8 +1042,14 @@ static int spi_transfer_one_message(struct spi_master *master,
if (msg->status != -EINPROGRESS) if (msg->status != -EINPROGRESS)
goto out; goto out;
if (xfer->delay_usecs) if (xfer->delay_usecs) {
udelay(xfer->delay_usecs); u16 us = xfer->delay_usecs;
if (us <= 10)
udelay(us);
else
usleep_range(us, us + DIV_ROUND_UP(us, 10));
}
if (xfer->cs_change) { if (xfer->cs_change) {
if (list_is_last(&xfer->transfer_list, if (list_is_last(&xfer->transfer_list,
......
...@@ -696,6 +696,7 @@ static struct class *spidev_class; ...@@ -696,6 +696,7 @@ static struct class *spidev_class;
static const struct of_device_id spidev_dt_ids[] = { static const struct of_device_id spidev_dt_ids[] = {
{ .compatible = "rohm,dh2228fv" }, { .compatible = "rohm,dh2228fv" },
{ .compatible = "lineartechnology,ltc2488" }, { .compatible = "lineartechnology,ltc2488" },
{ .compatible = "ge,achc" },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, spidev_dt_ids); MODULE_DEVICE_TABLE(of, spidev_dt_ids);
......
...@@ -442,6 +442,7 @@ struct spi_master { ...@@ -442,6 +442,7 @@ struct spi_master {
#define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */ #define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */
#define SPI_MASTER_MUST_RX BIT(3) /* requires rx */ #define SPI_MASTER_MUST_RX BIT(3) /* requires rx */
#define SPI_MASTER_MUST_TX BIT(4) /* requires tx */ #define SPI_MASTER_MUST_TX BIT(4) /* requires tx */
#define SPI_MASTER_GPIO_SS BIT(5) /* GPIO CS must select slave */
/* /*
* on some hardware transfer / message size may be constrained * on some hardware transfer / message size may be constrained
......
...@@ -315,7 +315,7 @@ static void transfer_file(int fd, char *filename) ...@@ -315,7 +315,7 @@ static void transfer_file(int fd, char *filename)
pabort("can't stat input file"); pabort("can't stat input file");
tx_fd = open(filename, O_RDONLY); tx_fd = open(filename, O_RDONLY);
if (fd < 0) if (tx_fd < 0)
pabort("can't open input file"); pabort("can't open input file");
tx = malloc(sb.st_size); tx = malloc(sb.st_size);
......
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