提交 5d3fed70 编写于 作者: L Linus Torvalds

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

Pull spi updates from Mark Brown:
 "Business as usual for SPI - some new drivers, lots of fixes and
  updates to existing drivers plus some new framework features.  Notable
  changes are:

   - Support for dual and quad data lines, commonly used by flash chips
     to improve performance, from Wang Yuhang.
   - Factored out a common pattern for runtime PM implementation into
     the core saving a bunch of code.
   - A particularly nice set of updates to the ep93xx driver from
     H Hartley Sweeten, modernising it and reducing the code size a lot.
   - New drivers for Blackfin v3, EFM32, Freescale DSPI and TI QSPI"

* tag 'spi-v3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (133 commits)
  spi/qspi: fix missing unlock on error in ti_qspi_start_transfer_one()
  spi: quad: fix the name of DT property
  spi: core: Fix spi_register_master error handling
  spi: efm32: Fix build error
  spi: altera: Use DIV_ROUND_UP to calculate hw->bytes_per_word
  spi: rspi: Add spi_master_get() call to prevent use after free
  spi: quad: Make DT properties optional
  spi: quad: Fix missing return
  spi: Use dev_get_drvdata at appropriate places
  spi: use dev_get_platdata()
  spi: nuc900: Fix mode_bits setting
  spi: simplify devm_request_mem_region/devm_ioremap
  spi: altera: Simplify altera_spi_txrx implementation for noirq case
  spi: spi-rspi: fix inconsistent spin_lock_irqsave
  spi/qspi: Add compatible string for am4372.
  spi/qspi: Fix device table entry
  spi/sirf: fix the misunderstanding about len of spi_transfer
  spi/qspi: Add dual/quad spi read support
  spi: sirf: fix error return code in spi_sirfsoc_probe()
  spi: bcm2835: Add spi_master_get() call to prevent use after free
  ...
