aboutsummaryrefslogtreecommitdiff
path: root/drivers/spi/spi-oc-tiny.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-oc-tiny.c')
-rw-r--r--drivers/spi/spi-oc-tiny.c117
1 files changed, 33 insertions, 84 deletions
diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c
index 698018fd992..8998d11c723 100644
--- a/drivers/spi/spi-oc-tiny.c
+++ b/drivers/spi/spi-oc-tiny.c
@@ -15,7 +15,6 @@
* published by the Free Software Foundation.
*/
-#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/module.h>
@@ -54,7 +53,7 @@ struct tiny_spi {
unsigned int txc, rxc;
const u8 *txp;
u8 *rxp;
- unsigned int gpio_cs_count;
+ int gpio_cs_count;
int *gpio_cs;
};
@@ -74,7 +73,7 @@ static void tiny_spi_chipselect(struct spi_device *spi, int is_active)
{
struct tiny_spi *hw = tiny_spi_to_hw(spi);
- if (hw->gpio_cs_count) {
+ if (hw->gpio_cs_count > 0) {
gpio_set_value(hw->gpio_cs[spi->chip_select],
(spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
}
@@ -129,7 +128,7 @@ static int tiny_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
unsigned int i;
if (hw->irq >= 0) {
- /* use intrrupt driven data transfer */
+ /* use interrupt driven data transfer */
hw->len = t->len;
hw->txp = t->tx_buf;
hw->rxp = t->rx_buf;
@@ -153,62 +152,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;
}
@@ -243,7 +202,7 @@ static irqreturn_t tiny_spi_irq(int irq, void *dev)
#ifdef CONFIG_OF
#include <linux/of_gpio.h>
-static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
+static int tiny_spi_of_probe(struct platform_device *pdev)
{
struct tiny_spi *hw = platform_get_drvdata(pdev);
struct device_node *np = pdev->dev.of_node;
@@ -254,7 +213,7 @@ static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
if (!np)
return 0;
hw->gpio_cs_count = of_gpio_count(np);
- if (hw->gpio_cs_count) {
+ if (hw->gpio_cs_count > 0) {
hw->gpio_cs = devm_kzalloc(&pdev->dev,
hw->gpio_cs_count * sizeof(unsigned int),
GFP_KERNEL);
@@ -277,15 +236,15 @@ static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
return 0;
}
#else /* !CONFIG_OF */
-static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
+static int tiny_spi_of_probe(struct platform_device *pdev)
{
return 0;
}
#endif /* CONFIG_OF */
-static int __devinit tiny_spi_probe(struct platform_device *pdev)
+static int tiny_spi_probe(struct platform_device *pdev)
{
- struct tiny_spi_platform_data *platp = pdev->dev.platform_data;
+ struct tiny_spi_platform_data *platp = dev_get_platdata(&pdev->dev);
struct tiny_spi *hw;
struct spi_master *master;
struct resource *res;
@@ -306,24 +265,18 @@ static int __devinit tiny_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, hw);
/* setup the state for the bitbang driver */
- hw->bitbang.master = spi_master_get(master);
- if (!hw->bitbang.master)
- return err;
+ hw->bitbang.master = master;
hw->bitbang.setup_transfer = tiny_spi_setup_transfer;
hw->bitbang.chipselect = tiny_spi_chipselect;
hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs;
/* find and map our resources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- goto exit_busy;
- if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
- pdev->name))
- goto exit_busy;
- hw->base = devm_ioremap_nocache(&pdev->dev, res->start,
- resource_size(res));
- if (!hw->base)
- goto exit_busy;
+ hw->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hw->base)) {
+ err = PTR_ERR(hw->base);
+ goto exit;
+ }
/* irq is optional */
hw->irq = platform_get_irq(pdev, 0);
if (hw->irq >= 0) {
@@ -337,8 +290,10 @@ static int __devinit tiny_spi_probe(struct platform_device *pdev)
if (platp) {
hw->gpio_cs_count = platp->gpio_cs_count;
hw->gpio_cs = platp->gpio_cs;
- if (platp->gpio_cs_count && !platp->gpio_cs)
- goto exit_busy;
+ if (platp->gpio_cs_count && !platp->gpio_cs) {
+ err = -EBUSY;
+ goto exit;
+ }
hw->freq = platp->freq;
hw->baudwidth = platp->baudwidth;
} else {
@@ -352,7 +307,7 @@ static int __devinit tiny_spi_probe(struct platform_device *pdev)
goto exit_gpio;
gpio_direction_output(hw->gpio_cs[i], 1);
}
- hw->bitbang.master->num_chipselect = max(1U, hw->gpio_cs_count);
+ hw->bitbang.master->num_chipselect = max(1, hw->gpio_cs_count);
/* register our spi controller */
err = spi_bitbang_start(&hw->bitbang);
@@ -365,15 +320,12 @@ static int __devinit tiny_spi_probe(struct platform_device *pdev)
exit_gpio:
while (i-- > 0)
gpio_free(hw->gpio_cs[i]);
-exit_busy:
- err = -EBUSY;
exit:
- platform_set_drvdata(pdev, NULL);
spi_master_put(master);
return err;
}
-static int __devexit tiny_spi_remove(struct platform_device *pdev)
+static int tiny_spi_remove(struct platform_device *pdev)
{
struct tiny_spi *hw = platform_get_drvdata(pdev);
struct spi_master *master = hw->bitbang.master;
@@ -382,7 +334,6 @@ static int __devexit tiny_spi_remove(struct platform_device *pdev)
spi_bitbang_stop(&hw->bitbang);
for (i = 0; i < hw->gpio_cs_count; i++)
gpio_free(hw->gpio_cs[i]);
- platform_set_drvdata(pdev, NULL);
spi_master_put(master);
return 0;
}
@@ -393,18 +344,16 @@ static const struct of_device_id tiny_spi_match[] = {
{},
};
MODULE_DEVICE_TABLE(of, tiny_spi_match);
-#else /* CONFIG_OF */
-#define tiny_spi_match NULL
#endif /* CONFIG_OF */
static struct platform_driver tiny_spi_driver = {
.probe = tiny_spi_probe,
- .remove = __devexit_p(tiny_spi_remove),
+ .remove = tiny_spi_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
.pm = NULL,
- .of_match_table = tiny_spi_match,
+ .of_match_table = of_match_ptr(tiny_spi_match),
},
};
module_platform_driver(tiny_spi_driver);