From a4ee96e4886768a177e4dc4935ac676513913581 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Mon, 30 Sep 2013 14:52:59 -0400 Subject: spi: davinci: Fix the build warning with CONFIG_ARM_LPAE=y MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With CONFIG_ARM_LPAE=y spi driver throws below warning drivers/spi/spi-davinci.c: In function ‘davinci_spi_probe’: drivers/spi/spi-davinci.c:965:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘resource_size_t’ [-Wformat] drivers/spi/spi-davinci.c:965:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘resource_size_t’ [-Wformat] Lets use '%pa' to properly print 'resource_size_t' type variables. Signed-off-by: Santosh Shilimkar Signed-off-by: Mark Brown --- drivers/spi/spi-davinci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 50b2d88c8190..d3f638613b40 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -963,8 +963,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); } -- cgit v1.2.3 From 8e1c8096faae6b8ac788a1bbeeea126044cb485a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 27 Nov 2013 01:41:44 +0100 Subject: spi: rcar: Fix uninitialized variable warning The transfer data length variable is set based on the desired access size, without a default case. This results in a compiler warning, even though the access size is always set to a supported value. Create a default case to silence the warning. Signed-off-by: Laurent Pinchart Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 58449ad4ad0d..a3dca1dfd8ab 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -268,7 +268,7 @@ 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; -- cgit v1.2.3 From 5ffbe2d90d81b8734eaf69ee4dad8507f318aad0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 27 Nov 2013 01:41:45 +0100 Subject: spi: rcar: Fix pointer cast in the remove function The platform driver data is set to point to the rspi_data structure at probe time. Calling spi_master_get() on the pointer is just plain wrong and only works by chance. Fix it by using the platform driver data directly. Signed-off-by: Laurent Pinchart Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index a3dca1dfd8ab..621be5dbea31 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -885,14 +885,13 @@ static void rspi_release_dma(struct rspi_data *rspi) static int rspi_remove(struct platform_device *pdev) { - struct rspi_data *rspi = spi_master_get(platform_get_drvdata(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); - spi_master_put(rspi->master); return 0; } -- cgit v1.2.3 From 5d79e9ac89b45643c98b68ea7ce62c80b3b4e160 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 27 Nov 2013 01:41:46 +0100 Subject: spi: rcar: Use devm_* managed allocators This simplies error and cleanup code paths. Signed-off-by: Laurent Pinchart Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 621be5dbea31..19c65c43cbc5 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -889,9 +889,6 @@ static int rspi_remove(struct platform_device *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); return 0; } @@ -913,12 +910,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 +927,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); @@ -966,36 +958,32 @@ static int rspi_probe(struct platform_device *pdev) master->transfer = rspi_transfer; master->cleanup = rspi_cleanup; - 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 error1; } rspi->irq = irq; ret = rspi_request_dma(rspi, pdev); if (ret < 0) { dev_err(&pdev->dev, "rspi_request_dma failed.\n"); - goto error4; + goto error2; } ret = spi_register_master(master); if (ret < 0) { dev_err(&pdev->dev, "spi_register_master error.\n"); - goto error4; + goto error2; } dev_info(&pdev->dev, "probed\n"); return 0; -error4: - rspi_release_dma(rspi); - free_irq(irq, rspi); -error3: - clk_put(rspi->clk); error2: - iounmap(rspi->addr); + rspi_release_dma(rspi); error1: spi_master_put(master); -- cgit v1.2.3 From 9a3ced19d8da908234fe9879ee1c0609c8ed21e8 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Wed, 4 Dec 2013 14:10:10 +0900 Subject: spi: coldfire-qspi: Use devm_*() functions Use devm_*() functions to make cleanup paths simpler. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-coldfire-qspi.c | 47 ++++++++++++----------------------------- 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index cc5b75d10c38..9ee81a4c7351 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -403,38 +403,31 @@ static int mcfqspi_probe(struct platform_device *pdev) goto fail0; } - if (!request_mem_region(res->start, resource_size(res), pdev->name)) { - dev_dbg(&pdev->dev, "request_mem_region failed\n"); - status = -EBUSY; + mcfqspi->iobase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mcfqspi->iobase)) { + status = PTR_ERR(mcfqspi->iobase); 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 +438,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 +452,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 +463,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 +487,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; } -- cgit v1.2.3 From 15e0964dc2a097de3cf518badf2237b6b6adf7fe Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Wed, 4 Dec 2013 14:14:30 +0900 Subject: spi: sc18is602: Use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler, and remove unnecessary remove(). Signed-off-by: Jingoo Han Acked-by: Guenter Roeck Signed-off-by: Mark Brown --- drivers/spi/spi-sc18is602.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/spi/spi-sc18is602.c b/drivers/spi/spi-sc18is602.c index 9eda21d739c6..c1a01d1ac315 100644 --- a/drivers/spi/spi-sc18is602.c +++ b/drivers/spi/spi-sc18is602.c @@ -319,7 +319,7 @@ static int sc18is602_probe(struct i2c_client *client, 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 +330,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 +343,6 @@ static struct i2c_driver sc18is602_driver = { .name = "sc18is602", }, .probe = sc18is602_probe, - .remove = sc18is602_remove, .id_table = sc18is602_id, }; -- cgit v1.2.3 From 999b6e932bf7238a0d1eb35d0b3d6eac673b8777 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Wed, 4 Dec 2013 14:11:56 +0900 Subject: spi: falcon: Use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler, and remove unnecessary remove(). Signed-off-by: Jingoo Han Acked-by: Thomas Langer Signed-off-by: Mark Brown --- drivers/spi/spi-falcon.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/spi/spi-falcon.c b/drivers/spi/spi-falcon.c index c7a74f0ef892..dd5bd468e962 100644 --- a/drivers/spi/spi-falcon.c +++ b/drivers/spi/spi-falcon.c @@ -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, -- cgit v1.2.3 From 142168eba9dc5c20538a67049ad53c49bc6f8336 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Sat, 30 Nov 2013 12:42:06 +0100 Subject: spi: bcm63xx-hsspi: add bcm63xx HSSPI driver Add a driver for the High Speed SPI controller found on newer BCM63XX SoCs. It does feature some new modes like 3-wire or dual spi, but neither of it is currently implemented. Signed-off-by: Jonas Gorski Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 7 + drivers/spi/Makefile | 1 + drivers/spi/spi-bcm63xx-hsspi.c | 484 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 492 insertions(+) create mode 100644 drivers/spi/spi-bcm63xx-hsspi.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index eb1f1ef5fa2e..62ce2a9ec612 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -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 diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index ab8d8644af0e..95af48d2d360 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -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 diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c new file mode 100644 index 000000000000..bc8d848d33b7 --- /dev/null +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -0,0 +1,484 @@ +/* + * Broadcom BCM63XX High Speed SPI Controller driver + * + * Copyright 2000-2010 Broadcom Corporation + * Copyright 2012-2013 Jonas Gorski + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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_request_and_ioremap(dev, res_mem); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + clk = clk_get(dev, "hsspi"); + + if (IS_ERR(clk)) + return PTR_ERR(clk); + + rate = clk_get_rate(clk); + if (!rate) { + ret = -EINVAL; + goto out_put_clk; + } + + clk_prepare_enable(clk); + + 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 = spi_register_master(master); + if (ret) + goto out_put_master; + + return 0; + +out_put_master: + spi_master_put(master); +out_disable_clk: + clk_disable_unprepare(clk); +out_put_clk: + clk_put(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); + + spi_unregister_master(master); + + /* reset the hardware and block queue progress */ + __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); + clk_disable_unprepare(bs->clk); + clk_put(bs->clk); + + return 0; +} + +#ifdef CONFIG_PM +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(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); + + clk_enable(bs->clk); + spi_master_resume(master); + + return 0; +} + +static const struct dev_pm_ops bcm63xx_hsspi_pm_ops = { + .suspend = bcm63xx_hsspi_suspend, + .resume = bcm63xx_hsspi_resume, +}; + +#define BCM63XX_HSSPI_PM_OPS (&bcm63xx_hsspi_pm_ops) +#else +#define BCM63XX_HSSPI_PM_OPS NULL +#endif + + + +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 "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From f885135ab6047dd159067d15c9a5de1a67de4e27 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 7 Dec 2013 14:00:40 +0800 Subject: spi: coldfire-qspi: remove redundant return value check of platform_get_resource() Remove unneeded error handling on the result of a call to platform_get_resource() when the value is passed to devm_ioremap_resource(). Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown --- drivers/spi/spi-coldfire-qspi.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index 9ee81a4c7351..cabed8f9119e 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -397,12 +397,6 @@ 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; - goto fail0; - } - mcfqspi->iobase = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(mcfqspi->iobase)) { status = PTR_ERR(mcfqspi->iobase); -- cgit v1.2.3 From 87917528cc922d0b91643dabacec01415c792086 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 6 Dec 2013 17:12:13 +0300 Subject: spi: bcm63xx-hsspi: checking for ERR_PTR instead of NULL devm_request_and_ioremap() returns NULL on error, it doesn't return an ERR_PTR(). This patch fixes it by switching to devm_ioremap_resource() which is the prefered function anyway. Fixes: 142168eba9dc ('spi: bcm63xx-hsspi: add bcm63xx HSSPI driver') Signed-off-by: Dan Carpenter Acked-by: Jonas Gorski Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx-hsspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index bc8d848d33b7..2cfe8eb619fd 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -338,7 +338,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) } res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_request_and_ioremap(dev, res_mem); + regs = devm_ioremap_resource(dev, res_mem); if (IS_ERR(regs)) return PTR_ERR(regs); -- cgit v1.2.3 From 9e03d05eee4ca45ed12749ef6c26bf616262cdd2 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Wed, 4 Dec 2013 14:13:50 +0900 Subject: spi: rcar: Use devm_spi_register_master() Use devm_spi_register_master() to make cleanup paths simpler. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 19c65c43cbc5..cfdbb422a40a 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -887,7 +887,6 @@ 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); return 0; @@ -972,7 +971,7 @@ static int rspi_probe(struct platform_device *pdev) goto error2; } - 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 error2; -- cgit v1.2.3 From b1bdd4f883e1938a1921f300d7f164ce583b1a64 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 19:20:45 +0900 Subject: spi: bcm63xx-hsspi: Use devm_clk_get() Use devm_clk_get() to make cleanup paths simpler. Signed-off-by: Jingoo Han Acked-by: Jonas Gorski Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx-hsspi.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 2cfe8eb619fd..6a763a8a8a5e 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -342,16 +342,14 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) if (IS_ERR(regs)) return PTR_ERR(regs); - clk = clk_get(dev, "hsspi"); + clk = devm_clk_get(dev, "hsspi"); if (IS_ERR(clk)) return PTR_ERR(clk); rate = clk_get_rate(clk); - if (!rate) { - ret = -EINVAL; - goto out_put_clk; - } + if (!rate) + return -EINVAL; clk_prepare_enable(clk); @@ -409,9 +407,6 @@ out_put_master: spi_master_put(master); out_disable_clk: clk_disable_unprepare(clk); -out_put_clk: - clk_put(clk); - return ret; } @@ -426,7 +421,6 @@ static int bcm63xx_hsspi_remove(struct platform_device *pdev) /* reset the hardware and block queue progress */ __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); clk_disable_unprepare(bs->clk); - clk_put(bs->clk); return 0; } -- cgit v1.2.3 From dea5de1b37c08bc8a028b6a53145b7594ba6eb31 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Tue, 17 Dec 2013 21:44:46 +0100 Subject: spi/bcm63xx-hsspi: check result of clk_prepare_enable Ensure we notice if the clock cannot be enabled for any reason and pass the error down. Signed-off-by: Jonas Gorski Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx-hsspi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 6a763a8a8a5e..949dfb57fe89 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -351,7 +351,9 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) if (!rate) return -EINVAL; - clk_prepare_enable(clk); + ret = clk_prepare_enable(clk); + if (ret) + return ret; master = spi_alloc_master(&pdev->dev, sizeof(*bs)); if (!master) { -- cgit v1.2.3 From 7d255695804fbe7b2c30bcd54c1faf1d0918443c Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Tue, 17 Dec 2013 21:44:47 +0100 Subject: spi/bcm63xx-hsspi: use devm_register_master() Simplifies the remove call. Signed-off-by: Jonas Gorski Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx-hsspi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 949dfb57fe89..1721ea99d688 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -399,7 +399,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) goto out_put_master; /* register and we are done */ - ret = spi_register_master(master); + ret = devm_spi_register_master(dev, master); if (ret) goto out_put_master; @@ -418,8 +418,6 @@ 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); - spi_unregister_master(master); - /* reset the hardware and block queue progress */ __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); clk_disable_unprepare(bs->clk); -- cgit v1.2.3 From 937ebf9cd34ab3bc4ca26a4adf9c759fc58cc5e2 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Tue, 17 Dec 2013 21:44:48 +0100 Subject: spi/bcm63xx-hsspi: fix pm sleep support Use the right CONFIG symbol to guard, properly (un)preprare clocks on suspend/resume, and check the result of it. Signed-off-by: Jonas Gorski Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx-hsspi.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 1721ea99d688..b528f9fc8bc0 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -425,14 +425,14 @@ static int bcm63xx_hsspi_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#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(bs->clk); + clk_disable_unprepare(bs->clk); return 0; } @@ -441,30 +441,27 @@ 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; - clk_enable(bs->clk); spi_master_resume(master); return 0; } +#endif static const struct dev_pm_ops bcm63xx_hsspi_pm_ops = { - .suspend = bcm63xx_hsspi_suspend, - .resume = bcm63xx_hsspi_resume, + SET_SYSTEM_SLEEP_PM_OPS(bcm63xx_hsspi_suspend, bcm63xx_hsspi_resume) }; -#define BCM63XX_HSSPI_PM_OPS (&bcm63xx_hsspi_pm_ops) -#else -#define BCM63XX_HSSPI_PM_OPS NULL -#endif - - - static struct platform_driver bcm63xx_hsspi_driver = { .driver = { .name = "bcm63xx-hsspi", .owner = THIS_MODULE, - .pm = BCM63XX_HSSPI_PM_OPS, + .pm = &bcm63xx_hsspi_pm_ops, }, .probe = bcm63xx_hsspi_probe, .remove = bcm63xx_hsspi_remove, -- cgit v1.2.3 From acf4fc6ffa84b59e83f34f587be623a05bc0c55c Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 19:20:15 +0900 Subject: spi: bcm63xx: Use devm_clk_get() Use devm_clk_get() to make cleanup paths simpler. Signed-off-by: Jingoo Han Acked-by: Jonas Gorski Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 80d56b214eb5..7b4ead78782c 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -345,22 +345,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); @@ -427,9 +424,6 @@ out_clk_disable: clk_disable_unprepare(clk); out_err: spi_master_put(master); -out_clk: - clk_put(clk); -out: return ret; } @@ -443,7 +437,6 @@ static int bcm63xx_spi_remove(struct platform_device *pdev) /* HW shutdown */ clk_disable_unprepare(bs->clk); - clk_put(bs->clk); return 0; } -- cgit v1.2.3 From 20e9e78f8b0f1ed02a3a095240853b1767482757 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Tue, 17 Dec 2013 21:42:08 +0100 Subject: spi/bcm63xx: don't reject reads >= 256 bytes The rx_tail register is only 8 bit wide, so it will wrap around after 256 read bytes. This makes it rather meaningless, so drop any usage of it to not treat reads over 256 as failed. Signed-off-by: Jonas Gorski Acked-by: Florian Fainelli Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 7b4ead78782c..e20a669c190c 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -205,13 +205,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; -- cgit v1.2.3 From ea01e8a4cdff627cbc417d1bf945bf34df9afa9d Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Tue, 17 Dec 2013 21:42:09 +0100 Subject: spi/bcm63xx: check return value of clk_prepare_enable Ensure we notice if the clock cannot be enabled for any reason and pass the error down. Signed-off-by: Jonas Gorski Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index e20a669c190c..db6a47d7b48c 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -399,7 +399,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 */ @@ -452,8 +455,11 @@ 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); -- cgit v1.2.3 From 1bae20285b6f8a692676a4489309bcad581c3f68 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Tue, 17 Dec 2013 21:42:10 +0100 Subject: spi/bcm63xx: fix pm sleep support Use the correct symbol to guard the callbacks and use appropriate defines for setting up the ops struct. Signed-off-by: Jonas Gorski Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index db6a47d7b48c..b440b0fef77b 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -438,7 +438,7 @@ static int bcm63xx_spi_remove(struct platform_device *pdev) 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,22 +465,17 @@ static int bcm63xx_spi_resume(struct device *dev) 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, -- cgit v1.2.3 From 5b3bb5963ff23a344062aba04937533a6f575761 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 19:12:03 +0900 Subject: spi: davinci: Use devm_*() functions Use devm_*() functions to make cleanup paths simpler. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-davinci.c | 41 +++++++++++------------------------------ 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index d3f638613b40..79d40c8b1cd0 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -853,7 +853,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 +894,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); @@ -1015,13 +1009,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 +1028,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 +1035,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; -- cgit v1.2.3 From 08bc0544a52e9c03457d00750ab2acd0c4f93da7 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 9 Dec 2013 19:25:00 +0900 Subject: spi: bcm2835: Use devm_request_irq() Use devm_request_irq() to make cleanup paths simpler. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 9025edd7dc45..8a89dd1f2654 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -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); -- cgit v1.2.3 From fc671a900b698e5aa35109100bb9a1598e914466 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 24 Dec 2013 10:49:30 +0100 Subject: spi: rspi: Use dev_get_platdata() instead of raw dev.platform_data access Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 58449ad4ad0d..e6aa42402850 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -904,7 +904,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; + 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; -- cgit v1.2.3 From c132f0949ab62ba95474f6eda44e9e1b5780b973 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 24 Dec 2013 10:49:31 +0100 Subject: spi: rspi: Remove casts Remove useless casts, and do not cast away const. Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index e6aa42402850..73f1a29b22c3 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -330,9 +330,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); @@ -358,12 +356,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) { @@ -399,8 +396,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 +437,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 +452,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)) { @@ -528,7 +527,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); @@ -575,7 +574,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) { @@ -802,7 +801,7 @@ 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; + struct rspi_data *rspi = _sr; unsigned long spsr; irqreturn_t ret = IRQ_NONE; unsigned char disable_irq = 0; -- cgit v1.2.3 From baf588f428e2b3bf91ac138e600c2e33c23cbfa3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 24 Dec 2013 10:49:32 +0100 Subject: spi: rspi: Make more pointers const Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 73f1a29b22c3..aea0c62b095d 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -170,34 +170,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 +209,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; @@ -243,7 +245,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; @@ -292,12 +295,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 +319,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); } @@ -507,7 +510,7 @@ 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; @@ -555,7 +558,7 @@ 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; @@ -703,7 +706,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; @@ -824,7 +827,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; @@ -903,7 +906,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 = dev_get_platdata(&pdev->dev); + 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; -- cgit v1.2.3 From 2aae80b27da6904939ed38959ee3d153f27ee7d1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 24 Dec 2013 10:49:33 +0100 Subject: spi: rspi: Use DUMMY_DATA macro instead of hardcoded value Make it more obvious that this value is dummy data. Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index aea0c62b095d..d7920d95a03c 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -149,6 +149,8 @@ #define SPBFCR_TXRST 0x80 /* qspi only */ #define SPBFCR_RXRST 0x40 /* qspi only */ +#define DUMMY_DATA 0x00 + struct rspi_data { void __iomem *addr; u32 max_speed_hz; @@ -541,7 +543,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, @@ -586,7 +588,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, -- cgit v1.2.3 From 97b95c117020461874de44ac612892f281ed3e31 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 24 Dec 2013 10:49:34 +0100 Subject: spi: rspi: Use u8 for 8-bit register values Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index d7920d95a03c..627126ae2571 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -160,7 +160,7 @@ struct rspi_data { wait_queue_head_t wait; spinlock_t lock; struct clk *clk; - unsigned char spsr; + u8 spsr; const struct spi_ops *ops; /* for dmaengine */ @@ -514,7 +514,7 @@ end_nomap: 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) @@ -562,7 +562,7 @@ static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg, 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) @@ -807,9 +807,9 @@ static void rspi_cleanup(struct spi_device *spi) static irqreturn_t rspi_irq(int irq, void *_sr) { struct rspi_data *rspi = _sr; - unsigned long spsr; + 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) -- cgit v1.2.3 From 0a47d3c40428fb8174ea36ede35267ddc7042f34 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 26 Dec 2013 09:00:15 +0200 Subject: spi: dw: drop unused struct dw_spi field Signed-off-by: Baruch Siach Signed-off-by: Mark Brown --- drivers/spi/spi-dw.c | 1 - drivers/spi/spi-dw.h | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index b897c4adb39d..abf4fd5a2a25 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -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; diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h index 9c57c078031e..5a5cd02ddb13 100644 --- a/drivers/spi/spi-dw.h +++ b/drivers/spi/spi-dw.h @@ -135,7 +135,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); -- cgit v1.2.3 From 04f421e7b0b10de3fae543dac4d324b449a1db6b Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Mon, 30 Dec 2013 20:30:44 +0200 Subject: spi: dw: use managed resources Migrate mmio code and core driver to managed resources to reduce boilerplate error handling code. Also, handle clk_enable() failure while at it, and drop unused dw_spi iolen field. Signed-off-by: Baruch Siach Signed-off-by: Mark Brown --- drivers/spi/spi-dw-mmio.c | 70 ++++++++++++++--------------------------------- drivers/spi/spi-dw-pci.c | 40 +++++++-------------------- drivers/spi/spi-dw.c | 20 ++++---------- drivers/spi/spi-dw.h | 4 +-- 4 files changed, 37 insertions(+), 97 deletions(-) diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 168c620947f4..569adf877b16 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -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 = iore