1
0
Fork 0

spi: Updates for v3.14

A respun version of the merges for the pull request previously sent with
 a few additional fixes.  The last two merges were fixed up by hand since
 the branches have moved on and currently have the prior merge in them.
 
 Quite a busy release for the SPI subsystem, mostly in cleanups big and
 small scattered through the stack rather than anything else:
 
  - New driver for the Broadcom BC63xx HSSPI controller.
  - Fix duplicate device registration for ACPI.
  - Conversion of s3c64xx to DMAEngine (this pulls in platform and DMA
    changes upon which the transiton depends).
  - Some small optimisations to reduce the amount of time we hold locks
    in the datapath, eliminate some redundant checks and the size of a
    spi_transfer.
  - Lots of fixes, cleanups and general enhancements to drivers,
    especially the rspi and Atmel drivers.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJS4RZvAAoJELSic+t+oim9XKAP/00WcCARVzqWmzZYhW2nCqVw
 zRu/DEC+RFlvUSOrwx5SojZNCJekKrsbJuzvapXKIj+SL5+wDm2gUo188s+J8e5V
 mXA9CGb2+tQUgzuQzKZ82kf5WT1a/VpgdVqxZ2EGBHqdJwMV6cG20YneTd9/A0ar
 QbD9Ikon07cE6j8sp/HKxzSnER+3ii4OTJPJCXkNPHiDE9xkA/FR4qy/DksC2hpy
 y6IHCNGA3yHB/8bC7hxUKabOBwPpvQlGELTLHKTVy4umoAE0/aYSjwMdE67SbqXg
 mxDLcDjacNb4ga9hfWiYdZOKRdYiljt1zXksKHldp+R654YFTSVGmYipMoc0l52b
 jyycLM9ZjQ8Q74ySY+BIdZ4RDKFg4QajDhd/sIJtI354HLdoJCQa82j3luj6/Ewu
 JSlI4EGZUjOWPZb72kkrwj0LFBT5k639fMmLPDCLLlg5sUvx2afFl96s9Z25mFGj
 JzgwhjBIcF8AmllLTEpS6cP8MOBeThJ79gTxmbH60tsWxil2yCS4etg+h6GFo7g9
 GBXL9UF63Q6t9Mg8/0oACDs/YyMMbFImi6p20B+Pr0QZiltiTSSc4Z7eo4gG4UYh
 m4svqZcMG8w6csMAMb6I6a9+EojERPt53bZayasnnX/e5HsXJah4qop9Pjrma4ed
 PQHMx8ivWztwyqqjoYTz
 =CbUw
 -----END PGP SIGNATURE-----

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

Pull spi updates from Mark Brown:
 "A respun version of the merges for the pull request previously sent
  with a few additional fixes.  The last two merges were fixed up by
  hand since the branches have moved on and currently have the prior
  merge in them.

  Quite a busy release for the SPI subsystem, mostly in cleanups big and
  small scattered through the stack rather than anything else:

   - New driver for the Broadcom BC63xx HSSPI controller
   - Fix duplicate device registration for ACPI
   - Conversion of s3c64xx to DMAEngine (this pulls in platform and DMA
     changes upon which the transiton depends)
   - Some small optimisations to reduce the amount of time we hold locks
     in the datapath, eliminate some redundant checks and the size of a
     spi_transfer
   - Lots of fixes, cleanups and general enhancements to drivers,
     especially the rspi and Atmel drivers"

* tag 'spi-v3.14-2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (112 commits)
  spi: core: Fix transfer failure when master->transfer_one returns positive value
  spi: Correct set_cs() documentation
  spi: Clarify transfer_one() w.r.t. spi_finalize_current_transfer()
  spi: Spelling s/finised/finished/
  spi: sc18is602: Convert to use bits_per_word_mask
  spi: Remove duplicate code to set default bits_per_word setting
  spi/pxa2xx: fix compilation warning when !CONFIG_PM_SLEEP
  spi: clps711x: Add MODULE_ALIAS to support module auto-loading
  spi: rspi: Add missing clk_disable() calls in error and cleanup paths
  spi: rspi: Spelling s/transmition/transmission/
  spi: rspi: Add support for specifying CPHA/CPOL
  spi/pxa2xx: initialize DMA channels to -1 to prevent inadvertent match
  spi: rspi: Add more QSPI register documentation
  spi: rspi: Add more RSPI register documentation
  spi: rspi: Remove dependency on DMAE for SHMOBILE
  spi/s3c64xx: Correct indentation
  spi: sh: Use spi_sh_clear_bit() instead of open-coded
  spi: bitbang: Grammar s/make to make/to make/
  spi: sh-hspi: Spelling s/recive/receive/
  spi: core: Improve tx/rx_nbits check comments
  ...
wifi-calibration
Linus Torvalds 2014-01-25 13:20:36 -08:00
commit 2d2e7d195b
53 changed files with 1495 additions and 1523 deletions

View File

@ -67,7 +67,7 @@ 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
via the SPI master node cs-gpios property.
SPI example for an MPC5200 SPI bus:
spi@f00 {

View File

@ -3,6 +3,11 @@ TI QSPI controller.
Required properties:
- compatible : should be "ti,dra7xxx-qspi" or "ti,am4372-qspi".
- reg: Should contain QSPI registers location and length.
- reg-names: Should contain the resource reg names.
- qspi_base: Qspi configuration register Address space
- qspi_mmap: Memory mapped Address space
- (optional) qspi_ctrlmod: Control module Address space
- interrupts: should contain the qspi interrupt number.
- #address-cells, #size-cells : Must be present if the device has sub-nodes
- ti,hwmods: Name of the hwmod associated to the QSPI
@ -14,7 +19,8 @@ Example:
qspi: qspi@4b300000 {
compatible = "ti,dra7xxx-qspi";
reg = <0x4b300000 0x100>;
reg = <0x47900000 0x100>, <0x30000000 0x3ffffff>;
reg-names = "qspi_base", "qspi_mmap";
#address-cells = <1>;
#size-cells = <0>;
spi-max-frequency = <25000000>;

View File

@ -34,7 +34,7 @@ SPI slave functions are usually not interoperable between vendors
- It may also be used to stream data in either direction (half duplex),
or both of them at the same time (full duplex).
- Some devices may use eight bit words. Others may different word
- Some devices may use eight bit words. Others may use different word
lengths, such as streams of 12-bit or 20-bit digital samples.
- Words are usually sent with their most significant bit (MSB) first,
@ -121,7 +121,7 @@ active. So the master must set the clock to inactive before selecting
a slave, and the slave can tell the chosen polarity by sampling the
clock level when its select line goes active. That's why many devices
support for example both modes 0 and 3: they don't care about polarity,
and alway clock data in/out on rising clock edges.
and always clock data in/out on rising clock edges.
How do these driver programming interfaces work?
@ -139,7 +139,7 @@ a command and then reading its response.
There are two types of SPI driver, here called:
Controller drivers ... controllers may be built in to System-On-Chip
Controller drivers ... controllers may be built into System-On-Chip
processors, and often support both Master and Slave roles.
These drivers touch hardware registers and may use DMA.
Or they can be PIO bitbangers, needing just GPIO pins.
@ -548,7 +548,7 @@ SPI MASTER METHODS
DEPRECATED METHODS
master->transfer(struct spi_device *spi, struct spi_message *message)
This must not sleep. Its responsibility is arrange that the
This must not sleep. Its responsibility is to arrange that the
transfer happens and its complete() callback is issued. The two
will normally happen later, after other transfers complete, and
if the controller is idle it will need to be kickstarted. This

View File

@ -1,13 +0,0 @@
/* linux/arch/arm/plat-samsung/include/plat/fiq.h
*
* Copyright (c) 2009 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* Header file for S3C24XX CPU FIQ support
*
* 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.
*/
extern int s3c24xx_set_fiq(unsigned int irq, bool on);

View File

@ -118,6 +118,13 @@ config SPI_BCM63XX
help
Enable support for the SPI controller on the Broadcom BCM63xx SoCs.
config SPI_BCM63XX_HSSPI
tristate "Broadcom BCM63XX HS SPI controller driver"
depends on BCM63XX || COMPILE_TEST
help
This enables support for the High Speed SPI controller present on
newer Broadcom BCM63XX SoCs.
config SPI_BITBANG
tristate "Utilities for Bitbanging SPI masters"
help
@ -159,7 +166,6 @@ config SPI_DAVINCI
tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
depends on ARCH_DAVINCI || ARCH_KEYSTONE
select SPI_BITBANG
select TI_EDMA
help
SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
@ -301,6 +307,7 @@ config SPI_OMAP_UWIRE
config SPI_OMAP24XX
tristate "McSPI driver for OMAP"
depends on ARM || ARM64 || AVR32 || HEXAGON || MIPS || SH
depends on ARCH_OMAP2PLUS || COMPILE_TEST
help
SPI master controller for OMAP24XX and later Multichannel SPI
@ -370,7 +377,7 @@ config SPI_PXA2XX_PCI
config SPI_RSPI
tristate "Renesas RSPI controller"
depends on (SUPERH || ARCH_SHMOBILE) && SH_DMAE_BASE
depends on (SUPERH && SH_DMAE_BASE) || ARCH_SHMOBILE
help
SPI driver for Renesas RSPI blocks.
@ -407,7 +414,8 @@ config SPI_SC18IS602
config SPI_SH_MSIOF
tristate "SuperH MSIOF SPI controller"
depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
depends on HAVE_CLK
depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
select SPI_BITBANG
help
SPI driver for SuperH and SH Mobile MSIOF blocks.

View File

@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o
obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
obj-$(CONFIG_SPI_BCM63XX_HSSPI) += spi-bcm63xx-hsspi.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

View File

@ -220,8 +220,6 @@ static int altera_spi_probe(struct platform_device *pdev)
/* setup the state for the bitbang driver */
hw->bitbang.master = master;
if (!hw->bitbang.master)
return err;
hw->bitbang.chipselect = altera_spi_chipsel;
hw->bitbang.txrx_bufs = altera_spi_txrx;

View File

@ -243,21 +243,21 @@ static int ath79_spi_probe(struct platform_device *pdev)
goto err_put_master;
}
sp->base = ioremap(r->start, resource_size(r));
sp->base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
if (!sp->base) {
ret = -ENXIO;
goto err_put_master;
}
sp->clk = clk_get(&pdev->dev, "ahb");
sp->clk = devm_clk_get(&pdev->dev, "ahb");
if (IS_ERR(sp->clk)) {
ret = PTR_ERR(sp->clk);
goto err_unmap;
goto err_put_master;
}
ret = clk_enable(sp->clk);
if (ret)
goto err_clk_put;
goto err_put_master;
rate = DIV_ROUND_UP(clk_get_rate(sp->clk), MHZ);
if (!rate) {
@ -280,10 +280,6 @@ err_disable:
ath79_spi_disable(sp);
err_clk_disable:
clk_disable(sp->clk);
err_clk_put:
clk_put(sp->clk);
err_unmap:
iounmap(sp->base);
err_put_master:
spi_master_put(sp->bitbang.master);
@ -297,8 +293,6 @@ static int ath79_spi_remove(struct platform_device *pdev)
spi_bitbang_stop(&sp->bitbang);
ath79_spi_disable(sp);
clk_disable(sp->clk);
clk_put(sp->clk);
iounmap(sp->base);
spi_master_put(sp->bitbang.master);
return 0;

File diff suppressed because it is too large Load Diff

View File

@ -347,8 +347,8 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
clk_prepare_enable(bs->clk);
err = request_irq(bs->irq, bcm2835_spi_interrupt, 0,
dev_name(&pdev->dev), master);
err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0,
dev_name(&pdev->dev), master);
if (err) {
dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
goto out_clk_disable;
@ -361,13 +361,11 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
err = devm_spi_register_master(&pdev->dev, master);
if (err) {
dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
goto out_free_irq;
goto out_clk_disable;
}
return 0;
out_free_irq:
free_irq(bs->irq, master);
out_clk_disable:
clk_disable_unprepare(bs->clk);
out_master_put:
@ -380,8 +378,6 @@ static int bcm2835_spi_remove(struct platform_device *pdev)
struct spi_master *master = platform_get_drvdata(pdev);
struct bcm2835_spi *bs = spi_master_get_devdata(master);
free_irq(bs->irq, master);
/* Clear FIFOs, and disable the HW block */
bcm2835_wr(bs, BCM2835_SPI_CS,
BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);

View File

@ -0,0 +1,475 @@
/*
* Broadcom BCM63XX High Speed SPI Controller driver
*
* Copyright 2000-2010 Broadcom Corporation
* Copyright 2012-2013 Jonas Gorski <jogo@openwrt.org>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/spi/spi.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
#define HSSPI_GLOBAL_CTRL_REG 0x0
#define GLOBAL_CTRL_CS_POLARITY_SHIFT 0
#define GLOBAL_CTRL_CS_POLARITY_MASK 0x000000ff
#define GLOBAL_CTRL_PLL_CLK_CTRL_SHIFT 8
#define GLOBAL_CTRL_PLL_CLK_CTRL_MASK 0x0000ff00
#define GLOBAL_CTRL_CLK_GATE_SSOFF BIT(16)
#define GLOBAL_CTRL_CLK_POLARITY BIT(17)
#define GLOBAL_CTRL_MOSI_IDLE BIT(18)
#define HSSPI_GLOBAL_EXT_TRIGGER_REG 0x4
#define HSSPI_INT_STATUS_REG 0x8
#define HSSPI_INT_STATUS_MASKED_REG 0xc
#define HSSPI_INT_MASK_REG 0x10
#define HSSPI_PINGx_CMD_DONE(i) BIT((i * 8) + 0)
#define HSSPI_PINGx_RX_OVER(i) BIT((i * 8) + 1)
#define HSSPI_PINGx_TX_UNDER(i) BIT((i * 8) + 2)
#define HSSPI_PINGx_POLL_TIMEOUT(i) BIT((i * 8) + 3)
#define HSSPI_PINGx_CTRL_INVAL(i) BIT((i * 8) + 4)
#define HSSPI_INT_CLEAR_ALL 0xff001f1f
#define HSSPI_PINGPONG_COMMAND_REG(x) (0x80 + (x) * 0x40)
#define PINGPONG_CMD_COMMAND_MASK 0xf
#define PINGPONG_COMMAND_NOOP 0
#define PINGPONG_COMMAND_START_NOW 1
#define PINGPONG_COMMAND_START_TRIGGER 2
#define PINGPONG_COMMAND_HALT 3
#define PINGPONG_COMMAND_FLUSH 4
#define PINGPONG_CMD_PROFILE_SHIFT 8
#define PINGPONG_CMD_SS_SHIFT 12
#define HSSPI_PINGPONG_STATUS_REG(x) (0x84 + (x) * 0x40)
#define HSSPI_PROFILE_CLK_CTRL_REG(x) (0x100 + (x) * 0x20)
#define CLK_CTRL_FREQ_CTRL_MASK 0x0000ffff
#define CLK_CTRL_SPI_CLK_2X_SEL BIT(14)
#define CLK_CTRL_ACCUM_RST_ON_LOOP BIT(15)
#define HSSPI_PROFILE_SIGNAL_CTRL_REG(x) (0x104 + (x) * 0x20)
#define SIGNAL_CTRL_LATCH_RISING BIT(12)
#define SIGNAL_CTRL_LAUNCH_RISING BIT(13)
#define SIGNAL_CTRL_ASYNC_INPUT_PATH BIT(16)
#define HSSPI_PROFILE_MODE_CTRL_REG(x) (0x108 + (x) * 0x20)
#define MODE_CTRL_MULTIDATA_RD_STRT_SHIFT 8
#define MODE_CTRL_MULTIDATA_WR_STRT_SHIFT 12
#define MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT 16
#define MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT 18
#define MODE_CTRL_MODE_3WIRE BIT(20)
#define MODE_CTRL_PREPENDBYTE_CNT_SHIFT 24
#define HSSPI_FIFO_REG(x) (0x200 + (x) * 0x200)
#define HSSPI_OP_CODE_SHIFT 13
#define HSSPI_OP_SLEEP (0 << HSSPI_OP_CODE_SHIFT)
#define HSSPI_OP_READ_WRITE (1 << HSSPI_OP_CODE_SHIFT)
#define HSSPI_OP_WRITE (2 << HSSPI_OP_CODE_SHIFT)
#define HSSPI_OP_READ (3 << HSSPI_OP_CODE_SHIFT)
#define HSSPI_OP_SETIRQ (4 << HSSPI_OP_CODE_SHIFT)
#define HSSPI_BUFFER_LEN 512
#define HSSPI_OPCODE_LEN 2
#define HSSPI_MAX_PREPEND_LEN 15
#define HSSPI_MAX_SYNC_CLOCK 30000000
#define HSSPI_BUS_NUM 1 /* 0 is legacy SPI */
struct bcm63xx_hsspi {
struct completion done;
struct mutex bus_mutex;
struct platform_device *pdev;
struct clk *clk;
void __iomem *regs;
u8 __iomem *fifo;
u32 speed_hz;
u8 cs_polarity;
};
static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned cs,
bool active)
{
u32 reg;
mutex_lock(&bs->bus_mutex);
reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
reg &= ~BIT(cs);
if (active == !(bs->cs_polarity & BIT(cs)))
reg |= BIT(cs);
__raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
mutex_unlock(&bs->bus_mutex);
}
static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs,
struct spi_device *spi, int hz)
{
unsigned profile = spi->chip_select;
u32 reg;
reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz));
__raw_writel(CLK_CTRL_ACCUM_RST_ON_LOOP | reg,
bs->regs + HSSPI_PROFILE_CLK_CTRL_REG(profile));
reg = __raw_readl(bs->regs + HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
if (hz > HSSPI_MAX_SYNC_CLOCK)
reg |= SIGNAL_CTRL_ASYNC_INPUT_PATH;
else
reg &= ~SIGNAL_CTRL_ASYNC_INPUT_PATH;
__raw_writel(reg, bs->regs + HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
mutex_lock(&bs->bus_mutex);
/* setup clock polarity */
reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
reg &= ~GLOBAL_CTRL_CLK_POLARITY;
if (spi->mode & SPI_CPOL)
reg |= GLOBAL_CTRL_CLK_POLARITY;
__raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
mutex_unlock(&bs->bus_mutex);
}
static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)
{
struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
unsigned chip_select = spi->chip_select;
u16 opcode = 0;
int pending = t->len;
int step_size = HSSPI_BUFFER_LEN;
const u8 *tx = t->tx_buf;
u8 *rx = t->rx_buf;
bcm63xx_hsspi_set_clk(bs, spi, t->speed_hz);
bcm63xx_hsspi_set_cs(bs, spi->chip_select, true);
if (tx && rx)
opcode = HSSPI_OP_READ_WRITE;
else if (tx)
opcode = HSSPI_OP_WRITE;
else if (rx)
opcode = HSSPI_OP_READ;
if (opcode != HSSPI_OP_READ)
step_size -= HSSPI_OPCODE_LEN;
__raw_writel(0 << MODE_CTRL_PREPENDBYTE_CNT_SHIFT |
2 << MODE_CTRL_MULTIDATA_WR_STRT_SHIFT |
2 << MODE_CTRL_MULTIDATA_RD_STRT_SHIFT | 0xff,
bs->regs + HSSPI_PROFILE_MODE_CTRL_REG(chip_select));
while (pending > 0) {
int curr_step = min_t(int, step_size, pending);
init_completion(&bs->done);
if (tx) {
memcpy_toio(bs->fifo + HSSPI_OPCODE_LEN, tx, curr_step);
tx += curr_step;
}
__raw_writew(opcode | curr_step, bs->fifo);
/* enable interrupt */
__raw_writel(HSSPI_PINGx_CMD_DONE(0),
bs->regs + HSSPI_INT_MASK_REG);
/* start the transfer */
__raw_writel(!chip_select << PINGPONG_CMD_SS_SHIFT |
chip_select << PINGPONG_CMD_PROFILE_SHIFT |
PINGPONG_COMMAND_START_NOW,
bs->regs + HSSPI_PINGPONG_COMMAND_REG(0));
if (wait_for_completion_timeout(&bs->done, HZ) == 0) {
dev_err(&bs->pdev->dev, "transfer timed out!\n");
return -ETIMEDOUT;
}
if (rx) {
memcpy_fromio(rx, bs->fifo, curr_step);
rx += curr_step;
}
pending -= curr_step;
}
return 0;
}
static int bcm63xx_hsspi_setup(struct spi_device *spi)
{
struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
u32 reg;
reg = __raw_readl(bs->regs +
HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select));
reg &= ~(SIGNAL_CTRL_LAUNCH_RISING | SIGNAL_CTRL_LATCH_RISING);
if (spi->mode & SPI_CPHA)
reg |= SIGNAL_CTRL_LAUNCH_RISING;
else
reg |= SIGNAL_CTRL_LATCH_RISING;
__raw_writel(reg, bs->regs +
HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select));
mutex_lock(&bs->bus_mutex);
reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
/* only change actual polarities if there is no transfer */
if ((reg & GLOBAL_CTRL_CS_POLARITY_MASK) == bs->cs_polarity) {
if (spi->mode & SPI_CS_HIGH)
reg |= BIT(spi->chip_select);
else
reg &= ~BIT(spi->chip_select);
__raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
}
if (spi->mode & SPI_CS_HIGH)
bs->cs_polarity |= BIT(spi->chip_select);
else
bs->cs_polarity &= ~BIT(spi->chip_select);
mutex_unlock(&bs->bus_mutex);
return 0;
}
static int bcm63xx_hsspi_transfer_one(struct spi_master *master,
struct spi_message *msg)
{
struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
struct spi_transfer *t;
struct spi_device *spi = msg->spi;
int status = -EINVAL;
int dummy_cs;
u32 reg;
/* This controller does not support keeping CS active during idle.
* To work around this, we use the following ugly hack:
*
* a. Invert the target chip select's polarity so it will be active.
* b. Select a "dummy" chip select to use as the hardware target.
* c. Invert the dummy chip select's polarity so it will be inactive
* during the actual transfers.
* d. Tell the hardware to send to the dummy chip select. Thanks to
* the multiplexed nature of SPI the actual target will receive
* the transfer and we see its response.
*
* e. At the end restore the polarities again to their default values.
*/
dummy_cs = !spi->chip_select;
bcm63xx_hsspi_set_cs(bs, dummy_cs, true);
list_for_each_entry(t, &msg->transfers, transfer_list) {
status = bcm63xx_hsspi_do_txrx(spi, t);
if (status)
break;
msg->actual_length += t->len;
if (t->delay_usecs)
udelay(t->delay_usecs);
if (t->cs_change)
bcm63xx_hsspi_set_cs(bs, spi->chip_select, false);
}
mutex_lock(&bs->bus_mutex);
reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
reg &= ~GLOBAL_CTRL_CS_POLARITY_MASK;
reg |= bs->cs_polarity;
__raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
mutex_unlock(&bs->bus_mutex);
msg->status = status;
spi_finalize_current_message(master);
return 0;
}
static irqreturn_t bcm63xx_hsspi_interrupt(int irq, void *dev_id)
{
struct bcm63xx_hsspi *bs = (struct bcm63xx_hsspi *)dev_id;
if (__raw_readl(bs->regs + HSSPI_INT_STATUS_MASKED_REG) == 0)
return IRQ_NONE;
__raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG);
__raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
complete(&bs->done);
return IRQ_HANDLED;
}
static int bcm63xx_hsspi_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct bcm63xx_hsspi *bs;
struct resource *res_mem;
void __iomem *regs;
struct device *dev = &pdev->dev;
struct clk *clk;
int irq, ret;
u32 reg, rate;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "no irq\n");
return -ENXIO;
}
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(dev, res_mem);
if (IS_ERR(regs))
return PTR_ERR(regs);
clk = devm_clk_get(dev, "hsspi");
if (IS_ERR(clk))
return PTR_ERR(clk);
rate = clk_get_rate(clk);
if (!rate)
return -EINVAL;
ret = clk_prepare_enable(clk);
if (ret)
return ret;
master = spi_alloc_master(&pdev->dev, sizeof(*bs));
if (!master) {
ret = -ENOMEM;
goto out_disable_clk;
}
bs = spi_master_get_devdata(master);
bs->pdev = pdev;
bs->clk = clk;
bs->regs = regs;
bs->speed_hz = rate;
bs->fifo = (u8 __iomem *)(bs->regs + HSSPI_FIFO_REG(0));
mutex_init(&bs->bus_mutex);
master->bus_num = HSSPI_BUS_NUM;
master->num_chipselect = 8;
master->setup = bcm63xx_hsspi_setup;
master->transfer_one_message = bcm63xx_hsspi_transfer_one;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_MASK(8);
master->auto_runtime_pm = true;
platform_set_drvdata(pdev, master);
/* Initialize the hardware */
__raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
/* clean up any pending interrupts */
__raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG);
/* read out default CS polarities */
reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
bs->cs_polarity = reg & GLOBAL_CTRL_CS_POLARITY_MASK;
__raw_writel(reg | GLOBAL_CTRL_CLK_GATE_SSOFF,
bs->regs + HSSPI_GLOBAL_CTRL_REG);
ret = devm_request_irq(dev, irq, bcm63xx_hsspi_interrupt, IRQF_SHARED,
pdev->name, bs);
if (ret)
goto out_put_master;
/* register and we are done */
ret = devm_spi_register_master(dev, master);
if (ret)
goto out_put_master;
return 0;
out_put_master:
spi_master_put(master);
out_disable_clk:
clk_disable_unprepare(clk);
return ret;
}
static int bcm63xx_hsspi_remove(struct platform_device *pdev)
{
struct spi_master *master = platform_get_drvdata(pdev);
struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
/* reset the hardware and block queue progress */
__raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
clk_disable_unprepare(bs->clk);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int bcm63xx_hsspi_suspend(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
spi_master_suspend(master);
clk_disable_unprepare(bs->clk);
return 0;
}
static int bcm63xx_hsspi_resume(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
int ret;
ret = clk_prepare_enable(bs->clk);
if (ret)
return ret;
spi_master_resume(master);
return 0;
}
#endif
static const struct dev_pm_ops bcm63xx_hsspi_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(bcm63xx_hsspi_suspend, bcm63xx_hsspi_resume)
};
static struct platform_driver bcm63xx_hsspi_driver = {
.driver = {
.name = "bcm63xx-hsspi",
.owner = THIS_MODULE,
.pm = &bcm63xx_hsspi_pm_ops,
},
.probe = bcm63xx_hsspi_probe,
.remove = bcm63xx_hsspi_remove,
};
module_platform_driver(bcm63xx_hsspi_driver);
MODULE_ALIAS("platform:bcm63xx_hsspi");
MODULE_DESCRIPTION("Broadcom BCM63xx High Speed SPI Controller driver");
MODULE_AUTHOR("Jonas Gorski <jogo@openwrt.org>");
MODULE_LICENSE("GPL");

