config SPI_CLPS711X
tristate "CLPS711X host SPI controller"
-------- depends on ARCH_CLPS711X
++++++++ depends on ARCH_CLPS711X || COMPILE_TEST
help
This enables dedicated general purpose SPI/Microwire1-compatible
master mode interface (SSI1) for CLPS711X-based CPUs.
tristate "Freescale i.MX SPI controllers"
depends on ARCH_MXC || COMPILE_TEST
select SPI_BITBANG
-------- default m if IMX_HAVE_PLATFORM_SPI_IMX
help
This enables using the Freescale i.MX SPI controllers in master
mode.
config SPI_FSL_DSPI
tristate "Freescale DSPI controller"
select SPI_BITBANG
++++++++ select REGMAP_MMIO
depends on SOC_VF610 || COMPILE_TEST
help
This enables support for the Freescale DSPI controller in master
config SPI_OMAP24XX
tristate "McSPI driver for OMAP"
--- ----- depends on ARM || ARM64 || AVR32 || HEXAGON || MIPS || SH
+++ +++++ depends on ARM || ARM64 || AVR32 || HEXAGON || MIPS || SUPERH
depends on ARCH_OMAP2PLUS || COMPILE_TEST
help
SPI master controller for OMAP24XX and later Multichannel SPI
def_tristate SPI_PXA2XX && PCI
config SPI_RSPI
---- --- tristate "Renesas RSPI controller"
++++ +++ tristate "Renesas RSPI/QSPI controller"
depends on (SUPERH && SH_DMAE_BASE) || ARCH_SHMOBILE
help
---- --- SPI driver for Renesas RSPI blocks.
++++ +++ SPI driver for Renesas RSPI and QSPI blocks.
++++ ++
++++++ ++config SPI_QUP
++++++ ++ tristate "Qualcomm SPI controller with QUP interface"
++++++ ++ depends on ARCH_MSM_DT || (ARM && COMPILE_TEST)
++++++ ++ help
++++++ ++ Qualcomm Universal Peripheral (QUP) core is an AHB slave that
++++++ ++ provides a common data path (an output FIFO and an input FIFO)
++++++ ++ for serial peripheral interface (SPI) mini-core. SPI in master
++++++ ++ mode supports up to 50MHz, up to four chip selects, programmable
++++++ ++ data path from 4 bits to 32 bits and numerous protocol variants.
++++++ ++
++++++ ++ This driver can also be built as a module. If so, the module
++++++ ++ will be called spi_qup.
+ +
config SPI_S3C24XX
tristate "Samsung S3C24XX series SPI"
depends on ARCH_S3C24XX
config SPI_TEGRA114
tristate "NVIDIA Tegra114 SPI Controller"
depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
+ depends on RESET_CONTROLLER
help
SPI driver for NVIDIA Tegra114 SPI Controller interface. This controller
is different than the older SoCs SPI controller and also register interface
config SPI_TEGRA20_SFLASH
tristate "Nvidia Tegra20 Serial flash Controller"
depends on ARCH_TEGRA || COMPILE_TEST
+ depends on RESET_CONTROLLER
help
SPI driver for Nvidia Tegra20 Serial flash Controller interface.
The main usecase of this controller is to use spi flash as boot
config SPI_TEGRA20_SLINK
tristate "Nvidia Tegra20/Tegra30 SLINK Controller"
depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
+ depends on RESET_CONTROLLER
help
SPI driver for Nvidia Tegra20/Tegra30 SLINK Controller interface.
config SPI_DW_MMIO
tristate "Memory-mapped io interface driver for DW SPI core"
-------- depends on SPI_DESIGNWARE && HAVE_CLK
++++++++ depends on SPI_DESIGNWARE
#
# There are lots of SPI device types, with sensors and memory
};
struct uwire_state {
- ------- unsigned bits_per_word;
unsigned div1_idx;
};
static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t)
{
- ------- struct uwire_state *ust = spi->controller_state;
unsigned len = t->len;
- ------- unsigned bits = ust->bits_per_word;
+ +++++++ unsigned bits = t->bits_per_word ? : spi->bits_per_word;
unsigned bytes;
u16 val, w;
int status = 0;
if (!t->tx_buf && !t->rx_buf)
return 0;
- ------- /* Microwire doesn't read and write concurrently */
- ------- if (t->tx_buf && t->rx_buf)
- ------- return -EPERM;
- -------
w = spi->chip_select << 10;
w |= CS_CMD;
struct uwire_state *ust = spi->controller_state;
struct uwire_spi *uwire;
unsigned flags = 0;
- ------- unsigned bits;
unsigned hz;
unsigned long rate;
int div1_idx;
uwire = spi_master_get_devdata(spi->master);
------- if (spi->chip_select > 3) {
------- pr_debug("%s: cs%d?\n", dev_name(&spi->dev), spi->chip_select);
------- status = -ENODEV;
------- goto done;
------- }
-------
- ------- bits = spi->bits_per_word;
- ------- if (t != NULL && t->bits_per_word)
- ------- bits = t->bits_per_word;
- -------
- ------- if (bits > 16) {
- ------- pr_debug("%s: wordsize %d?\n", dev_name(&spi->dev), bits);
- ------- status = -ENODEV;
- ------- goto done;
- ------- }
- ------- ust->bits_per_word = bits;
- -------
/* mode 0..3, clock inverted separately;
* standard nCS signaling;
* don't treat DI=high as "not ready"
status = PTR_ERR(uwire->ck);
dev_dbg(&pdev->dev, "no functional clock?\n");
spi_master_put(master);
+ +++++++ iounmap(uwire_base);
return status;
}
clk_enable(uwire->ck);
/* the spi->mode bits understood by this driver: */
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
- -------
+ +++++++ master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
master->flags = SPI_MASTER_HALF_DUPLEX;
master->bus_num = 2; /* "official" */
static int uwire_remove(struct platform_device *pdev)
{
struct uwire_spi *uwire = platform_get_drvdata(pdev);
-------- int status;
// FIXME remove all child devices, somewhere ...
-------- status = spi_bitbang_stop(&uwire->bitbang);
++++++++ spi_bitbang_stop(&uwire->bitbang);
uwire_off(uwire);
iounmap(uwire_base);
-------- return status;
++++++++ return 0;
}
/* work with hotplug and coldplug */
*/
#include <linux/kernel.h>
--------#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_data/spi-omap2-mcspi.h>
#define OMAP2_MCSPI_MAX_FREQ 48000000
+++ +++++#define OMAP2_MCSPI_MAX_DIVIDER 4096
#define OMAP2_MCSPI_MAX_FIFODEPTH 64
#define OMAP2_MCSPI_MAX_FIFOWCNT 0xFFFF
#define SPI_AUTOSUSPEND_TIMEOUT 2000
#define OMAP2_MCSPI_CHCONF_FORCE BIT(20)
#define OMAP2_MCSPI_CHCONF_FFET BIT(27)
#define OMAP2_MCSPI_CHCONF_FFER BIT(28)
+++ +++++#define OMAP2_MCSPI_CHCONF_CLKG BIT(29)
#define OMAP2_MCSPI_CHSTAT_RXS BIT(0)
#define OMAP2_MCSPI_CHSTAT_TXS BIT(1)
#define OMAP2_MCSPI_CHSTAT_TXFFE BIT(3)
#define OMAP2_MCSPI_CHCTRL_EN BIT(0)
+++ +++++#define OMAP2_MCSPI_CHCTRL_EXTCLK_MASK (0xff << 8)
#define OMAP2_MCSPI_WAKEUPENABLE_WKEN BIT(0)
int word_len;
struct list_head node;
/* Context save and restore shadow register */
--- ----- u32 chconf0;
+++ +++++ u32 chconf0, chctrl0;
};
static inline void mcspi_write_reg(struct spi_master *master,
static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
{
+++ +++++ struct omap2_mcspi_cs *cs = spi->controller_state;
u32 l;
--- ----- l = enable ? OMAP2_MCSPI_CHCTRL_EN : 0;
--- ----- mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, l);
+++ +++++ l = cs->chctrl0;
+++ +++++ if (enable)
+++ +++++ l |= OMAP2_MCSPI_CHCTRL_EN;
+++ +++++ else
+++ +++++ l &= ~OMAP2_MCSPI_CHCTRL_EN;
+++ +++++ cs->chctrl0 = l;
+++ +++++ mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, cs->chctrl0);
/* Flash post-writes */
mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0);
}
struct omap2_mcspi_cs *cs = spi->controller_state;
struct omap2_mcspi *mcspi;
struct spi_master *spi_cntrl;
--- ----- u32 l = 0, div = 0;
+++ +++++ u32 l = 0, clkd = 0, div, extclk = 0, clkg = 0;
u8 word_len = spi->bits_per_word;
u32 speed_hz = spi->max_speed_hz;
speed_hz = t->speed_hz;
speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ);
--- ----- div = omap2_mcspi_calc_divisor(speed_hz);
+++ +++++ if (speed_hz < (OMAP2_MCSPI_MAX_FREQ / OMAP2_MCSPI_MAX_DIVIDER)) {
+++ +++++ clkd = omap2_mcspi_calc_divisor(speed_hz);
+++ +++++ speed_hz = OMAP2_MCSPI_MAX_FREQ >> clkd;
+++ +++++ clkg = 0;
+++ +++++ } else {
+++ +++++ div = (OMAP2_MCSPI_MAX_FREQ + speed_hz - 1) / speed_hz;
+++ +++++ speed_hz = OMAP2_MCSPI_MAX_FREQ / div;
+++ +++++ clkd = (div - 1) & 0xf;
+++ +++++ extclk = (div - 1) >> 4;
+++ +++++ clkg = OMAP2_MCSPI_CHCONF_CLKG;
+++ +++++ }
l = mcspi_cached_chconf0(spi);
/* set clock divisor */
l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK;
--- ----- l |= div << 2;
+++ +++++ l |= clkd << 2;
+++ +++++
+++ +++++ /* set clock granularity */
+++ +++++ l &= ~OMAP2_MCSPI_CHCONF_CLKG;
+++ +++++ l |= clkg;
+++ +++++ if (clkg) {
+++ +++++ cs->chctrl0 &= ~OMAP2_MCSPI_CHCTRL_EXTCLK_MASK;
+++ +++++ cs->chctrl0 |= extclk << 8;
+++ +++++ mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, cs->chctrl0);
+++ +++++ }
/* set SPI mode 0..3 */
if (spi->mode & SPI_CPOL)
mcspi_write_chconf0(spi, l);
dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
--- ----- OMAP2_MCSPI_MAX_FREQ >> div,
+++ +++++ speed_hz,
(spi->mode & SPI_CPHA) ? "trailing" : "leading",
(spi->mode & SPI_CPOL) ? "inverted" : "normal");
cs->base = mcspi->base + spi->chip_select * 0x14;
cs->phys = mcspi->phys + spi->chip_select * 0x14;
cs->chconf0 = 0;
+++ +++++ cs->chctrl0 = 0;
spi->controller_state = cs;
/* Link this to context save list */
list_add_tail(&cs->node, &ctx->cs);
status = -EINVAL;
break;
}
--- ----- if (par_override || t->speed_hz || t->bits_per_word) {
+++ +++++ if (par_override ||
+++ +++++ (t->speed_hz != spi->max_speed_hz) ||
+++ +++++ (t->bits_per_word != spi->bits_per_word)) {
par_override = 1;
status = omap2_mcspi_setup_transfer(spi, t);
if (status < 0)
break;
--- ----- if (!t->speed_hz && !t->bits_per_word)
+++ +++++ if (t->speed_hz == spi->max_speed_hz &&
+++ +++++ t->bits_per_word == spi->bits_per_word)
par_override = 0;
}
if (cd && cd->cs_per_word) {
m->actual_length = 0;
m->status = 0;
--- ----- /* reject invalid messages and transfers */
--- ----- if (list_empty(&m->transfers))
--- ----- return -EINVAL;
list_for_each_entry(t, &m->transfers, transfer_list) {
const void *tx_buf = t->tx_buf;
void *rx_buf = t->rx_buf;
unsigned len = t->len;
--- ----- if (t->speed_hz > OMAP2_MCSPI_MAX_FREQ
--- ----- || (len && !(rx_buf || tx_buf))) {
+++ +++++ if ((len && !(rx_buf || tx_buf))) {
dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
t->speed_hz,
len,
t->bits_per_word);
return -EINVAL;
}
--- ----- if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) {
--- ----- dev_dbg(mcspi->dev, "speed_hz %d below minimum %d Hz\n",
--- ----- t->speed_hz,
--- ----- OMAP2_MCSPI_MAX_FREQ >> 15);
--- ----- return -EINVAL;
--- ----- }
if (m->is_dma_mapped || len < DMA_MIN_BYTES)
continue;
master->transfer_one_message = omap2_mcspi_transfer_one_message;
master->cleanup = omap2_mcspi_cleanup;
master->dev.of_node = node;
+++ +++++ master->max_speed_hz = OMAP2_MCSPI_MAX_FREQ;
+++ +++++ master->min_speed_hz = OMAP2_MCSPI_MAX_FREQ >> 15;
platform_set_drvdata(pdev, master);
* published by the Free Software Foundation.
*/
--------#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
struct orion_spi {
struct spi_master *master;
void __iomem *base;
---- ---- unsigned int max_speed;
---- ---- unsigned int min_speed;
struct clk *clk;
};
writel(val, reg_addr);
}
---- ----static int orion_spi_set_transfer_size(struct orion_spi *orion_spi, int size)
---- ----{
---- ---- if (size == 16) {
---- ---- orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
---- ---- ORION_SPI_IF_8_16_BIT_MODE);
---- ---- } else if (size == 8) {
---- ---- orion_spi_clrbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
---- ---- ORION_SPI_IF_8_16_BIT_MODE);
---- ---- } else {
---- ---- pr_debug("Bad bits per word value %d (only 8 or 16 are allowed).\n",
---- ---- size);
---- ---- return -EINVAL;
---- ---- }
---- ----
---- ---- return 0;
---- ----}
---- ----
static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
{
u32 tclk_hz;
if (rc)
return rc;
---- ---- return orion_spi_set_transfer_size(orion_spi, bits_per_word);
++++ ++++ if (bits_per_word == 16)
++++ ++++ orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
++++ ++++ ORION_SPI_IF_8_16_BIT_MODE);
++++ ++++ else
++++ ++++ orion_spi_clrbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
++++ ++++ ORION_SPI_IF_8_16_BIT_MODE);
++++ ++++
++++ ++++ return 0;
}
static void orion_spi_set_cs(struct orion_spi *orion_spi, int enable)
static unsigned int
orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
{
---- ---- struct orion_spi *orion_spi;
unsigned int count;
int word_len;
---- ---- orion_spi = spi_master_get_devdata(spi->master);
word_len = spi->bits_per_word;
count = xfer->len;
goto msg_done;
list_for_each_entry(t, &m->transfers, transfer_list) {
---- ---- /* make sure buffer length is even when working in 16
---- ---- * bit mode*/
---- ---- if ((t->bits_per_word == 16) && (t->len & 1)) {
---- ---- dev_err(&spi->dev,
---- ---- "message rejected : "
---- ---- "odd data length %d while in 16 bit mode\n",
---- ---- t->len);
---- ---- status = -EIO;
---- ---- goto msg_done;
---- ---- }
---- ----
---- ---- if (t->speed_hz && t->speed_hz < orion_spi->min_speed) {
---- ---- dev_err(&spi->dev,
---- ---- "message rejected : "
---- ---- "device min speed (%d Hz) exceeds "
---- ---- "required transfer speed (%d Hz)\n",
---- ---- orion_spi->min_speed, t->speed_hz);
---- ---- status = -EIO;
---- ---- goto msg_done;
---- ---- }
---- ----
if (par_override || t->speed_hz || t->bits_per_word) {
par_override = 1;
status = orion_spi_setup_transfer(spi, t);
return 0;
}
---- ----static int orion_spi_setup(struct spi_device *spi)
---- ----{
---- ---- struct orion_spi *orion_spi;
---- ----
---- ---- orion_spi = spi_master_get_devdata(spi->master);
---- ----
---- ---- if ((spi->max_speed_hz == 0)
---- ---- || (spi->max_speed_hz > orion_spi->max_speed))
---- ---- spi->max_speed_hz = orion_spi->max_speed;
---- ----
---- ---- if (spi->max_speed_hz < orion_spi->min_speed) {
---- ---- dev_err(&spi->dev, "setup: requested speed too low %d Hz\n",
---- ---- spi->max_speed_hz);
---- ---- return -EINVAL;
---- ---- }
---- ----
---- ---- /*
---- ---- * baudrate & width will be set orion_spi_setup_transfer
---- ---- */
---- ---- return 0;
---- ----}
---- ----
static int orion_spi_probe(struct platform_device *pdev)
{
struct spi_master *master;
/* we support only mode 0, and no options */
master->mode_bits = SPI_CPHA | SPI_CPOL;
---- ---- master->setup = orion_spi_setup;
master->transfer_one_message = orion_spi_transfer_one_message;
master->num_chipselect = ORION_NUM_CHIPSELECTS;
++++ ++++ master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
platform_set_drvdata(pdev, master);
clk_prepare(spi->clk);
clk_enable(spi->clk);
tclk_hz = clk_get_rate(spi->clk);
---- ---- spi->max_speed = DIV_ROUND_UP(tclk_hz, 4);
---- ---- spi->min_speed = DIV_ROUND_UP(tclk_hz, 30);
++++ ++++ master->max_speed_hz = DIV_ROUND_UP(tclk_hz, 4);
++++ ++++ master->min_speed_hz = DIV_ROUND_UP(tclk_hz, 30);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spi->base = devm_ioremap_resource(&pdev->dev, r);
struct spi_transfer *last_transfer;
pl022->next_msg_cs_active = false;
-------- last_transfer = list_entry(pl022->cur_msg->transfers.prev,
-------- struct spi_transfer,
-------- transfer_list);
++++++++ last_transfer = list_last_entry(&pl022->cur_msg->transfers,
++++++++ struct spi_transfer, transfer_list);
/* Delay if requested before any change in chip select */
if (last_transfer->delay_usecs)
pl022->chipselects = devm_kzalloc(dev, num_cs * sizeof(int),
GFP_KERNEL);
----- --- pinctrl_pm_select_default_state(dev);
----- ---
/*
* Bus Number Which has been Assigned to this SSP controller
* on this board
goto err_no_clk;
}
----- --- status = clk_prepare(pl022->clk);
----- --- if (status) {
----- --- dev_err(&adev->dev, "could not prepare SSP/SPI bus clock\n");
----- --- goto err_clk_prep;
----- --- }
----- ---
----- --- status = clk_enable(pl022->clk);
+++++ +++ status = clk_prepare_enable(pl022->clk);
if (status) {
dev_err(&adev->dev, "could not enable SSP/SPI bus clock\n");
goto err_no_clk_en;
if (platform_info->enable_dma)
pl022_dma_remove(pl022);
err_no_irq:
----- --- clk_disable(pl022->clk);
+++++ +++ clk_disable_unprepare(pl022->clk);
err_no_clk_en:
----- --- clk_unprepare(pl022->clk);
----- --- err_clk_prep:
err_no_clk:
err_no_ioremap:
amba_release_regions(adev);
if (pl022->master_info->enable_dma)
pl022_dma_remove(pl022);
----- --- clk_disable(pl022->clk);
----- --- clk_unprepare(pl022->clk);
+++++ +++ clk_disable_unprepare(pl022->clk);
amba_release_regions(adev);
tasklet_disable(&pl022->pump_transfers);
return 0;
}
----- ---#if defined(CONFIG_SUSPEND) || defined(CONFIG_PM_RUNTIME)
----- ---/*
----- --- * These two functions are used from both suspend/resume and
----- --- * the runtime counterparts to handle external resources like
----- --- * clocks, pins and regulators when going to sleep.
----- --- */
----- ---static void pl022_suspend_resources(struct pl022 *pl022, bool runtime)
----- ---{
----- --- clk_disable(pl022->clk);
----- ---
----- --- if (runtime)
----- --- pinctrl_pm_select_idle_state(&pl022->adev->dev);
----- --- else
----- --- pinctrl_pm_select_sleep_state(&pl022->adev->dev);
----- ---}
----- ---
----- ---static void pl022_resume_resources(struct pl022 *pl022, bool runtime)
----- ---{
----- --- /* First go to the default state */
----- --- pinctrl_pm_select_default_state(&pl022->adev->dev);
----- --- if (!runtime)
----- --- /* Then let's idle the pins until the next transfer happens */
----- --- pinctrl_pm_select_idle_state(&pl022->adev->dev);
----- ---
----- --- clk_enable(pl022->clk);
----- ---}
----- ---#endif
----- ---
----- ---#ifdef CONFIG_SUSPEND
+++++ +++#ifdef CONFIG_PM_SLEEP
static int pl022_suspend(struct device *dev)
{
struct pl022 *pl022 = dev_get_drvdata(dev);
return ret;
}
----- --- pm_runtime_get_sync(dev);
----- --- pl022_suspend_resources(pl022, false);
+++++ +++ ret = pm_runtime_force_suspend(dev);
+++++ +++ if (ret) {
+++++ +++ spi_master_resume(pl022->master);
+++++ +++ return ret;
+++++ +++ }
+++++ +++
+++++ +++ pinctrl_pm_select_sleep_state(dev);
dev_dbg(dev, "suspended\n");
return 0;
struct pl022 *pl022 = dev_get_drvdata(dev);
int ret;
----- --- pl022_resume_resources(pl022, false);
----- --- pm_runtime_put(dev);
+++++ +++ ret = pm_runtime_force_resume(dev);
+++++ +++ if (ret)
+++++ +++ dev_err(dev, "problem resuming\n");
/* Start the queue running */
ret = spi_master_resume(pl022->master);
return ret;
}
----- ---#endif /* CONFIG_PM */
+++++ +++#endif
----- ---#ifdef CONFIG_PM_RUNTIME
+++++ +++#ifdef CONFIG_PM
static int pl022_runtime_suspend(struct device *dev)
{
struct pl022 *pl022 = dev_get_drvdata(dev);
----- --- pl022_suspend_resources(pl022, true);
+++++ +++ clk_disable_unprepare(pl022->clk);
+++++ +++ pinctrl_pm_select_idle_state(dev);
+++++ +++
return 0;
}
{
struct pl022 *pl022 = dev_get_drvdata(dev);
----- --- pl022_resume_resources(pl022, true);
+++++ +++ pinctrl_pm_select_default_state(dev);
+++++ +++ clk_prepare_enable(pl022->clk);
+++++ +++
return 0;
}
#endif
static const struct dev_pm_ops pl022_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(pl022_suspend, pl022_resume)
----- --- SET_RUNTIME_PM_OPS(pl022_runtime_suspend, pl022_runtime_resume, NULL)
+++++ +++ SET_PM_RUNTIME_PM_OPS(pl022_runtime_suspend, pl022_runtime_resume, NULL)
};
static struct vendor_data vendor_arm = {
*
*/
--------#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
{
struct s3c24xx_spi *hw = to_hw(spi);
struct s3c24xx_spi_devstate *cs = spi->controller_state;
-------- unsigned int bpw;
unsigned int hz;
unsigned int div;
unsigned long clk;
-------- bpw = t ? t->bits_per_word : spi->bits_per_word;
hz = t ? t->speed_hz : spi->max_speed_hz;
-------- if (!bpw)
-------- bpw = 8;
--------
if (!hz)
hz = spi->max_speed_hz;
-------- if (bpw != 8) {
-------- dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
-------- return -EINVAL;
-------- }
--------
if (spi->mode != cs->mode) {
u8 spcon = SPCON_DEFAULT | S3C2410_SPCON_ENSCK;
master->num_chipselect = hw->pdata->num_cs;
master->bus_num = pdata->bus_num;
++++++++ master->bits_per_word_mask = SPI_BPW_MASK(8);
/* setup the state for the bitbang driver */
static int s3c24xx_spi_suspend(struct device *dev)
{
struct s3c24xx_spi *hw = dev_get_drvdata(dev);
++++++++ int ret;
++++++++
++++++++ ret = spi_master_suspend(hw->master);
++++++++ if (ret)
++++++++ return ret;
if (hw->pdata && hw->pdata->gpio_setup)
hw->pdata->gpio_setup(hw->pdata, 0);
struct s3c24xx_spi *hw = dev_get_drvdata(dev);
s3c24xx_spi_initialsetup(hw);
-------- return 0;
++++++++ return spi_master_resume(hw->master);
}
static const struct dev_pm_ops s3c24xx_spi_pmops = {