All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tony Lindgren <tony@atomide.com>
To: vimal singh <vimalsingh@ti.com>
Cc: linux-omap@vger.kernel.org
Subject: Re: [Resend][PATCH - Omapzoom][NAND] Add prefetch and DMA support
Date: Thu, 8 Jan 2009 16:16:28 +0200	[thread overview]
Message-ID: <20090108141626.GM27566@atomide.com> (raw)
In-Reply-To: <38756.192.168.10.89.1221565961.squirrel@dbdmail.itg.ti.com>

* vimal singh <vimalsingh@ti.com> [080916 14:53]:
> Following patch taken over the omapzoom.org tree adds
> prefetch (MPU and DMA) support to the OMAP2/3 nand driver.
> The prefetch supprot also adds the support for 8-bit
> devices.
> David Brownell's patch (omap2_nand updates) changes
> have been included in this patch manually.

Just few random comments.. Maybe try to get the
drivers/mtd/omap2.c first into the mainline kernel
on the mtd list, then start figuring out what needs
to be done for getting the prefetch support done.

Tony
 

> Signed-off-by: Vimal Singh <vimalsingh@ti.com>
> 
> ---
> 8-bit devices are supported only in prefetch mode.
> 
> vimal.
> 
> 
> ---
>  arch/arm/mach-omap2/gpmc.c             |   95 +++++++++++++
>  arch/arm/plat-omap/include/mach/gpmc.h |    4
>  drivers/mtd/nand/Kconfig               |   17 ++
>  drivers/mtd/nand/omap2.c               |  240
> +++++++++++++++++++++++++++++---- 4 files changed, 332 insertions(+), 24
> deletions(-)
> 
> Index: omapkernel/arch/arm/mach-omap2/gpmc.c
> =================================================================== ---
> omapkernel.orig/arch/arm/mach-omap2/gpmc.c	2008-09-15 17:59:47.000000000 +0530
> +++ omapkernel/arch/arm/mach-omap2/gpmc.c	2008-09-15 18:00:14.000000000 +0530
> @@ -54,6 +54,12 @@
>  #define GPMC_CHUNK_SHIFT	24		/* 16 MB */
>  #define GPMC_SECTION_SHIFT	28		/* 128 MB */
> 
> +#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH
> +#define CS_NUM_SHIFT		24
> +#define ENABLE_PREFETCH		7
> +#define DMA_MPU_MODE		2
> +#endif
> +
>  #ifdef CONFIG_OMAP3_PM
>  /*
>   * Structure to save/restore gpmc context
> @@ -407,6 +413,92 @@
>  }
>  EXPORT_SYMBOL(gpmc_cs_free);
> 
> +#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH
> +/*
> + * gpmc_prefetch_init - configures default configuration for prefetch engine + */
> +static void gpmc_prefetch_init(void)
> +{
> +	/* Setting the default threshold to 64 */
> +	gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0);
> +	gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x40  << 8);
> +	gpmc_write_reg(GPMC_PREFETCH_CONFIG2, 0x0);
> +}
> +
> +/*
> + * gpmc_prefetch_start - configures and starts prefetch transfer
> + * @cs - nand cs (chip select) number
> + * @dma_mode: dma mode enable (1) or disable (0)
> + * @u32_count: number of bytes to be transferred
> + * @is_write: prefetch read(0) or write post(1) mode
> + */
> +void gpmc_prefetch_start(int cs, int dma_mode,
> +				unsigned int u32_count, int is_write)
> +{
> +	uint32_t prefetch_config1;
> +	if (is_write) {
> +		/* Set the amount of bytes to be prefetched */
> +		gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
> +
> +		/* Set dma/mpu mode, the post write and enable the engine
> +		 * Set which cs is using the post write
> +		 */
> +		prefetch_config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
> +		prefetch_config1 |= ((cs << CS_NUM_SHIFT) |
> +					(dma_mode << DMA_MPU_MODE) |
> +					(1 << ENABLE_PREFETCH) | 0x1);
> +		gpmc_write_reg(GPMC_PREFETCH_CONFIG1, prefetch_config1);
> +	} else {
> +		/* Set the amount of bytes to be prefetched */
> +		gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
> +
> +		/* Set dma/mpu mode, the prefech read and enable the engine
> +		 * Set which cs is using the prefetch
> +		 */
> +		prefetch_config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
> +		prefetch_config1 |= (((cs << CS_NUM_SHIFT) |
> +					(dma_mode << DMA_MPU_MODE) |
> +					(1 << ENABLE_PREFETCH)) & ~0x1);
> +		gpmc_write_reg(GPMC_PREFETCH_CONFIG1, prefetch_config1);
> +	}
> +	/*  Start the prefetch engine */
> +	gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1);
> +}
> +EXPORT_SYMBOL(gpmc_prefetch_start);
> +
> +/*
> + * gpmc_prefetch_stop - disables and stops the prefetch engine
> + */
> +void gpmc_prefetch_stop(void)
> +{
> +	uint32_t prefetch_config1;
> +	/* stop the PFPW engine */
> +	gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0);
> +
> +	/* Disable the PFPW engine */
> +	prefetch_config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
> +	prefetch_config1 &= ~((0x07 << CS_NUM_SHIFT) |
> +				(1 << ENABLE_PREFETCH) |
> +					(1 << DMA_MPU_MODE) | 0x1);
> +	gpmc_write_reg(GPMC_PREFETCH_CONFIG1, prefetch_config1);
> +}
> +EXPORT_SYMBOL(gpmc_prefetch_stop);
> +
> +/*
> + * gpmc_prefetch_status - reads prefetch status of engine
> + */
> +int  gpmc_prefetch_status(void)
> +{
> +	return gpmc_read_reg(GPMC_PREFETCH_STATUS);
> +}
> +EXPORT_SYMBOL(gpmc_prefetch_status);
> +#else
> +int  gpmc_prefetch_status(void) {return 0; }
> +void gpmc_prefetch_stop(void) {}
> +void gpmc_prefetch_start(int cs, int dma_mode, unsigned int u32_count,
> +							int is_write) {}
> +#endif
> +
>  static void __init gpmc_mem_init(void)
>  {
>  	int cs;
> @@ -462,6 +554,9 @@
>  	gpmc_freq_cfg.freq_cfg = NULL;
>  	gpmc_freq_cfg.total_no_of_freq = 0;
>  #endif
> +#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH
> +	gpmc_prefetch_init();
> +#endif
>  	gpmc_mem_init();
>  }
> 
> Index: omapkernel/arch/arm/plat-omap/include/mach/gpmc.h
> =================================================================== ---
> omapkernel.orig/arch/arm/plat-omap/include/mach/gpmc.h	2008-09-15
> 17:59:47.000000000 +0530
> +++ omapkernel/arch/arm/plat-omap/include/mach/gpmc.h	2008-09-15
> 18:00:14.000000000 +0530
> @@ -139,6 +139,10 @@
>  extern void gpmc_cs_free(int cs);
>  extern int gpmc_cs_set_reserved(int cs, int reserved);
>  extern int gpmc_cs_reserved(int cs);
> +extern void gpmc_prefetch_start(int cs, int dma_mode,
> +					unsigned int u32_count, int is_write);
> +extern void gpmc_prefetch_stop(void);
> +extern int  gpmc_prefetch_status(void);
>  extern void __init gpmc_init(void);
> 
>  #endif
> Index: omapkernel/drivers/mtd/nand/Kconfig
> =================================================================== ---
> omapkernel.orig/drivers/mtd/nand/Kconfig	2008-09-15 17:59:47.000000000 +0530
> +++ omapkernel/drivers/mtd/nand/Kconfig	2008-09-16 14:42:04.000000000 +0530 @@
> -84,6 +84,23 @@
>             MTD_NAND_OMAP_HWECC = 1 which enables the hw ecc
>             MTD_NAND_OMAP_HWECC = 0, enables software ecc
> 
> +config MTD_NAND_OMAP_PREFETCH
> +	bool "GPMC prefetch support for NAND Flash device"
> +	depends on MTD_NAND && MTD_NAND_OMAP2
> +	default y
> +	help
> +	 The NAND device can be accessed for Read/Write using GPMC PREFETCH engine +	
> to improve the performance.
> +
> +config MTD_NAND_OMAP_PREFETCH_DMA
> +	depends on MTD_NAND_OMAP_PREFETCH
> +	bool "DMA mode"
> +	default n
> +	help
> +	 The GPMC PREFETCH engine can be configured eigther in MPU interrupt mode +	
> or in DMA interrupt mode.
> +	 Say y for DMA mode or MPU mode will be used
> +
>  config MTD_NAND_OMAP
>  	tristate "NAND Flash device on OMAP H3/H2/P2 boards"
>  	depends on ARM && ARCH_OMAP1 && MTD_NAND && (MACH_OMAP_H2 || MACH_OMAP_H3 ||
> MACH_OMAP_PERSEUS2)
> Index: omapkernel/drivers/mtd/nand/omap2.c
> =================================================================== ---
> omapkernel.orig/drivers/mtd/nand/omap2.c	2008-09-15 17:59:47.000000000 +0530
> +++ omapkernel/drivers/mtd/nand/omap2.c	2008-09-16 14:39:14.000000000 +0530 @@
> -112,7 +112,28 @@
>  #endif
> 
>  #ifndef MTD_NAND_OMAP_HWECC
> -#define MTD_NAND_OMAP_HWECC   0
> +#define MTD_NAND_OMAP_HWECC	0
> +#endif
> +
> +#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH
> +static int use_prefetch = 1;
> +
> +/* "modprobe ... use_prefetch=0" etc */
> +module_param(use_prefetch, bool, 0);
> +MODULE_PARM_DESC(use_prefetch, "enable/disable use of PREFETCH"); +
> +#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA
> +static int use_dma = 1;
> +
> +/* "modprobe ... use_dma=0" etc */
> +module_param(use_dma, bool, 0);
> +MODULE_PARM_DESC(use_dma, "enable/disable use of DMA");
> +#else
> +static int use_dma;
> +#endif
> +#else
> +static int use_prefetch;
> +static int use_dma;
>  #endif
> 
>  struct omap_nand_info {
> @@ -127,6 +148,9 @@
>  	unsigned long			phys_base;
>  	void __iomem			*gpmc_cs_baseaddr;
>  	void __iomem			*gpmc_baseaddr;
> +	void __iomem			*nand_pref_fifo_add;
> +	struct completion		comp;
> +	int				dma_ch;
>  };
> 
>  /*
> @@ -190,45 +214,191 @@
>  		__raw_writeb(cmd, info->nand.IO_ADDR_W);
>  }
> 
> +#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA
>  /*
> - * omap_read_buf - read data from NAND controller into buffer
> + * omap_nand_dma_cb: callback on the completion of dma transfer
> + * @lch: logical channel
> + * @ch_satuts: channel status
> + * @data: pointer to completion data structure
> + */
> +static void omap_nand_dma_cb(int lch, u16 ch_status, void *data)
> +{
> +	complete((struct completion *) data);
> +}
> +
> +/*
> + * omap_nand_dma_transfer: configer and start dma transfer
>   * @mtd: MTD device structure
> - * @buf: buffer to store date
> - * @len: number of bytes to read
> + * @addr: virtual address in RAM of source/destination
> + * @count: number of data bytes to be transferred
> + * @is_write: flag for read/write operation
>   */
> -static void omap_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static
> inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
> +					unsigned int count, int is_write)
>  {
>  	struct omap_nand_info *info = container_of(mtd,
>  					struct omap_nand_info, mtd);
> -	u16 *p = (u16 *) buf;
> +	uint32_t prefetch_status = 0;
> +	enum dma_data_direction dir = is_write ? DMA_TO_DEVICE :
> +							DMA_FROM_DEVICE;
> +	dma_addr_t dma_addr;
> 
> -	len >>= 1;
> +	/* The fifo depth is 64 bytes. We have a sync at each frame and frame +	 *
> length is 64 bytes.
> +	 */
> +	int buf_len = count/64;
> +
> +	dma_addr = dma_map_single(&info->pdev->dev, addr, count, dir);
> +
> +	if (is_write) {
> +	    omap_set_dma_dest_params(info->dma_ch, 0, OMAP_DMA_AMODE_CONSTANT,
> +						info->phys_base, 0, 0);
> +	    omap_set_dma_dest_burst_mode(info->dma_ch, OMAP_DMA_DATA_BURST_16); +	   
> omap_set_dma_src_params(info->dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
> +							dma_addr, 0, 0);
> +	    omap_set_dma_src_burst_mode(info->dma_ch, OMAP_DMA_DATA_BURST_16); +	   
> omap_set_dma_transfer_params(info->dma_ch, OMAP_DMA_DATA_TYPE_S32, +					0x10,
> buf_len, OMAP_DMA_SYNC_FRAME,
> +					OMAP24XX_DMA_GPMC, OMAP_DMA_DST_SYNC);
> +	} else {
> +	    omap_set_dma_src_params(info->dma_ch, 0, OMAP_DMA_AMODE_CONSTANT,
> +						info->phys_base, 0, 0);
> +	    omap_set_dma_src_burst_mode(info->dma_ch, OMAP_DMA_DATA_BURST_16); +	   
> omap_set_dma_dest_params(info->dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
> +							dma_addr, 0, 0);
> +	    omap_set_dma_dest_burst_mode(info->dma_ch, OMAP_DMA_DATA_BURST_16); +	   
> omap_set_dma_transfer_params(info->dma_ch, OMAP_DMA_DATA_TYPE_S32, +					0x10,
> buf_len, OMAP_DMA_SYNC_FRAME,
> +					OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC);
> +	}
> +	/*  configure and start prefetch transfer */
> +	gpmc_prefetch_start(info->gpmc_cs, 0x1, count, is_write);
> +	init_completion(&info->comp);
> +
> +	omap_start_dma(info->dma_ch);
> +
> +	/* setup and start DMA using dma_addr */
> +	wait_for_completion(&info->comp);
> +
> +	while (0x3fff & (prefetch_status = gpmc_prefetch_status()))
> +		;
> +	/* disable and stop the PFPW engine */
> +	gpmc_prefetch_stop();
> +
> +	dma_unmap_single(&info->pdev->dev, dma_addr, count, dir);
> +	return 0;
> +}
> +#else
> +static void omap_nand_dma_cb(int lch, u16 ch_status, void *data) {} +static
> inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
> +					unsigned int count, int is_write)
> +{
> +	return 0;
> +}
> +#endif
> 
> -	while (len--)
> -		*p++ = cpu_to_le16(readw(info->nand.IO_ADDR_R));
> +/*
> + * omap_read_buf16 - read data from NAND controller into buffer
> + * @mtd: MTD device structure
> + * @buf: buffer to store date
> + * @len: number of bytes to read
> + */
> +static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len) +{
> +	struct omap_nand_info *info = container_of(mtd,
> +						struct omap_nand_info, mtd);
> +	u16 *p = (u16 *)buf;
> +
> +	if (use_prefetch) {
> +		uint32_t prefetch_status = 0;
> +		int bytes_to_read = 0;
> +
> +		if ((use_dma && len <= mtd->oobsize) || (!use_dma)) {
> +			if (len % 2 != 0) {
> +				*buf = readb(info->nand.IO_ADDR_R);
> +				p = (u16 *)(buf + 1);
> +				len = len - 1;
> +			}
> +
> +			/* configure and start prefetch transfer */
> +			gpmc_prefetch_start(info->gpmc_cs, 0x0, len, 0x0);
> +
> +			do {
> +				prefetch_status = gpmc_prefetch_status();
> +				bytes_to_read = ((prefetch_status >> 24) &
> +								 0x7F) >> 1;
> +				__raw_readsw(info->nand_pref_fifo_add, p,
> +								bytes_to_read);
> +				p += bytes_to_read;
> +			} while (prefetch_status & 0x3FFF);
> +
> +			/* disable and stop the PFPW engine */
> +			gpmc_prefetch_stop();
> +		} else if (use_dma) {
> +			if (info->dma_ch >= 0)
> +				/* start transfer in DMA mode */
> +				omap_nand_dma_transfer(mtd, p, len, 0x0);
> +		}
> +	} else
> +		__raw_readsl(info->nand.IO_ADDR_R, buf, len >> 1);
>  }
> 
>  /*
> - * omap_write_buf - write buffer to NAND controller
> + * omap_write_buf16 - write buffer to NAND controller
>   * @mtd: MTD device structure
>   * @buf: data buffer
>   * @len: number of bytes to write
>   */
> -static void omap_write_buf(struct mtd_info *mtd, const u_char * buf, int len)
> +static void omap_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
>  {
>  	struct omap_nand_info *info = container_of(mtd,
>  						struct omap_nand_info, mtd);
> -	u16 *p = (u16 *) buf;
> +	u16 *p = (u16 *)buf;
> 
> -	len >>= 1;
> +	if (use_prefetch) {
> +		uint32_t prefetch_status = 0;
> +		int i = 0, bytes_to_write = 0;
> +
> +		if ((use_dma && len <= mtd->oobsize) || (!use_dma)) {
> +			if (len % 2 != 0) {
> +				writeb(*buf, info->nand.IO_ADDR_R);
> +				p = (u16 *)(buf + 1);
> +				len = len - 1;
> +			}
> +
> +			/*  configure and start prefetch transfer */
> +			gpmc_prefetch_start(info->gpmc_cs, 0x0, len, 0x1);
> +
> +			prefetch_status = gpmc_prefetch_status();
> +			while (prefetch_status & 0x3FFF) {
> +				bytes_to_write = ((prefetch_status >> 24) &
> +								0x7F) >> 1;
> +				for (i = 0; (i < bytes_to_write) && len; i++, len -= 2)
> +					__raw_writew(*p++,
> +						info->nand_pref_fifo_add);
> +				prefetch_status = gpmc_prefetch_status();
> +			}
> +
> +			/* disable and stop the PFPW engine */
> +			gpmc_prefetch_stop();
> +		} else if (use_dma) {
> +			if (info->dma_ch >= 0)
> +				/* start transfer in DMA mode */
> +				omap_nand_dma_transfer(mtd, p, len, 0x1);
> +		}
> +	} else {
> +		/* FIXME try bursts of writesw() or DMA ... */
> +		len >>= 1;
> 
> -	while (len--) {
> -		writew(cpu_to_le16(*p++), info->nand.IO_ADDR_W);
> +		while (len--) {
> +			writew(*p++, info->nand.IO_ADDR_W);
> 
> -		while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
> +			while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
>  						GPMC_STATUS) & GPMC_BUF_FULL));
> +		}
>  	}
>  }
> +
>  /*
>   * omap_verify_buf - Verify chip data against buffer
>   * @mtd: MTD device structure
> @@ -471,7 +641,6 @@
>  {
>  	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
>  							mtd);
> -	register struct nand_chip *chip = mtd->priv;
>  	unsigned long val = 0x0;
>  	unsigned long reg;
> 
> @@ -625,11 +794,6 @@
>  		gpmc_cs_write_reg(info->gpmc_cs, GPMC_CS_CONFIG1, val);
>  	}
> 
> -	val  = gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG7);
> -	val &= ~(0xf << 8);
> -	val |=  (0xc & 0xf) << 8;
> -	gpmc_cs_write_reg(info->gpmc_cs, GPMC_CS_CONFIG7, val);
> -
>  	/* NAND write protect off */
>  	omap_nand_wp(&info->mtd, NAND_WP_OFF);
> 
> @@ -644,13 +808,29 @@
>  		err = -ENOMEM;
>  		goto out_release_mem_region;
>  	}
> +	if (use_prefetch) {
> +		/* copy the virtual address of nand base for fifo access */
> +		info->nand_pref_fifo_add = info->nand.IO_ADDR_R;
> +		if (use_dma) {
> +			err = omap_request_dma(OMAP24XX_DMA_GPMC, "NAND",
> +				omap_nand_dma_cb, &info->comp, &info->dma_ch);
> +			if (err < 0) {
> +				info->dma_ch = -1;
> +				printk(KERN_WARNING "DMA request failed."
> +					" Non-dma data transfer mode\n");
> +			}
> +		}
> +	}
>  	info->nand.controller = &info->controller;
> 
>  	info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
>  	info->nand.cmd_ctrl  = omap_hwcontrol;
> 
> -	info->nand.read_buf   = omap_read_buf;
> -	info->nand.write_buf  = omap_write_buf;
> +	/* FIXME: currently 8-bit devices are supported through
> +	 * prefetch only.
> +	 */
> +	info->nand.read_buf   = omap_read_buf16;
> +	info->nand.write_buf  = omap_write_buf16;
>  	info->nand.verify_buf = omap_verify_buf;
> 
>  	/*
> @@ -728,6 +908,8 @@
>  	struct omap_nand_info *info = mtd->priv;
> 
>  	platform_set_drvdata(pdev, NULL);
> +	if (use_dma)
> +		omap_free_dma(info->dma_ch);
>  	/* Release NAND device, its internal structures and partitions */
> nand_release(&info->mtd);
>  	iounmap(info->nand.IO_ADDR_R);
> @@ -748,6 +930,16 @@
>  static int __init omap_nand_init(void)
>  {
>  	printk(KERN_INFO "%s driver initializing\n", DRIVER_NAME);
> +
> +	/* This check is required if driver is being
> +	 * loaded run time as a module
> +	 */
> +	if ((1 == use_dma) && (0 == use_prefetch)) {
> +		printk(KERN_INFO"Wrong parameters: 'use_dma' can not be 1 "
> +				"without use_prefetch'. 'use_dma' will be "
> +				"set to 0\n");
> +		use_dma = 0;
> +	}
>  	return platform_driver_register(&omap_nand_driver);
>  }
> 
> 
> 
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

  reply	other threads:[~2009-01-08 14:16 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-16 11:52 [Resend][PATCH - Omapzoom][NAND] Add prefetch and DMA support vimal singh
2009-01-08 14:16 ` Tony Lindgren [this message]
  -- strict thread matches above, loose matches on Subject: below --
2008-09-16 10:39 vimal singh
2008-09-08 18:03 nskamat
2008-09-08 18:13 ` Russell King - ARM Linux
2008-09-08 22:19   ` David Brownell
2008-09-10 10:47   ` Singh, Vimal

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=20090108141626.GM27566@atomide.com \
    --to=tony@atomide.com \
    --cc=linux-omap@vger.kernel.org \
    --cc=vimalsingh@ti.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.