mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 02:32:09 -04:00
Merge remote-tracking branches 'spi/topic/atmel', 'spi/topic/bcm-qspi', 'spi/topic/bcm2835aux', 'spi/topic/dw' and 'spi/topic/gpio' into spi-next
This commit is contained in:
commit
70a3550b8c
17 changed files with 313 additions and 325 deletions
|
|
@ -768,14 +768,14 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
|
|||
rxdesc = dmaengine_prep_slave_single(rxchan,
|
||||
as->dma_addr_rx_bbuf,
|
||||
xfer->len,
|
||||
DMA_FROM_DEVICE,
|
||||
DMA_DEV_TO_MEM,
|
||||
DMA_PREP_INTERRUPT |
|
||||
DMA_CTRL_ACK);
|
||||
} else {
|
||||
rxdesc = dmaengine_prep_slave_sg(rxchan,
|
||||
xfer->rx_sg.sgl,
|
||||
xfer->rx_sg.nents,
|
||||
DMA_FROM_DEVICE,
|
||||
DMA_DEV_TO_MEM,
|
||||
DMA_PREP_INTERRUPT |
|
||||
DMA_CTRL_ACK);
|
||||
}
|
||||
|
|
@ -787,14 +787,14 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
|
|||
memcpy(as->addr_tx_bbuf, xfer->tx_buf, xfer->len);
|
||||
txdesc = dmaengine_prep_slave_single(txchan,
|
||||
as->dma_addr_tx_bbuf,
|
||||
xfer->len, DMA_TO_DEVICE,
|
||||
xfer->len, DMA_MEM_TO_DEV,
|
||||
DMA_PREP_INTERRUPT |
|
||||
DMA_CTRL_ACK);
|
||||
} else {
|
||||
txdesc = dmaengine_prep_slave_sg(txchan,
|
||||
xfer->tx_sg.sgl,
|
||||
xfer->tx_sg.nents,
|
||||
DMA_TO_DEVICE,
|
||||
DMA_MEM_TO_DEV,
|
||||
DMA_PREP_INTERRUPT |
|
||||
DMA_CTRL_ACK);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1247,7 +1247,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
|
|||
qspi->base[MSPI] = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(qspi->base[MSPI])) {
|
||||
ret = PTR_ERR(qspi->base[MSPI]);
|
||||
goto qspi_probe_err;
|
||||
goto qspi_resource_err;
|
||||
}
|
||||
} else {
|
||||
goto qspi_resource_err;
|
||||
|
|
@ -1258,7 +1258,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
|
|||
qspi->base[BSPI] = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(qspi->base[BSPI])) {
|
||||
ret = PTR_ERR(qspi->base[BSPI]);
|
||||
goto qspi_probe_err;
|
||||
goto qspi_resource_err;
|
||||
}
|
||||
qspi->bspi_mode = true;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -321,7 +321,6 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
|
|||
struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
|
||||
unsigned long spi_hz, clk_hz, speed;
|
||||
unsigned long spi_used_hz;
|
||||
unsigned long long xfer_time_us;
|
||||
|
||||
/* calculate the registers to handle
|
||||
*
|
||||
|
|
@ -358,20 +357,21 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
|
|||
bs->rx_len = tfr->len;
|
||||
bs->pending = 0;
|
||||
|
||||
/* calculate the estimated time in us the transfer runs
|
||||
* note that there are are 2 idle clocks after each
|
||||
* chunk getting transferred - in our case the chunk size
|
||||
* is 3 bytes, so we approximate this by 9 bits/byte
|
||||
/* Calculate the estimated time in us the transfer runs. Note that
|
||||
* there are are 2 idle clocks cycles after each chunk getting
|
||||
* transferred - in our case the chunk size is 3 bytes, so we
|
||||
* approximate this by 9 cycles/byte. This is used to find the number
|
||||
* of Hz per byte per polling limit. E.g., we can transfer 1 byte in
|
||||
* 30 µs per 300,000 Hz of bus clock.
|
||||
*/
|
||||
xfer_time_us = tfr->len * 9 * 1000000;
|
||||
do_div(xfer_time_us, spi_used_hz);
|
||||
|
||||
#define HZ_PER_BYTE ((9 * 1000000) / BCM2835_AUX_SPI_POLLING_LIMIT_US)
|
||||
/* run in polling mode for short transfers */
|
||||
if (xfer_time_us < BCM2835_AUX_SPI_POLLING_LIMIT_US)
|
||||
if (tfr->len < spi_used_hz / HZ_PER_BYTE)
|
||||
return bcm2835aux_spi_transfer_one_poll(master, spi, tfr);
|
||||
|
||||
/* run in interrupt mode for all others */
|
||||
return bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
|
||||
#undef HZ_PER_BYTE
|
||||
}
|
||||
|
||||
static int bcm2835aux_spi_prepare_message(struct spi_master *master,
|
||||
|
|
|
|||
|
|
@ -112,10 +112,10 @@ static irqreturn_t dma_transfer(struct dw_spi *dws)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static bool mid_spi_can_dma(struct spi_master *master, struct spi_device *spi,
|
||||
struct spi_transfer *xfer)
|
||||
static bool mid_spi_can_dma(struct spi_controller *master,
|
||||
struct spi_device *spi, struct spi_transfer *xfer)
|
||||
{
|
||||
struct dw_spi *dws = spi_master_get_devdata(master);
|
||||
struct dw_spi *dws = spi_controller_get_devdata(master);
|
||||
|
||||
if (!dws->dma_inited)
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ static inline void dw_spi_debugfs_remove(struct dw_spi *dws)
|
|||
|
||||
static void dw_spi_set_cs(struct spi_device *spi, bool enable)
|
||||
{
|
||||
struct dw_spi *dws = spi_master_get_devdata(spi->master);
|
||||
struct dw_spi *dws = spi_controller_get_devdata(spi->controller);
|
||||
struct chip_data *chip = spi_get_ctldata(spi);
|
||||
|
||||
/* Chip select logic is inverted from spi_set_cs() */
|
||||
|
|
@ -250,8 +250,8 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
|
|||
|
||||
static irqreturn_t dw_spi_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct spi_master *master = dev_id;
|
||||
struct dw_spi *dws = spi_master_get_devdata(master);
|
||||
struct spi_controller *master = dev_id;
|
||||
struct dw_spi *dws = spi_controller_get_devdata(master);
|
||||
u16 irq_status = dw_readl(dws, DW_SPI_ISR) & 0x3f;
|
||||
|
||||
if (!irq_status)
|
||||
|
|
@ -277,10 +277,10 @@ static int poll_transfer(struct dw_spi *dws)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dw_spi_transfer_one(struct spi_master *master,
|
||||
static int dw_spi_transfer_one(struct spi_controller *master,
|
||||
struct spi_device *spi, struct spi_transfer *transfer)
|
||||
{
|
||||
struct dw_spi *dws = spi_master_get_devdata(master);
|
||||
struct dw_spi *dws = spi_controller_get_devdata(master);
|
||||
struct chip_data *chip = spi_get_ctldata(spi);
|
||||
u8 imask = 0;
|
||||
u16 txlevel = 0;
|
||||
|
|
@ -383,10 +383,10 @@ static int dw_spi_transfer_one(struct spi_master *master,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void dw_spi_handle_err(struct spi_master *master,
|
||||
static void dw_spi_handle_err(struct spi_controller *master,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct dw_spi *dws = spi_master_get_devdata(master);
|
||||
struct dw_spi *dws = spi_controller_get_devdata(master);
|
||||
|
||||
if (dws->dma_mapped)
|
||||
dws->dma_ops->dma_stop(dws);
|
||||
|
|
@ -471,7 +471,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi *dws)
|
|||
|
||||
int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
|
||||
{
|
||||
struct spi_master *master;
|
||||
struct spi_controller *master;
|
||||
int ret;
|
||||
|
||||
BUG_ON(dws == NULL);
|
||||
|
|
@ -518,8 +518,8 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
|
|||
}
|
||||
}
|
||||
|
||||
spi_master_set_devdata(master, dws);
|
||||
ret = devm_spi_register_master(dev, master);
|
||||
spi_controller_set_devdata(master, dws);
|
||||
ret = devm_spi_register_controller(dev, master);
|
||||
if (ret) {
|
||||
dev_err(&master->dev, "problem registering spi master\n");
|
||||
goto err_dma_exit;
|
||||
|
|
@ -534,7 +534,7 @@ err_dma_exit:
|
|||
spi_enable_chip(dws, 0);
|
||||
free_irq(dws->irq, master);
|
||||
err_free_master:
|
||||
spi_master_put(master);
|
||||
spi_controller_put(master);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_spi_add_host);
|
||||
|
|
@ -556,7 +556,7 @@ int dw_spi_suspend_host(struct dw_spi *dws)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = spi_master_suspend(dws->master);
|
||||
ret = spi_controller_suspend(dws->master);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -570,7 +570,7 @@ int dw_spi_resume_host(struct dw_spi *dws)
|
|||
int ret;
|
||||
|
||||
spi_hw_init(&dws->master->dev, dws);
|
||||
ret = spi_master_resume(dws->master);
|
||||
ret = spi_controller_resume(dws->master);
|
||||
if (ret)
|
||||
dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -93,14 +93,14 @@ struct dw_spi_dma_ops {
|
|||
int (*dma_init)(struct dw_spi *dws);
|
||||
void (*dma_exit)(struct dw_spi *dws);
|
||||
int (*dma_setup)(struct dw_spi *dws, struct spi_transfer *xfer);
|
||||
bool (*can_dma)(struct spi_master *master, struct spi_device *spi,
|
||||
bool (*can_dma)(struct spi_controller *master, struct spi_device *spi,
|
||||
struct spi_transfer *xfer);
|
||||
int (*dma_transfer)(struct dw_spi *dws, struct spi_transfer *xfer);
|
||||
void (*dma_stop)(struct dw_spi *dws);
|
||||
};
|
||||
|
||||
struct dw_spi {
|
||||
struct spi_master *master;
|
||||
struct spi_controller *master;
|
||||
enum dw_ssi_type type;
|
||||
|
||||
void __iomem *regs;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
* SPI master driver using generic bitbanged GPIO
|
||||
*
|
||||
* Copyright (C) 2006,2008 David Brownell
|
||||
* Copyright (C) 2017 Linus Walleij
|
||||
*
|
||||
* 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
|
||||
|
|
@ -16,10 +17,9 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi_bitbang.h>
|
||||
|
|
@ -44,7 +44,11 @@ struct spi_gpio {
|
|||
struct spi_bitbang bitbang;
|
||||
struct spi_gpio_platform_data pdata;
|
||||
struct platform_device *pdev;
|
||||
unsigned long cs_gpios[0];
|
||||
struct gpio_desc *sck;
|
||||
struct gpio_desc *miso;
|
||||
struct gpio_desc *mosi;
|
||||
struct gpio_desc **cs_gpios;
|
||||
bool has_cs;
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
|
@ -77,13 +81,6 @@ struct spi_gpio {
|
|||
|
||||
#define GENERIC_BITBANG /* vs tight inlines */
|
||||
|
||||
/* all functions referencing these symbols must define pdata */
|
||||
#define SPI_MISO_GPIO ((pdata)->miso)
|
||||
#define SPI_MOSI_GPIO ((pdata)->mosi)
|
||||
#define SPI_SCK_GPIO ((pdata)->sck)
|
||||
|
||||
#define SPI_N_CHIPSEL ((pdata)->num_chipselect)
|
||||
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
|
@ -105,25 +102,27 @@ spi_to_pdata(const struct spi_device *spi)
|
|||
return &spi_to_spi_gpio(spi)->pdata;
|
||||
}
|
||||
|
||||
/* this is #defined to avoid unused-variable warnings when inlining */
|
||||
#define pdata spi_to_pdata(spi)
|
||||
|
||||
/* These helpers are in turn called by the bitbang inlines */
|
||||
static inline void setsck(const struct spi_device *spi, int is_on)
|
||||
{
|
||||
gpio_set_value_cansleep(SPI_SCK_GPIO, is_on);
|
||||
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
|
||||
|
||||
gpiod_set_value_cansleep(spi_gpio->sck, is_on);
|
||||
}
|
||||
|
||||
static inline void setmosi(const struct spi_device *spi, int is_on)
|
||||
{
|
||||
gpio_set_value_cansleep(SPI_MOSI_GPIO, is_on);
|
||||
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
|
||||
|
||||
gpiod_set_value_cansleep(spi_gpio->mosi, is_on);
|
||||
}
|
||||
|
||||
static inline int getmiso(const struct spi_device *spi)
|
||||
{
|
||||
return !!gpio_get_value_cansleep(SPI_MISO_GPIO);
|
||||
}
|
||||
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
|
||||
|
||||
#undef pdata
|
||||
return !!gpiod_get_value_cansleep(spi_gpio->miso);
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: this clocks "as fast as we can". It "should" be a function of the
|
||||
|
|
@ -216,123 +215,89 @@ static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,
|
|||
static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
|
||||
{
|
||||
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
|
||||
unsigned long cs = spi_gpio->cs_gpios[spi->chip_select];
|
||||
|
||||
/* set initial clock polarity */
|
||||
/* set initial clock line level */
|
||||
if (is_active)
|
||||
setsck(spi, spi->mode & SPI_CPOL);
|
||||
gpiod_set_value_cansleep(spi_gpio->sck, spi->mode & SPI_CPOL);
|
||||
|
||||
if (cs != SPI_GPIO_NO_CHIPSELECT) {
|
||||
/* SPI is normally active-low */
|
||||
gpio_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
|
||||
/* Drive chip select line, if we have one */
|
||||
if (spi_gpio->has_cs) {
|
||||
struct gpio_desc *cs = spi_gpio->cs_gpios[spi->chip_select];
|
||||
|
||||
/* SPI chip selects are normally active-low */
|
||||
gpiod_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
|
||||
}
|
||||
}
|
||||
|
||||
static int spi_gpio_setup(struct spi_device *spi)
|
||||
{
|
||||
unsigned long cs;
|
||||
struct gpio_desc *cs;
|
||||
int status = 0;
|
||||
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
|
||||
struct device_node *np = spi->master->dev.of_node;
|
||||
|
||||
if (np) {
|
||||
/*
|
||||
* In DT environments, the CS GPIOs have already been
|
||||
* initialized from the "cs-gpios" property of the node.
|
||||
*/
|
||||
cs = spi_gpio->cs_gpios[spi->chip_select];
|
||||
} else {
|
||||
/*
|
||||
* ... otherwise, take it from spi->controller_data
|
||||
*/
|
||||
cs = (uintptr_t) spi->controller_data;
|
||||
}
|
||||
/*
|
||||
* The CS GPIOs have already been
|
||||
* initialized from the descriptor lookup.
|
||||
*/
|
||||
cs = spi_gpio->cs_gpios[spi->chip_select];
|
||||
if (!spi->controller_state && cs)
|
||||
status = gpiod_direction_output(cs,
|
||||
!(spi->mode & SPI_CS_HIGH));
|
||||
|
||||
if (!spi->controller_state) {
|
||||
if (cs != SPI_GPIO_NO_CHIPSELECT) {
|
||||
status = gpio_request(cs, dev_name(&spi->dev));
|
||||
if (status)
|
||||
return status;
|
||||
status = gpio_direction_output(cs,
|
||||
!(spi->mode & SPI_CS_HIGH));
|
||||
}
|
||||
}
|
||||
if (!status) {
|
||||
/* in case it was initialized from static board data */
|
||||
spi_gpio->cs_gpios[spi->chip_select] = cs;
|
||||
if (!status)
|
||||
status = spi_bitbang_setup(spi);
|
||||
}
|
||||
|
||||
if (status) {
|
||||
if (!spi->controller_state && cs != SPI_GPIO_NO_CHIPSELECT)
|
||||
gpio_free(cs);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static void spi_gpio_cleanup(struct spi_device *spi)
|
||||
{
|
||||
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
|
||||
unsigned long cs = spi_gpio->cs_gpios[spi->chip_select];
|
||||
|
||||
if (cs != SPI_GPIO_NO_CHIPSELECT)
|
||||
gpio_free(cs);
|
||||
spi_bitbang_cleanup(spi);
|
||||
}
|
||||
|
||||
static int spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
|
||||
/*
|
||||
* It can be convenient to use this driver with pins that have alternate
|
||||
* functions associated with a "native" SPI controller if a driver for that
|
||||
* controller is not available, or is missing important functionality.
|
||||
*
|
||||
* On platforms which can do so, configure MISO with a weak pullup unless
|
||||
* there's an external pullup on that signal. That saves power by avoiding
|
||||
* floating signals. (A weak pulldown would save power too, but many
|
||||
* drivers expect to see all-ones data as the no slave "response".)
|
||||
*/
|
||||
static int spi_gpio_request(struct device *dev,
|
||||
struct spi_gpio *spi_gpio,
|
||||
unsigned int num_chipselects,
|
||||
u16 *mflags)
|
||||
{
|
||||
int value;
|
||||
int i;
|
||||
|
||||
value = gpio_request(pin, label);
|
||||
if (value == 0) {
|
||||
if (is_in)
|
||||
value = gpio_direction_input(pin);
|
||||
else
|
||||
value = gpio_direction_output(pin, 0);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static int spi_gpio_request(struct spi_gpio_platform_data *pdata,
|
||||
const char *label, u16 *res_flags)
|
||||
{
|
||||
int value;
|
||||
|
||||
/* NOTE: SPI_*_GPIO symbols may reference "pdata" */
|
||||
|
||||
if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) {
|
||||
value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false);
|
||||
if (value)
|
||||
goto done;
|
||||
} else {
|
||||
spi_gpio->mosi = devm_gpiod_get_optional(dev, "mosi", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(spi_gpio->mosi))
|
||||
return PTR_ERR(spi_gpio->mosi);
|
||||
if (!spi_gpio->mosi)
|
||||
/* HW configuration without MOSI pin */
|
||||
*res_flags |= SPI_MASTER_NO_TX;
|
||||
}
|
||||
*mflags |= SPI_MASTER_NO_TX;
|
||||
|
||||
if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) {
|
||||
value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
|
||||
if (value)
|
||||
goto free_mosi;
|
||||
} else {
|
||||
spi_gpio->miso = devm_gpiod_get_optional(dev, "miso", GPIOD_IN);
|
||||
if (IS_ERR(spi_gpio->miso))
|
||||
return PTR_ERR(spi_gpio->miso);
|
||||
if (!spi_gpio->miso)
|
||||
/* HW configuration without MISO pin */
|
||||
*res_flags |= SPI_MASTER_NO_RX;
|
||||
*mflags |= SPI_MASTER_NO_RX;
|
||||
|
||||
spi_gpio->sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(spi_gpio->mosi))
|
||||
return PTR_ERR(spi_gpio->mosi);
|
||||
|
||||
for (i = 0; i < num_chipselects; i++) {
|
||||
spi_gpio->cs_gpios[i] = devm_gpiod_get_index(dev, "cs",
|
||||
i, GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(spi_gpio->cs_gpios[i]))
|
||||
return PTR_ERR(spi_gpio->cs_gpios[i]);
|
||||
}
|
||||
|
||||
value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
|
||||
if (value)
|
||||
goto free_miso;
|
||||
|
||||
goto done;
|
||||
|
||||
free_miso:
|
||||
if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
|
||||
gpio_free(SPI_MISO_GPIO);
|
||||
free_mosi:
|
||||
if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
|
||||
gpio_free(SPI_MOSI_GPIO);
|
||||
done:
|
||||
return value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
|
@ -358,26 +323,6 @@ static int spi_gpio_probe_dt(struct platform_device *pdev)
|
|||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = of_get_named_gpio(np, "gpio-sck", 0);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "gpio-sck property not found\n");
|
||||
goto error_free;
|
||||
}
|
||||
pdata->sck = ret;
|
||||
|
||||
ret = of_get_named_gpio(np, "gpio-miso", 0);
|
||||
if (ret < 0) {
|
||||
dev_info(&pdev->dev, "gpio-miso property not found, switching to no-rx mode\n");
|
||||
pdata->miso = SPI_GPIO_NO_MISO;
|
||||
} else
|
||||
pdata->miso = ret;
|
||||
|
||||
ret = of_get_named_gpio(np, "gpio-mosi", 0);
|
||||
if (ret < 0) {
|
||||
dev_info(&pdev->dev, "gpio-mosi property not found, switching to no-tx mode\n");
|
||||
pdata->mosi = SPI_GPIO_NO_MOSI;
|
||||
} else
|
||||
pdata->mosi = ret;
|
||||
|
||||
ret = of_property_read_u32(np, "num-chipselects", &tmp);
|
||||
if (ret < 0) {
|
||||
|
|
@ -409,7 +354,6 @@ static int spi_gpio_probe(struct platform_device *pdev)
|
|||
struct spi_gpio_platform_data *pdata;
|
||||
u16 master_flags = 0;
|
||||
bool use_of = 0;
|
||||
int num_devices;
|
||||
|
||||
status = spi_gpio_probe_dt(pdev);
|
||||
if (status < 0)
|
||||
|
|
@ -423,59 +367,41 @@ static int spi_gpio_probe(struct platform_device *pdev)
|
|||
return -ENODEV;
|
||||
#endif
|
||||
|
||||
if (use_of && !SPI_N_CHIPSEL)
|
||||
num_devices = 1;
|
||||
else
|
||||
num_devices = SPI_N_CHIPSEL;
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*spi_gpio));
|
||||
if (!master)
|
||||
return -ENOMEM;
|
||||
|
||||
status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*spi_gpio) +
|
||||
(sizeof(unsigned long) * num_devices));
|
||||
if (!master) {
|
||||
status = -ENOMEM;
|
||||
goto gpio_free;
|
||||
}
|
||||
spi_gpio = spi_master_get_devdata(master);
|
||||
|
||||
spi_gpio->cs_gpios = devm_kzalloc(&pdev->dev,
|
||||
pdata->num_chipselect * sizeof(*spi_gpio->cs_gpios),
|
||||
GFP_KERNEL);
|
||||
if (!spi_gpio->cs_gpios)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, spi_gpio);
|
||||
|
||||
/* Determine if we have chip selects connected */
|
||||
spi_gpio->has_cs = !!pdata->num_chipselect;
|
||||
|
||||
spi_gpio->pdev = pdev;
|
||||
if (pdata)
|
||||
spi_gpio->pdata = *pdata;
|
||||
|
||||
status = spi_gpio_request(&pdev->dev, spi_gpio,
|
||||
pdata->num_chipselect, &master_flags);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
|
||||
master->flags = master_flags;
|
||||
master->bus_num = pdev->id;
|
||||
master->num_chipselect = num_devices;
|
||||
/* The master needs to think there is a chipselect even if not connected */
|
||||
master->num_chipselect = spi_gpio->has_cs ? pdata->num_chipselect : 1;
|
||||
master->setup = spi_gpio_setup;
|
||||
master->cleanup = spi_gpio_cleanup;
|
||||
#ifdef CONFIG_OF
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
|
||||
if (use_of) {
|
||||
int i;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
|
||||
/*
|
||||
* In DT environments, take the CS GPIO from the "cs-gpios"
|
||||
* property of the node.
|
||||
*/
|
||||
|
||||
if (!SPI_N_CHIPSEL)
|
||||
spi_gpio->cs_gpios[0] = SPI_GPIO_NO_CHIPSELECT;
|
||||
else
|
||||
for (i = 0; i < SPI_N_CHIPSEL; i++) {
|
||||
status = of_get_named_gpio(np, "cs-gpios", i);
|
||||
if (status < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"invalid cs-gpios property\n");
|
||||
goto gpio_free;
|
||||
}
|
||||
spi_gpio->cs_gpios[i] = status;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
spi_gpio->bitbang.master = master;
|
||||
|
|
@ -496,15 +422,8 @@ static int spi_gpio_probe(struct platform_device *pdev)
|
|||
spi_gpio->bitbang.flags = SPI_CS_HIGH;
|
||||
|
||||
status = spi_bitbang_start(&spi_gpio->bitbang);
|
||||
if (status < 0) {
|
||||
gpio_free:
|
||||
if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
|
||||
gpio_free(SPI_MISO_GPIO);
|
||||
if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
|
||||
gpio_free(SPI_MOSI_GPIO);
|
||||
gpio_free(SPI_SCK_GPIO);
|
||||
if (status)
|
||||
spi_master_put(master);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
@ -520,11 +439,6 @@ static int spi_gpio_remove(struct platform_device *pdev)
|
|||
/* stop() unregisters child devices too */
|
||||
spi_bitbang_stop(&spi_gpio->bitbang);
|
||||
|
||||
if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
|
||||
gpio_free(SPI_MISO_GPIO);
|
||||
if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
|
||||
gpio_free(SPI_MOSI_GPIO);
|
||||
gpio_free(SPI_SCK_GPIO);
|
||||
spi_master_put(spi_gpio->bitbang.master);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue