Commit e13cccfd authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'spi-v3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi into next

Pull spi updates from Mark Brown:
 "For this release SPI has been exceptionally quiet, all the work has
  been on improving drivers (including taking advantage of some of the
  recent framework updates):

   - DMA support for the rspi driver providing a nice performance boost
   - performance improvement for the SIRF controller in PIO mode
   - new support for the Cadence SPI IP and for pxa2xx on BayTrail"

* tag 'spi-v3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (59 commits)
  spi: rspi: Extract rspi_common_transfer()
  spi: rspi: Add DMA support for RSPI on RZ/A1H
  spi: rspi: Add DMA support for QSPI on R-Car Gen2
  spi: rspi: Absorb rspi_rz_transfer_out_in() into rspi_rz_transfer_one()
  spi: rspi: Merge rspi_*_dma() into rspi_dma_transfer()
  spi: rspi: Pass sg_tables instead of spi_tranfer to rspi_*_dma()
  spi: rspi: Move RSPI-specific setup out of DMA routines
  spi: rspi: Use SPI core DMA mapping framework
  spi: rspi: SPI DMA core needs both RX and TX DMA to function
  spi: rspi: Remove unneeded resource test in DMA setup
  spi: rspi: Extract rspi_request_dma_chan()
  spi: rspi: Don't consider DMA configuration failures fatal
  spi: rspi: Extract rspi_pio_transfer()
  spi: rspi: Use core SPI_MASTER_MUST_[RT]X handling
  spi: rspi: Remove unused 16-bit DMA support
  spi: rspi: Do not call rspi_receive_init() for TX-only
  spi: rspi: Extract rspi_wait_for_{tx_empty,rx_full}()
  spi/pxa2xx: fix runtime PM enabling order
  spi/fsl-espi: fix rx_buf in fsl_espi_cmd_trans()/fsl_espi_rw_trans()
  spi: core: Ignore unsupported spi-[tr]x-bus-width property values
  ...