View File

@ -169,8 +169,6 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
transfer_list);
}
len -= prepend_len;
init_completion(&bs->done);
/* Fill in the Message control register */
@ -205,13 +203,7 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
if (!timeout)
return -ETIMEDOUT;
/* read out all data */
rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
if (do_rx && rx_tail != len)
return -EIO;
if (!rx_tail)
if (!do_rx)
return 0;
len = 0;
@ -345,22 +337,19 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "no irq\n");
ret = -ENXIO;
goto out;
return -ENXIO;
}
clk = clk_get(dev, "spi");
clk = devm_clk_get(dev, "spi");
if (IS_ERR(clk)) {
dev_err(dev, "no clock for device\n");
ret = PTR_ERR(clk);
goto out;
return PTR_ERR(clk);
}
master = spi_alloc_master(dev, sizeof(*bs));
if (!master) {
dev_err(dev, "out of memory\n");
ret = -ENOMEM;
goto out_clk;
return -ENOMEM;
}
bs = spi_master_get_devdata(master);
@ -408,7 +397,10 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
}
/* Initialize hardware */
clk_prepare_enable(bs->clk);
ret = clk_prepare_enable(bs->clk);
if (ret)
goto out_err;
bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
/* register and we are done */
@ -427,9 +419,6 @@ out_clk_disable:
clk_disable_unprepare(clk);
out_err:
spi_master_put(master);
out_clk:
clk_put(clk);
out:
return ret;
}
@ -443,12 +432,11 @@ static int bcm63xx_spi_remove(struct platform_device *pdev)
/* HW shutdown */
clk_disable_unprepare(bs->clk);
clk_put(bs->clk);
return 0;
}
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static int bcm63xx_spi_suspend(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
@ -465,29 +453,27 @@ static int bcm63xx_spi_resume(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
int ret;
clk_prepare_enable(bs->clk);
ret = clk_prepare_enable(bs->clk);
if (ret)
return ret;
spi_master_resume(master);
return 0;
}
#endif
static const struct dev_pm_ops bcm63xx_spi_pm_ops = {
.suspend = bcm63xx_spi_suspend,
.resume = bcm63xx_spi_resume,
SET_SYSTEM_SLEEP_PM_OPS(bcm63xx_spi_suspend, bcm63xx_spi_resume)
};
#define BCM63XX_SPI_PM_OPS (&bcm63xx_spi_pm_ops)
#else
#define BCM63XX_SPI_PM_OPS NULL
#endif
static struct platform_driver bcm63xx_spi_driver = {
.driver = {
.name = "bcm63xx-spi",
.owner = THIS_MODULE,
.pm = BCM63XX_SPI_PM_OPS,
.pm = &bcm63xx_spi_pm_ops,
},
.probe = bcm63xx_spi_probe,
.remove = bcm63xx_spi_remove,

View File

@ -38,7 +38,7 @@
*
* Since this is software, the timings may not be exactly what your board's
* chips need ... there may be several reasons you'd need to tweak timings
* in these routines, not just make to make it faster or slower to match a
* in these routines, not just to make it faster or slower to match a
* particular CPU clock rate.
*/

View File

@ -1,7 +1,7 @@
/*
* CLPS711X SPI bus driver
*
* Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
* Copyright (C) 2012-2014 Alexander Shiyan <shc_work@mail.ru>
*
* 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
@ -198,7 +198,7 @@ static int spi_clps711x_probe(struct platform_device *pdev)
ret = -EINVAL;
goto err_out;
}
if (gpio_request(hw->chipselect[i], DRIVER_NAME)) {
if (devm_gpio_request(&pdev->dev, hw->chipselect[i], NULL)) {
dev_err(&pdev->dev, "Can't get CS GPIO %i\n", i);
ret = -EINVAL;
goto err_out;
@ -240,38 +240,21 @@ static int spi_clps711x_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Failed to register master\n");
err_out:
while (--i >= 0)
if (gpio_is_valid(hw->chipselect[i]))
gpio_free(hw->chipselect[i]);
spi_master_put(master);
return ret;
}
static int spi_clps711x_remove(struct platform_device *pdev)
{
int i;
struct spi_master *master = platform_get_drvdata(pdev);
struct spi_clps711x_data *hw = spi_master_get_devdata(master);
for (i = 0; i < master->num_chipselect; i++)
if (gpio_is_valid(hw->chipselect[i]))
gpio_free(hw->chipselect[i]);
return 0;
}
static struct platform_driver clps711x_spi_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
.probe = spi_clps711x_probe,
.remove = spi_clps711x_remove,
};
module_platform_driver(clps711x_spi_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
MODULE_DESCRIPTION("CLPS711X SPI bus driver");
MODULE_ALIAS("platform:" DRIVER_NAME);

View File

@ -397,44 +397,31 @@ static int mcfqspi_probe(struct platform_device *pdev)
mcfqspi = spi_master_get_devdata(master);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_dbg(&pdev->dev, "platform_get_resource failed\n");
status = -ENXIO;
mcfqspi->iobase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mcfqspi->iobase)) {
status = PTR_ERR(mcfqspi->iobase);
goto fail0;
}
if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
dev_dbg(&pdev->dev, "request_mem_region failed\n");
status = -EBUSY;
goto fail0;
}
mcfqspi->iobase = ioremap(res->start, resource_size(res));
if (!mcfqspi->iobase) {
dev_dbg(&pdev->dev, "ioremap failed\n");
status = -ENOMEM;
goto fail1;
}
mcfqspi->irq = platform_get_irq(pdev, 0);
if (mcfqspi->irq < 0) {
dev_dbg(&pdev->dev, "platform_get_irq failed\n");
status = -ENXIO;
goto fail2;
goto fail0;
}
status = request_irq(mcfqspi->irq, mcfqspi_irq_handler, 0,
pdev->name, mcfqspi);
status = devm_request_irq(&pdev->dev, mcfqspi->irq, mcfqspi_irq_handler,
0, pdev->name, mcfqspi);
if (status) {
dev_dbg(&pdev->dev, "request_irq failed\n");
goto fail2;
goto fail0;
}
mcfqspi->clk = clk_get(&pdev->dev, "qspi_clk");
mcfqspi->clk = devm_clk_get(&pdev->dev, "qspi_clk");
if (IS_ERR(mcfqspi->clk)) {
dev_dbg(&pdev->dev, "clk_get failed\n");
status = PTR_ERR(mcfqspi->clk);
goto fail3;
goto fail0;
}
clk_enable(mcfqspi->clk);
@ -445,7 +432,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
status = mcfqspi_cs_setup(mcfqspi);
if (status) {
dev_dbg(&pdev->dev, "error initializing cs_control\n");
goto fail4;
goto fail1;
}
init_waitqueue_head(&mcfqspi->waitq);
@ -459,10 +446,10 @@ static int mcfqspi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master);
status = spi_register_master(master);
status = devm_spi_register_master(&pdev->dev, master);
if (status) {
dev_dbg(&pdev->dev, "spi_register_master failed\n");
goto fail5;
goto fail2;
}
pm_runtime_enable(mcfqspi->dev);
@ -470,17 +457,10 @@ static int mcfqspi_probe(struct platform_device *pdev)
return 0;
fail5:
mcfqspi_cs_teardown(mcfqspi);
fail4:
clk_disable(mcfqspi->clk);
clk_put(mcfqspi->clk);
fail3:
free_irq(mcfqspi->irq, mcfqspi);
fail2:
iounmap(mcfqspi->iobase);
mcfqspi_cs_teardown(mcfqspi);
fail1:
release_mem_region(res->start, resource_size(res));
clk_disable(mcfqspi->clk);
fail0:
spi_master_put(master);
@ -501,11 +481,6 @@ static int mcfqspi_remove(struct platform_device *pdev)
mcfqspi_cs_teardown(mcfqspi);
clk_disable(mcfqspi->clk);
clk_put(mcfqspi->clk);
free_irq(mcfqspi->irq, mcfqspi);
iounmap(mcfqspi->iobase);
release_mem_region(res->start, resource_size(res));
spi_unregister_master(master);
return 0;
}

View File

@ -396,10 +396,6 @@ static int davinci_spi_setup(struct spi_device *spi)
dspi = spi_master_get_devdata(spi->master);
pdata = &dspi->pdata;
/* if bits per word length is zero then set it default 8 */
if (!spi->bits_per_word)
spi->bits_per_word = 8;
if (!(spi->mode & SPI_NO_CS)) {
if ((pdata->chip_sel == NULL) ||
(pdata->chip_sel[spi->chip_select] == SPI_INTERN_CS))
@ -853,7 +849,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
struct spi_master *master;
struct davinci_spi *dspi;
struct davinci_spi_platform_data *pdata;
struct resource *r, *mem;
struct resource *r;
resource_size_t dma_rx_chan = SPI_NO_RESOURCE;
resource_size_t dma_tx_chan = SPI_NO_RESOURCE;
int i = 0, ret = 0;
@ -894,39 +890,33 @@ static int davinci_spi_probe(struct platform_device *pdev)
dspi->pbase = r->start;
mem = request_mem_region(r->start, resource_size(r), pdev->name);
if (mem == NULL) {
ret = -EBUSY;
dspi->base = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(dspi->base)) {
ret = PTR_ERR(dspi->base);
goto free_master;
}
dspi->base = ioremap(r->start, resource_size(r));
if (dspi->base == NULL) {
ret = -ENOMEM;
goto release_region;
}
dspi->irq = platform_get_irq(pdev, 0);
if (dspi->irq <= 0) {
ret = -EINVAL;
goto unmap_io;
goto free_master;
}
ret = request_threaded_irq(dspi->irq, davinci_spi_irq, dummy_thread_fn,
0, dev_name(&pdev->dev), dspi);
ret = devm_request_threaded_irq(&pdev->dev, dspi->irq, davinci_spi_irq,
dummy_thread_fn, 0, dev_name(&pdev->dev), dspi);
if (ret)
goto unmap_io;
goto free_master;
dspi->bitbang.master = master;
if (dspi->bitbang.master == NULL) {
ret = -ENODEV;
goto irq_free;
goto free_master;
}
dspi->clk = clk_get(&pdev->dev, NULL);
dspi->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(dspi->clk)) {
ret = -ENODEV;
goto irq_free;
goto free_master;
}
clk_prepare_enable(dspi->clk);
@ -963,8 +953,8 @@ static int davinci_spi_probe(struct platform_device *pdev)
goto free_clk;
dev_info(&pdev->dev, "DMA: supported\n");
dev_info(&pdev->dev, "DMA: RX channel: %d, TX channel: %d, "
"event queue: %d\n", dma_rx_chan, dma_tx_chan,
dev_info(&pdev->dev, "DMA: RX channel: %pa, TX channel: %pa, "
"event queue: %d\n", &dma_rx_chan, &dma_tx_chan,
pdata->dma_event_q);
}
@ -1015,13 +1005,6 @@ free_dma:
dma_release_channel(dspi->dma_tx);
free_clk:
clk_disable_unprepare(dspi->clk);
clk_put(dspi->clk);
irq_free:
free_irq(dspi->irq, dspi);
unmap_io:
iounmap(dspi->base);
release_region:
release_mem_region(dspi->pbase, resource_size(r));
free_master:
spi_master_put(master);
err:
@ -1041,7 +1024,6 @@ static int davinci_spi_remove(struct platform_device *pdev)
{
struct davinci_spi *dspi;
struct spi_master *master;
struct resource *r;
master = platform_get_drvdata(pdev);
dspi = spi_master_get_devdata(master);
@ -1049,11 +1031,6 @@ static int davinci_spi_remove(struct platform_device *pdev)
spi_bitbang_stop(&dspi->bitbang);
clk_disable_unprepare(dspi->clk);
clk_put(dspi->clk);
free_irq(dspi->irq, dspi);
iounmap(dspi->base);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(dspi->pbase, resource_size(r));
spi_master_put(master);
return 0;

View File

@ -30,14 +30,13 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
{
struct dw_spi_mmio *dwsmmio;
struct dw_spi *dws;
struct resource *mem, *ioarea;
struct resource *mem;
int ret;
dwsmmio = kzalloc(sizeof(struct dw_spi_mmio), GFP_KERNEL);
if (!dwsmmio) {
ret = -ENOMEM;
goto err_end;
}
dwsmmio = devm_kzalloc(&pdev->dev, sizeof(struct dw_spi_mmio),
GFP_KERNEL);
if (!dwsmmio)
return -ENOMEM;
dws = &dwsmmio->dws;
@ -45,80 +44,51 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
dev_err(&pdev->dev, "no mem resource?\n");
ret = -EINVAL;
goto err_kfree;
return -EINVAL;
}
ioarea = request_mem_region(mem->start, resource_size(mem),
pdev->name);
if (!ioarea) {
dev_err(&pdev->dev, "SPI region already claimed\n");
ret = -EBUSY;
goto err_kfree;
}
dws->regs = ioremap_nocache(mem->start, resource_size(mem));
if (!dws->regs) {
dev_err(&pdev->dev, "SPI region already mapped\n");
ret = -ENOMEM;
goto err_release_reg;
dws->regs = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(dws->regs)) {
dev_err(&pdev->dev, "SPI region map failed\n");
return PTR_ERR(dws->regs);
}
dws->irq = platform_get_irq(pdev, 0);
if (dws->irq < 0) {
dev_err(&pdev->dev, "no irq resource?\n");
ret = dws->irq; /* -ENXIO */
goto err_unmap;
return dws->irq; /* -ENXIO */
}
dwsmmio->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(dwsmmio->clk)) {
ret = PTR_ERR(dwsmmio->clk);
goto err_unmap;
}
clk_enable(dwsmmio->clk);
dwsmmio->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(dwsmmio->clk))
return PTR_ERR(dwsmmio->clk);
ret = clk_prepare_enable(dwsmmio->clk);
if (ret)
return ret;
dws->parent_dev = &pdev->dev;
dws->bus_num = 0;
dws->num_cs = 4;
dws->max_freq = clk_get_rate(dwsmmio->clk);
ret = dw_spi_add_host(dws);
ret = dw_spi_add_host(&pdev->dev, dws);
if (ret)
goto err_clk;
goto out;
platform_set_drvdata(pdev, dwsmmio);
return 0;
err_clk:
clk_disable(dwsmmio->clk);
clk_put(dwsmmio->clk);
dwsmmio->clk = NULL;
err_unmap:
iounmap(dws->regs);
err_release_reg:
release_mem_region(mem->start, resource_size(mem));
err_kfree:
kfree(dwsmmio);
err_end:
out:
clk_disable_unprepare(dwsmmio->clk);
return ret;
}
static int dw_spi_mmio_remove(struct platform_device *pdev)
{
struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev);
struct resource *mem;
clk_disable(dwsmmio->clk);
clk_put(dwsmmio->clk);
dwsmmio->clk = NULL;
clk_disable_unprepare(dwsmmio->clk);
dw_spi_remove_host(&dwsmmio->dws);
iounmap(dwsmmio->dws.regs);
kfree(dwsmmio);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(mem->start, resource_size(mem));
return 0;
}

