1
0
Fork 0

Merge remote-tracking branches 'spi/topic/octeon', 'spi/topic/pic32-sqi', 'spi/topic/pxa2xx' and 'spi/topic/qup' into spi-next

hifive-unleashed-5.1
Mark Brown 2016-09-30 09:14:14 -07:00
10 changed files with 281 additions and 67 deletions

View File

@ -648,6 +648,13 @@ config SPI_TEGRA20_SLINK
help
SPI driver for Nvidia Tegra20/Tegra30 SLINK Controller interface.
config SPI_THUNDERX
tristate "Cavium ThunderX SPI controller"
depends on PCI && 64BIT && (ARM64 || COMPILE_TEST)
help
SPI host driver for the hardware found on Cavium ThunderX
SOCs.
config SPI_TOPCLIFF_PCH
tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) SPI"
depends on PCI && (X86_32 || MIPS || COMPILE_TEST)

View File

@ -93,6 +93,8 @@ obj-$(CONFIG_SPI_TEGRA114) += spi-tegra114.o
obj-$(CONFIG_SPI_TEGRA20_SFLASH) += spi-tegra20-sflash.o
obj-$(CONFIG_SPI_TEGRA20_SLINK) += spi-tegra20-slink.o
obj-$(CONFIG_SPI_TLE62X0) += spi-tle62x0.o
spi-thunderx-objs := spi-cavium.o spi-cavium-thunderx.o
obj-$(CONFIG_SPI_THUNDERX) += spi-thunderx.o
obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o
obj-$(CONFIG_SPI_TXX9) += spi-txx9.o
obj-$(CONFIG_SPI_XCOMM) += spi-xcomm.o

View File

@ -0,0 +1,120 @@
/*
* Cavium ThunderX SPI driver.
*
* Copyright (C) 2016 Cavium Inc.
* Authors: Jan Glauber <jglauber@cavium.com>
*/
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/spi/spi.h>
#include "spi-cavium.h"
#define DRV_NAME "spi-thunderx"
#define SYS_FREQ_DEFAULT 700000000 /* 700 Mhz */
static int thunderx_spi_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct device *dev = &pdev->dev;
struct spi_master *master;
struct octeon_spi *p;
int ret;
master = spi_alloc_master(dev, sizeof(struct octeon_spi));
if (!master)
return -ENOMEM;
p = spi_master_get_devdata(master);
ret = pcim_enable_device(pdev);
if (ret)
goto error;
ret = pci_request_regions(pdev, DRV_NAME);
if (ret)
goto error;
p->register_base = pcim_iomap(pdev, 0, pci_resource_len(pdev, 0));
if (!p->register_base) {
ret = -EINVAL;
goto error;
}
p->regs.config = 0x1000;
p->regs.status = 0x1008;
p->regs.tx = 0x1010;
p->regs.data = 0x1080;
p->clk = devm_clk_get(dev, NULL);
if (IS_ERR(p->clk)) {
ret = PTR_ERR(p->clk);
goto error;
}
ret = clk_prepare_enable(p->clk);
if (ret)
goto error;
p->sys_freq = clk_get_rate(p->clk);
if (!p->sys_freq)
p->sys_freq = SYS_FREQ_DEFAULT;
dev_info(dev, "Set system clock to %u\n", p->sys_freq);
master->num_chipselect = 4;
master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH |
SPI_LSB_FIRST | SPI_3WIRE;
master->transfer_one_message = octeon_spi_transfer_one_message;
master->bits_per_word_mask = SPI_BPW_MASK(8);
master->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ;
master->dev.of_node = pdev->dev.of_node;
pci_set_drvdata(pdev, master);
ret = devm_spi_register_master(dev, master);
if (ret)
goto error;
return 0;
error:
clk_disable_unprepare(p->clk);
spi_master_put(master);
return ret;
}
static void thunderx_spi_remove(struct pci_dev *pdev)
{
struct spi_master *master = pci_get_drvdata(pdev);
struct octeon_spi *p;
p = spi_master_get_devdata(master);
if (!p)
return;
clk_disable_unprepare(p->clk);
/* Put everything in a known state. */
writeq(0, p->register_base + OCTEON_SPI_CFG(p));
}
static const struct pci_device_id thunderx_spi_pci_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa00b) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, thunderx_spi_pci_id_table);
static struct pci_driver thunderx_spi_driver = {
.name = DRV_NAME,
.id_table = thunderx_spi_pci_id_table,
.probe = thunderx_spi_probe,
.remove = thunderx_spi_remove,
};
module_pci_driver(thunderx_spi_driver);
MODULE_DESCRIPTION("Cavium, Inc. ThunderX SPI bus driver");
MODULE_AUTHOR("Jan Glauber");
MODULE_LICENSE("GPL");