parents de6b25de 69e25c75
...@@ -42,6 +42,10 @@ Required properties: ...@@ -42,6 +42,10 @@ Required properties:
- interrupts : should contain eSPI interrupt, the device has one interrupt. - interrupts : should contain eSPI interrupt, the device has one interrupt.
- fsl,espi-num-chipselects : the number of the chipselect signals. - fsl,espi-num-chipselects : the number of the chipselect signals.
Optional properties:
- fsl,csbef: chip select assertion time in bits before frame starts
- fsl,csaft: chip select negation time in bits after frame ends
Example: Example:
spi@110000 { spi@110000 {
#address-cells = <1>; #address-cells = <1>;
...@@ -51,4 +55,6 @@ Example: ...@@ -51,4 +55,6 @@ Example:
interrupts = <53 0x2>; interrupts = <53 0x2>;
interrupt-parent = <&mpic>; interrupt-parent = <&mpic>;
fsl,espi-num-chipselects = <4>; fsl,espi-num-chipselects = <4>;
fsl,csbef = <1>;
fsl,csaft = <1>;
}; };
...@@ -55,6 +55,8 @@ contain the following properties. ...@@ -55,6 +55,8 @@ contain the following properties.
chip select active high chip select active high
- spi-3wire - (optional) Empty property indicating device requires - spi-3wire - (optional) Empty property indicating device requires
3-wire mode. 3-wire mode.
- spi-lsb-first - (optional) Empty property indicating device requires
LSB first mode.
- spi-tx-bus-width - (optional) The bus width(number of data wires) that - spi-tx-bus-width - (optional) The bus width(number of data wires) that
used for MOSI. Defaults to 1 if not present. used for MOSI. Defaults to 1 if not present.
- spi-rx-bus-width - (optional) The bus width(number of data wires) that - spi-rx-bus-width - (optional) The bus width(number of data wires) that
......
Cadence SPI controller Device Tree Bindings
-------------------------------------------
Required properties:
- compatible : Should be "cdns,spi-r1p6" or "xlnx,zynq-spi-r1p6".
- reg : Physical base address and size of SPI registers map.
- interrupts : Property with a value describing the interrupt
number.
- interrupt-parent : Must be core interrupt controller
- clock-names : List of input clock names - "ref_clk", "pclk"
(See clock bindings for details).
- clocks : Clock phandles (see clock bindings for details).
Optional properties:
- num-cs : Number of chip selects used.
If a decoder is used, this will be the number of
chip selects after the decoder.
- is-decoded-cs : Flag to indicate whether decoder is used or not.
Example:
spi@e0007000 {
compatible = "xlnx,zynq-spi-r1p6";
clock-names = "ref_clk", "pclk";
clocks = <&clkc 26>, <&clkc 35>;
interrupt-parent = <&intc>;
interrupts = <0 49 4>;
num-cs = <4>;
is-decoded-cs = <0>;
reg = <0xe0007000 0x1000>;
} ;
Synopsys DesignWare SPI master
Required properties:
- compatible: should be "snps,designware-spi"
- #address-cells: see spi-bus.txt
- #size-cells: see spi-bus.txt
- reg: address and length of the spi master registers
- interrupts: should contain one interrupt
- clocks: spi clock phandle
- num-cs: see spi-bus.txt
Optional properties:
- cs-gpios: see spi-bus.txt
Example:
spi: spi@4020a000 {
compatible = "snps,designware-spi";
interrupts = <11 1>;
reg = <0x4020a000 0x1000>;
clocks = <&pclk>;
num-cs = <2>;
cs-gpios = <&banka 0 0>;
};
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include <linux/pinctrl/machine.h> #include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf-generic.h> #include <linux/pinctrl/pinconf-generic.h>
#include <linux/platform_data/pinctrl-adi2.h> #include <linux/platform_data/pinctrl-adi2.h>
#include <asm/bfin_spi3.h> #include <linux/spi/adi_spi3.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/gpio.h> #include <asm/gpio.h>
#include <asm/nand.h> #include <asm/nand.h>
...@@ -767,13 +767,13 @@ static struct flash_platform_data bfin_spi_flash_data = { ...@@ -767,13 +767,13 @@ static struct flash_platform_data bfin_spi_flash_data = {
.type = "w25q32", .type = "w25q32",
}; };
static struct bfin_spi3_chip spi_flash_chip_info = { static struct adi_spi3_chip spi_flash_chip_info = {
.enable_dma = true, /* use dma transfer with this chip*/ .enable_dma = true, /* use dma transfer with this chip*/
}; };
#endif #endif
#if IS_ENABLED(CONFIG_SPI_SPIDEV) #if IS_ENABLED(CONFIG_SPI_SPIDEV)
static struct bfin_spi3_chip spidev_chip_info = { static struct adi_spi3_chip spidev_chip_info = {
.enable_dma = true, .enable_dma = true,
}; };
#endif #endif
...@@ -1736,7 +1736,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { ...@@ -1736,7 +1736,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
}, },
#endif #endif
}; };
#if IS_ENABLED(CONFIG_SPI_BFIN_V3) #if IS_ENABLED(CONFIG_SPI_ADI_V3)
/* SPI (0) */ /* SPI (0) */
static struct resource bfin_spi0_resource[] = { static struct resource bfin_spi0_resource[] = {
{ {
...@@ -1777,13 +1777,13 @@ static struct resource bfin_spi1_resource[] = { ...@@ -1777,13 +1777,13 @@ static struct resource bfin_spi1_resource[] = {
}; };
/* SPI controller data */ /* SPI controller data */
static struct bfin_spi3_master bf60x_spi_master_info0 = { static struct adi_spi3_master bf60x_spi_master_info0 = {
.num_chipselect = MAX_CTRL_CS + MAX_BLACKFIN_GPIOS, .num_chipselect = MAX_CTRL_CS + MAX_BLACKFIN_GPIOS,
.pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0}, .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
}; };
static struct platform_device bf60x_spi_master0 = { static struct platform_device bf60x_spi_master0 = {
.name = "bfin-spi3", .name = "adi-spi3",
.id = 0, /* Bus number */ .id = 0, /* Bus number */
.num_resources = ARRAY_SIZE(bfin_spi0_resource), .num_resources = ARRAY_SIZE(bfin_spi0_resource),
.resource = bfin_spi0_resource, .resource = bfin_spi0_resource,
...@@ -1792,13 +1792,13 @@ static struct platform_device bf60x_spi_master0 = { ...@@ -1792,13 +1792,13 @@ static struct platform_device bf60x_spi_master0 = {
}, },
}; };
static struct bfin_spi3_master bf60x_spi_master_info1 = { static struct adi_spi3_master bf60x_spi_master_info1 = {
.num_chipselect = MAX_CTRL_CS + MAX_BLACKFIN_GPIOS, .num_chipselect = MAX_CTRL_CS + MAX_BLACKFIN_GPIOS,
.pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0}, .pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
}; };
static struct platform_device bf60x_spi_master1 = { static struct platform_device bf60x_spi_master1 = {
.name = "bfin-spi3", .name = "adi-spi3",
.id = 1, /* Bus number */ .id = 1, /* Bus number */
.num_resources = ARRAY_SIZE(bfin_spi1_resource), .num_resources = ARRAY_SIZE(bfin_spi1_resource),
.resource = bfin_spi1_resource, .resource = bfin_spi1_resource,
...@@ -1990,7 +1990,7 @@ static struct platform_device *ezkit_devices[] __initdata = { ...@@ -1990,7 +1990,7 @@ static struct platform_device *ezkit_devices[] __initdata = {
&bfin_sdh_device, &bfin_sdh_device,
#endif #endif
#if IS_ENABLED(CONFIG_SPI_BFIN_V3) #if IS_ENABLED(CONFIG_SPI_ADI_V3)
&bf60x_spi_master0, &bf60x_spi_master0,
&bf60x_spi_master1, &bf60x_spi_master1,
#endif #endif
...@@ -2051,8 +2051,8 @@ static struct pinctrl_map __initdata bfin_pinmux_map[] = { ...@@ -2051,8 +2051,8 @@ static struct pinctrl_map __initdata bfin_pinmux_map[] = {
PIN_MAP_MUX_GROUP_DEFAULT("bfin_sir.1", "pinctrl-adi2.0", NULL, "uart1"), PIN_MAP_MUX_GROUP_DEFAULT("bfin_sir.1", "pinctrl-adi2.0", NULL, "uart1"),
PIN_MAP_MUX_GROUP_DEFAULT("bfin-sdh.0", "pinctrl-adi2.0", NULL, "rsi0"), PIN_MAP_MUX_GROUP_DEFAULT("bfin-sdh.0", "pinctrl-adi2.0", NULL, "rsi0"),
PIN_MAP_MUX_GROUP_DEFAULT("stmmaceth.0", "pinctrl-adi2.0", NULL, "eth0"), PIN_MAP_MUX_GROUP_DEFAULT("stmmaceth.0", "pinctrl-adi2.0", NULL, "eth0"),
PIN_MAP_MUX_GROUP_DEFAULT("bfin-spi3.0", "pinctrl-adi2.0", NULL, "spi0"), PIN_MAP_MUX_GROUP_DEFAULT("adi-spi3.0", "pinctrl-adi2.0", NULL, "spi0"),
PIN_MAP_MUX_GROUP_DEFAULT("bfin-spi3.1", "pinctrl-adi2.0", NULL, "spi1"), PIN_MAP_MUX_GROUP_DEFAULT("adi-spi3.1", "pinctrl-adi2.0", NULL, "spi1"),
PIN_MAP_MUX_GROUP_DEFAULT("i2c-bfin-twi.0", "pinctrl-adi2.0", NULL, "twi0"), PIN_MAP_MUX_GROUP_DEFAULT("i2c-bfin-twi.0", "pinctrl-adi2.0", NULL, "twi0"),
PIN_MAP_MUX_GROUP_DEFAULT("i2c-bfin-twi.1", "pinctrl-adi2.0", NULL, "twi1"), PIN_MAP_MUX_GROUP_DEFAULT("i2c-bfin-twi.1", "pinctrl-adi2.0", NULL, "twi1"),
PIN_MAP_MUX_GROUP_DEFAULT("bfin-rotary", "pinctrl-adi2.0", NULL, "rotary"), PIN_MAP_MUX_GROUP_DEFAULT("bfin-rotary", "pinctrl-adi2.0", NULL, "rotary"),
......
...@@ -363,6 +363,12 @@ static struct clk ethclk = { ...@@ -363,6 +363,12 @@ static struct clk ethclk = {
.ops = &dummy_clk_ops, .ops = &dummy_clk_ops,
}; };
static struct clk spiclk = {
.name = "spi",
.parent = &sclk1,
.ops = &dummy_clk_ops,
};
static struct clk_lookup bf609_clks[] = { static struct clk_lookup bf609_clks[] = {
CLK(sys_clkin, NULL, "SYS_CLKIN"), CLK(sys_clkin, NULL, "SYS_CLKIN"),
CLK(pll_clk, NULL, "PLLCLK"), CLK(pll_clk, NULL, "PLLCLK"),
...@@ -375,6 +381,7 @@ static struct clk_lookup bf609_clks[] = { ...@@ -375,6 +381,7 @@ static struct clk_lookup bf609_clks[] = {
CLK(dclk, NULL, "DCLK"), CLK(dclk, NULL, "DCLK"),
CLK(oclk, NULL, "OCLK"), CLK(oclk, NULL, "OCLK"),
CLK(ethclk, NULL, "stmmaceth"), CLK(ethclk, NULL, "stmmaceth"),
CLK(spiclk, NULL, "spi"),
}; };
int __init clk_init(void) int __init clk_init(void)
......
...@@ -91,8 +91,8 @@ config SPI_BFIN5XX ...@@ -91,8 +91,8 @@ config SPI_BFIN5XX
help help
This is the SPI controller master driver for Blackfin 5xx processor. This is the SPI controller master driver for Blackfin 5xx processor.
config SPI_BFIN_V3 config SPI_ADI_V3
tristate "SPI controller v3 for Blackfin" tristate "SPI controller v3 for ADI"
depends on BF60x depends on BF60x
help help
This is the SPI controller v3 master driver This is the SPI controller v3 master driver
...@@ -148,6 +148,13 @@ config SPI_BUTTERFLY ...@@ -148,6 +148,13 @@ config SPI_BUTTERFLY
inexpensive battery powered microcontroller evaluation board. inexpensive battery powered microcontroller evaluation board.
This same cable can be used to flash new firmware. This same cable can be used to flash new firmware.
config SPI_CADENCE
tristate "Cadence SPI controller"
depends on ARM
help
This selects the Cadence SPI controller master driver
used by Xilinx Zynq.
config SPI_CLPS711X config SPI_CLPS711X
tristate "CLPS711X host SPI controller" tristate "CLPS711X host SPI controller"
depends on ARCH_CLPS711X || COMPILE_TEST depends on ARCH_CLPS711X || COMPILE_TEST
...@@ -505,7 +512,7 @@ config SPI_TEGRA20_SLINK ...@@ -505,7 +512,7 @@ config SPI_TEGRA20_SLINK
config SPI_TOPCLIFF_PCH config SPI_TOPCLIFF_PCH
tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) SPI" tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) SPI"
depends on PCI depends on PCI && (X86_32 || COMPILE_TEST)
help help
SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus
used in some x86 embedded processors. used in some x86 embedded processors.
......
...@@ -18,10 +18,11 @@ obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o ...@@ -18,10 +18,11 @@ obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o
obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
obj-$(CONFIG_SPI_BCM63XX_HSSPI) += spi-bcm63xx-hsspi.o obj-$(CONFIG_SPI_BCM63XX_HSSPI) += spi-bcm63xx-hsspi.o
obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o
obj-$(CONFIG_SPI_BFIN_V3) += spi-bfin-v3.o obj-$(CONFIG_SPI_ADI_V3) += spi-adi-v3.o
obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
obj-$(CONFIG_SPI_CADENCE) += spi-cadence.o
obj-$(CONFIG_SPI_CLPS711X) += spi-clps711x.o obj-$(CONFIG_SPI_CLPS711X) += spi-clps711x.o
obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o
obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o
......
/* /*
* Analog Devices SPI3 controller driver * Analog Devices SPI3 controller driver
* *
* Copyright (c) 2013 Analog Devices Inc. * Copyright (c) 2014 Analog Devices Inc.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
...@@ -26,35 +27,34 @@ ...@@ -26,35 +27,34 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/adi_spi3.h>
#include <linux/types.h> #include <linux/types.h>
#include <asm/bfin_spi3.h>
#include <asm/cacheflush.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/portmux.h> #include <asm/portmux.h>
enum bfin_spi_state { enum adi_spi_state {
START_STATE, START_STATE,
RUNNING_STATE, RUNNING_STATE,
DONE_STATE, DONE_STATE,
ERROR_STATE ERROR_STATE
}; };
struct bfin_spi_master; struct adi_spi_master;
struct bfin_spi_transfer_ops { struct adi_spi_transfer_ops {
void (*write) (struct bfin_spi_master *); void (*write) (struct adi_spi_master *);
void (*read) (struct bfin_spi_master *); void (*read) (struct adi_spi_master *);
void (*duplex) (struct bfin_spi_master *); void (*duplex) (struct adi_spi_master *);
}; };
/* runtime info for spi master */ /* runtime info for spi master */
struct bfin_spi_master { struct adi_spi_master {
/* SPI framework hookup */ /* SPI framework hookup */
struct spi_master *master; struct spi_master *master;
/* Regs base of SPI controller */ /* Regs base of SPI controller */
struct bfin_spi_regs __iomem *regs; struct adi_spi_regs __iomem *regs;
/* Pin request list */ /* Pin request list */
u16 *pin_req; u16 *pin_req;
...@@ -65,7 +65,7 @@ struct bfin_spi_master { ...@@ -65,7 +65,7 @@ struct bfin_spi_master {
/* Current message transfer state info */ /* Current message transfer state info */
struct spi_message *cur_msg; struct spi_message *cur_msg;
struct spi_transfer *cur_transfer; struct spi_transfer *cur_transfer;
struct bfin_spi_device *cur_chip; struct adi_spi_device *cur_chip;
unsigned transfer_len; unsigned transfer_len;
/* transfer buffer */ /* transfer buffer */
...@@ -90,12 +90,12 @@ struct bfin_spi_master { ...@@ -90,12 +90,12 @@ struct bfin_spi_master {
u32 ssel; u32 ssel;
unsigned long sclk; unsigned long sclk;
enum bfin_spi_state state; enum adi_spi_state state;
const struct bfin_spi_transfer_ops *ops; const struct adi_spi_transfer_ops *ops;
}; };
struct bfin_spi_device { struct adi_spi_device {
u32 control; u32 control;
u32 clock; u32 clock;
u32 ssel; u32 ssel;
...@@ -105,17 +105,25 @@ struct bfin_spi_device { ...@@ -105,17 +105,25 @@ struct bfin_spi_device {
u32 cs_gpio; u32 cs_gpio;
u32 tx_dummy_val; /* tx value for rx only transfer */ u32 tx_dummy_val; /* tx value for rx only transfer */
bool enable_dma; bool enable_dma;
const struct bfin_spi_transfer_ops *ops; const struct adi_spi_transfer_ops *ops;
}; };
static void bfin_spi_enable(struct bfin_spi_master *drv_data) static void adi_spi_enable(struct adi_spi_master *drv_data)
{ {
bfin_write_or(&drv_data->regs->control, SPI_CTL_EN); u32 ctl;
ctl = ioread32(&drv_data->regs->control);
ctl |= SPI_CTL_EN;
iowrite32(ctl, &drv_data->regs->control);
} }
static void bfin_spi_disable(struct bfin_spi_master *drv_data) static void adi_spi_disable(struct adi_spi_master *drv_data)
{ {
bfin_write_and(&drv_data->regs->control, ~SPI_CTL_EN); u32 ctl;
ctl = ioread32(&drv_data->regs->control);
ctl &= ~SPI_CTL_EN;
iowrite32(ctl, &drv_data->regs->control);
} }
/* Caculate the SPI_CLOCK register value based on input HZ */ /* Caculate the SPI_CLOCK register value based on input HZ */
...@@ -128,35 +136,43 @@ static u32 hz_to_spi_clock(u32 sclk, u32 speed_hz) ...@@ -128,35 +136,43 @@ static u32 hz_to_spi_clock(u32 sclk, u32 speed_hz)
return spi_clock; return spi_clock;
} }
static int bfin_spi_flush(struct bfin_spi_master *drv_data) static int adi_spi_flush(struct adi_spi_master *drv_data)
{ {
unsigned long limit = loops_per_jiffy << 1; unsigned long limit = loops_per_jiffy << 1;
/* wait for stop and clear stat */ /* wait for stop and clear stat */
while (!(bfin_read(&drv_data->regs->status) & SPI_STAT_SPIF) && --limit) while (!(ioread32(&drv_data->regs->status) & SPI_STAT_SPIF) && --limit)
cpu_relax(); cpu_relax();
bfin_write(&drv_data->regs->status, 0xFFFFFFFF); iowrite32(0xFFFFFFFF, &drv_data->regs->status);
return limit; return limit;
} }
/* Chip select operation functions for cs_change flag */ /* Chip select operation functions for cs_change flag */
static void bfin_spi_cs_active(struct bfin_spi_master *drv_data, struct bfin_spi_device *chip) static void adi_spi_cs_active(struct adi_spi_master *drv_data, struct adi_spi_device *chip)
{ {
if (likely(chip->cs < MAX_CTRL_CS)) if (likely(chip->cs < MAX_CTRL_CS)) {
bfin_write_and(&drv_data->regs->ssel, ~chip->ssel); u32 reg;
else reg = ioread32(&drv_data->regs->ssel);
reg &= ~chip->ssel;
iowrite32(reg, &drv_data->regs->ssel);
} else {
gpio_set_value(chip->cs_gpio, 0); gpio_set_value(chip->cs_gpio, 0);
}
} }
static void bfin_spi_cs_deactive(struct bfin_spi_master *drv_data, static void adi_spi_cs_deactive(struct adi_spi_master *drv_data,
struct bfin_spi_device *chip) struct adi_spi_device *chip)
{ {
if (likely(chip->cs < MAX_CTRL_CS)) if (likely(chip->cs < MAX_CTRL_CS)) {
bfin_write_or(&drv_data->regs->ssel, chip->ssel); u32 reg;
else reg = ioread32(&drv_data->regs->ssel);
reg |= chip->ssel;
iowrite32(reg, &drv_data->regs->ssel);
} else {
gpio_set_value(chip->cs_gpio, 1); gpio_set_value(chip->cs_gpio, 1);
}
/* Move delay here for consistency */ /* Move delay here for consistency */
if (chip->cs_chg_udelay) if (chip->cs_chg_udelay)
...@@ -164,187 +180,192 @@ static void bfin_spi_cs_deactive(struct bfin_spi_master *drv_data, ...@@ -164,187 +180,192 @@ static void bfin_spi_cs_deactive(struct bfin_spi_master *drv_data,
} }
/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */ /* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */
static inline void bfin_spi_cs_enable(struct bfin_spi_master *drv_data, static inline void adi_spi_cs_enable(struct adi_spi_master *drv_data,
struct bfin_spi_device *chip) struct adi_spi_device *chip)
{ {
if (chip->cs < MAX_CTRL_CS) if (chip->cs < MAX_CTRL_CS) {
bfin_write_or(&drv_data->regs->ssel, chip->ssel >> 8); u32 reg;
reg = ioread32(&drv_data->regs->ssel);
reg |= chip->ssel >> 8;
iowrite32(reg, &drv_data->regs->ssel);
}
} }
static inline void bfin_spi_cs_disable(struct bfin_spi_master *drv_data, static inline void adi_spi_cs_disable(struct adi_spi_master *drv_data,
struct bfin_spi_device *chip) struct adi_spi_device *chip)
{ {
if (chip->cs < MAX_CTRL_CS) if (chip->cs < MAX_CTRL_CS) {
bfin_write_and(&drv_data->regs->ssel, ~(chip->ssel >> 8)); u32 reg;
reg = ioread32(&drv_data->regs->ssel);
reg &= ~(chip->ssel >> 8);
iowrite32(reg, &drv_data->regs->ssel);
}
} }
/* stop controller and re-config current chip*/ /* stop controller and re-config current chip*/
static void bfin_spi_restore_state(struct bfin_spi_master *drv_data) static void adi_spi_restore_state(struct adi_spi_master *drv_data)
{ {
struct bfin_spi_device *chip = drv_data->cur_chip; struct adi_spi_device *chip = drv_data->cur_chip;
/* Clear status and disable clock */ /* Clear status and disable clock */
bfin_write(&drv_data->regs->status, 0xFFFFFFFF); iowrite32(0xFFFFFFFF, &drv_data->regs->status);
bfin_write(&drv_data->regs->rx_control, 0x0); iowrite32(0x0, &drv_data->regs->rx_control);
bfin_write(&drv_data->regs->tx_control, 0x0); iowrite32(0x0, &drv_data->regs->tx_control);
bfin_spi_disable(drv_data); adi_spi_disable(drv_data);
SSYNC();
/* Load the registers */ /* Load the registers */
bfin_write(&drv_data->regs->control, chip->control); iowrite32(chip->control, &drv_data->regs->control);
bfin_write(&drv_data->regs->clock, chip->clock); iowrite32(chip->clock, &drv_data->regs->clock);
bfin_spi_enable(drv_data); adi_spi_enable(drv_data);
drv_data->tx_num = drv_data->rx_num = 0; drv_data->tx_num = drv_data->rx_num = 0;
/* we always choose tx transfer initiate */ /* we always choose tx transfer initiate */
bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN); iowrite32(SPI_RXCTL_REN, &drv_data->regs->rx_control);
bfin_write(&drv_data->regs->tx_control, iowrite32(SPI_TXCTL_TEN | SPI_TXCTL_TTI, &drv_data->regs->tx_control);
SPI_TXCTL_TEN | SPI_TXCTL_TTI); adi_spi_cs_active(drv_data, chip);
bfin_spi_cs_active(drv_data, chip);
} }
/* discard invalid rx data and empty rfifo */ /* discard invalid rx data and empty rfifo */
static inline void dummy_read(struct bfin_spi_master *drv_data) static inline void dummy_read(struct adi_spi_master *drv_data)
{ {
while (!(bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)) while (!(ioread32(&drv_data->regs->status) & SPI_STAT_RFE))
bfin_read(&drv_data->regs->rfifo); ioread32(&drv_data->regs->rfifo);
} }
static void bfin_spi_u8_write(struct bfin_spi_master *drv_data) static void adi_spi_u8_write(struct adi_spi_master *drv_data)
{ {
dummy_read(drv_data); dummy_read(drv_data);
while (drv_data->tx < drv_data->tx_end) { while (drv_data->tx < drv_data->tx_end) {
bfin_write(&drv_data->regs->tfifo, (*(u8 *)(drv_data->tx++))); iowrite32(*(u8 *)(drv_data->tx++), &drv_data->regs->tfifo);
while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
cpu_relax(); cpu_relax();
bfin_read(&drv_data->regs->rfifo); ioread32(&drv_data->regs->rfifo);
} }
} }
static void bfin_spi_u8_read(struct bfin_spi_master *drv_data) static void adi_spi_u8_read(struct adi_spi_master *drv_data)
{ {
u32 tx_val = drv_data->cur_chip->tx_dummy_val; u32 tx_val = drv_data->cur_chip->tx_dummy_val;
dummy_read(drv_data); dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end) { while (drv_data->rx < drv_data->rx_end) {
bfin_write(&drv_data->regs->tfifo, tx_val); iowrite32(tx_val, &drv_data->regs->tfifo);
while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
cpu_relax(); cpu_relax();
*(u8 *)(drv_data->rx++) = bfin_read(&drv_data->regs->rfifo); *(u8 *)(drv_data->rx++) = ioread32(&drv_data->regs->rfifo);
} }
} }
static void bfin_spi_u8_duplex(struct bfin_spi_master *drv_data) static void adi_spi_u8_duplex(struct adi_spi_master *drv_data)
{ {
dummy_read(drv_data); dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end) { while (drv_data->rx < drv_data->rx_end) {
bfin_write(&drv_data->regs->tfifo, (*(u8 *)(drv_data->tx++))); iowrite32(*(u8 *)(drv_data->tx++), &drv_data->regs->tfifo);
while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
cpu_relax(); cpu_relax();
*(u8 *)(drv_data->rx++) = bfin_read(&drv_data->regs->rfifo); *(u8 *)(drv_data->rx++) = ioread32(&drv_data->regs->rfifo);
} }
} }
static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u8 = { static const struct adi_spi_transfer_ops adi_spi_transfer_ops_u8 = {
.write = bfin_spi_u8_write, .write = adi_spi_u8_write,
.read = bfin_spi_u8_read, .read = adi_spi_u8_read,
.duplex = bfin_spi_u8_duplex, .duplex = adi_spi_u8_duplex,
}; };
static void bfin_spi_u16_write(struct bfin_spi_master *drv_data) static void adi_spi_u16_write(struct adi_spi_master *drv_data)
{ {
dummy_read(drv_data); dummy_read(drv_data);
while (drv_data->tx < drv_data->tx_end) { while (drv_data->tx < drv_data->tx_end) {
bfin_write(&drv_data->regs->tfifo, (*(u16 *)drv_data->tx)); iowrite32(*(u16 *)drv_data->tx, &drv_data->regs->tfifo);
drv_data->tx += 2; drv_data->tx += 2;
while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
cpu_relax(); cpu_relax();
bfin_read(&drv_data->regs->rfifo); ioread32(&drv_data->regs->rfifo);
} }
} }
static void bfin_spi_u16_read(struct bfin_spi_master *drv_data) static void adi_spi_u16_read(struct adi_spi_master *drv_data)
{ {
u32 tx_val = drv_data->cur_chip->tx_dummy_val; u32 tx_val = drv_data->cur_chip->tx_dummy_val;
dummy_read(drv_data); dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end) { while (drv_data->rx < drv_data->rx_end) {
bfin_write(&drv_data->regs->tfifo, tx_val); iowrite32(tx_val, &drv_data->regs->tfifo);
while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
cpu_relax(); cpu_relax();
*(u16 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo); *(u16 *)drv_data->rx = ioread32(&drv_data->regs->rfifo);
drv_data->rx += 2; drv_data->rx += 2;
} }
} }
static void bfin_spi_u16_duplex(struct bfin_spi_master *drv_data) static void adi_spi_u16_duplex(struct adi_spi_master *drv_data)
{ {
dummy_read(drv_data); dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end) { while (drv_data->rx < drv_data->rx_end) {
bfin_write(&drv_data->regs->tfifo, (*(u16 *)drv_data->tx)); iowrite32(*(u16 *)drv_data->tx, &drv_data->regs->tfifo);
drv_data->tx += 2; drv_data->tx += 2;
while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
cpu_relax(); cpu_relax();
*(u16 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo); *(u16 *)drv_data->rx = ioread32(&drv_data->regs->rfifo);
drv_data->rx += 2; drv_data->rx += 2;
} }
} }
static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u16 = { static const struct adi_spi_transfer_ops adi_spi_transfer_ops_u16 = {
.write = bfin_spi_u16_write, .write = adi_spi_u16_write,
.read = bfin_spi_u16_read, .read = adi_spi_u16_read,
.duplex = bfin_spi_u16_duplex, .duplex = adi_spi_u16_duplex,
}; };
static void bfin_spi_u32_write(struct bfin_spi_master *drv_data) static void adi_spi_u32_write(struct adi_spi_master *drv_data)
{ {
dummy_read(drv_data); dummy_read(drv_data);
while (drv_data->tx < drv_data->tx_end) { while (drv_data->tx < drv_data->tx_end) {
bfin_write(&drv_data->regs->tfifo, (*(u32 *)drv_data->tx)); iowrite32(*(u32 *)drv_data->tx, &drv_data->regs->tfifo);
drv_data->tx += 4; drv_data->tx += 4;
while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
cpu_relax(); cpu_relax();
bfin_read(&drv_data->regs->rfifo); ioread32(&drv_data->regs->rfifo);
} }
} }
static void bfin_spi_u32_read(struct bfin_spi_master *drv_data) static void adi_spi_u32_read(struct adi_spi_master *drv_data)
{ {
u32 tx_val = drv_data->cur_chip->tx_dummy_val; u32 tx_val = drv_data->cur_chip->tx_dummy_val;
dummy_read(drv_data); dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end) { while (drv_data->rx < drv_data->rx_end) {
bfin_write(&drv_data->regs->tfifo, tx_val); iowrite32(tx_val, &drv_data->regs->tfifo);
while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
cpu_relax(); cpu_relax();
*(u32 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo); *(u32 *)drv_data->rx = ioread32(&drv_data->regs->rfifo);
drv_data->rx += 4; drv_data->rx += 4;
} }
} }
static void bfin_spi_u32_duplex(struct bfin_spi_master *drv_data) static void adi_spi_u32_duplex(struct adi_spi_master *drv_data)
{ {
dummy_read(drv_data); dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end) { while (drv_data->rx < drv_data->rx_end) {
bfin_write(&drv_data->regs->tfifo, (*(u32 *)drv_data->tx)); iowrite32(*(u32 *)drv_data->tx, &drv_data->regs->tfifo);
drv_data->tx += 4; drv_data->tx += 4;
while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE)
cpu_relax(); cpu_relax();
*(u32 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo); *(u32 *)drv_data->rx = ioread32(&drv_data->regs->rfifo);
drv_data->rx += 4; drv_data->rx += 4;
} }
} }
static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u32 = { static const struct adi_spi_transfer_ops adi_spi_transfer_ops_u32 = {
.write = bfin_spi_u32_write, .write = adi_spi_u32_write,
.read = bfin_spi_u32_read, .read = adi_spi_u32_read,
.duplex = bfin_spi_u32_duplex, .duplex = adi_spi_u32_duplex,
}; };
/* test if there is more transfer to be done */ /* test if there is more transfer to be done */
static void bfin_spi_next_transfer(struct bfin_spi_master *drv) static void adi_spi_next_transfer(struct adi_spi_master *drv)
{ {
struct spi_message *msg = drv->cur_msg; struct spi_message *msg = drv->cur_msg;
struct spi_transfer *t = drv->cur_transfer; struct spi_transfer *t = drv->cur_transfer;
...@@ -360,15 +381,15 @@ static void bfin_spi_next_transfer(struct bfin_spi_master *drv) ...@@ -360,15 +381,15 @@ static void bfin_spi_next_transfer(struct bfin_spi_master *drv)
} }
} }
static void bfin_spi_giveback(struct bfin_spi_master *drv_data) static void adi_spi_giveback(struct adi_spi_master *drv_data)
{ {
struct bfin_spi_device *chip = drv_data->cur_chip; struct adi_spi_device *chip = drv_data->cur_chip;
bfin_spi_cs_deactive(drv_data, chip); adi_spi_cs_deactive(drv_data, chip);
spi_finalize_current_message(drv_data->master); spi_finalize_current_message(drv_data->master);
} }
static int bfin_spi_setup_transfer(struct bfin_spi_master *drv) static int adi_spi_setup_transfer(struct adi_spi_master *drv)
{ {
struct spi_transfer *t = drv->cur_transfer; struct spi_transfer *t = drv->cur_transfer;
u32 cr, cr_width; u32 cr, cr_width;
...@@ -393,34 +414,33 @@ static int bfin_spi_setup_transfer(struct bfin_spi_master *drv) ...@@ -393,34 +414,33 @@ static int bfin_spi_setup_transfer(struct bfin_spi_master *drv)
switch (t->bits_per_word) { switch (t->bits_per_word) {
case 8: case 8:
cr_width = SPI_CTL_SIZE08; cr_width = SPI_CTL_SIZE08;
drv->ops = &bfin_bfin_spi_transfer_ops_u8; drv->ops = &adi_spi_transfer_ops_u8;
break; break;
case 16: case 16:
cr_width = SPI_CTL_SIZE16; cr_width = SPI_CTL_SIZE16;
drv->ops = &bfin_bfin_spi_transfer_ops_u16; drv->ops = &adi_spi_transfer_ops_u16;
break; break;
case 32: case 32:
cr_width = SPI_CTL_SIZE32; cr_width = SPI_CTL_SIZE32;
drv->ops = &bfin_bfin_spi_transfer_ops_u32; drv->ops = &adi_spi_transfer_ops_u32;
break; break;
default: default:
return -EINVAL; return -EINVAL;
} }
cr = bfin_read(&drv->regs->control) & ~SPI_CTL_SIZE; cr = ioread32(&drv->regs->control) & ~SPI_CTL_SIZE;
cr |= cr_width; cr |= cr_width;
bfin_write(&drv->regs->control, cr); iowrite32(cr, &drv->regs->control);
/* speed setup */ /* speed setup */
bfin_write(&drv->regs->clock, iowrite32(hz_to_spi_clock(drv->sclk, t->speed_hz), &drv->regs->clock);
hz_to_spi_clock(drv->sclk, t->speed_hz));
return 0; return 0;
} }
static int bfin_spi_dma_xfer(struct bfin_spi_master *drv_data) static int adi_spi_dma_xfer(struct adi_spi_master *drv_data)
{ {
struct spi_transfer *t = drv_data->cur_transfer; struct spi_transfer *t = drv_data->cur_transfer;
struct spi_message *msg = drv_data->cur_msg; struct spi_message *msg = drv_data->cur_msg;
struct bfin_spi_device *chip = drv_data->cur_chip; struct adi_spi_device *chip = drv_data->cur_chip;
u32 dma_config; u32 dma_config;
unsigned long word_count, word_size; unsigned long word_count, word_size;
void *tx_buf, *rx_buf; void *tx_buf, *rx_buf;
...@@ -498,17 +518,16 @@ static int bfin_spi_dma_xfer(struct bfin_spi_master *drv_data) ...@@ -498,17 +518,16 @@ static int bfin_spi_dma_xfer(struct bfin_spi_master *drv_data)
set_dma_config(drv_data->rx_dma, dma_config | WNR); set_dma_config(drv_data->rx_dma, dma_config | WNR);
enable_dma(drv_data->tx_dma); enable_dma(drv_data->tx_dma);
enable_dma(drv_data->rx_dma); enable_dma(drv_data->rx_dma);
SSYNC();
bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN | SPI_RXCTL_RDR_NE); iowrite32(SPI_RXCTL_REN | SPI_RXCTL_RDR_NE,
SSYNC(); &drv_data->regs->rx_control);
bfin_write(&drv_data->regs->tx_control, iowrite32(SPI_TXCTL_TEN | SPI_TXCTL_TTI | SPI_TXCTL_TDR_NF,
SPI_TXCTL_TEN | SPI_TXCTL_TTI | SPI_TXCTL_TDR_NF); &drv_data->regs->tx_control);
return 0; return 0;
} }
static int bfin_spi_pio_xfer(struct bfin_spi_master *drv_data) static int adi_spi_pio_xfer(struct adi_spi_master *drv_data)
{ {
struct spi_message *msg = drv_data->cur_msg; struct spi_message *msg = drv_data->cur_msg;
...@@ -529,19 +548,19 @@ static int bfin_spi_pio_xfer(struct bfin_spi_master *drv_data) ...@@ -529,19 +548,19 @@ static int bfin_spi_pio_xfer(struct bfin_spi_master *drv_data)
return -EIO; return -EIO;
} }
if (!bfin_spi_flush(drv_data)) if (!adi_spi_flush(drv_data))
return -EIO; return -EIO;
msg->actual_length += drv_data->transfer_len; msg->actual_length += drv_data->transfer_len;
tasklet_schedule(&drv_data->pump_transfers); tasklet_schedule(&drv_data->pump_transfers);
return 0; return 0;
} }
static void bfin_spi_pump_transfers(unsigned long data) static void adi_spi_pump_transfers(unsigned long data)
{ {
struct bfin_spi_master *drv_data = (struct bfin_spi_master *)data; struct adi_spi_master *drv_data = (struct adi_spi_master *)data;
struct spi_message *msg = NULL; struct spi_message *msg = NULL;
struct spi_transfer *t = NULL; struct spi_transfer *t = NULL;
struct bfin_spi_device *chip = NULL; struct adi_spi_device *chip = NULL;
int ret; int ret;
/* Get current state information */ /* Get current state information */
...@@ -552,7 +571,7 @@ static void bfin_spi_pump_transfers(unsigned long data) ...@@ -552,7 +571,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
/* Handle for abort */ /* Handle for abort */
if (drv_data->state == ERROR_STATE) { if (drv_data->state == ERROR_STATE) {
msg->status = -EIO; msg->status = -EIO;
bfin_spi_giveback(drv_data); adi_spi_giveback(drv_data);
return; return;
} }
...@@ -560,14 +579,14 @@ static void bfin_spi_pump_transfers(unsigned long data) ...@@ -560,14 +579,14 @@ static void bfin_spi_pump_transfers(unsigned long data)
if (t->delay_usecs) if (t->delay_usecs)
udelay(t->delay_usecs); udelay(t->delay_usecs);
if (t->cs_change) if (t->cs_change)
bfin_spi_cs_deactive(drv_data, chip); adi_spi_cs_deactive(drv_data, chip);
bfin_spi_next_transfer(drv_data); adi_spi_next_transfer(drv_data);
t = drv_data->cur_transfer; t = drv_data->cur_transfer;
} }
/* Handle end of message */ /* Handle end of message */
if (drv_data->state == DONE_STATE) { if (drv_data->state == DONE_STATE) {
msg->status = 0; msg->status = 0;
bfin_spi_giveback(drv_data); adi_spi_giveback(drv_data);
return; return;
} }
...@@ -577,34 +596,34 @@ static void bfin_spi_pump_transfers(unsigned long data) ...@@ -577,34 +596,34 @@ static void bfin_spi_pump_transfers(unsigned long data)
return; return;
} }
ret = bfin_spi_setup_transfer(drv_data); ret = adi_spi_setup_transfer(drv_data);
if (ret) { if (ret) {
msg->status = ret; msg->status = ret;
bfin_spi_giveback(drv_data); adi_spi_giveback(drv_data);
} }
bfin_write(&drv_data->regs->status, 0xFFFFFFFF); iowrite32(0xFFFFFFFF, &drv_data->regs->status);
bfin_spi_cs_active(drv_data, chip); adi_spi_cs_active(drv_data, chip);
drv_data->state = RUNNING_STATE; drv_data->state = RUNNING_STATE;
if (chip->enable_dma) if (chip->enable_dma)
ret = bfin_spi_dma_xfer(drv_data); ret = adi_spi_dma_xfer(drv_data);
else else
ret = bfin_spi_pio_xfer(drv_data); ret = adi_spi_pio_xfer(drv_data);
if (ret) { if (ret) {
msg->status = ret; msg->status = ret;
bfin_spi_giveback(drv_data); adi_spi_giveback(drv_data);
} }
} }
static int bfin_spi_transfer_one_message(struct spi_master *master, static int adi_spi_transfer_one_message(struct spi_master *master,
struct spi_message *m) struct spi_message *m)
{ {
struct bfin_spi_master *drv_data = spi_master_get_devdata(master); struct adi_spi_master *drv_data = spi_master_get_devdata(master);
drv_data->cur_msg = m; drv_data->cur_msg = m;
drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
bfin_spi_restore_state(drv_data); adi_spi_restore_state(drv_data);
drv_data->state = START_STATE; drv_data->state = START_STATE;
drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next, drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
...@@ -630,15 +649,15 @@ static const u16 ssel[][MAX_SPI_SSEL] = { ...@@ -630,15 +649,15 @@ static const u16 ssel[][MAX_SPI_SSEL] = {
P_SPI2_SSEL6, P_SPI2_SSEL7}, P_SPI2_SSEL6, P_SPI2_SSEL7},
}; };
static int bfin_spi_setup(struct spi_device *spi) static int adi_spi_setup(struct spi_device *spi)
{ {
struct bfin_spi_master *drv_data = spi_master_get_devdata(spi->master); struct adi_spi_master *drv_data = spi_master_get_devdata(spi->master);
struct bfin_spi_device *chip = spi_get_ctldata(spi); struct adi_spi_device *chip = spi_get_ctldata(spi);
u32 bfin_ctl_reg = SPI_CTL_ODM | SPI_CTL_PSSE; u32 ctl_reg = SPI_CTL_ODM | SPI_CTL_PSSE;
int ret = -EINVAL; int ret = -EINVAL;
if (!chip) { if (!chip) {
struct bfin_spi3_chip *chip_info = spi->controller_data; struct adi_spi3_chip *chip_info = spi->controller_data;
chip = kzalloc(sizeof(*chip), GFP_KERNEL); chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (!chip) { if (!chip) {
...@@ -646,7 +665,7 @@ static int bfin_spi_setup(struct spi_device *spi) ...@@ -646,7 +665,7 @@ static int bfin_spi_setup(struct spi_device *spi)
return -ENOMEM; return -ENOMEM;
} }
if (chip_info) { if (chip_info) {
if (chip_info->control & ~bfin_ctl_reg) { if (chip_info->control & ~ctl_reg) {
dev_err(&spi->dev, dev_err(&spi->dev,
"do not set bits that the SPI framework manages\n"); "do not set bits that the SPI framework manages\n");
goto error; goto error;
...@@ -657,6 +676,7 @@ static int bfin_spi_setup(struct spi_device *spi) ...@@ -657,6 +676,7 @@ static int bfin_spi_setup(struct spi_device *spi)
chip->enable_dma = chip_info->enable_dma; chip->enable_dma = chip_info->enable_dma;
} }
chip->cs = spi->chip_select; chip->cs = spi->chip_select;
if (chip->cs < MAX_CTRL_CS) { if (chip->cs < MAX_CTRL_CS) {
chip->ssel = (1 << chip->cs) << 8; chip->ssel = (1 << chip->cs) << 8;
ret = peripheral_request(ssel[spi->master->bus_num] ret = peripheral_request(ssel[spi->master->bus_num]
...@@ -678,7 +698,7 @@ static int bfin_spi_setup(struct spi_device *spi) ...@@ -678,7 +698,7 @@ static int bfin_spi_setup(struct spi_device *spi)
} }
/* force a default base state */ /* force a default base state */
chip->control &= bfin_ctl_reg; chip->control &= ctl_reg;
if (spi->mode & SPI_CPOL) if (spi->mode & SPI_CPOL)
chip->control |= SPI_CTL_CPOL; chip->control |= SPI_CTL_CPOL;
...@@ -692,8 +712,8 @@ static int bfin_spi_setup(struct spi_device *spi) ...@@ -692,8 +712,8 @@ static int bfin_spi_setup(struct spi_device *spi)
chip->clock = hz_to_spi_clock(drv_data->sclk, spi->max_speed_hz); chip->clock = hz_to_spi_clock(drv_data->sclk, spi->max_speed_hz);
bfin_spi_cs_enable(drv_data, chip); adi_spi_cs_enable(drv_data, chip);
bfin_spi_cs_deactive(drv_data, chip); adi_spi_cs_deactive(drv_data, chip);
return 0; return 0;
error: error:
...@@ -705,10 +725,10 @@ static int bfin_spi_setup(struct spi_device *spi) ...@@ -705,10 +725,10 @@ static int bfin_spi_setup(struct spi_device *spi)
return ret; return ret;
} }
static void bfin_spi_cleanup(struct spi_device *spi) static void adi_spi_cleanup(struct spi_device *spi)
{ {
struct bfin_spi_device *chip = spi_get_ctldata(spi); struct adi_spi_device *chip = spi_get_ctldata(spi);
struct bfin_spi_master *drv_data = spi_master_get_devdata(spi->master); struct adi_spi_master *drv_data = spi_master_get_devdata(spi->master);
if (!chip) if (!chip)
return; return;
...@@ -716,7 +736,7 @@ static void bfin_spi_cleanup(struct spi_device *spi) ...@@ -716,7 +736,7 @@ static void bfin_spi_cleanup(struct spi_device *spi)
if (chip->cs < MAX_CTRL_CS) { if (chip->cs < MAX_CTRL_CS) {
peripheral_free(ssel[spi->master->bus_num] peripheral_free(ssel[spi->master->bus_num]
[chip->cs-1]); [chip->cs-1]);
bfin_spi_cs_disable(drv_data, chip); adi_spi_cs_disable(drv_data, chip);
} else { } else {
gpio_free(chip->cs_gpio); gpio_free(chip->cs_gpio);
} }
...@@ -725,10 +745,11 @@ static void bfin_spi_cleanup(struct spi_device *spi) ...@@ -725,10 +745,11 @@ static void bfin_spi_cleanup(struct spi_device *spi)
spi_set_ctldata(spi, NULL); spi_set_ctldata(spi, NULL);
} }
static irqreturn_t bfin_spi_tx_dma_isr(int irq, void *dev_id) static irqreturn_t adi_spi_tx_dma_isr(int irq, void *dev_id)
{ {
struct bfin_spi_master *drv_data = dev_id; struct adi_spi_master *drv_data = dev_id;
u32 dma_stat = get_dma_curr_irqstat(drv_data->tx_dma); u32 dma_stat = get_dma_curr_irqstat(drv_data->tx_dma);
u32 tx_ctl;
clear_dma_irqstat(drv_data->tx_dma); clear_dma_irqstat(drv_data->tx_dma);
if (dma_stat & DMA_DONE) { if (dma_stat & DMA_DONE) {
...@@ -739,13 +760,15 @@ static irqreturn_t bfin_spi_tx_dma_isr(int irq, void *dev_id) ...@@ -739,13 +760,15 @@ static irqreturn_t bfin_spi_tx_dma_isr(int irq, void *dev_id)
if (drv_data->tx) if (drv_data->tx)
drv_data->state = ERROR_STATE; drv_data->state = ERROR_STATE;
} }
bfin_write_and(&drv_data->regs->tx_control, ~SPI_TXCTL_TDR_NF); tx_ctl = ioread32(&drv_data->regs->tx_control);
tx_ctl &= ~SPI_TXCTL_TDR_NF;
iowrite32(tx_ctl, &drv_data->regs->tx_control);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id) static irqreturn_t adi_spi_rx_dma_isr(int irq, void *dev_id)
{ {
struct bfin_spi_master *drv_data = dev_id; struct adi_spi_master *drv_data = dev_id;
struct spi_message *msg = drv_data->cur_msg; struct spi_message *msg = drv_data->cur_msg;
u32 dma_stat = get_dma_curr_irqstat(drv_data->rx_dma); u32 dma_stat = get_dma_curr_irqstat(drv_data->rx_dma);
...@@ -760,8 +783,8 @@ static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id) ...@@ -760,8 +783,8 @@ static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id)
dev_err(&drv_data->master->dev, dev_err(&drv_data->master->dev,
"spi rx dma error: %d\n", dma_stat); "spi rx dma error: %d\n", dma_stat);
} }
bfin_write(&drv_data->regs->tx_control, 0); iowrite32(0, &drv_data->regs->tx_control);
bfin_write(&drv_data->regs->rx_control, 0); iowrite32(0, &drv_data->regs->rx_control);
if (drv_data->rx_num != drv_data->tx_num) if (drv_data->rx_num != drv_data->tx_num)
dev_dbg(&drv_data->master->dev, dev_dbg(&drv_data->master->dev,
"dma interrupt missing: tx=%d,rx=%d\n", "dma interrupt missing: tx=%d,rx=%d\n",
...@@ -770,15 +793,15 @@ static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id) ...@@ -770,15 +793,15 @@ static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int bfin_spi_probe(struct platform_device *pdev) static int adi_spi_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct bfin_spi3_master *info = dev_get_platdata(dev); struct adi_spi3_master *info = dev_get_platdata(dev);
struct spi_master *master; struct spi_master *master;
struct bfin_spi_master *drv_data; struct adi_spi_master *drv_data;
struct resource *mem, *res; struct resource *mem, *res;
unsigned int tx_dma, rx_dma; unsigned int tx_dma, rx_dma;
unsigned long sclk; struct clk *sclk;
int ret; int ret;
if (!info) { if (!info) {
...@@ -786,10 +809,10 @@ static int bfin_spi_probe(struct platform_device *pdev) ...@@ -786,10 +809,10 @@ static int bfin_spi_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
sclk = get_sclk1(); sclk = devm_clk_get(dev, "spi");
if (!sclk) { if (IS_ERR(sclk)) {
dev_err(dev, "can not get sclk1\n"); dev_err(dev, "can not get spi clock\n");
return -ENXIO; return PTR_ERR(sclk);
} }
res = platform_get_resource(pdev, IORESOURCE_DMA, 0); res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
...@@ -819,9 +842,9 @@ static int bfin_spi_probe(struct platform_device *pdev) ...@@ -819,9 +842,9 @@ static int bfin_spi_probe(struct platform_device *pdev)
master->bus_num = pdev->id; master->bus_num = pdev->id;
master->num_chipselect = info->num_chipselect; master->num_chipselect = info->num_chipselect;
master->cleanup = bfin_spi_cleanup; master->cleanup = adi_spi_cleanup;
master->setup = bfin_spi_setup; master->setup = adi_spi_setup;
master->transfer_one_message = bfin_spi_transfer_one_message; master->transfer_one_message = adi_spi_transfer_one_message;
master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) | master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) |
SPI_BPW_MASK(8); SPI_BPW_MASK(8);
...@@ -830,7 +853,7 @@ static int bfin_spi_probe(struct platform_device *pdev) ...@@ -830,7 +853,7 @@ static int bfin_spi_probe(struct platform_device *pdev)
drv_data->tx_dma = tx_dma; drv_data->tx_dma = tx_dma;
drv_data->rx_dma = rx_dma; drv_data->rx_dma = rx_dma;
drv_data->pin_req = info->pin_req; drv_data->pin_req = info->pin_req;
drv_data->sclk = sclk; drv_data->sclk = clk_get_rate(sclk);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
drv_data->regs = devm_ioremap_resource(dev, mem); drv_data->regs = devm_ioremap_resource(dev, mem);
...@@ -845,28 +868,28 @@ static int bfin_spi_probe(struct platform_device *pdev) ...@@ -845,28 +868,28 @@ static int bfin_spi_probe(struct platform_device *pdev)
dev_err(dev, "can not request SPI TX DMA channel\n"); dev_err(dev, "can not request SPI TX DMA channel\n");
goto err_put_master; goto err_put_master;
} }
set_dma_callback(tx_dma, bfin_spi_tx_dma_isr, drv_data); set_dma_callback(tx_dma, adi_spi_tx_dma_isr, drv_data);
ret = request_dma(rx_dma, "SPI_RX_DMA"); ret = request_dma(rx_dma, "SPI_RX_DMA");
if (ret) { if (ret) {
dev_err(dev, "can not request SPI RX DMA channel\n"); dev_err(dev, "can not request SPI RX DMA channel\n");
goto err_free_tx_dma; goto err_free_tx_dma;
} }
set_dma_callback(drv_data->rx_dma, bfin_spi_rx_dma_isr, drv_data); set_dma_callback(drv_data->rx_dma, adi_spi_rx_dma_isr, drv_data);
/* request CLK, MOSI and MISO */ /* request CLK, MOSI and MISO */
ret = peripheral_request_list(drv_data->pin_req, "bfin-spi3"); ret = peripheral_request_list(drv_data->pin_req, "adi-spi3");
if (ret < 0) { if (ret < 0) {
dev_err(dev, "can not request spi pins\n"); dev_err(dev, "can not request spi pins\n");
goto err_free_rx_dma; goto err_free_rx_dma;
} }
bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA); iowrite32(SPI_CTL_MSTR | SPI_CTL_CPHA, &drv_data->regs->control);
bfin_write(&drv_data->regs->ssel, 0x0000FE00); iowrite32(0x0000FE00, &drv_data->regs->ssel);
bfin_write(&drv_data->regs->delay, 0x0); iowrite32(0x0, &drv_data->regs->delay);
tasklet_init(&drv_data->pump_transfers, tasklet_init(&drv_data->pump_transfers,
bfin_spi_pump_transfers, (unsigned long)drv_data); adi_spi_pump_transfers, (unsigned long)drv_data);
/* register with the SPI framework */ /* register with the SPI framework */
ret = devm_spi_register_master(dev, master); ret = devm_spi_register_master(dev, master);
if (ret) { if (ret) {
...@@ -888,43 +911,41 @@ static int bfin_spi_probe(struct platform_device *pdev) ...@@ -888,43 +911,41 @@ static int bfin_spi_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int bfin_spi_remove(struct platform_device *pdev) static int adi_spi_remove(struct platform_device *pdev)
{ {
struct spi_master *master = platform_get_drvdata(pdev); struct spi_master *master = platform_get_drvdata(pdev);
struct bfin_spi_master *drv_data = spi_master_get_devdata(master); struct adi_spi_master *drv_data = spi_master_get_devdata(master);
bfin_spi_disable(drv_data);
adi_spi_disable(drv_data);
peripheral_free_list(drv_data->pin_req); peripheral_free_list(drv_data->pin_req);
free_dma(drv_data->rx_dma); free_dma(drv_data->rx_dma);
free_dma(drv_data->tx_dma); free_dma(drv_data->tx_dma);
return 0; return 0;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int bfin_spi_suspend(struct device *dev) static int adi_spi_suspend(struct device *dev)
{ {
struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev);
struct bfin_spi_master *drv_data = spi_master_get_devdata(master); struct adi_spi_master *drv_data = spi_master_get_devdata(master);
spi_master_suspend(master); spi_master_suspend(master);
drv_data->control = bfin_read(&drv_data->regs->control); drv_data->control = ioread32(&drv_data->regs->control);
drv_data->ssel = bfin_read(&drv_data->regs->ssel); drv_data->ssel = ioread32(&drv_data->regs->ssel);
bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA); iowrite32(SPI_CTL_MSTR | SPI_CTL_CPHA, &drv_data->regs->control);
bfin_write(&drv_data->regs->ssel, 0x0000FE00); iowrite32(0x0000FE00, &drv_data->regs->ssel);
dma_disable_irq(drv_data->rx_dma); dma_disable_irq(drv_data->rx_dma);
dma_disable_irq(drv_data->tx_dma); dma_disable_irq(drv_data->tx_dma);
return 0; return 0;
} }
static int bfin_spi_resume(struct device *dev) static int adi_spi_resume(struct device *dev)
{ {
struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev);
struct bfin_spi_master *drv_data = spi_master_get_devdata(master); struct adi_spi_master *drv_data = spi_master_get_devdata(master);
int ret = 0; int ret = 0;
/* bootrom may modify spi and dma status when resume in spi boot mode */ /* bootrom may modify spi and dma status when resume in spi boot mode */
...@@ -932,8 +953,8 @@ static int bfin_spi_resume(struct device *dev) ...@@ -932,8 +953,8 @@ static int bfin_spi_resume(struct device *dev)
dma_enable_irq(drv_data->rx_dma); dma_enable_irq(drv_data->rx_dma);
dma_enable_irq(drv_data->tx_dma); dma_enable_irq(drv_data->tx_dma);
bfin_write(&drv_data->regs->control, drv_data->control); iowrite32(drv_data->control, &drv_data->regs->control);
bfin_write(&drv_data->regs->ssel, drv_data->ssel); iowrite32(drv_data->ssel, &drv_data->regs->ssel);
ret = spi_master_resume(master); ret = spi_master_resume(master);
if (ret) { if (ret) {
...@@ -944,21 +965,21 @@ static int bfin_spi_resume(struct device *dev) ...@@ -944,21 +965,21 @@ static int bfin_spi_resume(struct device *dev)
return ret; return ret;
} }
#endif #endif
static const struct dev_pm_ops bfin_spi_pm_ops = { static const struct dev_pm_ops adi_spi_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(bfin_spi_suspend, bfin_spi_resume) SET_SYSTEM_SLEEP_PM_OPS(adi_spi_suspend, adi_spi_resume)
}; };
MODULE_ALIAS("platform:bfin-spi3"); MODULE_ALIAS("platform:adi-spi3");
static struct platform_driver bfin_spi_driver = { static struct platform_driver adi_spi_driver = {
.driver = { .driver = {
.name = "bfin-spi3", .name = "adi-spi3",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &bfin_spi_pm_ops, .pm = &adi_spi_pm_ops,
}, },
.remove = bfin_spi_remove, .remove = adi_spi_remove,
}; };
module_platform_driver_probe(bfin_spi_driver, bfin_spi_probe); module_platform_driver_probe(adi_spi_driver, adi_spi_probe);
MODULE_DESCRIPTION("Analog Devices SPI3 controller driver"); MODULE_DESCRIPTION("Analog Devices SPI3 controller driver");
MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
......
...@@ -224,7 +224,7 @@ struct atmel_spi { ...@@ -224,7 +224,7 @@ struct atmel_spi {
struct platform_device *pdev; struct platform_device *pdev;
struct spi_transfer *current_transfer; struct spi_transfer *current_transfer;
unsigned long current_remaining_bytes; int current_remaining_bytes;
int done_status; int done_status;
struct completion xfer_completion; struct completion xfer_completion;
...@@ -874,8 +874,9 @@ atmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer) ...@@ -874,8 +874,9 @@ atmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer)
spi_readl(as, RDR); spi_readl(as, RDR);
} }
if (xfer->bits_per_word > 8) { if (xfer->bits_per_word > 8) {
if (as->current_remaining_bytes > 2)
as->current_remaining_bytes -= 2; as->current_remaining_bytes -= 2;
if (as->current_remaining_bytes < 0) else
as->current_remaining_bytes = 0; as->current_remaining_bytes = 0;
} else { } else {
as->current_remaining_bytes--; as->current_remaining_bytes--;
...@@ -1110,6 +1111,8 @@ static int atmel_spi_one_transfer(struct spi_master *master, ...@@ -1110,6 +1111,8 @@ static int atmel_spi_one_transfer(struct spi_master *master,
atmel_spi_next_xfer_pio(master, xfer); atmel_spi_next_xfer_pio(master, xfer);
} else { } else {
as->current_remaining_bytes -= len; as->current_remaining_bytes -= len;
if (as->current_remaining_bytes < 0)
as->current_remaining_bytes = 0;
} }
} else { } else {
atmel_spi_next_xfer_pio(master, xfer); atmel_spi_next_xfer_pio(master, xfer);
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/workqueue.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#define HSSPI_GLOBAL_CTRL_REG 0x0 #define HSSPI_GLOBAL_CTRL_REG 0x0
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/workqueue.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <bcm63xx_dev_spi.h> #include <bcm63xx_dev_spi.h>
......
/*
* Cadence SPI controller driver (master mode only)
*
* Copyright (C) 2008 - 2014 Xilinx, Inc.
*
* based on Blackfin On-Chip SPI Driver (spi_bfin5xx.c)
*
* 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; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
/* Name of this driver */
#define CDNS_SPI_NAME "cdns-spi"
/* Register offset definitions */
#define CDNS_SPI_CR_OFFSET 0x00 /* Configuration Register, RW */
#define CDNS_SPI_ISR_OFFSET 0x04 /* Interrupt Status Register, RO */
#define CDNS_SPI_IER_OFFSET 0x08 /* Interrupt Enable Register, WO */
#define CDNS_SPI_IDR_OFFSET 0x0c /* Interrupt Disable Register, WO */
#define CDNS_SPI_IMR_OFFSET 0x10 /* Interrupt Enabled Mask Register, RO */
#define CDNS_SPI_ER_OFFSET 0x14 /* Enable/Disable Register, RW */
#define CDNS_SPI_DR_OFFSET 0x18 /* Delay Register, RW */
#define CDNS_SPI_TXD_OFFSET 0x1C /* Data Transmit Register, WO */
#define CDNS_SPI_RXD_OFFSET 0x20 /* Data Receive Register, RO */
#define CDNS_SPI_SICR_OFFSET 0x24 /* Slave Idle Count Register, RW */
#define CDNS_SPI_THLD_OFFSET 0x28 /* Transmit FIFO Watermark Register,RW */
/*
* SPI Configuration Register bit Masks
*
* This register contains various control bits that affect the operation
* of the SPI controller
*/
#define CDNS_SPI_CR_MANSTRT_MASK 0x00010000 /* Manual TX Start */
#define CDNS_SPI_CR_CPHA_MASK 0x00000004 /* Clock Phase Control */
#define CDNS_SPI_CR_CPOL_MASK 0x00000002 /* Clock Polarity Control */
#define CDNS_SPI_CR_SSCTRL_MASK 0x00003C00 /* Slave Select Mask */
#define CDNS_SPI_CR_BAUD_DIV_MASK 0x00000038 /* Baud Rate Divisor Mask */
#define CDNS_SPI_CR_MSTREN_MASK 0x00000001 /* Master Enable Mask */
#define CDNS_SPI_CR_MANSTRTEN_MASK 0x00008000 /* Manual TX Enable Mask */
#define CDNS_SPI_CR_SSFORCE_MASK 0x00004000 /* Manual SS Enable Mask */
#define CDNS_SPI_CR_BAUD_DIV_4_MASK 0x00000008 /* Default Baud Div Mask */
#define CDNS_SPI_CR_DEFAULT_MASK (CDNS_SPI_CR_MSTREN_MASK | \
CDNS_SPI_CR_SSCTRL_MASK | \
CDNS_SPI_CR_SSFORCE_MASK | \
CDNS_SPI_CR_BAUD_DIV_4_MASK)
/*
* SPI Configuration Register - Baud rate and slave select
*
* These are the values used in the calculation of baud rate divisor and
* setting the slave select.
*/
#define CDNS_SPI_BAUD_DIV_MAX 7 /* Baud rate divisor maximum */
#define CDNS_SPI_BAUD_DIV_MIN 1 /* Baud rate divisor minimum */
#define CDNS_SPI_BAUD_DIV_SHIFT 3 /* Baud rate divisor shift in CR */
#define CDNS_SPI_SS_SHIFT 10 /* Slave Select field shift in CR */
#define CDNS_SPI_SS0 0x1 /* Slave Select zero */
/*
* SPI Interrupt Registers bit Masks
*
* All the four interrupt registers (Status/Mask/Enable/Disable) have the same
* bit definitions.
*/
#define CDNS_SPI_IXR_TXOW_MASK 0x00000004 /* SPI TX FIFO Overwater */
#define CDNS_SPI_IXR_MODF_MASK 0x00000002 /* SPI Mode Fault */
#define CDNS_SPI_IXR_RXNEMTY_MASK 0x00000010 /* SPI RX FIFO Not Empty */
#define CDNS_SPI_IXR_DEFAULT_MASK (CDNS_SPI_IXR_TXOW_MASK | \
CDNS_SPI_IXR_MODF_MASK)
#define CDNS_SPI_IXR_TXFULL_MASK 0x00000008 /* SPI TX Full */
#define CDNS_SPI_IXR_ALL_MASK 0x0000007F /* SPI all interrupts */
/*
* SPI Enable Register bit Masks
*
* This register is used to enable or disable the SPI controller
*/
#define CDNS_SPI_ER_ENABLE_MASK 0x00000001 /* SPI Enable Bit Mask */
#define CDNS_SPI_ER_DISABLE_MASK 0x0 /* SPI Disable Bit Mask */
/* SPI FIFO depth in bytes */
#define CDNS_SPI_FIFO_DEPTH 128
/* Default number of chip select lines */
#define CDNS_SPI_DEFAULT_NUM_CS 4
/**
* struct cdns_spi - This definition defines spi driver instance
* @regs: Virtual address of the SPI controller registers
* @ref_clk: Pointer to the peripheral clock
* @pclk: Pointer to the APB clock
* @speed_hz: Current SPI bus clock speed in Hz
* @txbuf: Pointer to the TX buffer
* @rxbuf: Pointer to the RX buffer
* @tx_bytes: Number of bytes left to transfer
* @rx_bytes: Number of bytes requested
* @dev_busy: Device busy flag
* @is_decoded_cs: Flag for decoder property set or not
*/
struct cdns_spi {
void __iomem *regs;
struct clk *ref_clk;
struct clk *pclk;
u32 speed_hz;
const u8 *txbuf;
u8 *rxbuf;
int tx_bytes;
int rx_bytes;
u8 dev_busy;
u32 is_decoded_cs;
};
/* Macros for the SPI controller read/write */
static inline u32 cdns_spi_read(struct cdns_spi *xspi, u32 offset)
{
return readl_relaxed(xspi->regs + offset);
}
static inline void cdns_spi_write(struct cdns_spi *xspi, u32 offset, u32 val)
{
writel_relaxed(val, xspi->regs + offset);
}
/**
* cdns_spi_init_hw - Initialize the hardware and configure the SPI controller
* @xspi: Pointer to the cdns_spi structure
*
* On reset the SPI controller is configured to be in master mode, baud rate
* divisor is set to 4, threshold value for TX FIFO not full interrupt is set
* to 1 and size of the word to be transferred as 8 bit.
* This function initializes the SPI controller to disable and clear all the
* interrupts, enable manual slave select and manual start, deselect all the
* chip select lines, and enable the SPI controller.
*/
static void cdns_spi_init_hw(struct cdns_spi *xspi)
{
cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
CDNS_SPI_ER_DISABLE_MASK);
cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET,
CDNS_SPI_IXR_ALL_MASK);
/* Clear the RX FIFO */
while (cdns_spi_read(xspi, CDNS_SPI_ISR_OFFSET) &
CDNS_SPI_IXR_RXNEMTY_MASK)
cdns_spi_read(xspi, CDNS_SPI_RXD_OFFSET);
cdns_spi_write(xspi, CDNS_SPI_ISR_OFFSET,
CDNS_SPI_IXR_ALL_MASK);
cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET,
CDNS_SPI_CR_DEFAULT_MASK);
cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
CDNS_SPI_ER_ENABLE_MASK);
}
/**
* cdns_spi_chipselect - Select or deselect the chip select line
* @spi: Pointer to the spi_device structure
* @is_on: Select(0) or deselect (1) the chip select line
*/
static void cdns_spi_chipselect(struct spi_device *spi, bool is_high)
{
struct cdns_spi *xspi = spi_master_get_devdata(spi->master);
u32 ctrl_reg;
ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET);
if (is_high) {
/* Deselect the slave */
ctrl_reg |= CDNS_SPI_CR_SSCTRL_MASK;
} else {
/* Select the slave */
ctrl_reg &= ~CDNS_SPI_CR_SSCTRL_MASK;
if (!(xspi->is_decoded_cs))
ctrl_reg |= ((~(CDNS_SPI_SS0 << spi->chip_select)) <<
CDNS_SPI_SS_SHIFT) &
CDNS_SPI_CR_SSCTRL_MASK;
else
ctrl_reg |= (spi->chip_select << CDNS_SPI_SS_SHIFT) &
CDNS_SPI_CR_SSCTRL_MASK;
}
cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg);
}
/**
* cdns_spi_config_clock_mode - Sets clock polarity and phase
* @spi: Pointer to the spi_device structure
*
* Sets the requested clock polarity and phase.
*/
static void cdns_spi_config_clock_mode(struct spi_device *spi)
{
struct cdns_spi *xspi = spi_master_get_devdata(spi->master);
u32 ctrl_reg;
ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET);
/* Set the SPI clock phase and clock polarity */
ctrl_reg &= ~(CDNS_SPI_CR_CPHA_MASK | CDNS_SPI_CR_CPOL_MASK);
if (spi->mode & SPI_CPHA)
ctrl_reg |= CDNS_SPI_CR_CPHA_MASK;
if (spi->mode & SPI_CPOL)
ctrl_reg |= CDNS_SPI_CR_CPOL_MASK;
cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg);
}
/**
* cdns_spi_config_clock_freq - Sets clock frequency
* @spi: Pointer to the spi_device structure
* @transfer: Pointer to the spi_transfer structure which provides
* information about next transfer setup parameters
*
* Sets the requested clock frequency.
* Note: If the requested frequency is not an exact match with what can be
* obtained using the prescalar value the driver sets the clock frequency which
* is lower than the requested frequency (maximum lower) for the transfer. If
* the requested frequency is higher or lower than that is supported by the SPI
* controller the driver will set the highest or lowest frequency supported by
* controller.
*/
static void cdns_spi_config_clock_freq(struct spi_device *spi,
struct spi_transfer *transfer)
{
struct cdns_spi *xspi = spi_master_get_devdata(spi->master);
u32 ctrl_reg, baud_rate_val;
unsigned long frequency;
frequency = clk_get_rate(xspi->ref_clk);
ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET);
/* Set the clock frequency */
if (xspi->speed_hz != transfer->speed_hz) {
/* first valid value is 1 */
baud_rate_val = CDNS_SPI_BAUD_DIV_MIN;
while ((baud_rate_val < CDNS_SPI_BAUD_DIV_MAX) &&
(frequency / (2 << baud_rate_val)) > transfer->speed_hz)
baud_rate_val++;
ctrl_reg &= ~CDNS_SPI_CR_BAUD_DIV_MASK;
ctrl_reg |= baud_rate_val << CDNS_SPI_BAUD_DIV_SHIFT;
xspi->speed_hz = frequency / (2 << baud_rate_val);
}
cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg);
}
/**
* cdns_spi_setup_transfer - Configure SPI controller for specified transfer
* @spi: Pointer to the spi_device structure
* @transfer: Pointer to the spi_transfer structure which provides
* information about next transfer setup parameters
*
* Sets the operational mode of SPI controller for the next SPI transfer and
* sets the requested clock frequency.
*
* Return: Always 0
*/
static int cdns_spi_setup_transfer(struct spi_device *spi,
struct spi_transfer *transfer)
{
struct cdns_spi *xspi = spi_master_get_devdata(spi->master);
cdns_spi_config_clock_freq(spi, transfer);
dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u clock speed\n",
__func__, spi->mode, spi->bits_per_word,
xspi->speed_hz);
return 0;
}
/**
* cdns_spi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible
* @xspi: Pointer to the cdns_spi structure
*/
static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi)
{
unsigned long trans_cnt = 0;
while ((trans_cnt < CDNS_SPI_FIFO_DEPTH) &&
(xspi->tx_bytes > 0)) {
if (xspi->txbuf)
cdns_spi_write(xspi, CDNS_SPI_TXD_OFFSET,
*xspi->txbuf++);
else
cdns_spi_write(xspi, CDNS_SPI_TXD_OFFSET, 0);
xspi->tx_bytes--;
trans_cnt++;
}
}
/**
* cdns_spi_irq - Interrupt service routine of the SPI controller
* @irq: IRQ number
* @dev_id: Pointer to the xspi structure
*
* This function handles TX empty and Mode Fault interrupts only.
* On TX empty interrupt this function reads the received data from RX FIFO and
* fills the TX FIFO if there is any data remaining to be transferred.
* On Mode Fault interrupt this function indicates that transfer is completed,
* the SPI subsystem will identify the error as the remaining bytes to be
* transferred is non-zero.
*
* Return: IRQ_HANDLED when handled; IRQ_NONE otherwise.
*/
static irqreturn_t cdns_spi_irq(int irq, void *dev_id)
{
struct spi_master *master = dev_id;
struct cdns_spi *xspi = spi_master_get_devdata(master);
u32 intr_status, status;
status = IRQ_NONE;
intr_status = cdns_spi_read(xspi, CDNS_SPI_ISR_OFFSET);
cdns_spi_write(xspi, CDNS_SPI_ISR_OFFSET, intr_status);
if (intr_status & CDNS_SPI_IXR_MODF_MASK) {
/* Indicate that transfer is completed, the SPI subsystem will
* identify the error as the remaining bytes to be
* transferred is non-zero
*/
cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET,
CDNS_SPI_IXR_DEFAULT_MASK);
spi_finalize_current_transfer(master);
status = IRQ_HANDLED;
} else if (intr_status & CDNS_SPI_IXR_TXOW_MASK) {
unsigned long trans_cnt;
trans_cnt = xspi->rx_bytes - xspi->tx_bytes;
/* Read out the data from the RX FIFO */
while (trans_cnt) {
u8 data;
data = cdns_spi_read(xspi, CDNS_SPI_RXD_OFFSET);
if (xspi->rxbuf)
*xspi->rxbuf++ = data;
xspi->rx_bytes--;
trans_cnt--;
}
if (xspi->tx_bytes) {
/* There is more data to send */
cdns_spi_fill_tx_fifo(xspi);
} else {
/* Transfer is completed */
cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET,
CDNS_SPI_IXR_DEFAULT_MASK);
spi_finalize_current_transfer(master);
}
status = IRQ_HANDLED;
}
return status;
}
/**
* cdns_transfer_one - Initiates the SPI transfer
* @master: Pointer to spi_master structure
* @spi: Pointer to the spi_device structure
* @transfer: Pointer to the spi_transfer structure which provides
* information about next transfer parameters
*
* This function fills the TX FIFO, starts the SPI transfer and
* returns a positive transfer count so that core will wait for completion.
*
* Return: Number of bytes transferred in the last transfer
*/
static int cdns_transfer_one(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *transfer)
{
struct cdns_spi *xspi = spi_master_get_devdata(master);
xspi->txbuf = transfer->tx_buf;
xspi->rxbuf = transfer->rx_buf;
xspi->tx_bytes = transfer->len;
xspi->rx_bytes = transfer->len;
cdns_spi_setup_transfer(spi, transfer);
cdns_spi_fill_tx_fifo(xspi);
cdns_spi_write(xspi, CDNS_SPI_IER_OFFSET,
CDNS_SPI_IXR_DEFAULT_MASK);
return transfer->len;
}
/**
* cdns_prepare_transfer_hardware - Prepares hardware for transfer.
* @master: Pointer to the spi_master structure which provides
* information about the controller.
*
* This function enables SPI master controller.
*
* Return: 0 always
*/
static int cdns_prepare_transfer_hardware(struct spi_master *master)
{
struct cdns_spi *xspi = spi_master_get_devdata(master);
cdns_spi_config_clock_mode(master->cur_msg->spi);
cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
CDNS_SPI_ER_ENABLE_MASK);
return 0;
}
/**
* cdns_unprepare_transfer_hardware - Relaxes hardware after transfer
* @master: Pointer to the spi_master structure which provides
* information about the controller.
*
* This function disables the SPI master controller.
*
* Return: 0 always
*/
static int cdns_unprepare_transfer_hardware(struct spi_master *master)
{
struct cdns_spi *xspi = spi_master_get_devdata(master);
cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
CDNS_SPI_ER_DISABLE_MASK);
return 0;
}
/**
* cdns_spi_probe - Probe method for the SPI driver
* @pdev: Pointer to the platform_device structure
*
* This function initializes the driver data structures and the hardware.
*
* Return: 0 on success and error value on error
*/
static int cdns_spi_probe(struct platform_device *pdev)
{
int ret = 0, irq;
struct spi_master *master;
struct cdns_spi *xspi;
struct resource *res;
u32 num_cs;
master = spi_alloc_master(&pdev->dev, sizeof(*xspi));
if (master == NULL)
return -ENOMEM;
xspi = spi_master_get_devdata(master);
master->dev.of_node = pdev->dev.of_node;
platform_set_drvdata(pdev, master);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
xspi->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(xspi->regs)) {
ret = PTR_ERR(xspi->regs);
goto remove_master;
}
xspi->pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(xspi->pclk)) {
dev_err(&pdev->dev, "pclk clock not found.\n");
ret = PTR_ERR(xspi->pclk);
goto remove_master;
}
xspi->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
if (IS_ERR(xspi->ref_clk)) {
dev_err(&pdev->dev, "ref_clk clock not found.\n");
ret = PTR_ERR(xspi->ref_clk);
goto remove_master;
}
ret = clk_prepare_enable(xspi->pclk);
if (ret) {
dev_err(&pdev->dev, "Unable to enable APB clock.\n");
goto remove_master;
}
ret = clk_prepare_enable(xspi->ref_clk);
if (ret) {
dev_err(&pdev->dev, "Unable to enable device clock.\n");
goto clk_dis_apb;
}
/* SPI controller initializations */
cdns_spi_init_hw(xspi);
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
ret = -ENXIO;
dev_err(&pdev->dev, "irq number is invalid\n");
goto remove_master;
}
ret = devm_request_irq(&pdev->dev, irq, cdns_spi_irq,
0, pdev->name, master);
if (ret != 0) {
ret = -ENXIO;
dev_err(&pdev->dev, "request_irq failed\n");
goto remove_master;
}
ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
if (ret < 0)
master->num_chipselect = CDNS_SPI_DEFAULT_NUM_CS;
else
master->num_chipselect = num_cs;
ret = of_property_read_u32(pdev->dev.of_node, "is-decoded-cs",
&xspi->is_decoded_cs);
if (ret < 0)
xspi->is_decoded_cs = 0;
master->prepare_transfer_hardware = cdns_prepare_transfer_hardware;
master->transfer_one = cdns_transfer_one;
master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware;
master->set_cs = cdns_spi_chipselect;
master->mode_bits = SPI_CPOL | SPI_CPHA;
/* Set to default valid value */
master->max_speed_hz = clk_get_rate(xspi->ref_clk) / 4;
xspi->speed_hz = master->max_speed_hz;
master->bits_per_word_mask = SPI_BPW_MASK(8);
ret = spi_register_master(master);
if (ret) {
dev_err(&pdev->dev, "spi_register_master failed\n");
goto clk_dis_all;
}
return ret;
clk_dis_all:
clk_disable_unprepare(xspi->ref_clk);
clk_dis_apb:
clk_disable_unprepare(xspi->pclk);
remove_master:
spi_master_put(master);
return ret;
}
/**
* cdns_spi_remove - Remove method for the SPI driver
* @pdev: Pointer to the platform_device structure
*
* This function is called if a device is physically removed from the system or
* if the driver module is being unloaded. It frees all resources allocated to
* the device.
*
* Return: 0 on success and error value on error
*/
static int cdns_spi_remove(struct platform_device *pdev)
{
struct spi_master *master = platform_get_drvdata(pdev);
struct cdns_spi *xspi = spi_master_get_devdata(master);
cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
CDNS_SPI_ER_DISABLE_MASK);
clk_disable_unprepare(xspi->ref_clk);
clk_disable_unprepare(xspi->pclk);
spi_unregister_master(master);
return 0;
}
/**
* cdns_spi_suspend - Suspend method for the SPI driver
* @dev: Address of the platform_device structure
*
* This function disables the SPI controller and
* changes the driver state to "suspend"
*
* Return: Always 0
*/
static int __maybe_unused cdns_spi_suspend(struct device *dev)
{
struct platform_device *pdev = container_of(dev,
struct platform_device, dev);
struct spi_master *master = platform_get_drvdata(pdev);
struct cdns_spi *xspi = spi_master_get_devdata(master);
spi_master_suspend(master);
clk_disable_unprepare(xspi->ref_clk);
clk_disable_unprepare(xspi->pclk);
return 0;
}
/**
* cdns_spi_resume - Resume method for the SPI driver
* @dev: Address of the platform_device structure
*
* This function changes the driver state to "ready"
*
* Return: 0 on success and error value on error
*/
static int __maybe_unused cdns_spi_resume(struct device *dev)
{
struct platform_device *pdev = container_of(dev,
struct platform_device, dev);
struct spi_master *master = platform_get_drvdata(pdev);
struct cdns_spi *xspi = spi_master_get_devdata(master);
int ret = 0;
ret = clk_prepare_enable(xspi->pclk);
if (ret) {
dev_err(dev, "Cannot enable APB clock.\n");
return ret;
}
ret = clk_prepare_enable(xspi->ref_clk);
if (ret) {
dev_err(dev, "Cannot enable device clock.\n");
clk_disable(xspi->pclk);
return ret;
}
spi_master_resume(master);
return 0;
}
static SIMPLE_DEV_PM_OPS(cdns_spi_dev_pm_ops, cdns_spi_suspend,
cdns_spi_resume);
static struct of_device_id cdns_spi_of_match[] = {
{ .compatible = "xlnx,zynq-spi-r1p6" },
{ .compatible = "cdns,spi-r1p6" },
{ /* end of table */ }
};
MODULE_DEVICE_TABLE(of, cdns_spi_of_match);
/* cdns_spi_driver - This structure defines the SPI subsystem platform driver */
static struct platform_driver cdns_spi_driver = {
.probe = cdns_spi_probe,
.remove = cdns_spi_remove,
.driver = {
.name = CDNS_SPI_NAME,
.owner = THIS_MODULE,
.of_match_table = cdns_spi_of_match,
.pm = &cdns_spi_dev_pm_ops,
},
};
module_platform_driver(cdns_spi_driver);
MODULE_AUTHOR("Xilinx, Inc.");
MODULE_DESCRIPTION("Cadence SPI driver");
MODULE_LICENSE("GPL");
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_gpio.h>
#include "spi-dw.h" #include "spi-dw.h"
...@@ -70,6 +71,27 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) ...@@ -70,6 +71,27 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
dws->num_cs = 4; dws->num_cs = 4;
dws->max_freq = clk_get_rate(dwsmmio->clk); dws->max_freq = clk_get_rate(dwsmmio->clk);
if (pdev->dev.of_node) {
int i;
for (i = 0; i < dws->num_cs; i++) {
int cs_gpio = of_get_named_gpio(pdev->dev.of_node,
"cs-gpios", i);
if (cs_gpio == -EPROBE_DEFER) {
ret = cs_gpio;
goto out;
}
if (gpio_is_valid(cs_gpio)) {
ret = devm_gpio_request(&pdev->dev, cs_gpio,
dev_name(&pdev->dev));
if (ret)
goto out;
}
}
}
ret = dw_spi_add_host(&pdev->dev, dws); ret = dw_spi_add_host(&pdev->dev, dws);
if (ret) if (ret)
goto out; goto out;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/gpio.h>
#include "spi-dw.h" #include "spi-dw.h"
...@@ -36,12 +37,6 @@ ...@@ -36,12 +37,6 @@
#define DONE_STATE ((void *)2) #define DONE_STATE ((void *)2)
#define ERROR_STATE ((void *)-1) #define ERROR_STATE ((void *)-1)
#define QUEUE_RUNNING 0
#define QUEUE_STOPPED 1
#define MRST_SPI_DEASSERT 0
#define MRST_SPI_ASSERT 1
/* Slave spi_dev related */ /* Slave spi_dev related */
struct chip_data { struct chip_data {
u16 cr0; u16 cr0;
...@@ -263,28 +258,22 @@ static int map_dma_buffers(struct dw_spi *dws) ...@@ -263,28 +258,22 @@ static int map_dma_buffers(struct dw_spi *dws)
static void giveback(struct dw_spi *dws) static void giveback(struct dw_spi *dws)
{ {
struct spi_transfer *last_transfer; struct spi_transfer *last_transfer;
unsigned long flags;
struct spi_message *msg; struct spi_message *msg;
spin_lock_irqsave(&dws->lock, flags);
msg = dws->cur_msg; msg = dws->cur_msg;
dws->cur_msg = NULL; dws->cur_msg = NULL;
dws->cur_transfer = NULL; dws->cur_transfer = NULL;
dws->prev_chip = dws->cur_chip; dws->prev_chip = dws->cur_chip;
dws->cur_chip = NULL; dws->cur_chip = NULL;
dws->dma_mapped = 0; dws->dma_mapped = 0;
queue_work(dws->workqueue, &dws->pump_messages);
spin_unlock_irqrestore(&dws->lock, flags);
last_transfer = list_last_entry(&msg->transfers, struct spi_transfer, last_transfer = list_last_entry(&msg->transfers, struct spi_transfer,
transfer_list); transfer_list);
if (!last_transfer->cs_change && dws->cs_control) if (!last_transfer->cs_change)
dws->cs_control(MRST_SPI_DEASSERT); spi_chip_sel(dws, dws->cur_msg->spi, 0);
msg->state = NULL; spi_finalize_current_message(dws->master);
if (msg->complete)
msg->complete(msg->context);
} }
static void int_error_stop(struct dw_spi *dws, const char *msg) static void int_error_stop(struct dw_spi *dws, const char *msg)
...@@ -502,7 +491,7 @@ static void pump_transfers(unsigned long data) ...@@ -502,7 +491,7 @@ static void pump_transfers(unsigned long data)
dw_writew(dws, DW_SPI_CTRL0, cr0); dw_writew(dws, DW_SPI_CTRL0, cr0);
spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);
spi_chip_sel(dws, spi->chip_select); spi_chip_sel(dws, spi, 1);
/* Set the interrupt mask, for poll mode just disable all int */ /* Set the interrupt mask, for poll mode just disable all int */
spi_mask_intr(dws, 0xff); spi_mask_intr(dws, 0xff);
...@@ -529,30 +518,12 @@ static void pump_transfers(unsigned long data) ...@@ -529,30 +518,12 @@ static void pump_transfers(unsigned long data)
return; return;
} }
static void pump_messages(struct work_struct *work) static int dw_spi_transfer_one_message(struct spi_master *master,
struct spi_message *msg)
{ {
struct dw_spi *dws = struct dw_spi *dws = spi_master_get_devdata(master);
container_of(work, struct dw_spi, pump_messages);
unsigned long flags;
/* Lock queue and check for queue work */
spin_lock_irqsave(&dws->lock, flags);
if (list_empty(&dws->queue) || dws->run == QUEUE_STOPPED) {
dws->busy = 0;
spin_unlock_irqrestore(&dws->lock, flags);
return;
}
/* Make sure we are not already running a message */
if (dws->cur_msg) {
spin_unlock_irqrestore(&dws->lock, flags);
return;
}
/* Extract head of queue */
dws->cur_msg = list_entry(dws->queue.next, struct spi_message, queue);
list_del_init(&dws->cur_msg->queue);
dws->cur_msg = msg;
/* Initial message state*/ /* Initial message state*/
dws->cur_msg->state = START_STATE; dws->cur_msg->state = START_STATE;
dws->cur_transfer = list_entry(dws->cur_msg->transfers.next, dws->cur_transfer = list_entry(dws->cur_msg->transfers.next,
...@@ -560,46 +531,9 @@ static void pump_messages(struct work_struct *work) ...@@ -560,46 +531,9 @@ static void pump_messages(struct work_struct *work)
transfer_list); transfer_list);
dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi); dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi);
/* Mark as busy and launch transfers */ /* Launch transfers */
tasklet_schedule(&dws->pump_transfers); tasklet_schedule(&dws->pump_transfers);
dws->busy = 1;
spin_unlock_irqrestore(&dws->lock, flags);
}
/* spi_device use this to queue in their spi_msg */
static int dw_spi_transfer(struct spi_device *spi, struct spi_message *msg)
{
struct dw_spi *dws = spi_master_get_devdata(spi->master);
unsigned long flags;
spin_lock_irqsave(&dws->lock, flags);
if (dws->run == QUEUE_STOPPED) {
spin_unlock_irqrestore(&dws->lock, flags);
return -ESHUTDOWN;
}
msg->actual_length = 0;
msg->status = -EINPROGRESS;
msg->state = START_STATE;
list_add_tail(&msg->queue, &dws->queue);
if (dws->run == QUEUE_RUNNING && !dws->busy) {
if (dws->cur_transfer || dws->cur_msg)
queue_work(dws->workqueue,
&dws->pump_messages);
else {
/* If no other data transaction in air, just go */
spin_unlock_irqrestore(&dws->lock, flags);
pump_messages(&dws->pump_messages);
return 0;
}
}
spin_unlock_irqrestore(&dws->lock, flags);
return 0; return 0;
} }
...@@ -608,6 +542,7 @@ static int dw_spi_setup(struct spi_device *spi) ...@@ -608,6 +542,7 @@ static int dw_spi_setup(struct spi_device *spi)
{ {
struct dw_spi_chip *chip_info = NULL; struct dw_spi_chip *chip_info = NULL;
struct chip_data *chip; struct chip_data *chip;
int ret;
/* Only alloc on first setup */ /* Only alloc on first setup */
chip = spi_get_ctldata(spi); chip = spi_get_ctldata(spi);
...@@ -661,81 +596,13 @@ static int dw_spi_setup(struct spi_device *spi) ...@@ -661,81 +596,13 @@ static int dw_spi_setup(struct spi_device *spi)
| (spi->mode << SPI_MODE_OFFSET) | (spi->mode << SPI_MODE_OFFSET)
| (chip->tmode << SPI_TMOD_OFFSET); | (chip->tmode << SPI_TMOD_OFFSET);
return 0; if (gpio_is_valid(spi->cs_gpio)) {
} ret = gpio_direction_output(spi->cs_gpio,
!(spi->mode & SPI_CS_HIGH));
static int init_queue(struct dw_spi *dws) if (ret)
{ return ret;
INIT_LIST_HEAD(&dws->queue);
spin_lock_init(&dws->lock);
dws->run = QUEUE_STOPPED;
dws->busy = 0;
tasklet_init(&dws->pump_transfers,
pump_transfers, (unsigned long)dws);
INIT_WORK(&dws->pump_messages, pump_messages);
dws->workqueue = create_singlethread_workqueue(
dev_name(dws->master->dev.parent));
if (dws->workqueue == NULL)
return -EBUSY;
return 0;
}
static int start_queue(struct dw_spi *dws)
{
unsigned long flags;
spin_lock_irqsave(&dws->lock, flags);
if (dws->run == QUEUE_RUNNING || dws->busy) {
spin_unlock_irqrestore(&dws->lock, flags);
return -EBUSY;
}
dws->run = QUEUE_RUNNING;
dws->cur_msg = NULL;
dws->cur_transfer = NULL;
dws->cur_chip = NULL;
dws->prev_chip = NULL;
spin_unlock_irqrestore(&dws->lock, flags);
queue_work(dws->workqueue, &dws->pump_messages);
return 0;
}
static int stop_queue(struct dw_spi *dws)
{
unsigned long flags;
unsigned limit = 50;
int status = 0;
spin_lock_irqsave(&dws->lock, flags);
dws->run = QUEUE_STOPPED;
while ((!list_empty(&dws->queue) || dws->busy) && limit--) {
spin_unlock_irqrestore(&dws->lock, flags);
msleep(10);
spin_lock_irqsave(&dws->lock, flags);
} }
if (!list_empty(&dws->queue) || dws->busy)
status = -EBUSY;
spin_unlock_irqrestore(&dws->lock, flags);
return status;
}
static int destroy_queue(struct dw_spi *dws)
{
int status;
status = stop_queue(dws);
if (status != 0)
return status;
destroy_workqueue(dws->workqueue);
return 0; return 0;
} }
...@@ -794,7 +661,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) ...@@ -794,7 +661,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
master->bus_num = dws->bus_num; master->bus_num = dws->bus_num;
master->num_chipselect = dws->num_cs; master->num_chipselect = dws->num_cs;
master->setup = dw_spi_setup; master->setup = dw_spi_setup;
master->transfer = dw_spi_transfer; master->transfer_one_message = dw_spi_transfer_one_message;
master->max_speed_hz = dws->max_freq; master->max_speed_hz = dws->max_freq;
/* Basic HW init */ /* Basic HW init */
...@@ -808,33 +675,21 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) ...@@ -808,33 +675,21 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
} }
} }
/* Initial and start queue */ tasklet_init(&dws->pump_transfers, pump_transfers, (unsigned long)dws);
ret = init_queue(dws);
if (ret) {
dev_err(&master->dev, "problem initializing queue\n");
goto err_diable_hw;
}
ret = start_queue(dws);
if (ret) {
dev_err(&master->dev, "problem starting queue\n");
goto err_diable_hw;
}
spi_master_set_devdata(master, dws); spi_master_set_devdata(master, dws);
ret = devm_spi_register_master(dev, master); ret = devm_spi_register_master(dev, master);
if (ret) { if (ret) {
dev_err(&master->dev, "problem registering spi master\n"); dev_err(&master->dev, "problem registering spi master\n");
goto err_queue_alloc; goto err_dma_exit;
} }
mrst_spi_debugfs_init(dws); mrst_spi_debugfs_init(dws);
return 0; return 0;
err_queue_alloc: err_dma_exit:
destroy_queue(dws);
if (dws->dma_ops && dws->dma_ops->dma_exit) if (dws->dma_ops && dws->dma_ops->dma_exit)
dws->dma_ops->dma_exit(dws); dws->dma_ops->dma_exit(dws);
err_diable_hw:
spi_enable_chip(dws, 0); spi_enable_chip(dws, 0);
err_free_master: err_free_master:
spi_master_put(master); spi_master_put(master);
...@@ -844,18 +699,10 @@ EXPORT_SYMBOL_GPL(dw_spi_add_host); ...@@ -844,18 +699,10 @@ EXPORT_SYMBOL_GPL(dw_spi_add_host);
void dw_spi_remove_host(struct dw_spi *dws) void dw_spi_remove_host(struct dw_spi *dws)
{ {
int status = 0;
if (!dws) if (!dws)
return; return;
mrst_spi_debugfs_remove(dws); mrst_spi_debugfs_remove(dws);
/* Remove the queue */
status = destroy_queue(dws);
if (status != 0)
dev_err(&dws->master->dev,
"dw_spi_remove: workqueue will not complete, message memory not freed\n");
if (dws->dma_ops && dws->dma_ops->dma_exit) if (dws->dma_ops && dws->dma_ops->dma_exit)
dws->dma_ops->dma_exit(dws); dws->dma_ops->dma_exit(dws);
spi_enable_chip(dws, 0); spi_enable_chip(dws, 0);
...@@ -868,7 +715,7 @@ int dw_spi_suspend_host(struct dw_spi *dws) ...@@ -868,7 +715,7 @@ int dw_spi_suspend_host(struct dw_spi *dws)
{ {
int ret = 0; int ret = 0;
ret = stop_queue(dws); ret = spi_master_suspend(dws->master);
if (ret) if (ret)
return ret; return ret;
spi_enable_chip(dws, 0); spi_enable_chip(dws, 0);
...@@ -882,7 +729,7 @@ int dw_spi_resume_host(struct dw_spi *dws) ...@@ -882,7 +729,7 @@ int dw_spi_resume_host(struct dw_spi *dws)
int ret; int ret;
spi_hw_init(dws); spi_hw_init(dws);
ret = start_queue(dws); ret = spi_master_resume(dws->master);
if (ret) if (ret)
dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret); dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret);
return ret; return ret;
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/gpio.h>
/* Register offsets */ /* Register offsets */
#define DW_SPI_CTRL0 0x00 #define DW_SPI_CTRL0 0x00
...@@ -104,14 +105,6 @@ struct dw_spi { ...@@ -104,14 +105,6 @@ struct dw_spi {
u16 bus_num; u16 bus_num;
u16 num_cs; /* supported slave numbers */ u16 num_cs; /* supported slave numbers */
/* Driver message queue */
struct workqueue_struct *workqueue;
struct work_struct pump_messages;
spinlock_t lock;
struct list_head queue;
int busy;
int run;
/* Message Transfer pump */ /* Message Transfer pump */
struct tasklet_struct pump_transfers; struct tasklet_struct pump_transfers;
...@@ -186,14 +179,19 @@ static inline void spi_set_clk(struct dw_spi *dws, u16 div) ...@@ -186,14 +179,19 @@ static inline void spi_set_clk(struct dw_spi *dws, u16 div)
dw_writel(dws, DW_SPI_BAUDR, div); dw_writel(dws, DW_SPI_BAUDR, div);
} }
static inline void spi_chip_sel(struct dw_spi *dws, u16 cs) static inline void spi_chip_sel(struct dw_spi *dws, struct spi_device *spi,
int active)
{ {
if (cs > dws->num_cs) u16 cs = spi->chip_select;
return; int gpio_val = active ? (spi->mode & SPI_CS_HIGH) :
!(spi->mode & SPI_CS_HIGH);
if (dws->cs_control) if (dws->cs_control)
dws->cs_control(1); dws->cs_control(active);
if (gpio_is_valid(spi->cs_gpio))
gpio_set_value(spi->cs_gpio, gpio_val);
if (active)
dw_writel(dws, DW_SPI_SER, 1 << cs); dw_writel(dws, DW_SPI_SER, 1 << cs);
} }
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
......
...@@ -406,7 +406,7 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) ...@@ -406,7 +406,7 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static struct of_device_id fsl_dspi_dt_ids[] = { static const struct of_device_id fsl_dspi_dt_ids[] = {
{ .compatible = "fsl,vf610-dspi", .data = NULL, }, { .compatible = "fsl,vf610-dspi", .data = NULL, },
{ /* sentinel */ } { /* sentinel */ }
}; };
......
...@@ -348,7 +348,7 @@ static void fsl_espi_cmd_trans(struct spi_message *m, ...@@ -348,7 +348,7 @@ static void fsl_espi_cmd_trans(struct spi_message *m,
} }
espi_trans->tx_buf = local_buf; espi_trans->tx_buf = local_buf;
espi_trans->rx_buf = local_buf + espi_trans->n_tx; espi_trans->rx_buf = local_buf;
fsl_espi_do_trans(m, espi_trans); fsl_espi_do_trans(m, espi_trans);
espi_trans->actual_length = espi_trans->len; espi_trans->actual_length = espi_trans->len;
...@@ -397,7 +397,7 @@ static void fsl_espi_rw_trans(struct spi_message *m, ...@@ -397,7 +397,7 @@ static void fsl_espi_rw_trans(struct spi_message *m,
espi_trans->n_rx = trans_len; espi_trans->n_rx = trans_len;
espi_trans->len = trans_len + n_tx; espi_trans->len = trans_len + n_tx;
espi_trans->tx_buf = local_buf; espi_trans->tx_buf = local_buf;
espi_trans->rx_buf = local_buf + n_tx; espi_trans->rx_buf = local_buf;
fsl_espi_do_trans(m, espi_trans); fsl_espi_do_trans(m, espi_trans);
memcpy(rx_buf + pos, espi_trans->rx_buf + n_tx, trans_len); memcpy(rx_buf + pos, espi_trans->rx_buf + n_tx, trans_len);
...@@ -458,7 +458,7 @@ static int fsl_espi_setup(struct spi_device *spi) ...@@ -458,7 +458,7 @@ static int fsl_espi_setup(struct spi_device *spi)
return -EINVAL; return -EINVAL;
if (!cs) { if (!cs) {
cs = kzalloc(sizeof *cs, GFP_KERNEL); cs = devm_kzalloc(&spi->dev, sizeof(*cs), GFP_KERNEL);
if (!cs) if (!cs)
return -ENOMEM; return -ENOMEM;
spi->controller_state = cs; spi->controller_state = cs;
...@@ -586,8 +586,10 @@ static struct spi_master * fsl_espi_probe(struct device *dev, ...@@ -586,8 +586,10 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
struct spi_master *master; struct spi_master *master;
struct mpc8xxx_spi *mpc8xxx_spi; struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_espi_reg *reg_base; struct fsl_espi_reg *reg_base;
u32 regval; struct device_node *nc;
int i, ret = 0; const __be32 *prop;
u32 regval, csmode;
int i, len, ret = 0;
master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi)); master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
if (!master) { if (!master) {
...@@ -634,8 +636,32 @@ static struct spi_master * fsl_espi_probe(struct device *dev, ...@@ -634,8 +636,32 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff); mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
/* Init eSPI CS mode register */ /* Init eSPI CS mode register */
for (i = 0; i < pdata->max_chipselect; i++) for_each_available_child_of_node(master->dev.of_node, nc) {
mpc8xxx_spi_write_reg(&reg_base->csmode[i], CSMODE_INIT_VAL); /* get chip select */
prop = of_get_property(nc, "reg", &len);
if (!prop || len < sizeof(*prop))
continue;
i = be32_to_cpup(prop);
if (i < 0 || i >= pdata->max_chipselect)
continue;
csmode = CSMODE_INIT_VAL;
/* check if CSBEF is set in device tree */
prop = of_get_property(nc, "fsl,csbef", &len);
if (prop && len >= sizeof(*prop)) {
csmode &= ~(CSMODE_BEF(0xf));
csmode |= CSMODE_BEF(be32_to_cpup(prop));
}
/* check if CSAFT is set in device tree */
prop = of_get_property(nc, "fsl,csaft", &len);
if (prop && len >= sizeof(*prop)) {
csmode &= ~(CSMODE_AFT(0xf));
csmode |= CSMODE_AFT(be32_to_cpup(prop));
}
mpc8xxx_spi_write_reg(&reg_base->csmode[i], csmode);
dev_info(dev, "cs=%d, init_csmode=0x%x\n", i, csmode);
}
/* Enable SPI interface */ /* Enable SPI interface */
regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE; regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
......
...@@ -99,11 +99,6 @@ int mpc8xxx_spi_transfer(struct spi_device *spi, ...@@ -99,11 +99,6 @@ int mpc8xxx_spi_transfer(struct spi_device *spi,
return 0; return 0;
} }
void mpc8xxx_spi_cleanup(struct spi_device *spi)
{
kfree(spi->controller_state);
}
const char *mpc8xxx_spi_strmode(unsigned int flags) const char *mpc8xxx_spi_strmode(unsigned int flags)
{ {
if (flags & SPI_QE_CPU_MODE) { if (flags & SPI_QE_CPU_MODE) {
...@@ -134,7 +129,6 @@ int mpc8xxx_spi_probe(struct device *dev, struct resource *mem, ...@@ -134,7 +129,6 @@ int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
| SPI_LSB_FIRST | SPI_LOOP; | SPI_LSB_FIRST | SPI_LOOP;
master->transfer = mpc8xxx_spi_transfer; master->transfer = mpc8xxx_spi_transfer;
master->cleanup = mpc8xxx_spi_cleanup;
master->dev.of_node = dev->of_node; master->dev.of_node = dev->of_node;
mpc8xxx_spi = spi_master_get_devdata(master); mpc8xxx_spi = spi_master_get_devdata(master);
......
...@@ -124,7 +124,6 @@ extern struct mpc8xxx_spi_probe_info *to_of_pinfo( ...@@ -124,7 +124,6 @@ extern struct mpc8xxx_spi_probe_info *to_of_pinfo(
extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi, extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi,
struct spi_transfer *t, unsigned int len); struct spi_transfer *t, unsigned int len);
extern int mpc8xxx_spi_transfer(struct spi_device *spi, struct spi_message *m); extern int mpc8xxx_spi_transfer(struct spi_device *spi, struct spi_message *m);
extern void mpc8xxx_spi_cleanup(struct spi_device *spi);
extern const char *mpc8xxx_spi_strmode(unsigned int flags); extern const char *mpc8xxx_spi_strmode(unsigned int flags);
extern int mpc8xxx_spi_probe(struct device *dev, struct resource *mem, extern int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
unsigned int irq); unsigned int irq);
......
...@@ -431,7 +431,7 @@ static int fsl_spi_setup(struct spi_device *spi) ...@@ -431,7 +431,7 @@ static int fsl_spi_setup(struct spi_device *spi)
return -EINVAL; return -EINVAL;
if (!cs) { if (!cs) {
cs = kzalloc(sizeof *cs, GFP_KERNEL); cs = devm_kzalloc(&spi->dev, sizeof(*cs), GFP_KERNEL);
if (!cs) if (!cs)
return -ENOMEM; return -ENOMEM;
spi->controller_state = cs; spi->controller_state = cs;
......
...@@ -340,7 +340,7 @@ static int spi_gpio_request(struct spi_gpio_platform_data *pdata, ...@@ -340,7 +340,7 @@ static int spi_gpio_request(struct spi_gpio_platform_data *pdata,
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
static struct of_device_id spi_gpio_dt_ids[] = { static const struct of_device_id spi_gpio_dt_ids[] = {
{ .compatible = "spi-gpio" }, { .compatible = "spi-gpio" },
{} {}
}; };
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/errno.h> #include <linux/errno.h>
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/clk.h> #include <linux/clk.h>
......
...@@ -1111,10 +1111,8 @@ static int pl022_dma_probe(struct pl022 *pl022) ...@@ -1111,10 +1111,8 @@ static int pl022_dma_probe(struct pl022 *pl022)
} }
pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL); pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!pl022->dummypage) { if (!pl022->dummypage)
dev_dbg(&pl022->adev->dev, "no DMA dummypage!\n");
goto err_no_dummypage; goto err_no_dummypage;
}
dev_info(&pl022->adev->dev, "setup for DMA on RX %s, TX %s\n", dev_info(&pl022->adev->dev, "setup for DMA on RX %s, TX %s\n",
dma_chan_name(pl022->dma_rx_channel), dma_chan_name(pl022->dma_rx_channel),
...@@ -1809,11 +1807,8 @@ static int pl022_setup(struct spi_device *spi) ...@@ -1809,11 +1807,8 @@ static int pl022_setup(struct spi_device *spi)
if (chip == NULL) { if (chip == NULL) {
chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
if (!chip) { if (!chip)
dev_err(&spi->dev,
"cannot allocate controller state\n");
return -ENOMEM; return -ENOMEM;
}
dev_dbg(&spi->dev, dev_dbg(&spi->dev,
"allocated memory for controller's runtime state\n"); "allocated memory for controller's runtime state\n");
} }
...@@ -2050,10 +2045,8 @@ pl022_platform_data_dt_get(struct device *dev) ...@@ -2050,10 +2045,8 @@ pl022_platform_data_dt_get(struct device *dev)
} }
pd = devm_kzalloc(dev, sizeof(struct pl022_ssp_controller), GFP_KERNEL); pd = devm_kzalloc(dev, sizeof(struct pl022_ssp_controller), GFP_KERNEL);
if (!pd) { if (!pd)
dev_err(dev, "cannot allocate platform data memory\n");
return NULL; return NULL;
}
pd->bus_id = -1; pd->bus_id = -1;
pd->enable_dma = 1; pd->enable_dma = 1;
......
...@@ -8,7 +8,43 @@ ...@@ -8,7 +8,43 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/spi/pxa2xx_spi.h> #include <linux/spi/pxa2xx_spi.h>
static int ce4100_spi_probe(struct pci_dev *dev, enum {
PORT_CE4100,
PORT_BYT,
};
struct pxa_spi_info {
enum pxa_ssp_type type;
int port_id;
int num_chipselect;
int tx_slave_id;
int tx_chan_id;
int rx_slave_id;
int rx_chan_id;
};
static struct pxa_spi_info spi_info_configs[] = {
[PORT_CE4100] = {
.type = PXA25x_SSP,
.port_id = -1,
.num_chipselect = -1,
.tx_slave_id = -1,
.tx_chan_id = -1,
.rx_slave_id = -1,
.rx_chan_id = -1,
},
[PORT_BYT] = {
.type = LPSS_SSP,
.port_id = 0,
.num_chipselect = 1,
.tx_slave_id = 0,
.tx_chan_id = 0,
.rx_slave_id = 1,
.rx_chan_id = 1,
},
};
static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
struct platform_device_info pi; struct platform_device_info pi;
...@@ -16,6 +52,7 @@ static int ce4100_spi_probe(struct pci_dev *dev, ...@@ -16,6 +52,7 @@ static int ce4100_spi_probe(struct pci_dev *dev,
struct platform_device *pdev; struct platform_device *pdev;
struct pxa2xx_spi_master spi_pdata; struct pxa2xx_spi_master spi_pdata;
struct ssp_device *ssp; struct ssp_device *ssp;
struct pxa_spi_info *c;
ret = pcim_enable_device(dev); ret = pcim_enable_device(dev);
if (ret) if (ret)
...@@ -25,8 +62,16 @@ static int ce4100_spi_probe(struct pci_dev *dev, ...@@ -25,8 +62,16 @@ static int ce4100_spi_probe(struct pci_dev *dev,
if (ret) if (ret)
return ret; return ret;
c = &spi_info_configs[ent->driver_data];
memset(&spi_pdata, 0, sizeof(spi_pdata)); memset(&spi_pdata, 0, sizeof(spi_pdata));
spi_pdata.num_chipselect = dev->devfn; spi_pdata.num_chipselect = (c->num_chipselect > 0) ?
c->num_chipselect : dev->devfn;
spi_pdata.tx_slave_id = c->tx_slave_id;
spi_pdata.tx_chan_id = c->tx_chan_id;
spi_pdata.rx_slave_id = c->rx_slave_id;
spi_pdata.rx_chan_id = c->rx_chan_id;
spi_pdata.enable_dma = c->rx_slave_id >= 0 && c->tx_slave_id >= 0;
ssp = &spi_pdata.ssp; ssp = &spi_pdata.ssp;
ssp->phys_base = pci_resource_start(dev, 0); ssp->phys_base = pci_resource_start(dev, 0);
...@@ -36,8 +81,8 @@ static int ce4100_spi_probe(struct pci_dev *dev, ...@@ -36,8 +81,8 @@ static int ce4100_spi_probe(struct pci_dev *dev,
return -EIO; return -EIO;
} }
ssp->irq = dev->irq; ssp->irq = dev->irq;
ssp->port_id = dev->devfn; ssp->port_id = (c->port_id >= 0) ? c->port_id : dev->devfn;
ssp->type = PXA25x_SSP; ssp->type = c->type;
memset(&pi, 0, sizeof(pi)); memset(&pi, 0, sizeof(pi));
pi.parent = &dev->dev; pi.parent = &dev->dev;
...@@ -55,28 +100,29 @@ static int ce4100_spi_probe(struct pci_dev *dev, ...@@ -55,28 +100,29 @@ static int ce4100_spi_probe(struct pci_dev *dev,
return 0; return 0;
} }
static void ce4100_spi_remove(struct pci_dev *dev) static void pxa2xx_spi_pci_remove(struct pci_dev *dev)
{ {
struct platform_device *pdev = pci_get_drvdata(dev); struct platform_device *pdev = pci_get_drvdata(dev);
platform_device_unregister(pdev); platform_device_unregister(pdev);
} }
static const struct pci_device_id ce4100_spi_devices[] = { static const struct pci_device_id pxa2xx_spi_pci_devices[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) }, { PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 },
{ PCI_VDEVICE(INTEL, 0x0f0e), PORT_BYT },
{ }, { },
}; };
MODULE_DEVICE_TABLE(pci, ce4100_spi_devices); MODULE_DEVICE_TABLE(pci, pxa2xx_spi_pci_devices);
static struct pci_driver ce4100_spi_driver = { static struct pci_driver pxa2xx_spi_pci_driver = {
.name = "ce4100_spi", .name = "pxa2xx_spi_pci",
.id_table = ce4100_spi_devices, .id_table = pxa2xx_spi_pci_devices,
.probe = ce4100_spi_probe, .probe = pxa2xx_spi_pci_probe,
.remove = ce4100_spi_remove, .remove = pxa2xx_spi_pci_remove,
}; };
module_pci_driver(ce4100_spi_driver); module_pci_driver(pxa2xx_spi_pci_driver);
MODULE_DESCRIPTION("CE4100 PCI-SPI glue code for PXA's driver"); MODULE_DESCRIPTION("CE4100/LPSS PCI-SPI glue code for PXA's driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>"); MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#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>
#include <linux/workqueue.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -886,11 +885,8 @@ static int setup(struct spi_device *spi) ...@@ -886,11 +885,8 @@ static int setup(struct spi_device *spi)
chip = spi_get_ctldata(spi); chip = spi_get_ctldata(spi);
if (!chip) { if (!chip) {
chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
if (!chip) { if (!chip)
dev_err(&spi->dev,
"failed setup: can't allocate chip data\n");
return -ENOMEM; return -ENOMEM;
}
if (drv_data->ssp_type == CE4100_SSP) { if (drv_data->ssp_type == CE4100_SSP) {
if (spi->chip_select > 4) { if (spi->chip_select > 4) {
...@@ -1037,11 +1033,8 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) ...@@ -1037,11 +1033,8 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
return NULL; return NULL;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) { if (!pdata)
dev_err(&pdev->dev,
"failed to allocate memory for platform data\n");
return NULL; return NULL;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) if (!res)
...@@ -1202,6 +1195,11 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1202,6 +1195,11 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
tasklet_init(&drv_data->pump_transfers, pump_transfers, tasklet_init(&drv_data->pump_transfers, pump_transfers,
(unsigned long)drv_data); (unsigned long)drv_data);
pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
/* Register with the SPI framework */ /* Register with the SPI framework */
platform_set_drvdata(pdev, drv_data); platform_set_drvdata(pdev, drv_data);
status = devm_spi_register_master(&pdev->dev, master); status = devm_spi_register_master(&pdev->dev, master);
...@@ -1210,11 +1208,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1210,11 +1208,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
goto out_error_clock_enabled; goto out_error_clock_enabled;
} }
pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
return status; return status;
out_error_clock_enabled: out_error_clock_enabled:
......
...@@ -287,7 +287,7 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id) ...@@ -287,7 +287,7 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
writel_relaxed(opflags, controller->base + QUP_OPERATIONAL); writel_relaxed(opflags, controller->base + QUP_OPERATIONAL);
if (!xfer) { if (!xfer) {
dev_err_ratelimited(controller->dev, "unexpected irq %x08 %x08 %x08\n", dev_err_ratelimited(controller->dev, "unexpected irq %08x %08x %08x\n",
qup_err, spi_err, opflags); qup_err, spi_err, opflags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -366,7 +366,7 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -366,7 +366,7 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
n_words = xfer->len / w_size; n_words = xfer->len / w_size;
controller->w_size = w_size; controller->w_size = w_size;
if (n_words <= controller->in_fifo_sz) { if (n_words <= (controller->in_fifo_sz / sizeof(u32))) {
mode = QUP_IO_M_MODE_FIFO; mode = QUP_IO_M_MODE_FIFO;
writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT); writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT);
writel_relaxed(n_words, controller->base + QUP_MX_WRITE_CNT); writel_relaxed(n_words, controller->base + QUP_MX_WRITE_CNT);
...@@ -749,7 +749,7 @@ static int spi_qup_remove(struct platform_device *pdev) ...@@ -749,7 +749,7 @@ static int spi_qup_remove(struct platform_device *pdev)
return 0; return 0;
} }
static struct of_device_id spi_qup_dt_match[] = { static const struct of_device_id spi_qup_dt_match[] = {
{ .compatible = "qcom,spi-qup-v2.1.1", }, { .compatible = "qcom,spi-qup-v2.1.1", },
{ .compatible = "qcom,spi-qup-v2.2.1", }, { .compatible = "qcom,spi-qup-v2.2.1", },
{ } { }
......
...@@ -183,8 +183,6 @@ ...@@ -183,8 +183,6 @@
#define SPBFCR_TXTRG_MASK 0x30 /* Transmit Buffer Data Triggering Number */ #define SPBFCR_TXTRG_MASK 0x30 /* Transmit Buffer Data Triggering Number */
#define SPBFCR_RXTRG_MASK 0x07 /* Receive Buffer Data Triggering Number */ #define SPBFCR_RXTRG_MASK 0x07 /* Receive Buffer Data Triggering Number */
#define DUMMY_DATA 0x00
struct rspi_data { struct rspi_data {
void __iomem *addr; void __iomem *addr;
u32 max_speed_hz; u32 max_speed_hz;
...@@ -197,11 +195,6 @@ struct rspi_data { ...@@ -197,11 +195,6 @@ struct rspi_data {
int rx_irq, tx_irq; int rx_irq, tx_irq;
const struct spi_ops *ops; const struct spi_ops *ops;
/* for dmaengine */
struct dma_chan *chan_tx;
struct dma_chan *chan_rx;
unsigned dma_width_16bit:1;
unsigned dma_callbacked:1; unsigned dma_callbacked:1;
unsigned byte_access:1; unsigned byte_access:1;
}; };
...@@ -253,6 +246,8 @@ struct spi_ops { ...@@ -253,6 +246,8 @@ struct spi_ops {
int (*transfer_one)(struct spi_master *master, struct spi_device *spi, int (*transfer_one)(struct spi_master *master, struct spi_device *spi,
struct spi_transfer *xfer); struct spi_transfer *xfer);
u16 mode_bits; u16 mode_bits;
u16 flags;
u16 fifo_size;
}; };
/* /*
...@@ -266,7 +261,8 @@ static int rspi_set_config_register(struct rspi_data *rspi, int access_size) ...@@ -266,7 +261,8 @@ static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR); rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
/* Sets transfer bit rate */ /* Sets transfer bit rate */
spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1; spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk),
2 * rspi->max_speed_hz) - 1;
rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
/* Disable dummy transmission, set 16-bit word access, 1 frame */ /* Disable dummy transmission, set 16-bit word access, 1 frame */
...@@ -302,7 +298,8 @@ static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size) ...@@ -302,7 +298,8 @@ static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size)
rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR); rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
/* Sets transfer bit rate */ /* Sets transfer bit rate */
spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1; spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk),
2 * rspi->max_speed_hz) - 1;
rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
/* Disable dummy transmission, set byte access */ /* Disable dummy transmission, set byte access */
...@@ -335,7 +332,7 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size) ...@@ -335,7 +332,7 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR); rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
/* Sets transfer bit rate */ /* Sets transfer bit rate */
spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz); spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), 2 * rspi->max_speed_hz);
rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
/* Disable dummy transmission, set byte access */ /* Disable dummy transmission, set byte access */
...@@ -403,11 +400,22 @@ static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask, ...@@ -403,11 +400,22 @@ static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,
return 0; return 0;
} }
static inline int rspi_wait_for_tx_empty(struct rspi_data *rspi)
{
return rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
}
static inline int rspi_wait_for_rx_full(struct rspi_data *rspi)
{
return rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE);
}
static int rspi_data_out(struct rspi_data *rspi, u8 data) static int rspi_data_out(struct rspi_data *rspi, u8 data)
{ {
if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) { int error = rspi_wait_for_tx_empty(rspi);
if (error < 0) {
dev_err(&rspi->master->dev, "transmit timeout\n"); dev_err(&rspi->master->dev, "transmit timeout\n");
return -ETIMEDOUT; return error;
} }
rspi_write_data(rspi, data); rspi_write_data(rspi, data);
return 0; return 0;
...@@ -415,25 +423,36 @@ static int rspi_data_out(struct rspi_data *rspi, u8 data) ...@@ -415,25 +423,36 @@ static int rspi_data_out(struct rspi_data *rspi, u8 data)
static int rspi_data_in(struct rspi_data *rspi) static int rspi_data_in(struct rspi_data *rspi)
{ {
int error;
u8 data; u8 data;
if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) { error = rspi_wait_for_rx_full(rspi);
if (error < 0) {
dev_err(&rspi->master->dev, "receive timeout\n"); dev_err(&rspi->master->dev, "receive timeout\n");
return -ETIMEDOUT; return error;
} }
data = rspi_read_data(rspi); data = rspi_read_data(rspi);
return data; return data;
} }
static int rspi_data_out_in(struct rspi_data *rspi, u8 data) static int rspi_pio_transfer(struct rspi_data *rspi, const u8 *tx, u8 *rx,
unsigned int n)
{ {
int ret; while (n-- > 0) {
if (tx) {
ret = rspi_data_out(rspi, data); int ret = rspi_data_out(rspi, *tx++);
if (ret < 0)
return ret;
}
if (rx) {
int ret = rspi_data_in(rspi);
if (ret < 0) if (ret < 0)
return ret; return ret;
*rx++ = ret;
}
}
return rspi_data_in(rspi); return 0;
} }
static void rspi_dma_complete(void *arg) static void rspi_dma_complete(void *arg)
...@@ -444,97 +463,67 @@ static void rspi_dma_complete(void *arg) ...@@ -444,97 +463,67 @@ static void rspi_dma_complete(void *arg)
wake_up_interruptible(&rspi->wait); wake_up_interruptible(&rspi->wait);
} }
static int rspi_dma_map_sg(struct scatterlist *sg, const void *buf, static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
unsigned len, struct dma_chan *chan, struct sg_table *rx)
enum dma_transfer_direction dir)
{
sg_init_table(sg, 1);
sg_set_buf(sg, buf, len);
sg_dma_len(sg) = len;
return dma_map_sg(chan->device->dev, sg, 1, dir);
}
static void rspi_dma_unmap_sg(struct scatterlist *sg, struct dma_chan *chan,
enum dma_transfer_direction dir)
{
dma_unmap_sg(chan->device->dev, sg, 1, dir);
}
static void rspi_memory_to_8bit(void *buf, const void *data, unsigned len)
{
u16 *dst = buf;
const u8 *src = data;
while (len) {
*dst++ = (u16)(*src++);
len--;
}
}
static void rspi_memory_from_8bit(void *buf, const void *data, unsigned len)
{ {
u8 *dst = buf; struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL;
const u16 *src = data; u8 irq_mask = 0;
unsigned int other_irq = 0;
while (len) { dma_cookie_t cookie;
*dst++ = (u8)*src++; int ret;
len--;
}
}
static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t) if (tx) {
{ desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx,
struct scatterlist sg; tx->sgl, tx->nents, DMA_TO_DEVICE,
const void *buf = NULL; DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
struct dma_async_tx_descriptor *desc; if (!desc_tx)
unsigned int len; return -EIO;
int ret = 0;
if (rspi->dma_width_16bit) {
void *tmp;
/*
* If DMAC bus width is 16-bit, the driver allocates a dummy
* buffer. And, the driver converts original data into the
* DMAC data as the following format:
* original data: 1st byte, 2nd byte ...
* DMAC data: 1st byte, dummy, 2nd byte, dummy ...
*/
len = t->len * 2;
tmp = kmalloc(len, GFP_KERNEL);
if (!tmp)
return -ENOMEM;
rspi_memory_to_8bit(tmp, t->tx_buf, t->len);
buf = tmp;
} else {
len = t->len;
buf = t->tx_buf;
}
if (!rspi_dma_map_sg(&sg, buf, len, rspi->chan_tx, DMA_TO_DEVICE)) { irq_mask |= SPCR_SPTIE;
ret = -EFAULT;
goto end_nomap;
} }
desc = dmaengine_prep_slave_sg(rspi->chan_tx, &sg, 1, DMA_TO_DEVICE, if (rx) {
desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx,
rx->sgl, rx->nents, DMA_FROM_DEVICE,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) { if (!desc_rx)
ret = -EIO; return -EIO;
goto end;
irq_mask |= SPCR_SPRIE;
} }
/* /*
* DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be * DMAC needs SPxIE, but if SPxIE is set, the IRQ routine will be
* called. So, this driver disables the IRQ while DMA transfer. * called. So, this driver disables the IRQ while DMA transfer.
*/ */
disable_irq(rspi->tx_irq); if (tx)
disable_irq(other_irq = rspi->tx_irq);
if (rx && rspi->rx_irq != other_irq)
disable_irq(rspi->rx_irq);
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD, RSPI_SPCR); rspi_enable_irq(rspi, irq_mask);
rspi_enable_irq(rspi, SPCR_SPTIE);
rspi->dma_callbacked = 0; rspi->dma_callbacked = 0;
desc->callback = rspi_dma_complete; if (rx) {
desc->callback_param = rspi; desc_rx->callback = rspi_dma_complete;
dmaengine_submit(desc); desc_rx->callback_param = rspi;
dma_async_issue_pending(rspi->chan_tx); cookie = dmaengine_submit(desc_rx);
if (dma_submit_error(cookie))
return cookie;
dma_async_issue_pending(rspi->master->dma_rx);
}
if (tx) {
if (rx) {
/* No callback */
desc_tx->callback = NULL;
} else {
desc_tx->callback = rspi_dma_complete;
desc_tx->callback_param = rspi;
}
cookie = dmaengine_submit(desc_tx);
if (dma_submit_error(cookie))
return cookie;
dma_async_issue_pending(rspi->master->dma_tx);
}
ret = wait_event_interruptible_timeout(rspi->wait, ret = wait_event_interruptible_timeout(rspi->wait,
rspi->dma_callbacked, HZ); rspi->dma_callbacked, HZ);
...@@ -542,15 +531,13 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t) ...@@ -542,15 +531,13 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
ret = 0; ret = 0;
else if (!ret) else if (!ret)
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
rspi_disable_irq(rspi, SPCR_SPTIE);
enable_irq(rspi->tx_irq); rspi_disable_irq(rspi, irq_mask);
end: if (tx)
rspi_dma_unmap_sg(&sg, rspi->chan_tx, DMA_TO_DEVICE); enable_irq(rspi->tx_irq);
end_nomap: if (rx && rspi->rx_irq != other_irq)
if (rspi->dma_width_16bit) enable_irq(rspi->rx_irq);
kfree(buf);
return ret; return ret;
} }
...@@ -585,157 +572,37 @@ static void qspi_receive_init(const struct rspi_data *rspi) ...@@ -585,157 +572,37 @@ static void qspi_receive_init(const struct rspi_data *rspi)
rspi_write8(rspi, 0, QSPI_SPBFCR); rspi_write8(rspi, 0, QSPI_SPBFCR);
} }
static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t) static bool __rspi_can_dma(const struct rspi_data *rspi,
const struct spi_transfer *xfer)
{ {
struct scatterlist sg, sg_dummy; return xfer->len > rspi->ops->fifo_size;
void *dummy = NULL, *rx_buf = NULL;
struct dma_async_tx_descriptor *desc, *desc_dummy;
unsigned int len;
int ret = 0;
if (rspi->dma_width_16bit) {
/*
* If DMAC bus width is 16-bit, the driver allocates a dummy
* buffer. And, finally the driver converts the DMAC data into
* actual data as the following format:
* DMAC data: 1st byte, dummy, 2nd byte, dummy ...
* actual data: 1st byte, 2nd byte ...
*/
len = t->len * 2;
rx_buf = kmalloc(len, GFP_KERNEL);
if (!rx_buf)
return -ENOMEM;
} else {
len = t->len;
rx_buf = t->rx_buf;
}
/* prepare dummy transfer to generate SPI clocks */
dummy = kzalloc(len, GFP_KERNEL);
if (!dummy) {
ret = -ENOMEM;
goto end_nomap;
}
if (!rspi_dma_map_sg(&sg_dummy, dummy, len, rspi->chan_tx,
DMA_TO_DEVICE)) {
ret = -EFAULT;
goto end_nomap;
}
desc_dummy = dmaengine_prep_slave_sg(rspi->chan_tx, &sg_dummy, 1,
DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_dummy) {
ret = -EIO;
goto end_dummy_mapped;
}
/* prepare receive transfer */
if (!rspi_dma_map_sg(&sg, rx_buf, len, rspi->chan_rx,
DMA_FROM_DEVICE)) {
ret = -EFAULT;
goto end_dummy_mapped;
}
desc = dmaengine_prep_slave_sg(rspi->chan_rx, &sg, 1, DMA_FROM_DEVICE,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) {
ret = -EIO;
goto end;
}
rspi_receive_init(rspi);
/*
* DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be
* called. So, this driver disables the IRQ while DMA transfer.
*/
disable_irq(rspi->tx_irq);
if (rspi->rx_irq != rspi->tx_irq)
disable_irq(rspi->rx_irq);
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD, RSPI_SPCR);
rspi_enable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE);
rspi->dma_callbacked = 0;
desc->callback = rspi_dma_complete;
desc->callback_param = rspi;
dmaengine_submit(desc);
dma_async_issue_pending(rspi->chan_rx);
desc_dummy->callback = NULL; /* No callback */
dmaengine_submit(desc_dummy);
dma_async_issue_pending(rspi->chan_tx);
ret = wait_event_interruptible_timeout(rspi->wait,
rspi->dma_callbacked, HZ);
if (ret > 0 && rspi->dma_callbacked)
ret = 0;
else if (!ret)
ret = -ETIMEDOUT;
rspi_disable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE);
enable_irq(rspi->tx_irq);
if (rspi->rx_irq != rspi->tx_irq)
enable_irq(rspi->rx_irq);
end:
rspi_dma_unmap_sg(&sg, rspi->chan_rx, DMA_FROM_DEVICE);
end_dummy_mapped:
rspi_dma_unmap_sg(&sg_dummy, rspi->chan_tx, DMA_TO_DEVICE);
end_nomap:
if (rspi->dma_width_16bit) {
if (!ret)
rspi_memory_from_8bit(t->rx_buf, rx_buf, t->len);
kfree(rx_buf);
}
kfree(dummy);
return ret;
} }
static int rspi_is_dma(const struct rspi_data *rspi, struct spi_transfer *t) static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi,
struct spi_transfer *xfer)
{ {
if (t->tx_buf && rspi->chan_tx) struct rspi_data *rspi = spi_master_get_devdata(master);
return 1;
/* If the module receives data by DMAC, it also needs TX DMAC */
if (t->rx_buf && rspi->chan_tx && rspi->chan_rx)
return 1;
return 0; return __rspi_can_dma(rspi, xfer);
} }
static int rspi_transfer_out_in(struct rspi_data *rspi, static int rspi_common_transfer(struct rspi_data *rspi,
struct spi_transfer *xfer) struct spi_transfer *xfer)
{ {
int remain = xfer->len, ret; int ret;
const u8 *tx_buf = xfer->tx_buf;
u8 *rx_buf = xfer->rx_buf;
u8 spcr, data;
rspi_receive_init(rspi);
spcr = rspi_read8(rspi, RSPI_SPCR); if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
if (rx_buf) /* rx_buf can be NULL on RSPI on SH in TX-only Mode */
spcr &= ~SPCR_TXMD; return rspi_dma_transfer(rspi, &xfer->tx_sg,
else xfer->rx_buf ? &xfer->rx_sg : NULL);
spcr |= SPCR_TXMD; }
rspi_write8(rspi, spcr, RSPI_SPCR);
while (remain > 0) { ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
data = tx_buf ? *tx_buf++ : DUMMY_DATA;
ret = rspi_data_out(rspi, data);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (rx_buf) {
ret = rspi_data_in(rspi);
if (ret < 0)
return ret;
*rx_buf++ = ret;
}
remain--;
}
/* Wait for the last transmission */ /* Wait for the last transmission */
rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE); rspi_wait_for_tx_empty(rspi);
return 0; return 0;
} }
...@@ -744,46 +611,18 @@ static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi, ...@@ -744,46 +611,18 @@ static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,
struct spi_transfer *xfer) struct spi_transfer *xfer)
{ {
struct rspi_data *rspi = spi_master_get_devdata(master); struct rspi_data *rspi = spi_master_get_devdata(master);
int ret; u8 spcr;
if (!rspi_is_dma(rspi, xfer))
return rspi_transfer_out_in(rspi, xfer);
if (xfer->tx_buf) {
ret = rspi_send_dma(rspi, xfer);
if (ret < 0)
return ret;
}
if (xfer->rx_buf)
return rspi_receive_dma(rspi, xfer);
return 0;
}
static int rspi_rz_transfer_out_in(struct rspi_data *rspi,
struct spi_transfer *xfer)
{
int remain = xfer->len, ret;
const u8 *tx_buf = xfer->tx_buf;
u8 *rx_buf = xfer->rx_buf;
u8 data;
rspi_rz_receive_init(rspi);
while (remain > 0) { spcr = rspi_read8(rspi, RSPI_SPCR);
data = tx_buf ? *tx_buf++ : DUMMY_DATA; if (xfer->rx_buf) {
ret = rspi_data_out_in(rspi, data); rspi_receive_init(rspi);
if (ret < 0) spcr &= ~SPCR_TXMD;
return ret; } else {
if (rx_buf) spcr |= SPCR_TXMD;
*rx_buf++ = ret;
remain--;
} }
rspi_write8(rspi, spcr, RSPI_SPCR);
/* Wait for the last transmission */ return rspi_common_transfer(rspi, xfer);
rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
return 0;
} }
static int rspi_rz_transfer_one(struct spi_master *master, static int rspi_rz_transfer_one(struct spi_master *master,
...@@ -791,68 +630,44 @@ static int rspi_rz_transfer_one(struct spi_master *master, ...@@ -791,68 +630,44 @@ static int rspi_rz_transfer_one(struct spi_master *master,
struct spi_transfer *xfer) struct spi_transfer *xfer)
{ {
struct rspi_data *rspi = spi_master_get_devdata(master); struct rspi_data *rspi = spi_master_get_devdata(master);
int ret;
rspi_rz_receive_init(rspi);
return rspi_rz_transfer_out_in(rspi, xfer); return rspi_common_transfer(rspi, xfer);
} }
static int qspi_transfer_out_in(struct rspi_data *rspi, static int qspi_transfer_out_in(struct rspi_data *rspi,
struct spi_transfer *xfer) struct spi_transfer *xfer)
{ {
int remain = xfer->len, ret;
const u8 *tx_buf = xfer->tx_buf;
u8 *rx_buf = xfer->rx_buf;
u8 data;
qspi_receive_init(rspi); qspi_receive_init(rspi);
while (remain > 0) { return rspi_common_transfer(rspi, xfer);
data = tx_buf ? *tx_buf++ : DUMMY_DATA;
ret = rspi_data_out_in(rspi, data);
if (ret < 0)
return ret;
if (rx_buf)
*rx_buf++ = ret;
remain--;
}
/* Wait for the last transmission */
rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
return 0;
} }
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 *buf = xfer->tx_buf;
unsigned int i;
int ret; int ret;
for (i = 0; i < xfer->len; i++) { if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer))
ret = rspi_data_out(rspi, *buf++); return rspi_dma_transfer(rspi, &xfer->tx_sg, NULL);
ret = rspi_pio_transfer(rspi, xfer->tx_buf, NULL, xfer->len);
if (ret < 0) if (ret < 0)
return ret; return ret;
}
/* Wait for the last transmission */ /* Wait for the last transmission */
rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE); rspi_wait_for_tx_empty(rspi);
return 0; return 0;
} }
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 *buf = xfer->rx_buf; if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer))
unsigned int i; return rspi_dma_transfer(rspi, NULL, &xfer->rx_sg);
int ret;
for (i = 0; i < xfer->len; i++) { return rspi_pio_transfer(rspi, NULL, xfer->rx_buf, xfer->len);
ret = rspi_data_in(rspi);
if (ret < 0)
return ret;
*buf++ = ret;
}
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,
...@@ -862,10 +677,10 @@ static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi, ...@@ -862,10 +677,10 @@ static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi,
if (spi->mode & SPI_LOOP) { if (spi->mode & SPI_LOOP) {
return qspi_transfer_out_in(rspi, xfer); return qspi_transfer_out_in(rspi, xfer);
} else if (xfer->tx_buf && xfer->tx_nbits > SPI_NBITS_SINGLE) { } else if (xfer->tx_nbits > SPI_NBITS_SINGLE) {
/* Quad or Dual SPI Write */ /* Quad or Dual SPI Write */
return qspi_transfer_out(rspi, xfer); return qspi_transfer_out(rspi, xfer);
} else if (xfer->rx_buf && xfer->rx_nbits > SPI_NBITS_SINGLE) { } else if (xfer->rx_nbits > SPI_NBITS_SINGLE) {
/* Quad or Dual SPI Read */ /* Quad or Dual SPI Read */
return qspi_transfer_in(rspi, xfer); return qspi_transfer_in(rspi, xfer);
} else { } else {
...@@ -1046,65 +861,78 @@ static irqreturn_t rspi_irq_tx(int irq, void *_sr) ...@@ -1046,65 +861,78 @@ static irqreturn_t rspi_irq_tx(int irq, void *_sr)
return 0; return 0;
} }
static int rspi_request_dma(struct rspi_data *rspi, static struct dma_chan *rspi_request_dma_chan(struct device *dev,
struct platform_device *pdev) enum dma_transfer_direction dir,
unsigned int id,
dma_addr_t port_addr)
{ {
const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dma_cap_mask_t mask; dma_cap_mask_t mask;
struct dma_chan *chan;
struct dma_slave_config cfg; struct dma_slave_config cfg;
int ret; int ret;
if (!res || !rspi_pd)
return 0; /* The driver assumes no error. */
rspi->dma_width_16bit = rspi_pd->dma_width_16bit;
/* If the module receives data by DMAC, it also needs TX DMAC */
if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) {
dma_cap_zero(mask); dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_SLAVE, mask);
rspi->chan_rx = dma_request_channel(mask, shdma_chan_filter,
(void *)rspi_pd->dma_rx_id); chan = dma_request_channel(mask, shdma_chan_filter,
if (rspi->chan_rx) { (void *)(unsigned long)id);
cfg.slave_id = rspi_pd->dma_rx_id; if (!chan) {
cfg.direction = DMA_DEV_TO_MEM; dev_warn(dev, "dma_request_channel failed\n");
cfg.dst_addr = 0; return NULL;
cfg.src_addr = res->start + RSPI_SPDR;
ret = dmaengine_slave_config(rspi->chan_rx, &cfg);
if (!ret)
dev_info(&pdev->dev, "Use DMA when rx.\n");
else
return ret;
}
} }
if (rspi_pd->dma_tx_id) {
dma_cap_zero(mask); memset(&cfg, 0, sizeof(cfg));
dma_cap_set(DMA_SLAVE, mask); cfg.slave_id = id;
rspi->chan_tx = dma_request_channel(mask, shdma_chan_filter, cfg.direction = dir;
(void *)rspi_pd->dma_tx_id); if (dir == DMA_MEM_TO_DEV)
if (rspi->chan_tx) { cfg.dst_addr = port_addr;
cfg.slave_id = rspi_pd->dma_tx_id;
cfg.direction = DMA_MEM_TO_DEV;
cfg.dst_addr = res->start + RSPI_SPDR;
cfg.src_addr = 0;
ret = dmaengine_slave_config(rspi->chan_tx, &cfg);
if (!ret)
dev_info(&pdev->dev, "Use DMA when tx\n");
else else
return ret; cfg.src_addr = port_addr;
ret = dmaengine_slave_config(chan, &cfg);
if (ret) {
dev_warn(dev, "dmaengine_slave_config failed %d\n", ret);
dma_release_channel(chan);
return NULL;
} }
return chan;
}
static int rspi_request_dma(struct device *dev, struct spi_master *master,
const struct resource *res)
{
const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev);
if (!rspi_pd || !rspi_pd->dma_rx_id || !rspi_pd->dma_tx_id)
return 0; /* The driver assumes no error. */
master->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM,
rspi_pd->dma_rx_id,
res->start + RSPI_SPDR);
if (!master->dma_rx)
return -ENODEV;
master->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV,
rspi_pd->dma_tx_id,
res->start + RSPI_SPDR);
if (!master->dma_tx) {
dma_release_channel(master->dma_rx);
master->dma_rx = NULL;
return -ENODEV;
} }
master->can_dma = rspi_can_dma;
dev_info(dev, "DMA available");
return 0; return 0;
} }
static void rspi_release_dma(struct rspi_data *rspi) static void rspi_release_dma(struct rspi_data *rspi)
{ {
if (rspi->chan_tx) if (rspi->master->dma_tx)
dma_release_channel(rspi->chan_tx); dma_release_channel(rspi->master->dma_tx);
if (rspi->chan_rx) if (rspi->master->dma_rx)
dma_release_channel(rspi->chan_rx); dma_release_channel(rspi->master->dma_rx);
} }
static int rspi_remove(struct platform_device *pdev) static int rspi_remove(struct platform_device *pdev)
...@@ -1121,12 +949,16 @@ static const struct spi_ops rspi_ops = { ...@@ -1121,12 +949,16 @@ static const struct spi_ops rspi_ops = {
.set_config_register = rspi_set_config_register, .set_config_register = rspi_set_config_register,
.transfer_one = rspi_transfer_one, .transfer_one = rspi_transfer_one,
.mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP, .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP,
.flags = SPI_MASTER_MUST_TX,
.fifo_size = 8,
}; };
static const struct spi_ops rspi_rz_ops = { static const struct spi_ops rspi_rz_ops = {
.set_config_register = rspi_rz_set_config_register, .set_config_register = rspi_rz_set_config_register,
.transfer_one = rspi_rz_transfer_one, .transfer_one = rspi_rz_transfer_one,
.mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP, .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP,
.flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX,
.fifo_size = 8, /* 8 for TX, 32 for RX */
}; };
static const struct spi_ops qspi_ops = { static const struct spi_ops qspi_ops = {
...@@ -1135,6 +967,8 @@ static const struct spi_ops qspi_ops = { ...@@ -1135,6 +967,8 @@ static const struct spi_ops qspi_ops = {
.mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP | .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP |
SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD |
SPI_RX_DUAL | SPI_RX_QUAD, SPI_RX_DUAL | SPI_RX_QUAD,
.flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX,
.fifo_size = 32,
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF
...@@ -1254,6 +1088,7 @@ static int rspi_probe(struct platform_device *pdev) ...@@ -1254,6 +1088,7 @@ static int rspi_probe(struct platform_device *pdev)
master->prepare_message = rspi_prepare_message; master->prepare_message = rspi_prepare_message;
master->unprepare_message = rspi_unprepare_message; master->unprepare_message = rspi_unprepare_message;
master->mode_bits = ops->mode_bits; master->mode_bits = ops->mode_bits;
master->flags = ops->flags;
master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
ret = platform_get_irq_byname(pdev, "rx"); ret = platform_get_irq_byname(pdev, "rx");
...@@ -1291,11 +1126,9 @@ static int rspi_probe(struct platform_device *pdev) ...@@ -1291,11 +1126,9 @@ static int rspi_probe(struct platform_device *pdev)
goto error2; goto error2;
} }
ret = rspi_request_dma(rspi, pdev); ret = rspi_request_dma(&pdev->dev, master, res);
if (ret < 0) { if (ret < 0)
dev_err(&pdev->dev, "rspi_request_dma failed.\n"); dev_warn(&pdev->dev, "DMA not available, using PIO\n");
goto error3;
}
ret = devm_spi_register_master(&pdev->dev, master); ret = devm_spi_register_master(&pdev->dev, master);
if (ret < 0) { if (ret < 0) {
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
*/ */
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -183,11 +182,11 @@ static int s3c24xx_spi_setup(struct spi_device *spi) ...@@ -183,11 +182,11 @@ static int s3c24xx_spi_setup(struct spi_device *spi)
/* allocate settings on the first call */ /* allocate settings on the first call */
if (!cs) { if (!cs) {
cs = kzalloc(sizeof(struct s3c24xx_spi_devstate), GFP_KERNEL); cs = devm_kzalloc(&spi->dev,
if (!cs) { sizeof(struct s3c24xx_spi_devstate),
dev_err(&spi->dev, "no memory for controller state\n"); GFP_KERNEL);
if (!cs)
return -ENOMEM; return -ENOMEM;
}
cs->spcon = SPCON_DEFAULT; cs->spcon = SPCON_DEFAULT;
cs->hz = -1; cs->hz = -1;
...@@ -209,11 +208,6 @@ static int s3c24xx_spi_setup(struct spi_device *spi) ...@@ -209,11 +208,6 @@ static int s3c24xx_spi_setup(struct spi_device *spi)
return 0; return 0;
} }
static void s3c24xx_spi_cleanup(struct spi_device *spi)
{
kfree(spi->controller_state);
}
static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count) static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count)
{ {
return hw->tx ? hw->tx[count] : 0; return hw->tx ? hw->tx[count] : 0;
...@@ -543,7 +537,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) ...@@ -543,7 +537,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
hw->bitbang.txrx_bufs = s3c24xx_spi_txrx; hw->bitbang.txrx_bufs = s3c24xx_spi_txrx;
hw->master->setup = s3c24xx_spi_setup; hw->master->setup = s3c24xx_spi_setup;
hw->master->cleanup = s3c24xx_spi_cleanup;
dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang); dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/clk.h> #include <linux/clk.h>
...@@ -773,7 +772,6 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( ...@@ -773,7 +772,6 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
cs = kzalloc(sizeof(*cs), GFP_KERNEL); cs = kzalloc(sizeof(*cs), GFP_KERNEL);
if (!cs) { if (!cs) {
dev_err(&spi->dev, "could not allocate memory for controller data\n");
of_node_put(data_np); of_node_put(data_np);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
...@@ -987,10 +985,8 @@ static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev) ...@@ -987,10 +985,8 @@ static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev)
u32 temp; u32 temp;
sci = devm_kzalloc(dev, sizeof(*sci), GFP_KERNEL); sci = devm_kzalloc(dev, sizeof(*sci), GFP_KERNEL);
if (!sci) { if (!sci)
dev_err(dev, "memory allocation for spi_info failed\n");
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
if (of_property_read_u32(dev->of_node, "samsung,spi-src-clk", &temp)) { if (of_property_read_u32(dev->of_node, "samsung,spi-src-clk", &temp)) {
dev_warn(dev, "spi bus clock parent not specified, using clock at index 0 as parent\n"); dev_warn(dev, "spi bus clock parent not specified, using clock at index 0 as parent\n");
......
...@@ -642,10 +642,8 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) ...@@ -642,10 +642,8 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev)
u32 num_cs = 1; u32 num_cs = 1;
info = devm_kzalloc(dev, sizeof(struct sh_msiof_spi_info), GFP_KERNEL); info = devm_kzalloc(dev, sizeof(struct sh_msiof_spi_info), GFP_KERNEL);
if (!info) { if (!info)
dev_err(dev, "failed to allocate setup data\n");
return NULL; return NULL;
}
/* Parse the MSIOF properties */ /* Parse the MSIOF properties */
of_property_read_u32(np, "num-cs", &num_cs); of_property_read_u32(np, "num-cs", &num_cs);
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/completion.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
...@@ -85,6 +86,7 @@ ...@@ -85,6 +86,7 @@
#define SIRFSOC_SPI_TX_DONE BIT(1) #define SIRFSOC_SPI_TX_DONE BIT(1)
#define SIRFSOC_SPI_RX_OFLOW BIT(2) #define SIRFSOC_SPI_RX_OFLOW BIT(2)
#define SIRFSOC_SPI_TX_UFLOW BIT(3) #define SIRFSOC_SPI_TX_UFLOW BIT(3)
#define SIRFSOC_SPI_RX_IO_DMA BIT(4)
#define SIRFSOC_SPI_RX_FIFO_FULL BIT(6) #define SIRFSOC_SPI_RX_FIFO_FULL BIT(6)
#define SIRFSOC_SPI_TXFIFO_EMPTY BIT(7) #define SIRFSOC_SPI_TXFIFO_EMPTY BIT(7)
#define SIRFSOC_SPI_RXFIFO_THD_REACH BIT(8) #define SIRFSOC_SPI_RXFIFO_THD_REACH BIT(8)
...@@ -264,41 +266,34 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id) ...@@ -264,41 +266,34 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
{ {
struct sirfsoc_spi *sspi = dev_id; struct sirfsoc_spi *sspi = dev_id;
u32 spi_stat = readl(sspi->base + SIRFSOC_SPI_INT_STATUS); u32 spi_stat = readl(sspi->base + SIRFSOC_SPI_INT_STATUS);
writel(spi_stat, sspi->base + SIRFSOC_SPI_INT_STATUS);
if (sspi->tx_by_cmd && (spi_stat & SIRFSOC_SPI_FRM_END)) { if (sspi->tx_by_cmd && (spi_stat & SIRFSOC_SPI_FRM_END)) {
complete(&sspi->tx_done); complete(&sspi->tx_done);
writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
writel(SIRFSOC_SPI_INT_MASK_ALL,
sspi->base + SIRFSOC_SPI_INT_STATUS);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/* Error Conditions */ /* Error Conditions */
if (spi_stat & SIRFSOC_SPI_RX_OFLOW || if (spi_stat & SIRFSOC_SPI_RX_OFLOW ||
spi_stat & SIRFSOC_SPI_TX_UFLOW) { spi_stat & SIRFSOC_SPI_TX_UFLOW) {
complete(&sspi->tx_done);
complete(&sspi->rx_done); complete(&sspi->rx_done);
writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
writel(SIRFSOC_SPI_INT_MASK_ALL,
sspi->base + SIRFSOC_SPI_INT_STATUS);
return IRQ_HANDLED;
} }
if (spi_stat & SIRFSOC_SPI_TXFIFO_EMPTY)
if (spi_stat & (SIRFSOC_SPI_FRM_END complete(&sspi->tx_done);
| SIRFSOC_SPI_RXFIFO_THD_REACH)) while (!(readl(sspi->base + SIRFSOC_SPI_INT_STATUS) &
while (!((readl(sspi->base + SIRFSOC_SPI_RXFIFO_STATUS) SIRFSOC_SPI_RX_IO_DMA))
& SIRFSOC_SPI_FIFO_EMPTY)) && cpu_relax();
sspi->left_rx_word)
sspi->rx_word(sspi);
if (spi_stat & (SIRFSOC_SPI_TXFIFO_EMPTY |
SIRFSOC_SPI_TXFIFO_THD_REACH))
while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS)
& SIRFSOC_SPI_FIFO_FULL)) &&
sspi->left_tx_word)
sspi->tx_word(sspi);
/* Received all words */
if ((sspi->left_rx_word == 0) && (sspi->left_tx_word == 0)) {
complete(&sspi->rx_done); complete(&sspi->rx_done);
writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
} writel(SIRFSOC_SPI_INT_MASK_ALL,
sspi->base + SIRFSOC_SPI_INT_STATUS);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -309,59 +304,51 @@ static void spi_sirfsoc_dma_fini_callback(void *data) ...@@ -309,59 +304,51 @@ static void spi_sirfsoc_dma_fini_callback(void *data)
complete(dma_complete); complete(dma_complete);
} }
static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t) static int spi_sirfsoc_cmd_transfer(struct spi_device *spi,
struct spi_transfer *t)
{ {
struct sirfsoc_spi *sspi; struct sirfsoc_spi *sspi;
int timeout = t->len * 10; int timeout = t->len * 10;
sspi = spi_master_get_devdata(spi->master);
sspi->tx = t->tx_buf ? t->tx_buf : sspi->dummypage;
sspi->rx = t->rx_buf ? t->rx_buf : sspi->dummypage;
sspi->left_tx_word = sspi->left_rx_word = t->len / sspi->word_width;
reinit_completion(&sspi->rx_done);
reinit_completion(&sspi->tx_done);
writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS);
/*
* fill tx_buf into command register and wait for its completion
*/
if (sspi->tx_by_cmd) {
u32 cmd; u32 cmd;
memcpy(&cmd, sspi->tx, t->len);
sspi = spi_master_get_devdata(spi->master);
memcpy(&cmd, sspi->tx, t->len);
if (sspi->word_width == 1 && !(spi->mode & SPI_LSB_FIRST)) if (sspi->word_width == 1 && !(spi->mode & SPI_LSB_FIRST))
cmd = cpu_to_be32(cmd) >> cmd = cpu_to_be32(cmd) >>
((SIRFSOC_MAX_CMD_BYTES - t->len) * 8); ((SIRFSOC_MAX_CMD_BYTES - t->len) * 8);
if (sspi->word_width == 2 && t->len == 4 && if (sspi->word_width == 2 && t->len == 4 &&
(!(spi->mode & SPI_LSB_FIRST))) (!(spi->mode & SPI_LSB_FIRST)))
cmd = ((cmd & 0xffff) << 16) | (cmd >> 16); cmd = ((cmd & 0xffff) << 16) | (cmd >> 16);
writel(cmd, sspi->base + SIRFSOC_SPI_CMD); writel(cmd, sspi->base + SIRFSOC_SPI_CMD);
writel(SIRFSOC_SPI_FRM_END_INT_EN, writel(SIRFSOC_SPI_FRM_END_INT_EN,
sspi->base + SIRFSOC_SPI_INT_EN); sspi->base + SIRFSOC_SPI_INT_EN);
writel(SIRFSOC_SPI_CMD_TX_EN, writel(SIRFSOC_SPI_CMD_TX_EN,
sspi->base + SIRFSOC_SPI_TX_RX_EN); sspi->base + SIRFSOC_SPI_TX_RX_EN);
if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) { if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) {
dev_err(&spi->dev, "transfer timeout\n"); dev_err(&spi->dev, "cmd transfer timeout\n");
return 0; return 0;
} }
return t->len; return t->len;
} }
if (sspi->left_tx_word == 1) { static void spi_sirfsoc_dma_transfer(struct spi_device *spi,
writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | struct spi_transfer *t)
SIRFSOC_SPI_ENA_AUTO_CLR, {
sspi->base + SIRFSOC_SPI_CTRL); struct sirfsoc_spi *sspi;
writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN); struct dma_async_tx_descriptor *rx_desc, *tx_desc;
writel(0, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN); int timeout = t->len * 10;
} else if ((sspi->left_tx_word > 1) && (sspi->left_tx_word <
SIRFSOC_SPI_DAT_FRM_LEN_MAX)) { sspi = spi_master_get_devdata(spi->master);
writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
writel(0, sspi->base + SIRFSOC_SPI_INT_EN);
writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS);
if (sspi->left_tx_word < SIRFSOC_SPI_DAT_FRM_LEN_MAX) {
writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | writel(readl(sspi->base + SIRFSOC_SPI_CTRL) |
SIRFSOC_SPI_MUL_DAT_MODE | SIRFSOC_SPI_ENA_AUTO_CLR | SIRFSOC_SPI_MUL_DAT_MODE,
SIRFSOC_SPI_ENA_AUTO_CLR,
sspi->base + SIRFSOC_SPI_CTRL); sspi->base + SIRFSOC_SPI_CTRL);
writel(sspi->left_tx_word - 1, writel(sspi->left_tx_word - 1,
sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN); sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN);
...@@ -373,23 +360,18 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -373,23 +360,18 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)
writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN); writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN);
writel(0, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN); writel(0, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN);
} }
sspi->dst_start = dma_map_single(&spi->dev, sspi->rx, t->len,
writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP); (t->tx_buf != t->rx_buf) ?
writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP); DMA_FROM_DEVICE : DMA_BIDIRECTIONAL);
writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
if (IS_DMA_VALID(t)) {
struct dma_async_tx_descriptor *rx_desc, *tx_desc;
sspi->dst_start = dma_map_single(&spi->dev, sspi->rx, t->len, DMA_FROM_DEVICE);
rx_desc = dmaengine_prep_slave_single(sspi->rx_chan, rx_desc = dmaengine_prep_slave_single(sspi->rx_chan,
sspi->dst_start, t->len, DMA_DEV_TO_MEM, sspi->dst_start, t->len, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
rx_desc->callback = spi_sirfsoc_dma_fini_callback; rx_desc->callback = spi_sirfsoc_dma_fini_callback;
rx_desc->callback_param = &sspi->rx_done; rx_desc->callback_param = &sspi->rx_done;
sspi->src_start = dma_map_single(&spi->dev, (void *)sspi->tx, t->len, DMA_TO_DEVICE); sspi->src_start = dma_map_single(&spi->dev, (void *)sspi->tx, t->len,
(t->tx_buf != t->rx_buf) ?
DMA_TO_DEVICE : DMA_BIDIRECTIONAL);
tx_desc = dmaengine_prep_slave_single(sspi->tx_chan, tx_desc = dmaengine_prep_slave_single(sspi->tx_chan,
sspi->src_start, t->len, DMA_MEM_TO_DEV, sspi->src_start, t->len, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
...@@ -400,49 +382,100 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -400,49 +382,100 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)
dmaengine_submit(rx_desc); dmaengine_submit(rx_desc);
dma_async_issue_pending(sspi->tx_chan); dma_async_issue_pending(sspi->tx_chan);
dma_async_issue_pending(sspi->rx_chan); dma_async_issue_pending(sspi->rx_chan);
} else { writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN,
/* Send the first word to trigger the whole tx/rx process */ sspi->base + SIRFSOC_SPI_TX_RX_EN);
sspi->tx_word(sspi); if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0) {
writel(SIRFSOC_SPI_RX_OFLOW_INT_EN | SIRFSOC_SPI_TX_UFLOW_INT_EN |
SIRFSOC_SPI_RXFIFO_THD_INT_EN | SIRFSOC_SPI_TXFIFO_THD_INT_EN |
SIRFSOC_SPI_FRM_END_INT_EN | SIRFSOC_SPI_RXFIFO_FULL_INT_EN |
SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN, sspi->base + SIRFSOC_SPI_INT_EN);
}
writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN, sspi->base + SIRFSOC_SPI_TX_RX_EN);
if (!IS_DMA_VALID(t)) { /* for PIO */
if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0)
dev_err(&spi->dev, "transfer timeout\n");
} else if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0) {
dev_err(&spi->dev, "transfer timeout\n"); dev_err(&spi->dev, "transfer timeout\n");
dmaengine_terminate_all(sspi->rx_chan); dmaengine_terminate_all(sspi->rx_chan);
} else } else
sspi->left_rx_word = 0; sspi->left_rx_word = 0;
/* /*
* we only wait tx-done event if transferring by DMA. for PIO, * we only wait tx-done event if transferring by DMA. for PIO,
* we get rx data by writing tx data, so if rx is done, tx has * we get rx data by writing tx data, so if rx is done, tx has
* done earlier * done earlier
*/ */
if (IS_DMA_VALID(t)) {
if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) { if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) {
dev_err(&spi->dev, "transfer timeout\n"); dev_err(&spi->dev, "transfer timeout\n");
dmaengine_terminate_all(sspi->tx_chan); dmaengine_terminate_all(sspi->tx_chan);
} }
}
if (IS_DMA_VALID(t)) {
dma_unmap_single(&spi->dev, sspi->src_start, t->len, DMA_TO_DEVICE); dma_unmap_single(&spi->dev, sspi->src_start, t->len, DMA_TO_DEVICE);
dma_unmap_single(&spi->dev, sspi->dst_start, t->len, DMA_FROM_DEVICE); dma_unmap_single(&spi->dev, sspi->dst_start, t->len, DMA_FROM_DEVICE);
}
/* TX, RX FIFO stop */ /* TX, RX FIFO stop */
writel(0, sspi->base + SIRFSOC_SPI_RXFIFO_OP); writel(0, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
writel(0, sspi->base + SIRFSOC_SPI_TXFIFO_OP); writel(0, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
if (sspi->left_tx_word >= SIRFSOC_SPI_DAT_FRM_LEN_MAX)
writel(0, sspi->base + SIRFSOC_SPI_TX_RX_EN); writel(0, sspi->base + SIRFSOC_SPI_TX_RX_EN);
}
static void spi_sirfsoc_pio_transfer(struct spi_device *spi,
struct spi_transfer *t)
{
struct sirfsoc_spi *sspi;
int timeout = t->len * 10;
sspi = spi_master_get_devdata(spi->master);
do {
writel(SIRFSOC_SPI_FIFO_RESET,
sspi->base + SIRFSOC_SPI_RXFIFO_OP);
writel(SIRFSOC_SPI_FIFO_RESET,
sspi->base + SIRFSOC_SPI_TXFIFO_OP);
writel(SIRFSOC_SPI_FIFO_START,
sspi->base + SIRFSOC_SPI_RXFIFO_OP);
writel(SIRFSOC_SPI_FIFO_START,
sspi->base + SIRFSOC_SPI_TXFIFO_OP);
writel(0, sspi->base + SIRFSOC_SPI_INT_EN); writel(0, sspi->base + SIRFSOC_SPI_INT_EN);
writel(SIRFSOC_SPI_INT_MASK_ALL,
sspi->base + SIRFSOC_SPI_INT_STATUS);
writel(readl(sspi->base + SIRFSOC_SPI_CTRL) |
SIRFSOC_SPI_MUL_DAT_MODE | SIRFSOC_SPI_ENA_AUTO_CLR,
sspi->base + SIRFSOC_SPI_CTRL);
writel(min(sspi->left_tx_word, (u32)(256 / sspi->word_width))
- 1, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN);
writel(min(sspi->left_rx_word, (u32)(256 / sspi->word_width))
- 1, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN);
while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS)
& SIRFSOC_SPI_FIFO_FULL)) && sspi->left_tx_word)
sspi->tx_word(sspi);
writel(SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN |
SIRFSOC_SPI_TX_UFLOW_INT_EN |
SIRFSOC_SPI_RX_OFLOW_INT_EN,
sspi->base + SIRFSOC_SPI_INT_EN);
writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN,
sspi->base + SIRFSOC_SPI_TX_RX_EN);
if (!wait_for_completion_timeout(&sspi->tx_done, timeout) ||
!wait_for_completion_timeout(&sspi->rx_done, timeout)) {
dev_err(&spi->dev, "transfer timeout\n");
break;
}
while (!((readl(sspi->base + SIRFSOC_SPI_RXFIFO_STATUS)
& SIRFSOC_SPI_FIFO_EMPTY)) && sspi->left_rx_word)
sspi->rx_word(sspi);
writel(0, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
writel(0, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
} while (sspi->left_tx_word != 0 || sspi->left_rx_word != 0);
}
static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)
{
struct sirfsoc_spi *sspi;
sspi = spi_master_get_devdata(spi->master);
sspi->tx = t->tx_buf ? t->tx_buf : sspi->dummypage;
sspi->rx = t->rx_buf ? t->rx_buf : sspi->dummypage;
sspi->left_tx_word = sspi->left_rx_word = t->len / sspi->word_width;
reinit_completion(&sspi->rx_done);
reinit_completion(&sspi->tx_done);
/*
* in the transfer, if transfer data using command register with rx_buf
* null, just fill command data into command register and wait for its
* completion.
*/
if (sspi->tx_by_cmd)
spi_sirfsoc_cmd_transfer(spi, t);
else if (IS_DMA_VALID(t))
spi_sirfsoc_dma_transfer(spi, t);
else
spi_sirfsoc_pio_transfer(spi, t);
return t->len - sspi->left_rx_word * sspi->word_width; return t->len - sspi->left_rx_word * sspi->word_width;
} }
...@@ -512,7 +545,8 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -512,7 +545,8 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
break; break;
case 12: case 12:
case 16: case 16:
regval |= (bits_per_word == 12) ? SIRFSOC_SPI_TRAN_DAT_FORMAT_12 : regval |= (bits_per_word == 12) ?
SIRFSOC_SPI_TRAN_DAT_FORMAT_12 :
SIRFSOC_SPI_TRAN_DAT_FORMAT_16; SIRFSOC_SPI_TRAN_DAT_FORMAT_16;
sspi->rx_word = spi_sirfsoc_rx_word_u16; sspi->rx_word = spi_sirfsoc_rx_word_u16;
sspi->tx_word = spi_sirfsoc_tx_word_u16; sspi->tx_word = spi_sirfsoc_tx_word_u16;
...@@ -540,8 +574,8 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -540,8 +574,8 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
regval |= SIRFSOC_SPI_CLK_IDLE_STAT; regval |= SIRFSOC_SPI_CLK_IDLE_STAT;
/* /*
* Data should be driven at least 1/2 cycle before the fetch edge to make * Data should be driven at least 1/2 cycle before the fetch edge
* sure that data gets stable at the fetch edge. * to make sure that data gets stable at the fetch edge.
*/ */
if (((spi->mode & SPI_CPOL) && (spi->mode & SPI_CPHA)) || if (((spi->mode & SPI_CPOL) && (spi->mode & SPI_CPHA)) ||
(!(spi->mode & SPI_CPOL) && !(spi->mode & SPI_CPHA))) (!(spi->mode & SPI_CPOL) && !(spi->mode & SPI_CPHA)))
...@@ -578,11 +612,14 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -578,11 +612,14 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
if (IS_DMA_VALID(t)) { if (IS_DMA_VALID(t)) {
/* Enable DMA mode for RX, TX */ /* Enable DMA mode for RX, TX */
writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL); writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL);
writel(SIRFSOC_SPI_RX_DMA_FLUSH, sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL); writel(SIRFSOC_SPI_RX_DMA_FLUSH,
sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL);
} else { } else {
/* Enable IO mode for RX, TX */ /* Enable IO mode for RX, TX */
writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL); writel(SIRFSOC_SPI_IO_MODE_SEL,
writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL); sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL);
writel(SIRFSOC_SPI_IO_MODE_SEL,
sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL);
} }
return 0; return 0;
...@@ -612,7 +649,8 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) ...@@ -612,7 +649,8 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
goto err_cs; goto err_cs;
} }
master = spi_alloc_master(&pdev->dev, sizeof(*sspi) + sizeof(int) * num_cs); master = spi_alloc_master(&pdev->dev,
sizeof(*sspi) + sizeof(int) * num_cs);
if (!master) { if (!master) {
dev_err(&pdev->dev, "Unable to allocate SPI master\n"); dev_err(&pdev->dev, "Unable to allocate SPI master\n");
return -ENOMEM; return -ENOMEM;
...@@ -808,8 +846,7 @@ static struct platform_driver spi_sirfsoc_driver = { ...@@ -808,8 +846,7 @@ static struct platform_driver spi_sirfsoc_driver = {
.remove = spi_sirfsoc_remove, .remove = spi_sirfsoc_remove,
}; };
module_platform_driver(spi_sirfsoc_driver); module_platform_driver(spi_sirfsoc_driver);
MODULE_DESCRIPTION("SiRF SoC SPI master driver"); MODULE_DESCRIPTION("SiRF SoC SPI master driver");
MODULE_AUTHOR("Zhiwu Song <Zhiwu.Song@csr.com>, " MODULE_AUTHOR("Zhiwu Song <Zhiwu.Song@csr.com>");
"Barry Song <Baohua.Song@csr.com>"); MODULE_AUTHOR("Barry Song <Baohua.Song@csr.com>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/workqueue.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#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>
#include <linux/workqueue.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
......
...@@ -1012,7 +1012,7 @@ static irqreturn_t tegra_spi_isr(int irq, void *context_data) ...@@ -1012,7 +1012,7 @@ static irqreturn_t tegra_spi_isr(int irq, void *context_data)
return IRQ_WAKE_THREAD; return IRQ_WAKE_THREAD;
} }
static struct of_device_id tegra_spi_of_match[] = { static const struct of_device_id tegra_spi_of_match[] = {
{ .compatible = "nvidia,tegra114-spi", }, { .compatible = "nvidia,tegra114-spi", },
{} {}
}; };
......
...@@ -419,7 +419,7 @@ static irqreturn_t tegra_sflash_isr(int irq, void *context_data) ...@@ -419,7 +419,7 @@ static irqreturn_t tegra_sflash_isr(int irq, void *context_data)
return handle_cpu_based_xfer(tsd); return handle_cpu_based_xfer(tsd);
} }
static struct of_device_id tegra_sflash_of_match[] = { static const struct of_device_id tegra_sflash_of_match[] = {
{ .compatible = "nvidia,tegra20-sflash", }, { .compatible = "nvidia,tegra20-sflash", },
{} {}
}; };
......
...@@ -1001,7 +1001,7 @@ static const struct tegra_slink_chip_data tegra20_spi_cdata = { ...@@ -1001,7 +1001,7 @@ static const struct tegra_slink_chip_data tegra20_spi_cdata = {
.cs_hold_time = false, .cs_hold_time = false,
}; };
static struct of_device_id tegra_slink_of_match[] = { static const struct of_device_id tegra_slink_of_match[] = {
{ .compatible = "nvidia,tegra30-slink", .data = &tegra30_spi_cdata, }, { .compatible = "nvidia,tegra30-slink", .data = &tegra30_spi_cdata, },
{ .compatible = "nvidia,tegra20-slink", .data = &tegra20_spi_cdata, }, { .compatible = "nvidia,tegra20-slink", .data = &tegra20_spi_cdata, },
{} {}
......
...@@ -253,10 +253,8 @@ static int tle62x0_probe(struct spi_device *spi) ...@@ -253,10 +253,8 @@ static int tle62x0_probe(struct spi_device *spi)
} }
st = kzalloc(sizeof(struct tle62x0_state), GFP_KERNEL); st = kzalloc(sizeof(struct tle62x0_state), GFP_KERNEL);
if (st == NULL) { if (st == NULL)
dev_err(&spi->dev, "no memory for device state\n");
return -ENOMEM; return -ENOMEM;
}
st->us = spi; st->us = spi;
st->nr_gpio = pdata->gpio_count; st->nr_gpio = pdata->gpio_count;
......
...@@ -1578,14 +1578,11 @@ static int pch_spi_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1578,14 +1578,11 @@ static int pch_spi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct pch_pd_dev_save *pd_dev_save; struct pch_pd_dev_save *pd_dev_save;
pd_dev_save = kzalloc(sizeof(struct pch_pd_dev_save), GFP_KERNEL); pd_dev_save = kzalloc(sizeof(struct pch_pd_dev_save), GFP_KERNEL);
if (!pd_dev_save) { if (!pd_dev_save)
dev_err(&pdev->dev, "%s Can't allocate pd_dev_sav\n", __func__);
return -ENOMEM; return -ENOMEM;
}
board_dat = kzalloc(sizeof(struct pch_spi_board_data), GFP_KERNEL); board_dat = kzalloc(sizeof(struct pch_spi_board_data), GFP_KERNEL);
if (!board_dat) { if (!board_dat) {
dev_err(&pdev->dev, "%s Can't allocate board_dat\n", __func__);
retval = -ENOMEM; retval = -ENOMEM;
goto err_no_mem; goto err_no_mem;
} }
......
...@@ -796,7 +796,7 @@ static int spi_transfer_one_message(struct spi_master *master, ...@@ -796,7 +796,7 @@ static int spi_transfer_one_message(struct spi_master *master,
if (ret > 0) { if (ret > 0) {
ret = 0; ret = 0;
ms = xfer->len * 8 * 1000 / xfer->speed_hz; ms = xfer->len * 8 * 1000 / xfer->speed_hz;
ms += 10; /* some tolerance */ ms += ms + 100; /* some tolerance */
ms = wait_for_completion_timeout(&master->xfer_completion, ms = wait_for_completion_timeout(&master->xfer_completion,
msecs_to_jiffies(ms)); msecs_to_jiffies(ms));
...@@ -1255,6 +1255,8 @@ static void of_register_spi_devices(struct spi_master *master) ...@@ -1255,6 +1255,8 @@ static void of_register_spi_devices(struct spi_master *master)
spi->mode |= SPI_CS_HIGH; spi->mode |= SPI_CS_HIGH;
if (of_find_property(nc, "spi-3wire", NULL)) if (of_find_property(nc, "spi-3wire", NULL))
spi->mode |= SPI_3WIRE; spi->mode |= SPI_3WIRE;
if (of_find_property(nc, "spi-lsb-first", NULL))
spi->mode |= SPI_LSB_FIRST;
/* Device DUAL/QUAD mode */ /* Device DUAL/QUAD mode */
if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) { if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) {
...@@ -1268,11 +1270,10 @@ static void of_register_spi_devices(struct spi_master *master) ...@@ -1268,11 +1270,10 @@ static void of_register_spi_devices(struct spi_master *master)
spi->mode |= SPI_TX_QUAD; spi->mode |= SPI_TX_QUAD;
break; break;
default: default:
dev_err(&master->dev, dev_warn(&master->dev,
"spi-tx-bus-width %d not supported\n", "spi-tx-bus-width %d not supported\n",
value); value);
spi_dev_put(spi); break;
continue;
} }
} }
...@@ -1287,11 +1288,10 @@ static void of_register_spi_devices(struct spi_master *master) ...@@ -1287,11 +1288,10 @@ static void of_register_spi_devices(struct spi_master *master)
spi->mode |= SPI_RX_QUAD; spi->mode |= SPI_RX_QUAD;
break; break;
default: default:
dev_err(&master->dev, dev_warn(&master->dev,
"spi-rx-bus-width %d not supported\n", "spi-rx-bus-width %d not supported\n",
value); value);
spi_dev_put(spi); break;
continue;
} }
} }
......
/* /*
* Analog Devices SPI3 controller driver * Analog Devices SPI3 controller driver
* *
* Copyright (c) 2011 Analog Devices Inc. * Copyright (c) 2014 Analog Devices Inc.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -11,14 +11,10 @@ ...@@ -11,14 +11,10 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#ifndef _SPI_CHANNEL_H_ #ifndef _ADI_SPI3_H_
#define _SPI_CHANNEL_H_ #define _ADI_SPI3_H_
#include <linux/types.h> #include <linux/types.h>
...@@ -209,9 +205,9 @@ ...@@ -209,9 +205,9 @@
#define SPI_ILAT_CLR_TFI 0x00000800 /* Transmit Finish Indication */ #define SPI_ILAT_CLR_TFI 0x00000800 /* Transmit Finish Indication */
/* /*
* bfin spi3 registers layout * adi spi3 registers layout
*/ */
struct bfin_spi_regs { struct adi_spi_regs {
u32 revid; u32 revid;
u32 control; u32 control;
u32 rx_control; u32 rx_control;
...@@ -240,7 +236,7 @@ struct bfin_spi_regs { ...@@ -240,7 +236,7 @@ struct bfin_spi_regs {
#define MAX_CTRL_CS 8 /* cs in spi controller */ #define MAX_CTRL_CS 8 /* cs in spi controller */
/* device.platform_data for SSP controller devices */ /* device.platform_data for SSP controller devices */
struct bfin_spi3_master { struct adi_spi3_master {
u16 num_chipselect; u16 num_chipselect;
u16 pin_req[7]; u16 pin_req[7];
}; };
...@@ -248,11 +244,11 @@ struct bfin_spi3_master { ...@@ -248,11 +244,11 @@ struct bfin_spi3_master {
/* spi_board_info.controller_data for SPI slave devices, /* spi_board_info.controller_data for SPI slave devices,
* copied to spi_device.platform_data ... mostly for dma tuning * copied to spi_device.platform_data ... mostly for dma tuning
*/ */
struct bfin_spi3_chip { struct adi_spi3_chip {
u32 control; u32 control;
u16 cs_chg_udelay; /* Some devices require 16-bit delays */ u16 cs_chg_udelay; /* Some devices require 16-bit delays */
u32 tx_dummy_val; /* tx value for rx only transfer */ u32 tx_dummy_val; /* tx value for rx only transfer */
bool enable_dma; bool enable_dma;
}; };
#endif /* _SPI_CHANNEL_H_ */ #endif /* _ADI_SPI3_H_ */
...@@ -25,8 +25,6 @@ struct rspi_plat_data { ...@@ -25,8 +25,6 @@ struct rspi_plat_data {
unsigned int dma_tx_id; unsigned int dma_tx_id;
unsigned int dma_rx_id; unsigned int dma_rx_id;
unsigned dma_width_16bit:1; /* DMAC read/write width = 16-bit */
u16 num_chipselect; u16 num_chipselect;
}; };
......
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