View File

@ -43,35 +43,25 @@ static int spi_pci_probe(struct pci_dev *pdev,
dev_info(&pdev->dev, "found PCI SPI controller(ID: %04x:%04x)\n",
pdev->vendor, pdev->device);
ret = pci_enable_device(pdev);
ret = pcim_enable_device(pdev);
if (ret)
return ret;
dwpci = kzalloc(sizeof(struct dw_spi_pci), GFP_KERNEL);
if (!dwpci) {
ret = -ENOMEM;
goto err_disable;
}
dwpci = devm_kzalloc(&pdev->dev, sizeof(struct dw_spi_pci),
GFP_KERNEL);
if (!dwpci)
return -ENOMEM;
dwpci->pdev = pdev;
dws = &dwpci->dws;
/* Get basic io resource and map it */
dws->paddr = pci_resource_start(pdev, pci_bar);
dws->iolen = pci_resource_len(pdev, pci_bar);
ret = pci_request_region(pdev, pci_bar, dev_name(&pdev->dev));
ret = pcim_iomap_regions(pdev, 1, dev_name(&pdev->dev));
if (ret)
goto err_kfree;
return ret;
dws->regs = ioremap_nocache((unsigned long)dws->paddr,
pci_resource_len(pdev, pci_bar));
if (!dws->regs) {
ret = -ENOMEM;
goto err_release_reg;
}
dws->parent_dev = &pdev->dev;
dws->bus_num = 0;
dws->num_cs = 4;
dws->irq = pdev->irq;
@ -83,26 +73,17 @@ static int spi_pci_probe(struct pci_dev *pdev,
if (pdev->device == 0x0800) {
ret = dw_spi_mid_init(dws);
if (ret)
goto err_unmap;
return ret;
}
ret = dw_spi_add_host(dws);
ret = dw_spi_add_host(&pdev->dev, dws);
if (ret)
goto err_unmap;
return ret;
/* PCI hook and SPI hook use the same drv data */
pci_set_drvdata(pdev, dwpci);
return 0;
err_unmap:
iounmap(dws->regs);
err_release_reg:
pci_release_region(pdev, pci_bar);
err_kfree:
kfree(dwpci);
err_disable:
pci_disable_device(pdev);
return ret;
return 0;
}
static void spi_pci_remove(struct pci_dev *pdev)
@ -110,10 +91,6 @@ static void spi_pci_remove(struct pci_dev *pdev)
struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
dw_spi_remove_host(&dwpci->dws);
iounmap(dwpci->dws.regs);
pci_release_region(pdev, 0);
kfree(dwpci);
pci_disable_device(pdev);
}
#ifdef CONFIG_PM
@ -148,7 +125,7 @@ static int spi_resume(struct pci_dev *pdev)
#define spi_resume NULL
#endif
static DEFINE_PCI_DEVICE_TABLE(pci_ids) = {
static const struct pci_device_id pci_ids[] = {
/* Intel MID platform SPI controller 0 */
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) },
{},

View File

@ -427,7 +427,6 @@ static void pump_transfers(unsigned long data)
dws->tx_end = dws->tx + transfer->len;
dws->rx = transfer->rx_buf;
dws->rx_end = dws->rx + transfer->len;
dws->cs_change = transfer->cs_change;
dws->len = dws->cur_transfer->len;
if (chip != dws->prev_chip)
cs_change = 1;
@ -620,9 +619,11 @@ static int dw_spi_setup(struct spi_device *spi)
/* Only alloc on first setup */
chip = spi_get_ctldata(spi);
if (!chip) {
chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
chip = devm_kzalloc(&spi->dev, sizeof(struct chip_data),
GFP_KERNEL);
if (!chip)
return -ENOMEM;
spi_set_ctldata(spi, chip);
}
/*
@ -667,7 +668,6 @@ static int dw_spi_setup(struct spi_device *spi)
| (spi->mode << SPI_MODE_OFFSET)
| (chip->tmode << SPI_TMOD_OFFSET);
spi_set_ctldata(spi, chip);
return 0;
}
@ -776,18 +776,16 @@ static void spi_hw_init(struct dw_spi *dws)
}
}
int dw_spi_add_host(struct dw_spi *dws)
int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
{
struct spi_master *master;
int ret;
BUG_ON(dws == NULL);
master = spi_alloc_master(dws->parent_dev, 0);
if (!master) {
ret = -ENOMEM;
goto exit;
}
master = spi_alloc_master(dev, 0);
if (!master)
return -ENOMEM;
dws->master = master;
dws->type = SSI_MOTO_SPI;
@ -797,7 +795,7 @@ int dw_spi_add_host(struct dw_spi *dws)
snprintf(dws->name, sizeof(dws->name), "dw_spi%d",
dws->bus_num);
ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED,
ret = devm_request_irq(dev, dws->irq, dw_spi_irq, IRQF_SHARED,
dws->name, dws);
if (ret < 0) {
dev_err(&master->dev, "can not get IRQ\n");
@ -836,7 +834,7 @@ int dw_spi_add_host(struct dw_spi *dws)
}
spi_master_set_devdata(master, dws);
ret = spi_register_master(master);
ret = devm_spi_register_master(dev, master);
if (ret) {
dev_err(&master->dev, "problem registering spi master\n");
goto err_queue_alloc;
@ -851,10 +849,8 @@ err_queue_alloc:
dws->dma_ops->dma_exit(dws);
err_diable_hw:
spi_enable_chip(dws, 0);
free_irq(dws->irq, dws);
err_free_master:
spi_master_put(master);
exit:
return ret;
}
EXPORT_SYMBOL_GPL(dw_spi_add_host);
@ -878,10 +874,6 @@ void dw_spi_remove_host(struct dw_spi *dws)
spi_enable_chip(dws, 0);
/* Disable clk */
spi_set_clk(dws, 0);
free_irq(dws->irq, dws);
/* Disconnect from the SPI framework */
spi_unregister_master(dws->master);
}
EXPORT_SYMBOL_GPL(dw_spi_remove_host);

View File

@ -92,13 +92,11 @@ struct dw_spi_dma_ops {
struct dw_spi {
struct spi_master *master;
struct spi_device *cur_dev;
struct device *parent_dev;
enum dw_ssi_type type;
char name[16];
void __iomem *regs;
unsigned long paddr;
u32 iolen;
int irq;
u32 fifo_len; /* depth of the FIFO buffer */
u32 max_freq; /* max bus freq supported */
@ -135,7 +133,6 @@ struct dw_spi {
u8 n_bytes; /* current is a 1/2 bytes op */
u8 max_bits_per_word; /* maxim is 16b */
u32 dma_width;
int cs_change;
irqreturn_t (*transfer_handler)(struct dw_spi *dws);
void (*cs_control)(u32 command);
@ -231,7 +228,7 @@ struct dw_spi_chip {
void (*cs_control)(u32 command);
};
extern int dw_spi_add_host(struct dw_spi *dws);
extern int dw_spi_add_host(struct device *dev, struct dw_spi *dws);
extern void dw_spi_remove_host(struct dw_spi *dws);
extern int dw_spi_suspend_host(struct dw_spi *dws);
extern int dw_spi_resume_host(struct dw_spi *dws);

View File

@ -433,21 +433,12 @@ static int falcon_sflash_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv);
ret = spi_register_master(master);
ret = devm_spi_register_master(&pdev->dev, master);
if (ret)
spi_master_put(master);
return ret;
}
static int falcon_sflash_remove(struct platform_device *pdev)
{
struct falcon_sflash *priv = platform_get_drvdata(pdev);
spi_unregister_master(priv->master);
return 0;
}
static const struct of_device_id falcon_sflash_match[] = {
{ .compatible = "lantiq,sflash-falcon" },
{},
@ -456,7 +447,6 @@ MODULE_DEVICE_TABLE(of, falcon_sflash_match);
static struct platform_driver falcon_sflash_driver = {
.probe = falcon_sflash_probe,
.remove = falcon_sflash_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,

View File

@ -320,8 +320,10 @@ static void dspi_chipselect(struct spi_device *spi, int value)
switch (value) {
case BITBANG_CS_ACTIVE:
pushr |= SPI_PUSHR_CONT;
break;
case BITBANG_CS_INACTIVE:
pushr &= ~SPI_PUSHR_CONT;
break;
}
writel(pushr, dspi->base + SPI_PUSHR);
@ -373,9 +375,6 @@ 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);
}

View File

@ -705,7 +705,7 @@ static int of_fsl_espi_probe(struct platform_device *ofdev)
goto err;
irq = irq_of_parse_and_map(np, 0);
if (!ret) {
if (!irq) {
ret = -EINVAL;
goto err;
}
@ -727,6 +727,66 @@ static int of_fsl_espi_remove(struct platform_device *dev)
return mpc8xxx_spi_remove(&dev->dev);
}
#ifdef CONFIG_PM_SLEEP
static int of_fsl_espi_suspend(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_espi_reg *reg_base;
u32 regval;
int ret;
mpc8xxx_spi = spi_master_get_devdata(master);
reg_base = mpc8xxx_spi->reg_base;
ret = spi_master_suspend(master);
if (ret) {
dev_warn(dev, "cannot suspend master\n");
return ret;
}
regval = mpc8xxx_spi_read_reg(&reg_base->mode);
regval &= ~SPMODE_ENABLE;
mpc8xxx_spi_write_reg(&reg_base->mode, regval);
return 0;
}
static int of_fsl_espi_resume(struct device *dev)
{
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct spi_master *master = dev_get_drvdata(dev);
struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_espi_reg *reg_base;
u32 regval;
int i;
mpc8xxx_spi = spi_master_get_devdata(master);
reg_base = mpc8xxx_spi->reg_base;
/* SPI controller initializations */
mpc8xxx_spi_write_reg(&reg_base->mode, 0);
mpc8xxx_spi_write_reg(&reg_base->mask, 0);
mpc8xxx_spi_write_reg(&reg_base->command, 0);
mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
/* Init eSPI CS mode register */
for (i = 0; i < pdata->max_chipselect; i++)
mpc8xxx_spi_write_reg(&reg_base->csmode[i], CSMODE_INIT_VAL);
/* Enable SPI interface */
regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
mpc8xxx_spi_write_reg(&reg_base->mode, regval);
return spi_master_resume(master);
}
#endif /* CONFIG_PM_SLEEP */
static const struct dev_pm_ops espi_pm = {
SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume)
};
static const struct of_device_id of_fsl_espi_match[] = {
{ .compatible = "fsl,mpc8536-espi" },
{}
@ -738,6 +798,7 @@ static struct platform_driver fsl_espi_driver = {
.name = "fsl_espi",
.owner = THIS_MODULE,
.of_match_table = of_fsl_espi_match,
.pm = &espi_pm,
},
.probe = of_fsl_espi_probe,
.remove = of_fsl_espi_remove,

View File

@ -115,17 +115,17 @@ spi_to_pdata(const struct spi_device *spi)
static inline void setsck(const struct spi_device *spi, int is_on)
{
gpio_set_value(SPI_SCK_GPIO, is_on);
gpio_set_value_cansleep(SPI_SCK_GPIO, is_on);
}
static inline void setmosi(const struct spi_device *spi, int is_on)
{
gpio_set_value(SPI_MOSI_GPIO, is_on);
gpio_set_value_cansleep(SPI_MOSI_GPIO, is_on);
}
static inline int getmiso(const struct spi_device *spi)
{
return !!gpio_get_value(SPI_MISO_GPIO);
return !!gpio_get_value_cansleep(SPI_MISO_GPIO);
}
#undef pdata
@ -229,7 +229,7 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
if (cs != SPI_GPIO_NO_CHIPSELECT) {
/* SPI is normally active-low */
gpio_set_value(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
gpio_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
}
}

View File

@ -206,7 +206,8 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
#define MX51_ECSPI_STAT_RR (1 << 3)
/* MX51 eCSPI */
static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi)
static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
unsigned int *fres)
{
/*
* there are two 4-bit dividers, the pre-divider divides by
@ -234,6 +235,10 @@ static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi)
pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n",
__func__, fin, fspi, post, pre);
/* Resulting frequency for the SCLK line. */
*fres = (fin / (pre + 1)) >> post;
return (pre << MX51_ECSPI_CTRL_PREDIV_OFFSET) |
(post << MX51_ECSPI_CTRL_POSTDIV_OFFSET);
}
@ -264,6 +269,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
struct spi_imx_config *config)
{
u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0;
u32 clk = config->speed_hz, delay;
/*
* The hardware seems to have a race condition when changing modes. The
@ -275,7 +281,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
/* set clock speed */
ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz);
ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz, &clk);
/* set chip select to use */
ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
@ -297,6 +303,23 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
/*
* Wait until the changes in the configuration register CONFIGREG
* propagate into the hardware. It takes exactly one tick of the
* SCLK clock, but we will wait two SCLK clock just to be sure. The
* effect of the delay it takes for the hardware to apply changes
* is noticable if the SCLK clock run very slow. In such a case, if
* the polarity of SCLK should be inverted, the GPIO ChipSelect might
* be asserted before the SCLK polarity changes, which would disrupt
* the SPI communication as the device on the other end would consider
* the change of SCLK polarity as a clock tick already.
*/
delay = (2 * 1000000) / clk;
if (likely(delay < 10)) /* SCLK is faster than 100 kHz */
udelay(delay);
else /* SCLK is _very_ slow */
usleep_range(delay, delay + 10);
return 0;
}

View File

@ -504,7 +504,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
master->cleanup = mpc512x_psc_spi_cleanup;
master->dev.of_node = dev->of_node;
tempp = ioremap(regaddr, size);
tempp = devm_ioremap(dev, regaddr, size);
if (!tempp) {
dev_err(dev, "could not ioremap I/O port range\n");
ret = -EFAULT;
@ -513,9 +513,8 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
mps->psc = tempp;
mps->fifo =
(struct mpc512x_psc_fifo *)(tempp + sizeof(struct mpc52xx_psc));
ret = request_irq(mps->irq, mpc512x_psc_spi_isr, IRQF_SHARED,
"mpc512x-psc-spi", mps);
ret = devm_request_irq(dev, mps->irq, mpc512x_psc_spi_isr, IRQF_SHARED,
"mpc512x-psc-spi", mps);
if (ret)
goto free_master;
init_completion(&mps->txisrdone);
@ -525,11 +524,11 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
clk = devm_clk_get(dev, clk_name);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
goto free_irq;
goto free_master;
}
ret = clk_prepare_enable(clk);
if (ret)
goto free_irq;
goto free_master;
mps->clk_mclk = clk;
mps->mclk_rate = clk_get_rate(clk);
@ -545,11 +544,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
free_clock:
clk_disable_unprepare(mps->clk_mclk);
free_irq:
free_irq(mps->irq, mps);
free_master:
if (mps->psc)
iounmap(mps->psc);
spi_master_put(master);
return ret;
@ -561,9 +556,6 @@ static int mpc512x_psc_spi_do_remove(struct device *dev)
struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
clk_disable_unprepare(mps->clk_mclk);
free_irq(mps->irq, mps);
if (mps->psc)
iounmap(mps->psc);
return 0;
}

View File

