diff options
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-pxa2xx.c | 4 | ||||
-rw-r--r-- | drivers/spi/spi-s3c64xx.c | 18 | ||||
-rw-r--r-- | drivers/spi/spi-sh-msiof.c | 116 | ||||
-rw-r--r-- | drivers/spi/spi-sirf.c | 4 | ||||
-rw-r--r-- | drivers/spi/spi-sun6i.c | 2 |
5 files changed, 103 insertions, 41 deletions
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 4cb515a3104c..b0822d1dba29 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1237,7 +1237,7 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip, * different chip_info, release previously requested GPIO */ if (chip->gpiod_cs) { - gpio_free(desc_to_gpio(chip->gpiod_cs)); + gpiod_put(chip->gpiod_cs); chip->gpiod_cs = NULL; } @@ -1417,7 +1417,7 @@ static void cleanup(struct spi_device *spi) if (drv_data->ssp_type != CE4100_SSP && !drv_data->cs_gpiods && chip->gpiod_cs) - gpio_free(desc_to_gpio(chip->gpiod_cs)); + gpiod_put(chip->gpiod_cs); kfree(chip); } diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index de7df20f8712..baa3a9fa2638 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1,17 +1,7 @@ -/* - * Copyright (C) 2009 Samsung Electronics Ltd. - * Jaswinder Singh <jassi.brar@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// Copyright (c) 2009 Samsung Electronics Co., Ltd. +// Jaswinder Singh <jassi.brar@samsung.com> #include <linux/init.h> #include <linux/module.h> diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 06bc4b170c47..c5dcfb434a49 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -19,6 +19,7 @@ #include <linux/dmaengine.h> #include <linux/err.h> #include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/kernel.h> @@ -55,9 +56,14 @@ struct sh_msiof_spi_priv { void *rx_dma_page; dma_addr_t tx_dma_addr; dma_addr_t rx_dma_addr; + unsigned short unused_ss; + bool native_cs_inited; + bool native_cs_high; bool slave_aborted; }; +#define MAX_SS 3 /* Maximum number of native chip selects */ + #define TMDR1 0x00 /* Transmit Mode Register 1 */ #define TMDR2 0x04 /* Transmit Mode Register 2 */ #define TMDR3 0x08 /* Transmit Mode Register 3 */ @@ -91,6 +97,8 @@ struct sh_msiof_spi_priv { #define MDR1_XXSTP 0x00000001 /* Transmission/Reception Stop on FIFO */ /* TMDR1 */ #define TMDR1_PCON 0x40000000 /* Transfer Signal Connection */ +#define TMDR1_SYNCCH_MASK 0xc000000 /* Synchronization Signal Channel Select */ +#define TMDR1_SYNCCH_SHIFT 26 /* 0=MSIOF_SYNC, 1=MSIOF_SS1, 2=MSIOF_SS2 */ /* TMDR2 and RMDR2 */ #define MDR2_BITLEN1(i) (((i) - 1) << 24) /* Data Size (8-32 bits) */ @@ -324,7 +332,7 @@ static u32 sh_msiof_spi_get_dtdl_and_syncdl(struct sh_msiof_spi_priv *p) return val; } -static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, +static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, u32 ss, u32 cpol, u32 cpha, u32 tx_hi_z, u32 lsb_first, u32 cs_high) { @@ -342,10 +350,13 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, tmp |= !cs_high << MDR1_SYNCAC_SHIFT; tmp |= lsb_first << MDR1_BITLSB_SHIFT; tmp |= sh_msiof_spi_get_dtdl_and_syncdl(p); - if (spi_controller_is_slave(p->master)) + if (spi_controller_is_slave(p->master)) { sh_msiof_write(p, TMDR1, tmp | TMDR1_PCON); - else - sh_msiof_write(p, TMDR1, tmp | MDR1_TRMD | TMDR1_PCON); + } else { + sh_msiof_write(p, TMDR1, + tmp | MDR1_TRMD | TMDR1_PCON | + (ss < MAX_SS ? ss : 0) << TMDR1_SYNCCH_SHIFT); + } if (p->master->flags & SPI_MASTER_MUST_TX) { /* These bits are reserved if RX needs TX */ tmp &= ~0x0000ffff; @@ -528,8 +539,7 @@ static int sh_msiof_spi_setup(struct spi_device *spi) { struct device_node *np = spi->master->dev.of_node; struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master); - - pm_runtime_get_sync(&p->pdev->dev); + u32 clr, set, tmp; if (!np) { /* @@ -539,19 +549,31 @@ static int sh_msiof_spi_setup(struct spi_device *spi) spi->cs_gpio = (uintptr_t)spi->controller_data; } - /* Configure pins before deasserting CS */ - sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL), - !!(spi->mode & SPI_CPHA), - !!(spi->mode & SPI_3WIRE), - !!(spi->mode & SPI_LSB_FIRST), - !!(spi->mode & SPI_CS_HIGH)); + if (gpio_is_valid(spi->cs_gpio)) { + gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); + return 0; + } - if (spi->cs_gpio >= 0) - gpio_set_value(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); + if (spi_controller_is_slave(p->master)) + return 0; + if (p->native_cs_inited && + (p->native_cs_high == !!(spi->mode & SPI_CS_HIGH))) + return 0; + /* Configure native chip select mode/polarity early */ + clr = MDR1_SYNCMD_MASK; + set = MDR1_TRMD | TMDR1_PCON | MDR1_SYNCMD_SPI; + if (spi->mode & SPI_CS_HIGH) + clr |= BIT(MDR1_SYNCAC_SHIFT); + else + set |= BIT(MDR1_SYNCAC_SHIFT); + pm_runtime_get_sync(&p->pdev->dev); + tmp = sh_msiof_read(p, TMDR1) & ~clr; + sh_msiof_write(p, TMDR1, tmp | set); pm_runtime_put(&p->pdev->dev); - + p->native_cs_high = spi->mode & SPI_CS_HIGH; + p->native_cs_inited = true; return 0; } @@ -560,13 +582,20 @@ static int sh_msiof_prepare_message(struct spi_master *master, { struct sh_msiof_spi_priv *p = spi_master_get_devdata(master); const struct spi_device *spi = msg->spi; + u32 ss, cs_high; /* Configure pins before asserting CS */ - sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL), + if (gpio_is_valid(spi->cs_gpio)) { + ss = p->unused_ss; + cs_high = p->native_cs_high; + } else { + ss = spi->chip_select; + cs_high = !!(spi->mode & SPI_CS_HIGH); + } + sh_msiof_spi_set_pin_regs(p, ss, !!(spi->mode & SPI_CPOL), !!(spi->mode & SPI_CPHA), !!(spi->mode & SPI_3WIRE), - !!(spi->mode & SPI_LSB_FIRST), - !!(spi->mode & SPI_CS_HIGH)); + !!(spi->mode & SPI_LSB_FIRST), cs_high); return 0; } @@ -922,9 +951,8 @@ static int sh_msiof_transfer_one(struct spi_master *master, ret = sh_msiof_dma_once(p, tx_buf, rx_buf, l); if (ret == -EAGAIN) { - pr_warn_once("%s %s: DMA not available, falling back to PIO\n", - dev_driver_string(&p->pdev->dev), - dev_name(&p->pdev->dev)); + dev_warn_once(&p->pdev->dev, + "DMA not available, falling back to PIO\n"); break; } if (ret) @@ -1081,6 +1109,45 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) } #endif +static int sh_msiof_get_cs_gpios(struct sh_msiof_spi_priv *p) +{ + struct device *dev = &p->pdev->dev; + unsigned int used_ss_mask = 0; + unsigned int cs_gpios = 0; + unsigned int num_cs, i; + int ret; + + ret = gpiod_count(dev, "cs"); + if (ret <= 0) + return 0; + + num_cs = max_t(unsigned int, ret, p->master->num_chipselect); + for (i = 0; i < num_cs; i++) { + struct gpio_desc *gpiod; + + gpiod = devm_gpiod_get_index(dev, "cs", i, GPIOD_ASIS); + if (!IS_ERR(gpiod)) { + cs_gpios++; + continue; + } + + if (PTR_ERR(gpiod) != -ENOENT) + return PTR_ERR(gpiod); + + if (i >= MAX_SS) { + dev_err(dev, "Invalid native chip select %d\n", i); + return -EINVAL; + } + used_ss_mask |= BIT(i); + } + p->unused_ss = ffz(used_ss_mask); + if (cs_gpios && p->unused_ss >= MAX_SS) { + dev_err(dev, "No unused native chip select available\n"); + return -EINVAL; + } + return 0; +} + static struct dma_chan *sh_msiof_request_dma_chan(struct device *dev, enum dma_transfer_direction dir, unsigned int id, dma_addr_t port_addr) { @@ -1294,13 +1361,18 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) if (p->info->rx_fifo_override) p->rx_fifo_size = p->info->rx_fifo_override; + /* Setup GPIO chip selects */ + master->num_chipselect = p->info->num_chipselect; + ret = sh_msiof_get_cs_gpios(p); + if (ret) + goto err1; + /* init master code */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE; master->flags = chipdata->master_flags; master->bus_num = pdev->id; master->dev.of_node = pdev->dev.of_node; - master->num_chipselect = p->info->num_chipselect; master->setup = sh_msiof_spi_setup; master->prepare_message = sh_msiof_prepare_message; master->slave_abort = sh_msiof_slave_abort; diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index bbb1a275f718..f009d76f96b1 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -1072,7 +1072,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) struct sirfsoc_spi *sspi; struct spi_master *master; struct resource *mem_res; - struct sirf_spi_comp_data *spi_comp_data; + const struct sirf_spi_comp_data *spi_comp_data; int irq; int ret; const struct of_device_id *match; @@ -1092,7 +1092,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, master); sspi = spi_master_get_devdata(master); sspi->fifo_full_offset = ilog2(sspi->fifo_size); - spi_comp_data = (struct sirf_spi_comp_data *)match->data; + spi_comp_data = match->data; sspi->regs = spi_comp_data->regs; sspi->type = spi_comp_data->type; sspi->fifo_level_chk_mask = (sspi->fifo_size / 4) - 1; diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index fb38234249a8..8533f4edd00a 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c @@ -541,7 +541,7 @@ err_free_master: static int sun6i_spi_remove(struct platform_device *pdev) { - pm_runtime_disable(&pdev->dev); + pm_runtime_force_suspend(&pdev->dev); return 0; } |