View File

@ -1,6 +1,8 @@
#ifndef __SPI_CAVIUM_H
#define __SPI_CAVIUM_H
#include <linux/clk.h>
#define OCTEON_SPI_MAX_BYTES 9
#define OCTEON_SPI_MAX_CLOCK_HZ 16000000
@ -17,6 +19,7 @@ struct octeon_spi {
u64 cs_enax;
int sys_freq;
struct octeon_spi_regs regs;
struct clk *clk;
};
#define OCTEON_SPI_CFG(x) (x->regs.config)

View File

@ -253,15 +253,13 @@ static struct ring_desc *ring_desc_get(struct pic32_sqi *sqi)
return NULL;
rdesc = list_first_entry(&sqi->bd_list_free, struct ring_desc, list);
list_del(&rdesc->list);
list_add_tail(&rdesc->list, &sqi->bd_list_used);
list_move_tail(&rdesc->list, &sqi->bd_list_used);
return rdesc;
}
static void ring_desc_put(struct pic32_sqi *sqi, struct ring_desc *rdesc)
{
list_del(&rdesc->list);
list_add(&rdesc->list, &sqi->bd_list_free);
list_move(&rdesc->list, &sqi->bd_list_free);
}
static int pic32_sqi_one_transfer(struct pic32_sqi *sqi,

View File

@ -23,7 +23,7 @@
static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data,
bool error)
{
struct spi_message *msg = drv_data->cur_msg;
struct spi_message *msg = drv_data->master->cur_msg;
/*
* It is possible that one CPU is handling ROR interrupt and other
@ -76,7 +76,8 @@ static struct dma_async_tx_descriptor *
pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data,
enum dma_transfer_direction dir)
{
struct chip_data *chip = drv_data->cur_chip;
struct chip_data *chip =
spi_get_ctldata(drv_data->master->cur_msg->spi);
struct spi_transfer *xfer = drv_data->cur_transfer;
enum dma_slave_buswidth width;
struct dma_slave_config cfg;
@ -146,7 +147,7 @@ irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data)
int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32 dma_burst)
{
struct dma_async_tx_descriptor *tx_desc, *rx_desc;
int err = 0;
int err;
tx_desc = pxa2xx_spi_dma_prepare_one(drv_data, DMA_MEM_TO_DEV);
if (!tx_desc) {

View File

@ -28,6 +28,7 @@
#include <linux/spi/spi.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/pm_runtime.h>
@ -62,6 +63,13 @@ MODULE_ALIAS("platform:pxa2xx-spi");
| QUARK_X1000_SSCR1_TFT \
| SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
#define CE4100_SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_SCFR \
| SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
| SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \
| SSCR1_IFS | SSCR1_STRF | SSCR1_EFWR \
| CE4100_SSCR1_RFT | CE4100_SSCR1_TFT | SSCR1_MWDS \
| SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
#define LPSS_GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
#define LPSS_CS_CONTROL_SW_MODE BIT(0)
#define LPSS_CS_CONTROL_CS_HIGH BIT(1)
@ -175,6 +183,8 @@ static u32 pxa2xx_spi_get_ssrc1_change_mask(const struct driver_data *drv_data)
switch (drv_data->ssp_type) {
case QUARK_X1000_SSP:
return QUARK_X1000_SSCR1_CHANGE_MASK;
case CE4100_SSP:
return CE4100_SSCR1_CHANGE_MASK;
default:
return SSCR1_CHANGE_MASK;
}
@ -186,6 +196,8 @@ pxa2xx_spi_get_rx_default_thre(const struct driver_data *drv_data)
switch (drv_data->ssp_type) {
case QUARK_X1000_SSP:
return RX_THRESH_QUARK_X1000_DFLT;
case CE4100_SSP:
return RX_THRESH_CE4100_DFLT;
default:
return RX_THRESH_DFLT;
}
@ -199,6 +211,9 @@ static bool pxa2xx_spi_txfifo_full(const struct driver_data *drv_data)
case QUARK_X1000_SSP:
mask = QUARK_X1000_SSSR_TFL_MASK;
break;
case CE4100_SSP:
mask = CE4100_SSSR_TFL_MASK;
break;
default:
mask = SSSR_TFL_MASK;
break;
@ -216,6 +231,9 @@ static void pxa2xx_spi_clear_rx_thre(const struct driver_data *drv_data,
case QUARK_X1000_SSP:
mask = QUARK_X1000_SSCR1_RFT;
break;
case CE4100_SSP:
mask = CE4100_SSCR1_RFT;
break;
default:
mask = SSCR1_RFT;
break;
@ -230,6 +248,9 @@ static void pxa2xx_spi_set_rx_thre(const struct driver_data *drv_data,
case QUARK_X1000_SSP:
*sccr1_reg |= QUARK_X1000_SSCR1_RxTresh(threshold);
break;
case CE4100_SSP:
*sccr1_reg |= CE4100_SSCR1_RxTresh(threshold);
break;
default:
*sccr1_reg |= SSCR1_RxTresh(threshold);
break;
@ -316,7 +337,7 @@ static void lpss_ssp_select_cs(struct driver_data *drv_data,
value = __lpss_ssp_read_priv(drv_data, config->reg_cs_ctrl);
cs = drv_data->cur_msg->spi->chip_select;
cs = drv_data->master->cur_msg->spi->chip_select;
cs <<= config->cs_sel_shift;
if (cs != (value & config->cs_sel_mask)) {
/*
@ -355,10 +376,11 @@ static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable)
static void cs_assert(struct driver_data *drv_data)
{
struct chip_data *chip = drv_data->cur_chip;
struct chip_data *chip =
spi_get_ctldata(drv_data->master->cur_msg->spi);
if (drv_data->ssp_type == CE4100_SSP) {
pxa2xx_spi_write(drv_data, SSSR, drv_data->cur_chip->frm);
pxa2xx_spi_write(drv_data, SSSR, chip->frm);
return;
}
@ -378,7 +400,8 @@ static void cs_assert(struct driver_data *drv_data)
static void cs_deassert(struct driver_data *drv_data)
{
struct chip_data *chip = drv_data->cur_chip;
struct chip_data *chip =
spi_get_ctldata(drv_data->master->cur_msg->spi);
if (drv_data->ssp_type == CE4100_SSP)
return;
@ -508,7 +531,7 @@ static int u32_reader(struct driver_data *drv_data)
void *pxa2xx_spi_next_transfer(struct driver_data *drv_data)
{
struct spi_message *msg = drv_data->cur_msg;
struct spi_message *msg = drv_data->master->cur_msg;
struct spi_transfer *trans = drv_data->cur_transfer;
/* Move to next transfer */
@ -529,8 +552,7 @@ static void giveback(struct driver_data *drv_data)
struct spi_message *msg;
unsigned long timeout;
msg = drv_data->cur_msg;
drv_data->cur_msg = NULL;
msg = drv_data->master->cur_msg;
drv_data->cur_transfer = NULL;
last_transfer = list_last_entry(&msg->transfers, struct spi_transfer,
@ -575,13 +597,13 @@ static void giveback(struct driver_data *drv_data)
cs_deassert(drv_data);
}
drv_data->cur_chip = NULL;
spi_finalize_current_message(drv_data->master);
}
static void reset_sccr1(struct driver_data *drv_data)
{
struct chip_data *chip = drv_data->cur_chip;
struct chip_data *chip =
spi_get_ctldata(drv_data->master->cur_msg->spi);
u32 sccr1_reg;
sccr1_reg = pxa2xx_spi_read(drv_data, SSCR1) & ~drv_data->int_cr1;
@ -589,6 +611,9 @@ static void reset_sccr1(struct driver_data *drv_data)
case QUARK_X1000_SSP:
sccr1_reg &= ~QUARK_X1000_SSCR1_RFT;
break;
case CE4100_SSP:
sccr1_reg &= ~CE4100_SSCR1_RFT;
break;
default:
sccr1_reg &= ~SSCR1_RFT;
break;
@ -610,7 +635,7 @@ static void int_error_stop(struct driver_data *drv_data, const char* msg)
dev_err(&drv_data->pdev->dev, "%s\n", msg);
drv_data->cur_msg->state = ERROR_STATE;
drv_data->master->cur_msg->state = ERROR_STATE;
tasklet_schedule(&drv_data->pump_transfers);
}
@ -623,7 +648,7 @@ static void int_transfer_complete(struct driver_data *drv_data)
pxa2xx_spi_write(drv_data, SSTO, 0);
/* Update total byte transferred return count actual bytes read */
drv_data->cur_msg->actual_length += drv_data->len -
drv_data->master->cur_msg->actual_length += drv_data->len -
(drv_data->rx_end - drv_data->rx);
/* Transfer delays and chip select release are
@ -631,7 +656,7 @@ static void int_transfer_complete(struct driver_data *drv_data)
*/
/* Move to next transfer */
drv_data->cur_msg->state = pxa2xx_spi_next_transfer(drv_data);
drv_data->master->cur_msg->state = pxa2xx_spi_next_transfer(drv_data);
/* Schedule transfer tasklet */
tasklet_schedule(&drv_data->pump_transfers);
@ -746,7 +771,7 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
if (!(status & mask))
return IRQ_NONE;
if (!drv_data->cur_msg) {
if (!drv_data->master->cur_msg) {
pxa2xx_spi_write(drv_data, SSCR0,
pxa2xx_spi_read(drv_data, SSCR0)
@ -905,7 +930,8 @@ static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data,
int rate)
{
struct chip_data *chip = drv_data->cur_chip;
struct chip_data *chip =
spi_get_ctldata(drv_data->master->cur_msg->spi);
unsigned int clk_div;
switch (drv_data->ssp_type) {
@ -934,25 +960,23 @@ static void pump_transfers(unsigned long data)
{
struct driver_data *drv_data = (struct driver_data *)data;
struct spi_master *master = drv_data->master;
struct spi_message *message = NULL;
struct spi_transfer *transfer = NULL;
struct spi_transfer *previous = NULL;
struct chip_data *chip = NULL;
u32 clk_div = 0;
u8 bits = 0;
u32 speed = 0;
struct spi_message *message = master->cur_msg;
struct chip_data *chip = spi_get_ctldata(message->spi);
u32 dma_thresh = chip->dma_threshold;
u32 dma_burst = chip->dma_burst_size;
u32 change_mask = pxa2xx_spi_get_ssrc1_change_mask(drv_data);
struct spi_transfer *transfer;
struct spi_transfer *previous;
u32 clk_div;
u8 bits;
u32 speed;
u32 cr0;
u32 cr1;
u32 dma_thresh = drv_data->cur_chip->dma_threshold;
u32 dma_burst = drv_data->cur_chip->dma_burst_size;
u32 change_mask = pxa2xx_spi_get_ssrc1_change_mask(drv_data);
int err;
int dma_mapped;
/* Get current state information */
message = drv_data->cur_msg;
transfer = drv_data->cur_transfer;
chip = drv_data->cur_chip;
/* Handle for abort */
if (message->state == ERROR_STATE) {
@ -1146,17 +1170,12 @@ static int pxa2xx_spi_transfer_one_message(struct spi_master *master,
{
struct driver_data *drv_data = spi_master_get_devdata(master);
drv_data->cur_msg = msg;
/* Initial message state*/
drv_data->cur_msg->state = START_STATE;
drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
msg->state = START_STATE;
drv_data->cur_transfer = list_entry(msg->transfers.next,
struct spi_transfer,
transfer_list);
/* prepare to setup the SSP, in pump_transfers, using the per
* chip configuration */
drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
/* Mark as busy and launch transfers */
tasklet_schedule(&drv_data->pump_transfers);
return 0;
@ -1176,9 +1195,26 @@ static int pxa2xx_spi_unprepare_transfer(struct spi_master *master)
static int setup_cs(struct spi_device *spi, struct chip_data *chip,
struct pxa2xx_spi_chip *chip_info)
{
struct driver_data *drv_data = spi_master_get_devdata(spi->master);
int err = 0;
if (chip == NULL || chip_info == NULL)
if (chip == NULL)
return 0;
if (drv_data->cs_gpiods) {
struct gpio_desc *gpiod;
gpiod = drv_data->cs_gpiods[spi->chip_select];
if (gpiod) {
chip->gpio_cs = desc_to_gpio(gpiod);
chip->gpio_cs_inverted = spi->mode & SPI_CS_HIGH;
gpiod_set_value(gpiod, chip->gpio_cs_inverted);
}
return 0;
}
if (chip_info == NULL)
return 0;
/* NOTE: setup() can be called multiple times, possibly with
@ -1213,7 +1249,7 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip,
static int setup(struct spi_device *spi)
{
struct pxa2xx_spi_chip *chip_info = NULL;
struct pxa2xx_spi_chip *chip_info;
struct chip_data *chip;
const struct lpss_config *config;
struct driver_data *drv_data = spi_master_get_devdata(spi->master);
@ -1225,6 +1261,11 @@ static int setup(struct spi_device *spi)
tx_hi_thres = 0;
rx_thres = RX_THRESH_QUARK_X1000_DFLT;
break;
case CE4100_SSP:
tx_thres = TX_THRESH_CE4100_DFLT;
tx_hi_thres = 0;
rx_thres = RX_THRESH_CE4100_DFLT;
break;
case LPSS_LPT_SSP:
case LPSS_BYT_SSP:
case LPSS_BSW_SSP:
@ -1309,6 +1350,10 @@ static int setup(struct spi_device *spi)
| (QUARK_X1000_SSCR1_TxTresh(tx_thres)
& QUARK_X1000_SSCR1_TFT);
break;
case CE4100_SSP:
chip->threshold = (CE4100_SSCR1_RxTresh(rx_thres) & CE4100_SSCR1_RFT) |
(CE4100_SSCR1_TxTresh(tx_thres) & CE4100_SSCR1_TFT);
break;
default:
chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
(SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
@ -1352,7 +1397,8 @@ static void cleanup(struct spi_device *spi)
if (!chip)
return;
if (drv_data->ssp_type != CE4100_SSP && gpio_is_valid(chip->gpio_cs))
if (drv_data->ssp_type != CE4100_SSP && !drv_data->cs_gpiods &&
gpio_is_valid(chip->gpio_cs))
gpio_free(chip->gpio_cs);
kfree(chip);
@ -1530,7 +1576,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
struct driver_data *drv_data;
struct ssp_device *ssp;
const struct lpss_config *config;
int status;
int status, count;
u32 tmp;
platform_info = dev_get_platdata(dev);
@ -1630,15 +1676,20 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
pxa2xx_spi_write(drv_data, SSCR0, 0);
switch (drv_data->ssp_type) {
case QUARK_X1000_SSP:
tmp = QUARK_X1000_SSCR1_RxTresh(RX_THRESH_QUARK_X1000_DFLT)
| QUARK_X1000_SSCR1_TxTresh(TX_THRESH_QUARK_X1000_DFLT);
tmp = QUARK_X1000_SSCR1_RxTresh(RX_THRESH_QUARK_X1000_DFLT) |
QUARK_X1000_SSCR1_TxTresh(TX_THRESH_QUARK_X1000_DFLT);
pxa2xx_spi_write(drv_data, SSCR1, tmp);
/* using the Motorola SPI protocol and use 8 bit frame */
pxa2xx_spi_write(drv_data, SSCR0,
QUARK_X1000_SSCR0_Motorola
| QUARK_X1000_SSCR0_DataSize(8));
tmp = QUARK_X1000_SSCR0_Motorola | QUARK_X1000_SSCR0_DataSize(8);
pxa2xx_spi_write(drv_data, SSCR0, tmp);
break;
case CE4100_SSP:
tmp = CE4100_SSCR1_RxTresh(RX_THRESH_CE4100_DFLT) |
CE4100_SSCR1_TxTresh(TX_THRESH_CE4100_DFLT);
pxa2xx_spi_write(drv_data, SSCR1, tmp);
tmp = SSCR0_SCR(2) | SSCR0_Motorola | SSCR0_DataSize(8);
pxa2xx_spi_write(drv_data, SSCR0, tmp);
default:
tmp = SSCR1_RxTresh(RX_THRESH_DFLT) |
SSCR1_TxTresh(TX_THRESH_DFLT);
@ -1669,6 +1720,39 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
}
master->num_chipselect = platform_info->num_chipselect;
count = gpiod_count(&pdev->dev, "cs");
if (count > 0) {
int i;
master->num_chipselect = max_t(int, count,
master->num_chipselect);
drv_data->cs_gpiods = devm_kcalloc(&pdev->dev,
master->num_chipselect, sizeof(struct gpio_desc *),
GFP_KERNEL);
if (!drv_data->cs_gpiods) {
status = -ENOMEM;
goto out_error_clock_enabled;
}
for (i = 0; i < master->num_chipselect; i++) {
struct gpio_desc *gpiod;
gpiod = devm_gpiod_get_index(dev, "cs", i,
GPIOD_OUT_HIGH);
if (IS_ERR(gpiod)) {
/* Means use native chip select */
if (PTR_ERR(gpiod) == -ENOENT)
continue;
status = (int)PTR_ERR(gpiod);
goto out_error_clock_enabled;
} else {
drv_data->cs_gpiods[i] = gpiod;
}
}
}
tasklet_init(&drv_data->pump_transfers, pump_transfers,
(unsigned long)drv_data);
@ -1742,7 +1826,7 @@ static int pxa2xx_spi_suspend(struct device *dev)
{
struct driver_data *drv_data = dev_get_drvdata(dev);
struct ssp_device *ssp = drv_data->ssp;
int status = 0;
int status;
status = spi_master_suspend(drv_data->master);
if (status != 0)
@ -1759,7 +1843,7 @@ static int pxa2xx_spi_resume(struct device *dev)
{
struct driver_data *drv_data = dev_get_drvdata(dev);
struct ssp_device *ssp = drv_data->ssp;
int status = 0;
int status;
/* Enable the SSP clock */
if (!pm_runtime_suspended(dev))

View File

@ -53,9 +53,7 @@ struct driver_data {
atomic_t dma_running;
/* Current message transfer state info */
struct spi_message *cur_msg;
struct spi_transfer *cur_transfer;
struct chip_data *cur_chip;
size_t len;
void *tx;
void *tx_end;
@ -68,6 +66,9 @@ struct driver_data {
void (*cs_control)(u32 command);
void __iomem *lpss_base;
/* GPIOs for chip selects */
struct gpio_desc **cs_gpiods;
};
struct chip_data {

View File

@ -982,8 +982,10 @@ static int spi_qup_suspend(struct device *device)
if (ret)
return ret;
clk_disable_unprepare(controller->cclk);
clk_disable_unprepare(controller->iclk);
if (!pm_runtime_suspended(device)) {
clk_disable_unprepare(controller->cclk);
clk_disable_unprepare(controller->iclk);
}
return 0;
}

View File

@ -83,7 +83,6 @@
#define SSSR_RFS (1 << 6) /* Receive FIFO Service Request */
#define SSSR_ROR (1 << 7) /* Receive FIFO Overrun */
#ifdef CONFIG_ARCH_PXA
#define RX_THRESH_DFLT 8
#define TX_THRESH_DFLT 8
@ -95,19 +94,16 @@
#define SSCR1_RFT (0x00003c00) /* Receive FIFO Threshold (mask) */
#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..16] */
#else
#define RX_THRESH_CE4100_DFLT 2
#define TX_THRESH_CE4100_DFLT 2
#define RX_THRESH_DFLT 2
#define TX_THRESH_DFLT 2
#define CE4100_SSSR_TFL_MASK (0x3 << 8) /* Transmit FIFO Level mask */
#define CE4100_SSSR_RFL_MASK (0x3 << 12) /* Receive FIFO Level mask */
#define SSSR_TFL_MASK (0x3 << 8) /* Transmit FIFO Level mask */
#define SSSR_RFL_MASK (0x3 << 12) /* Receive FIFO Level mask */
#define SSCR1_TFT (0x000000c0) /* Transmit FIFO Threshold (mask) */
#define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..4] */
#define SSCR1_RFT (0x00000c00) /* Receive FIFO Threshold (mask) */
#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..4] */
#endif
#define CE4100_SSCR1_TFT (0x000000c0) /* Transmit FIFO Threshold (mask) */
#define CE4100_SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..4] */
#define CE4100_SSCR1_RFT (0x00000c00) /* Receive FIFO Threshold (mask) */
#define CE4100_SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..4] */
/* QUARK_X1000 SSCR0 bit definition */
#define QUARK_X1000_SSCR0_DSS (0x1F) /* Data Size Select (mask) */