From 2418991efb7b1f9fc574771450ac17689682b3f6 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Sun, 26 Jan 2014 10:14:32 +0200 Subject: spi: dw-mmio: allow multiple instances Use the platform_device id to uniquely identify each SPI master instance. Cc: Jean-Hugues Deschenes Signed-off-by: Baruch Siach Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 9af56cd..1492f5e 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -66,7 +66,7 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) if (ret) return ret; - dws->bus_num = 0; + dws->bus_num = pdev->id; dws->num_cs = 4; dws->max_freq = clk_get_rate(dwsmmio->clk); -- cgit v0.10.2 From 794f61a30e115f44821d8c3cf812a969be48a8a5 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Fri, 31 Jan 2014 12:07:48 +0200 Subject: spi: dw-mmio: remove HAVE_CLK build dependecy Since 93abe8e4 (clk: add non CONFIG_HAVE_CLK routines) code using clk.h like this platform driver needs not depend on HAVE_CLK. Signed-off-by: Baruch Siach Signed-off-by: Mark Brown diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index ba9310b..b1fc8eb 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -546,7 +546,7 @@ config SPI_DW_MID_DMA config SPI_DW_MMIO tristate "Memory-mapped io interface driver for DW SPI core" - depends on SPI_DESIGNWARE && HAVE_CLK + depends on SPI_DESIGNWARE # # There are lots of SPI device types, with sensors and memory -- cgit v0.10.2 From e1bde3b11fedace5042f0232339da90bc85666af Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Tue, 4 Feb 2014 15:58:09 +0900 Subject: spi: fix pointer-integer size mismatch warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the pointer-integer size mismatch warning below: drivers/spi/spi-gpio.c: In function ‘spi_gpio_setup’: drivers/spi/spi-gpio.c:252:8: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] cs = (unsigned int) spi->controller_data; ^ Signed-off-by: SeongJae Park Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 7beeb29..dd4fe50 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -250,7 +250,7 @@ static int spi_gpio_setup(struct spi_device *spi) /* * ... otherwise, take it from spi->controller_data */ - cs = (unsigned int) spi->controller_data; + cs = (unsigned int)(uintptr_t) spi->controller_data; } if (!spi->controller_state) { -- cgit v0.10.2 From 4302a59629f7a0bd70fd1605d2b558597517372a Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Fri, 31 Jan 2014 13:44:59 +0100 Subject: spi: fsl: Fix problem with multi message transfers When used via spidev with more than one messages to tranfer via SPI_IOC_MESSAGE the current implementation would return with -EINVAL, since bits_per_word and speed_hz are set in all transfer structs. And in the 2nd loop status will stay at -EINVAL as its not overwritten again via fsl_spi_setup_transfer(). This patch changes this behavious by first checking if one of the messages uses different settings. If this is the case the function will return with -EINVAL. If not, the messages are transferred correctly. Signed-off-by: Stefan Roese Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 119f7af..4dcb292 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -362,18 +362,28 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t, static void fsl_spi_do_one_msg(struct spi_message *m) { struct spi_device *spi = m->spi; - struct spi_transfer *t; + struct spi_transfer *t, *first; unsigned int cs_change; const int nsecs = 50; int status; - cs_change = 1; - status = 0; + /* Don't allow changes if CS is active */ + first = list_first_entry(&m->transfers, struct spi_transfer, + transfer_list); list_for_each_entry(t, &m->transfers, transfer_list) { - if (t->bits_per_word || t->speed_hz) { - /* Don't allow changes if CS is active */ + if ((first->bits_per_word != t->bits_per_word) || + (first->speed_hz != t->speed_hz)) { status = -EINVAL; + dev_err(&spi->dev, + "bits_per_word/speed_hz should be same for the same SPI transfer\n"); + return; + } + } + cs_change = 1; + status = -EINVAL; + list_for_each_entry(t, &m->transfers, transfer_list) { + if (t->bits_per_word || t->speed_hz) { if (cs_change) status = fsl_spi_setup_transfer(spi, t); if (status < 0) -- cgit v0.10.2 From 56fc0b42dc5aeb4ee2b10ab5785e28c87c83280a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 8 Feb 2014 23:52:26 +0800 Subject: spi: ep93xx: Convert to let spi core handle checking transfer speed By setting master->max_speed_hz and master->min_speed_hz, spi core will handle checking transfer speed. So we can remove the same checking in this driver. Signed-off-by: Axel Lin Acked-by: Mika Westerberg Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 1bfaed6..2f675d3 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -73,8 +73,6 @@ * @clk: clock for the controller * @regs_base: pointer to ioremap()'d registers * @sspdr_phys: physical address of the SSPDR register - * @min_rate: minimum clock rate (in Hz) supported by the controller - * @max_rate: maximum clock rate (in Hz) supported by the controller * @wait: wait here until given transfer is completed * @current_msg: message that is currently processed (or %NULL if none) * @tx: current byte in transfer to transmit @@ -95,8 +93,6 @@ struct ep93xx_spi { struct clk *clk; void __iomem *regs_base; unsigned long sspdr_phys; - unsigned long min_rate; - unsigned long max_rate; struct completion wait; struct spi_message *current_msg; size_t tx; @@ -199,9 +195,9 @@ static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi) * @div_scr: pointer to return the scr divider */ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, - unsigned long rate, - u8 *div_cpsr, u8 *div_scr) + u32 rate, u8 *div_cpsr, u8 *div_scr) { + struct spi_master *master = platform_get_drvdata(espi->pdev); unsigned long spi_clk_rate = clk_get_rate(espi->clk); int cpsr, scr; @@ -210,7 +206,7 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, * controller. Note that minimum value is already checked in * ep93xx_spi_transfer_one_message(). */ - rate = clamp(rate, espi->min_rate, espi->max_rate); + rate = clamp(rate, master->min_speed_hz, master->max_speed_hz); /* * Calculate divisors so that we can get speed according the @@ -735,13 +731,6 @@ static int ep93xx_spi_transfer_one_message(struct spi_master *master, struct spi_message *msg) { struct ep93xx_spi *espi = spi_master_get_devdata(master); - struct spi_transfer *t; - - /* first validate each transfer */ - list_for_each_entry(t, &msg->transfers, transfer_list) { - if (t->speed_hz < espi->min_rate) - return -EINVAL; - } msg->state = NULL; msg->status = 0; @@ -917,8 +906,8 @@ static int ep93xx_spi_probe(struct platform_device *pdev) * Calculate maximum and minimum supported clock rates * for the controller. */ - espi->max_rate = clk_get_rate(espi->clk) / 2; - espi->min_rate = clk_get_rate(espi->clk) / (254 * 256); + master->max_speed_hz = clk_get_rate(espi->clk) / 2; + master->min_speed_hz = clk_get_rate(espi->clk) / (254 * 256); espi->pdev = pdev; espi->sspdr_phys = res->start + SSPDR; -- cgit v0.10.2 From 1acbdeb92c87fc18eade0815dedc257fe45b88b7 Mon Sep 17 00:00:00 2001 From: Chao Fu Date: Wed, 12 Feb 2014 15:29:05 +0800 Subject: spi/fsl-dspi: Convert to use regmap and add big-endian support Freescale DSPI module will have two endianess in different platform, but ARM is little endian. So when DSPI in big endian, core in little endian, readl and writel can not adjust R/W register in this condition. This patch will remove general readl/writel, and import regmap mechanism. Data endian will be transfered in regmap APIs. Documents: dspi add bool "big-endian" in dts node if DSPI module work in big endian. Signed-off-by: Chao Fu Reviewed-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt index a1fb303..5376de4 100644 --- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt +++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt @@ -10,6 +10,7 @@ Required properties: - pinctrl-names: must contain a "default" entry. - spi-num-chipselects : the number of the chipselect signals. - bus-num : the slave chip chipselect signal number. +- big-endian : if DSPI modudle is big endian, the bool will be set in node. Example: dspi0@4002c000 { @@ -24,6 +25,7 @@ dspi0@4002c000 { bus-num = <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_dspi0_1>; + big-endian; status = "okay"; sflash: at26df081a@0 { diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index ba9310b..00e9510 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -270,6 +270,7 @@ config SPI_FSL_SPI config SPI_FSL_DSPI tristate "Freescale DSPI controller" select SPI_BITBANG + select REGMAP_MMIO depends on SOC_VF610 || COMPILE_TEST help This enables support for the Freescale DSPI controller in master diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index ec79f72..fb16575 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -108,7 +109,7 @@ struct fsl_dspi { struct spi_bitbang bitbang; struct platform_device *pdev; - void __iomem *base; + struct regmap *regmap; int irq; struct clk *clk; @@ -129,18 +130,11 @@ struct fsl_dspi { static inline int is_double_byte_mode(struct fsl_dspi *dspi) { - return ((readl(dspi->base + SPI_CTAR(dspi->cs)) & SPI_FRAME_BITS_MASK) - == SPI_FRAME_BITS(8)) ? 0 : 1; -} + unsigned int val; -static void set_bit_mode(struct fsl_dspi *dspi, unsigned char bits) -{ - u32 temp; + regmap_read(dspi->regmap, SPI_CTAR(dspi->cs), &val); - temp = readl(dspi->base + SPI_CTAR(dspi->cs)); - temp &= ~SPI_FRAME_BITS_MASK; - temp |= SPI_FRAME_BITS(bits); - writel(temp, dspi->base + SPI_CTAR(dspi->cs)); + return ((val & SPI_FRAME_BITS_MASK) == SPI_FRAME_BITS(8)) ? 0 : 1; } static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, @@ -188,7 +182,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi) */ if (tx_word && (dspi->len == 1)) { dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM; - set_bit_mode(dspi, 8); + regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), + SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8)); tx_word = 0; } @@ -238,7 +233,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi) dspi_pushr |= SPI_PUSHR_CTCNT; /* clear counter */ } - writel(dspi_pushr, dspi->base + SPI_PUSHR); + regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr); + tx_count++; } @@ -253,17 +249,23 @@ static int dspi_transfer_read(struct fsl_dspi *dspi) while ((dspi->rx < dspi->rx_end) && (rx_count < DSPI_FIFO_SIZE)) { if (rx_word) { + unsigned int val; + if ((dspi->rx_end - dspi->rx) == 1) break; - d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR)); + regmap_read(dspi->regmap, SPI_POPR, &val); + d = SPI_POPR_RXDATA(val); if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) *(u16 *)dspi->rx = d; dspi->rx += 2; } else { - d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR)); + unsigned int val; + + regmap_read(dspi->regmap, SPI_POPR, &val); + d = SPI_POPR_RXDATA(val); if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) *(u8 *)dspi->rx = d; dspi->rx++; @@ -295,13 +297,13 @@ static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t) if (!dspi->tx) dspi->dataflags |= TRAN_STATE_TX_VOID; - writel(dspi->cur_chip->mcr_val, dspi->base + SPI_MCR); - writel(dspi->cur_chip->ctar_val, dspi->base + SPI_CTAR(dspi->cs)); - writel(SPI_RSER_EOQFE, dspi->base + SPI_RSER); + regmap_write(dspi->regmap, SPI_MCR, dspi->cur_chip->mcr_val); + regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), dspi->cur_chip->ctar_val); + regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE); if (t->speed_hz) - writel(dspi->cur_chip->ctar_val, - dspi->base + SPI_CTAR(dspi->cs)); + regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), + dspi->cur_chip->ctar_val); dspi_transfer_write(dspi); @@ -315,7 +317,9 @@ static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t) static void dspi_chipselect(struct spi_device *spi, int value) { struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); - u32 pushr = readl(dspi->base + SPI_PUSHR); + unsigned int pushr; + + regmap_read(dspi->regmap, SPI_PUSHR, &pushr); switch (value) { case BITBANG_CS_ACTIVE: @@ -326,7 +330,7 @@ static void dspi_chipselect(struct spi_device *spi, int value) break; } - writel(pushr, dspi->base + SPI_PUSHR); + regmap_write(dspi->regmap, SPI_PUSHR, pushr); } static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) @@ -382,13 +386,15 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) { struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; - writel(SPI_SR_EOQF, dspi->base + SPI_SR); + regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF); dspi_transfer_read(dspi); if (!dspi->len) { if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) - set_bit_mode(dspi, 16); + regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), + SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(16)); + dspi->waitflags = 1; wake_up_interruptible(&dspi->waitq); } else { @@ -435,12 +441,20 @@ static const struct dev_pm_ops dspi_pm = { SET_SYSTEM_SLEEP_PM_OPS(dspi_suspend, dspi_resume) }; +static struct regmap_config dspi_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x88, +}; + static int dspi_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct spi_master *master; struct fsl_dspi *dspi; struct resource *res; + void __iomem *base; int ret = 0, cs_num, bus_num; master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); @@ -475,12 +489,24 @@ static int dspi_probe(struct platform_device *pdev) master->bus_num = bus_num; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dspi->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(dspi->base)) { - ret = PTR_ERR(dspi->base); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) { + ret = PTR_ERR(base); goto out_master_put; } + dspi_regmap_config.lock_arg = dspi; + dspi_regmap_config.val_format_endian = + of_property_read_bool(np, "big-endian") + ? REGMAP_ENDIAN_BIG : REGMAP_ENDIAN_DEFAULT; + dspi->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "dspi", base, + &dspi_regmap_config); + if (IS_ERR(dspi->regmap)) { + dev_err(&pdev->dev, "failed to init regmap: %ld\n", + PTR_ERR(dspi->regmap)); + return PTR_ERR(dspi->regmap); + } + dspi->irq = platform_get_irq(pdev, 0); if (dspi->irq < 0) { dev_err(&pdev->dev, "can't get platform irq\n"); -- cgit v0.10.2 From 88386e858bbb21eb05c15c040dbb3e6ad1cb3568 Mon Sep 17 00:00:00 2001 From: Chao Fu Date: Wed, 12 Feb 2014 15:29:06 +0800 Subject: spi/fsl-dspi: Remove some coding sytle not in standard Remove some coding sytle not in standard in former code. Signed-off-by: Chao Fu Reviewed-by: Xiubo Li Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index fb16575..42ede0d 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -111,9 +111,9 @@ struct fsl_dspi { struct regmap *regmap; int irq; - struct clk *clk; + struct clk *clk; - struct spi_transfer *cur_transfer; + struct spi_transfer *cur_transfer; struct chip_data *cur_chip; size_t len; void *tx; @@ -124,8 +124,8 @@ struct fsl_dspi { u8 cs; u16 void_write_data; - wait_queue_head_t waitq; - u32 waitflags; + wait_queue_head_t waitq; + u32 waitflags; }; static inline int is_double_byte_mode(struct fsl_dspi *dspi) -- cgit v0.10.2 From 23e2c2aa45a213ea25636ac5add66c2507e7361b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 12 Feb 2014 22:13:27 +0800 Subject: spi: Use list_last_entry at appropriate places Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index bf98d63..390da9b 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -276,8 +276,7 @@ static void giveback(struct dw_spi *dws) queue_work(dws->workqueue, &dws->pump_messages); spin_unlock_irqrestore(&dws->lock, flags); - last_transfer = list_entry(msg->transfers.prev, - struct spi_transfer, + last_transfer = list_last_entry(&msg->transfers, struct spi_transfer, transfer_list); if (!last_transfer->cs_change && dws->cs_control) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 2789b45..3c5b905 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -459,9 +459,8 @@ static void giveback(struct pl022 *pl022) struct spi_transfer *last_transfer; pl022->next_msg_cs_active = false; - last_transfer = list_entry(pl022->cur_msg->transfers.prev, - struct spi_transfer, - transfer_list); + last_transfer = list_last_entry(&pl022->cur_msg->transfers, + struct spi_transfer, transfer_list); /* Delay if requested before any change in chip select */ if (last_transfer->delay_usecs) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index c702fc5..41185d0 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -362,8 +362,7 @@ static void giveback(struct driver_data *drv_data) drv_data->cur_msg = NULL; drv_data->cur_transfer = NULL; - last_transfer = list_entry(msg->transfers.prev, - struct spi_transfer, + last_transfer = list_last_entry(&msg->transfers, struct spi_transfer, transfer_list); /* Delay if requested before any change in chip select */ -- cgit v0.10.2 From f734394d861fe71eafa28d6c28199d9847c5a319 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 13 Feb 2014 19:05:38 +0800 Subject: spi: fsl-spi: Convert to let spi core validate xfer->bits_per_word Set bits_per_word_mask so spi core will reject transfers that attempt to use an unsupported bits_per_word value. fsl_spi_grlib_probe() may update mpc8xxx_spi->max_bits_per_word setting. So set master->bits_per_word_mask after fsl_spi_grlib_probe(). Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 4dcb292..f35488e 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -239,12 +239,6 @@ static int fsl_spi_setup_transfer(struct spi_device *spi, if (!bits_per_word) bits_per_word = spi->bits_per_word; - /* Make sure its a bit width we support [4..16, 32] */ - if ((bits_per_word < 4) - || ((bits_per_word > 16) && (bits_per_word != 32)) - || (bits_per_word > mpc8xxx_spi->max_bits_per_word)) - return -EINVAL; - if (!hz) hz = spi->max_speed_hz; @@ -651,6 +645,10 @@ static struct spi_master * fsl_spi_probe(struct device *dev, if (mpc8xxx_spi->type == TYPE_GRLIB) fsl_spi_grlib_probe(dev); + master->bits_per_word_mask = + (SPI_BPW_RANGE_MASK(4, 16) | SPI_BPW_MASK(32)) & + SPI_BPW_RANGE_MASK(1, mpc8xxx_spi->max_bits_per_word); + if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) mpc8xxx_spi->set_shifts = fsl_spi_qe_cpu_set_shifts; -- cgit v0.10.2 From 765ee709eb40abf0c43c6d864ac6f01677b7fd5a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 20 Feb 2014 21:37:56 +0800 Subject: spi: dw: Convert to let spi core validate transfer speed Set master->max_speed_hz then spi core will handle checking transfer speed. So we can remove the same checking in this driver. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index bf98d63..9e4a0aa 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -439,12 +439,6 @@ static void pump_transfers(unsigned long data) if (transfer->speed_hz != speed) { speed = transfer->speed_hz; - if (speed > dws->max_freq) { - printk(KERN_ERR "MRST SPI0: unsupported" - "freq: %dHz\n", speed); - message->status = -EIO; - goto early_exit; - } /* clk_div doesn't support odd number */ clk_div = dws->max_freq / speed; @@ -809,6 +803,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) master->cleanup = dw_spi_cleanup; master->setup = dw_spi_setup; master->transfer = dw_spi_transfer; + master->max_speed_hz = dws->max_freq; /* Basic HW init */ spi_hw_init(dws); -- cgit v0.10.2 From ba811addff3d29d1ea9861dbfc06e8ef80714f94 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Wed, 26 Feb 2014 10:30:14 +0900 Subject: spi: fsl-dspi: Use SIMPLE_DEV_PM_OPS macro Use SIMPLE_DEV_PM_OPS macro in order to make the code simpler. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 42ede0d..7f0dddb 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -437,9 +437,7 @@ static int dspi_resume(struct device *dev) } #endif /* CONFIG_PM_SLEEP */ -static const struct dev_pm_ops dspi_pm = { - SET_SYSTEM_SLEEP_PM_OPS(dspi_suspend, dspi_resume) -}; +static SIMPLE_DEV_PM_OPS(dspi_pm, dspi_suspend, dspi_resume); static struct regmap_config dspi_regmap_config = { .reg_bits = 32, -- cgit v0.10.2 From f9f4cbde587335515acaaef9e23028fc0a616292 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 12 Mar 2014 18:35:23 +0800 Subject: spi: efm32: Clean up non-DT paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a DT-only driver, so remove all non-DT paths. of_gpio_named_count() may fail, thus also add checking it's return value. efm32_spi_probe_dt() never fails, make it return void. Signed-off-by: Axel Lin Acked-by: Uwe Kleine-König Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c index 7199d2f..0512fed 100644 --- a/drivers/spi/spi-efm32.c +++ b/drivers/spi/spi-efm32.c @@ -287,16 +287,13 @@ static u32 efm32_spi_get_configured_location(struct efm32_spi_ddata *ddata) return (reg & REG_ROUTE_LOCATION__MASK) >> __ffs(REG_ROUTE_LOCATION__MASK); } -static int efm32_spi_probe_dt(struct platform_device *pdev, +static void efm32_spi_probe_dt(struct platform_device *pdev, struct spi_master *master, struct efm32_spi_ddata *ddata) { struct device_node *np = pdev->dev.of_node; u32 location; int ret; - if (!np) - return 1; - ret = of_property_read_u32(np, "location", &location); if (!ret) { dev_dbg(&pdev->dev, "using location %u\n", location); @@ -308,7 +305,6 @@ static int efm32_spi_probe_dt(struct platform_device *pdev, } ddata->pdata.location = location; - return 0; } static int efm32_spi_probe(struct platform_device *pdev) @@ -318,9 +314,14 @@ static int efm32_spi_probe(struct platform_device *pdev) int ret; struct spi_master *master; struct device_node *np = pdev->dev.of_node; - unsigned int num_cs, i; + int num_cs, i; + + if (!np) + return -EINVAL; num_cs = of_gpio_named_count(np, "cs-gpios"); + if (num_cs < 0) + return num_cs; master = spi_alloc_master(&pdev->dev, sizeof(*ddata) + num_cs * sizeof(unsigned)); @@ -411,23 +412,7 @@ static int efm32_spi_probe(struct platform_device *pdev) goto err; } - ret = efm32_spi_probe_dt(pdev, master, ddata); - if (ret > 0) { - /* not created by device tree */ - const struct efm32_spi_pdata *pdata = - dev_get_platdata(&pdev->dev); - - if (pdata) - ddata->pdata = *pdata; - else - ddata->pdata.location = - efm32_spi_get_configured_location(ddata); - - master->bus_num = pdev->id; - - } else if (ret < 0) { - goto err_disable_clk; - } + efm32_spi_probe_dt(pdev, master, ddata); efm32_spi_write32(ddata, 0, REG_IEN); efm32_spi_write32(ddata, REG_ROUTE_TXPEN | REG_ROUTE_RXPEN | -- cgit v0.10.2 From f2bb31057a42cb439161066db615ca73e4438e30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 14 Mar 2014 21:34:22 +0100 Subject: spi: efm32: properly namespace location property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While reviewing an i2c driver for efm32 that needs a similar property Wolfram Sang pointed out that "location" is a too generic name for something that is efm32 specific. So add an appropriate namespace and fall back to the generic name in case of failure. Signed-off-by: Uwe Kleine-König Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/spi/efm32-spi.txt b/Documentation/devicetree/bindings/spi/efm32-spi.txt index a590ca5..25c02ba 100644 --- a/Documentation/devicetree/bindings/spi/efm32-spi.txt +++ b/Documentation/devicetree/bindings/spi/efm32-spi.txt @@ -8,7 +8,7 @@ Required properties: - interrupts: pair specifying rx and tx irq - clocks: phandle to the spi clock - cs-gpios: see spi-bus.txt -- location: Value to write to the ROUTE register's LOCATION bitfield to configure the pinmux for the device, see datasheet for values. +- efm32,location: Value to write to the ROUTE register's LOCATION bitfield to configure the pinmux for the device, see datasheet for values. Example: @@ -20,7 +20,7 @@ spi1: spi@0x4000c400 { /* USART1 */ interrupts = <15 16>; clocks = <&cmu 20>; cs-gpios = <&gpio 51 1>; // D3 - location = <1>; + efm32,location = <1>; status = "ok"; ks8851@0 { diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c index 0512fed..fdb6fce 100644 --- a/drivers/spi/spi-efm32.c +++ b/drivers/spi/spi-efm32.c @@ -294,7 +294,10 @@ static void efm32_spi_probe_dt(struct platform_device *pdev, u32 location; int ret; - ret = of_property_read_u32(np, "location", &location); + ret = of_property_read_u32(np, "efm32,location", &location); + if (ret) + /* fall back to old and (wrongly) generic property "location" */ + ret = of_property_read_u32(np, "location", &location); if (!ret) { dev_dbg(&pdev->dev, "using location %u\n", location); } else { -- cgit v0.10.2 From 7282326b722995c3fabd4dcd9244182b37500252 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 20 Mar 2014 17:20:17 +0800 Subject: spi: fsl-lib: Fix memory leak of pinfo of_mpc8xxx_spi_probe() allocates memory for pinfo but the memory is not freed anywhere. of_mpc8xxx_spi_probe() is called in .probe() and pinfo should be freed in .remove(), so convert kzalloc to devm_kzalloc to fix the memory leak. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-fsl-lib.c b/drivers/spi/spi-fsl-lib.c index 0b75f26..e5d45fc 100644 --- a/drivers/spi/spi-fsl-lib.c +++ b/drivers/spi/spi-fsl-lib.c @@ -200,7 +200,7 @@ int of_mpc8xxx_spi_probe(struct platform_device *ofdev) const void *prop; int ret = -ENOMEM; - pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL); + pinfo = devm_kzalloc(&ofdev->dev, sizeof(*pinfo), GFP_KERNEL); if (!pinfo) return -ENOMEM; @@ -215,15 +215,13 @@ int of_mpc8xxx_spi_probe(struct platform_device *ofdev) pdata->sysclk = get_brgfreq(); if (pdata->sysclk == -1) { pdata->sysclk = fsl_get_sys_freq(); - if (pdata->sysclk == -1) { - ret = -ENODEV; - goto err; - } + if (pdata->sysclk == -1) + return -ENODEV; } #else ret = of_property_read_u32(np, "clock-frequency", &pdata->sysclk); if (ret) - goto err; + return ret; #endif prop = of_get_property(np, "mode", NULL); @@ -237,8 +235,4 @@ int of_mpc8xxx_spi_probe(struct platform_device *ofdev) pdata->flags = SPI_CPM_MODE | SPI_CPM1; return 0; - -err: - kfree(pinfo); - return ret; } -- cgit v0.10.2 From f0a71337be7f19cc929aabfffc3ecd4c056df03a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 21 Mar 2014 22:59:58 +0800 Subject: spi: fsl-espi: Remove unused bits_per_word variable in fsl_espi_bufs Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 428dc7a..6fb2b75 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -219,13 +219,8 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base; unsigned int len = t->len; - u8 bits_per_word; int ret; - bits_per_word = spi->bits_per_word; - if (t->bits_per_word) - bits_per_word = t->bits_per_word; - mpc8xxx_spi->len = t->len; len = roundup(len, 4) / 4; -- cgit v0.10.2 From 12f6dd860cf8bf036c0bec38c00a53da71bcd43a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 25 Mar 2014 15:51:50 +0100 Subject: spi: efm32: use $vendor,$device scheme for compatible string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wolfram Sang pointed out that "efm32,$device" is non-standard. So use the common scheme and prefix device with "efm32-". The old compatible string is left in place until arch/arm/boot/dts/efm32* is fixed. Signed-off-by: Uwe Kleine-König Acked-by: Wolfram Sang Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/Documentation/devicetree/bindings/spi/efm32-spi.txt b/Documentation/devicetree/bindings/spi/efm32-spi.txt index 25c02ba..8f081c9 100644 --- a/Documentation/devicetree/bindings/spi/efm32-spi.txt +++ b/Documentation/devicetree/bindings/spi/efm32-spi.txt @@ -3,7 +3,7 @@ Required properties: - #address-cells: see spi-bus.txt - #size-cells: see spi-bus.txt -- compatible: should be "efm32,spi" +- compatible: should be "energymicro,efm32-spi" - reg: Offset and length of the register set for the controller - interrupts: pair specifying rx and tx irq - clocks: phandle to the spi clock @@ -15,7 +15,7 @@ Example: spi1: spi@0x4000c400 { /* USART1 */ #address-cells = <1>; #size-cells = <0>; - compatible = "efm32,spi"; + compatible = "energymicro,efm32-spi"; reg = <0x4000c400 0x400>; interrupts = <15 16>; clocks = <&cmu 20>; diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c index fdb6fce..4a5a359 100644 --- a/drivers/spi/spi-efm32.c +++ b/drivers/spi/spi-efm32.c @@ -471,6 +471,9 @@ static int efm32_spi_remove(struct platform_device *pdev) static const struct of_device_id efm32_spi_dt_ids[] = { { + .compatible = "energymicro,efm32-spi", + }, { + /* doesn't follow the "vendor,device" scheme, don't use */ .compatible = "efm32,spi", }, { /* sentinel */ -- cgit v0.10.2 From 0e0cd9ea8961b82947a40471080e7968b634820e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 25 Mar 2014 09:19:05 +0800 Subject: spi: fsl-dspi: Fix memory leak The memory allocated for chip is not freed anywhere. Convert to use devm_kzalloc to fix the memory leak. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 7f0dddb..c5ecfc1 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -342,7 +342,8 @@ static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) /* Only alloc on first setup */ chip = spi_get_ctldata(spi); if (chip == NULL) { - chip = kcalloc(1, sizeof(struct chip_data), GFP_KERNEL); + chip = devm_kzalloc(&spi->dev, sizeof(struct chip_data), + GFP_KERNEL); if (!chip) return -ENOMEM; } @@ -353,7 +354,6 @@ static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) fmsz = spi->bits_per_word - 1; } else { pr_err("Invalid wordsize\n"); - kfree(chip); return -ENODEV; } -- cgit v0.10.2 From c63f5da00845143de621e991ea186be0829647ee Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 25 Mar 2014 12:44:13 +0800 Subject: spi: dw: Don't call kfree for memory allocated by devm_kzalloc With devm_kzalloc, the memory is automatically freed when spi_device detach from the bus. Fixes: commit 43f627ac9de42 (spi: dw: fix memory leak on error path) Signed-off-by: Axel Lin Acked-by: Baruch Siach Signed-off-by: Mark Brown Cc: stabe@vger.kernel.org diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 9e4a0aa..79fd1fa 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -665,12 +665,6 @@ static int dw_spi_setup(struct spi_device *spi) return 0; } -static void dw_spi_cleanup(struct spi_device *spi) -{ - struct chip_data *chip = spi_get_ctldata(spi); - kfree(chip); -} - static int init_queue(struct dw_spi *dws) { INIT_LIST_HEAD(&dws->queue); @@ -800,7 +794,6 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); master->bus_num = dws->bus_num; master->num_chipselect = dws->num_cs; - master->cleanup = dw_spi_cleanup; master->setup = dw_spi_setup; master->transfer = dw_spi_transfer; master->max_speed_hz = dws->max_freq; -- cgit v0.10.2