@ -111,14 +111,6 @@ static int mxs_spi_setup_transfer(struct spi_device *dev,
return 0;
}
static int mxs_spi_setup(struct spi_device *dev)
{
if (!dev->bits_per_word)
dev->bits_per_word = 8;
return 0;
}
static u32 mxs_spi_cs_to_reg(unsigned cs)
{
u32 select = 0;
@ -502,7 +494,6 @@ static int mxs_spi_probe(struct platform_device *pdev)
return -ENOMEM;
master->transfer_one_message = mxs_spi_transfer_one;
master->setup = mxs_spi_setup;
master->bits_per_word_mask = SPI_BPW_MASK(8);
master->mode_bits = SPI_CPOL | SPI_CPHA;
master->num_chipselect = 3;

View File

@ -57,7 +57,6 @@ struct nuc900_spi {
const unsigned char *tx;
unsigned char *rx;
struct clk *clk;
struct resource *ioarea;
struct spi_master *master;
struct spi_device *curdev;
struct device *dev;
@ -344,8 +343,7 @@ static int nuc900_spi_probe(struct platform_device *pdev)
master = spi_alloc_master(&pdev->dev, sizeof(struct nuc900_spi));
if (master == NULL) {
dev_err(&pdev->dev, "No memory for spi_master\n");
err = -ENOMEM;
goto err_nomem;
return -ENOMEM;
}
hw = spi_master_get_devdata(master);
@ -370,46 +368,31 @@ static int nuc900_spi_probe(struct platform_device *pdev)
hw->bitbang.txrx_bufs = nuc900_spi_txrx;
hw->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (hw->res == NULL) {
dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
err = -ENOENT;
hw->regs = devm_ioremap_resource(&pdev->dev, hw->res);
if (IS_ERR(hw->regs)) {
err = PTR_ERR(hw->regs);
goto err_pdata;
}
hw->ioarea = request_mem_region(hw->res->start,
resource_size(hw->res), pdev->name);
if (hw->ioarea == NULL) {
dev_err(&pdev->dev, "Cannot reserve region\n");
err = -ENXIO;
goto err_pdata;
}
hw->regs = ioremap(hw->res->start, resource_size(hw->res));
if (hw->regs == NULL) {
dev_err(&pdev->dev, "Cannot map IO\n");
err = -ENXIO;
goto err_iomap;
}
hw->irq = platform_get_irq(pdev, 0);
if (hw->irq < 0) {
dev_err(&pdev->dev, "No IRQ specified\n");
err = -ENOENT;
goto err_irq;
goto err_pdata;
}
err = request_irq(hw->irq, nuc900_spi_irq, 0, pdev->name, hw);
err = devm_request_irq(&pdev->dev, hw->irq, nuc900_spi_irq, 0,
pdev->name, hw);
if (err) {
dev_err(&pdev->dev, "Cannot claim IRQ\n");
goto err_irq;
goto err_pdata;
}
hw->clk = clk_get(&pdev->dev, "spi");
hw->clk = devm_clk_get(&pdev->dev, "spi");
if (IS_ERR(hw->clk)) {
dev_err(&pdev->dev, "No clock for device\n");
err = PTR_ERR(hw->clk);
goto err_clk;
goto err_pdata;
}
mfp_set_groupg(&pdev->dev, NULL);
@ -425,17 +408,8 @@ static int nuc900_spi_probe(struct platform_device *pdev)
err_register:
clk_disable(hw->clk);
clk_put(hw->clk);
err_clk:
free_irq(hw->irq, hw);
err_irq:
iounmap(hw->regs);
err_iomap:
release_mem_region(hw->res->start, resource_size(hw->res));
kfree(hw->ioarea);
err_pdata:
spi_master_put(hw->master);
err_nomem:
return err;
}
@ -443,18 +417,8 @@ static int nuc900_spi_remove(struct platform_device *dev)
{
struct nuc900_spi *hw = platform_get_drvdata(dev);
free_irq(hw->irq, hw);
spi_bitbang_stop(&hw->bitbang);
clk_disable(hw->clk);
clk_put(hw->clk);
iounmap(hw->regs);
release_mem_region(hw->res->start, resource_size(hw->res));
kfree(hw->ioarea);
spi_master_put(hw->master);
return 0;
}

View File

@ -153,62 +153,22 @@ static int tiny_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
}
wait_for_completion(&hw->done);
} else if (txp && rxp) {
/* we need to tighten the transfer loop */
writeb(*txp++, hw->base + TINY_SPI_TXDATA);
if (t->len > 1) {
writeb(*txp++, hw->base + TINY_SPI_TXDATA);
for (i = 2; i < t->len; i++) {
u8 rx, tx = *txp++;
tiny_spi_wait_txr(hw);
rx = readb(hw->base + TINY_SPI_TXDATA);
writeb(tx, hw->base + TINY_SPI_TXDATA);
*rxp++ = rx;
}
tiny_spi_wait_txr(hw);
*rxp++ = readb(hw->base + TINY_SPI_TXDATA);
}
tiny_spi_wait_txe(hw);
*rxp++ = readb(hw->base + TINY_SPI_RXDATA);
} else if (rxp) {
writeb(0, hw->base + TINY_SPI_TXDATA);
if (t->len > 1) {
writeb(0,
hw->base + TINY_SPI_TXDATA);
for (i = 2; i < t->len; i++) {
u8 rx;
tiny_spi_wait_txr(hw);
rx = readb(hw->base + TINY_SPI_TXDATA);
writeb(0, hw->base + TINY_SPI_TXDATA);
*rxp++ = rx;
}
tiny_spi_wait_txr(hw);
*rxp++ = readb(hw->base + TINY_SPI_TXDATA);
}
tiny_spi_wait_txe(hw);
*rxp++ = readb(hw->base + TINY_SPI_RXDATA);
} else if (txp) {
writeb(*txp++, hw->base + TINY_SPI_TXDATA);
if (t->len > 1) {
writeb(*txp++, hw->base + TINY_SPI_TXDATA);
for (i = 2; i < t->len; i++) {
u8 tx = *txp++;
tiny_spi_wait_txr(hw);
writeb(tx, hw->base + TINY_SPI_TXDATA);
}
}
tiny_spi_wait_txe(hw);
} else {
writeb(0, hw->base + TINY_SPI_TXDATA);
if (t->len > 1) {
writeb(0, hw->base + TINY_SPI_TXDATA);
for (i = 2; i < t->len; i++) {
/* we need to tighten the transfer loop */
writeb(txp ? *txp++ : 0, hw->base + TINY_SPI_TXDATA);
for (i = 1; i < t->len; i++) {
writeb(txp ? *txp++ : 0, hw->base + TINY_SPI_TXDATA);
if (rxp || (i != t->len - 1))
tiny_spi_wait_txr(hw);
writeb(0, hw->base + TINY_SPI_TXDATA);
}
if (rxp)
*rxp++ = readb(hw->base + TINY_SPI_TXDATA);
}
tiny_spi_wait_txe(hw);
if (rxp)
*rxp++ = readb(hw->base + TINY_SPI_RXDATA);
}
return t->len;
}

View File

@ -470,31 +470,12 @@ err:
return status;
}
static int omap1_spi100k_remove(struct platform_device *pdev)
{
struct spi_master *master;
struct omap1_spi100k *spi100k;
struct resource *r;
int status = 0;
master = platform_get_drvdata(pdev);
spi100k = spi_master_get_devdata(master);
if (status != 0)
return status;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
return 0;
}
static struct platform_driver omap1_spi100k_driver = {
.driver = {
.name = "omap1_spi100k",
.owner = THIS_MODULE,
},
.probe = omap1_spi100k_probe,
.remove = omap1_spi100k_remove,
};
module_platform_driver(omap1_spi100k_driver);
@ -502,4 +483,3 @@ module_platform_driver(omap1_spi100k_driver);
MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver");
MODULE_AUTHOR("Fabrice Crohas <fcrohas@gmail.com>");
MODULE_LICENSE("GPL");

View File

