From: Eugeniy Paltsev <eugeniy.paltsev@synopsys.com>
To: "linux-mtd@lists.infradead.org" <linux-mtd@lists.infradead.org>
Cc: "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"linux-snps-arc@lists.infradead.org"
<linux-snps-arc@lists.infradead.org>,
Alexey Brodkin <alexey.brodkin@synopsys.com>,
"boris.brezillon@bootlin.com" <boris.brezillon@bootlin.com>,
Vineet Gupta <vineet.gupta1@synopsys.com>,
"dwmw2@infradead.org" <dwmw2@infradead.org>,
"computersforpeace@gmail.com" <computersforpeace@gmail.com>,
"marek.vasut@gmail.com" <marek.vasut@gmail.com>,
"richard@nod.at" <richard@nod.at>
Subject: Re: [PATCH v2 1/2] mtd: spi-nor: Add support of sst26wf* flash ICs protection ops
Date: Mon, 15 Oct 2018 14:21:18 +0000 [thread overview]
Message-ID: <1539613276.4199.9.camel@synopsys.com> (raw)
In-Reply-To: <20180910114628.19156-2-Eugeniy.Paltsev@synopsys.com>
Hi!
Maybe you have any comments or remarks about this patch?
And if you don't could you please apply it. Thanks!
On Mon, 2018-09-10 at 14:46 +0300, Eugeniy Paltsev wrote:
> sst26wf flash series block protection implementation differs
> from other SST series, so add specific implementation
> flash_lock/flash_unlock/flash_is_locked functions for sst26wf
> flash ICs.
>
> NOTE:
> this patch is basically following mine u-boot commit port:
> http://git.denx.de/?p=u-boot.git;a=commitdiff;h=3d4fed87a5fa3ffedf64ff2811cd95c5ac4503ac
>
> Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
> ---
> Changes v1->v2:
> * Check return value of {read | write}_reg callbacks.
>
> drivers/mtd/spi-nor/spi-nor.c | 177 ++++++++++++++++++++++++++++++++++++++++++
> include/linux/mtd/spi-nor.h | 4 +
> 2 files changed, 181 insertions(+)
>
> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
> index d9c368c44194..d0e7c85b6002 100644
> --- a/drivers/mtd/spi-nor/spi-nor.c
> +++ b/drivers/mtd/spi-nor/spi-nor.c
> @@ -598,6 +598,177 @@ static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask)
> return ((ret & mask) != (status_new & mask)) ? -EIO : 0;
> }
>
> +/*
> + * sst26wf016/sst26wf032/sst26wf064 have next block protection:
> + * 4x - 8 KByte blocks - read & write protection bits - upper addresses
> + * 1x - 32 KByte blocks - write protection bits
> + * rest - 64 KByte blocks - write protection bits
> + * 1x - 32 KByte blocks - write protection bits
> + * 4x - 8 KByte blocks - read & write protection bits - lower addresses
> + *
> + * We'll support only per 64k lock/unlock so lower and upper 64 KByte region
> + * will be treated as single block.
> + */
> +#define SST26_BPR_8K_NUM 4
> +#define SST26_MAX_BPR_REG_LEN (18 + 1)
> +#define SST26_BOUND_REG_SIZE ((32 + SST26_BPR_8K_NUM * 8) * SZ_1K)
> +
> +enum lock_ctl {
> + SST26_CTL_LOCK,
> + SST26_CTL_UNLOCK,
> + SST26_CTL_CHECK
> +};
> +
> +static bool sst26_process_bpr(u32 bpr_size, u8 *cmd, u32 bit, enum lock_ctl ctl)
> +{
> + switch (ctl) {
> + case SST26_CTL_LOCK:
> + cmd[bpr_size - (bit / 8) - 1] |= BIT(bit % 8);
> + break;
> + case SST26_CTL_UNLOCK:
> + cmd[bpr_size - (bit / 8) - 1] &= ~BIT(bit % 8);
> + break;
> + case SST26_CTL_CHECK:
> + return !!(cmd[bpr_size - (bit / 8) - 1] & BIT(bit % 8));
> + }
> +
> + return false;
> +}
> +
> +/*
> + * Lock, unlock or check lock status of the flash region of the flash (depending
> + * on the lock_ctl value)
> + */
> +static int sst26_lock_ctl(struct spi_nor *nor, loff_t ofs, uint64_t len, enum lock_ctl ctl)
> +{
> + struct mtd_info *mtd = &nor->mtd;
> + u32 i, bpr_ptr, rptr_64k, lptr_64k, bpr_size;
> + bool lower_64k = false, upper_64k = false;
> + u8 bpr_buff[SST26_MAX_BPR_REG_LEN] = {};
> + int ret;
> +
> + /* Check length and offset for 64k alignment */
> + if ((ofs & (SZ_64K - 1)) || (len & (SZ_64K - 1))) {
> + dev_err(nor->dev, "length or offset is not 64KiB allighned\n");
> + return -EINVAL;
> + }
> +
> + if (ofs + len > mtd->size) {
> + dev_err(nor->dev, "range is more than device size: %#llx + %#llx > %#llx\n",
> + ofs, len, mtd->size);
> + return -EINVAL;
> + }
> +
> + /* SST26 family has only 16 Mbit, 32 Mbit and 64 Mbit IC */
> + if (mtd->size != SZ_2M &&
> + mtd->size != SZ_4M &&
> + mtd->size != SZ_8M)
> + return -EINVAL;
> +
> + bpr_size = 2 + (mtd->size / SZ_64K / 8);
> +
> + ret = nor->read_reg(nor, SPINOR_OP_READ_BPR, bpr_buff, bpr_size);
> + if (ret < 0) {
> + dev_err(nor->dev, "fail to read block-protection register\n");
> + return ret;
> + }
> +
> + rptr_64k = min_t(u32, ofs + len, mtd->size - SST26_BOUND_REG_SIZE);
> + lptr_64k = max_t(u32, ofs, SST26_BOUND_REG_SIZE);
> +
> + upper_64k = ((ofs + len) > (mtd->size - SST26_BOUND_REG_SIZE));
> + lower_64k = (ofs < SST26_BOUND_REG_SIZE);
> +
> + /* Lower bits in block-protection register are about 64k region */
> + bpr_ptr = lptr_64k / SZ_64K - 1;
> +
> + /* Process 64K blocks region */
> + while (lptr_64k < rptr_64k) {
> + if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
> + return EACCES;
> +
> + bpr_ptr++;
> + lptr_64k += SZ_64K;
> + }
> +
> + /* 32K and 8K region bits in BPR are after 64k region bits */
> + bpr_ptr = (mtd->size - 2 * SST26_BOUND_REG_SIZE) / SZ_64K;
> +
> + /* Process lower 32K block region */
> + if (lower_64k)
> + if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
> + return EACCES;
> +
> + bpr_ptr++;
> +
> + /* Process upper 32K block region */
> + if (upper_64k)
> + if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
> + return EACCES;
> +
> + bpr_ptr++;
> +
> + /* Process lower 8K block regions */
> + for (i = 0; i < SST26_BPR_8K_NUM; i++) {
> + if (lower_64k)
> + if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
> + return EACCES;
> +
> + /* In 8K area BPR has both read and write protection bits */
> + bpr_ptr += 2;
> + }
> +
> + /* Process upper 8K block regions */
> + for (i = 0; i < SST26_BPR_8K_NUM; i++) {
> + if (upper_64k)
> + if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
> + return EACCES;
> +
> + /* In 8K area BPR has both read and write protection bits */
> + bpr_ptr += 2;
> + }
> +
> + /* If we check region status we don't need to write BPR back */
> + if (ctl == SST26_CTL_CHECK)
> + return 0;
> +
> + ret = nor->write_reg(nor, SPINOR_OP_WRITE_BPR, bpr_buff, bpr_size);
> + if (ret < 0) {
> + dev_err(nor->dev, "fail to write block-protection register\n");
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int sst26_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
> +{
> + return sst26_lock_ctl(nor, ofs, len, SST26_CTL_UNLOCK);
> +}
> +
> +static int sst26_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
> +{
> + return sst26_lock_ctl(nor, ofs, len, SST26_CTL_LOCK);
> +}
> +
> +/*
> + * Returns EACCES (positive value) if region is locked, 0 if region is unlocked,
> + * and negative on errors.
> + */
> +static int sst26_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len)
> +{
> + /*
> + * is_locked function is used for check before reading or erasing flash
> + * region, so offset and length might be not 64k allighned, so adjust
> + * them to be 64k allighned as sst26_lock_ctl works only with 64k
> + * allighned regions.
> + */
> + ofs -= ofs & (SZ_64K - 1);
> + len = len & (SZ_64K - 1) ? (len & ~(SZ_64K - 1)) + SZ_64K : len;
> +
> + return sst26_lock_ctl(nor, ofs, len, SST26_CTL_CHECK);
> +}
> +
> static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs,
> uint64_t *len)
> {
> @@ -2872,6 +3043,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
> nor->flash_is_locked = stm_is_locked;
> }
>
> + if (JEDEC_MFR(info) == SNOR_MFR_SST && info->id[1] == 0x26) {
> + nor->flash_lock = sst26_lock;
> + nor->flash_unlock = sst26_unlock;
> + nor->flash_is_locked = sst26_is_locked;
> + }
> +
> if (nor->flash_lock && nor->flash_unlock && nor->flash_is_locked) {
> mtd->_lock = spi_nor_lock;
> mtd->_unlock = spi_nor_unlock;
> diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
> index e60da0d34cc1..246014a73f83 100644
> --- a/include/linux/mtd/spi-nor.h
> +++ b/include/linux/mtd/spi-nor.h
> @@ -93,6 +93,10 @@
> #define SPINOR_OP_WRDI 0x04 /* Write disable */
> #define SPINOR_OP_AAI_WP 0xad /* Auto address increment word program */
>
> +/* Used for SST26* flashes only. */
> +#define SPINOR_OP_READ_BPR 0x72 /* Read block protection register */
> +#define SPINOR_OP_WRITE_BPR 0x42 /* Write block protection register */
> +
> /* Used for S3AN flashes only */
> #define SPINOR_OP_XSE 0x50 /* Sector erase */
> #define SPINOR_OP_XPP 0x82 /* Page program */
--
Eugeniy Paltsev
WARNING: multiple messages have this Message-ID (diff)
From: eugeniy.paltsev@synopsys.com (Eugeniy Paltsev)
To: linux-snps-arc@lists.infradead.org
Subject: [PATCH v2 1/2] mtd: spi-nor: Add support of sst26wf* flash ICs protection ops
Date: Mon, 15 Oct 2018 14:21:18 +0000 [thread overview]
Message-ID: <1539613276.4199.9.camel@synopsys.com> (raw)
In-Reply-To: <20180910114628.19156-2-Eugeniy.Paltsev@synopsys.com>
Hi!
Maybe you have any comments or remarks about this patch?
And if you don't could you please apply it. Thanks!
On Mon, 2018-09-10@14:46 +0300, Eugeniy Paltsev wrote:
> sst26wf flash series block protection implementation differs
> from other SST series, so add specific implementation
> flash_lock/flash_unlock/flash_is_locked functions for sst26wf
> flash ICs.
>
> NOTE:
> this patch is basically following mine u-boot commit port:
> http://git.denx.de/?p=u-boot.git;a=commitdiff;h=3d4fed87a5fa3ffedf64ff2811cd95c5ac4503ac
>
> Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev at synopsys.com>
> ---
> Changes v1->v2:
> * Check return value of {read | write}_reg callbacks.
>
> drivers/mtd/spi-nor/spi-nor.c | 177 ++++++++++++++++++++++++++++++++++++++++++
> include/linux/mtd/spi-nor.h | 4 +
> 2 files changed, 181 insertions(+)
>
> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
> index d9c368c44194..d0e7c85b6002 100644
> --- a/drivers/mtd/spi-nor/spi-nor.c
> +++ b/drivers/mtd/spi-nor/spi-nor.c
> @@ -598,6 +598,177 @@ static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask)
> return ((ret & mask) != (status_new & mask)) ? -EIO : 0;
> }
>
> +/*
> + * sst26wf016/sst26wf032/sst26wf064 have next block protection:
> + * 4x - 8 KByte blocks - read & write protection bits - upper addresses
> + * 1x - 32 KByte blocks - write protection bits
> + * rest - 64 KByte blocks - write protection bits
> + * 1x - 32 KByte blocks - write protection bits
> + * 4x - 8 KByte blocks - read & write protection bits - lower addresses
> + *
> + * We'll support only per 64k lock/unlock so lower and upper 64 KByte region
> + * will be treated as single block.
> + */
> +#define SST26_BPR_8K_NUM 4
> +#define SST26_MAX_BPR_REG_LEN (18 + 1)
> +#define SST26_BOUND_REG_SIZE ((32 + SST26_BPR_8K_NUM * 8) * SZ_1K)
> +
> +enum lock_ctl {
> + SST26_CTL_LOCK,
> + SST26_CTL_UNLOCK,
> + SST26_CTL_CHECK
> +};
> +
> +static bool sst26_process_bpr(u32 bpr_size, u8 *cmd, u32 bit, enum lock_ctl ctl)
> +{
> + switch (ctl) {
> + case SST26_CTL_LOCK:
> + cmd[bpr_size - (bit / 8) - 1] |= BIT(bit % 8);
> + break;
> + case SST26_CTL_UNLOCK:
> + cmd[bpr_size - (bit / 8) - 1] &= ~BIT(bit % 8);
> + break;
> + case SST26_CTL_CHECK:
> + return !!(cmd[bpr_size - (bit / 8) - 1] & BIT(bit % 8));
> + }
> +
> + return false;
> +}
> +
> +/*
> + * Lock, unlock or check lock status of the flash region of the flash (depending
> + * on the lock_ctl value)
> + */
> +static int sst26_lock_ctl(struct spi_nor *nor, loff_t ofs, uint64_t len, enum lock_ctl ctl)
> +{
> + struct mtd_info *mtd = &nor->mtd;
> + u32 i, bpr_ptr, rptr_64k, lptr_64k, bpr_size;
> + bool lower_64k = false, upper_64k = false;
> + u8 bpr_buff[SST26_MAX_BPR_REG_LEN] = {};
> + int ret;
> +
> + /* Check length and offset for 64k alignment */
> + if ((ofs & (SZ_64K - 1)) || (len & (SZ_64K - 1))) {
> + dev_err(nor->dev, "length or offset is not 64KiB allighned\n");
> + return -EINVAL;
> + }
> +
> + if (ofs + len > mtd->size) {
> + dev_err(nor->dev, "range is more than device size: %#llx + %#llx > %#llx\n",
> + ofs, len, mtd->size);
> + return -EINVAL;
> + }
> +
> + /* SST26 family has only 16 Mbit, 32 Mbit and 64 Mbit IC */
> + if (mtd->size != SZ_2M &&
> + mtd->size != SZ_4M &&
> + mtd->size != SZ_8M)
> + return -EINVAL;
> +
> + bpr_size = 2 + (mtd->size / SZ_64K / 8);
> +
> + ret = nor->read_reg(nor, SPINOR_OP_READ_BPR, bpr_buff, bpr_size);
> + if (ret < 0) {
> + dev_err(nor->dev, "fail to read block-protection register\n");
> + return ret;
> + }
> +
> + rptr_64k = min_t(u32, ofs + len, mtd->size - SST26_BOUND_REG_SIZE);
> + lptr_64k = max_t(u32, ofs, SST26_BOUND_REG_SIZE);
> +
> + upper_64k = ((ofs + len) > (mtd->size - SST26_BOUND_REG_SIZE));
> + lower_64k = (ofs < SST26_BOUND_REG_SIZE);
> +
> + /* Lower bits in block-protection register are about 64k region */
> + bpr_ptr = lptr_64k / SZ_64K - 1;
> +
> + /* Process 64K blocks region */
> + while (lptr_64k < rptr_64k) {
> + if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
> + return EACCES;
> +
> + bpr_ptr++;
> + lptr_64k += SZ_64K;
> + }
> +
> + /* 32K and 8K region bits in BPR are after 64k region bits */
> + bpr_ptr = (mtd->size - 2 * SST26_BOUND_REG_SIZE) / SZ_64K;
> +
> + /* Process lower 32K block region */
> + if (lower_64k)
> + if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
> + return EACCES;
> +
> + bpr_ptr++;
> +
> + /* Process upper 32K block region */
> + if (upper_64k)
> + if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
> + return EACCES;
> +
> + bpr_ptr++;
> +
> + /* Process lower 8K block regions */
> + for (i = 0; i < SST26_BPR_8K_NUM; i++) {
> + if (lower_64k)
> + if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
> + return EACCES;
> +
> + /* In 8K area BPR has both read and write protection bits */
> + bpr_ptr += 2;
> + }
> +
> + /* Process upper 8K block regions */
> + for (i = 0; i < SST26_BPR_8K_NUM; i++) {
> + if (upper_64k)
> + if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl))
> + return EACCES;
> +
> + /* In 8K area BPR has both read and write protection bits */
> + bpr_ptr += 2;
> + }
> +
> + /* If we check region status we don't need to write BPR back */
> + if (ctl == SST26_CTL_CHECK)
> + return 0;
> +
> + ret = nor->write_reg(nor, SPINOR_OP_WRITE_BPR, bpr_buff, bpr_size);
> + if (ret < 0) {
> + dev_err(nor->dev, "fail to write block-protection register\n");
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int sst26_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
> +{
> + return sst26_lock_ctl(nor, ofs, len, SST26_CTL_UNLOCK);
> +}
> +
> +static int sst26_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
> +{
> + return sst26_lock_ctl(nor, ofs, len, SST26_CTL_LOCK);
> +}
> +
> +/*
> + * Returns EACCES (positive value) if region is locked, 0 if region is unlocked,
> + * and negative on errors.
> + */
> +static int sst26_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len)
> +{
> + /*
> + * is_locked function is used for check before reading or erasing flash
> + * region, so offset and length might be not 64k allighned, so adjust
> + * them to be 64k allighned as sst26_lock_ctl works only with 64k
> + * allighned regions.
> + */
> + ofs -= ofs & (SZ_64K - 1);
> + len = len & (SZ_64K - 1) ? (len & ~(SZ_64K - 1)) + SZ_64K : len;
> +
> + return sst26_lock_ctl(nor, ofs, len, SST26_CTL_CHECK);
> +}
> +
> static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs,
> uint64_t *len)
> {
> @@ -2872,6 +3043,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
> nor->flash_is_locked = stm_is_locked;
> }
>
> + if (JEDEC_MFR(info) == SNOR_MFR_SST && info->id[1] == 0x26) {
> + nor->flash_lock = sst26_lock;
> + nor->flash_unlock = sst26_unlock;
> + nor->flash_is_locked = sst26_is_locked;
> + }
> +
> if (nor->flash_lock && nor->flash_unlock && nor->flash_is_locked) {
> mtd->_lock = spi_nor_lock;
> mtd->_unlock = spi_nor_unlock;
> diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
> index e60da0d34cc1..246014a73f83 100644
> --- a/include/linux/mtd/spi-nor.h
> +++ b/include/linux/mtd/spi-nor.h
> @@ -93,6 +93,10 @@
> #define SPINOR_OP_WRDI 0x04 /* Write disable */
> #define SPINOR_OP_AAI_WP 0xad /* Auto address increment word program */
>
> +/* Used for SST26* flashes only. */
> +#define SPINOR_OP_READ_BPR 0x72 /* Read block protection register */
> +#define SPINOR_OP_WRITE_BPR 0x42 /* Write block protection register */
> +
> /* Used for S3AN flashes only */
> #define SPINOR_OP_XSE 0x50 /* Sector erase */
> #define SPINOR_OP_XPP 0x82 /* Page program */
--
Eugeniy Paltsev
next prev parent reply other threads:[~2018-10-15 14:21 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-09-10 11:46 [PATCH v2 0/2] MTD: spi-nor: add support for sst26wf016, sst26wf032 Eugeniy Paltsev
2018-09-10 11:46 ` Eugeniy Paltsev
2018-09-10 11:46 ` [PATCH v2 1/2] mtd: spi-nor: Add support of sst26wf* flash ICs protection ops Eugeniy Paltsev
2018-09-10 11:46 ` Eugeniy Paltsev
2018-09-24 9:55 ` Eugeniy Paltsev
2018-09-24 9:55 ` Eugeniy Paltsev
2018-10-15 14:21 ` Eugeniy Paltsev [this message]
2018-10-15 14:21 ` Eugeniy Paltsev
2018-11-28 13:17 ` Tudor.Ambarus
2018-11-28 13:17 ` Tudor.Ambarus
2018-10-22 13:46 ` Eugeniy Paltsev
2018-10-22 13:46 ` Eugeniy Paltsev
2018-09-10 11:46 ` [PATCH v2 2/2] mtd: spi-nor: add support for sst26wf016, sst26wf032 Eugeniy Paltsev
2018-09-10 11:46 ` Eugeniy Paltsev
2018-10-22 13:47 ` [PATCH v2 0/2] MTD: " Eugeniy Paltsev
2018-10-22 13:47 ` Eugeniy Paltsev
2018-10-22 13:56 ` Boris Brezillon
2018-10-22 13:56 ` Boris Brezillon
2018-11-19 15:25 ` Eugeniy Paltsev
2018-11-19 15:25 ` Eugeniy Paltsev
2018-11-22 17:45 ` Tudor.Ambarus
2018-11-22 17:45 ` Tudor.Ambarus
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=1539613276.4199.9.camel@synopsys.com \
--to=eugeniy.paltsev@synopsys.com \
--cc=alexey.brodkin@synopsys.com \
--cc=boris.brezillon@bootlin.com \
--cc=computersforpeace@gmail.com \
--cc=dwmw2@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
--cc=linux-snps-arc@lists.infradead.org \
--cc=marek.vasut@gmail.com \
--cc=richard@nod.at \
--cc=vineet.gupta1@synopsys.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.