From: Sahitya Tummala <stummala@codeaurora.org>
To: dwalker@codeaurora.org, linux-arm-msm@vger.kernel.org
Cc: san@google.com, Sahitya Tummala <stummala@codeaurora.org>
Subject: [PATCH] msm: 7x30: Add initial support for SDCC
Date: Fri, 22 Oct 2010 16:37:33 +0530 [thread overview]
Message-ID: <1287745654-19530-1-git-send-email-stummala@codeaurora.org> (raw)
Add platform data and base address for SDCC on MSM7x30. This adds
support for slot 2 and slot 4.
Signed-off-by: Sahitya Tummala <stummala@codeaurora.org>
---
arch/arm/mach-msm/board-msm7x30.c | 218 +++++++++++++++++++++++
arch/arm/mach-msm/devices-msm7x30.c | 196 ++++++++++++++++++++
arch/arm/mach-msm/gpiomux-7x30.c | 103 +++++++++++
arch/arm/mach-msm/include/mach/msm_iomap-7x30.h | 12 ++
4 files changed, 529 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 74abb74..0f1079d 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -22,6 +22,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/smsc911x.h>
+#include <linux/err.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -34,11 +35,225 @@
#include <mach/dma.h>
#include <mach/vreg.h>
+#include <mach/mmc.h>
#include "devices.h"
#include "proc_comm.h"
extern struct sys_timer msm_timer;
+#if defined(CONFIG_MMC_MSM) || defined(CONFIG_MMC_MSM_MODULE)
+struct vreg *vreg_s3;
+struct vreg *vreg_mmc;
+
+struct sdcc_vreg {
+ struct vreg *vreg_data;
+ unsigned level;
+};
+
+static struct sdcc_vreg sdcc_vreg_data[4];
+static unsigned long vreg_sts;
+
+struct sdcc_gpio_data {
+ unsigned no;
+ const char *name;
+};
+
+static struct sdcc_gpio_data sdc2_gpio_cfg[] = {
+ {64, "sdc2_clk"},
+ {65, "sdc2_cmd"},
+ {66, "sdc2_dat_3"},
+ {67, "sdc2_dat_2"},
+ {68, "sdc2_dat_1"},
+ {69, "sdc2_dat_0"}
+};
+
+static struct sdcc_gpio_data sdc3_gpio_cfg[] = {
+ {110, "sdc3_clk"},
+ {111, "sdc3_cmd"},
+ {116, "sdc3_dat_3"},
+ {117, "sdc3_dat_2"},
+ {118, "sdc3_dat_1"},
+ {119, "sdc3_dat_0"},
+};
+
+static struct sdcc_gpio_data sdc4_gpio_cfg[] = {
+ {58, "sdc4_clk"},
+ {59, "sdc4_cmd"},
+ {60, "sdc4_dat_3"},
+ {61, "sdc4_dat_2"},
+ {62, "sdc4_dat_1"},
+ {63, "sdc4_dat_0"}
+};
+
+struct msm_sdcc_gpio {
+ struct sdcc_gpio_data *cfg_data;
+ uint32_t size;
+ uint32_t cfg_sts;
+};
+
+static struct msm_sdcc_gpio sdcc_cfg_data[] = {
+ {
+ .cfg_data = NULL,
+ },
+ {
+ .cfg_data = sdc2_gpio_cfg,
+ .size = ARRAY_SIZE(sdc2_gpio_cfg),
+ },
+ {
+ .cfg_data = sdc3_gpio_cfg,
+ .size = ARRAY_SIZE(sdc3_gpio_cfg),
+ },
+ {
+ .cfg_data = sdc4_gpio_cfg,
+ .size = ARRAY_SIZE(sdc4_gpio_cfg),
+ },
+};
+
+static uint32_t msm_sdcc_setup_gpio(int dev_id, unsigned int enable)
+{
+ int rc = 0;
+ struct msm_sdcc_gpio *curr;
+ int n;
+
+ curr = &sdcc_cfg_data[dev_id - 1];
+
+ if (!curr->cfg_data) {
+ pr_err("%s: gpio config data not defined for slot %d\n",
+ __func__, dev_id);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (curr->cfg_sts == enable)
+ goto out;
+
+ for (n = 0; n < curr->size; n++) {
+ if (enable) {
+ rc = gpio_request(curr->cfg_data[n].no,
+ curr->cfg_data[n].name);
+ if (rc) {
+ pr_err("%s: gpio_request(%d, %s) failed %d\n",
+ __func__, curr->cfg_data[n].no,
+ curr->cfg_data[n].name, rc);
+ goto free_gpios;
+ }
+ /* set direction as output for all GPIOs */
+ rc = gpio_direction_output(curr->cfg_data[n].no, 1);
+ if (rc) {
+ pr_err("%s: gpio_direction_output"
+ "(%d, 1) failed (%d)\n", __func__,
+ curr->cfg_data[n].no, rc);
+ goto free_gpios;
+ }
+ } else {
+ /*
+ * now free this GPIO which will put GPIO
+ * in low power mode and will also put GPIO
+ * in input mode
+ */
+ gpio_free(curr->cfg_data[n].no);
+ }
+ }
+ curr->cfg_sts = enable;
+ goto out;
+
+free_gpios:
+ for (; n >= 0; n--)
+ gpio_free(curr->cfg_data[n].no);
+out:
+ return rc;
+}
+
+static uint32_t msm_sdcc_setup_vreg(int dev_id, unsigned int enable)
+{
+ int rc = 0;
+ struct sdcc_vreg *curr;
+ static int enabled_once[] = {0, 0, 0, 0};
+
+ curr = &sdcc_vreg_data[dev_id - 1];
+
+ if (!(test_bit(dev_id, &vreg_sts)^enable))
+ return rc;
+
+ if (!enable || enabled_once[dev_id - 1])
+ return 0;
+
+ if (enable) {
+ set_bit(dev_id, &vreg_sts);
+ rc = vreg_set_level(curr->vreg_data, curr->level);
+ if (rc) {
+ printk(KERN_ERR "%s: vreg_set_level() = %d\n",
+ __func__, rc);
+ }
+ rc = vreg_enable(curr->vreg_data);
+ if (rc) {
+ printk(KERN_ERR "%s: vreg_enable() = %d\n",
+ __func__, rc);
+ }
+ enabled_once[dev_id - 1] = 1;
+ } else {
+ clear_bit(dev_id, &vreg_sts);
+ rc = vreg_disable(curr->vreg_data);
+ if (rc) {
+ printk(KERN_ERR "%s: vreg_disable() = %d\n",
+ __func__, rc);
+ }
+ }
+ return rc;
+}
+
+static uint32_t msm_sdcc_setup_power(struct device *dv, unsigned int vdd)
+{
+ int rc = 0;
+ struct platform_device *pdev;
+
+ pdev = container_of(dv, struct platform_device, dev);
+ rc = msm_sdcc_setup_gpio(pdev->id, (vdd ? 1 : 0));
+ if (rc)
+ goto out;
+
+ if (pdev->id == 4) /* S3 is always ON and cannot be disabled */
+ rc = msm_sdcc_setup_vreg(pdev->id, (vdd ? 1 : 0));
+out:
+ return rc;
+}
+
+static struct msm_mmc_platform_data msm7x30_sdc2_data = {
+ .ocr_mask = MMC_VDD_165_195 | MMC_VDD_27_28,
+ .translate_vdd = msm_sdcc_setup_power,
+};
+
+static struct msm_mmc_platform_data msm7x30_sdc4_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
+ .translate_vdd = msm_sdcc_setup_power,
+};
+
+static void __init msm7x30_init_mmc(void)
+{
+ vreg_s3 = vreg_get(NULL, "s3");
+ if (IS_ERR(vreg_s3)) {
+ printk(KERN_ERR "%s: vreg get failed (%ld)\n",
+ __func__, PTR_ERR(vreg_s3));
+ return;
+ }
+
+ vreg_mmc = vreg_get(NULL, "mmc");
+ if (IS_ERR(vreg_mmc)) {
+ printk(KERN_ERR "%s: vreg get failed (%ld)\n",
+ __func__, PTR_ERR(vreg_mmc));
+ return;
+ }
+
+ sdcc_vreg_data[1].vreg_data = vreg_s3;
+ sdcc_vreg_data[1].level = 1800;
+ msm_add_sdcc(2, &msm7x30_sdc2_data, 0, 0);
+
+ sdcc_vreg_data[3].vreg_data = vreg_mmc;
+ sdcc_vreg_data[3].level = 2850;
+ msm_add_sdcc(4, &msm7x30_sdc4_data, 0, 0);
+}
+#endif
+
static struct platform_device *devices[] __initdata = {
#if defined(CONFIG_SERIAL_MSM) || defined(CONFIG_MSM_SERIAL_DEBUGGER)
&msm_device_uart2,
@@ -54,6 +269,9 @@ static void __init msm7x30_init_irq(void)
static void __init msm7x30_init(void)
{
platform_add_devices(devices, ARRAY_SIZE(devices));
+#if defined(CONFIG_MMC_MSM) || defined(CONFIG_MMC_MSM_MODULE)
+ msm7x30_init_mmc();
+#endif
}
static void __init msm7x30_map_io(void)
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index b449e8a..945aa24 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -51,6 +51,194 @@ struct platform_device msm_device_uart2 = {
.resource = resources_uart2,
};
+static struct resource resources_sdc1[] = {
+ {
+ .start = MSM_SDC1_PHYS,
+ .end = MSM_SDC1_PHYS + MSM_SDC1_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_SDC1_0,
+ .end = INT_SDC1_0,
+ .flags = IORESOURCE_IRQ,
+ .name = "cmd_irq",
+ },
+ {
+ .start = INT_SDC1_1,
+ .end = INT_SDC1_1,
+ .flags = IORESOURCE_IRQ,
+ .name = "pio_irq",
+ },
+ {
+ .flags = IORESOURCE_IRQ | IORESOURCE_DISABLED,
+ .name = "status_irq"
+ },
+ {
+ .start = 8,
+ .end = 8,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct resource resources_sdc2[] = {
+ {
+ .start = MSM_SDC2_PHYS,
+ .end = MSM_SDC2_PHYS + MSM_SDC2_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_SDC2_0,
+ .end = INT_SDC2_0,
+ .flags = IORESOURCE_IRQ,
+ .name = "cmd_irq",
+ },
+ {
+ .start = INT_SDC2_1,
+ .end = INT_SDC2_1,
+ .flags = IORESOURCE_IRQ,
+ .name = "pio_irq",
+ },
+ {
+ .flags = IORESOURCE_IRQ | IORESOURCE_DISABLED,
+ .name = "status_irq"
+ },
+ {
+ .start = 8,
+ .end = 8,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct resource resources_sdc3[] = {
+ {
+ .start = MSM_SDC3_PHYS,
+ .end = MSM_SDC3_PHYS + MSM_SDC3_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_SDC3_0,
+ .end = INT_SDC3_0,
+ .flags = IORESOURCE_IRQ,
+ .name = "cmd_irq",
+ },
+ {
+ .start = INT_SDC3_1,
+ .end = INT_SDC3_1,
+ .flags = IORESOURCE_IRQ,
+ .name = "pio_irq",
+ },
+ {
+ .flags = IORESOURCE_IRQ | IORESOURCE_DISABLED,
+ .name = "status_irq"
+ },
+ {
+ .start = 8,
+ .end = 8,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct resource resources_sdc4[] = {
+ {
+ .start = MSM_SDC4_PHYS,
+ .end = MSM_SDC4_PHYS + MSM_SDC4_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_SDC4_0,
+ .end = INT_SDC4_0,
+ .flags = IORESOURCE_IRQ,
+ .name = "cmd_irq",
+ },
+ {
+ .start = INT_SDC4_1,
+ .end = INT_SDC4_1,
+ .flags = IORESOURCE_IRQ,
+ .name = "pio_irq",
+ },
+ {
+ .flags = IORESOURCE_IRQ | IORESOURCE_DISABLED,
+ .name = "status_irq"
+ },
+ {
+ .start = 8,
+ .end = 8,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+struct platform_device msm_device_sdc1 = {
+ .name = "msm_sdcc",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(resources_sdc1),
+ .resource = resources_sdc1,
+ .dev = {
+ .coherent_dma_mask = 0xffffffff,
+ },
+};
+
+struct platform_device msm_device_sdc2 = {
+ .name = "msm_sdcc",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(resources_sdc2),
+ .resource = resources_sdc2,
+ .dev = {
+ .coherent_dma_mask = 0xffffffff,
+ },
+};
+
+struct platform_device msm_device_sdc3 = {
+ .name = "msm_sdcc",
+ .id = 3,
+ .num_resources = ARRAY_SIZE(resources_sdc3),
+ .resource = resources_sdc3,
+ .dev = {
+ .coherent_dma_mask = 0xffffffff,
+ },
+};
+
+struct platform_device msm_device_sdc4 = {
+ .name = "msm_sdcc",
+ .id = 4,
+ .num_resources = ARRAY_SIZE(resources_sdc4),
+ .resource = resources_sdc4,
+ .dev = {
+ .coherent_dma_mask = 0xffffffff,
+ },
+};
+
+static struct platform_device *msm_sdcc_devices[] __initdata = {
+ &msm_device_sdc1,
+ &msm_device_sdc2,
+ &msm_device_sdc3,
+ &msm_device_sdc4,
+};
+
+int __init msm_add_sdcc(unsigned int controller,
+ struct msm_mmc_platform_data *plat,
+ unsigned int stat_irq, unsigned long stat_irq_flags)
+{
+ struct platform_device *pdev;
+ struct resource *res;
+
+ if (controller < 1 || controller > 4)
+ return -EINVAL;
+
+ pdev = msm_sdcc_devices[controller-1];
+ pdev->dev.platform_data = plat;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "status_irq");
+ if (!res)
+ return -EINVAL;
+ else if (stat_irq) {
+ res->start = res->end = stat_irq;
+ res->flags &= ~IORESOURCE_DISABLED;
+ res->flags |= stat_irq_flags;
+ }
+
+ return platform_device_register(pdev);
+}
+
struct clk msm_clocks_7x30[] = {
CLK_PCOM("adm_clk", ADM_CLK, NULL, 0),
CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0),
@@ -117,6 +305,14 @@ struct clk msm_clocks_7x30[] = {
CLK_PCOM("vfe_mdc_clk", VFE_MDC_CLK, NULL, 0),
CLK_PCOM("vfe_pclk", VFE_P_CLK, NULL, OFF),
CLK_PCOM("vpe_clk", VPE_CLK, NULL, 0),
+ CLK_PCOM("sdc_clk", SDC1_CLK, &msm_device_sdc1.dev, OFF),
+ CLK_PCOM("sdc_pclk", SDC1_P_CLK, &msm_device_sdc1.dev, OFF),
+ CLK_PCOM("sdc_clk", SDC2_CLK, &msm_device_sdc2.dev, OFF),
+ CLK_PCOM("sdc_pclk", SDC2_P_CLK, &msm_device_sdc2.dev, OFF),
+ CLK_PCOM("sdc_clk", SDC3_CLK, &msm_device_sdc3.dev, OFF),
+ CLK_PCOM("sdc_pclk", SDC3_P_CLK, &msm_device_sdc3.dev, OFF),
+ CLK_PCOM("sdc_clk", SDC4_CLK, &msm_device_sdc4.dev, OFF),
+ CLK_PCOM("sdc_pclk", SDC4_P_CLK, &msm_device_sdc4.dev, OFF),
/* 7x30 v2 hardware only. */
CLK_PCOM("csi_clk", CSI0_CLK, NULL, 0),
diff --git a/arch/arm/mach-msm/gpiomux-7x30.c b/arch/arm/mach-msm/gpiomux-7x30.c
index 6ce41c5..97d13ab 100644
--- a/arch/arm/mach-msm/gpiomux-7x30.c
+++ b/arch/arm/mach-msm/gpiomux-7x30.c
@@ -16,6 +16,19 @@
*/
#include "gpiomux.h"
+#if defined(CONFIG_MMC_MSM) || defined(CONFIG_MMC_MSM_MODULE)
+ #define SDCC_DAT_0_3_CMD_ACTV_CFG (GPIOMUX_VALID | GPIOMUX_PULL_UP\
+ | GPIOMUX_FUNC_1 | GPIOMUX_DRV_8MA)
+ #define SDCC_CLK_ACTV_CFG (GPIOMUX_VALID | GPIOMUX_PULL_NONE\
+ | GPIOMUX_FUNC_1 | GPIOMUX_DRV_16MA)
+#else
+ #define SDCC_DAT_0_3_CMD_ACTV_CFG 0
+ #define SDCC_CLK_ACTV_CFG 0
+#endif
+
+#define SDCC_SUSPEND_CONFIG (GPIOMUX_VALID | GPIOMUX_PULL_NONE\
+ | GPIOMUX_FUNC_GPIO | GPIOMUX_DRV_2MA)
+
struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
#ifdef CONFIG_SERIAL_MSM_CONSOLE
[49] = { /* UART2 RFR */
@@ -35,4 +48,94 @@ struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
GPIOMUX_FUNC_2 | GPIOMUX_VALID,
},
#endif
+ /* SDC2 CLK */
+ [64] = {
+ .active = SDCC_CLK_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC2 CMD */
+ [65] = {
+ .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC2 data[3] */
+ [66] = {
+ .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC2 data[2] */
+ [67] = {
+ .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC2 data[1] */
+ [68] = {
+ .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC2 data[0] */
+ [69] = {
+ .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC3 CLK */
+ [110] = {
+ .active = SDCC_CLK_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC3 CMD */
+ [111] = {
+ .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC3 data[3] */
+ [116] = {
+ .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC3 data[2] */
+ [117] = {
+ .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC3 data[1] */
+ [118] = {
+ .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC3 data[0] */
+ [119] = {
+ .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC4 CLK */
+ [58] = {
+ .active = SDCC_CLK_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC4 CMD */
+ [59] = {
+ .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC4 data[3] */
+ [60] = {
+ .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC4 data[2] */
+ [61] = {
+ .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC4 data[1] */
+ [62] = {
+ .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
+ /* SDC4 data[0] */
+ [63] = {
+ .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+ .suspended = SDCC_SUSPEND_CONFIG
+ },
};
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
index 8a00c2d..361e7d9 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
@@ -119,4 +119,16 @@
#define MSM_AD5_PHYS 0xA7000000
#define MSM_AD5_SIZE (SZ_1M*13)
+#define MSM_SDC1_PHYS 0xA0400000
+#define MSM_SDC1_SIZE SZ_4K
+
+#define MSM_SDC2_PHYS 0xA0500000
+#define MSM_SDC2_SIZE SZ_4K
+
+#define MSM_SDC3_PHYS 0xA3000000
+#define MSM_SDC3_SIZE SZ_4K
+
+#define MSM_SDC4_PHYS 0xA3100000
+#define MSM_SDC4_SIZE SZ_4K
+
#endif
--
1.7.1
--
Consultant for Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum.
next reply other threads:[~2010-10-22 11:07 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-10-22 11:07 Sahitya Tummala [this message]
2010-10-22 11:07 ` [PATCH] msm: 8x50: Add initial support for SDCC Sahitya Tummala
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=1287745654-19530-1-git-send-email-stummala@codeaurora.org \
--to=stummala@codeaurora.org \
--cc=dwalker@codeaurora.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=san@google.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.