@ -157,14 +157,14 @@ static inline void mcspi_write_reg(struct spi_master *master,
{
struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
__raw_writel(val, mcspi->base + idx);
writel_relaxed(val, mcspi->base + idx);
}
static inline u32 mcspi_read_reg(struct spi_master *master, int idx)
{
struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
return __raw_readl(mcspi->base + idx);
return readl_relaxed(mcspi->base + idx);
}
static inline void mcspi_write_cs_reg(const struct spi_device *spi,
@ -172,14 +172,14 @@ static inline void mcspi_write_cs_reg(const struct spi_device *spi,
{
struct omap2_mcspi_cs *cs = spi->controller_state;
__raw_writel(val, cs->base + idx);
writel_relaxed(val, cs->base + idx);
}
static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx)
{
struct omap2_mcspi_cs *cs = spi->controller_state;
return __raw_readl(cs->base + idx);
return readl_relaxed(cs->base + idx);
}
static inline u32 mcspi_cached_chconf0(const struct spi_device *spi)
@ -338,7 +338,7 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE, ctx->wakeupenable);
list_for_each_entry(cs, &ctx->cs, node)
__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
}
static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
@ -346,9 +346,9 @@ static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
unsigned long timeout;
timeout = jiffies + msecs_to_jiffies(1000);
while (!(__raw_readl(reg) & bit)) {
while (!(readl_relaxed(reg) & bit)) {
if (time_after(jiffies, timeout)) {
if (!(__raw_readl(reg) & bit))
if (!(readl_relaxed(reg) & bit))
return -ETIMEDOUT;
else
return 0;
@ -675,7 +675,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
}
dev_vdbg(&spi->dev, "write-%d %02x\n",
word_len, *tx);
__raw_writel(*tx++, tx_reg);
writel_relaxed(*tx++, tx_reg);
}
if (rx != NULL) {
if (mcspi_wait_for_reg_bit(chstat_reg,
@ -687,7 +687,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
if (c == 1 && tx == NULL &&
(l & OMAP2_MCSPI_CHCONF_TURBO)) {
omap2_mcspi_set_enable(spi, 0);
*rx++ = __raw_readl(rx_reg);
*rx++ = readl_relaxed(rx_reg);
dev_vdbg(&spi->dev, "read-%d %02x\n",
word_len, *(rx - 1));
if (mcspi_wait_for_reg_bit(chstat_reg,
@ -701,7 +701,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
omap2_mcspi_set_enable(spi, 0);
}
*rx++ = __raw_readl(rx_reg);
*rx++ = readl_relaxed(rx_reg);
dev_vdbg(&spi->dev, "read-%d %02x\n",
word_len, *(rx - 1));
}
@ -722,7 +722,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
}
dev_vdbg(&spi->dev, "write-%d %04x\n",
word_len, *tx);
__raw_writel(*tx++, tx_reg);
writel_relaxed(*tx++, tx_reg);
}
if (rx != NULL) {
if (mcspi_wait_for_reg_bit(chstat_reg,
@ -734,7 +734,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
if (c == 2 && tx == NULL &&
(l & OMAP2_MCSPI_CHCONF_TURBO)) {
omap2_mcspi_set_enable(spi, 0);
*rx++ = __raw_readl(rx_reg);
*rx++ = readl_relaxed(rx_reg);
dev_vdbg(&spi->dev, "read-%d %04x\n",
word_len, *(rx - 1));
if (mcspi_wait_for_reg_bit(chstat_reg,
@ -748,7 +748,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
omap2_mcspi_set_enable(spi, 0);
}
*rx++ = __raw_readl(rx_reg);
*rx++ = readl_relaxed(rx_reg);
dev_vdbg(&spi->dev, "read-%d %04x\n",
word_len, *(rx - 1));
}
@ -769,7 +769,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
}
dev_vdbg(&spi->dev, "write-%d %08x\n",
word_len, *tx);
__raw_writel(*tx++, tx_reg);
writel_relaxed(*tx++, tx_reg);
}
if (rx != NULL) {
if (mcspi_wait_for_reg_bit(chstat_reg,
@ -781,7 +781,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
if (c == 4 && tx == NULL &&
(l & OMAP2_MCSPI_CHCONF_TURBO)) {
omap2_mcspi_set_enable(spi, 0);
*rx++ = __raw_readl(rx_reg);
*rx++ = readl_relaxed(rx_reg);
dev_vdbg(&spi->dev, "read-%d %08x\n",
word_len, *(rx - 1));
if (mcspi_wait_for_reg_bit(chstat_reg,
@ -795,7 +795,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
omap2_mcspi_set_enable(spi, 0);
}
*rx++ = __raw_readl(rx_reg);
*rx++ = readl_relaxed(rx_reg);
dev_vdbg(&spi->dev, "read-%d %08x\n",
word_len, *(rx - 1));
}
@ -1107,7 +1107,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
/* RX_ONLY mode needs dummy data in TX reg */
if (t->tx_buf == NULL)
__raw_writel(0, cs->base
writel_relaxed(0, cs->base
+ OMAP2_MCSPI_TX0);
if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
@ -1470,9 +1470,9 @@ static int omap2_mcspi_resume(struct device *dev)
* change in account.
*/
cs->chconf0 |= OMAP2_MCSPI_CHCONF_FORCE;
__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
cs->chconf0 &= ~OMAP2_MCSPI_CHCONF_FORCE;
__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
}
}
pm_runtime_mark_last_busy(mcspi->dev);

View File

@ -434,7 +434,7 @@ static int orion_spi_probe(struct platform_device *pdev)
spi = spi_master_get_devdata(master);
spi->master = master;
spi->clk = clk_get(&pdev->dev, NULL);
spi->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(spi->clk)) {
status = PTR_ERR(spi->clk);
goto out;
@ -465,7 +465,6 @@ static int orion_spi_probe(struct platform_device *pdev)
out_rel_clk:
clk_disable_unprepare(spi->clk);
clk_put(spi->clk);
out:
spi_master_put(master);
return status;
@ -481,7 +480,6 @@ static int orion_spi_remove(struct platform_device *pdev)
spi = spi_master_get_devdata(master);
clk_disable_unprepare(spi->clk);
clk_put(spi->clk);
return 0;
}

View File

@ -62,7 +62,7 @@ static void ce4100_spi_remove(struct pci_dev *dev)
platform_device_unregister(pdev);
}
static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = {
static const struct pci_device_id ce4100_spi_devices[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) },
{ },
};

View File

@ -1066,6 +1066,8 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
pdata->num_chipselect = 1;
pdata->enable_dma = true;
pdata->tx_chan_id = -1;
pdata->rx_chan_id = -1;
return pdata;
}
@ -1266,7 +1268,7 @@ static void pxa2xx_spi_shutdown(struct platform_device *pdev)
dev_err(&pdev->dev, "shutdown failed with %d\n", status);
}
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static int pxa2xx_spi_suspend(struct device *dev)
{
struct driver_data *drv_data = dev_get_drvdata(dev);

View File

@ -37,117 +37,145 @@
#include <linux/spi/spi.h>
#include <linux/spi/rspi.h>
#define RSPI_SPCR 0x00
#define RSPI_SSLP 0x01
#define RSPI_SPPCR 0x02
#define RSPI_SPSR 0x03
#define RSPI_SPDR 0x04
#define RSPI_SPSCR 0x08
#define RSPI_SPSSR 0x09
#define RSPI_SPBR 0x0a
#define RSPI_SPDCR 0x0b
#define RSPI_SPCKD 0x0c
#define RSPI_SSLND 0x0d
#define RSPI_SPND 0x0e
#define RSPI_SPCR2 0x0f
#define RSPI_SPCMD0 0x10
#define RSPI_SPCMD1 0x12
#define RSPI_SPCMD2 0x14
#define RSPI_SPCMD3 0x16
#define RSPI_SPCMD4 0x18
#define RSPI_SPCMD5 0x1a
#define RSPI_SPCMD6 0x1c
#define RSPI_SPCMD7 0x1e
#define RSPI_SPCR 0x00 /* Control Register */
#define RSPI_SSLP 0x01 /* Slave Select Polarity Register */
#define RSPI_SPPCR 0x02 /* Pin Control Register */
#define RSPI_SPSR 0x03 /* Status Register */
#define RSPI_SPDR 0x04 /* Data Register */
#define RSPI_SPSCR 0x08 /* Sequence Control Register */
#define RSPI_SPSSR 0x09 /* Sequence Status Register */
#define RSPI_SPBR 0x0a /* Bit Rate Register */
#define RSPI_SPDCR 0x0b /* Data Control Register */
#define RSPI_SPCKD 0x0c /* Clock Delay Register */
#define RSPI_SSLND 0x0d /* Slave Select Negation Delay Register */
#define RSPI_SPND 0x0e /* Next-Access Delay Register */
#define RSPI_SPCR2 0x0f /* Control Register 2 */
#define RSPI_SPCMD0 0x10 /* Command Register 0 */
#define RSPI_SPCMD1 0x12 /* Command Register 1 */
#define RSPI_SPCMD2 0x14 /* Command Register 2 */
#define RSPI_SPCMD3 0x16 /* Command Register 3 */
#define RSPI_SPCMD4 0x18 /* Command Register 4 */
#define RSPI_SPCMD5 0x1a /* Command Register 5 */
#define RSPI_SPCMD6 0x1c /* Command Register 6 */
#define RSPI_SPCMD7 0x1e /* Command Register 7 */
#define RSPI_SPBFCR 0x20 /* Buffer Control Register */
#define RSPI_SPBFDR 0x22 /* Buffer Data Count Setting Register */
/*qspi only */
#define QSPI_SPBFCR 0x18
#define QSPI_SPBDCR 0x1a
#define QSPI_SPBMUL0 0x1c
#define QSPI_SPBMUL1 0x20
#define QSPI_SPBMUL2 0x24
#define QSPI_SPBMUL3 0x28
#define QSPI_SPBFCR 0x18 /* Buffer Control Register */
#define QSPI_SPBDCR 0x1a /* Buffer Data Count Register */
#define QSPI_SPBMUL0 0x1c /* Transfer Data Length Multiplier Setting Register 0 */
#define QSPI_SPBMUL1 0x20 /* Transfer Data Length Multiplier Setting Register 1 */
#define QSPI_SPBMUL2 0x24 /* Transfer Data Length Multiplier Setting Register 2 */
#define QSPI_SPBMUL3 0x28 /* Transfer Data Length Multiplier Setting Register 3 */
/* SPCR */
#define SPCR_SPRIE 0x80
#define SPCR_SPE 0x40
#define SPCR_SPTIE 0x20
#define SPCR_SPEIE 0x10
#define SPCR_MSTR 0x08
#define SPCR_MODFEN 0x04
#define SPCR_TXMD 0x02
#define SPCR_SPMS 0x01
/* SPCR - Control Register */
#define SPCR_SPRIE 0x80 /* Receive Interrupt Enable */
#define SPCR_SPE 0x40 /* Function Enable */
#define SPCR_SPTIE 0x20 /* Transmit Interrupt Enable */
#define SPCR_SPEIE 0x10 /* Error Interrupt Enable */
#define SPCR_MSTR 0x08 /* Master/Slave Mode Select */
#define SPCR_MODFEN 0x04 /* Mode Fault Error Detection Enable */
/* RSPI on SH only */
#define SPCR_TXMD 0x02 /* TX Only Mode (vs. Full Duplex) */
#define SPCR_SPMS 0x01 /* 3-wire Mode (vs. 4-wire) */
/* QSPI on R-Car M2 only */
#define SPCR_WSWAP 0x02 /* Word Swap of read-data for DMAC */
#define SPCR_BSWAP 0x01 /* Byte Swap of read-data for DMAC */
/* SSLP */
#define SSLP_SSL1P 0x02
#define SSLP_SSL0P 0x01
/* SSLP - Slave Select Polarity Register */
#define SSLP_SSL1P 0x02 /* SSL1 Signal Polarity Setting */
#define SSLP_SSL0P 0x01 /* SSL0 Signal Polarity Setting */
/* SPPCR */
#define SPPCR_MOIFE 0x20
#define SPPCR_MOIFV 0x10
/* SPPCR - Pin Control Register */
#define SPPCR_MOIFE 0x20 /* MOSI Idle Value Fixing Enable */
#define SPPCR_MOIFV 0x10 /* MOSI Idle Fixed Value */
#define SPPCR_SPOM 0x04
#define SPPCR_SPLP2 0x02
#define SPPCR_SPLP 0x01
#define SPPCR_SPLP2 0x02 /* Loopback Mode 2 (non-inverting) */
#define SPPCR_SPLP 0x01 /* Loopback Mode (inverting) */
/* SPSR */
#define SPSR_SPRF 0x80
#define SPSR_SPTEF 0x20
#define SPSR_PERF 0x08
#define SPSR_MODF 0x04
#define SPSR_IDLNF 0x02
#define SPSR_OVRF 0x01
#define SPPCR_IO3FV 0x04 /* Single-/Dual-SPI Mode IO3 Output Fixed Value */
#define SPPCR_IO2FV 0x04 /* Single-/Dual-SPI Mode IO2 Output Fixed Value */
/* SPSCR */
#define SPSCR_SPSLN_MASK 0x07
/* SPSR - Status Register */
#define SPSR_SPRF 0x80 /* Receive Buffer Full Flag */
#define SPSR_TEND 0x40 /* Transmit End */
#define SPSR_SPTEF 0x20 /* Transmit Buffer Empty Flag */
#define SPSR_PERF 0x08 /* Parity Error Flag */
#define SPSR_MODF 0x04 /* Mode Fault Error Flag */
#define SPSR_IDLNF 0x02 /* RSPI Idle Flag */
#define SPSR_OVRF 0x01 /* Overrun Error Flag */
/* SPSSR */
#define SPSSR_SPECM_MASK 0x70
#define SPSSR_SPCP_MASK 0x07
/* SPSCR - Sequence Control Register */
#define SPSCR_SPSLN_MASK 0x07 /* Sequence Length Specification */
/* SPDCR */
#define SPDCR_SPLW 0x20
#define SPDCR_SPRDTD 0x10
/* SPSSR - Sequence Status Register */
#define SPSSR_SPECM_MASK 0x70 /* Command Error Mask */
#define SPSSR_SPCP_MASK 0x07 /* Command Pointer Mask */
/* SPDCR - Data Control Register */
#define SPDCR_TXDMY 0x80 /* Dummy Data Transmission Enable */
#define SPDCR_SPLW1 0x40 /* Access Width Specification (RZ) */
#define SPDCR_SPLW0 0x20 /* Access Width Specification (RZ) */
#define SPDCR_SPLLWORD (SPDCR_SPLW1 | SPDCR_SPLW0)
#define SPDCR_SPLWORD SPDCR_SPLW1
#define SPDCR_SPLBYTE SPDCR_SPLW0
#define SPDCR_SPLW 0x20 /* Access Width Specification (SH) */
#define SPDCR_SPRDTD 0x10 /* Receive Transmit Data Select */
#define SPDCR_SLSEL1 0x08
#define SPDCR_SLSEL0 0x04
#define SPDCR_SLSEL_MASK 0x0c
#define SPDCR_SLSEL_MASK 0x0c /* SSL1 Output Select */
#define SPDCR_SPFC1 0x02
#define SPDCR_SPFC0 0x01
#define SPDCR_SPFC_MASK 0x03 /* Frame Count Setting (1-4) */
/* SPCKD */
#define SPCKD_SCKDL_MASK 0x07
/* SPCKD - Clock Delay Register */
#define SPCKD_SCKDL_MASK 0x07 /* Clock Delay Setting (1-8) */
/* SSLND */
#define SSLND_SLNDL_MASK 0x07
/* SSLND - Slave Select Negation Delay Register */
#define SSLND_SLNDL_MASK 0x07 /* SSL Negation Delay Setting (1-8) */
/* SPND */
#define SPND_SPNDL_MASK 0x07
/* SPND - Next-Access Delay Register */
#define SPND_SPNDL_MASK 0x07 /* Next-Access Delay Setting (1-8) */
/* SPCR2 */
#define SPCR2_PTE 0x08
#define SPCR2_SPIE 0x04
#define SPCR2_SPOE 0x02
#define SPCR2_SPPE 0x01
/* SPCR2 - Control Register 2 */
#define SPCR2_PTE 0x08 /* Parity Self-Test Enable */
#define SPCR2_SPIE 0x04 /* Idle Interrupt Enable */
#define SPCR2_SPOE 0x02 /* Odd Parity Enable (vs. Even) */
#define SPCR2_SPPE 0x01 /* Parity Enable */
/* SPCMDn */
#define SPCMD_SCKDEN 0x8000
#define SPCMD_SLNDEN 0x4000
#define SPCMD_SPNDEN 0x2000
#define SPCMD_LSBF 0x1000
#define SPCMD_SPB_MASK 0x0f00
/* SPCMDn - Command Registers */
#define SPCMD_SCKDEN 0x8000 /* Clock Delay Setting Enable */
#define SPCMD_SLNDEN 0x4000 /* SSL Negation Delay Setting Enable */
#define SPCMD_SPNDEN 0x2000 /* Next-Access Delay Enable */
#define SPCMD_LSBF 0x1000 /* LSB First */
#define SPCMD_SPB_MASK 0x0f00 /* Data Length Setting */
#define SPCMD_SPB_8_TO_16(bit) (((bit - 1) << 8) & SPCMD_SPB_MASK)
#define SPCMD_SPB_8BIT 0x0000 /* qspi only */
#define SPCMD_SPB_16BIT 0x0100
#define SPCMD_SPB_20BIT 0x0000
#define SPCMD_SPB_24BIT 0x0100
#define SPCMD_SPB_32BIT 0x0200
#define SPCMD_SSLKP 0x0080
#define SPCMD_SSLA_MASK 0x0030
#define SPCMD_BRDV_MASK 0x000c
#define SPCMD_CPOL 0x0002
#define SPCMD_CPHA 0x0001
#define SPCMD_SSLKP 0x0080 /* SSL Signal Level Keeping */
#define SPCMD_SPIMOD_MASK 0x0060 /* SPI Operating Mode (QSPI only) */
#define SPCMD_SPIMOD1 0x0040
#define SPCMD_SPIMOD0 0x0020
#define SPCMD_SPIMOD_SINGLE 0
#define SPCMD_SPIMOD_DUAL SPCMD_SPIMOD0
#define SPCMD_SPIMOD_QUAD SPCMD_SPIMOD1
#define SPCMD_SPRW 0x0010 /* SPI Read/Write Access (Dual/Quad) */
#define SPCMD_SSLA_MASK 0x0030 /* SSL Assert Signal Setting (RSPI) */
#define SPCMD_BRDV_MASK 0x000c /* Bit Rate Division Setting */
#define SPCMD_CPOL 0x0002 /* Clock Polarity Setting */
#define SPCMD_CPHA 0x0001 /* Clock Phase Setting */
/* SPBFCR */
#define SPBFCR_TXRST 0x80 /* qspi only */
#define SPBFCR_RXRST 0x40 /* qspi only */
/* SPBFCR - Buffer Control Register */
#define SPBFCR_TXRST 0x80 /* Transmit Buffer Data Reset (qspi only) */
#define SPBFCR_RXRST 0x40 /* Receive Buffer Data Reset (qspi only) */
#define SPBFCR_TXTRG_MASK 0x30 /* Transmit Buffer Data Triggering Number */
#define SPBFCR_RXTRG_MASK 0x07 /* Receive Buffer Data Triggering Number */
#define DUMMY_DATA 0x00
struct rspi_data {
void __iomem *addr;
@ -158,7 +186,8 @@ struct rspi_data {
wait_queue_head_t wait;
spinlock_t lock;
struct clk *clk;
unsigned char spsr;
u8 spsr;
u16 spcmd;
const struct spi_ops *ops;
/* for dmaengine */
@ -170,34 +199,35 @@ struct rspi_data {
unsigned dma_callbacked:1;
};
static void rspi_write8(struct rspi_data *rspi, u8 data, u16 offset)
static void rspi_write8(const struct rspi_data *rspi, u8 data, u16 offset)
{
iowrite8(data, rspi->addr + offset);
}
static void rspi_write16(struct rspi_data *rspi, u16 data, u16 offset)
static void rspi_write16(const struct rspi_data *rspi, u16 data, u16 offset)
{
iowrite16(data, rspi->addr + offset);
}
static void rspi_write32(struct rspi_data *rspi, u32 data, u16 offset)
static void rspi_write32(const struct rspi_data *rspi, u32 data, u16 offset)
{
iowrite32(data, rspi->addr + offset);
}
static u8 rspi_read8(struct rspi_data *rspi, u16 offset)
static u8 rspi_read8(const struct rspi_data *rspi, u16 offset)
{
return ioread8(rspi->addr + offset);
}
static u16 rspi_read16(struct rspi_data *rspi, u16 offset)
static u16 rspi_read16(const struct rspi_data *rspi, u16 offset)
{
return ioread16(rspi->addr + offset);
}
/* optional functions */
struct spi_ops {
int (*set_config_register)(struct rspi_data *rspi, int access_size);
int (*set_config_register)(const struct rspi_data *rspi,
int access_size);
int (*send_pio)(struct rspi_data *rspi, struct spi_message *mesg,
struct spi_transfer *t);
int (*receive_pio)(struct rspi_data *rspi, struct spi_message *mesg,
@ -208,7 +238,8 @@ struct spi_ops {
/*
* functions for RSPI
*/
static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
static int rspi_set_config_register(const struct rspi_data *rspi,
int access_size)
{
int spbr;
@ -231,7 +262,7 @@ static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
rspi_write8(rspi, 0x00, RSPI_SPCR2);
/* Sets SPCMD */
rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP,
rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | rspi->spcmd,
RSPI_SPCMD0);
/* Sets RSPI mode */
@ -243,7 +274,8 @@ static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
/*
* functions for QSPI
*/
static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
static int qspi_set_config_register(const struct rspi_data *rspi,
int access_size)
{
u16 spcmd;
int spbr;
@ -268,10 +300,10 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
spcmd = SPCMD_SPB_8BIT;
else if (access_size == 16)
spcmd = SPCMD_SPB_16BIT;
else if (access_size == 32)
else
spcmd = SPCMD_SPB_32BIT;
spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SSLKP | SPCMD_SPNDEN;
spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | rspi->spcmd | SPCMD_SPNDEN;
/* Resets transfer data length */
rspi_write32(rspi, 0, QSPI_SPBMUL0);
@ -292,12 +324,12 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
#define set_config_register(spi, n) spi->ops->set_config_register(spi, n)
static void rspi_enable_irq(struct rspi_data *rspi, u8 enable)
static void rspi_enable_irq(const struct rspi_data *rspi, u8 enable)
{
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR);
}
static void rspi_disable_irq(struct rspi_data *rspi, u8 disable)
static void rspi_disable_irq(const struct rspi_data *rspi, u8 disable)
{
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~disable, RSPI_SPCR);
}
@ -316,12 +348,12 @@ static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,
return 0;
}
static void rspi_assert_ssl(struct rspi_data *rspi)
static void rspi_assert_ssl(const struct rspi_data *rspi)
{
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR);
}
static void rspi_negate_ssl(struct rspi_data *rspi)
static void rspi_negate_ssl(const struct rspi_data *rspi)
{
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
}
@ -330,9 +362,7 @@ static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
struct spi_transfer *t)
{
int remain = t->len;
u8 *data;
data = (u8 *)t->tx_buf;
const u8 *data = t->tx_buf;
while (remain > 0) {
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD,
RSPI_SPCR);
@ -348,7 +378,7 @@ static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
remain--;
}
/* Waiting for the last transmition */
/* Waiting for the last transmission */
rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
return 0;
@ -358,12 +388,11 @@ static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
struct spi_transfer *t)
{
int remain = t->len;
u8 *data;
const u8 *data = t->tx_buf;
rspi_write8(rspi, SPBFCR_TXRST, QSPI_SPBFCR);
rspi_write8(rspi, 0x00, QSPI_SPBFCR);
data = (u8 *)t->tx_buf;
while (remain > 0) {
if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
@ -383,7 +412,7 @@ static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
remain--;
}
/* Waiting for the last transmition */
/* Waiting for the last transmission */
rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
return 0;
@ -399,8 +428,8 @@ static void rspi_dma_complete(void *arg)
wake_up_interruptible(&rspi->wait);
}
static int rspi_dma_map_sg(struct scatterlist *sg, void *buf, unsigned len,
struct dma_chan *chan,
static int rspi_dma_map_sg(struct scatterlist *sg, const void *buf,
unsigned len, struct dma_chan *chan,
enum dma_transfer_direction dir)
{
sg_init_table(sg, 1);
@ -440,12 +469,13 @@ static void rspi_memory_from_8bit(void *buf, const void *data, unsigned len)
static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
{
struct scatterlist sg;
void *buf = NULL;
const void *buf = NULL;
struct dma_async_tx_descriptor *desc;
unsigned len;
int ret = 0;
if (rspi->dma_width_16bit) {
void *tmp;
/*
* If DMAC bus width is 16-bit, the driver allocates a dummy
* buffer. And, the driver converts original data into the
@ -454,13 +484,14 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
* DMAC data: 1st byte, dummy, 2nd byte, dummy ...
*/
len = t->len * 2;
buf = kmalloc(len, GFP_KERNEL);
if (!buf)
tmp = kmalloc(len, GFP_KERNEL);
if (!tmp)
return -ENOMEM;
rspi_memory_to_8bit(buf, t->tx_buf, t->len);
rspi_memory_to_8bit(tmp, t->tx_buf, t->len);
buf = tmp;
} else {
len = t->len;
buf = (void *)t->tx_buf;
buf = t->tx_buf;
}
if (!rspi_dma_map_sg(&sg, buf, len, rspi->chan_tx, DMA_TO_DEVICE)) {
@ -508,16 +539,16 @@ end_nomap:
return ret;
}
static void rspi_receive_init(struct rspi_data *rspi)
static void rspi_receive_init(const struct rspi_data *rspi)
{
unsigned char spsr;
u8 spsr;
spsr = rspi_read8(rspi, RSPI_SPSR);
if (spsr & SPSR_SPRF)
rspi_read16(rspi, RSPI_SPDR); /* dummy read */
if (spsr & SPSR_OVRF)
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPSR) & ~SPSR_OVRF,
RSPI_SPCR);
RSPI_SPSR);
}
static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
@ -528,7 +559,7 @@ static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
rspi_receive_init(rspi);
data = (u8 *)t->rx_buf;
data = t->rx_buf;
while (remain > 0) {
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD,
RSPI_SPCR);
@ -539,7 +570,7 @@ static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
return -ETIMEDOUT;
}
/* dummy write for generate clock */
rspi_write16(rspi, 0x00, RSPI_SPDR);
rspi_write16(rspi, DUMMY_DATA, RSPI_SPDR);
if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
dev_err(&rspi->master->dev,
@ -556,9 +587,9 @@ static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
return 0;
}
static void qspi_receive_init(struct rspi_data *rspi)
static void qspi_receive_init(const struct rspi_data *rspi)
{
unsigned char spsr;
u8 spsr;
spsr = rspi_read8(rspi, RSPI_SPSR);
if (spsr & SPSR_SPRF)
@ -575,7 +606,7 @@ static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
qspi_receive_init(rspi);
data = (u8 *)t->rx_buf;
data = t->rx_buf;
while (remain > 0) {
if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
@ -584,7 +615,7 @@ static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
return -ETIMEDOUT;
}
/* dummy write for generate clock */
rspi_write8(rspi, 0x00, RSPI_SPDR);
rspi_write8(rspi, DUMMY_DATA, RSPI_SPDR);
if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
dev_err(&rspi->master->dev,
@ -704,7 +735,7 @@ end_nomap:
return ret;
}
static int rspi_is_dma(struct rspi_data *rspi, struct spi_transfer *t)
static int rspi_is_dma(const struct rspi_data *rspi, struct spi_transfer *t)
{
if (t->tx_buf && rspi->chan_tx)
return 1;
@ -771,10 +802,14 @@ static int rspi_setup(struct spi_device *spi)
{
struct rspi_data *rspi = spi_master_get_devdata(spi->master);
if (!spi->bits_per_word)
spi->bits_per_word = 8;
rspi->max_speed_hz = spi->max_speed_hz;
rspi->spcmd = SPCMD_SSLKP;
if (spi->mode & SPI_CPOL)
rspi->spcmd |= SPCMD_CPOL;
if (spi->mode & SPI_CPHA)
rspi->spcmd |= SPCMD_CPHA;
set_config_register(rspi, 8);
return 0;
@ -802,10 +837,10 @@ static void rspi_cleanup(struct spi_device *spi)
static irqreturn_t rspi_irq(int irq, void *_sr)
{
struct rspi_data *rspi = (struct rspi_data *)_sr;
unsigned long spsr;
struct rspi_data *rspi = _sr;
u8 spsr;
irqreturn_t ret = IRQ_NONE;
unsigned char disable_irq = 0;
u8 disable_irq = 0;
rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
if (spsr & SPSR_SPRF)
@ -825,7 +860,7 @@ 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 = dev_get_platdata(&pdev->dev);
const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dma_cap_mask_t mask;
struct dma_slave_config cfg;
@ -887,11 +922,8 @@ static int rspi_remove(struct platform_device *pdev)
{
struct rspi_data *rspi = platform_get_drvdata(pdev);
spi_unregister_master(rspi->master);
rspi_release_dma(rspi);
free_irq(platform_get_irq(pdev, 0), rspi);
clk_put(rspi->clk);
iounmap(rspi->addr);
clk_disable(rspi->clk);
return 0;
}
@ -903,7 +935,7 @@ static int rspi_probe(struct platform_device *pdev)
struct rspi_data *rspi;
int ret, irq;
char clk_name[16];
struct rspi_plat_data *rspi_pd = pdev->dev.platform_data;
const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
const struct spi_ops *ops;
const struct platform_device_id *id_entry = pdev->id_entry;
@ -913,12 +945,6 @@ static int rspi_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "there is no set_config_register\n");
return -ENODEV;
}
/* get base addr */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (unlikely(res == NULL)) {
dev_err(&pdev->dev, "invalid resource\n");
return -EINVAL;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@ -936,19 +962,20 @@ static int rspi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rspi);
rspi->ops = ops;
rspi->master = master;
rspi->addr = ioremap(res->start, resource_size(res));
if (rspi->addr == NULL) {
dev_err(&pdev->dev, "ioremap error.\n");
ret = -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rspi->addr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(rspi->addr)) {
ret = PTR_ERR(rspi->addr);
goto error1;
}
snprintf(clk_name, sizeof(clk_name), "%s%d", id_entry->name, pdev->id);
rspi->clk = clk_get(&pdev->dev, clk_name);
rspi->clk = devm_clk_get(&pdev->dev, clk_name);
if (IS_ERR(rspi->clk)) {
dev_err(&pdev->dev, "cannot get clock\n");
ret = PTR_ERR(rspi->clk);
goto error2;
goto error1;
}
clk_enable(rspi->clk);
@ -957,45 +984,45 @@ static int rspi_probe(struct platform_device *pdev)
INIT_WORK(&rspi->ws, rspi_work);
init_waitqueue_head(&rspi->wait);
master->num_chipselect = rspi_pd->num_chipselect;
if (!master->num_chipselect)
if (rspi_pd && rspi_pd->num_chipselect)
master->num_chipselect = rspi_pd->num_chipselect;
else
master->num_chipselect = 2; /* default */
master->bus_num = pdev->id;
master->setup = rspi_setup;
master->transfer = rspi_transfer;
master->cleanup = rspi_cleanup;
master->mode_bits = SPI_CPHA | SPI_CPOL;
ret = request_irq(irq, rspi_irq, 0, dev_name(&pdev->dev), rspi);
ret = devm_request_irq(&pdev->dev, irq, rspi_irq, 0,
dev_name(&pdev->dev), rspi);
if (ret < 0) {
dev_err(&pdev->dev, "request_irq error\n");
goto error3;
goto error2;
}
rspi->irq = irq;
ret = rspi_request_dma(rspi, pdev);
if (ret < 0) {
dev_err(&pdev->dev, "rspi_request_dma failed.\n");
goto error4;
goto error3;
}
ret = spi_register_master(master);
ret = devm_spi_register_master(&pdev->dev, master);
if (ret < 0) {
dev_err(&pdev->dev, "spi_register_master error.\n");
goto error4;
goto error3;
}
dev_info(&pdev->dev, "probed\n");
return 0;
error4:
rspi_release_dma(rspi);
free_irq(irq, rspi);
error3:
clk_put(rspi->clk);
rspi_release_dma(rspi);
error2:
iounmap(rspi->addr);
clk_disable(rspi->clk);
error1:
spi_master_put(master);

View File

@ -29,7 +29,6 @@
#include <plat/regs-spi.h>
#include <plat/fiq.h>
#include <asm/fiq.h>
#include "spi-s3c24xx-fiq.h"
@ -78,14 +77,12 @@ struct s3c24xx_spi {
unsigned char *rx;
struct clk *clk;
struct resource *ioarea;
struct spi_master *master;
struct spi_device *curdev;
struct device *dev;
struct s3c2410_spi_info *pdata;
};
#define SPCON_DEFAULT (S3C2410_SPCON_MSTR | S3C2410_SPCON_SMOD_INT)
#define SPPIN_DEFAULT (S3C2410_SPPIN_KEEP)
@ -517,8 +514,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));
if (master == NULL) {
dev_err(&pdev->dev, "No memory for spi_master\n");
err = -ENOMEM;
goto err_nomem;
return -ENOMEM;
}
hw = spi_master_get_devdata(master);
@ -562,48 +558,32 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
/* find and map our resources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
err = -ENOENT;
goto err_no_iores;
}
hw->ioarea = request_mem_region(res->start, resource_size(res),
pdev->name);
if (hw->ioarea == NULL) {
dev_err(&pdev->dev, "Cannot reserve region\n");
err = -ENXIO;
goto err_no_iores;
}
hw->regs = ioremap(res->start, resource_size(res));
if (hw->regs == NULL) {
dev_err(&pdev->dev, "Cannot map IO\n");
err = -ENXIO;
goto err_no_iomap;
hw->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(hw->regs)) {
err = PTR_ERR(hw->regs);
goto err_no_pdata;
}
hw->irq = platform_get_irq(pdev, 0);
if (hw->irq < 0) {
dev_err(&pdev->dev, "No IRQ specified\n");
err = -ENOENT;
goto err_no_irq;
goto err_no_pdata;
}
err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw);
err = devm_request_irq(&pdev->dev, hw->irq, s3c24xx_spi_irq, 0,
pdev->name, hw);
if (err) {
dev_err(&pdev->dev, "Cannot claim IRQ\n");
goto err_no_irq;
goto err_no_pdata;
}
hw->clk = clk_get(&pdev->dev, "spi");
hw->clk = devm_clk_get(&pdev->dev, "spi");
if (IS_ERR(hw->clk)) {
dev_err(&pdev->dev, "No clock for device\n");
err = PTR_ERR(hw->clk);
goto err_no_clk;
goto err_no_pdata;
}
/* setup any gpio we can */
@ -615,7 +595,8 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
goto err_register;
}
err = gpio_request(pdata->pin_cs, dev_name(&pdev->dev));
err = devm_gpio_request(&pdev->dev, pdata->pin_cs,
dev_name(&pdev->dev));
if (err) {
dev_err(&pdev->dev, "Failed to get gpio for cs\n");
goto err_register;
@ -639,27 +620,10 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
return 0;
err_register:
if (hw->set_cs == s3c24xx_spi_gpiocs)
gpio_free(pdata->pin_cs);
clk_disable(hw->clk);
clk_put(hw->clk);
err_no_clk:
free_irq(hw->irq, hw);
err_no_irq:
iounmap(hw->regs);
err_no_iomap:
release_resource(hw->ioarea);
kfree(hw->ioarea);
err_no_iores:
err_no_pdata:
spi_master_put(hw->master);
err_nomem:
return err;
}
@ -668,19 +632,7 @@ static int s3c24xx_spi_remove(struct platform_device *dev)
struct s3c24xx_spi *hw = platform_get_drvdata(dev);
spi_bitbang_stop(&hw->bitbang);
clk_disable(hw->clk);
clk_put(hw->clk);
free_irq(hw->irq, hw);
iounmap(hw->regs);
if (hw->set_cs == s3c24xx_spi_gpiocs)
gpio_free(hw->pdata->pin_cs);
release_resource(hw->ioarea);
kfree(hw->ioarea);
spi_master_put(hw->master);
return 0;
}

View File

@ -890,7 +890,7 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
unsigned long flags;
int use_dma;
reinit_completion(&sdd->xfer_completion);
reinit_completion(&sdd->xfer_completion);
/* Only BPW and Speed may change across transfers */
bpw = xfer->bits_per_word;
@ -927,9 +927,6 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
/* Start the signals */
writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
/* Start the signals */
writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
spin_unlock_irqrestore(&sdd->lock, flags);
status = wait_for_xfer(sdd, xfer, use_dma);

View File

@ -183,18 +183,11 @@ static int sc18is602_setup_transfer(struct sc18is602 *hw, u32 hz, u8 mode)
static int sc18is602_check_transfer(struct spi_device *spi,
struct spi_transfer *t, int tlen)
{
int bpw;
uint32_t hz;
if (t && t->len + tlen > SC18IS602_BUFSIZ)
return -EINVAL;
bpw = spi->bits_per_word;
if (t && t->bits_per_word)
bpw = t->bits_per_word;
if (bpw != 8)
return -EINVAL;
hz = spi->max_speed_hz;
if (t && t->speed_hz)
hz = t->speed_hz;
@ -254,9 +247,6 @@ error:
static int sc18is602_setup(struct spi_device *spi)
{
if (!spi->bits_per_word)
spi->bits_per_word = 8;
if (spi->mode & ~(SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST))
return -EINVAL;
@ -315,11 +305,12 @@ static int sc18is602_probe(struct i2c_client *client,
}
master->bus_num = client->adapter->nr;
master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST;
master->bits_per_word_mask = SPI_BPW_MASK(8);
master->setup = sc18is602_setup;
master->transfer_one_message = sc18is602_transfer_one;
master->dev.of_node = np;
error = spi_register_master(master);
error = devm_spi_register_master(dev, master);
if (error)
goto error_reg;
@ -330,16 +321,6 @@ error_reg:
return error;
}
static int sc18is602_remove(struct i2c_client *client)
{
struct sc18is602 *hw = i2c_get_clientdata(client);
struct spi_master *master = hw->master;
spi_unregister_master(master);
return 0;
}
static const struct i2c_device_id sc18is602_id[] = {
{ "sc18is602", sc18is602 },
{ "sc18is602b", sc18is602b },
@ -353,7 +334,6 @@ static struct i2c_driver sc18is602_driver = {
.name = "sc18is602",
},
.probe = sc18is602_probe,
.remove = sc18is602_remove,
.id_table = sc18is602_id,
};

View File

@ -197,7 +197,7 @@ static int hspi_transfer_one_message(struct spi_master *master,
hspi_write(hspi, SPTBR, tx);
/* wait recive */
/* wait receive */
ret = hspi_status_check_timeout(hspi, 0x4, 0x4);
if (ret < 0)
break;
@ -353,4 +353,4 @@ module_platform_driver(hspi_driver);
MODULE_DESCRIPTION("SuperH HSPI bus driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
MODULE_ALIAS("platform:sh_spi");
MODULE_ALIAS("platform:sh-hspi");

View File

@ -152,7 +152,7 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
size_t k;
if (!WARN_ON(!spi_hz || !parent_rate))
div = parent_rate / spi_hz;
div = DIV_ROUND_UP(parent_rate, spi_hz);
/* TODO: make more fine grained */
@ -169,7 +169,7 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
u32 cpol, u32 cpha,
u32 tx_hi_z, u32 lsb_first)
u32 tx_hi_z, u32 lsb_first, u32 cs_high)
{
u32 tmp;
int edge;
@ -182,8 +182,12 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
* 1 1 11 11 1 1
*/
sh_msiof_write(p, FCTR, 0);
sh_msiof_write(p, TMDR1, 0xe2000005 | (lsb_first << 24));
sh_msiof_write(p, RMDR1, 0x22000005 | (lsb_first << 24));
tmp = 0;
tmp |= !cs_high << 25;
tmp |= lsb_first << 24;
sh_msiof_write(p, TMDR1, 0xe0000005 | tmp);
sh_msiof_write(p, RMDR1, 0x20000005 | tmp);
tmp = 0xa0000000;
tmp |= cpol << 30; /* TSCKIZ */
@ -417,11 +421,12 @@ static void sh_msiof_spi_chipselect(struct spi_device *spi, int is_on)
sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL),
!!(spi->mode & SPI_CPHA),
!!(spi->mode & SPI_3WIRE),
!!(spi->mode & SPI_LSB_FIRST));
!!(spi->mode & SPI_LSB_FIRST),
!!(spi->mode & SPI_CS_HIGH));
}
/* use spi->controller data for CS (same strategy as spi_gpio) */
gpio_set_value((unsigned)spi->controller_data, value);
gpio_set_value((uintptr_t)spi->controller_data, value);
if (is_on == BITBANG_CS_INACTIVE) {
if (test_and_clear_bit(0, &p->flags)) {
@ -635,8 +640,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv));
if (master == NULL) {
dev_err(&pdev->dev, "failed to allocate spi master\n");
ret = -ENOMEM;
goto err0;
return -ENOMEM;
}
p = spi_master_get_devdata(master);
@ -655,32 +659,38 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
init_completion(&p->done);
p->clk = clk_get(&pdev->dev, NULL);
p->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(p->clk)) {
dev_err(&pdev->dev, "cannot get clock\n");
ret = PTR_ERR(p->clk);
goto err1;
}
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
i = platform_get_irq(pdev, 0);
if (!r || i < 0) {
dev_err(&pdev->dev, "cannot get platform resources\n");
if (i < 0) {
dev_err(&pdev->dev, "cannot get platform IRQ\n");
ret = -ENOENT;
goto err2;
}
p->mapbase = ioremap_nocache(r->start, resource_size(r));
if (!p->mapbase) {
dev_err(&pdev->dev, "unable to ioremap\n");
ret = -ENXIO;
goto err2;
goto err1;
}
ret = request_irq(i, sh_msiof_spi_irq, 0,
dev_name(&pdev->dev), p);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
p->mapbase = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(p->mapbase)) {
ret = PTR_ERR(p->mapbase);
goto err1;
}
ret = devm_request_irq(&pdev->dev, i, sh_msiof_spi_irq, 0,
dev_name(&pdev->dev), p);
if (ret) {
dev_err(&pdev->dev, "unable to request irq\n");
goto err3;
goto err1;
}
ret = clk_prepare(p->clk);
if (ret < 0) {
dev_err(&pdev->dev, "unable to prepare clock\n");
goto err1;
}
p->pdev = pdev;
@ -719,13 +729,9 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
return 0;
pm_runtime_disable(&pdev->dev);
err3:
iounmap(p->mapbase);
err2:
clk_put(p->clk);
clk_unprepare(p->clk);
err1:
spi_master_put(master);
err0:
return ret;
}
@ -737,9 +743,7 @@ static int sh_msiof_spi_remove(struct platform_device *pdev)
ret = spi_bitbang_stop(&p->bitbang);
if (!ret) {
pm_runtime_disable(&pdev->dev);
free_irq(platform_get_irq(pdev, 0), p);
iounmap(p->mapbase);
clk_put(p->clk);
clk_unprepare(p->clk);
spi_master_put(p->bitbang.master);
}
return ret;

