summaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-atmel.c16
-rw-r--r--drivers/spi/spi-bcm-qspi.c4
-rw-r--r--drivers/spi/spi-dw-mid.c6
-rw-r--r--drivers/spi/spi-dw.c26
-rw-r--r--drivers/spi/spi-dw.h4
-rw-r--r--drivers/spi/spi-gpio.c270
-rw-r--r--drivers/spi/spi-pxa2xx.c2
-rw-r--r--drivers/spi/spi.c19
8 files changed, 133 insertions, 214 deletions
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 4a11fc0d4136..3f890d162934 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -768,14 +768,14 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
rxdesc = dmaengine_prep_slave_single(rxchan,
as->dma_addr_rx_bbuf,
xfer->len,
- DMA_FROM_DEVICE,
+ DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT |
DMA_CTRL_ACK);
} else {
rxdesc = dmaengine_prep_slave_sg(rxchan,
xfer->rx_sg.sgl,
xfer->rx_sg.nents,
- DMA_FROM_DEVICE,
+ DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT |
DMA_CTRL_ACK);
}
@@ -787,14 +787,14 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
memcpy(as->addr_tx_bbuf, xfer->tx_buf, xfer->len);
txdesc = dmaengine_prep_slave_single(txchan,
as->dma_addr_tx_bbuf,
- xfer->len, DMA_TO_DEVICE,
+ xfer->len, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT |
DMA_CTRL_ACK);
} else {
txdesc = dmaengine_prep_slave_sg(txchan,
xfer->tx_sg.sgl,
xfer->tx_sg.nents,
- DMA_TO_DEVICE,
+ DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT |
DMA_CTRL_ACK);
}
@@ -1512,6 +1512,11 @@ static void atmel_spi_init(struct atmel_spi *as)
{
spi_writel(as, CR, SPI_BIT(SWRST));
spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
+
+ /* It is recommended to enable FIFOs first thing after reset */
+ if (as->fifo_size)
+ spi_writel(as, CR, SPI_BIT(FIFOEN));
+
if (as->caps.has_wdrbt) {
spi_writel(as, MR, SPI_BIT(WDRBT) | SPI_BIT(MODFDIS)
| SPI_BIT(MSTR));
@@ -1522,9 +1527,6 @@ static void atmel_spi_init(struct atmel_spi *as)
if (as->use_pdc)
spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
spi_writel(as, CR, SPI_BIT(SPIEN));
-
- if (as->fifo_size)
- spi_writel(as, CR, SPI_BIT(FIFOEN));
}
static int atmel_spi_probe(struct platform_device *pdev)
diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c
index a172ab299e80..1596d35498c5 100644
--- a/drivers/spi/spi-bcm-qspi.c
+++ b/drivers/spi/spi-bcm-qspi.c
@@ -1247,7 +1247,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
qspi->base[MSPI] = devm_ioremap_resource(dev, res);
if (IS_ERR(qspi->base[MSPI])) {
ret = PTR_ERR(qspi->base[MSPI]);
- goto qspi_probe_err;
+ goto qspi_resource_err;
}
} else {
goto qspi_resource_err;
@@ -1258,7 +1258,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
qspi->base[BSPI] = devm_ioremap_resource(dev, res);
if (IS_ERR(qspi->base[BSPI])) {
ret = PTR_ERR(qspi->base[BSPI]);
- goto qspi_probe_err;
+ goto qspi_resource_err;
}
qspi->bspi_mode = true;
} else {
diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c
index 837cb8d0bac6..3db905f5f345 100644
--- a/drivers/spi/spi-dw-mid.c
+++ b/drivers/spi/spi-dw-mid.c
@@ -112,10 +112,10 @@ static irqreturn_t dma_transfer(struct dw_spi *dws)
return IRQ_HANDLED;
}
-static bool mid_spi_can_dma(struct spi_master *master, struct spi_device *spi,
- struct spi_transfer *xfer)
+static bool mid_spi_can_dma(struct spi_controller *master,
+ struct spi_device *spi, struct spi_transfer *xfer)
{
- struct dw_spi *dws = spi_master_get_devdata(master);
+ struct dw_spi *dws = spi_controller_get_devdata(master);
if (!dws->dma_inited)
return false;
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
index 211cc7d75bf8..f693bfe95ab9 100644
--- a/drivers/spi/spi-dw.c
+++ b/drivers/spi/spi-dw.c
@@ -135,7 +135,7 @@ static inline void dw_spi_debugfs_remove(struct dw_spi *dws)
static void dw_spi_set_cs(struct spi_device *spi, bool enable)
{
- struct dw_spi *dws = spi_master_get_devdata(spi->master);
+ struct dw_spi *dws = spi_controller_get_devdata(spi->controller);
struct chip_data *chip = spi_get_ctldata(spi);
/* Chip select logic is inverted from spi_set_cs() */
@@ -250,8 +250,8 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
static irqreturn_t dw_spi_irq(int irq, void *dev_id)
{
- struct spi_master *master = dev_id;
- struct dw_spi *dws = spi_master_get_devdata(master);
+ struct spi_controller *master = dev_id;
+ struct dw_spi *dws = spi_controller_get_devdata(master);
u16 irq_status = dw_readl(dws, DW_SPI_ISR) & 0x3f;
if (!irq_status)
@@ -277,10 +277,10 @@ static int poll_transfer(struct dw_spi *dws)
return 0;
}
-static int dw_spi_transfer_one(struct spi_master *master,
+static int dw_spi_transfer_one(struct spi_controller *master,
struct spi_device *spi, struct spi_transfer *transfer)
{
- struct dw_spi *dws = spi_master_get_devdata(master);
+ struct dw_spi *dws = spi_controller_get_devdata(master);
struct chip_data *chip = spi_get_ctldata(spi);
u8 imask = 0;
u16 txlevel = 0;
@@ -383,10 +383,10 @@ static int dw_spi_transfer_one(struct spi_master *master,
return 1;
}
-static void dw_spi_handle_err(struct spi_master *master,
+static void dw_spi_handle_err(struct spi_controller *master,
struct spi_message *msg)
{
- struct dw_spi *dws = spi_master_get_devdata(master);
+ struct dw_spi *dws = spi_controller_get_devdata(master);
if (dws->dma_mapped)
dws->dma_ops->dma_stop(dws);
@@ -471,7 +471,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi *dws)
int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
{
- struct spi_master *master;
+ struct spi_controller *master;
int ret;
BUG_ON(dws == NULL);
@@ -518,8 +518,8 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
}
}
- spi_master_set_devdata(master, dws);
- ret = devm_spi_register_master(dev, master);
+ spi_controller_set_devdata(master, dws);
+ ret = devm_spi_register_controller(dev, master);
if (ret) {
dev_err(&master->dev, "problem registering spi master\n");
goto err_dma_exit;
@@ -534,7 +534,7 @@ err_dma_exit:
spi_enable_chip(dws, 0);
free_irq(dws->irq, master);
err_free_master:
- spi_master_put(master);
+ spi_controller_put(master);
return ret;
}
EXPORT_SYMBOL_GPL(dw_spi_add_host);
@@ -556,7 +556,7 @@ int dw_spi_suspend_host(struct dw_spi *dws)
{
int ret;
- ret = spi_master_suspend(dws->master);
+ ret = spi_controller_suspend(dws->master);
if (ret)
return ret;
@@ -570,7 +570,7 @@ int dw_spi_resume_host(struct dw_spi *dws)
int ret;
spi_hw_init(&dws->master->dev, dws);
- ret = spi_master_resume(dws->master);
+ ret = spi_controller_resume(dws->master);
if (ret)
dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret);
return ret;
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index 5c07cf8f19e0..2cde2473b3e9 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -93,14 +93,14 @@ struct dw_spi_dma_ops {
int (*dma_init)(struct dw_spi *dws);
void (*dma_exit)(struct dw_spi *dws);
int (*dma_setup)(struct dw_spi *dws, struct spi_transfer *xfer);
- bool (*can_dma)(struct spi_master *master, struct spi_device *spi,
+ bool (*can_dma)(struct spi_controller *master, struct spi_device *spi,
struct spi_transfer *xfer);
int (*dma_transfer)(struct dw_spi *dws, struct spi_transfer *xfer);
void (*dma_stop)(struct dw_spi *dws);
};
struct dw_spi {
- struct spi_master *master;
+ struct spi_controller *master;
enum dw_ssi_type type;
void __iomem *regs;
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index 1c34c9314c8a..b85a93cad44a 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -2,6 +2,7 @@
* SPI master driver using generic bitbanged GPIO
*
* Copyright (C) 2006,2008 David Brownell
+ * Copyright (C) 2017 Linus Walleij
*
* 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
@@ -16,10 +17,9 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/of_gpio.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
@@ -44,7 +44,11 @@ struct spi_gpio {
struct spi_bitbang bitbang;
struct spi_gpio_platform_data pdata;
struct platform_device *pdev;
- unsigned long cs_gpios[0];
+ struct gpio_desc *sck;
+ struct gpio_desc *miso;
+ struct gpio_desc *mosi;
+ struct gpio_desc **cs_gpios;
+ bool has_cs;
};
/*----------------------------------------------------------------------*/
@@ -77,13 +81,6 @@ struct spi_gpio {
#define GENERIC_BITBANG /* vs tight inlines */
-/* all functions referencing these symbols must define pdata */
-#define SPI_MISO_GPIO ((pdata)->miso)
-#define SPI_MOSI_GPIO ((pdata)->mosi)
-#define SPI_SCK_GPIO ((pdata)->sck)
-
-#define SPI_N_CHIPSEL ((pdata)->num_chipselect)
-
#endif
/*----------------------------------------------------------------------*/
@@ -105,25 +102,27 @@ spi_to_pdata(const struct spi_device *spi)
return &spi_to_spi_gpio(spi)->pdata;
}
-/* this is #defined to avoid unused-variable warnings when inlining */
-#define pdata spi_to_pdata(spi)
-
+/* These helpers are in turn called by the bitbang inlines */
static inline void setsck(const struct spi_device *spi, int is_on)
{
- gpio_set_value_cansleep(SPI_SCK_GPIO, is_on);
+ struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
+
+ gpiod_set_value_cansleep(spi_gpio->sck, is_on);
}
static inline void setmosi(const struct spi_device *spi, int is_on)
{
- gpio_set_value_cansleep(SPI_MOSI_GPIO, is_on);
+ struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
+
+ gpiod_set_value_cansleep(spi_gpio->mosi, is_on);
}
static inline int getmiso(const struct spi_device *spi)
{
- return !!gpio_get_value_cansleep(SPI_MISO_GPIO);
-}
+ struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
-#undef pdata
+ return !!gpiod_get_value_cansleep(spi_gpio->miso);
+}
/*
* NOTE: this clocks "as fast as we can". It "should" be a function of the
@@ -216,123 +215,89 @@ static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,
static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
{
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
- unsigned long cs = spi_gpio->cs_gpios[spi->chip_select];
- /* set initial clock polarity */
+ /* set initial clock line level */
if (is_active)
- setsck(spi, spi->mode & SPI_CPOL);
+ gpiod_set_value_cansleep(spi_gpio->sck, spi->mode & SPI_CPOL);
+
+ /* Drive chip select line, if we have one */
+ if (spi_gpio->has_cs) {
+ struct gpio_desc *cs = spi_gpio->cs_gpios[spi->chip_select];
- if (cs != SPI_GPIO_NO_CHIPSELECT) {
- /* SPI is normally active-low */
- gpio_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
+ /* SPI chip selects are normally active-low */
+ gpiod_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
}
}
static int spi_gpio_setup(struct spi_device *spi)
{
- unsigned long cs;
+ struct gpio_desc *cs;
int status = 0;
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
- struct device_node *np = spi->master->dev.of_node;
-
- if (np) {
- /*
- * In DT environments, the CS GPIOs have already been
- * initialized from the "cs-gpios" property of the node.
- */
- cs = spi_gpio->cs_gpios[spi->chip_select];
- } else {
- /*
- * ... otherwise, take it from spi->controller_data
- */
- cs = (uintptr_t) spi->controller_data;
- }
- if (!spi->controller_state) {
- if (cs != SPI_GPIO_NO_CHIPSELECT) {
- status = gpio_request(cs, dev_name(&spi->dev));
- if (status)
- return status;
- status = gpio_direction_output(cs,
- !(spi->mode & SPI_CS_HIGH));
- }
- }
- if (!status) {
- /* in case it was initialized from static board data */
- spi_gpio->cs_gpios[spi->chip_select] = cs;
+ /*
+ * The CS GPIOs have already been
+ * initialized from the descriptor lookup.
+ */
+ cs = spi_gpio->cs_gpios[spi->chip_select];
+ if (!spi->controller_state && cs)
+ status = gpiod_direction_output(cs,
+ !(spi->mode & SPI_CS_HIGH));
+
+ if (!status)
status = spi_bitbang_setup(spi);
- }
- if (status) {
- if (!spi->controller_state && cs != SPI_GPIO_NO_CHIPSELECT)
- gpio_free(cs);
- }
return status;
}
static void spi_gpio_cleanup(struct spi_device *spi)
{
- struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
- unsigned long cs = spi_gpio->cs_gpios[spi->chip_select];
-
- if (cs != SPI_GPIO_NO_CHIPSELECT)
- gpio_free(cs);
spi_bitbang_cleanup(spi);
}
-static int spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
-{
- int value;
-
- value = gpio_request(pin, label);
- if (value == 0) {
- if (is_in)
- value = gpio_direction_input(pin);
- else
- value = gpio_direction_output(pin, 0);
- }
- return value;
-}
-
-static int spi_gpio_request(struct spi_gpio_platform_data *pdata,
- const char *label, u16 *res_flags)
+/*
+ * It can be convenient to use this driver with pins that have alternate
+ * functions associated with a "native" SPI controller if a driver for that
+ * controller is not available, or is missing important functionality.
+ *
+ * On platforms which can do so, configure MISO with a weak pullup unless
+ * there's an external pullup on that signal. That saves power by avoiding
+ * floating signals. (A weak pulldown would save power too, but many
+ * drivers expect to see all-ones data as the no slave "response".)
+ */
+static int spi_gpio_request(struct device *dev,
+ struct spi_gpio *spi_gpio,
+ unsigned int num_chipselects,
+ u16 *mflags)
{
- int value;
-
- /* NOTE: SPI_*_GPIO symbols may reference "pdata" */
+ int i;
- if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) {
- value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false);
- if (value)
- goto done;
- } else {
+ spi_gpio->mosi = devm_gpiod_get_optional(dev, "mosi", GPIOD_OUT_LOW);
+ if (IS_ERR(spi_gpio->mosi))
+ return PTR_ERR(spi_gpio->mosi);
+ if (!spi_gpio->mosi)
/* HW configuration without MOSI pin */
- *res_flags |= SPI_MASTER_NO_TX;
- }
+ *mflags |= SPI_MASTER_NO_TX;
- if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) {
- value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
- if (value)
- goto free_mosi;
- } else {
+ spi_gpio->miso = devm_gpiod_get_optional(dev, "miso", GPIOD_IN);
+ if (IS_ERR(spi_gpio->miso))
+ return PTR_ERR(spi_gpio->miso);
+ if (!spi_gpio->miso)
/* HW configuration without MISO pin */
- *res_flags |= SPI_MASTER_NO_RX;
- }
+ *mflags |= SPI_MASTER_NO_RX;
- value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
- if (value)
- goto free_miso;
+ spi_gpio->sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW);
+ if (IS_ERR(spi_gpio->mosi))
+ return PTR_ERR(spi_gpio->mosi);
- goto done;
+ for (i = 0; i < num_chipselects; i++) {
+ spi_gpio->cs_gpios[i] = devm_gpiod_get_index(dev, "cs",
+ i, GPIOD_OUT_HIGH);
+ if (IS_ERR(spi_gpio->cs_gpios[i]))
+ return PTR_ERR(spi_gpio->cs_gpios[i]);
+ }
-free_miso:
- if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
- gpio_free(SPI_MISO_GPIO);
-free_mosi:
- if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
- gpio_free(SPI_MOSI_GPIO);
-done:
- return value;
+ return 0;
}
#ifdef CONFIG_OF
@@ -358,26 +323,6 @@ static int spi_gpio_probe_dt(struct platform_device *pdev)
if (!pdata)
return -ENOMEM;
- ret = of_get_named_gpio(np, "gpio-sck", 0);
- if (ret < 0) {
- dev_err(&pdev->dev, "gpio-sck property not found\n");
- goto error_free;
- }
- pdata->sck = ret;
-
- ret = of_get_named_gpio(np, "gpio-miso", 0);
- if (ret < 0) {
- dev_info(&pdev->dev, "gpio-miso property not found, switching to no-rx mode\n");
- pdata->miso = SPI_GPIO_NO_MISO;
- } else
- pdata->miso = ret;
-
- ret = of_get_named_gpio(np, "gpio-mosi", 0);
- if (ret < 0) {
- dev_info(&pdev->dev, "gpio-mosi property not found, switching to no-tx mode\n");
- pdata->mosi = SPI_GPIO_NO_MOSI;
- } else
- pdata->mosi = ret;
ret = of_property_read_u32(np, "num-chipselects", &tmp);
if (ret < 0) {
@@ -409,7 +354,6 @@ static int spi_gpio_probe(struct platform_device *pdev)
struct spi_gpio_platform_data *pdata;
u16 master_flags = 0;
bool use_of = 0;
- int num_devices;
status = spi_gpio_probe_dt(pdev);
if (status < 0)
@@ -423,59 +367,41 @@ static int spi_gpio_probe(struct platform_device *pdev)
return -ENODEV;
#endif
- if (use_of && !SPI_N_CHIPSEL)
- num_devices = 1;
- else
- num_devices = SPI_N_CHIPSEL;
-
- status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags);
- if (status < 0)
- return status;
+ master = spi_alloc_master(&pdev->dev, sizeof(*spi_gpio));
+ if (!master)
+ return -ENOMEM;
- master = spi_alloc_master(&pdev->dev, sizeof(*spi_gpio) +
- (sizeof(unsigned long) * num_devices));
- if (!master) {
- status = -ENOMEM;
- goto gpio_free;
- }
spi_gpio = spi_master_get_devdata(master);
+
+ spi_gpio->cs_gpios = devm_kzalloc(&pdev->dev,
+ pdata->num_chipselect * sizeof(*spi_gpio->cs_gpios),
+ GFP_KERNEL);
+ if (!spi_gpio->cs_gpios)
+ return -ENOMEM;
+
platform_set_drvdata(pdev, spi_gpio);
+ /* Determine if we have chip selects connected */
+ spi_gpio->has_cs = !!pdata->num_chipselect;
+
spi_gpio->pdev = pdev;
if (pdata)
spi_gpio->pdata = *pdata;
+ status = spi_gpio_request(&pdev->dev, spi_gpio,
+ pdata->num_chipselect, &master_flags);
+ if (status)
+ return status;
+
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
master->flags = master_flags;
master->bus_num = pdev->id;
- master->num_chipselect = num_devices;
+ /* The master needs to think there is a chipselect even if not connected */
+ master->num_chipselect = spi_gpio->has_cs ? pdata->num_chipselect : 1;
master->setup = spi_gpio_setup;
master->cleanup = spi_gpio_cleanup;
#ifdef CONFIG_OF
master->dev.of_node = pdev->dev.of_node;
-
- if (use_of) {
- int i;
- struct device_node *np = pdev->dev.of_node;
-
- /*
- * In DT environments, take the CS GPIO from the "cs-gpios"
- * property of the node.
- */
-
- if (!SPI_N_CHIPSEL)
- spi_gpio->cs_gpios[0] = SPI_GPIO_NO_CHIPSELECT;
- else
- for (i = 0; i < SPI_N_CHIPSEL; i++) {
- status = of_get_named_gpio(np, "cs-gpios", i);
- if (status < 0) {
- dev_err(&pdev->dev,
- "invalid cs-gpios property\n");
- goto gpio_free;
- }
- spi_gpio->cs_gpios[i] = status;
- }
- }
#endif
spi_gpio->bitbang.master = master;
@@ -496,15 +422,8 @@ static int spi_gpio_probe(struct platform_device *pdev)
spi_gpio->bitbang.flags = SPI_CS_HIGH;
status = spi_bitbang_start(&spi_gpio->bitbang);
- if (status < 0) {
-gpio_free:
- if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
- gpio_free(SPI_MISO_GPIO);
- if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
- gpio_free(SPI_MOSI_GPIO);
- gpio_free(SPI_SCK_GPIO);
+ if (status)
spi_master_put(master);
- }
return status;
}
@@ -520,11 +439,6 @@ static int spi_gpio_remove(struct platform_device *pdev)
/* stop() unregisters child devices too */
spi_bitbang_stop(&spi_gpio->bitbang);
- if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
- gpio_free(SPI_MISO_GPIO);
- if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
- gpio_free(SPI_MOSI_GPIO);
- gpio_free(SPI_SCK_GPIO);
spi_master_put(spi_gpio->bitbang.master);
return 0;
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index b0822d1dba29..56254b35875d 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -1802,6 +1802,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
return status;
out_error_clock_enabled:
+ pm_runtime_put_noidle(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
clk_disable_unprepare(ssp->clk);
pxa2xx_spi_dma_release(drv_data);
free_irq(ssp->irq, drv_data);
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index b33a727a0158..7b213faa0a2b 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -779,8 +779,14 @@ static int spi_map_buf(struct spi_controller *ctlr, struct device *dev,
for (i = 0; i < sgs; i++) {
if (vmalloced_buf || kmap_buf) {
- min = min_t(size_t,
- len, desc_len - offset_in_page(buf));
+ /*
+ * Next scatterlist entry size is the minimum between
+ * the desc_len and the remaining buffer length that
+ * fits in a page.
+ */
+ min = min_t(size_t, desc_len,
+ min_t(size_t, len,
+ PAGE_SIZE - offset_in_page(buf)));
if (vmalloced_buf)
vm_page = vmalloc_to_page(buf);
else
@@ -2254,12 +2260,6 @@ void spi_unregister_controller(struct spi_controller *ctlr)
mutex_lock(&board_lock);
found = idr_find(&spi_master_idr, id);
mutex_unlock(&board_lock);
- if (found != ctlr) {
- dev_dbg(&ctlr->dev,
- "attempting to delete unregistered controller [%s]\n",
- dev_name(&ctlr->dev));
- return;
- }
if (ctlr->queued) {
if (spi_destroy_queue(ctlr))
dev_err(&ctlr->dev, "queue remove failed\n");
@@ -2272,7 +2272,8 @@ void spi_unregister_controller(struct spi_controller *ctlr)
device_unregister(&ctlr->dev);
/* free bus id */
mutex_lock(&board_lock);
- idr_remove(&spi_master_idr, id);
+ if (found == ctlr)
+ idr_remove(&spi_master_idr, id);
mutex_unlock(&board_lock);
}
EXPORT_SYMBOL_GPL(spi_unregister_controller);