* [PATCH v4 0/2] spi: omap2-mcspi: Add support for GPIO chipselects
@ 2015-05-07 23:36 Michael Welling
2015-05-07 23:36 ` [PATCH v4 1/2] spi: omap2-mcspi: Switch driver to use transfer_one Michael Welling
2015-05-07 23:36 ` [PATCH v4 2/2] spi: omap2-mcspi: Add gpio_request and init CS Michael Welling
0 siblings, 2 replies; 7+ messages in thread
From: Michael Welling @ 2015-05-07 23:36 UTC (permalink / raw)
To: broonie, linux-spi, linux-kernel; +Cc: Michael Welling
This patch allows for GPIOs specified in the devicetree to be used as SPI
chipselects on TI OMAP2 SoCs.
Tested on the AM3354.
v4: Breaks patch down into patch series.
v3: Switches driver to use transfer_one instead of transfer_one_message
allowing the spi core to handle toggling GPIO chip selects if specified.
v2: Considers the possible use of SPI_CS_HIGH during chip select activation.
Michael Welling (2):
spi: omap2-mcspi: Switch driver to use transfer_one
spi: omap2-mcspi: Add gpio_request and init CS
drivers/spi/spi-omap2-mcspi.c | 251 +++++++++++++++++++----------------------
1 file changed, 117 insertions(+), 134 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v4 1/2] spi: omap2-mcspi: Switch driver to use transfer_one
2015-05-07 23:36 [PATCH v4 0/2] spi: omap2-mcspi: Add support for GPIO chipselects Michael Welling
@ 2015-05-07 23:36 ` Michael Welling
2015-05-08 16:59 ` Mark Brown
2015-05-07 23:36 ` [PATCH v4 2/2] spi: omap2-mcspi: Add gpio_request and init CS Michael Welling
1 sibling, 1 reply; 7+ messages in thread
From: Michael Welling @ 2015-05-07 23:36 UTC (permalink / raw)
To: broonie, linux-spi, linux-kernel; +Cc: Michael Welling
Switches from transfer_one_message to transfer_one to prepare driver for
use of GPIO chip selects.
Signed-off-by: Michael Welling <mwelling@ieee.org>
---
drivers/spi/spi-omap2-mcspi.c | 244 +++++++++++++++++++----------------------
1 file changed, 110 insertions(+), 134 deletions(-)
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index d1a5b9f..3ac06ad 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -1052,7 +1052,8 @@ static void omap2_mcspi_cleanup(struct spi_device *spi)
}
}
-static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
+static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi,
+ struct spi_device *spi, struct spi_transfer *t)
{
/* We only enable one channel at a time -- the one whose message is
@@ -1062,8 +1063,6 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
* chipselect with the FORCE bit ... CS != channel enable.
*/
- struct spi_device *spi;
- struct spi_transfer *t = NULL;
struct spi_master *master;
struct omap2_mcspi_dma *mcspi_dma;
int cs_active = 0;
@@ -1073,7 +1072,6 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
int status = 0;
u32 chconf;
- spi = m->spi;
master = spi->master;
mcspi_dma = mcspi->dma_channels + spi->chip_select;
cs = spi->controller_state;
@@ -1090,94 +1088,89 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
par_override = 1;
omap2_mcspi_set_enable(spi, 0);
- list_for_each_entry(t, &m->transfers, transfer_list) {
- if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
- status = -EINVAL;
- break;
- }
- if (par_override ||
- (t->speed_hz != spi->max_speed_hz) ||
- (t->bits_per_word != spi->bits_per_word)) {
- par_override = 1;
- status = omap2_mcspi_setup_transfer(spi, t);
- if (status < 0)
- break;
- if (t->speed_hz == spi->max_speed_hz &&
- t->bits_per_word == spi->bits_per_word)
- par_override = 0;
- }
- if (cd && cd->cs_per_word) {
- chconf = mcspi->ctx.modulctrl;
- chconf &= ~OMAP2_MCSPI_MODULCTRL_SINGLE;
- mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, chconf);
- mcspi->ctx.modulctrl =
- mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL);
- }
+ if (par_override ||
+ (t->speed_hz != spi->max_speed_hz) ||
+ (t->bits_per_word != spi->bits_per_word)) {
+ par_override = 1;
+ status = omap2_mcspi_setup_transfer(spi, t);
+ if (status < 0)
+ goto out;
+ if (t->speed_hz == spi->max_speed_hz &&
+ t->bits_per_word == spi->bits_per_word)
+ par_override = 0;
+ }
+ if (cd && cd->cs_per_word) {
+ chconf = mcspi->ctx.modulctrl;
+ chconf &= ~OMAP2_MCSPI_MODULCTRL_SINGLE;
+ mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, chconf);
+ mcspi->ctx.modulctrl =
+ mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL);
+ }
- if (!cs_active) {
- omap2_mcspi_force_cs(spi, 1);
- cs_active = 1;
- }
-
- chconf = mcspi_cached_chconf0(spi);
- chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
- chconf &= ~OMAP2_MCSPI_CHCONF_TURBO;
+ if (!cs_active) {
+ omap2_mcspi_force_cs(spi, 1);
+ cs_active = 1;
+ }
- if (t->tx_buf == NULL)
- chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY;
- else if (t->rx_buf == NULL)
- chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY;
-
- if (cd && cd->turbo_mode && t->tx_buf == NULL) {
- /* Turbo mode is for more than one word */
- if (t->len > ((cs->word_len + 7) >> 3))
- chconf |= OMAP2_MCSPI_CHCONF_TURBO;
- }
+ chconf = mcspi_cached_chconf0(spi);
+ chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
+ chconf &= ~OMAP2_MCSPI_CHCONF_TURBO;
+
+ if (t->tx_buf == NULL)
+ chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY;
+ else if (t->rx_buf == NULL)
+ chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY;
+
+ if (cd && cd->turbo_mode && t->tx_buf == NULL) {
+ /* Turbo mode is for more than one word */
+ if (t->len > ((cs->word_len + 7) >> 3))
+ chconf |= OMAP2_MCSPI_CHCONF_TURBO;
+ }
- mcspi_write_chconf0(spi, chconf);
+ mcspi_write_chconf0(spi, chconf);
- if (t->len) {
- unsigned count;
+ if (t->len) {
+ unsigned count;
- if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
- (m->is_dma_mapped || t->len >= DMA_MIN_BYTES))
- omap2_mcspi_set_fifo(spi, t, 1);
+ if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
+ (t->len >= DMA_MIN_BYTES))
+ omap2_mcspi_set_fifo(spi, t, 1);
- omap2_mcspi_set_enable(spi, 1);
+ omap2_mcspi_set_enable(spi, 1);
- /* RX_ONLY mode needs dummy data in TX reg */
- if (t->tx_buf == NULL)
- writel_relaxed(0, cs->base
- + OMAP2_MCSPI_TX0);
+ /* RX_ONLY mode needs dummy data in TX reg */
+ if (t->tx_buf == NULL)
+ writel_relaxed(0, cs->base
+ + OMAP2_MCSPI_TX0);
- if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
- (m->is_dma_mapped || t->len >= DMA_MIN_BYTES))
- count = omap2_mcspi_txrx_dma(spi, t);
- else
- count = omap2_mcspi_txrx_pio(spi, t);
- m->actual_length += count;
+ if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
+ (t->len >= DMA_MIN_BYTES))
+ count = omap2_mcspi_txrx_dma(spi, t);
+ else
+ count = omap2_mcspi_txrx_pio(spi, t);
- if (count != t->len) {
- status = -EIO;
- break;
- }
+ if (count != t->len) {
+ status = -EIO;
+ goto out;
}
+ }
- if (t->delay_usecs)
- udelay(t->delay_usecs);
+ if (t->delay_usecs)
+ udelay(t->delay_usecs);
- /* ignore the "leave it on after last xfer" hint */
- if (t->cs_change) {
- omap2_mcspi_force_cs(spi, 0);
- cs_active = 0;
- }
+ /* ignore the "leave it on after last xfer" hint */
+ if (t->cs_change) {
+ omap2_mcspi_force_cs(spi, 0);
+ cs_active = 0;
+ }
- omap2_mcspi_set_enable(spi, 0);
+ omap2_mcspi_set_enable(spi, 0);
- if (mcspi->fifo_depth > 0)
- omap2_mcspi_set_fifo(spi, t, 0);
- }
+ if (mcspi->fifo_depth > 0)
+ omap2_mcspi_set_fifo(spi, t, 0);
+
+out:
/* Restore defaults if they were overriden */
if (par_override) {
par_override = 0;
@@ -1200,75 +1193,58 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
if (mcspi->fifo_depth > 0 && t)
omap2_mcspi_set_fifo(spi, t, 0);
- m->status = status;
+ return status;
}
-static int omap2_mcspi_transfer_one_message(struct spi_master *master,
- struct spi_message *m)
+static int omap2_mcspi_transfer_one(struct spi_master *master,
+ struct spi_device *spi, struct spi_transfer *t)
{
- struct spi_device *spi;
struct omap2_mcspi *mcspi;
struct omap2_mcspi_dma *mcspi_dma;
- struct spi_transfer *t;
- int status;
+ const void *tx_buf = t->tx_buf;
+ void *rx_buf = t->rx_buf;
+ unsigned len = t->len;
- spi = m->spi;
mcspi = spi_master_get_devdata(master);
mcspi_dma = mcspi->dma_channels + spi->chip_select;
- m->actual_length = 0;
- m->status = 0;
-
- list_for_each_entry(t, &m->transfers, transfer_list) {
- const void *tx_buf = t->tx_buf;
- void *rx_buf = t->rx_buf;
- unsigned len = t->len;
-
- if ((len && !(rx_buf || tx_buf))) {
- dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
- t->speed_hz,
- len,
- tx_buf ? "tx" : "",
- rx_buf ? "rx" : "",
- t->bits_per_word);
- status = -EINVAL;
- goto out;
- }
- if (m->is_dma_mapped || len < DMA_MIN_BYTES)
- continue;
-
- if (mcspi_dma->dma_tx && tx_buf != NULL) {
- t->tx_dma = dma_map_single(mcspi->dev, (void *) tx_buf,
- len, DMA_TO_DEVICE);
- if (dma_mapping_error(mcspi->dev, t->tx_dma)) {
- dev_dbg(mcspi->dev, "dma %cX %d bytes error\n",
- 'T', len);
- status = -EINVAL;
- goto out;
- }
+ if ((len && !(rx_buf || tx_buf))) {
+ dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
+ t->speed_hz,
+ len,
+ tx_buf ? "tx" : "",
+ rx_buf ? "rx" : "",
+ t->bits_per_word);
+ return -EINVAL;
+ }
+
+ if (len < DMA_MIN_BYTES)
+ goto skip_dma_map;
+
+ if (mcspi_dma->dma_tx && tx_buf != NULL) {
+ t->tx_dma = dma_map_single(mcspi->dev, (void *) tx_buf,
+ len, DMA_TO_DEVICE);
+ if (dma_mapping_error(mcspi->dev, t->tx_dma)) {
+ dev_dbg(mcspi->dev, "dma %cX %d bytes error\n",
+ 'T', len);
+ return -EINVAL;
}
- if (mcspi_dma->dma_rx && rx_buf != NULL) {
- t->rx_dma = dma_map_single(mcspi->dev, rx_buf, t->len,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(mcspi->dev, t->rx_dma)) {
- dev_dbg(mcspi->dev, "dma %cX %d bytes error\n",
- 'R', len);
- if (tx_buf != NULL)
- dma_unmap_single(mcspi->dev, t->tx_dma,
- len, DMA_TO_DEVICE);
- status = -EINVAL;
- goto out;
- }
+ }
+ if (mcspi_dma->dma_rx && rx_buf != NULL) {
+ t->rx_dma = dma_map_single(mcspi->dev, rx_buf, t->len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(mcspi->dev, t->rx_dma)) {
+ dev_dbg(mcspi->dev, "dma %cX %d bytes error\n",
+ 'R', len);
+ if (tx_buf != NULL)
+ dma_unmap_single(mcspi->dev, t->tx_dma,
+ len, DMA_TO_DEVICE);
+ return -EINVAL;
}
}
- omap2_mcspi_work(mcspi, m);
- /* spi_finalize_current_message() changes the status inside the
- * spi_message, save the status here. */
- status = m->status;
-out:
- spi_finalize_current_message(master);
- return status;
+skip_dma_map:
+ return omap2_mcspi_work_one(mcspi, spi, t);
}
static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
@@ -1347,7 +1323,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
master->setup = omap2_mcspi_setup;
master->auto_runtime_pm = true;
- master->transfer_one_message = omap2_mcspi_transfer_one_message;
+ master->transfer_one = omap2_mcspi_transfer_one;
master->cleanup = omap2_mcspi_cleanup;
master->dev.of_node = node;
master->max_speed_hz = OMAP2_MCSPI_MAX_FREQ;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v4 2/2] spi: omap2-mcspi: Add gpio_request and init CS
2015-05-07 23:36 [PATCH v4 0/2] spi: omap2-mcspi: Add support for GPIO chipselects Michael Welling
2015-05-07 23:36 ` [PATCH v4 1/2] spi: omap2-mcspi: Switch driver to use transfer_one Michael Welling
@ 2015-05-07 23:36 ` Michael Welling
2015-05-08 17:09 ` Mark Brown
1 sibling, 1 reply; 7+ messages in thread
From: Michael Welling @ 2015-05-07 23:36 UTC (permalink / raw)
To: broonie, linux-spi, linux-kernel; +Cc: Michael Welling
If GPIO chipselects are specified initialise the GPIO in the setup function.
Signed-off-by: Michael Welling <mwelling@ieee.org>
---
drivers/spi/spi-omap2-mcspi.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 3ac06ad..370c333 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -35,6 +35,7 @@
#include <linux/gcd.h>
#include <linux/spi/spi.h>
+#include <linux/gpio.h>
#include <linux/platform_data/spi-omap2-mcspi.h>
@@ -1015,6 +1016,12 @@ static int omap2_mcspi_setup(struct spi_device *spi)
if (ret < 0)
return ret;
+ if (gpio_is_valid(spi->cs_gpio)) {
+ if (gpio_request(spi->cs_gpio, dev_name(&spi->dev)) == 0)
+ gpio_direction_output(spi->cs_gpio,
+ !(spi->mode & SPI_CS_HIGH));
+ }
+
ret = omap2_mcspi_setup_transfer(spi, NULL);
pm_runtime_mark_last_busy(mcspi->dev);
pm_runtime_put_autosuspend(mcspi->dev);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v4 1/2] spi: omap2-mcspi: Switch driver to use transfer_one
2015-05-07 23:36 ` [PATCH v4 1/2] spi: omap2-mcspi: Switch driver to use transfer_one Michael Welling
@ 2015-05-08 16:59 ` Mark Brown
0 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2015-05-08 16:59 UTC (permalink / raw)
To: Michael Welling; +Cc: linux-spi, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 186 bytes --]
On Thu, May 07, 2015 at 06:36:53PM -0500, Michael Welling wrote:
> Switches from transfer_one_message to transfer_one to prepare driver for
> use of GPIO chip selects.
Applied, thanks.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v4 2/2] spi: omap2-mcspi: Add gpio_request and init CS
2015-05-07 23:36 ` [PATCH v4 2/2] spi: omap2-mcspi: Add gpio_request and init CS Michael Welling
@ 2015-05-08 17:09 ` Mark Brown
2015-05-08 17:37 ` Michael Welling
0 siblings, 1 reply; 7+ messages in thread
From: Mark Brown @ 2015-05-08 17:09 UTC (permalink / raw)
To: Michael Welling; +Cc: linux-spi, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 298 bytes --]
On Thu, May 07, 2015 at 06:36:54PM -0500, Michael Welling wrote:
> + if (gpio_is_valid(spi->cs_gpio)) {
> + if (gpio_request(spi->cs_gpio, dev_name(&spi->dev)) == 0)
> + gpio_direction_output(spi->cs_gpio,
> + !(spi->mode & SPI_CS_HIGH));
> + }
I'm not seeing anything that frees this GPIO?
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v4 2/2] spi: omap2-mcspi: Add gpio_request and init CS
2015-05-08 17:09 ` Mark Brown
@ 2015-05-08 17:37 ` Michael Welling
2015-05-08 17:53 ` Mark Brown
0 siblings, 1 reply; 7+ messages in thread
From: Michael Welling @ 2015-05-08 17:37 UTC (permalink / raw)
To: Mark Brown; +Cc: linux-spi, linux-kernel
On Fri, May 08, 2015 at 06:09:16PM +0100, Mark Brown wrote:
> On Thu, May 07, 2015 at 06:36:54PM -0500, Michael Welling wrote:
>
> > + if (gpio_is_valid(spi->cs_gpio)) {
> > + if (gpio_request(spi->cs_gpio, dev_name(&spi->dev)) == 0)
> > + gpio_direction_output(spi->cs_gpio,
> > + !(spi->mode & SPI_CS_HIGH));
> > + }
>
> I'm not seeing anything that frees this GPIO?
Ooops I forgot to add this to the cleanup function.
It appears that the transfer_one patch got applied so how should I
provide the new version of this patch?
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v4 2/2] spi: omap2-mcspi: Add gpio_request and init CS
2015-05-08 17:37 ` Michael Welling
@ 2015-05-08 17:53 ` Mark Brown
0 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2015-05-08 17:53 UTC (permalink / raw)
To: Michael Welling; +Cc: linux-spi, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 192 bytes --]
On Fri, May 08, 2015 at 12:37:37PM -0500, Michael Welling wrote:
> It appears that the transfer_one patch got applied so how should I
> provide the new version of this patch?
Incrementally.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2015-05-08 17:53 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-07 23:36 [PATCH v4 0/2] spi: omap2-mcspi: Add support for GPIO chipselects Michael Welling
2015-05-07 23:36 ` [PATCH v4 1/2] spi: omap2-mcspi: Switch driver to use transfer_one Michael Welling
2015-05-08 16:59 ` Mark Brown
2015-05-07 23:36 ` [PATCH v4 2/2] spi: omap2-mcspi: Add gpio_request and init CS Michael Welling
2015-05-08 17:09 ` Mark Brown
2015-05-08 17:37 ` Michael Welling
2015-05-08 17:53 ` Mark Brown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).