* Energy Micro EFM32 SPI
Required properties:
- #address-cells: see spi-bus.txt
- #size-cells: see spi-bus.txt
- compatible: should be "efm32,spi"
- reg: Offset and length of the register set for the controller
- interrupts: pair specifying rx and tx irq
- clocks: phandle to the spi clock
- cs-gpios: see spi-bus.txt
- location: Value to write to the ROUTE register's LOCATION bitfield to configure the pinmux for the device, see datasheet for values.
Example:
spi1: spi@0x4000c400 { /* USART1 */
#address-cells = <1>;
#size-cells = <0>;
compatible = "efm32,spi";
reg = <0x4000c400 0x400>;
interrupts = <15 16>;
clocks = <&cmu 20>;
cs-gpios = <&gpio 51 1>; // D3
location = <1>;
status = "ok";
ks8851@0 {
compatible = "ks8851";
spi-max-frequency = <6000000>;
reg = <0>;
interrupt-parent = <&boardfpga>;
interrupts = <4>;
status = "ok";
};
};
......@@ -55,6 +55,16 @@ contain the following properties.
chip select active high
- spi-3wire - (optional) Empty property indicating device requires
3-wire mode.
- spi-tx-bus-width - (optional) The bus width(number of data wires) that
used for MOSI. Defaults to 1 if not present.
- spi-rx-bus-width - (optional) The bus width(number of data wires) that
used for MISO. Defaults to 1 if not present.
Some SPI controllers and devices support Dual and Quad SPI transfer mode.
It allows data in SPI system transfered in 2 wires(DUAL) or 4 wires(QUAD).
Now the value that spi-tx-bus-width and spi-rx-bus-width can receive is
only 1(SINGLE), 2(DUAL) and 4(QUAD).
Dual/Quad mode is not allowed when 3-wire mode is used.
If a gpio chipselect is used for the SPI slave the gpio number will be passed
via the cs_gpio
......
ARM Freescale DSPI controller
Required properties:
- compatible : "fsl,vf610-dspi"
- reg : Offset and length of the register set for the device
- interrupts : Should contain SPI controller interrupt
- clocks: from common clock binding: handle to dspi clock.
- clock-names: from common clock binding: Shall be "dspi".
- pinctrl-0: pin control group to be used for this controller.
- pinctrl-names: must contain a "default" entry.
- spi-num-chipselects : the number of the chipselect signals.
- bus-num : the slave chip chipselect signal number.
Example:
dspi0@4002c000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,vf610-dspi";
reg = <0x4002c000 0x1000>;
interrupts = <0 67 0x04>;
clocks = <&clks VF610_CLK_DSPI0>;
clock-names = "dspi";
spi-num-chipselects = <5>;
bus-num = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_dspi0_1>;
status = "okay";
sflash: at26df081a@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "atmel,at26df081a";
spi-max-frequency = <16000000>;
spi-cpol;
spi-cpha;
reg = <0>;
linux,modalias = "m25p80";
modal = "at26df081a";
};
};
TI QSPI controller.
Required properties:
- compatible : should be "ti,dra7xxx-qspi" or "ti,am4372-qspi".
- reg: Should contain QSPI registers location and length.
- #address-cells, #size-cells : Must be present if the device has sub-nodes
- ti,hwmods: Name of the hwmod associated to the QSPI
Recommended properties:
- spi-max-frequency: Definition as per
Documentation/devicetree/bindings/spi/spi-bus.txt
Example:
qspi: qspi@4b300000 {
compatible = "ti,dra7xxx-qspi";
reg = <0x4b300000 0x100>;
#address-cells = <1>;
#size-cells = <0>;
spi-max-frequency = <25000000>;
ti,hwmods = "qspi";
};
......@@ -215,7 +215,7 @@ So for example arch/.../mach-*/board-*.c files might have code like:
/* if your mach-* infrastructure doesn't support kernels that can
* run on multiple boards, pdata wouldn't benefit from "__init".
*/
static struct mysoc_spi_data __initdata pdata = { ... };
static struct mysoc_spi_data pdata __initdata = { ... };
static __init board_init(void)
{
......
......@@ -70,14 +70,14 @@ config SPI_ATH79
config SPI_ATMEL
tristate "Atmel SPI Controller"
depends on (ARCH_AT91 || AVR32)
depends on (ARCH_AT91 || AVR32 || COMPILE_TEST)
help
This selects a driver for the Atmel SPI Controller, present on
many AT32 (AVR32) and AT91 (ARM) chips.
config SPI_BCM2835
tristate "BCM2835 SPI controller"
depends on ARCH_BCM2835
depends on ARCH_BCM2835 || COMPILE_TEST
help
This selects a driver for the Broadcom BCM2835 SPI master.
......@@ -88,10 +88,17 @@ config SPI_BCM2835
config SPI_BFIN5XX
tristate "SPI controller driver for ADI Blackfin5xx"
depends on BLACKFIN
depends on BLACKFIN && !BF60x
help
This is the SPI controller master driver for Blackfin 5xx processor.
config SPI_BFIN_V3
tristate "SPI controller v3 for Blackfin"
depends on BF60x
help
This is the SPI controller v3 master driver
found on Blackfin 60x processor.
config SPI_BFIN_SPORT
tristate "SPI bus via Blackfin SPORT"
depends on BLACKFIN
......@@ -151,15 +158,22 @@ config SPI_COLDFIRE_QSPI
config SPI_DAVINCI
tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
depends on ARCH_DAVINCI
depends on ARCH_DAVINCI || ARCH_KEYSTONE
select SPI_BITBANG
select TI_EDMA
help
SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
config SPI_EFM32
tristate "EFM32 SPI controller"
depends on OF && ARM && (ARCH_EFM32 || COMPILE_TEST)
select SPI_BITBANG
help
Driver for the spi controller found on Energy Micro's EFM32 SoCs.
config SPI_EP93XX
tristate "Cirrus Logic EP93xx SPI controller"
depends on ARCH_EP93XX
depends on ARCH_EP93XX || COMPILE_TEST
help
This enables using the Cirrus EP93xx SPI controller in master
mode.
......@@ -191,7 +205,7 @@ config SPI_GPIO
config SPI_IMX
tristate "Freescale i.MX SPI controllers"
depends on ARCH_MXC
depends on ARCH_MXC || COMPILE_TEST
select SPI_BITBANG
default m if IMX_HAVE_PLATFORM_SPI_IMX
help
......@@ -248,6 +262,13 @@ config SPI_FSL_SPI
This also enables using the Aeroflex Gaisler GRLIB SPI controller in
master mode.
config SPI_FSL_DSPI
tristate "Freescale DSPI controller"
select SPI_BITBANG
help
This enables support for the Freescale DSPI controller in master
mode. VF610 platform uses the controller.
config SPI_FSL_ESPI
bool "Freescale eSPI controller"
depends on FSL_SOC
......@@ -280,20 +301,28 @@ config SPI_OMAP_UWIRE
config SPI_OMAP24XX
tristate "McSPI driver for OMAP"
depends on ARCH_OMAP2PLUS
depends on ARCH_OMAP2PLUS || COMPILE_TEST
help
SPI master controller for OMAP24XX and later Multichannel SPI
(McSPI) modules.
config SPI_TI_QSPI
tristate "DRA7xxx QSPI controller support"
depends on ARCH_OMAP2PLUS || COMPILE_TEST
help
QSPI master controller for DRA7xxx used for flash devices.
This device supports single, dual and quad read support, while
it only supports single write mode.
config SPI_OMAP_100K
tristate "OMAP SPI 100K"
depends on ARCH_OMAP850 || ARCH_OMAP730
depends on ARCH_OMAP850 || ARCH_OMAP730 || COMPILE_TEST
help
OMAP SPI 100K master controller for omap7xx boards.
config SPI_ORION
tristate "Orion SPI master"
depends on PLAT_ORION
depends on PLAT_ORION || COMPILE_TEST
help
This enables using the SPI master controller on the Orion chips.
......@@ -341,7 +370,7 @@ config SPI_PXA2XX_PCI
config SPI_RSPI
tristate "Renesas RSPI controller"
depends on SUPERH
depends on SUPERH && SH_DMAE_BASE
help
SPI driver for Renesas RSPI blocks.
......@@ -385,7 +414,7 @@ config SPI_SH_MSIOF
config SPI_SH
tristate "SuperH SPI controller"
depends on SUPERH
depends on SUPERH || COMPILE_TEST
help
SPI driver for SuperH SPI blocks.
......@@ -398,13 +427,13 @@ config SPI_SH_SCI
config SPI_SH_HSPI
tristate "SuperH HSPI controller"
depends on ARCH_SHMOBILE
depends on ARCH_SHMOBILE || COMPILE_TEST
help
SPI driver for SuperH HSPI blocks.
config SPI_SIRF
tristate "CSR SiRFprimaII SPI controller"
depends on ARCH_SIRF
depends on SIRF_DMA
select SPI_BITBANG
help
SPI driver for CSR SiRFprimaII SoCs
......@@ -418,7 +447,7 @@ config SPI_MXS
config SPI_TEGRA114
tristate "NVIDIA Tegra114 SPI Controller"
depends on ARCH_TEGRA && TEGRA20_APB_DMA
depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
help
SPI driver for NVIDIA Tegra114 SPI Controller interface. This controller
is different than the older SoCs SPI controller and also register interface
......@@ -426,7 +455,7 @@ config SPI_TEGRA114
config SPI_TEGRA20_SFLASH
tristate "Nvidia Tegra20 Serial flash Controller"
depends on ARCH_TEGRA
depends on ARCH_TEGRA || COMPILE_TEST
help
SPI driver for Nvidia Tegra20 Serial flash Controller interface.
The main usecase of this controller is to use spi flash as boot
......@@ -434,7 +463,7 @@ config SPI_TEGRA20_SFLASH
config SPI_TEGRA20_SLINK
tristate "Nvidia Tegra20/Tegra30 SLINK Controller"
depends on ARCH_TEGRA && TEGRA20_APB_DMA
depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
help
SPI driver for Nvidia Tegra20/Tegra30 SLINK Controller interface.
......@@ -457,7 +486,7 @@ config SPI_TOPCLIFF_PCH
config SPI_TXX9
tristate "Toshiba TXx9 SPI controller"
depends on GPIOLIB && CPU_TX49XX
depends on GPIOLIB && (CPU_TX49XX || COMPILE_TEST)
help
SPI driver for Toshiba TXx9 MIPS SoCs
......
......@@ -17,6 +17,7 @@ obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o
obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o
obj-$(CONFIG_SPI_BFIN_V3) += spi-bfin-v3.o
obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
......@@ -27,9 +28,11 @@ obj-$(CONFIG_SPI_DESIGNWARE) += spi-dw.o
obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o
obj-$(CONFIG_SPI_DW_PCI) += spi-dw-midpci.o
spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o
obj-$(CONFIG_SPI_EFM32) += spi-efm32.o
obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o
obj-$(CONFIG_SPI_FALCON) += spi-falcon.o
obj-$(CONFIG_SPI_FSL_CPM) += spi-fsl-cpm.o
obj-$(CONFIG_SPI_FSL_DSPI) += spi-fsl-dspi.o
obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o
obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o
obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
......@@ -46,6 +49,7 @@ obj-$(CONFIG_SPI_OCTEON) += spi-octeon.o
obj-$(CONFIG_SPI_OMAP_UWIRE) += spi-omap-uwire.o
obj-$(CONFIG_SPI_OMAP_100K) += spi-omap-100k.o
obj-$(CONFIG_SPI_OMAP24XX) += spi-omap2-mcspi.o
obj-$(CONFIG_SPI_TI_QSPI) += spi-ti-qspi.o
obj-$(CONFIG_SPI_ORION) += spi-orion.o
obj-$(CONFIG_SPI_PL022) += spi-pl022.o
obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o
......
......@@ -103,16 +103,6 @@ static void altera_spi_chipsel(struct spi_device *spi, int value)
}
}
static int altera_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
{
return 0;
}
static int altera_spi_setup(struct spi_device *spi)
{
return 0;
}
static inline unsigned int hw_txbyte(struct altera_spi *hw, int count)
{
if (hw->tx) {
......@@ -134,7 +124,7 @@ static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
hw->tx = t->tx_buf;
hw->rx = t->rx_buf;
hw->count = 0;
hw->bytes_per_word = t->bits_per_word / 8;
hw->bytes_per_word = DIV_ROUND_UP(t->bits_per_word, 8);
hw->len = t->len / hw->bytes_per_word;
if (hw->irq >= 0) {
......@@ -150,12 +140,12 @@ static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
} else {
/* send the first byte */
writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA);
while (1) {
while (hw->count < hw->len) {
unsigned int rxd;
writel(hw_txbyte(hw, hw->count),
hw->base + ALTERA_SPI_TXDATA);
while (!(readl(hw->base + ALTERA_SPI_STATUS) &
ALTERA_SPI_STATUS_RRDY_MSK))
cpu_relax();
......@@ -174,14 +164,7 @@ static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
}
hw->count++;
if (hw->count < hw->len)
writel(hw_txbyte(hw, hw->count),
hw->base + ALTERA_SPI_TXDATA);
else
break;
}
}
return hw->count * hw->bytes_per_word;
......@@ -217,7 +200,7 @@ static irqreturn_t altera_spi_irq(int irq, void *dev)
static int altera_spi_probe(struct platform_device *pdev)
{
struct altera_spi_platform_data *platp = pdev->dev.platform_data;
struct altera_spi_platform_data *platp = dev_get_platdata(&pdev->dev);
struct altera_spi *hw;
struct spi_master *master;
struct resource *res;
......@@ -231,7 +214,6 @@ static int altera_spi_probe(struct platform_device *pdev)
master->bus_num = pdev->id;
master->num_chipselect = 16;
master->mode_bits = SPI_CS_HIGH;
master->setup = altera_spi_setup;
hw = spi_master_get_devdata(master);
platform_set_drvdata(pdev, hw);
......@@ -240,21 +222,16 @@ static int altera_spi_probe(struct platform_device *pdev)
hw->bitbang.master = spi_master_get(master);
if (!hw->bitbang.master)
return err;
hw->bitbang.setup_transfer = altera_spi_setupxfer;
hw->bitbang.chipselect = altera_spi_chipsel;
hw->bitbang.txrx_bufs = altera_spi_txrx;
/* find and map our resources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
goto exit_busy;
if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
pdev->name))
goto exit_busy;
hw->base = devm_ioremap_nocache(&pdev->dev, res->start,
resource_size(res));
if (!hw->base)
goto exit_busy;
hw->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(hw->base)) {
err = PTR_ERR(hw->base);
goto exit;
}
/* program defaults into the registers */
hw->imr = 0; /* disable spi interrupts */
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
......@@ -281,9 +258,6 @@ static int altera_spi_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
return 0;
exit_busy:
err = -EBUSY;
exit:
spi_master_put(master);
return err;
......
......@@ -221,7 +221,7 @@ static int ath79_spi_probe(struct platform_device *pdev)
sp = spi_master_get_devdata(master);
platform_set_drvdata(pdev, sp);
pdata = pdev->dev.platform_data;
pdata = dev_get_platdata(&pdev->dev);
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
master->setup = ath79_spi_setup;
......
......@@ -360,12 +360,12 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
gpio_set_value(asd->npcs_pin, !active);
}
static void atmel_spi_lock(struct atmel_spi *as)
static void atmel_spi_lock(struct atmel_spi *as) __acquires(&as->lock)
{
spin_lock_irqsave(&as->lock, as->flags);
}
static void atmel_spi_unlock(struct atmel_spi *as)
static void atmel_spi_unlock(struct atmel_spi *as) __releases(&as->lock)
{
spin_unlock_irqrestore(&as->lock, as->flags);
}
......@@ -629,9 +629,9 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
goto err_dma;
dev_dbg(master->dev.parent,
" start dma xfer %p: len %u tx %p/%08x rx %p/%08x\n",
xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
xfer->rx_buf, xfer->rx_dma);
" start dma xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
xfer, xfer->len, xfer->tx_buf, (unsigned long long)xfer->tx_dma,
xfer->rx_buf, (unsigned long long)xfer->rx_dma);
/* Enable relevant interrupts */
spi_writel(as, IER, SPI_BIT(OVRES));
......@@ -732,9 +732,10 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
spi_writel(as, TCR, len);
dev_dbg(&msg->spi->dev,
" start xfer %p: len %u tx %p/%08x rx %p/%08x\n",
xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
xfer->rx_buf, xfer->rx_dma);
" start xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
xfer, xfer->len, xfer->tx_buf,
(unsigned long long)xfer->tx_dma, xfer->rx_buf,
(unsigned long long)xfer->rx_dma);
} else {
xfer = as->next_transfer;
remaining = as->next_remaining_bytes;
......@@ -771,9 +772,10 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
spi_writel(as, TNCR, len);
dev_dbg(&msg->spi->dev,
" next xfer %p: len %u tx %p/%08x rx %p/%08x\n",
xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
xfer->rx_buf, xfer->rx_dma);
" next xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
xfer, xfer->len, xfer->tx_buf,
(unsigned long long)xfer->tx_dma, xfer->rx_buf,
(unsigned long long)xfer->rx_dma);
ieval = SPI_BIT(ENDRX) | SPI_BIT(OVRES);
} else {
spi_writel(as, RNCR, 0);
......@@ -1579,7 +1581,9 @@ static int atmel_spi_probe(struct platform_device *pdev)
goto out_unmap_regs;
/* Initialize the hardware */
clk_enable(clk);
ret = clk_prepare_enable(clk);
if (ret)
goto out_unmap_regs;
spi_writel(as, CR, SPI_BIT(SWRST));
spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
if (as->caps.has_wdrbt) {
......@@ -1609,7 +1613,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
spi_writel(as, CR, SPI_BIT(SWRST));
spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
clk_disable(clk);
clk_disable_unprepare(clk);
free_irq(irq, master);
out_unmap_regs:
iounmap(as->regs);
......@@ -1661,7 +1665,7 @@ static int atmel_spi_remove(struct platform_device *pdev)
dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
as->buffer_dma);
clk_disable(as->clk);
clk_disable_unprepare(as->clk);
clk_put(as->clk);
free_irq(as->irq, master);
iounmap(as->regs);
......@@ -1678,7 +1682,7 @@ static int atmel_spi_suspend(struct platform_device *pdev, pm_message_t mesg)
struct spi_master *master = platform_get_drvdata(pdev);
struct atmel_spi *as = spi_master_get_devdata(master);
clk_disable(as->clk);
clk_disable_unprepare(as->clk);
return 0;
}
......@@ -1687,7 +1691,7 @@ static int atmel_spi_resume(struct platform_device *pdev)
struct spi_master *master = platform_get_drvdata(pdev);
struct atmel_spi *as = spi_master_get_devdata(master);
clk_enable(as->clk);
return clk_prepare_enable(as->clk);
return 0;
}
......
......@@ -776,7 +776,7 @@ static int au1550_spi_probe(struct platform_device *pdev)
hw = spi_master_get_devdata(master);
hw->master = spi_master_get(master);
hw->pdata = pdev->dev.platform_data;
hw->pdata = dev_get_platdata(&pdev->dev);
hw->dev = &pdev->dev;
if (hw->pdata == NULL) {
......
......@@ -314,7 +314,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master);
master->mode_bits = BCM2835_SPI_MODE_BITS;
master->bits_per_word_mask = BIT(8 - 1);
master->bits_per_word_mask = SPI_BPW_MASK(8);
master->bus_num = -1;
master->num_chipselect = 3;
master->transfer_one_message = bcm2835_spi_transfer_one;
......@@ -325,12 +325,6 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
init_completion(&bs->done);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "could not get memory resource\n");
err = -ENODEV;
goto out_master_put;
}
bs->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(bs->regs)) {
err = PTR_ERR(bs->regs);
......@@ -383,7 +377,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
static int bcm2835_spi_remove(struct platform_device *pdev)
{
struct spi_master *master = platform_get_drvdata(pdev);
struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
struct bcm2835_spi *bs = spi_master_get_devdata(master);
free_irq(bs->irq, master);
......
......@@ -231,24 +231,6 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
return 0;
}
static int bcm63xx_spi_prepare_transfer(struct spi_master *master)
{
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
pm_runtime_get_sync(&bs->pdev->dev);
return 0;
}
static int bcm63xx_spi_unprepare_transfer(struct spi_master *master)
{
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
pm_runtime_put(&bs->pdev->dev);
return 0;
}
static int bcm63xx_spi_transfer_one(struct spi_master *master,
struct spi_message *m)
{
......@@ -353,20 +335,13 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
{
struct resource *r;
struct device *dev = &pdev->dev;
struct bcm63xx_spi_pdata *pdata = pdev->dev.platform_data;
struct bcm63xx_spi_pdata *pdata = dev_get_platdata(&pdev->dev);
int irq;
struct spi_master *master;
struct clk *clk;
struct bcm63xx_spi *bs;
int ret;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
dev_err(dev, "no iomem\n");
ret = -ENXIO;
goto out;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "no irq\n");
......@@ -393,6 +368,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master);
bs->pdev = pdev;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
bs->regs = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(bs->regs)) {
ret = PTR_ERR(bs->regs);
......@@ -412,11 +388,10 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
master->bus_num = pdata->bus_num;
master->num_chipselect = pdata->num_chipselect;
master->prepare_transfer_hardware = bcm63xx_spi_prepare_transfer;
master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer;
master->transfer_one_message = bcm63xx_spi_transfer_one;
master->mode_bits = MODEBITS;
master->bits_per_word_mask = SPI_BPW_MASK(8);
master->auto_runtime_pm = true;
bs->msg_type_shift = pdata->msg_type_shift;
bs->msg_ctl_width = pdata->msg_ctl_width;
bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
......@@ -480,8 +455,7 @@ static int bcm63xx_spi_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int bcm63xx_spi_suspend(struct device *dev)
{
struct spi_master *master =
platform_get_drvdata(to_platform_device(dev));
struct spi_master *master = dev_get_drvdata(dev);
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
spi_master_suspend(master);
......@@ -493,8 +467,7 @@ static int bcm63xx_spi_suspend(struct device *dev)
static int bcm63xx_spi_resume(struct device *dev)
{
struct spi_master *master =
platform_get_drvdata(to_platform_device(dev));
struct spi_master *master = dev_get_drvdata(dev);
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
clk_prepare_enable(bs->clk);
......
......@@ -756,7 +756,7 @@ static int bfin_sport_spi_probe(struct platform_device *pdev)
struct bfin_sport_spi_master_data *drv_data;
int status;
platform_info = dev->platform_data;
platform_info = dev_get_platdata(dev);
/* Allocate master with space for drv_data */
master = spi_alloc_master(dev, sizeof(*master) + 16);
......
此差异已折叠。
......@@ -1271,7 +1271,7 @@ static int bfin_spi_probe(struct platform_device *pdev)
struct resource *res;
int status = 0;
platform_info = dev->platform_data;
platform_info = dev_get_platdata(dev);
/* Allocate master with space for drv_data */
master = spi_alloc_master(dev, sizeof(*drv_data));
......
......@@ -255,150 +255,140 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
* Drivers can provide word-at-a-time i/o primitives, or provide
* transfer-at-a-time ones to leverage dma or fifo hardware.
*/
static void bitbang_work(struct work_struct *work)
static int spi_bitbang_prepare_hardware(struct spi_master *spi)
{
struct spi_bitbang *bitbang =
container_of(work, struct spi_bitbang, work);
struct spi_bitbang *bitbang;
unsigned long flags;
struct spi_message *m, *_m;
bitbang = spi_master_get_devdata(spi);
spin_lock_irqsave(&bitbang->lock, flags);
bitbang->busy = 1;
list_for_each_entry_safe(m, _m, &bitbang->queue, queue) {
struct spi_device *spi;
unsigned nsecs;
struct spi_transfer *t = NULL;
unsigned tmp;
unsigned cs_change;
int status;
int do_setup = -1;
list_del(&m->queue);
spin_unlock_irqrestore(&bitbang->lock, flags);
/* FIXME this is made-up ... the correct value is known to
* word-at-a-time bitbang code, and presumably chipselect()
* should enforce these requirements too?
*/
nsecs = 100;
spin_unlock_irqrestore(&bitbang->lock, flags);
spi = m->spi;
tmp = 0;
cs_change = 1;
status = 0;
return 0;
}
list_for_each_entry (t, &m->transfers, transfer_list) {
/* override speed or wordsize? */
if (t->speed_hz || t->bits_per_word)
do_setup = 1;
/* init (-1) or override (1) transfer params */
if (do_setup != 0) {
status = bitbang->setup_transfer(spi, t);
if (status < 0)
break;
if (do_setup == -1)
do_setup = 0;
}
/* set up default clock polarity, and activate chip;
* this implicitly updates clock and spi modes as
* previously recorded for this device via setup().
* (and also deselects any other chip that might be
* selected ...)
*/
if (cs_change) {
bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
ndelay(nsecs);
}
cs_change = t->cs_change;
if (!t->tx_buf && !t->rx_buf && t->len) {
status = -EINVAL;
break;
}
static int spi_bitbang_transfer_one(struct spi_master *master,
struct spi_message *m)
{
struct spi_bitbang *bitbang;
unsigned nsecs;
struct spi_transfer *t = NULL;
unsigned cs_change;
int status;
int do_setup = -1;
struct spi_device *spi = m->spi;
bitbang = spi_master_get_devdata(master);
/* FIXME this is made-up ... the correct value is known to
* word-at-a-time bitbang code, and presumably chipselect()
* should enforce these requirements too?
*/
nsecs = 100;
/* transfer data. the lower level code handles any
* new dma mappings it needs. our caller always gave
* us dma-safe buffers.
*/
if (t->len) {
/* REVISIT dma API still needs a designated
* DMA_ADDR_INVALID; ~0 might be better.
*/
if (!m->is_dma_mapped)
t->rx_dma = t->tx_dma = 0;
status = bitbang->txrx_bufs(spi, t);
}
if (status > 0)
m->actual_length += status;
if (status != t->len) {
/* always report some kind of error */
if (status >= 0)
status = -EREMOTEIO;
cs_change = 1;
status = 0;
list_for_each_entry (t, &m->transfers, transfer_list) {
/* override speed or wordsize? */
if (t->speed_hz || t->bits_per_word)
do_setup = 1;
/* init (-1) or override (1) transfer params */
if (do_setup != 0) {
status = bitbang->setup_transfer(spi, t);
if (status < 0)
break;
}
status = 0;
/* protocol tweaks before next transfer */
if (t->delay_usecs)
udelay(t->delay_usecs);
if (cs_change && !list_is_last(&t->transfer_list, &m->transfers)) {
/* sometimes a short mid-message deselect of the chip
* may be needed to terminate a mode or command
*/
ndelay(nsecs);
bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
ndelay(nsecs);
}
if (do_setup == -1)
do_setup = 0;
}
m->status = status;
m->complete(m->context);
/* set up default clock polarity, and activate chip;
* this implicitly updates clock and spi modes as
* previously recorded for this device via setup().
* (and also deselects any other chip that might be
* selected ...)
*/
if (cs_change) {
bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
ndelay(nsecs);
}
cs_change = t->cs_change;
if (!t->tx_buf && !t->rx_buf && t->len) {
status = -EINVAL;
break;
}
/* normally deactivate chipselect ... unless no error and
* cs_change has hinted that the next message will probably
* be for this chip too.
/* transfer data. the lower level code handles any
* new dma mappings it needs. our caller always gave
* us dma-safe buffers.
*/
if (!(status == 0 && cs_change)) {
if (t->len) {
/* REVISIT dma API still needs a designated
* DMA_ADDR_INVALID; ~0 might be better.
*/
if (!m->is_dma_mapped)
t->rx_dma = t->tx_dma = 0;
status = bitbang->txrx_bufs(spi, t);
}
if (status > 0)
m->actual_length += status;
if (status != t->len) {
/* always report some kind of error */
if (status >= 0)
status = -EREMOTEIO;
break;
}
status = 0;
/* protocol tweaks before next transfer */
if (t->delay_usecs)
udelay(t->delay_usecs);
if (cs_change && !list_is_last(&t->transfer_list, &m->transfers)) {
/* sometimes a short mid-message deselect of the chip
* may be needed to terminate a mode or command
*/
ndelay(nsecs);
bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
ndelay(nsecs);
}
}
m->status = status;
spin_lock_irqsave(&bitbang->lock, flags);
/* normally deactivate chipselect ... unless no error and
* cs_change has hinted that the next message will probably
* be for this chip too.
*/
if (!(status == 0 && cs_change)) {
ndelay(nsecs);
bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
ndelay(nsecs);
}
bitbang->busy = 0;
spin_unlock_irqrestore(&bitbang->lock, flags);
spi_finalize_current_message(master);
return status;
}
/**
* spi_bitbang_transfer - default submit to transfer queue
*/
int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
static int spi_bitbang_unprepare_hardware(struct spi_master *spi)
{
struct spi_bitbang *bitbang;
struct spi_bitbang *bitbang;
unsigned long flags;
int status = 0;
m->actual_length = 0;
m->status = -EINPROGRESS;
bitbang = spi_master_get_devdata(spi->master);
bitbang = spi_master_get_devdata(spi);
spin_lock_irqsave(&bitbang->lock, flags);
if (!spi->max_speed_hz)
status = -ENETDOWN;
else {
list_add_tail(&m->queue, &bitbang->queue);
queue_work(bitbang->workqueue, &bitbang->work);
}
bitbang->busy = 0;
spin_unlock_irqrestore(&bitbang->lock, flags);
return status;
return 0;
}
EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
/*----------------------------------------------------------------------*/
......@@ -428,20 +418,22 @@ EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
int spi_bitbang_start(struct spi_bitbang *bitbang)
{
struct spi_master *master = bitbang->master;
int status;
if (!master || !bitbang->chipselect)
return -EINVAL;
INIT_WORK(&bitbang->work, bitbang_work);
spin_lock_init(&bitbang->lock);
INIT_LIST_HEAD(&bitbang->queue);
if (!master->mode_bits)
master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
if (!master->transfer)
master->transfer = spi_bitbang_transfer;
if (master->transfer || master->transfer_one_message)
return -EINVAL;
master->prepare_transfer_hardware = spi_bitbang_prepare_hardware;
master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware;
master->transfer_one_message = spi_bitbang_transfer_one;
if (!bitbang->txrx_bufs) {
bitbang->use_dma = 0;
bitbang->txrx_bufs = spi_bitbang_bufs;
......@@ -452,34 +444,12 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
master->setup = spi_bitbang_setup;
master->cleanup = spi_bitbang_cleanup;
}
} else if (!master->setup)
return -EINVAL;
if (master->transfer == spi_bitbang_transfer &&
!bitbang->setup_transfer)
return -EINVAL;
/* this task is the only thing to touch the SPI bits */
bitbang->busy = 0;
bitbang->workqueue = create_singlethread_workqueue(
dev_name(master->dev.parent));
if (bitbang->workqueue == NULL) {
status = -EBUSY;
goto err1;
}
/* driver may get busy before register() returns, especially
* if someone registered boardinfo for devices
*/
status = spi_register_master(master);
if (status < 0)
goto err2;
return status;
err2:
destroy_workqueue(bitbang->workqueue);
err1:
return status;
return spi_register_master(master);
}
EXPORT_SYMBOL_GPL(spi_bitbang_start);
......@@ -490,10 +460,6 @@ int spi_bitbang_stop(struct spi_bitbang *bitbang)
{
spi_unregister_master(bitbang->master);
WARN_ON(!list_empty(&bitbang->queue));
destroy_workqueue(bitbang->workqueue);
return 0;
}
EXPORT_SYMBOL_GPL(spi_bitbang_stop);
......
......@@ -239,11 +239,8 @@ static int spi_clps711x_probe(struct platform_device *pdev)
}
dev_err(&pdev->dev, "Failed to register master\n");
devm_free_irq(&pdev->dev, IRQ_SSEOTI, hw);
clk_out:
devm_clk_put(&pdev->dev, hw->spi_clk);
err_out:
while (--i >= 0)
if (gpio_is_valid(hw->chipselect[i]))
......@@ -261,13 +258,10 @@ static int spi_clps711x_remove(struct platform_device *pdev)
struct spi_master *master = platform_get_drvdata(pdev);
struct spi_clps711x_data *hw = spi_master_get_devdata(master);
devm_free_irq(&pdev->dev, IRQ_SSEOTI, hw);
for (i = 0; i < master->num_chipselect; i++)
if (gpio_is_valid(hw->chipselect[i]))
gpio_free(hw->chipselect[i]);
devm_clk_put(&pdev->dev, hw->spi_clk);
spi_unregister_master(master);
kfree(master);
......
......@@ -354,24 +354,6 @@ static int mcfqspi_transfer_one_message(struct spi_master *master,
}
static int mcfqspi_prepare_transfer_hw(struct spi_master *master)
{
struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
pm_runtime_get_sync(mcfqspi->dev);
return 0;
}
static int mcfqspi_unprepare_transfer_hw(struct spi_master *master)
{
struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
pm_runtime_put_sync(mcfqspi->dev);
return 0;
}
static int mcfqspi_setup(struct spi_device *spi)
{
if (spi->chip_select >= spi->master->num_chipselect) {
......@@ -400,7 +382,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
struct mcfqspi_platform_data *pdata;
int status;
pdata = pdev->dev.platform_data;
pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_dbg(&pdev->dev, "platform data is missing\n");
return -ENOENT;
......@@ -473,8 +455,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16);
master->setup = mcfqspi_setup;
master->transfer_one_message = mcfqspi_transfer_one_message;
master->prepare_transfer_hardware = mcfqspi_prepare_transfer_hw;
master->unprepare_transfer_hardware = mcfqspi_unprepare_transfer_hw;
master->auto_runtime_pm = true;
platform_set_drvdata(pdev, master);
......@@ -558,7 +539,7 @@ static int mcfqspi_resume(struct device *dev)
#ifdef CONFIG_PM_RUNTIME
static int mcfqspi_runtime_suspend(struct device *dev)
{
struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
struct mcfqspi *mcfqspi = dev_get_drvdata(dev);
clk_disable(mcfqspi->clk);
......@@ -567,7 +548,7 @@ static int mcfqspi_runtime_suspend(struct device *dev)
static int mcfqspi_runtime_resume(struct device *dev)
{
struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
struct mcfqspi *mcfqspi = dev_get_drvdata(dev);
clk_enable(mcfqspi->clk);
......
......@@ -872,8 +872,8 @@ static int davinci_spi_probe(struct platform_device *pdev)
goto free_master;
}
if (pdev->dev.platform_data) {
pdata = pdev->dev.platform_data;
if (dev_get_platdata(&pdev->dev)) {
pdata = dev_get_platdata(&pdev->dev);
dspi->pdata = *pdata;
} else {
/* update dspi pdata with that from the DT */
......
/*
* Copyright (C) 2012-2013 Uwe Kleine-Koenig for Pengutronix
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/platform_data/efm32-spi.h>
#define DRIVER_NAME "efm32-spi"
#define MASK_VAL(mask, val) ((val << __ffs(mask)) & mask)
#define REG_CTRL 0x00
#define REG_CTRL_SYNC 0x0001
#define REG_CTRL_CLKPOL 0x0100
#define REG_CTRL_CLKPHA 0x0200
#define REG_CTRL_MSBF 0x0400
#define REG_CTRL_TXBIL 0x1000
#define REG_FRAME 0x04
#define REG_FRAME_DATABITS__MASK 0x000f
#define REG_FRAME_DATABITS(n) ((n) - 3)
#define REG_CMD 0x0c
#define REG_CMD_RXEN 0x0001
#define REG_CMD_RXDIS 0x0002
#define REG_CMD_TXEN 0x0004
#define REG_CMD_TXDIS 0x0008
#define REG_CMD_MASTEREN 0x0010
#define REG_STATUS 0x10
#define REG_STATUS_TXENS 0x0002
#define REG_STATUS_TXC 0x0020
#define REG_STATUS_TXBL 0x0040
#define REG_STATUS_RXDATAV 0x0080
#define REG_CLKDIV 0x14
#define REG_RXDATAX 0x18
#define REG_RXDATAX_RXDATA__MASK 0x01ff
#define REG_RXDATAX_PERR 0x4000
#define REG_RXDATAX_FERR 0x8000
#define REG_TXDATA 0x34
#define REG_IF 0x40
#define REG_IF_TXBL 0x0002
#define REG_IF_RXDATAV 0x0004
#define REG_IFS 0x44
#define REG_IFC 0x48
#define REG_IEN 0x4c
#define REG_ROUTE 0x54
#define REG_ROUTE_RXPEN 0x0001
#define REG_ROUTE_TXPEN 0x0002
#define REG_ROUTE_CLKPEN 0x0008
#define REG_ROUTE_LOCATION__MASK 0x0700
#define REG_ROUTE_LOCATION(n) MASK_VAL(REG_ROUTE_LOCATION__MASK, (n))
struct efm32_spi_ddata {
struct spi_bitbang bitbang;
spinlock_t lock;
struct clk *clk;
void __iomem *base;
unsigned int rxirq, txirq;
struct efm32_spi_pdata pdata;
/* irq data */
struct completion done;
const u8 *tx_buf;
u8 *rx_buf;
unsigned tx_len, rx_len;
/* chip selects */
unsigned csgpio[];
};
#define ddata_to_dev(ddata) (&(ddata->bitbang.master->dev))
#define efm32_spi_vdbg(ddata, format, arg...) \
dev_vdbg(ddata_to_dev(ddata), format, ##arg)
static void efm32_spi_write32(struct efm32_spi_ddata *ddata,
u32 value, unsigned offset)
{
writel_relaxed(value, ddata->base + offset);
}
static u32 efm32_spi_read32(struct efm32_spi_ddata *ddata, unsigned offset)
{
return readl_relaxed(ddata->base + offset);
}
static void efm32_spi_chipselect(struct spi_device *spi, int is_on)
{
struct efm32_spi_ddata *ddata = spi_master_get_devdata(spi->master);
int value = !(spi->mode & SPI_CS_HIGH) == !(is_on == BITBANG_CS_ACTIVE);
gpio_set_value(ddata->csgpio[spi->chip_select], value);
}
static int efm32_spi_setup_transfer(struct spi_device *spi,
struct spi_transfer *t)
{
struct efm32_spi_ddata *ddata = spi_master_get_devdata(spi->master);
unsigned bpw = t->bits_per_word ?: spi->bits_per_word;
unsigned speed = t->speed_hz ?: spi->max_speed_hz;
unsigned long clkfreq = clk_get_rate(ddata->clk);
u32 clkdiv;
efm32_spi_write32(ddata, REG_CTRL_SYNC | REG_CTRL_MSBF |
(spi->mode & SPI_CPHA ? REG_CTRL_CLKPHA : 0) |
(spi->mode & SPI_CPOL ? REG_CTRL_CLKPOL : 0), REG_CTRL);
efm32_spi_write32(ddata,
REG_FRAME_DATABITS(bpw), REG_FRAME);
if (2 * speed >= clkfreq)
clkdiv = 0;
else
clkdiv = 64 * (DIV_ROUND_UP(2 * clkfreq, speed) - 4);
if (clkdiv > (1U << 21))
return -EINVAL;
efm32_spi_write32(ddata, clkdiv, REG_CLKDIV);
efm32_spi_write32(ddata, REG_CMD_MASTEREN, REG_CMD);
efm32_spi_write32(ddata, REG_CMD_RXEN | REG_CMD_TXEN, REG_CMD);
return 0;
}
static void efm32_spi_tx_u8(struct efm32_spi_ddata *ddata)
{
u8 val = 0;
if (ddata->tx_buf) {
val = *ddata->tx_buf;
ddata->tx_buf++;
}
ddata->tx_len--;
efm32_spi_write32(ddata, val, REG_TXDATA);
efm32_spi_vdbg(ddata, "%s: tx 0x%x\n", __func__, val);
}
static void efm32_spi_rx_u8(struct efm32_spi_ddata *ddata)
{
u32 rxdata = efm32_spi_read32(ddata, REG_RXDATAX);
efm32_spi_vdbg(ddata, "%s: rx 0x%x\n", __func__, rxdata);
if (ddata->rx_buf) {
*ddata->rx_buf = rxdata;
ddata->rx_buf++;
}
ddata->rx_len--;
}
static void efm32_spi_filltx(struct efm32_spi_ddata *ddata)
{
while (ddata->tx_len &&
ddata->tx_len + 2 > ddata->rx_len &&
efm32_spi_read32(ddata, REG_STATUS) & REG_STATUS_TXBL) {
efm32_spi_tx_u8(ddata);
}
}
static int efm32_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
{
struct efm32_spi_ddata *ddata = spi_master_get_devdata(spi->master);
int ret = -EBUSY;
spin_lock_irq(&ddata->lock);
if (ddata->tx_buf || ddata->rx_buf)
goto out_unlock;
ddata->tx_buf = t->tx_buf;
ddata->rx_buf = t->rx_buf;
ddata->tx_len = ddata->rx_len =
t->len * DIV_ROUND_UP(t->bits_per_word, 8);
efm32_spi_filltx(ddata);
init_completion(&ddata->done);
efm32_spi_write32(ddata, REG_IF_TXBL | REG_IF_RXDATAV, REG_IEN);
spin_unlock_irq(&ddata->lock);
wait_for_completion(&ddata->done);
spin_lock_irq(&ddata->lock);
ret = t->len - max(ddata->tx_len, ddata->rx_len);
efm32_spi_write32(ddata, 0, REG_IEN);
ddata->tx_buf = ddata->rx_buf = NULL;
out_unlock:
spin_unlock_irq(&ddata->lock);
return ret;
}
static irqreturn_t efm32_spi_rxirq(int irq, void *data)
{
struct efm32_spi_ddata *ddata = data;
irqreturn_t ret = IRQ_NONE;
spin_lock(&ddata->lock);
while (ddata->rx_len > 0 &&
efm32_spi_read32(ddata, REG_STATUS) &
REG_STATUS_RXDATAV) {
efm32_spi_rx_u8(ddata);
ret = IRQ_HANDLED;
}
if (!ddata->rx_len) {
u32 ien = efm32_spi_read32(ddata, REG_IEN);
ien &= ~REG_IF_RXDATAV;
efm32_spi_write32(ddata, ien, REG_IEN);
complete(&ddata->done);
}
spin_unlock(&ddata->lock);
return ret;
}
static irqreturn_t efm32_spi_txirq(int irq, void *data)
{
struct efm32_spi_ddata *ddata = data;
efm32_spi_vdbg(ddata,
"%s: txlen = %u, rxlen = %u, if=0x%08x, stat=0x%08x\n",
__func__, ddata->tx_len, ddata->rx_len,
efm32_spi_read32(ddata, REG_IF),
efm32_spi_read32(ddata, REG_STATUS));
spin_lock(&ddata->lock);
efm32_spi_filltx(ddata);
efm32_spi_vdbg(ddata, "%s: txlen = %u, rxlen = %u\n",
__func__, ddata->tx_len, ddata->rx_len);
if (!ddata->tx_len) {
u32 ien = efm32_spi_read32(ddata, REG_IEN);
ien &= ~REG_IF_TXBL;
efm32_spi_write32(ddata, ien, REG_IEN);
efm32_spi_vdbg(ddata, "disable TXBL\n");
}
spin_unlock(&ddata->lock);
return IRQ_HANDLED;
}
static const struct efm32_spi_pdata efm32_spi_pdata_default = {
.location = 1,
};
static u32 efm32_spi_get_configured_location(struct efm32_spi_ddata *ddata)
{
u32 reg = efm32_spi_read32(ddata, REG_ROUTE);
return (reg & REG_ROUTE_LOCATION__MASK) >> __ffs(REG_ROUTE_LOCATION__MASK);
}
static int efm32_spi_probe_dt(struct platform_device *pdev,
struct spi_master *master, struct efm32_spi_ddata *ddata)
{
struct device_node *np = pdev->dev.of_node;
u32 location;
int ret;
if (!np)
return 1;
ret = of_property_read_u32(np, "location", &location);
if (!ret) {
dev_dbg(&pdev->dev, "using location %u\n", location);
} else {
/* default to location configured in hardware */
location = efm32_spi_get_configured_location(ddata);
dev_info(&pdev->dev, "fall back to location %u\n", location);
}
ddata->pdata.location = location;
/* spi core takes care about the bus number using an alias */
master->bus_num = -1;
return 0;
}
static int efm32_spi_probe(struct platform_device *pdev)
{
struct efm32_spi_ddata *ddata;
struct resource *res;
int ret;
struct spi_master *master;
struct device_node *np = pdev->dev.of_node;
unsigned int num_cs, i;
num_cs = of_gpio_named_count(np, "cs-gpios");
master = spi_alloc_master(&pdev->dev,
sizeof(*ddata) + num_cs * sizeof(unsigned));
if (!master) {
dev_dbg(&pdev->dev,
"failed to allocate spi master controller\n");
return -ENOMEM;
}
platform_set_drvdata(pdev, master);
master->dev.of_node = pdev->dev.of_node;
master->num_chipselect = num_cs;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
ddata = spi_master_get_devdata(master);
ddata->bitbang.master = spi_master_get(master);
ddata->bitbang.chipselect = efm32_spi_chipselect;
ddata->bitbang.setup_transfer = efm32_spi_setup_transfer;
ddata->bitbang.txrx_bufs = efm32_spi_txrx_bufs;
spin_lock_init(&ddata->lock);
ddata->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(ddata->clk)) {
ret = PTR_ERR(ddata->clk);
dev_err(&pdev->dev, "failed to get clock: %d\n", ret);
goto err;
}
for (i = 0; i < num_cs; ++i) {
ret = of_get_named_gpio(np, "cs-gpios", i);
if (ret < 0) {
dev_err(&pdev->dev, "failed to get csgpio#%u (%d)\n",
i, ret);
goto err;
}
ddata->csgpio[i] = ret;
dev_dbg(&pdev->dev, "csgpio#%u = %u\n", i, ddata->csgpio[i]);
ret = devm_gpio_request_one(&pdev->dev, ddata->csgpio[i],
GPIOF_OUT_INIT_LOW, DRIVER_NAME);
if (ret < 0) {
dev_err(&pdev->dev,
"failed to configure csgpio#%u (%d)\n",
i, ret);
goto err;
}
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
ret = -ENODEV;
dev_err(&pdev->dev, "failed to determine base address\n");
goto err;
}
if (resource_size(res) < 60) {
ret = -EINVAL;
dev_err(&pdev->dev, "memory resource too small\n");
goto err;
}
ddata->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ddata->base)) {
ret = PTR_ERR(ddata->base);
goto err;
}
ret = platform_get_irq(pdev, 0);
if (ret <= 0) {
dev_err(&pdev->dev, "failed to get rx irq (%d)\n", ret);
goto err;
}
ddata->rxirq = ret;
ret = platform_get_irq(pdev, 1);
if (ret <= 0)
ret = ddata->rxirq + 1;
ddata->txirq = ret;
ret = clk_prepare_enable(ddata->clk);
if (ret < 0) {
dev_err(&pdev->dev, "failed to enable clock (%d)\n", ret);
goto err;
}
ret = efm32_spi_probe_dt(pdev, master, ddata);
if (ret > 0) {
/* not created by device tree */
const struct efm32_spi_pdata *pdata =
dev_get_platdata(&pdev->dev);
if (pdata)
ddata->pdata = *pdata;
else
ddata->pdata.location =
efm32_spi_get_configured_location(ddata);
master->bus_num = pdev->id;
} else if (ret < 0) {
goto err_disable_clk;
}
efm32_spi_write32(ddata, 0, REG_IEN);
efm32_spi_write32(ddata, REG_ROUTE_TXPEN | REG_ROUTE_RXPEN |
REG_ROUTE_CLKPEN |
REG_ROUTE_LOCATION(ddata->pdata.location), REG_ROUTE);
ret = request_irq(ddata->rxirq, efm32_spi_rxirq,
0, DRIVER_NAME " rx", ddata);
if (ret) {
dev_err(&pdev->dev, "failed to register rxirq (%d)\n", ret);
goto err_disable_clk;
}
ret = request_irq(ddata->txirq, efm32_spi_txirq,
0, DRIVER_NAME " tx", ddata);
if (ret) {
dev_err(&pdev->dev, "failed to register txirq (%d)\n", ret);
goto err_free_rx_irq;
}
ret = spi_bitbang_start(&ddata->bitbang);
if (ret) {
dev_err(&pdev->dev, "spi_bitbang_start failed (%d)\n", ret);
free_irq(ddata->txirq, ddata);
err_free_rx_irq:
free_irq(ddata->rxirq, ddata);
err_disable_clk:
clk_disable_unprepare(ddata->clk);
err:
spi_master_put(master);
kfree(master);
}
return ret;
}
static int efm32_spi_remove(struct platform_device *pdev)
{
struct spi_master *master = platform_get_drvdata(pdev);
struct efm32_spi_ddata *ddata = spi_master_get_devdata(master);
efm32_spi_write32(ddata, 0, REG_IEN);
free_irq(ddata->txirq, ddata);
free_irq(ddata->rxirq, ddata);
clk_disable_unprepare(ddata->clk);
spi_master_put(master);
kfree(master);
return 0;
}
static const struct of_device_id efm32_spi_dt_ids[] = {
{
.compatible = "efm32,spi",
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(of, efm32_spi_dt_ids);
static struct platform_driver efm32_spi_driver = {
.probe = efm32_spi_probe,
.remove = efm32_spi_remove,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = efm32_spi_dt_ids,
},
};
module_platform_driver(efm32_spi_driver);
MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>");
MODULE_DESCRIPTION("EFM32 SPI driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRIVER_NAME);
......@@ -26,7 +26,6 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/scatterlist.h>
#include <linux/spi/spi.h>
......@@ -70,19 +69,13 @@
/**
* struct ep93xx_spi - EP93xx SPI controller structure
* @lock: spinlock that protects concurrent accesses to fields @running,
* @current_msg and @msg_queue
* @pdev: pointer to platform device
* @clk: clock for the controller
* @regs_base: pointer to ioremap()'d registers
* @sspdr_phys: physical address of the SSPDR register
* @min_rate: minimum clock rate (in Hz) supported by the controller
* @max_rate: maximum clock rate (in Hz) supported by the controller
* @running: is the queue running
* @wq: workqueue used by the driver
* @msg_work: work that is queued for the driver
* @wait: wait here until given transfer is completed
* @msg_queue: queue for the messages
* @current_msg: message that is currently processed (or %NULL if none)
* @tx: current byte in transfer to transmit
* @rx: current byte in transfer to receive
......@@ -96,30 +89,15 @@
* @tx_sgt: sg table for TX transfers
* @zeropage: dummy page used as RX buffer when only TX buffer is passed in by
* the client
*
* This structure holds EP93xx SPI controller specific information. When
* @running is %true, driver accepts transfer requests from protocol drivers.
* @current_msg is used to hold pointer to the message that is currently
* processed. If @current_msg is %NULL, it means that no processing is going
* on.
*
* Most of the fields are only written once and they can be accessed without
* taking the @lock. Fields that are accessed concurrently are: @current_msg,
* @running, and @msg_queue.
*/
struct ep93xx_spi {
spinlock_t lock;
const struct platform_device *pdev;
struct clk *clk;
void __iomem *regs_base;
unsigned long sspdr_phys;
unsigned long min_rate;
unsigned long max_rate;
bool running;
struct workqueue_struct *wq;
struct work_struct msg_work;
struct completion wait;
struct list_head msg_queue;
struct spi_message *current_msg;
size_t tx;
size_t rx;
......@@ -136,50 +114,36 @@ struct ep93xx_spi {
/**
* struct ep93xx_spi_chip - SPI device hardware settings
* @spi: back pointer to the SPI device
* @rate: max rate in hz this chip supports
* @div_cpsr: cpsr (pre-scaler) divider
* @div_scr: scr divider
* @dss: bits per word (4 - 16 bits)
* @ops: private chip operations
*
* This structure is used to store hardware register specific settings for each
* SPI device. Settings are written to hardware by function
* ep93xx_spi_chip_setup().
*/
struct ep93xx_spi_chip {
const struct spi_device *spi;
unsigned long rate;
u8 div_cpsr;
u8 div_scr;
u8 dss;
struct ep93xx_spi_chip_ops *ops;
};
/* converts bits per word to CR0.DSS value */
#define bits_per_word_to_dss(bpw) ((bpw) - 1)
static inline void
ep93xx_spi_write_u8(const struct ep93xx_spi *espi, u16 reg, u8 value)
static void ep93xx_spi_write_u8(const struct ep93xx_spi *espi,
u16 reg, u8 value)
{
__raw_writeb(value, espi->regs_base + reg);
writeb(value, espi->regs_base + reg);
}
static inline u8
ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg)
static u8 ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg)
{
return __raw_readb(spi->regs_base + reg);
return readb(spi->regs_base + reg);
}
static inline void
ep93xx_spi_write_u16(const struct ep93xx_spi *espi, u16 reg, u16 value)
static void ep93xx_spi_write_u16(const struct ep93xx_spi *espi,
u16 reg, u16 value)
{
__raw_writew(value, espi->regs_base + reg);
writew(value, espi->regs_base + reg);
}
static inline u16
ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg)
static u16 ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg)
{
return __raw_readw(spi->regs_base + reg);
return readw(spi->regs_base + reg);
}
static int ep93xx_spi_enable(const struct ep93xx_spi *espi)
......@@ -230,17 +194,13 @@ static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi)
/**
* ep93xx_spi_calc_divisors() - calculates SPI clock divisors
* @espi: ep93xx SPI controller struct
* @chip: divisors are calculated for this chip
* @rate: desired SPI output clock rate
*
* Function calculates cpsr (clock pre-scaler) and scr divisors based on
* given @rate and places them to @chip->div_cpsr and @chip->div_scr. If,
* for some reason, divisors cannot be calculated nothing is stored and
* %-EINVAL is returned.
* @div_cpsr: pointer to return the cpsr (pre-scaler) divider
* @div_scr: pointer to return the scr divider
*/
static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
struct ep93xx_spi_chip *chip,
unsigned long rate)
unsigned long rate,
u8 *div_cpsr, u8 *div_scr)
{
unsigned long spi_clk_rate = clk_get_rate(espi->clk);
int cpsr, scr;
......@@ -248,7 +208,7 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
/*
* Make sure that max value is between values supported by the
* controller. Note that minimum value is already checked in
* ep93xx_spi_transfer().
* ep93xx_spi_transfer_one_message().
*/
rate = clamp(rate, espi->min_rate, espi->max_rate);
......@@ -263,8 +223,8 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
for (cpsr = 2; cpsr <= 254; cpsr += 2) {
for (scr = 0; scr <= 255; scr++) {
if ((spi_clk_rate / (cpsr * (scr + 1))) <= rate) {
chip->div_scr = (u8)scr;
chip->div_cpsr = (u8)cpsr;
*div_scr = (u8)scr;
*div_cpsr = (u8)cpsr;
return 0;
}
}
......@@ -319,72 +279,10 @@ static int ep93xx_spi_setup(struct spi_device *spi)
spi_set_ctldata(spi, chip);
}
if (spi->max_speed_hz != chip->rate) {
int err;
err = ep93xx_spi_calc_divisors(espi, chip, spi->max_speed_hz);
if (err != 0) {
spi_set_ctldata(spi, NULL);
kfree(chip);
return err;
}
chip->rate = spi->max_speed_hz;
}
chip->dss = bits_per_word_to_dss(spi->bits_per_word);
ep93xx_spi_cs_control(spi, false);
return 0;
}
/**
* ep93xx_spi_transfer() - queue message to be transferred
* @spi: target SPI device
* @msg: message to be transferred
*
* This function is called by SPI device drivers when they are going to transfer
* a new message. It simply puts the message in the queue and schedules
* workqueue to perform the actual transfer later on.
*
* Returns %0 on success and negative error in case of failure.
*/
static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *msg)
{
struct ep93xx_spi *espi = spi_master_get_devdata(spi->master);
struct spi_transfer *t;
unsigned long flags;
if (!msg || !msg->complete)
return -EINVAL;
/* first validate each transfer */
list_for_each_entry(t, &msg->transfers, transfer_list) {
if (t->speed_hz && t->speed_hz < espi->min_rate)
return -EINVAL;
}
/*
* Now that we own the message, let's initialize it so that it is
* suitable for us. We use @msg->status to signal whether there was
* error in transfer and @msg->state is used to hold pointer to the
* current transfer (or %NULL if no active current transfer).
*/
msg->state = NULL;
msg->status = 0;
msg->actual_length = 0;
spin_lock_irqsave(&espi->lock, flags);
if (!espi->running) {
spin_unlock_irqrestore(&espi->lock, flags);
return -ESHUTDOWN;
}
list_add_tail(&msg->queue, &espi->msg_queue);
queue_work(espi->wq, &espi->msg_work);
spin_unlock_irqrestore(&espi->lock, flags);
return 0;
}
/**
* ep93xx_spi_cleanup() - cleans up master controller specific state
* @spi: SPI device to cleanup
......@@ -409,39 +307,40 @@ static void ep93xx_spi_cleanup(struct spi_device *spi)
* ep93xx_spi_chip_setup() - configures hardware according to given @chip
* @espi: ep93xx SPI controller struct
* @chip: chip specific settings
*
* This function sets up the actual hardware registers with settings given in
* @chip. Note that no validation is done so make sure that callers validate
* settings before calling this.
* @speed_hz: transfer speed
* @bits_per_word: transfer bits_per_word
*/
static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi,
const struct ep93xx_spi_chip *chip)
static int ep93xx_spi_chip_setup(const struct ep93xx_spi *espi,
const struct ep93xx_spi_chip *chip,
u32 speed_hz, u8 bits_per_word)
{
u8 dss = bits_per_word_to_dss(bits_per_word);
u8 div_cpsr = 0;
u8 div_scr = 0;
u16 cr0;
int err;
cr0 = chip->div_scr << SSPCR0_SCR_SHIFT;
err = ep93xx_spi_calc_divisors(espi, speed_hz, &div_cpsr, &div_scr);
if (err)
return err;
cr0 = div_scr << SSPCR0_SCR_SHIFT;
cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT;
cr0 |= chip->dss;
cr0 |= dss;
dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n",
chip->spi->mode, chip->div_cpsr, chip->div_scr, chip->dss);
chip->spi->mode, div_cpsr, div_scr, dss);
dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0);
ep93xx_spi_write_u8(espi, SSPCPSR, chip->div_cpsr);
ep93xx_spi_write_u8(espi, SSPCPSR, div_cpsr);
ep93xx_spi_write_u16(espi, SSPCR0, cr0);
}
static inline int bits_per_word(const struct ep93xx_spi *espi)
{
struct spi_message *msg = espi->current_msg;
struct spi_transfer *t = msg->state;
return t->bits_per_word;
return 0;
}
static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t)
{
if (bits_per_word(espi) > 8) {
if (t->bits_per_word > 8) {
u16 tx_val = 0;
if (t->tx_buf)
......@@ -460,7 +359,7 @@ static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t)
static void ep93xx_do_read(struct ep93xx_spi *espi, struct spi_transfer *t)
{
if (bits_per_word(espi) > 8) {
if (t->bits_per_word > 8) {
u16 rx_val;
rx_val = ep93xx_spi_read_u16(espi, SSPDR);
......@@ -546,7 +445,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir)
size_t len = t->len;
int i, ret, nents;
if (bits_per_word(espi) > 8)
if (t->bits_per_word > 8)
buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
else
buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
......@@ -610,7 +509,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir)
}
if (WARN_ON(len)) {
dev_warn(&espi->pdev->dev, "len = %d expected 0!", len);
dev_warn(&espi->pdev->dev, "len = %zu expected 0!", len);
return ERR_PTR(-EINVAL);
}
......@@ -708,37 +607,16 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
struct spi_transfer *t)
{
struct ep93xx_spi_chip *chip = spi_get_ctldata(msg->spi);
int err;
msg->state = t;
/*
* Handle any transfer specific settings if needed. We use
* temporary chip settings here and restore original later when
* the transfer is finished.
*/
if (t->speed_hz || t->bits_per_word) {
struct ep93xx_spi_chip tmp_chip = *chip;
if (t->speed_hz) {
int err;
err = ep93xx_spi_calc_divisors(espi, &tmp_chip,
t->speed_hz);
if (err) {
dev_err(&espi->pdev->dev,
"failed to adjust speed\n");
msg->status = err;
return;
}
}
if (t->bits_per_word)
tmp_chip.dss = bits_per_word_to_dss(t->bits_per_word);
/*
* Set up temporary new hw settings for this transfer.
*/
ep93xx_spi_chip_setup(espi, &tmp_chip);
err = ep93xx_spi_chip_setup(espi, chip, t->speed_hz, t->bits_per_word);
if (err) {
dev_err(&espi->pdev->dev,
"failed to setup chip for transfer\n");
msg->status = err;
return;
}
espi->rx = 0;
......@@ -783,9 +661,6 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
ep93xx_spi_cs_control(msg->spi, true);
}
}
if (t->speed_hz || t->bits_per_word)
ep93xx_spi_chip_setup(espi, chip);
}
/*
......@@ -838,10 +713,8 @@ static void ep93xx_spi_process_message(struct ep93xx_spi *espi,
espi->fifo_level = 0;
/*
* Update SPI controller registers according to spi device and assert
* the chipselect.
* Assert the chipselect.
*/
ep93xx_spi_chip_setup(espi, spi_get_ctldata(msg->spi));
ep93xx_spi_cs_control(msg->spi, true);
list_for_each_entry(t, &msg->transfers, transfer_list) {
......@@ -858,50 +731,29 @@ static void ep93xx_spi_process_message(struct ep93xx_spi *espi,
ep93xx_spi_disable(espi);
}
#define work_to_espi(work) (container_of((work), struct ep93xx_spi, msg_work))
/**
* ep93xx_spi_work() - EP93xx SPI workqueue worker function
* @work: work struct
*
* Workqueue worker function. This function is called when there are new
* SPI messages to be processed. Message is taken out from the queue and then
* passed to ep93xx_spi_process_message().
*
* After message is transferred, protocol driver is notified by calling
* @msg->complete(). In case of error, @msg->status is set to negative error
* number, otherwise it contains zero (and @msg->actual_length is updated).
*/
static void ep93xx_spi_work(struct work_struct *work)
static int ep93xx_spi_transfer_one_message(struct spi_master *master,
struct spi_message *msg)
{
struct ep93xx_spi *espi = work_to_espi(work);
struct spi_message *msg;
struct ep93xx_spi *espi = spi_master_get_devdata(master);
struct spi_transfer *t;
spin_lock_irq(&espi->lock);
if (!espi->running || espi->current_msg ||
list_empty(&espi->msg_queue)) {
spin_unlock_irq(&espi->lock);
return;
/* first validate each transfer */
list_for_each_entry(t, &msg->transfers, transfer_list) {
if (t->speed_hz < espi->min_rate)
return -EINVAL;
}
msg = list_first_entry(&espi->msg_queue, struct spi_message, queue);
list_del_init(&msg->queue);
espi->current_msg = msg;
spin_unlock_irq(&espi->lock);
ep93xx_spi_process_message(espi, msg);
msg->state = NULL;
msg->status = 0;
msg->actual_length = 0;
/*
* Update the current message and re-schedule ourselves if there are
* more messages in the queue.
*/
spin_lock_irq(&espi->lock);
espi->current_msg = msg;
ep93xx_spi_process_message(espi, msg);
espi->current_msg = NULL;
if (espi->running && !list_empty(&espi->msg_queue))
queue_work(espi->wq, &espi->msg_work);
spin_unlock_irq(&espi->lock);
/* notify the protocol driver that we are done with this message */
msg->complete(msg->context);
spi_finalize_current_message(master);
return 0;
}
static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id)
......@@ -1022,16 +874,26 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
int irq;
int error;
info = pdev->dev.platform_data;
info = dev_get_platdata(&pdev->dev);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "failed to get irq resources\n");
return -EBUSY;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "unable to get iomem resource\n");
return -ENODEV;
}
master = spi_alloc_master(&pdev->dev, sizeof(*espi));
if (!master) {
dev_err(&pdev->dev, "failed to allocate spi master\n");
if (!master)
return -ENOMEM;
}
master->setup = ep93xx_spi_setup;
master->transfer = ep93xx_spi_transfer;
master->transfer_one_message = ep93xx_spi_transfer_one_message;
master->cleanup = ep93xx_spi_cleanup;
master->bus_num = pdev->id;
master->num_chipselect = info->num_chipselect;
......@@ -1042,14 +904,13 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
espi = spi_master_get_devdata(master);
espi->clk = clk_get(&pdev->dev, NULL);
espi->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(espi->clk)) {
dev_err(&pdev->dev, "unable to get spi clock\n");
error = PTR_ERR(espi->clk);
goto fail_release_master;
}
spin_lock_init(&espi->lock);
init_completion(&espi->wait);
/*
......@@ -1060,55 +921,31 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
espi->min_rate = clk_get_rate(espi->clk) / (254 * 256);
espi->pdev = pdev;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
error = -EBUSY;
dev_err(&pdev->dev, "failed to get irq resources\n");
goto fail_put_clock;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "unable to get iomem resource\n");
error = -ENODEV;
goto fail_put_clock;
}
espi->sspdr_phys = res->start + SSPDR;
espi->regs_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(espi->regs_base)) {
error = PTR_ERR(espi->regs_base);
goto fail_put_clock;
goto fail_release_master;
}
error = devm_request_irq(&pdev->dev, irq, ep93xx_spi_interrupt,
0, "ep93xx-spi", espi);
if (error) {
dev_err(&pdev->dev, "failed to request irq\n");
goto fail_put_clock;
goto fail_release_master;
}
if (info->use_dma && ep93xx_spi_setup_dma(espi))
dev_warn(&pdev->dev, "DMA setup failed. Falling back to PIO\n");
espi->wq = create_singlethread_workqueue("ep93xx_spid");
if (!espi->wq) {
dev_err(&pdev->dev, "unable to create workqueue\n");
error = -ENOMEM;
goto fail_free_dma;
}
INIT_WORK(&espi->msg_work, ep93xx_spi_work);
INIT_LIST_HEAD(&espi->msg_queue);
espi->running = true;
/* make sure that the hardware is disabled */
ep93xx_spi_write_u8(espi, SSPCR1, 0);
error = spi_register_master(master);
if (error) {
dev_err(&pdev->dev, "failed to register SPI master\n");
goto fail_free_queue;
goto fail_free_dma;
}
dev_info(&pdev->dev, "EP93xx SPI Controller at 0x%08lx irq %d\n",
......@@ -1116,12 +953,8 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
return 0;
fail_free_queue:
destroy_workqueue(espi->wq);
fail_free_dma:
ep93xx_spi_release_dma(espi);
fail_put_clock:
clk_put(espi->clk);
fail_release_master:
spi_master_put(master);
......@@ -1133,31 +966,7 @@ static int ep93xx_spi_remove(struct platform_device *pdev)
struct spi_master *master = platform_get_drvdata(pdev);
struct ep93xx_spi *espi = spi_master_get_devdata(master);
spin_lock_irq(&espi->lock);
espi->running = false;
spin_unlock_irq(&espi->lock);
destroy_workqueue(espi->wq);
/*
* Complete remaining messages with %-ESHUTDOWN status.
*/
spin_lock_irq(&espi->lock);
while (!list_empty(&espi->msg_queue)) {
struct spi_message *msg;
msg = list_first_entry(&espi->msg_queue,
struct spi_message, queue);
list_del_init(&msg->queue);
msg->status = -ESHUTDOWN;
spin_unlock_irq(&espi->lock);
msg->complete(msg->context);
spin_lock_irq(&espi->lock);
}
spin_unlock_irq(&espi->lock);
ep93xx_spi_release_dma(espi);
clk_put(espi->clk);
spi_unregister_master(master);
return 0;
......
/*
* drivers/spi/spi-fsl-dspi.c
*
* Copyright 2013 Freescale Semiconductor, Inc.
*
* Freescale DSPI driver
* This file contains a driver for the Freescale DSPI
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/of_device.h>
#define DRIVER_NAME "fsl-dspi"
#define TRAN_STATE_RX_VOID 0x01
#define TRAN_STATE_TX_VOID 0x02
#define TRAN_STATE_WORD_ODD_NUM 0x04
#define DSPI_FIFO_SIZE 4
#define SPI_MCR 0x00
#define SPI_MCR_MASTER (1 << 31)
#define SPI_MCR_PCSIS (0x3F << 16)
#define SPI_MCR_CLR_TXF (1 << 11)
#define SPI_MCR_CLR_RXF (1 << 10)
#define SPI_TCR 0x08
#define SPI_CTAR(x) (0x0c + (x * 4))
#define SPI_CTAR_FMSZ(x) (((x) & 0x0000000f) << 27)
#define SPI_CTAR_CPOL(x) ((x) << 26)
#define SPI_CTAR_CPHA(x) ((x) << 25)
#define SPI_CTAR_LSBFE(x) ((x) << 24)
#define SPI_CTAR_PCSSCR(x) (((x) & 0x00000003) << 22)
#define SPI_CTAR_PASC(x) (((x) & 0x00000003) << 20)
#define SPI_CTAR_PDT(x) (((x) & 0x00000003) << 18)
#define SPI_CTAR_PBR(x) (((x) & 0x00000003) << 16)
#define SPI_CTAR_CSSCK(x) (((x) & 0x0000000f) << 12)
#define SPI_CTAR_ASC(x) (((x) & 0x0000000f) << 8)
#define SPI_CTAR_DT(x) (((x) & 0x0000000f) << 4)
#define SPI_CTAR_BR(x) ((x) & 0x0000000f)
#define SPI_CTAR0_SLAVE 0x0c
#define SPI_SR 0x2c
#define SPI_SR_EOQF 0x10000000
#define SPI_RSER 0x30
#define SPI_RSER_EOQFE 0x10000000
#define SPI_PUSHR 0x34
#define SPI_PUSHR_CONT (1 << 31)
#define SPI_PUSHR_CTAS(x) (((x) & 0x00000007) << 28)
#define SPI_PUSHR_EOQ (1 << 27)
#define SPI_PUSHR_CTCNT (1 << 26)
#define SPI_PUSHR_PCS(x) (((1 << x) & 0x0000003f) << 16)
#define SPI_PUSHR_TXDATA(x) ((x) & 0x0000ffff)
#define SPI_PUSHR_SLAVE 0x34
#define SPI_POPR 0x38
#define SPI_POPR_RXDATA(x) ((x) & 0x0000ffff)
#define SPI_TXFR0 0x3c
#define SPI_TXFR1 0x40
#define SPI_TXFR2 0x44
#define SPI_TXFR3 0x48
#define SPI_RXFR0 0x7c
#define SPI_RXFR1 0x80
#define SPI_RXFR2 0x84
#define SPI_RXFR3 0x88
#define SPI_FRAME_BITS(bits) SPI_CTAR_FMSZ((bits) - 1)
#define SPI_FRAME_BITS_MASK SPI_CTAR_FMSZ(0xf)
#define SPI_FRAME_BITS_16 SPI_CTAR_FMSZ(0xf)
#define SPI_FRAME_BITS_8 SPI_CTAR_FMSZ(0x7)
#define SPI_CS_INIT 0x01
#define SPI_CS_ASSERT 0x02
#define SPI_CS_DROP 0x04
struct chip_data {
u32 mcr_val;
u32 ctar_val;
u16 void_write_data;
};
struct fsl_dspi {
struct spi_bitbang bitbang;
struct platform_device *pdev;
void *base;
int irq;
struct clk *clk;
struct spi_transfer *cur_transfer;
struct chip_data *cur_chip;
size_t len;
void *tx;
void *tx_end;
void *rx;
void *rx_end;
char dataflags;
u8 cs;
u16 void_write_data;
wait_queue_head_t waitq;
u32 waitflags;
};
static inline int is_double_byte_mode(struct fsl_dspi *dspi)
{
return ((readl(dspi->base + SPI_CTAR(dspi->cs)) & SPI_FRAME_BITS_MASK)
== SPI_FRAME_BITS(8)) ? 0 : 1;
}
static void set_bit_mode(struct fsl_dspi *dspi, unsigned char bits)
{
u32 temp;
temp = readl(dspi->base + SPI_CTAR(dspi->cs));
temp &= ~SPI_FRAME_BITS_MASK;
temp |= SPI_FRAME_BITS(bits);
writel(temp, dspi->base + SPI_CTAR(dspi->cs));
}
static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
unsigned long clkrate)
{
/* Valid baud rate pre-scaler values */
int pbr_tbl[4] = {2, 3, 5, 7};
int brs[16] = { 2, 4, 6, 8,
16, 32, 64, 128,
256, 512, 1024, 2048,
4096, 8192, 16384, 32768 };
int temp, i = 0, j = 0;
temp = clkrate / 2 / speed_hz;
for (i = 0; i < ARRAY_SIZE(pbr_tbl); i++)
for (j = 0; j < ARRAY_SIZE(brs); j++) {
if (pbr_tbl[i] * brs[j] >= temp) {
*pbr = i;
*br = j;
return;
}
}
pr_warn("Can not find valid buad rate,speed_hz is %d,clkrate is %ld\
,we use the max prescaler value.\n", speed_hz, clkrate);
*pbr = ARRAY_SIZE(pbr_tbl) - 1;
*br = ARRAY_SIZE(brs) - 1;
}
static int dspi_transfer_write(struct fsl_dspi *dspi)
{
int tx_count = 0;
int tx_word;
u16 d16;
u8 d8;
u32 dspi_pushr = 0;
int first = 1;
tx_word = is_double_byte_mode(dspi);
/* If we are in word mode, but only have a single byte to transfer
* then switch to byte mode temporarily. Will switch back at the
* end of the transfer.
*/
if (tx_word && (dspi->len == 1)) {
dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM;
set_bit_mode(dspi, 8);
tx_word = 0;
}
while (dspi->len && (tx_count < DSPI_FIFO_SIZE)) {
if (tx_word) {
if (dspi->len == 1)
break;
if (!(dspi->dataflags & TRAN_STATE_TX_VOID)) {
d16 = *(u16 *)dspi->tx;
dspi->tx += 2;
} else {
d16 = dspi->void_write_data;
}
dspi_pushr = SPI_PUSHR_TXDATA(d16) |
SPI_PUSHR_PCS(dspi->cs) |
SPI_PUSHR_CTAS(dspi->cs) |
SPI_PUSHR_CONT;
dspi->len -= 2;
} else {
if (!(dspi->dataflags & TRAN_STATE_TX_VOID)) {
d8 = *(u8 *)dspi->tx;
dspi->tx++;
} else {
d8 = (u8)dspi->void_write_data;
}
dspi_pushr = SPI_PUSHR_TXDATA(d8) |
SPI_PUSHR_PCS(dspi->cs) |
SPI_PUSHR_CTAS(dspi->cs) |
SPI_PUSHR_CONT;
dspi->len--;
}
if (dspi->len == 0 || tx_count == DSPI_FIFO_SIZE - 1) {
/* last transfer in the transfer */
dspi_pushr |= SPI_PUSHR_EOQ;
} else if (tx_word && (dspi->len == 1))
dspi_pushr |= SPI_PUSHR_EOQ;
if (first) {
first = 0;
dspi_pushr |= SPI_PUSHR_CTCNT; /* clear counter */
}
writel(dspi_pushr, dspi->base + SPI_PUSHR);
tx_count++;
}
return tx_count * (tx_word + 1);
}
static int dspi_transfer_read(struct fsl_dspi *dspi)
{
int rx_count = 0;
int rx_word = is_double_byte_mode(dspi);
u16 d;
while ((dspi->rx < dspi->rx_end)
&& (rx_count < DSPI_FIFO_SIZE)) {
if (rx_word) {
if ((dspi->rx_end - dspi->rx) == 1)
break;
d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR));
if (!(dspi->dataflags & TRAN_STATE_RX_VOID))
*(u16 *)dspi->rx = d;
dspi->rx += 2;
} else {
d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR));
if (!(dspi->dataflags & TRAN_STATE_RX_VOID))
*(u8 *)dspi->rx = d;
dspi->rx++;
}
rx_count++;
}
return rx_count;
}
static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t)
{
struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
dspi->cur_transfer = t;
dspi->cur_chip = spi_get_ctldata(spi);
dspi->cs = spi->chip_select;
dspi->void_write_data = dspi->cur_chip->void_write_data;
dspi->dataflags = 0;
dspi->tx = (void *)t->tx_buf;
dspi->tx_end = dspi->tx + t->len;
dspi->rx = t->rx_buf;
dspi->rx_end = dspi->rx + t->len;
dspi->len = t->len;
if (!dspi->rx)
dspi->dataflags |= TRAN_STATE_RX_VOID;
if (!dspi->tx)
dspi->dataflags |= TRAN_STATE_TX_VOID;
writel(dspi->cur_chip->mcr_val, dspi->base + SPI_MCR);
writel(dspi->cur_chip->ctar_val, dspi->base + SPI_CTAR(dspi->cs));
writel(SPI_RSER_EOQFE, dspi->base + SPI_RSER);
if (t->speed_hz)
writel(dspi->cur_chip->ctar_val,
dspi->base + SPI_CTAR(dspi->cs));
dspi_transfer_write(dspi);
if (wait_event_interruptible(dspi->waitq, dspi->waitflags))
dev_err(&dspi->pdev->dev, "wait transfer complete fail!\n");
dspi->waitflags = 0;
return t->len - dspi->len;
}
static void dspi_chipselect(struct spi_device *spi, int value)
{
struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
u32 pushr = readl(dspi->base + SPI_PUSHR);
switch (value) {
case BITBANG_CS_ACTIVE:
pushr |= SPI_PUSHR_CONT;
case BITBANG_CS_INACTIVE:
pushr &= ~SPI_PUSHR_CONT;
}
writel(pushr, dspi->base + SPI_PUSHR);
}
static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
{
struct chip_data *chip;
struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
unsigned char br = 0, pbr = 0, fmsz = 0;
/* Only alloc on first setup */
chip = spi_get_ctldata(spi);
if (chip == NULL) {
chip = kcalloc(1, sizeof(struct chip_data), GFP_KERNEL);
if (!chip)
return -ENOMEM;
}
chip->mcr_val = SPI_MCR_MASTER | SPI_MCR_PCSIS |
SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF;
if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) {
fmsz = spi->bits_per_word - 1;
} else {
pr_err("Invalid wordsize\n");
kfree(chip);
return -ENODEV;
}
chip->void_write_data = 0;
hz_to_spi_baud(&pbr, &br,
spi->max_speed_hz, clk_get_rate(dspi->clk));
chip->ctar_val = SPI_CTAR_FMSZ(fmsz)
| SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0)
| SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0)
| SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0)
| SPI_CTAR_PBR(pbr)
| SPI_CTAR_BR(br);
spi_set_ctldata(spi, chip);
return 0;
}
static int dspi_setup(struct spi_device *spi)
{
if (!spi->max_speed_hz)
return -EINVAL;
if (!spi->bits_per_word)
spi->bits_per_word = 8;
return dspi_setup_transfer(spi, NULL);
}
static irqreturn_t dspi_interrupt(int irq, void *dev_id)
{
struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id;
writel(SPI_SR_EOQF, dspi->base + SPI_SR);
dspi_transfer_read(dspi);
if (!dspi->len) {
if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM)
set_bit_mode(dspi, 16);
dspi->waitflags = 1;
wake_up_interruptible(&dspi->waitq);
} else {
dspi_transfer_write(dspi);
return IRQ_HANDLED;
}
return IRQ_HANDLED;
}
static struct of_device_id fsl_dspi_dt_ids[] = {
{ .compatible = "fsl,vf610-dspi", .data = NULL, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, fsl_dspi_dt_ids);
#ifdef CONFIG_PM_SLEEP
static int dspi_suspend(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct fsl_dspi *dspi = spi_master_get_devdata(master);
spi_master_suspend(master);
clk_disable_unprepare(dspi->clk);
return 0;
}
static int dspi_resume(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct fsl_dspi *dspi = spi_master_get_devdata(master);
clk_prepare_enable(dspi->clk);
spi_master_resume(master);
return 0;
}
#endif /* CONFIG_PM_SLEEP */
static const struct dev_pm_ops dspi_pm = {
SET_SYSTEM_SLEEP_PM_OPS(dspi_suspend, dspi_resume)
};
static int dspi_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct spi_master *master;
struct fsl_dspi *dspi;
struct resource *res;
int ret = 0, cs_num, bus_num;
master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi));
if (!master)
return -ENOMEM;
dspi = spi_master_get_devdata(master);
dspi->pdev = pdev;
dspi->bitbang.master = spi_master_get(master);
dspi->bitbang.chipselect = dspi_chipselect;
dspi->bitbang.setup_transfer = dspi_setup_transfer;
dspi->bitbang.txrx_bufs = dspi_txrx_transfer;
dspi->bitbang.master->setup = dspi_setup;
dspi->bitbang.master->dev.of_node = pdev->dev.of_node;
master->mode_bits = SPI_CPOL | SPI_CPHA;
master->bits_per_word_mask = SPI_BPW_MASK(4) | SPI_BPW_MASK(8) |
SPI_BPW_MASK(16);
ret = of_property_read_u32(np, "spi-num-chipselects", &cs_num);
if (ret < 0) {
dev_err(&pdev->dev, "can't get spi-num-chipselects\n");
goto out_master_put;
}
master->num_chipselect = cs_num;
ret = of_property_read_u32(np, "bus-num", &bus_num);
if (ret < 0) {
dev_err(&pdev->dev, "can't get bus-num\n");
goto out_master_put;
}
master->bus_num = bus_num;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "can't get platform resource\n");
ret = -EINVAL;
goto out_master_put;
}
dspi->base = devm_ioremap_resource(&pdev->dev, res);
if (!dspi->base) {
ret = -EINVAL;
goto out_master_put;
}
dspi->irq = platform_get_irq(pdev, 0);
if (dspi->irq < 0) {
dev_err(&pdev->dev, "can't get platform irq\n");
ret = dspi->irq;
goto out_master_put;
}
ret = devm_request_irq(&pdev->dev, dspi->irq, dspi_interrupt, 0,
pdev->name, dspi);
if (ret < 0) {
dev_err(&pdev->dev, "Unable to attach DSPI interrupt\n");
goto out_master_put;
}
dspi->clk = devm_clk_get(&pdev->dev, "dspi");
if (IS_ERR(dspi->clk)) {
ret = PTR_ERR(dspi->clk);
dev_err(&pdev->dev, "unable to get clock\n");
goto out_master_put;
}
clk_prepare_enable(dspi->clk);
init_waitqueue_head(&dspi->waitq);
platform_set_drvdata(pdev, dspi);
ret = spi_bitbang_start(&dspi->bitbang);
if (ret != 0) {
dev_err(&pdev->dev, "Problem registering DSPI master\n");
goto out_clk_put;
}
pr_info(KERN_INFO "Freescale DSPI master initialized\n");
return ret;
out_clk_put:
clk_disable_unprepare(dspi->clk);
out_master_put:
spi_master_put(master);
platform_set_drvdata(pdev, NULL);
return ret;
}
static int dspi_remove(struct platform_device *pdev)
{
struct fsl_dspi *dspi = platform_get_drvdata(pdev);
/* Disconnect from the SPI framework */
spi_bitbang_stop(&dspi->bitbang);
spi_master_put(dspi->bitbang.master);
return 0;
}
static struct platform_driver fsl_dspi_driver = {
.driver.name = DRIVER_NAME,
.driver.of_match_table = fsl_dspi_dt_ids,
.driver.owner = THIS_MODULE,
.driver.pm = &dspi_pm,
.probe = dspi_probe,
.remove = dspi_remove,
};
module_platform_driver(fsl_dspi_driver);
MODULE_DESCRIPTION("Freescale DSPI Controller Driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRIVER_NAME);
......@@ -584,7 +584,7 @@ static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
static struct spi_master * fsl_espi_probe(struct device *dev,
struct resource *mem, unsigned int irq)
{
struct fsl_spi_platform_data *pdata = dev->platform_data;
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct spi_master *master;
struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_espi_reg *reg_base;
......@@ -665,7 +665,7 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
static int of_fsl_espi_get_chipselects(struct device *dev)
{
struct device_node *np = dev->of_node;
struct fsl_spi_platform_data *pdata = dev->platform_data;
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
const u32 *prop;
int len;
......
......@@ -122,7 +122,7 @@ const char *mpc8xxx_spi_strmode(unsigned int flags)
int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
unsigned int irq)
{
struct fsl_spi_platform_data *pdata = dev->platform_data;
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct spi_master *master;
struct mpc8xxx_spi *mpc8xxx_spi;
int ret = 0;
......
......@@ -574,7 +574,7 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
static void fsl_spi_grlib_probe(struct device *dev)
{
struct fsl_spi_platform_data *pdata = dev->platform_data;
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct spi_master *master = dev_get_drvdata(dev);
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
struct fsl_spi_reg *reg_base = mpc8xxx_spi->reg_base;
......@@ -600,7 +600,7 @@ static void fsl_spi_grlib_probe(struct device *dev)
static struct spi_master * fsl_spi_probe(struct device *dev,
struct resource *mem, unsigned int irq)
{
struct fsl_spi_platform_data *pdata = dev->platform_data;
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct spi_master *master;
struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_spi_reg *reg_base;
......@@ -700,7 +700,8 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
static void fsl_spi_cs_control(struct spi_device *spi, bool on)
{
struct device *dev = spi->dev.parent->parent;
struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data);
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
u16 cs = spi->chip_select;
int gpio = pinfo->gpios[cs];
bool alow = pinfo->alow_flags[cs];
......@@ -711,7 +712,7 @@ static void fsl_spi_cs_control(struct spi_device *spi, bool on)
static int of_fsl_spi_get_chipselects(struct device *dev)
{
struct device_node *np = dev->of_node;
struct fsl_spi_platform_data *pdata = dev->platform_data;
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
int ngpios;
int i = 0;
......@@ -790,7 +791,7 @@ static int of_fsl_spi_get_chipselects(struct device *dev)
static int of_fsl_spi_free_chipselects(struct device *dev)
{
struct fsl_spi_platform_data *pdata = dev->platform_data;
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
int i;
......@@ -889,7 +890,7 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev)
int irq;
struct spi_master *master;
if (!pdev->dev.platform_data)
if (!dev_get_platdata(&pdev->dev))
return -EINVAL;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......
......@@ -420,7 +420,7 @@ static int spi_gpio_probe(struct platform_device *pdev)
if (status > 0)
use_of = 1;
pdata = pdev->dev.platform_data;
pdata = dev_get_platdata(&pdev->dev);
#ifdef GENERIC_BITBANG
if (!pdata || !pdata->num_chipselect)
return -ENODEV;
......@@ -506,7 +506,7 @@ static int spi_gpio_remove(struct platform_device *pdev)
int status;
spi_gpio = platform_get_drvdata(pdev);
pdata = pdev->dev.platform_data;
pdata = dev_get_platdata(&pdev->dev);
/* stop() unregisters child devices too */
status = spi_bitbang_stop(&spi_gpio->bitbang);
......
......@@ -619,6 +619,7 @@ static const struct of_device_id spi_imx_dt_ids[] = {
{ .compatible = "fsl,imx51-ecspi", .data = &imx51_ecspi_devtype_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, spi_imx_dt_ids);
static void spi_imx_chipselect(struct spi_device *spi, int is_active)
{
......@@ -796,10 +797,11 @@ static int spi_imx_probe(struct platform_device *pdev)
if (!gpio_is_valid(cs_gpio))
continue;
ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME);
ret = devm_gpio_request(&pdev->dev, spi_imx->chipselect[i],
DRIVER_NAME);
if (ret) {
dev_err(&pdev->dev, "can't get cs gpios\n");
goto out_gpio_free;
goto out_master_put;
}
}
......@@ -816,50 +818,44 @@ static int spi_imx_probe(struct platform_device *pdev)
(struct spi_imx_devtype_data *) pdev->id_entry->driver_data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "can't get platform resource\n");
ret = -ENOMEM;
goto out_gpio_free;
}
if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
dev_err(&pdev->dev, "request_mem_region failed\n");
ret = -EBUSY;
goto out_gpio_free;
}
spi_imx->base = ioremap(res->start, resource_size(res));
if (!spi_imx->base) {
ret = -EINVAL;
goto out_release_mem;
spi_imx->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(spi_imx->base)) {
ret = PTR_ERR(spi_imx->base);
goto out_master_put;
}
spi_imx->irq = platform_get_irq(pdev, 0);
if (spi_imx->irq < 0) {
ret = -EINVAL;
goto out_iounmap;
goto out_master_put;
}
ret = request_irq(spi_imx->irq, spi_imx_isr, 0, DRIVER_NAME, spi_imx);
ret = devm_request_irq(&pdev->dev, spi_imx->irq, spi_imx_isr, 0,
DRIVER_NAME, spi_imx);
if (ret) {
dev_err(&pdev->dev, "can't get irq%d: %d\n", spi_imx->irq, ret);
goto out_iounmap;
goto out_master_put;
}
spi_imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(spi_imx->clk_ipg)) {
ret = PTR_ERR(spi_imx->clk_ipg);
goto out_free_irq;
goto out_master_put;
}
spi_imx->clk_per = devm_clk_get(&pdev->dev, "per");
if (IS_ERR(spi_imx->clk_per)) {
ret = PTR_ERR(spi_imx->clk_per);
goto out_free_irq;
goto out_master_put;
}
clk_prepare_enable(spi_imx->clk_per);
clk_prepare_enable(spi_imx->clk_ipg);
ret = clk_prepare_enable(spi_imx->clk_per);
if (ret)
goto out_master_put;
ret = clk_prepare_enable(spi_imx->clk_ipg);
if (ret)
goto out_put_per;
spi_imx->spi_clk = clk_get_rate(spi_imx->clk_per);
......@@ -879,47 +875,27 @@ static int spi_imx_probe(struct platform_device *pdev)
return ret;
out_clk_put:
clk_disable_unprepare(spi_imx->clk_per);
clk_disable_unprepare(spi_imx->clk_ipg);
out_free_irq:
free_irq(spi_imx->irq, spi_imx);
out_iounmap:
iounmap(spi_imx->base);
out_release_mem:
release_mem_region(res->start, resource_size(res));
out_gpio_free:
while (--i >= 0) {
if (gpio_is_valid(spi_imx->chipselect[i]))
gpio_free(spi_imx->chipselect[i]);
}
out_put_per:
clk_disable_unprepare(spi_imx->clk_per);
out_master_put:
spi_master_put(master);
kfree(master);
return ret;
}
static int spi_imx_remove(struct platform_device *pdev)
{
struct spi_master *master = platform_get_drvdata(pdev);
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
int i;
spi_bitbang_stop(&spi_imx->bitbang);
writel(0, spi_imx->base + MXC_CSPICTRL);
clk_disable_unprepare(spi_imx->clk_per);
clk_disable_unprepare(spi_imx->clk_ipg);
free_irq(spi_imx->irq, spi_imx);
iounmap(spi_imx->base);
for (i = 0; i < master->num_chipselect; i++)
if (gpio_is_valid(spi_imx->chipselect[i]))
gpio_free(spi_imx->chipselect[i]);
clk_disable_unprepare(spi_imx->clk_per);
spi_master_put(master);
release_mem_region(res->start, resource_size(res));
return 0;
}
......
......@@ -38,7 +38,8 @@ struct mpc512x_psc_spi {
struct mpc512x_psc_fifo __iomem *fifo;
unsigned int irq;
u8 bits_per_word;
u32 mclk;
struct clk *clk_mclk;
u32 mclk_rate;
struct completion txisrdone;
};
......@@ -72,6 +73,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
struct mpc52xx_psc __iomem *psc = mps->psc;
u32 sicr;
u32 ccr;
int speed;
u16 bclkdiv;
sicr = in_be32(&psc->sicr);
......@@ -95,10 +97,10 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
ccr = in_be32(&psc->ccr);
ccr &= 0xFF000000;
if (cs->speed_hz)
bclkdiv = (mps->mclk / cs->speed_hz) - 1;
else
bclkdiv = (mps->mclk / 1000000) - 1; /* default 1MHz */
speed = cs->speed_hz;
if (!speed)
speed = 1000000; /* default 1MHz */
bclkdiv = (mps->mclk_rate / speed) - 1;
ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
out_be32(&psc->ccr, ccr);
......@@ -386,19 +388,11 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
{
struct mpc52xx_psc __iomem *psc = mps->psc;
struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
struct clk *spiclk;
int ret = 0;
char name[32];
u32 sicr;
u32 ccr;
int speed;
u16 bclkdiv;
sprintf(name, "psc%d_mclk", master->bus_num);
spiclk = clk_get(&master->dev, name);
clk_enable(spiclk);
mps->mclk = clk_get_rate(spiclk);
clk_put(spiclk);
/* Reset the PSC into a known state */
out_8(&psc->command, MPC52xx_PSC_RST_RX);
out_8(&psc->command, MPC52xx_PSC_RST_TX);
......@@ -425,7 +419,8 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
ccr = in_be32(&psc->ccr);
ccr &= 0xFF000000;
bclkdiv = (mps->mclk / 1000000) - 1; /* default 1MHz */
speed = 1000000; /* default 1MHz */
bclkdiv = (mps->mclk_rate / speed) - 1;
ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
out_be32(&psc->ccr, ccr);
......@@ -445,7 +440,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
mps->bits_per_word = 8;
return ret;
return 0;
}
static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
......@@ -474,11 +469,14 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
u32 size, unsigned int irq,
s16 bus_num)
{
struct fsl_spi_platform_data *pdata = dev->platform_data;
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct mpc512x_psc_spi *mps;
struct spi_master *master;
int ret;
void *tempp;
int psc_num;
char clk_name[16];
struct clk *clk;
master = spi_alloc_master(dev, sizeof *mps);
if (master == NULL)
......@@ -521,16 +519,29 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
goto free_master;
init_completion(&mps->txisrdone);
psc_num = master->bus_num;
snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
clk = devm_clk_get(dev, clk_name);
if (IS_ERR(clk))
goto free_irq;
ret = clk_prepare_enable(clk);
if (ret)
goto free_irq;
mps->clk_mclk = clk;
mps->mclk_rate = clk_get_rate(clk);
ret = mpc512x_psc_spi_port_config(master, mps);
if (ret < 0)
goto free_irq;
goto free_clock;
ret = spi_register_master(master);
if (ret < 0)
goto free_irq;
goto free_clock;
return ret;
free_clock:
clk_disable_unprepare(mps->clk_mclk);
free_irq:
free_irq(mps->irq, mps);
free_master:
......@@ -547,6 +558,7 @@ static int mpc512x_psc_spi_do_remove(struct device *dev)
struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
spi_unregister_master(master);
clk_disable_unprepare(mps->clk_mclk);
free_irq(mps->irq, mps);
if (mps->psc)
iounmap(mps->psc);
......
......@@ -366,7 +366,7 @@ static irqreturn_t mpc52xx_psc_spi_isr(int irq, void *dev_id)
static int mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
u32 size, unsigned int irq, s16 bus_num)
{
struct fsl_spi_platform_data *pdata = dev->platform_data;
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct mpc52xx_psc_spi *mps;
struct spi_master *master;
int ret;
......
......@@ -67,13 +67,8 @@ static int mxs_spi_setup_transfer(struct spi_device *dev,
{
struct mxs_spi *spi = spi_master_get_devdata(dev->master);
struct mxs_ssp *ssp = &spi->ssp;
uint8_t bits_per_word;
uint32_t hz = 0;
bits_per_word = dev->bits_per_word;
if (t && t->bits_per_word)
bits_per_word = t->bits_per_word;
hz = dev->max_speed_hz;
if (t && t->speed_hz)
hz = min(hz, t->speed_hz);
......@@ -513,7 +508,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq_err = platform_get_irq(pdev, 0);
if (!iores || irq_err < 0)
if (irq_err < 0)
return -EINVAL;
base = devm_ioremap_resource(&pdev->dev, iores);
......@@ -563,25 +558,31 @@ static int mxs_spi_probe(struct platform_device *pdev)
goto out_master_free;
}
clk_prepare_enable(ssp->clk);
ret = clk_prepare_enable(ssp->clk);
if (ret)
goto out_dma_release;
clk_set_rate(ssp->clk, clk_freq);
ssp->clk_rate = clk_get_rate(ssp->clk) / 1000;
stmp_reset_block(ssp->base);
ret = stmp_reset_block(ssp->base);
if (ret)
goto out_disable_clk;
platform_set_drvdata(pdev, master);
ret = spi_register_master(master);
if (ret) {
dev_err(&pdev->dev, "Cannot register SPI master, %d\n", ret);
goto out_free_dma;
goto out_disable_clk;
}
return 0;
out_free_dma:
dma_release_channel(ssp->dmach);
out_disable_clk:
clk_disable_unprepare(ssp->clk);
out_dma_release:
dma_release_channel(ssp->dmach);
out_master_free:
spi_master_put(master);
return ret;
......@@ -598,11 +599,8 @@ static int mxs_spi_remove(struct platform_device *pdev)
ssp = &spi->ssp;
spi_unregister_master(master);
dma_release_channel(ssp->dmach);
clk_disable_unprepare(ssp->clk);
dma_release_channel(ssp->dmach);
spi_master_put(master);
return 0;
......
......@@ -174,17 +174,6 @@ static void nuc900_spi_gobusy(struct nuc900_spi *hw)
spin_unlock_irqrestore(&hw->lock, flags);
}
static int nuc900_spi_setupxfer(struct spi_device *spi,
struct spi_transfer *t)
{
return 0;
}
static int nuc900_spi_setup(struct spi_device *spi)
{
return 0;
}
static inline unsigned int hw_txbyte(struct nuc900_spi *hw, int count)
{
return hw->tx ? hw->tx[count] : 0;
......@@ -361,7 +350,7 @@ static int nuc900_spi_probe(struct platform_device *pdev)
hw = spi_master_get_devdata(master);
hw->master = spi_master_get(master);
hw->pdata = pdev->dev.platform_data;
hw->pdata = dev_get_platdata(&pdev->dev);
hw->dev = &pdev->dev;
if (hw->pdata == NULL) {
......@@ -373,14 +362,12 @@ static int nuc900_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, hw);
init_completion(&hw->done);
master->mode_bits = SPI_MODE_0;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
master->num_chipselect = hw->pdata->num_cs;
master->bus_num = hw->pdata->bus_num;
hw->bitbang.master = hw->master;
hw->bitbang.setup_transfer = nuc900_spi_setupxfer;
hw->bitbang.chipselect = nuc900_spi_chipsel;
hw->bitbang.txrx_bufs = nuc900_spi_txrx;
hw->bitbang.master->setup = nuc900_spi_setup;
hw->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (hw->res == NULL) {
......
......@@ -285,7 +285,7 @@ static int tiny_spi_of_probe(struct platform_device *pdev)
static int tiny_spi_probe(struct platform_device *pdev)
{
struct tiny_spi_platform_data *platp = pdev->dev.platform_data;
struct tiny_spi_platform_data *platp = dev_get_platdata(&pdev->dev);
struct tiny_spi *hw;
struct spi_master *master;
struct resource *res;
......@@ -315,15 +315,11 @@ static int tiny_spi_probe(struct platform_device *pdev)
/* find and map our resources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
goto exit_busy;
if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
pdev->name))
goto exit_busy;
hw->base = devm_ioremap_nocache(&pdev->dev, res->start,
resource_size(res));
if (!hw->base)
goto exit_busy;
hw->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(hw->base)) {
err = PTR_ERR(hw->base);
goto exit;
}
/* irq is optional */
hw->irq = platform_get_irq(pdev, 0);
if (hw->irq >= 0) {
......@@ -337,8 +333,10 @@ static int tiny_spi_probe(struct platform_device *pdev)
if (platp) {
hw->gpio_cs_count = platp->gpio_cs_count;
hw->gpio_cs = platp->gpio_cs;
if (platp->gpio_cs_count && !platp->gpio_cs)
goto exit_busy;
if (platp->gpio_cs_count && !platp->gpio_cs) {
err = -EBUSY;
goto exit;
}
hw->freq = platp->freq;
hw->baudwidth = platp->baudwidth;
} else {
......@@ -365,8 +363,6 @@ static int tiny_spi_probe(struct platform_device *pdev)
exit_gpio:
while (i-- > 0)
gpio_free(hw->gpio_cs[i]);
exit_busy:
err = -EBUSY;
exit:
spi_master_put(master);
return err;
......
......@@ -28,7 +28,6 @@
#define OCTEON_SPI_MAX_CLOCK_HZ 16000000
struct octeon_spi {
struct spi_master *my_master;
u64 register_base;
u64 last_cfg;
u64 cs_enax;
......@@ -64,7 +63,6 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
unsigned int speed_hz;
int mode;
bool cpha, cpol;
int bits_per_word;
const u8 *tx_buf;
u8 *rx_buf;
int len;
......@@ -76,12 +74,9 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
mode = msg_setup->mode;
cpha = mode & SPI_CPHA;
cpol = mode & SPI_CPOL;
bits_per_word = msg_setup->bits_per_word;
if (xfer->speed_hz)
speed_hz = xfer->speed_hz;
if (xfer->bits_per_word)
bits_per_word = xfer->bits_per_word;
if (speed_hz > OCTEON_SPI_MAX_CLOCK_HZ)
speed_hz = OCTEON_SPI_MAX_CLOCK_HZ;
......@@ -166,19 +161,6 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
return xfer->len;
}
static int octeon_spi_validate_bpw(struct spi_device *spi, u32 speed)
{
switch (speed) {
case 8:
break;
default:
dev_err(&spi->dev, "Error: %d bits per word not supported\n",
speed);
return -EINVAL;
}
return 0;
}
static int octeon_spi_transfer_one_message(struct spi_master *master,
struct spi_message *msg)
{
......@@ -196,15 +178,6 @@ static int octeon_spi_transfer_one_message(struct spi_master *master,
goto err;
}
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
if (xfer->bits_per_word) {
status = octeon_spi_validate_bpw(msg->spi,
xfer->bits_per_word);
if (status)
goto err;
}
}
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
bool last_xfer = &xfer->transfer_list == msg->transfers.prev;
int r = octeon_spi_do_transfer(p, msg, xfer, last_xfer);
......@@ -236,14 +209,9 @@ static struct octeon_spi_setup *octeon_spi_new_setup(struct spi_device *spi)
static int octeon_spi_setup(struct spi_device *spi)
{
int r;
struct octeon_spi_setup *new_setup;
struct octeon_spi_setup *old_setup = spi_get_ctldata(spi);
r = octeon_spi_validate_bpw(spi, spi->bits_per_word);
if (r)
return r;
new_setup = octeon_spi_new_setup(spi);
if (!new_setup)
return -ENOMEM;
......@@ -261,14 +229,8 @@ static void octeon_spi_cleanup(struct spi_device *spi)
kfree(old_setup);
}
static int octeon_spi_nop_transfer_hardware(struct spi_master *master)
{
return 0;
}
static int octeon_spi_probe(struct platform_device *pdev)
{
struct resource *res_mem;
struct spi_master *master;
struct octeon_spi *p;
......@@ -278,8 +240,7 @@ static int octeon_spi_probe(struct platform_device *pdev)
if (!master)
return -ENOMEM;
p = spi_master_get_devdata(master);
platform_set_drvdata(pdev, p);
p->my_master = master;
platform_set_drvdata(pdev, master);
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......@@ -307,9 +268,8 @@ static int octeon_spi_probe(struct platform_device *pdev)
master->setup = octeon_spi_setup;
master->cleanup = octeon_spi_cleanup;
master->prepare_transfer_hardware = octeon_spi_nop_transfer_hardware;
master->transfer_one_message = octeon_spi_transfer_one_message;
master->unprepare_transfer_hardware = octeon_spi_nop_transfer_hardware;
master->bits_per_word_mask = SPI_BPW_MASK(8);
master->dev.of_node = pdev->dev.of_node;
err = spi_register_master(master);
......@@ -328,10 +288,11 @@ static int octeon_spi_probe(struct platform_device *pdev)
static int octeon_spi_remove(struct platform_device *pdev)
{
struct octeon_spi *p = platform_get_drvdata(pdev);
struct spi_master *master = platform_get_drvdata(pdev);
struct octeon_spi *p = spi_master_get_devdata(master);
u64 register_base = p->register_base;
spi_unregister_master(p->my_master);
spi_unregister_master(master);
/* Clear the CSENA* and put everything in a known state. */
cvmx_write_csr(register_base + OCTEON_SPI_CFG, 0);
......
......@@ -83,11 +83,6 @@
#define SPI_SHUTDOWN 1
struct omap1_spi100k {
struct work_struct work;
/* lock protects queue and registers */
spinlock_t lock;
struct list_head msg_queue;
struct spi_master *master;
struct clk *ick;
struct clk *fck;
......@@ -104,8 +99,6 @@ struct omap1_spi100k_cs {
int word_len;
};
static struct workqueue_struct *omap1_spi100k_wq;
#define MOD_REG_BIT(val, mask, set) do { \
if (set) \
val |= mask; \
......@@ -310,170 +303,102 @@ static int omap1_spi100k_setup(struct spi_device *spi)
spi100k_open(spi->master);
clk_enable(spi100k->ick);
clk_enable(spi100k->fck);
clk_prepare_enable(spi100k->ick);
clk_prepare_enable(spi100k->fck);
ret = omap1_spi100k_setup_transfer(spi, NULL);
clk_disable(spi100k->ick);
clk_disable(spi100k->fck);
clk_disable_unprepare(spi100k->ick);
clk_disable_unprepare(spi100k->fck);
return ret;
}
static void omap1_spi100k_work(struct work_struct *work)
static int omap1_spi100k_prepare_hardware(struct spi_master *master)
{
struct omap1_spi100k *spi100k;
int status = 0;
struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
spi100k = container_of(work, struct omap1_spi100k, work);
spin_lock_irq(&spi100k->lock);
clk_prepare_enable(spi100k->ick);
clk_prepare_enable(spi100k->fck);
clk_enable(spi100k->ick);
clk_enable(spi100k->fck);
return 0;
}
/* We only enable one channel at a time -- the one whose message is
* at the head of the queue -- although this controller would gladly
* arbitrate among multiple channels. This corresponds to "single
* channel" master mode. As a side effect, we need to manage the
* chipselect with the FORCE bit ... CS != channel enable.
*/
while (!list_empty(&spi100k->msg_queue)) {
struct spi_message *m;
struct spi_device *spi;
struct spi_transfer *t = NULL;
int cs_active = 0;
struct omap1_spi100k_cs *cs;
int par_override = 0;
m = container_of(spi100k->msg_queue.next, struct spi_message,
queue);
list_del_init(&m->queue);
spin_unlock_irq(&spi100k->lock);
spi = m->spi;
cs = spi->controller_state;
list_for_each_entry(t, &m->transfers, transfer_list) {
if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
status = -EINVAL;
static int omap1_spi100k_transfer_one_message(struct spi_master *master,
struct spi_message *m)
{
struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
struct spi_device *spi = m->spi;
struct spi_transfer *t = NULL;
int cs_active = 0;
int par_override = 0;
int status = 0;
list_for_each_entry(t, &m->transfers, transfer_list) {
if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
status = -EINVAL;
break;
}
if (par_override || t->speed_hz || t->bits_per_word) {
par_override = 1;
status = omap1_spi100k_setup_transfer(spi, t);
if (status < 0)
break;
}
if (par_override || t->speed_hz || t->bits_per_word) {
par_override = 1;
status = omap1_spi100k_setup_transfer(spi, t);
if (status < 0)
break;
if (!t->speed_hz && !t->bits_per_word)
par_override = 0;
}
if (!t->speed_hz && !t->bits_per_word)
par_override = 0;
}
if (!cs_active) {
omap1_spi100k_force_cs(spi100k, 1);
cs_active = 1;
}
if (!cs_active) {
omap1_spi100k_force_cs(spi100k, 1);
cs_active = 1;
}
if (t->len) {
unsigned count;
if (t->len) {
unsigned count;
count = omap1_spi100k_txrx_pio(spi, t);
m->actual_length += count;
count = omap1_spi100k_txrx_pio(spi, t);
m->actual_length += count;
if (count != t->len) {
status = -EIO;
break;
}
if (count != t->len) {
status = -EIO;
break;
}
}
if (t->delay_usecs)
udelay(t->delay_usecs);
if (t->delay_usecs)
udelay(t->delay_usecs);
/* ignore the "leave it on after last xfer" hint */
/* ignore the "leave it on after last xfer" hint */
if (t->cs_change) {
omap1_spi100k_force_cs(spi100k, 0);
cs_active = 0;
}
}
/* Restore defaults if they were overriden */
if (par_override) {
par_override = 0;
status = omap1_spi100k_setup_transfer(spi, NULL);
if (t->cs_change) {
omap1_spi100k_force_cs(spi100k, 0);
cs_active = 0;
}
}
if (cs_active)
omap1_spi100k_force_cs(spi100k, 0);
/* Restore defaults if they were overriden */
if (par_override) {
par_override = 0;
status = omap1_spi100k_setup_transfer(spi, NULL);
}
m->status = status;
m->complete(m->context);
if (cs_active)
omap1_spi100k_force_cs(spi100k, 0);
spin_lock_irq(&spi100k->lock);
}
m->status = status;
clk_disable(spi100k->ick);
clk_disable(spi100k->fck);
spin_unlock_irq(&spi100k->lock);
spi_finalize_current_message(master);
if (status < 0)
printk(KERN_WARNING "spi transfer failed with %d\n", status);
return status;
}
static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m)
static int omap1_spi100k_unprepare_hardware(struct spi_master *master)
{
struct omap1_spi100k *spi100k;
unsigned long flags;
struct spi_transfer *t;
m->actual_length = 0;
m->status = -EINPROGRESS;
spi100k = spi_master_get_devdata(spi->master);
/* Don't accept new work if we're shutting down */
if (spi100k->state == SPI_SHUTDOWN)
return -ESHUTDOWN;
/* reject invalid messages and transfers */
if (list_empty(&m->transfers) || !m->complete)
return -EINVAL;
list_for_each_entry(t, &m->transfers, transfer_list) {
const void *tx_buf = t->tx_buf;
void *rx_buf = t->rx_buf;
unsigned len = t->len;
if (t->speed_hz > OMAP1_SPI100K_MAX_FREQ
|| (len && !(rx_buf || tx_buf))) {
dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
t->speed_hz,
len,
tx_buf ? "tx" : "",
rx_buf ? "rx" : "",
t->bits_per_word);
return -EINVAL;
}
if (t->speed_hz && t->speed_hz < OMAP1_SPI100K_MAX_FREQ/(1<<16)) {
dev_dbg(&spi->dev, "%d Hz max exceeds %d\n",
t->speed_hz,
OMAP1_SPI100K_MAX_FREQ/(1<<16));
return -EINVAL;
}
}
spin_lock_irqsave(&spi100k->lock, flags);
list_add_tail(&m->queue, &spi100k->msg_queue);
queue_work(omap1_spi100k_wq, &spi100k->work);
spin_unlock_irqrestore(&spi100k->lock, flags);
struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
return 0;
}
clk_disable_unprepare(spi100k->ick);
clk_disable_unprepare(spi100k->fck);
static int omap1_spi100k_reset(struct omap1_spi100k *spi100k)
{
return 0;
}
......@@ -496,11 +421,15 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
master->bus_num = pdev->id;
master->setup = omap1_spi100k_setup;
master->transfer = omap1_spi100k_transfer;
master->transfer_one_message = omap1_spi100k_transfer_one_message;
master->prepare_transfer_hardware = omap1_spi100k_prepare_hardware;
master->unprepare_transfer_hardware = omap1_spi100k_unprepare_hardware;
master->cleanup = NULL;
master->num_chipselect = 2;
master->mode_bits = MODEBITS;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
master->min_speed_hz = OMAP1_SPI100K_MAX_FREQ/(1<<16);
master->max_speed_hz = OMAP1_SPI100K_MAX_FREQ;
platform_set_drvdata(pdev, master);
......@@ -512,42 +441,31 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
* You should allocate this with ioremap() before initializing
* the SPI.
*/
spi100k->base = (void __iomem *) pdev->dev.platform_data;
INIT_WORK(&spi100k->work, omap1_spi100k_work);
spi100k->base = (void __iomem *)dev_get_platdata(&pdev->dev);
spin_lock_init(&spi100k->lock);
INIT_LIST_HEAD(&spi100k->msg_queue);
spi100k->ick = clk_get(&pdev->dev, "ick");
spi100k->ick = devm_clk_get(&pdev->dev, "ick");
if (IS_ERR(spi100k->ick)) {
dev_dbg(&pdev->dev, "can't get spi100k_ick\n");
status = PTR_ERR(spi100k->ick);
goto err1;
goto err;
}
spi100k->fck = clk_get(&pdev->dev, "fck");
spi100k->fck = devm_clk_get(&pdev->dev, "fck");
if (IS_ERR(spi100k->fck)) {
dev_dbg(&pdev->dev, "can't get spi100k_fck\n");
status = PTR_ERR(spi100k->fck);
goto err2;
goto err;
}
if (omap1_spi100k_reset(spi100k) < 0)
goto err3;
status = spi_register_master(master);
if (status < 0)
goto err3;
goto err;
spi100k->state = SPI_RUNNING;
return status;
err3:
clk_put(spi100k->fck);
err2:
clk_put(spi100k->ick);
err1:
err:
spi_master_put(master);
return status;
}
......@@ -557,33 +475,14 @@ static int omap1_spi100k_remove(struct platform_device *pdev)
struct spi_master *master;
struct omap1_spi100k *spi100k;
struct resource *r;
unsigned limit = 500;
unsigned long flags;
int status = 0;
master = platform_get_drvdata(pdev);
spi100k = spi_master_get_devdata(master);
spin_lock_irqsave(&spi100k->lock, flags);
spi100k->state = SPI_SHUTDOWN;
while (!list_empty(&spi100k->msg_queue) && limit--) {
spin_unlock_irqrestore(&spi100k->lock, flags);
msleep(10);
spin_lock_irqsave(&spi100k->lock, flags);
}
if (!list_empty(&spi100k->msg_queue))
status = -EBUSY;
spin_unlock_irqrestore(&spi100k->lock, flags);
if (status != 0)
return status;
clk_put(spi100k->fck);
clk_put(spi100k->ick);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spi_unregister_master(master);
......@@ -596,30 +495,11 @@ static struct platform_driver omap1_spi100k_driver = {
.name = "omap1_spi100k",
.owner = THIS_MODULE,
},
.probe = omap1_spi100k_probe,
.remove = omap1_spi100k_remove,
};
static int __init omap1_spi100k_init(void)
{
omap1_spi100k_wq = create_singlethread_workqueue(
omap1_spi100k_driver.driver.name);
if (omap1_spi100k_wq == NULL)
return -1;
return platform_driver_probe(&omap1_spi100k_driver, omap1_spi100k_probe);
}
static void __exit omap1_spi100k_exit(void)
{
platform_driver_unregister(&omap1_spi100k_driver);
destroy_workqueue(omap1_spi100k_wq);
}
module_init(omap1_spi100k_init);
module_exit(omap1_spi100k_exit);
module_platform_driver(omap1_spi100k_driver);
MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver");
MODULE_AUTHOR("Fabrice Crohas <fcrohas@gmail.com>");
......
......@@ -335,23 +335,6 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
}
static int omap2_prepare_transfer(struct spi_master *master)
{
struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
pm_runtime_get_sync(mcspi->dev);
return 0;
}
static int omap2_unprepare_transfer(struct spi_master *master)
{
struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
pm_runtime_mark_last_busy(mcspi->dev);
pm_runtime_put_autosuspend(mcspi->dev);
return 0;
}
static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
{
unsigned long timeout;
......@@ -1318,8 +1301,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
master->setup = omap2_mcspi_setup;
master->prepare_transfer_hardware = omap2_prepare_transfer;
master->unprepare_transfer_hardware = omap2_unprepare_transfer;
master->auto_runtime_pm = true;
master->transfer_one_message = omap2_mcspi_transfer_one_message;
master->cleanup = omap2_mcspi_cleanup;
master->dev.of_node = node;
......@@ -1340,7 +1322,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
if (of_get_property(node, "ti,pindir-d0-out-d1-in", NULL))
mcspi->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
} else {
pdata = pdev->dev.platform_data;
pdata = dev_get_platdata(&pdev->dev);
master->num_chipselect = pdata->num_cs;
if (pdev->id != -1)
master->bus_num = pdev->id;
......
......@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/clk.h>
#include <linux/sizes.h>
#include <asm/unaligned.h>
#define DRIVER_NAME "orion_spi"
......@@ -446,30 +447,22 @@ static int orion_spi_probe(struct platform_device *pdev)
spi->min_speed = DIV_ROUND_UP(tclk_hz, 30);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (r == NULL) {
status = -ENODEV;
spi->base = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(spi->base)) {
status = PTR_ERR(spi->base);
goto out_rel_clk;
}
if (!request_mem_region(r->start, resource_size(r),
dev_name(&pdev->dev))) {
status = -EBUSY;
goto out_rel_clk;
}
spi->base = ioremap(r->start, SZ_1K);
if (orion_spi_reset(spi) < 0)
goto out_rel_mem;
goto out_rel_clk;
master->dev.of_node = pdev->dev.of_node;
status = spi_register_master(master);
if (status < 0)
goto out_rel_mem;
goto out_rel_clk;
return status;
out_rel_mem:
release_mem_region(r->start, resource_size(r));
out_rel_clk:
clk_disable_unprepare(spi->clk);
clk_put(spi->clk);
......@@ -482,7 +475,6 @@ static int orion_spi_probe(struct platform_device *pdev)
static int orion_spi_remove(struct platform_device *pdev)
{
struct spi_master *master;
struct resource *r;
struct orion_spi *spi;
master = platform_get_drvdata(pdev);
......@@ -491,9 +483,6 @@ static int orion_spi_remove(struct platform_device *pdev)
clk_disable_unprepare(spi->clk);
clk_put(spi->clk);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(r->start, resource_size(r));
spi_unregister_master(master);
return 0;
......
......@@ -1555,18 +1555,6 @@ static int pl022_transfer_one_message(struct spi_master *master,
return 0;
}
static int pl022_prepare_transfer_hardware(struct spi_master *master)
{
struct pl022 *pl022 = spi_master_get_devdata(master);
/*
* Just make sure we have all we need to run the transfer by syncing
* with the runtime PM framework.
*/
pm_runtime_get_sync(&pl022->adev->dev);
return 0;
}
static int pl022_unprepare_transfer_hardware(struct spi_master *master)
{
struct pl022 *pl022 = spi_master_get_devdata(master);
......@@ -1575,13 +1563,6 @@ static int pl022_unprepare_transfer_hardware(struct spi_master *master)
writew((readw(SSP_CR1(pl022->virtbase)) &
(~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase));
if (pl022->master_info->autosuspend_delay > 0) {
pm_runtime_mark_last_busy(&pl022->adev->dev);
pm_runtime_put_autosuspend(&pl022->adev->dev);
} else {
pm_runtime_put(&pl022->adev->dev);
}
return 0;
}
......@@ -2091,7 +2072,8 @@ pl022_platform_data_dt_get(struct device *dev)
static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
{
struct device *dev = &adev->dev;
struct pl022_ssp_controller *platform_info = adev->dev.platform_data;
struct pl022_ssp_controller *platform_info =
dev_get_platdata(&adev->dev);
struct spi_master *master;
struct pl022 *pl022 = NULL; /*Data for this driver */
struct device_node *np = adev->dev.of_node;
......@@ -2139,7 +2121,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
master->num_chipselect = num_cs;
master->cleanup = pl022_cleanup;
master->setup = pl022_setup;
master->prepare_transfer_hardware = pl022_prepare_transfer_hardware;
master->auto_runtime_pm = true;
master->transfer_one_message = pl022_transfer_one_message;
master->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware;
master->rt = platform_info->rt;
......@@ -2193,8 +2175,8 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
status = -ENOMEM;
goto err_no_ioremap;
}
printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
adev->res.start, pl022->virtbase);
printk(KERN_INFO "pl022: mapped registers from %pa to %p\n",
&adev->res.start, pl022->virtbase);
pl022->clk = devm_clk_get(&adev->dev, NULL);
if (IS_ERR(pl022->clk)) {
......
......@@ -69,6 +69,8 @@ MODULE_ALIAS("platform:pxa2xx-spi");
#define LPSS_TX_HITHRESH_DFLT 224
/* Offset from drv_data->lpss_base */
#define GENERAL_REG 0x08
#define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
#define SSP_REG 0x0c
#define SPI_CS_CONTROL 0x18
#define SPI_CS_CONTROL_SW_MODE BIT(0)
......@@ -142,8 +144,13 @@ static void lpss_ssp_setup(struct driver_data *drv_data)
__lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value);
/* Enable multiblock DMA transfers */
if (drv_data->master_info->enable_dma)
if (drv_data->master_info->enable_dma) {
__lpss_ssp_write_priv(drv_data, SSP_REG, 1);
value = __lpss_ssp_read_priv(drv_data, GENERAL_REG);
value |= GENERAL_REG_RXTO_HOLDOFF_DISABLE;
__lpss_ssp_write_priv(drv_data, GENERAL_REG, value);
}
}
static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable)
......@@ -804,14 +811,6 @@ static int pxa2xx_spi_transfer_one_message(struct spi_master *master,
return 0;
}
static int pxa2xx_spi_prepare_transfer(struct spi_master *master)
{
struct driver_data *drv_data = spi_master_get_devdata(master);
pm_runtime_get_sync(&drv_data->pdev->dev);
return 0;
}
static int pxa2xx_spi_unprepare_transfer(struct spi_master *master)
{
struct driver_data *drv_data = spi_master_get_devdata(master);
......@@ -820,8 +819,6 @@ static int pxa2xx_spi_unprepare_transfer(struct spi_master *master)
write_SSCR0(read_SSCR0(drv_data->ioaddr) & ~SSCR0_SSE,
drv_data->ioaddr);
pm_runtime_mark_last_busy(&drv_data->pdev->dev);
pm_runtime_put_autosuspend(&drv_data->pdev->dev);
return 0;
}
......@@ -1134,8 +1131,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
master->cleanup = cleanup;
master->setup = setup;
master->transfer_one_message = pxa2xx_spi_transfer_one_message;
master->prepare_transfer_hardware = pxa2xx_spi_prepare_transfer;
master->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer;
master->auto_runtime_pm = true;
drv_data->ssp_type = ssp->type;
drv_data->null_dma_buf = (u32 *)PTR_ALIGN(&drv_data[1], DMA_ALIGNMENT);
......
......@@ -564,8 +564,12 @@ static void rspi_work(struct work_struct *work)
unsigned long flags;
int ret;
spin_lock_irqsave(&rspi->lock, flags);
while (!list_empty(&rspi->queue)) {
while (1) {
spin_lock_irqsave(&rspi->lock, flags);
if (list_empty(&rspi->queue)) {
spin_unlock_irqrestore(&rspi->lock, flags);
break;
}
mesg = list_entry(rspi->queue.next, struct spi_message, queue);
list_del_init(&mesg->queue);
spin_unlock_irqrestore(&rspi->lock, flags);
......@@ -595,8 +599,6 @@ static void rspi_work(struct work_struct *work)
mesg->status = 0;
mesg->complete(mesg->context);
spin_lock_irqsave(&rspi->lock, flags);
}
return;
......@@ -664,12 +666,13 @@ static irqreturn_t rspi_irq(int irq, void *_sr)
static int rspi_request_dma(struct rspi_data *rspi,
struct platform_device *pdev)
{
struct rspi_plat_data *rspi_pd = pdev->dev.platform_data;
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;
struct dma_slave_config cfg;
int ret;
if (!rspi_pd)
if (!res || !rspi_pd)
return 0; /* The driver assumes no error. */
rspi->dma_width_16bit = rspi_pd->dma_width_16bit;
......@@ -683,6 +686,8 @@ static int rspi_request_dma(struct rspi_data *rspi,
if (rspi->chan_rx) {
cfg.slave_id = rspi_pd->dma_rx_id;
cfg.direction = DMA_DEV_TO_MEM;
cfg.dst_addr = 0;
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");
......@@ -698,6 +703,8 @@ static int rspi_request_dma(struct rspi_data *rspi,
if (rspi->chan_tx) {
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");
......@@ -719,7 +726,7 @@ static void rspi_release_dma(struct rspi_data *rspi)
static int rspi_remove(struct platform_device *pdev)
{
struct rspi_data *rspi = platform_get_drvdata(pdev);
struct rspi_data *rspi = spi_master_get(platform_get_drvdata(pdev));
spi_unregister_master(rspi->master);
rspi_release_dma(rspi);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -130,7 +130,7 @@ static int sh_sci_spi_probe(struct platform_device *dev)
sp = spi_master_get_devdata(master);
platform_set_drvdata(dev, sp);
sp->info = dev->dev.platform_data;
sp->info = dev_get_platdata(&dev->dev);
/* setup spi bitbang adaptor */
sp->bitbang.master = spi_master_get(master);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册