diff options
Diffstat (limited to 'drivers/spi/spi-gpio.c')
-rw-r--r-- | drivers/spi/spi-gpio.c | 80 |
1 files changed, 37 insertions, 43 deletions
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index d8db4564b406..4f192e013cd6 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -5,17 +5,17 @@ * Copyright (C) 2006,2008 David Brownell * Copyright (C) 2017 Linus Walleij */ +#include <linux/gpio/consumer.h> #include <linux/kernel.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/gpio/consumer.h> -#include <linux/of.h> +#include <linux/property.h> #include <linux/spi/spi.h> #include <linux/spi/spi_bitbang.h> #include <linux/spi/spi_gpio.h> - /* * This bitbanging SPI host driver should help make systems usable * when a native hardware SPI engine is not available, perhaps because @@ -236,11 +236,19 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active) } } +static void spi_gpio_set_mosi_idle(struct spi_device *spi) +{ + struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); + + gpiod_set_value_cansleep(spi_gpio->mosi, + !!(spi->mode & SPI_MOSI_IDLE_HIGH)); +} + static int spi_gpio_setup(struct spi_device *spi) { struct gpio_desc *cs; - int status = 0; struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); + int ret; /* * The CS GPIOs have already been @@ -248,15 +256,14 @@ static int spi_gpio_setup(struct spi_device *spi) */ if (spi_gpio->cs_gpios) { cs = spi_gpio->cs_gpios[spi_get_chipselect(spi, 0)]; - if (!spi->controller_state && cs) - status = gpiod_direction_output(cs, - !(spi->mode & SPI_CS_HIGH)); + if (!spi->controller_state && cs) { + ret = gpiod_direction_output(cs, !(spi->mode & SPI_CS_HIGH)); + if (ret) + return ret; + } } - if (!status) - status = spi_bitbang_setup(spi); - - return status; + return spi_bitbang_setup(spi); } static int spi_gpio_set_direction(struct spi_device *spi, bool output) @@ -326,29 +333,6 @@ static int spi_gpio_request(struct device *dev, struct spi_gpio *spi_gpio) return PTR_ERR_OR_ZERO(spi_gpio->sck); } -#ifdef CONFIG_OF -static const struct of_device_id spi_gpio_dt_ids[] = { - { .compatible = "spi-gpio" }, - {} -}; -MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids); - -static int spi_gpio_probe_dt(struct platform_device *pdev, - struct spi_controller *host) -{ - host->dev.of_node = pdev->dev.of_node; - host->use_gpio_descriptors = true; - - return 0; -} -#else -static inline int spi_gpio_probe_dt(struct platform_device *pdev, - struct spi_controller *host) -{ - return 0; -} -#endif - static int spi_gpio_probe_pdata(struct platform_device *pdev, struct spi_controller *host) { @@ -389,19 +373,21 @@ static int spi_gpio_probe(struct platform_device *pdev) struct spi_controller *host; struct spi_gpio *spi_gpio; struct device *dev = &pdev->dev; + struct fwnode_handle *fwnode = dev_fwnode(dev); struct spi_bitbang *bb; host = devm_spi_alloc_host(dev, sizeof(*spi_gpio)); if (!host) return -ENOMEM; - if (pdev->dev.of_node) - status = spi_gpio_probe_dt(pdev, host); - else + if (fwnode) { + device_set_node(&host->dev, fwnode); + host->use_gpio_descriptors = true; + } else { status = spi_gpio_probe_pdata(pdev, host); - - if (status) - return status; + if (status) + return status; + } spi_gpio = spi_controller_get_devdata(host); @@ -411,7 +397,8 @@ static int spi_gpio_probe(struct platform_device *pdev) host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); host->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL | - SPI_CS_HIGH | SPI_LSB_FIRST; + SPI_CS_HIGH | SPI_LSB_FIRST | SPI_MOSI_IDLE_LOW | + SPI_MOSI_IDLE_HIGH; if (!spi_gpio->mosi) { /* HW configuration without MOSI pin * @@ -427,7 +414,7 @@ static int spi_gpio_probe(struct platform_device *pdev) host->cleanup = spi_gpio_cleanup; bb = &spi_gpio->bitbang; - bb->master = host; + bb->ctlr = host; /* * There is some additional business, apart from driving the CS GPIO * line, that we need to do on selection. This makes the local @@ -436,6 +423,7 @@ static int spi_gpio_probe(struct platform_device *pdev) host->flags |= SPI_CONTROLLER_GPIO_SS; bb->chipselect = spi_gpio_chipselect; bb->set_line_direction = spi_gpio_set_direction; + bb->set_mosi_idle = spi_gpio_set_mosi_idle; if (host->flags & SPI_CONTROLLER_NO_TX) { bb->txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0; @@ -459,10 +447,16 @@ static int spi_gpio_probe(struct platform_device *pdev) MODULE_ALIAS("platform:" DRIVER_NAME); +static const struct of_device_id spi_gpio_dt_ids[] = { + { .compatible = "spi-gpio" }, + {} +}; +MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids); + static struct platform_driver spi_gpio_driver = { .driver = { .name = DRIVER_NAME, - .of_match_table = of_match_ptr(spi_gpio_dt_ids), + .of_match_table = spi_gpio_dt_ids, }, .probe = spi_gpio_probe, }; |