From: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
To: Feng Tang <feng.tang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Cc: Vinod Koul <vinod.koul-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org,
dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org,
linus.walleij-0IS4wlFg1OjSUeElwK9/Pw@public.gmane.org,
alan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org
Subject: Re: [Patch v2 3/3] spi/dw_spi: add DMA support
Date: Fri, 24 Dec 2010 01:12:14 -0700 [thread overview]
Message-ID: <20101224081214.GC5544@angua.secretlab.ca> (raw)
In-Reply-To: <1293170351-7426-3-git-send-email-feng.tang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
On Fri, Dec 24, 2010 at 01:59:11PM +0800, Feng Tang wrote:
> dw_spi driver in upstream only supports PIO mode, and this patch
> will support it to cowork with the Designware dma controller used
> on Intel Moorestown platform, at the same time it provides a general
> framework to support dw_spi core to cowork with dma controllers on
> other platforms
>
> It has been tested with a Option GTM501L 3G modem and Infenion 60x60
> modem. To use DMA mode, DMA controller 2 of Moorestown has to be enabled
>
> Also change the dma interface suggested by Linus Walleij.
>
> Acked-by: Linus Walleij <linus.walleij-0IS4wlFg1OjSUeElwK9/Pw@public.gmane.org>
> Acked-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> Signed-off-by: Feng Tang <feng.tang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> [Typo fix and renames to match intel_mid_dma renaming]
> Signed-off-by: Vinod Koul <vinod.koul-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> Signed-off-by: Alan Cox <alan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Applied for -next, thanks.
g.
> ---
> drivers/spi/Kconfig | 4 +
> drivers/spi/Makefile | 3 +-
> drivers/spi/dw_spi.c | 33 ++++---
> drivers/spi/dw_spi_mid.c | 224 ++++++++++++++++++++++++++++++++++++++++++++
> drivers/spi/dw_spi_pci.c | 20 +++-
> include/linux/spi/dw_spi.h | 24 ++++-
> 6 files changed, 284 insertions(+), 24 deletions(-)
> create mode 100644 drivers/spi/dw_spi_mid.c
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index 78f9fd0..d53c830 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -396,6 +396,10 @@ config SPI_DW_PCI
> tristate "PCI interface driver for DW SPI core"
> depends on SPI_DESIGNWARE && PCI
>
> +config SPI_DW_MID_DMA
> + bool "DMA support for DW SPI controller on Intel Moorestown platform"
> + depends on SPI_DW_PCI && INTEL_MID_DMAC
> +
> config SPI_DW_MMIO
> tristate "Memory-mapped io interface driver for DW SPI core"
> depends on SPI_DESIGNWARE && HAVE_CLK
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index 8bc1a5a..5e6e812 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -17,7 +17,8 @@ obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
> obj-$(CONFIG_SPI_COLDFIRE_QSPI) += coldfire_qspi.o
> obj-$(CONFIG_SPI_DAVINCI) += davinci_spi.o
> obj-$(CONFIG_SPI_DESIGNWARE) += dw_spi.o
> -obj-$(CONFIG_SPI_DW_PCI) += dw_spi_pci.o
> +obj-$(CONFIG_SPI_DW_PCI) += dw_spi_midpci.o
> +dw_spi_midpci-objs := dw_spi_pci.o dw_spi_mid.o
> obj-$(CONFIG_SPI_DW_MMIO) += dw_spi_mmio.o
> obj-$(CONFIG_SPI_EP93XX) += ep93xx_spi.o
> obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
> diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
> index b50bf5b..497ecb3 100644
> --- a/drivers/spi/dw_spi.c
> +++ b/drivers/spi/dw_spi.c
> @@ -288,8 +288,10 @@ static void *next_transfer(struct dw_spi *dws)
> */
> static int map_dma_buffers(struct dw_spi *dws)
> {
> - if (!dws->cur_msg->is_dma_mapped || !dws->dma_inited
> - || !dws->cur_chip->enable_dma)
> + if (!dws->cur_msg->is_dma_mapped
> + || !dws->dma_inited
> + || !dws->cur_chip->enable_dma
> + || !dws->dma_ops)
> return 0;
>
> if (dws->cur_transfer->tx_dma)
> @@ -341,7 +343,7 @@ static void int_error_stop(struct dw_spi *dws, const char *msg)
> tasklet_schedule(&dws->pump_transfers);
> }
>
> -static void transfer_complete(struct dw_spi *dws)
> +void dw_spi_xfer_done(struct dw_spi *dws)
> {
> /* Update total byte transfered return count actual bytes read */
> dws->cur_msg->actual_length += dws->len;
> @@ -356,6 +358,7 @@ static void transfer_complete(struct dw_spi *dws)
> } else
> tasklet_schedule(&dws->pump_transfers);
> }
> +EXPORT_SYMBOL_GPL(dw_spi_xfer_done);
>
> static irqreturn_t interrupt_transfer(struct dw_spi *dws)
> {
> @@ -387,7 +390,7 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
> if (dws->tx_end > dws->tx)
> spi_umask_intr(dws, SPI_INT_TXEI);
> else
> - transfer_complete(dws);
> + dw_spi_xfer_done(dws);
> }
>
> return IRQ_HANDLED;
> @@ -422,11 +425,7 @@ static void poll_transfer(struct dw_spi *dws)
> */
> dws->read(dws);
>
> - transfer_complete(dws);
> -}
> -
> -static void dma_transfer(struct dw_spi *dws, int cs_change)
> -{
> + dw_spi_xfer_done(dws);
> }
>
> static void pump_transfers(unsigned long data)
> @@ -608,7 +607,7 @@ static void pump_transfers(unsigned long data)
> }
>
> if (dws->dma_mapped)
> - dma_transfer(dws, cs_change);
> + dws->dma_ops->dma_transfer(dws, cs_change);
>
> if (chip->poll_mode)
> poll_transfer(dws);
> @@ -904,11 +903,17 @@ int __devinit dw_spi_add_host(struct dw_spi *dws)
> master->setup = dw_spi_setup;
> master->transfer = dw_spi_transfer;
>
> - dws->dma_inited = 0;
> -
> /* Basic HW init */
> spi_hw_init(dws);
>
> + if (dws->dma_ops && dws->dma_ops->dma_init) {
> + ret = dws->dma_ops->dma_init(dws);
> + if (ret) {
> + dev_warn(&master->dev, "DMA init failed\n");
> + dws->dma_inited = 0;
> + }
> + }
> +
> /* Initial and start queue */
> ret = init_queue(dws);
> if (ret) {
> @@ -933,6 +938,8 @@ int __devinit dw_spi_add_host(struct dw_spi *dws)
>
> err_queue_alloc:
> destroy_queue(dws);
> + if (dws->dma_ops && dws->dma_ops->dma_exit)
> + dws->dma_ops->dma_exit(dws);
> err_diable_hw:
> spi_enable_chip(dws, 0);
> free_irq(dws->irq, dws);
> @@ -957,6 +964,8 @@ void __devexit dw_spi_remove_host(struct dw_spi *dws)
> dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not "
> "complete, message memory not freed\n");
>
> + if (dws->dma_ops && dws->dma_ops->dma_exit)
> + dws->dma_ops->dma_exit(dws);
> spi_enable_chip(dws, 0);
> /* Disable clk */
> spi_set_clk(dws, 0);
> diff --git a/drivers/spi/dw_spi_mid.c b/drivers/spi/dw_spi_mid.c
> new file mode 100644
> index 0000000..8a49a13
> --- /dev/null
> +++ b/drivers/spi/dw_spi_mid.c
> @@ -0,0 +1,224 @@
> +/*
> + * dw_spi_mid.c - special handling for DW core on Intel MID platform
> + *
> + * Copyright (c) 2009, Intel Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope 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.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation,
> + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#include <linux/dma-mapping.h>
> +#include <linux/dmaengine.h>
> +#include <linux/interrupt.h>
> +#include <linux/slab.h>
> +#include <linux/spi/spi.h>
> +#include <linux/spi/dw_spi.h>
> +
> +#ifdef CONFIG_SPI_DW_MID_DMA
> +#include <linux/intel_mid_dma.h>
> +#include <linux/pci.h>
> +
> +struct mid_dma {
> + struct intel_mid_dma_slave dmas_tx;
> + struct intel_mid_dma_slave dmas_rx;
> +};
> +
> +static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param)
> +{
> + struct dw_spi *dws = param;
> +
> + return dws->dmac && (&dws->dmac->dev == chan->device->dev);
> +}
> +
> +static int mid_spi_dma_init(struct dw_spi *dws)
> +{
> + struct mid_dma *dw_dma = dws->dma_priv;
> + struct intel_mid_dma_slave *rxs, *txs;
> + dma_cap_mask_t mask;
> +
> + /*
> + * Get pci device for DMA controller, currently it could only
> + * be the DMA controller of either Moorestown or Medfield
> + */
> + dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0813, NULL);
> + if (!dws->dmac)
> + dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0827, NULL);
> +
> + dma_cap_zero(mask);
> + dma_cap_set(DMA_SLAVE, mask);
> +
> + /* 1. Init rx channel */
> + dws->rxchan = dma_request_channel(mask, mid_spi_dma_chan_filter, dws);
> + if (!dws->rxchan)
> + goto err_exit;
> + rxs = &dw_dma->dmas_rx;
> + rxs->hs_mode = LNW_DMA_HW_HS;
> + rxs->cfg_mode = LNW_DMA_PER_TO_MEM;
> + dws->rxchan->private = rxs;
> +
> + /* 2. Init tx channel */
> + dws->txchan = dma_request_channel(mask, mid_spi_dma_chan_filter, dws);
> + if (!dws->txchan)
> + goto free_rxchan;
> + txs = &dw_dma->dmas_tx;
> + txs->hs_mode = LNW_DMA_HW_HS;
> + txs->cfg_mode = LNW_DMA_MEM_TO_PER;
> + dws->txchan->private = txs;
> +
> + dws->dma_inited = 1;
> + return 0;
> +
> +free_rxchan:
> + dma_release_channel(dws->rxchan);
> +err_exit:
> + return -1;
> +
> +}
> +
> +static void mid_spi_dma_exit(struct dw_spi *dws)
> +{
> + dma_release_channel(dws->txchan);
> + dma_release_channel(dws->rxchan);
> +}
> +
> +/*
> + * dws->dma_chan_done is cleared before the dma transfer starts,
> + * callback for rx/tx channel will each increment it by 1.
> + * Reaching 2 means the whole spi transaction is done.
> + */
> +static void dw_spi_dma_done(void *arg)
> +{
> + struct dw_spi *dws = arg;
> +
> + if (++dws->dma_chan_done != 2)
> + return;
> + dw_spi_xfer_done(dws);
> +}
> +
> +static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
> +{
> + struct dma_async_tx_descriptor *txdesc = NULL, *rxdesc = NULL;
> + struct dma_chan *txchan, *rxchan;
> + struct dma_slave_config txconf, rxconf;
> + u16 dma_ctrl = 0;
> +
> + /* 1. setup DMA related registers */
> + if (cs_change) {
> + spi_enable_chip(dws, 0);
> + dw_writew(dws, dmardlr, 0xf);
> + dw_writew(dws, dmatdlr, 0x10);
> + if (dws->tx_dma)
> + dma_ctrl |= 0x2;
> + if (dws->rx_dma)
> + dma_ctrl |= 0x1;
> + dw_writew(dws, dmacr, dma_ctrl);
> + spi_enable_chip(dws, 1);
> + }
> +
> + dws->dma_chan_done = 0;
> + txchan = dws->txchan;
> + rxchan = dws->rxchan;
> +
> + /* 2. Prepare the TX dma transfer */
> + txconf.direction = DMA_TO_DEVICE;
> + txconf.dst_addr = dws->dma_addr;
> + txconf.dst_maxburst = LNW_DMA_MSIZE_16;
> + txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
> + txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
> +
> + txchan->device->device_control(txchan, DMA_SLAVE_CONFIG,
> + (unsigned long) &txconf);
> +
> + memset(&dws->tx_sgl, 0, sizeof(dws->tx_sgl));
> + dws->tx_sgl.dma_address = dws->tx_dma;
> + dws->tx_sgl.length = dws->len;
> +
> + txdesc = txchan->device->device_prep_slave_sg(txchan,
> + &dws->tx_sgl,
> + 1,
> + DMA_TO_DEVICE,
> + DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP);
> + txdesc->callback = dw_spi_dma_done;
> + txdesc->callback_param = dws;
> +
> + /* 3. Prepare the RX dma transfer */
> + rxconf.direction = DMA_FROM_DEVICE;
> + rxconf.src_addr = dws->dma_addr;
> + rxconf.src_maxburst = LNW_DMA_MSIZE_16;
> + rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
> + rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
> +
> + rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG,
> + (unsigned long) &rxconf);
> +
> + memset(&dws->rx_sgl, 0, sizeof(dws->rx_sgl));
> + dws->rx_sgl.dma_address = dws->rx_dma;
> + dws->rx_sgl.length = dws->len;
> +
> + rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
> + &dws->rx_sgl,
> + 1,
> + DMA_FROM_DEVICE,
> + DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP);
> + rxdesc->callback = dw_spi_dma_done;
> + rxdesc->callback_param = dws;
> +
> + /* rx must be started before tx due to spi instinct */
> + rxdesc->tx_submit(rxdesc);
> + txdesc->tx_submit(txdesc);
> + return 0;
> +}
> +
> +static struct dw_spi_dma_ops mid_dma_ops = {
> + .dma_init = mid_spi_dma_init,
> + .dma_exit = mid_spi_dma_exit,
> + .dma_transfer = mid_spi_dma_transfer,
> +};
> +#endif
> +
> +/* Some specific info for SPI0 controller on Moorestown */
> +
> +/* HW info for MRST CLk Control Unit, one 32b reg */
> +#define MRST_SPI_CLK_BASE 100000000 /* 100m */
> +#define MRST_CLK_SPI0_REG 0xff11d86c
> +#define CLK_SPI_BDIV_OFFSET 0
> +#define CLK_SPI_BDIV_MASK 0x00000007
> +#define CLK_SPI_CDIV_OFFSET 9
> +#define CLK_SPI_CDIV_MASK 0x00000e00
> +#define CLK_SPI_DISABLE_OFFSET 8
> +
> +int dw_spi_mid_init(struct dw_spi *dws)
> +{
> + u32 *clk_reg, clk_cdiv;
> +
> + clk_reg = ioremap_nocache(MRST_CLK_SPI0_REG, 16);
> + if (!clk_reg)
> + return -ENOMEM;
> +
> + /* get SPI controller operating freq info */
> + clk_cdiv = (readl(clk_reg) & CLK_SPI_CDIV_MASK) >> CLK_SPI_CDIV_OFFSET;
> + dws->max_freq = MRST_SPI_CLK_BASE / (clk_cdiv + 1);
> + iounmap(clk_reg);
> +
> + dws->num_cs = 16;
> + dws->fifo_len = 40; /* FIFO has 40 words buffer */
> +
> +#ifdef CONFIG_SPI_DW_MID_DMA
> + dws->dma_priv = kzalloc(sizeof(struct mid_dma), GFP_KERNEL);
> + if (!dws->dma_priv)
> + return -ENOMEM;
> + dws->dma_ops = &mid_dma_ops;
> +#endif
> + return 0;
> +}
> +
> diff --git a/drivers/spi/dw_spi_pci.c b/drivers/spi/dw_spi_pci.c
> index 1f52755..49ec3aa 100644
> --- a/drivers/spi/dw_spi_pci.c
> +++ b/drivers/spi/dw_spi_pci.c
> @@ -1,5 +1,5 @@
> /*
> - * mrst_spi_pci.c - PCI interface driver for DW SPI Core
> + * dw_spi_pci.c - PCI interface driver for DW SPI Core
> *
> * Copyright (c) 2009, Intel Corporation.
> *
> @@ -26,8 +26,8 @@
> #define DRIVER_NAME "dw_spi_pci"
>
> struct dw_spi_pci {
> - struct pci_dev *pdev;
> - struct dw_spi dws;
> + struct pci_dev *pdev;
> + struct dw_spi dws;
> };
>
> static int __devinit spi_pci_probe(struct pci_dev *pdev,
> @@ -72,9 +72,17 @@ static int __devinit spi_pci_probe(struct pci_dev *pdev,
> dws->parent_dev = &pdev->dev;
> dws->bus_num = 0;
> dws->num_cs = 4;
> - dws->max_freq = 25000000; /* for Moorestwon */
> dws->irq = pdev->irq;
> - dws->fifo_len = 40; /* FIFO has 40 words buffer */
> +
> + /*
> + * Specific handling for Intel MID paltforms, like dma setup,
> + * clock rate, FIFO depth.
> + */
> + if (pdev->device == 0x0800) {
> + ret = dw_spi_mid_init(dws);
> + if (ret)
> + goto err_unmap;
> + }
>
> ret = dw_spi_add_host(dws);
> if (ret)
> @@ -140,7 +148,7 @@ static int spi_resume(struct pci_dev *pdev)
> #endif
>
> static const struct pci_device_id pci_ids[] __devinitdata = {
> - /* Intel Moorestown platform SPI controller 0 */
> + /* Intel MID platform SPI controller 0 */
> { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) },
> {},
> };
> diff --git a/include/linux/spi/dw_spi.h b/include/linux/spi/dw_spi.h
> index c91302f..6cd10f6 100644
> --- a/include/linux/spi/dw_spi.h
> +++ b/include/linux/spi/dw_spi.h
> @@ -1,5 +1,6 @@
> #ifndef DW_SPI_HEADER_H
> #define DW_SPI_HEADER_H
> +
> #include <linux/io.h>
>
> /* Bit fields in CTRLR0 */
> @@ -82,6 +83,13 @@ struct dw_spi_reg {
> though only low 16 bits matters */
> } __packed;
>
> +struct dw_spi;
> +struct dw_spi_dma_ops {
> + int (*dma_init)(struct dw_spi *dws);
> + void (*dma_exit)(struct dw_spi *dws);
> + int (*dma_transfer)(struct dw_spi *dws, int cs_change);
> +};
> +
> struct dw_spi {
> struct spi_master *master;
> struct spi_device *cur_dev;
> @@ -136,13 +144,15 @@ struct dw_spi {
> /* Dma info */
> int dma_inited;
> struct dma_chan *txchan;
> + struct scatterlist tx_sgl;
> struct dma_chan *rxchan;
> - int txdma_done;
> - int rxdma_done;
> - u64 tx_param;
> - u64 rx_param;
> + struct scatterlist rx_sgl;
> + int dma_chan_done;
> struct device *dma_dev;
> - dma_addr_t dma_addr;
> + dma_addr_t dma_addr; /* phy address of the Data register */
> + struct dw_spi_dma_ops *dma_ops;
> + void *dma_priv; /* platform relate info */
> + struct pci_dev *dmac;
>
> /* Bus interface info */
> void *priv;
> @@ -216,4 +226,8 @@ extern int dw_spi_add_host(struct dw_spi *dws);
> extern void dw_spi_remove_host(struct dw_spi *dws);
> extern int dw_spi_suspend_host(struct dw_spi *dws);
> extern int dw_spi_resume_host(struct dw_spi *dws);
> +extern void dw_spi_xfer_done(struct dw_spi *dws);
> +
> +/* platform related setup */
> +extern int dw_spi_mid_init(struct dw_spi *dws); /* Intel MID platforms */
> #endif /* DW_SPI_HEADER_H */
> --
> 1.7.0.4
>
------------------------------------------------------------------------------
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and,
should the need arise, upgrade to a full multi-node Oracle RAC database
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl
next prev parent reply other threads:[~2010-12-24 8:12 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-24 5:59 [Patch v2 1/3] spi/dw_spi: Fix too short timeout in spi polling loop Feng Tang
[not found] ` <1293170351-7426-1-git-send-email-feng.tang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2010-12-24 5:59 ` [Patch v2 2/3] spi/dw_spi: change to EXPORT_SYMBOL_GPL for exported APIs Feng Tang
[not found] ` <1293170351-7426-2-git-send-email-feng.tang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2010-12-24 8:11 ` Grant Likely
2010-12-24 5:59 ` [Patch v2 3/3] spi/dw_spi: add DMA support Feng Tang
[not found] ` <1293170351-7426-3-git-send-email-feng.tang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2010-12-24 8:12 ` Grant Likely [this message]
2010-12-24 8:10 ` [Patch v2 1/3] spi/dw_spi: Fix too short timeout in spi polling loop Grant Likely
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20101224081214.GC5544@angua.secretlab.ca \
--to=grant.likely-s3s/wqlpoipyb63q8fvjnq@public.gmane.org \
--cc=alan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org \
--cc=dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
--cc=feng.tang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
--cc=linus.walleij-0IS4wlFg1OjSUeElwK9/Pw@public.gmane.org \
--cc=spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
--cc=vinod.koul-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).