View File

@ -171,7 +171,6 @@ static int spi_sh_send(struct spi_sh_data *ss, struct spi_message *mesg,
int remain = t->len;
int cur_len;
unsigned char *data;
unsigned long tmp;
long ret;
if (t->len)
@ -213,9 +212,7 @@ static int spi_sh_send(struct spi_sh_data *ss, struct spi_message *mesg,
}
if (list_is_last(&t->transfer_list, &mesg->transfers)) {
tmp = spi_sh_read(ss, SPI_SH_CR1);
tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB);
spi_sh_write(ss, tmp, SPI_SH_CR1);
spi_sh_clear_bit(ss, SPI_SH_SSD | SPI_SH_SSDB, SPI_SH_CR1);
spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
ss->cr1 &= ~SPI_SH_TBE;
@ -239,7 +236,6 @@ static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg,
int remain = t->len;
int cur_len;
unsigned char *data;
unsigned long tmp;
long ret;
if (t->len > SPI_SH_MAX_BYTE)
@ -247,9 +243,7 @@ static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg,
else
spi_sh_write(ss, t->len, SPI_SH_CR3);
tmp = spi_sh_read(ss, SPI_SH_CR1);
tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB);
spi_sh_write(ss, tmp, SPI_SH_CR1);
spi_sh_clear_bit(ss, SPI_SH_SSD | SPI_SH_SSDB, SPI_SH_CR1);
spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
spi_sh_wait_write_buffer_empty(ss);
@ -358,9 +352,6 @@ static int spi_sh_setup(struct spi_device *spi)
{
struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
if (!spi->bits_per_word)
spi->bits_per_word = 8;
pr_debug("%s: enter\n", __func__);
spi_sh_write(ss, 0xfe, SPI_SH_CR1); /* SPI sycle stop */

View File

@ -536,16 +536,9 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
static int spi_sirfsoc_setup(struct spi_device *spi)
{
struct sirfsoc_spi *sspi;
if (!spi->max_speed_hz)
return -EINVAL;
sspi = spi_master_get_devdata(spi->master);
if (!spi->bits_per_word)
spi->bits_per_word = 8;
return spi_sirfsoc_setup_transfer(spi, NULL);
}

View File

@ -54,11 +54,8 @@
#define SPI_CS_SS_VAL (1 << 20)
#define SPI_CS_SW_HW (1 << 21)
/* SPI_CS_POL_INACTIVE bits are default high */
#define SPI_CS_POL_INACTIVE 22
#define SPI_CS_POL_INACTIVE_0 (1 << 22)
#define SPI_CS_POL_INACTIVE_1 (1 << 23)
#define SPI_CS_POL_INACTIVE_2 (1 << 24)
#define SPI_CS_POL_INACTIVE_3 (1 << 25)
/* n from 0 to 3 */
#define SPI_CS_POL_INACTIVE(n) (1 << (22 + (n)))
#define SPI_CS_POL_INACTIVE_MASK (0xF << 22)
#define SPI_CS_SEL_0 (0 << 26)
@ -165,9 +162,6 @@
#define MAX_HOLD_CYCLES 16
#define SPI_DEFAULT_SPEED 25000000
#define MAX_CHIP_SELECT 4
#define SPI_FIFO_DEPTH 64
struct tegra_spi_data {
struct device *dev;
struct spi_master *master;
@ -184,7 +178,6 @@ struct tegra_spi_data {
struct spi_device *cur_spi;
struct spi_device *cs_control;
unsigned cur_pos;
unsigned cur_len;
unsigned words_per_32bit;
unsigned bytes_per_word;
unsigned curr_dma_words;
@ -204,12 +197,10 @@ struct tegra_spi_data {
u32 rx_status;
u32 status_reg;
bool is_packed;
unsigned long packed_size;
u32 command1_reg;
u32 dma_control_reg;
u32 def_command1_reg;
u32 spi_cs_timing;
struct completion xfer_completion;
struct spi_transfer *curr_xfer;
@ -227,14 +218,14 @@ struct tegra_spi_data {
static int tegra_spi_runtime_suspend(struct device *dev);
static int tegra_spi_runtime_resume(struct device *dev);
static inline unsigned long tegra_spi_readl(struct tegra_spi_data *tspi,
static inline u32 tegra_spi_readl(struct tegra_spi_data *tspi,
unsigned long reg)
{
return readl(tspi->base + reg);
}
static inline void tegra_spi_writel(struct tegra_spi_data *tspi,
unsigned long val, unsigned long reg)
u32 val, unsigned long reg)
{
writel(val, tspi->base + reg);
@ -245,7 +236,7 @@ static inline void tegra_spi_writel(struct tegra_spi_data *tspi,
static void tegra_spi_clear_status(struct tegra_spi_data *tspi)
{
unsigned long val;
u32 val;
/* Write 1 to clear status register */
val = tegra_spi_readl(tspi, SPI_TRANS_STATUS);
@ -296,10 +287,9 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
{
unsigned nbytes;
unsigned tx_empty_count;
unsigned long fifo_status;
u32 fifo_status;
unsigned max_n_32bit;
unsigned i, count;
unsigned long x;
unsigned int written_words;
unsigned fifo_words_left;
u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
@ -313,9 +303,9 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
nbytes = written_words * tspi->bytes_per_word;
max_n_32bit = DIV_ROUND_UP(nbytes, 4);
for (count = 0; count < max_n_32bit; count++) {
x = 0;
u32 x = 0;
for (i = 0; (i < 4) && nbytes; i++, nbytes--)
x |= (*tx_buf++) << (i*8);
x |= (u32)(*tx_buf++) << (i * 8);
tegra_spi_writel(tspi, x, SPI_TX_FIFO);
}
} else {
@ -323,10 +313,10 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
written_words = max_n_32bit;
nbytes = written_words * tspi->bytes_per_word;
for (count = 0; count < max_n_32bit; count++) {
x = 0;
u32 x = 0;
for (i = 0; nbytes && (i < tspi->bytes_per_word);
i++, nbytes--)
x |= ((*tx_buf++) << i*8);
x |= (u32)(*tx_buf++) << (i * 8);
tegra_spi_writel(tspi, x, SPI_TX_FIFO);
}
}
@ -338,9 +328,8 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf(
struct tegra_spi_data *tspi, struct spi_transfer *t)
{
unsigned rx_full_count;
unsigned long fifo_status;
u32 fifo_status;
unsigned i, count;
unsigned long x;
unsigned int read_words = 0;
unsigned len;
u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_rx_pos;
@ -350,20 +339,16 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf(
if (tspi->is_packed) {
len = tspi->curr_dma_words * tspi->bytes_per_word;
for (count = 0; count < rx_full_count; count++) {
x = tegra_spi_readl(tspi, SPI_RX_FIFO);
u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO);
for (i = 0; len && (i < 4); i++, len--)
*rx_buf++ = (x >> i*8) & 0xFF;
}
tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
read_words += tspi->curr_dma_words;
} else {
unsigned int rx_mask;
unsigned int bits_per_word = t->bits_per_word;
rx_mask = (1 << bits_per_word) - 1;
u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
for (count = 0; count < rx_full_count; count++) {
x = tegra_spi_readl(tspi, SPI_RX_FIFO);
x &= rx_mask;
u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO) & rx_mask;
for (i = 0; (i < tspi->bytes_per_word); i++)
*rx_buf++ = (x >> (i*8)) & 0xFF;
}
@ -376,27 +361,24 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf(
static void tegra_spi_copy_client_txbuf_to_spi_txbuf(
struct tegra_spi_data *tspi, struct spi_transfer *t)
{
unsigned len;
/* Make the dma buffer to read by cpu */
dma_sync_single_for_cpu(tspi->dev, tspi->tx_dma_phys,
tspi->dma_buf_size, DMA_TO_DEVICE);
if (tspi->is_packed) {
len = tspi->curr_dma_words * tspi->bytes_per_word;
unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len);
} else {
unsigned int i;
unsigned int count;
u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word;
unsigned int x;
for (count = 0; count < tspi->curr_dma_words; count++) {
x = 0;
u32 x = 0;
for (i = 0; consume && (i < tspi->bytes_per_word);
i++, consume--)
x |= ((*tx_buf++) << i * 8);
x |= (u32)(*tx_buf++) << (i * 8);
tspi->tx_dma_buf[count] = x;
}
}
@ -410,27 +392,21 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf(
static void tegra_spi_copy_spi_rxbuf_to_client_rxbuf(
struct tegra_spi_data *tspi, struct spi_transfer *t)
{
unsigned len;
/* Make the dma buffer to read by cpu */
dma_sync_single_for_cpu(tspi->dev, tspi->rx_dma_phys,
tspi->dma_buf_size, DMA_FROM_DEVICE);
if (tspi->is_packed) {
len = tspi->curr_dma_words * tspi->bytes_per_word;
unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
memcpy(t->rx_buf + tspi->cur_rx_pos, tspi->rx_dma_buf, len);
} else {
unsigned int i;
unsigned int count;
unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos;
unsigned int x;
unsigned int rx_mask;
unsigned int bits_per_word = t->bits_per_word;
u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
rx_mask = (1 << bits_per_word) - 1;
for (count = 0; count < tspi->curr_dma_words; count++) {
x = tspi->rx_dma_buf[count];
x &= rx_mask;
u32 x = tspi->rx_dma_buf[count] & rx_mask;
for (i = 0; (i < tspi->bytes_per_word); i++)
*rx_buf++ = (x >> (i*8)) & 0xFF;
}
@ -490,16 +466,16 @@ static int tegra_spi_start_rx_dma(struct tegra_spi_data *tspi, int len)
static int tegra_spi_start_dma_based_transfer(
struct tegra_spi_data *tspi, struct spi_transfer *t)
{
unsigned long val;
u32 val;
unsigned int len;
int ret = 0;
unsigned long status;
u32 status;
/* Make sure that Rx and Tx fifo are empty */
status = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) {
dev_err(tspi->dev,
"Rx/Tx fifo are not empty status 0x%08lx\n", status);
dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n",
(unsigned)status);
return -EIO;
}
@ -564,7 +540,7 @@ static int tegra_spi_start_dma_based_transfer(
static int tegra_spi_start_cpu_based_transfer(
struct tegra_spi_data *tspi, struct spi_transfer *t)
{
unsigned long val;
u32 val;
unsigned cur_words;
if (tspi->cur_direction & DATA_DIR_TX)
@ -676,13 +652,13 @@ static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi,
dma_release_channel(dma_chan);
}
static unsigned long tegra_spi_setup_transfer_one(struct spi_device *spi,
static u32 tegra_spi_setup_transfer_one(struct spi_device *spi,
struct spi_transfer *t, bool is_first_of_msg)
{
struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
u32 speed = t->speed_hz;
u8 bits_per_word = t->bits_per_word;
unsigned long command1;
u32 command1;
int req_mode;
if (speed != tspi->cur_speed) {
@ -737,7 +713,7 @@ static unsigned long tegra_spi_setup_transfer_one(struct spi_device *spi,
}
static int tegra_spi_start_transfer_one(struct spi_device *spi,
struct spi_transfer *t, unsigned long command1)
struct spi_transfer *t, u32 command1)
{
struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
unsigned total_fifo_words;
@ -762,8 +738,8 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi,
tegra_spi_writel(tspi, command1, SPI_COMMAND1);
tspi->command1_reg = command1;
dev_dbg(tspi->dev, "The def 0x%x and written 0x%lx\n",
tspi->def_command1_reg, command1);
dev_dbg(tspi->dev, "The def 0x%x and written 0x%x\n",
tspi->def_command1_reg, (unsigned)command1);
if (total_fifo_words > SPI_FIFO_DEPTH)
ret = tegra_spi_start_dma_based_transfer(tspi, t);
@ -775,15 +751,9 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi,
static int tegra_spi_setup(struct spi_device *spi)
{
struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
unsigned long val;
u32 val;
unsigned long flags;
int ret;
unsigned int cs_pol_bit[MAX_CHIP_SELECT] = {
SPI_CS_POL_INACTIVE_0,
SPI_CS_POL_INACTIVE_1,
SPI_CS_POL_INACTIVE_2,
SPI_CS_POL_INACTIVE_3,
};
dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n",
spi->bits_per_word,
@ -805,9 +775,9 @@ static int tegra_spi_setup(struct spi_device *spi)
spin_lock_irqsave(&tspi->lock, flags);
val = tspi->def_command1_reg;
if (spi->mode & SPI_CS_HIGH)
val &= ~cs_pol_bit[spi->chip_select];
val &= ~SPI_CS_POL_INACTIVE(spi->chip_select);
else
val |= cs_pol_bit[spi->chip_select];
val |= SPI_CS_POL_INACTIVE(spi->chip_select);
tspi->def_command1_reg = val;
tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
spin_unlock_irqrestore(&tspi->lock, flags);
@ -841,7 +811,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
msg->actual_length = 0;
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
unsigned long cmd1;
u32 cmd1;
reinit_completion(&tspi->xfer_completion);

View File

@ -149,14 +149,14 @@ struct tegra_sflash_data {
static int tegra_sflash_runtime_suspend(struct device *dev);
static int tegra_sflash_runtime_resume(struct device *dev);
static inline unsigned long tegra_sflash_readl(struct tegra_sflash_data *tsd,
static inline u32 tegra_sflash_readl(struct tegra_sflash_data *tsd,
unsigned long reg)
{
return readl(tsd->base + reg);
}
static inline void tegra_sflash_writel(struct tegra_sflash_data *tsd,
unsigned long val, unsigned long reg)
u32 val, unsigned long reg)
{
writel(val, tsd->base + reg);
}
@ -186,7 +186,7 @@ static unsigned tegra_sflash_fill_tx_fifo_from_client_txbuf(
struct tegra_sflash_data *tsd, struct spi_transfer *t)
{
unsigned nbytes;
unsigned long status;
u32 status;
unsigned max_n_32bit = tsd->curr_xfer_words;
u8 *tx_buf = (u8 *)t->tx_buf + tsd->cur_tx_pos;
@ -197,11 +197,11 @@ static unsigned tegra_sflash_fill_tx_fifo_from_client_txbuf(
status = tegra_sflash_readl(tsd, SPI_STATUS);
while (!(status & SPI_TXF_FULL)) {
int i;
unsigned int x = 0;
u32 x = 0;
for (i = 0; nbytes && (i < tsd->bytes_per_word);
i++, nbytes--)
x |= ((*tx_buf++) << i*8);
x |= (u32)(*tx_buf++) << (i * 8);
tegra_sflash_writel(tsd, x, SPI_TX_FIFO);
if (!nbytes)
break;
@ -215,16 +215,14 @@ static unsigned tegra_sflash_fill_tx_fifo_from_client_txbuf(
static int tegra_sflash_read_rx_fifo_to_client_rxbuf(
struct tegra_sflash_data *tsd, struct spi_transfer *t)
{
unsigned long status;
u32 status;
unsigned int read_words = 0;
u8 *rx_buf = (u8 *)t->rx_buf + tsd->cur_rx_pos;
status = tegra_sflash_readl(tsd, SPI_STATUS);
while (!(status & SPI_RXF_EMPTY)) {
int i;
unsigned long x;
x = tegra_sflash_readl(tsd, SPI_RX_FIFO);
u32 x = tegra_sflash_readl(tsd, SPI_RX_FIFO);
for (i = 0; (i < tsd->bytes_per_word); i++)
*rx_buf++ = (x >> (i*8)) & 0xFF;
read_words++;
@ -237,7 +235,7 @@ static int tegra_sflash_read_rx_fifo_to_client_rxbuf(
static int tegra_sflash_start_cpu_based_transfer(
struct tegra_sflash_data *tsd, struct spi_transfer *t)
{
unsigned long val = 0;
u32 val = 0;
unsigned cur_words;
if (tsd->cur_direction & DATA_DIR_TX)
@ -267,7 +265,7 @@ static int tegra_sflash_start_transfer_one(struct spi_device *spi,
{
struct tegra_sflash_data *tsd = spi_master_get_devdata(spi->master);
u32 speed;
unsigned long command;
u32 command;
speed = t->speed_hz;
if (speed != tsd->cur_speed) {
@ -314,7 +312,7 @@ static int tegra_sflash_start_transfer_one(struct spi_device *spi,
tegra_sflash_writel(tsd, command, SPI_COMMAND);
tsd->command_reg = command;
return tegra_sflash_start_cpu_based_transfer(tsd, t);
return tegra_sflash_start_cpu_based_transfer(tsd, t);
}
static int tegra_sflash_setup(struct spi_device *spi)

View File

@ -196,7 +196,7 @@ struct tegra_slink_data {
u32 rx_status;
u32 status_reg;
bool is_packed;
unsigned long packed_size;
u32 packed_size;
u32 command_reg;
u32 command2_reg;
@ -220,14 +220,14 @@ struct tegra_slink_data {
static int tegra_slink_runtime_suspend(struct device *dev);
static int tegra_slink_runtime_resume(struct device *dev);
static inline unsigned long tegra_slink_readl(struct tegra_slink_data *tspi,
static inline u32 tegra_slink_readl(struct tegra_slink_data *tspi,
unsigned long reg)
{
return readl(tspi->base + reg);
}
static inline void tegra_slink_writel(struct tegra_slink_data *tspi,
unsigned long val, unsigned long reg)
u32 val, unsigned long reg)
{
writel(val, tspi->base + reg);
@ -238,38 +238,30 @@ static inline void tegra_slink_writel(struct tegra_slink_data *tspi,
static void tegra_slink_clear_status(struct tegra_slink_data *tspi)
{
unsigned long val;
unsigned long val_write = 0;
u32 val_write;
val = tegra_slink_readl(tspi, SLINK_STATUS);
tegra_slink_readl(tspi, SLINK_STATUS);
/* Write 1 to clear status register */
val_write = SLINK_RDY | SLINK_FIFO_ERROR;
tegra_slink_writel(tspi, val_write, SLINK_STATUS);
}
static unsigned long tegra_slink_get_packed_size(struct tegra_slink_data *tspi,
static u32 tegra_slink_get_packed_size(struct tegra_slink_data *tspi,
struct spi_transfer *t)
{
unsigned long val;
switch (tspi->bytes_per_word) {
case 0:
val = SLINK_PACK_SIZE_4;
break;
return SLINK_PACK_SIZE_4;
case 1:
val = SLINK_PACK_SIZE_8;
break;
return SLINK_PACK_SIZE_8;
case 2:
val = SLINK_PACK_SIZE_16;
break;
return SLINK_PACK_SIZE_16;
case 4:
val = SLINK_PACK_SIZE_32;
break;
return SLINK_PACK_SIZE_32;
default:
val = 0;
return 0;
}
return val;
}
static unsigned tegra_slink_calculate_curr_xfer_param(
@ -312,10 +304,9 @@ static unsigned tegra_slink_fill_tx_fifo_from_client_txbuf(
{
unsigned nbytes;
unsigned tx_empty_count;
unsigned long fifo_status;
u32 fifo_status;
unsigned max_n_32bit;
unsigned i, count;
unsigned long x;
unsigned int written_words;
unsigned fifo_words_left;
u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
@ -329,9 +320,9 @@ static unsigned tegra_slink_fill_tx_fifo_from_client_txbuf(
nbytes = written_words * tspi->bytes_per_word;
max_n_32bit = DIV_ROUND_UP(nbytes, 4);
for (count = 0; count < max_n_32bit; count++) {
x = 0;
u32 x = 0;
for (i = 0; (i < 4) && nbytes; i++, nbytes--)
x |= (*tx_buf++) << (i*8);
x |= (u32)(*tx_buf++) << (i * 8);
tegra_slink_writel(tspi, x, SLINK_TX_FIFO);
}
} else {
@ -339,10 +330,10 @@ static unsigned tegra_slink_fill_tx_fifo_from_client_txbuf(
written_words = max_n_32bit;
nbytes = written_words * tspi->bytes_per_word;
for (count = 0; count < max_n_32bit; count++) {
x = 0;
u32 x = 0;
for (i = 0; nbytes && (i < tspi->bytes_per_word);
i++, nbytes--)
x |= ((*tx_buf++) << i*8);
x |= (u32)(*tx_buf++) << (i * 8);
tegra_slink_writel(tspi, x, SLINK_TX_FIFO);
}
}
@ -354,9 +345,8 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
struct tegra_slink_data *tspi, struct spi_transfer *t)
{
unsigned rx_full_count;
unsigned long fifo_status;
u32 fifo_status;
unsigned i, count;
unsigned long x;
unsigned int read_words = 0;
unsigned len;
u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_rx_pos;
@ -366,7 +356,7 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
if (tspi->is_packed) {
len = tspi->curr_dma_words * tspi->bytes_per_word;
for (count = 0; count < rx_full_count; count++) {
x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
u32 x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
for (i = 0; len && (i < 4); i++, len--)
*rx_buf++ = (x >> i*8) & 0xFF;
}
@ -374,7 +364,7 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
read_words += tspi->curr_dma_words;
} else {
for (count = 0; count < rx_full_count; count++) {
x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
u32 x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
for (i = 0; (i < tspi->bytes_per_word); i++)
*rx_buf++ = (x >> (i*8)) & 0xFF;
}
@ -387,27 +377,24 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
static void tegra_slink_copy_client_txbuf_to_spi_txbuf(
struct tegra_slink_data *tspi, struct spi_transfer *t)
{
unsigned len;
/* Make the dma buffer to read by cpu */
dma_sync_single_for_cpu(tspi->dev, tspi->tx_dma_phys,
tspi->dma_buf_size, DMA_TO_DEVICE);
if (tspi->is_packed) {
len = tspi->curr_dma_words * tspi->bytes_per_word;
unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len);
} else {
unsigned int i;
unsigned int count;
u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word;
unsigned int x;
for (count = 0; count < tspi->curr_dma_words; count++) {
x = 0;
u32 x = 0;
for (i = 0; consume && (i < tspi->bytes_per_word);
i++, consume--)
x |= ((*tx_buf++) << i * 8);
x |= (u32)(*tx_buf++) << (i * 8);
tspi->tx_dma_buf[count] = x;
}
}
@ -434,14 +421,10 @@ static void tegra_slink_copy_spi_rxbuf_to_client_rxbuf(
unsigned int i;
unsigned int count;
unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos;
unsigned int x;
unsigned int rx_mask, bits_per_word;
u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
bits_per_word = t->bits_per_word;
rx_mask = (1 << bits_per_word) - 1;
for (count = 0; count < tspi->curr_dma_words; count++) {
x = tspi->rx_dma_buf[count];
x &= rx_mask;
u32 x = tspi->rx_dma_buf[count] & rx_mask;
for (i = 0; (i < tspi->bytes_per_word); i++)
*rx_buf++ = (x >> (i*8)) & 0xFF;
}
@ -501,17 +484,16 @@ static int tegra_slink_start_rx_dma(struct tegra_slink_data *tspi, int len)
static int tegra_slink_start_dma_based_transfer(
struct tegra_slink_data *tspi, struct spi_transfer *t)
{
unsigned long val;
unsigned long test_val;
u32 val;
unsigned int len;
int ret = 0;
unsigned long status;
u32 status;
/* Make sure that Rx and Tx fifo are empty */
status = tegra_slink_readl(tspi, SLINK_STATUS);
if ((status & SLINK_FIFO_EMPTY) != SLINK_FIFO_EMPTY) {
dev_err(tspi->dev,
"Rx/Tx fifo are not empty status 0x%08lx\n", status);
dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n",
(unsigned)status);
return -EIO;
}
@ -551,9 +533,9 @@ static int tegra_slink_start_dma_based_transfer(
}
/* Wait for tx fifo to be fill before starting slink */
test_val = tegra_slink_readl(tspi, SLINK_STATUS);
while (!(test_val & SLINK_TX_FULL))
test_val = tegra_slink_readl(tspi, SLINK_STATUS);
status = tegra_slink_readl(tspi, SLINK_STATUS);
while (!(status & SLINK_TX_FULL))
status = tegra_slink_readl(tspi, SLINK_STATUS);
}
if (tspi->cur_direction & DATA_DIR_RX) {
@ -587,7 +569,7 @@ static int tegra_slink_start_dma_based_transfer(
static int tegra_slink_start_cpu_based_transfer(
struct tegra_slink_data *tspi, struct spi_transfer *t)
{
unsigned long val;
u32 val;
unsigned cur_words;
val = tspi->packed_size;
@ -713,8 +695,8 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi,
u8 bits_per_word;
unsigned total_fifo_words;
int ret;
unsigned long command;
unsigned long command2;
u32 command;
u32 command2;
bits_per_word = t->bits_per_word;
speed = t->speed_hz;
@ -761,17 +743,18 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi,
static int tegra_slink_setup(struct spi_device *spi)
{
struct tegra_slink_data *tspi = spi_master_get_devdata(spi->master);
unsigned long val;
unsigned long flags;
int ret;
unsigned int cs_pol_bit[MAX_CHIP_SELECT] = {
static const u32 cs_pol_bit[MAX_CHIP_SELECT] = {
SLINK_CS_POLARITY,
SLINK_CS_POLARITY1,
SLINK_CS_POLARITY2,
SLINK_CS_POLARITY3,
};
struct tegra_slink_data *tspi = spi_master_get_devdata(spi->master);
u32 val;
unsigned long flags;
int ret;
dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n",
spi->bits_per_word,
spi->mode & SPI_CPOL ? "" : "~",

View File

@ -46,6 +46,8 @@ struct ti_qspi {
struct spi_master *master;
void __iomem *base;
void __iomem *ctrl_base;
void __iomem *mmap_base;
struct clk *fclk;
struct device *dev;
@ -54,6 +56,8 @@ struct ti_qspi {
u32 spi_max_frequency;
u32 cmd;
u32 dc;
bool ctrl_mod;
};
#define QSPI_PID (0x0)
@ -204,53 +208,36 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
txbuf = t->tx_buf;
cmd = qspi->cmd | QSPI_WR_SNGL;
count = t->len;
wlen = t->bits_per_word;
wlen = t->bits_per_word >> 3; /* in bytes */
while (count) {
switch (wlen) {
case 8:
case 1:
dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %02x\n",
cmd, qspi->dc, *txbuf);
writeb(*txbuf, qspi->base + QSPI_SPI_DATA_REG);
ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
ret = wait_for_completion_timeout(&qspi->transfer_complete,
QSPI_COMPLETION_TIMEOUT);
if (ret == 0) {
dev_err(qspi->dev, "write timed out\n");
return -ETIMEDOUT;
}
txbuf += 1;
count -= 1;
break;
case 16:
case 2:
dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %04x\n",
cmd, qspi->dc, *txbuf);
writew(*((u16 *)txbuf), qspi->base + QSPI_SPI_DATA_REG);
ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
ret = wait_for_completion_timeout(&qspi->transfer_complete,
QSPI_COMPLETION_TIMEOUT);
if (ret == 0) {
dev_err(qspi->dev, "write timed out\n");
return -ETIMEDOUT;
}
txbuf += 2;
count -= 2;
break;
case 32:
case 4:
dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %08x\n",
cmd, qspi->dc, *txbuf);
writel(*((u32 *)txbuf), qspi->base + QSPI_SPI_DATA_REG);
ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
ret = wait_for_completion_timeout(&qspi->transfer_complete,
QSPI_COMPLETION_TIMEOUT);
if (ret == 0) {
dev_err(qspi->dev, "write timed out\n");
return -ETIMEDOUT;
}
txbuf += 4;
count -= 4;
break;
}
ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
ret = wait_for_completion_timeout(&qspi->transfer_complete,
QSPI_COMPLETION_TIMEOUT);
if (ret == 0) {
dev_err(qspi->dev, "write timed out\n");
return -ETIMEDOUT;
}
txbuf += wlen;
count -= wlen;
}
return 0;
@ -276,7 +263,7 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
break;
}
count = t->len;
wlen = t->bits_per_word;
wlen = t->bits_per_word >> 3; /* in bytes */
while (count) {
dev_dbg(qspi->dev, "rx cmd %08x dc %08x\n", cmd, qspi->dc);
@ -288,22 +275,18 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
return -ETIMEDOUT;
}
switch (wlen) {
case 8:
case 1:
*rxbuf = readb(qspi->base + QSPI_SPI_DATA_REG);
rxbuf += 1;
count -= 1;
break;
case 16:
case 2:
*((u16 *)rxbuf) = readw(qspi->base + QSPI_SPI_DATA_REG);
rxbuf += 2;
count -= 2;
break;
case 32:
case 4:
*((u32 *)rxbuf) = readl(qspi->base + QSPI_SPI_DATA_REG);
rxbuf += 4;
count -= 4;
break;
}
rxbuf += wlen;
count -= wlen;
}
return 0;
@ -417,10 +400,8 @@ out:
static int ti_qspi_runtime_resume(struct device *dev)
{
struct ti_qspi *qspi;
struct spi_master *master;
master = dev_get_drvdata(dev);
qspi = spi_master_get_devdata(master);
qspi = dev_get_drvdata(dev);
ti_qspi_restore_ctx(qspi);
return 0;
@ -437,7 +418,7 @@ static int ti_qspi_probe(struct platform_device *pdev)
{
struct ti_qspi *qspi;
struct spi_master *master;
struct resource *r;
struct resource *r, *res_ctrl, *res_mmap;
struct device_node *np = pdev->dev.of_node;
u32 max_freq;
int ret = 0, num_cs, irq;
@ -464,7 +445,35 @@ static int ti_qspi_probe(struct platform_device *pdev)
qspi->dev = &pdev->dev;
platform_set_drvdata(pdev, qspi);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_base");
if (r == NULL) {
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (r == NULL) {
dev_err(&pdev->dev, "missing platform data\n");
return -ENODEV;
}
}
res_mmap = platform_get_resource_byname(pdev,
IORESOURCE_MEM, "qspi_mmap");
if (res_mmap == NULL) {
res_mmap = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (res_mmap == NULL) {
dev_err(&pdev->dev,
"memory mapped resource not required\n");
return -ENODEV;
}
}
res_ctrl = platform_get_resource_byname(pdev,
IORESOURCE_MEM, "qspi_ctrlmod");
if (res_ctrl == NULL) {
res_ctrl = platform_get_resource(pdev, IORESOURCE_MEM, 2);
if (res_ctrl == NULL) {
dev_dbg(&pdev->dev,
"control module resources not required\n");
}
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@ -480,6 +489,23 @@ static int ti_qspi_probe(struct platform_device *pdev)
goto free_master;
}
if (res_ctrl) {
qspi->ctrl_mod = true;
qspi->ctrl_base = devm_ioremap_resource(&pdev->dev, res_ctrl);
if (IS_ERR(qspi->ctrl_base)) {
ret = PTR_ERR(qspi->ctrl_base);
goto free_master;
}
}
if (res_mmap) {
qspi->mmap_base = devm_ioremap_resource(&pdev->dev, res_mmap);
if (IS_ERR(qspi->mmap_base)) {
ret = PTR_ERR(qspi->mmap_base);
goto free_master;
}
}
ret = devm_request_irq(&pdev->dev, irq, ti_qspi_isr, 0,
dev_name(&pdev->dev), qspi);
if (ret < 0) {
@ -516,13 +542,9 @@ free_master:
static int ti_qspi_remove(struct platform_device *pdev)
{
struct spi_master *master;
struct ti_qspi *qspi;
struct ti_qspi *qspi = platform_get_drvdata(pdev);
int ret;
master = platform_get_drvdata(pdev);
qspi = spi_master_get_devdata(master);
ret = pm_runtime_get_sync(qspi->dev);
if (ret < 0) {
dev_err(qspi->dev, "pm_runtime_get_sync() failed\n");
@ -534,8 +556,6 @@ static int ti_qspi_remove(struct platform_device *pdev)
pm_runtime_put(qspi->dev);
pm_runtime_disable(&pdev->dev);
spi_unregister_master(master);
return 0;
}
@ -547,7 +567,7 @@ static struct platform_driver ti_qspi_driver = {
.probe = ti_qspi_probe,
.remove = ti_qspi_remove,
.driver = {
.name = "ti,dra7xxx-qspi",
.name = "ti-qspi",
.owner = THIS_MODULE,
.pm = &ti_qspi_pm_ops,
.of_match_table = ti_qspi_match,
@ -559,3 +579,4 @@ module_platform_driver(ti_qspi_driver);
MODULE_AUTHOR("Sourav Poddar <sourav.poddar@ti.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("TI QSPI controller driver");
MODULE_ALIAS("platform:ti-qspi");

View File

@ -217,7 +217,7 @@ struct pch_pd_dev_save {
struct pch_spi_board_data *board_dat;
};
static DEFINE_PCI_DEVICE_TABLE(pch_spi_pcidev_id) = {
static const struct pci_device_id pch_spi_pcidev_id[] = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_GE_SPI), 1, },
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_SPI), 2, },
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_SPI), 1, },
@ -466,12 +466,6 @@ static void pch_spi_reset(struct spi_master *master)
static int pch_spi_setup(struct spi_device *pspi)
{
/* check bits per word */
if (pspi->bits_per_word == 0) {
pspi->bits_per_word = 8;
dev_dbg(&pspi->dev, "%s 8 bits per word\n", __func__);
}
/* Check baud rate setting */
/* if baud rate of chip is greater than
max we can support,return error */

View File

@ -348,7 +348,7 @@ static int txx9spi_probe(struct platform_device *dev)
INIT_LIST_HEAD(&c->queue);
init_waitqueue_head(&c->waitq);
c->clk = clk_get(&dev->dev, "spi-baseclk");
c->clk = devm_clk_get(&dev->dev, "spi-baseclk");
if (IS_ERR(c->clk)) {
ret = PTR_ERR(c->clk);
c->clk = NULL;
@ -356,7 +356,6 @@ static int txx9spi_probe(struct platform_device *dev)
}
ret = clk_enable(c->clk);
if (ret) {
clk_put(c->clk);
c->clk = NULL;
goto exit;
}
@ -415,10 +414,8 @@ exit_busy:
exit:
if (c->workqueue)
destroy_workqueue(c->workqueue);
if (c->clk) {
if (c->clk)
clk_disable(c->clk);
clk_put(c->clk);
}
spi_master_put(master);
return ret;
}
@ -430,7 +427,6 @@ static int txx9spi_remove(struct platform_device *dev)
destroy_workqueue(c->workqueue);
clk_disable(c->clk);
clk_put(c->clk);
return 0;
}

View File

@ -231,22 +231,13 @@ static int spi_xcomm_probe(struct i2c_client *i2c,
master->dev.of_node = i2c->dev.of_node;
i2c_set_clientdata(i2c, master);
ret = spi_register_master(master);
ret = devm_spi_register_master(&i2c->dev, master);
if (ret < 0)
spi_master_put(master);
return ret;
}
static int spi_xcomm_remove(struct i2c_client *i2c)
{
struct spi_master *master = i2c_get_clientdata(i2c);
spi_unregister_master(master);
return 0;
}
static const struct i2c_device_id spi_xcomm_ids[] = {
{ "spi-xcomm" },
{ },
@ -259,7 +250,6 @@ static struct i2c_driver spi_xcomm_driver = {
},
.id_table = spi_xcomm_ids,
.probe = spi_xcomm_probe,
.remove = spi_xcomm_remove,
};
module_i2c_driver(spi_xcomm_driver);

View File

@ -380,6 +380,17 @@ static void spi_dev_set_name(struct spi_device *spi)
spi->chip_select);
}
static int spi_dev_check(struct device *dev, void *data)
{
struct spi_device *spi = to_spi_device(dev);
struct spi_device *new_spi = data;
if (spi->master == new_spi->master &&
spi->chip_select == new_spi->chip_select)
return -EBUSY;
return 0;
}
/**
* spi_add_device - Add spi_device allocated with spi_alloc_device
* @spi: spi_device to register
@ -394,7 +405,6 @@ int spi_add_device(struct spi_device *spi)
static DEFINE_MUTEX(spi_add_lock);
struct spi_master *master = spi->master;
struct device *dev = master->dev.parent;
struct device *d;
int status;
/* Chipselects are numbered 0..max; validate. */
@ -414,12 +424,10 @@ int spi_add_device(struct spi_device *spi)
*/
mutex_lock(&spi_add_lock);
d = bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev));
if (d != NULL) {
status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check);
if (status) {
dev_err(dev, "chipselect %d already in use\n",
spi->chip_select);
put_device(d);
status = -EBUSY;
goto done;
}
@ -601,8 +609,10 @@ static int spi_transfer_one_message(struct spi_master *master,
goto out;
}
if (ret > 0)
if (ret > 0) {
ret = 0;
wait_for_completion(&master->xfer_completion);
}
trace_spi_transfer_stop(msg, xfer);
@ -642,7 +652,7 @@ out:
*
* Called by SPI drivers using the core transfer_one_message()
* implementation to notify it that the current interrupt driven
* transfer has finised and the next one may be scheduled.
* transfer has finished and the next one may be scheduled.
*/
void spi_finalize_current_transfer(struct spi_master *master)
{
@ -695,7 +705,7 @@ static void spi_pump_messages(struct kthread_work *work)
}
/* Extract head of queue */
master->cur_msg =
list_entry(master->queue.next, struct spi_message, queue);
list_first_entry(&master->queue, struct spi_message, queue);
list_del_init(&master->cur_msg->queue);
if (master->busy)
@ -745,7 +755,9 @@ static void spi_pump_messages(struct kthread_work *work)
ret = master->transfer_one_message(master, master->cur_msg);
if (ret) {
dev_err(&master->dev,
"failed to transfer one message from queue\n");
"failed to transfer one message from queue: %d\n", ret);
master->cur_msg->status = ret;
spi_finalize_current_message(master);
return;
}
}
@ -801,11 +813,8 @@ struct spi_message *spi_get_next_queued_message(struct spi_master *master)
/* get a pointer to the next message, if any */
spin_lock_irqsave(&master->queue_lock, flags);
if (list_empty(&master->queue))
next = NULL;
else
next = list_entry(master->queue.next,
struct spi_message, queue);
next = list_first_entry_or_null(&master->queue, struct spi_message,
queue);
spin_unlock_irqrestore(&master->queue_lock, flags);
return next;
@ -1606,15 +1615,11 @@ int spi_setup(struct spi_device *spi)
}
EXPORT_SYMBOL_GPL(spi_setup);
static int __spi_async(struct spi_device *spi, struct spi_message *message)
static int __spi_validate(struct spi_device *spi, struct spi_message *message)
{
struct spi_master *master = spi->master;
struct spi_transfer *xfer;
message->spi = spi;
trace_spi_message_submit(message);
if (list_empty(&message->transfers))
return -EINVAL;
if (!message->complete)
@ -1677,9 +1682,8 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
if (xfer->rx_buf && !xfer->rx_nbits)
xfer->rx_nbits = SPI_NBITS_SINGLE;
/* check transfer tx/rx_nbits:
* 1. keep the value is not out of single, dual and quad
* 2. keep tx/rx_nbits is contained by mode in spi_device
* 3. if SPI_3WIRE, tx/rx_nbits should be in single
* 1. check the value matches one of single, dual and quad
* 2. check tx/rx_nbits match the mode in spi_device
*/
if (xfer->tx_buf) {
if (xfer->tx_nbits != SPI_NBITS_SINGLE &&
@ -1692,9 +1696,6 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
if ((xfer->tx_nbits == SPI_NBITS_QUAD) &&
!(spi->mode & SPI_TX_QUAD))
return -EINVAL;
if ((spi->mode & SPI_3WIRE) &&
(xfer->tx_nbits != SPI_NBITS_SINGLE))
return -EINVAL;
}
/* check transfer rx_nbits */
if (xfer->rx_buf) {
@ -1708,13 +1709,22 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
if ((xfer->rx_nbits == SPI_NBITS_QUAD) &&
!(spi->mode & SPI_RX_QUAD))
return -EINVAL;
if ((spi->mode & SPI_3WIRE) &&
(xfer->rx_nbits != SPI_NBITS_SINGLE))
return -EINVAL;
}
}
message->status = -EINPROGRESS;
return 0;
}
static int __spi_async(struct spi_device *spi, struct spi_message *message)
{
struct spi_master *master = spi->master;
message->spi = spi;
trace_spi_message_submit(message);
return master->transfer(spi, message);
}
@ -1753,6 +1763,10 @@ int spi_async(struct spi_device *spi, struct spi_message *message)
int ret;
unsigned long flags;
ret = __spi_validate(spi, message);
if (ret != 0)
return ret;
spin_lock_irqsave(&master->bus_lock_spinlock, flags);
if (master->bus_lock_flag)
@ -1801,6 +1815,10 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message)
int ret;
unsigned long flags;
ret = __spi_validate(spi, message);
if (ret != 0)
return ret;
spin_lock_irqsave(&master->bus_lock_spinlock, flags);
ret = __spi_async(spi, message);

View File

@ -1,6 +1,4 @@
/*
* arch/arm/mach-w90x900/include/mach/nuc900_spi.h
*
* Copyright (c) 2009 Nuvoton technology corporation.
*
* Wan ZongShun <mcuos.com@gmail.com>
@ -11,8 +9,8 @@
*
*/
#ifndef __ASM_ARCH_SPI_H
#define __ASM_ARCH_SPI_H
#ifndef __SPI_NUC900_H
#define __SPI_NUC900_H
extern void mfp_set_groupg(struct device *dev, const char *subname);
@ -32,4 +30,4 @@ struct nuc900_spi_chip {
unsigned char bits_per_word;
};
#endif /* __ASM_ARCH_SPI_H */
#endif /* __SPI_NUC900_H */

View File

@ -23,4 +23,6 @@ struct s3c2410_spi_info {
void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol);
};
extern int s3c24xx_set_fiq(unsigned int irq, bool on);
#endif /* __LINUX_SPI_S3C24XX_H */

View File

@ -75,6 +75,7 @@ struct spi_device {
struct spi_master *master;
u32 max_speed_hz;
u8 chip_select;
u8 bits_per_word;
u16 mode;
#define SPI_CPHA 0x01 /* clock phase */
#define SPI_CPOL 0x02 /* clock polarity */
@ -92,7 +93,6 @@ struct spi_device {
#define SPI_TX_QUAD 0x200 /* transmit with 4 wires */
#define SPI_RX_DUAL 0x400 /* receive with 2 wires */
#define SPI_RX_QUAD 0x800 /* receive with 4 wires */
u8 bits_per_word;
int irq;
void *controller_state;
void *controller_data;
@ -277,15 +277,17 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
* @unprepare_transfer_hardware: there are currently no more messages on the
* queue so the subsystem notifies the driver that it may relax the
* hardware by issuing this call
* @set_cs: assert or deassert chip select, true to assert. May be called
* @set_cs: set the logic level of the chip select line. May be called
* from interrupt context.
* @prepare_message: set up the controller to transfer a single message,
* for example doing DMA mapping. Called from threaded
* context.
* @transfer_one: transfer a single spi_transfer. When the
* driver is finished with this transfer it must call
* spi_finalize_current_transfer() so the subsystem can issue
* the next transfer
* @transfer_one: transfer a single spi_transfer.
* - return 0 if the transfer is finished,
* - return 1 if the transfer is still in progress. When
* the driver is finished with this transfer it must
* call spi_finalize_current_transfer() so the subsystem
* can issue the next transfer
* @unprepare_message: undo any work done by prepare_message().
* @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
* number. Any individual value may be -ENOENT for CS lines that
@ -576,8 +578,8 @@ struct spi_transfer {
dma_addr_t rx_dma;
unsigned cs_change:1;
u8 tx_nbits;
u8 rx_nbits;
unsigned tx_nbits:3;
unsigned rx_nbits:3;
#define SPI_NBITS_SINGLE 0x01 /* 1bit transfer */
#define SPI_NBITS_DUAL 0x02 /* 2bits transfer */
#define SPI_NBITS_QUAD 0x04 /* 4bits transfer */
@ -847,7 +849,7 @@ static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd)
ssize_t status;
u16 result;
status = spi_write_then_read(spi, &cmd, 1, (u8 *) &result, 2);
status = spi_write_then_read(spi, &cmd, 1, &result, 2);
/* return negative errno or unsigned value */
return (status < 0) ? status : result;