From: Andrew Baumann <Andrew.Baumann@microsoft.com>
To: qemu-devel@nongnu.org
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
"Grégory ESTRADE" <gregory.estrade@gmail.com>,
"Stefan Weil" <sw@weilnetz.de>,
"Peter Crosthwaite" <crosthwaite.peter@gmail.com>,
"Andrew Baumann" <Andrew.Baumann@microsoft.com>,
qemu-arm@nongnu.org, "Paolo Bonzini" <pbonzini@redhat.com>,
"Rob Herring" <robh@kernel.org>
Subject: [Qemu-devel] [PATCH v4 4/8] bcm2835_peripherals: add rollup device for bcm2835 peripherals
Date: Fri, 15 Jan 2016 15:58:53 -0800 [thread overview]
Message-ID: <1452902337-13844-5-git-send-email-Andrew.Baumann@microsoft.com> (raw)
In-Reply-To: <1452902337-13844-1-git-send-email-Andrew.Baumann@microsoft.com>
This device maintains all the non-CPU peripherals on bcm2835 (Pi1)
which are also present on bcm2836 (Pi2). It also implements the
private address spaces used for DMA and mailboxes.
Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
---
Notes:
v3:
* clean up raspi_platform.h
* s/_/-/ in type/property/child names
* use memory_region_init where appropriate rather than memory_region_init_io
* pass ram as link property
v2:
* adapted to use common SDHCI emulation
hw/arm/Makefile.objs | 1 +
hw/arm/bcm2835_peripherals.c | 205 +++++++++++++++++++++++++++++++++++
include/hw/arm/bcm2835_peripherals.h | 42 +++++++
include/hw/arm/raspi_platform.h | 128 ++++++++++++++++++++++
4 files changed, 376 insertions(+)
create mode 100644 hw/arm/bcm2835_peripherals.c
create mode 100644 include/hw/arm/bcm2835_peripherals.h
create mode 100644 include/hw/arm/raspi_platform.h
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 2195b60..82cc142 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -11,6 +11,7 @@ obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
obj-$(CONFIG_DIGIC) += digic.o
obj-y += omap1.o omap2.o strongarm.o
obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
+obj-$(CONFIG_RASPI) += bcm2835_peripherals.o
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o
obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
new file mode 100644
index 0000000..879a41d
--- /dev/null
+++ b/hw/arm/bcm2835_peripherals.c
@@ -0,0 +1,205 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
+ *
+ * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ *
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#include "hw/arm/bcm2835_peripherals.h"
+#include "hw/misc/bcm2835_mbox_defs.h"
+#include "hw/arm/raspi_platform.h"
+
+/* Peripheral base address on the VC (GPU) system bus */
+#define BCM2835_VC_PERI_BASE 0x7e000000
+
+/* Capabilities for SD controller: no DMA, high-speed, default clocks etc. */
+#define BCM2835_SDHC_CAPAREG 0x52034b4
+
+static void bcm2835_peripherals_init(Object *obj)
+{
+ BCM2835PeripheralState *s = BCM2835_PERIPHERALS(obj);
+
+ /* Memory region for peripheral devices, which we export to our parent */
+ memory_region_init_io(&s->peri_mr, obj, NULL, s, "bcm2835-peripherals",
+ 0x1000000);
+ object_property_add_child(obj, "peripheral-io", OBJECT(&s->peri_mr), NULL);
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->peri_mr);
+
+ /* Internal memory region for peripheral bus addresses (not exported) */
+ memory_region_init(&s->gpu_bus_mr, obj, "bcm2835-gpu", (uint64_t)1 << 32);
+ object_property_add_child(obj, "gpu-bus", OBJECT(&s->gpu_bus_mr), NULL);
+
+ /* Internal memory region for request/response communication with
+ * mailbox-addressable peripherals (not exported)
+ */
+ memory_region_init(&s->mbox_mr, obj, "bcm2835-mbox",
+ MBOX_CHAN_COUNT << MBOX_AS_CHAN_SHIFT);
+
+ /* Interrupt Controller */
+ object_initialize(&s->ic, sizeof(s->ic), TYPE_BCM2835_IC);
+ object_property_add_child(obj, "ic", OBJECT(&s->ic), NULL);
+ qdev_set_parent_bus(DEVICE(&s->ic), sysbus_get_default());
+
+ /* UART0 */
+ s->uart0 = SYS_BUS_DEVICE(object_new("pl011"));
+ object_property_add_child(obj, "uart0", OBJECT(s->uart0), NULL);
+ qdev_set_parent_bus(DEVICE(s->uart0), sysbus_get_default());
+
+ /* Mailboxes */
+ object_initialize(&s->mboxes, sizeof(s->mboxes), TYPE_BCM2835_MBOX);
+ object_property_add_child(obj, "mbox", OBJECT(&s->mboxes), NULL);
+ qdev_set_parent_bus(DEVICE(&s->mboxes), sysbus_get_default());
+
+ object_property_add_const_link(OBJECT(&s->mboxes), "mbox-mr",
+ OBJECT(&s->mbox_mr), &error_abort);
+
+ /* Property channel */
+ object_initialize(&s->property, sizeof(s->property), TYPE_BCM2835_PROPERTY);
+ object_property_add_child(obj, "property", OBJECT(&s->property), NULL);
+ qdev_set_parent_bus(DEVICE(&s->property), sysbus_get_default());
+
+ object_property_add_const_link(OBJECT(&s->property), "dma-mr",
+ OBJECT(&s->gpu_bus_mr), &error_abort);
+
+ /* Extended Mass Media Controller */
+ object_initialize(&s->sdhci, sizeof(s->sdhci), TYPE_SYSBUS_SDHCI);
+ object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL);
+ qdev_set_parent_bus(DEVICE(&s->sdhci), sysbus_get_default());
+}
+
+static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
+{
+ BCM2835PeripheralState *s = BCM2835_PERIPHERALS(dev);
+ Object *obj;
+ MemoryRegion *ram;
+ Error *err = NULL;
+ uint32_t ram_size;
+ int n;
+
+ obj = object_property_get_link(OBJECT(dev), "ram", &err);
+ if (obj == NULL) {
+ error_setg(errp, "%s: required ram link not found: %s",
+ __func__, error_get_pretty(err));
+ return;
+ }
+
+ ram = MEMORY_REGION(obj);
+ ram_size = memory_region_size(ram);
+
+ /* Map peripherals and RAM into the GPU address space. */
+ memory_region_init_alias(&s->peri_mr_alias, OBJECT(s),
+ "bcm2835-peripherals", &s->peri_mr, 0,
+ memory_region_size(&s->peri_mr));
+
+ memory_region_add_subregion_overlap(&s->gpu_bus_mr, BCM2835_VC_PERI_BASE,
+ &s->peri_mr_alias, 1);
+
+ /* RAM is aliased four times (different cache configurations) on the GPU */
+ for (n = 0; n < 4; n++) {
+ memory_region_init_alias(&s->ram_alias[n], OBJECT(s),
+ "bcm2835-gpu-ram-alias[*]", ram, 0, ram_size);
+ memory_region_add_subregion_overlap(&s->gpu_bus_mr, (hwaddr)n << 30,
+ &s->ram_alias[n], 0);
+ }
+
+ /* Interrupt Controller */
+ object_property_set_bool(OBJECT(&s->ic), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ memory_region_add_subregion(&s->peri_mr, ARMCTRL_IC_OFFSET,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ic), 0));
+ sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic));
+
+ /* UART0 */
+ object_property_set_bool(OBJECT(s->uart0), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ memory_region_add_subregion(&s->peri_mr, UART0_OFFSET,
+ sysbus_mmio_get_region(s->uart0, 0));
+ sysbus_connect_irq(s->uart0, 0,
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
+ INTERRUPT_UART));
+
+ /* Mailboxes */
+ object_property_set_bool(OBJECT(&s->mboxes), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ memory_region_add_subregion(&s->peri_mr, ARMCTRL_0_SBM_OFFSET,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mboxes), 0));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->mboxes), 0,
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
+ INTERRUPT_ARM_MAILBOX));
+
+ /* Property channel */
+ object_property_set_int(OBJECT(&s->property), ram_size, "ram-size", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ object_property_set_bool(OBJECT(&s->property), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ memory_region_add_subregion(&s->mbox_mr,
+ MBOX_CHAN_PROPERTY << MBOX_AS_CHAN_SHIFT,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->property), 0));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->property), 0,
+ qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_PROPERTY));
+
+ /* Extended Mass Media Controller */
+ object_property_set_int(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg",
+ &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ object_property_set_bool(OBJECT(&s->sdhci), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ memory_region_add_subregion(&s->peri_mr, EMMC_OFFSET,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhci), 0));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
+ INTERRUPT_ARASANSDIO));
+}
+
+static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = bcm2835_peripherals_realize;
+}
+
+static const TypeInfo bcm2835_peripherals_type_info = {
+ .name = TYPE_BCM2835_PERIPHERALS,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(BCM2835PeripheralState),
+ .instance_init = bcm2835_peripherals_init,
+ .class_init = bcm2835_peripherals_class_init,
+};
+
+static void bcm2835_peripherals_register_types(void)
+{
+ type_register_static(&bcm2835_peripherals_type_info);
+}
+
+type_init(bcm2835_peripherals_register_types)
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
new file mode 100644
index 0000000..5d888dc
--- /dev/null
+++ b/include/hw/arm/bcm2835_peripherals.h
@@ -0,0 +1,42 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
+ *
+ * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ *
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#ifndef BCM2835_PERIPHERALS_H
+#define BCM2835_PERIPHERALS_H
+
+#include "qemu-common.h"
+#include "exec/address-spaces.h"
+#include "hw/sysbus.h"
+#include "hw/intc/bcm2835_ic.h"
+#include "hw/misc/bcm2835_property.h"
+#include "hw/misc/bcm2835_mbox.h"
+#include "hw/sd/sdhci.h"
+
+#define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
+#define BCM2835_PERIPHERALS(obj) \
+ OBJECT_CHECK(BCM2835PeripheralState, (obj), TYPE_BCM2835_PERIPHERALS)
+
+typedef struct BCM2835PeripheralState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion peri_mr, peri_mr_alias, gpu_bus_mr, mbox_mr;
+ MemoryRegion ram_alias[4];
+ qemu_irq irq, fiq;
+
+ SysBusDevice *uart0;
+ BCM2835ICState ic;
+ BCM2835PropertyState property;
+ BCM2835MboxState mboxes;
+ SDHCIState sdhci;
+} BCM2835PeripheralState;
+
+#endif /* BCM2835_PERIPHERALS_H */
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
new file mode 100644
index 0000000..6467e88
--- /dev/null
+++ b/include/hw/arm/raspi_platform.h
@@ -0,0 +1,128 @@
+/*
+ * bcm2708 aka bcm2835/2836 aka Raspberry Pi/Pi2 SoC platform defines
+ *
+ * These definitions are derived from those in Raspbian Linux at
+ * arch/arm/mach-{bcm2708,bcm2709}/include/mach/platform.h
+ * where they carry the following notice:
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define MCORE_OFFSET 0x0000 /* Fake frame buffer device
+ * (the multicore sync block) */
+#define IC0_OFFSET 0x2000
+#define ST_OFFSET 0x3000 /* System Timer */
+#define MPHI_OFFSET 0x6000 /* Message-based Parallel Host Intf. */
+#define DMA_OFFSET 0x7000 /* DMA controller, channels 0-14 */
+#define ARM_OFFSET 0xB000 /* BCM2708 ARM control block */
+#define ARMCTRL_OFFSET (ARM_OFFSET + 0x000)
+#define ARMCTRL_IC_OFFSET (ARM_OFFSET + 0x200) /* Interrupt controller */
+#define ARMCTRL_TIMER0_1_OFFSET (ARM_OFFSET + 0x400) /* Timer 0 and 1 */
+#define ARMCTRL_0_SBM_OFFSET (ARM_OFFSET + 0x800) /* User 0 (ARM) Semaphores
+ * Doorbells & Mailboxes */
+#define PM_OFFSET 0x100000 /* Power Management, Reset controller
+ * and Watchdog registers */
+#define PCM_CLOCK_OFFSET 0x101098
+#define RNG_OFFSET 0x104000
+#define GPIO_OFFSET 0x200000
+#define UART0_OFFSET 0x201000
+#define MMCI0_OFFSET 0x202000
+#define I2S_OFFSET 0x203000
+#define SPI0_OFFSET 0x204000
+#define BSC0_OFFSET 0x205000 /* BSC0 I2C/TWI */
+#define UART1_OFFSET 0x215000
+#define EMMC_OFFSET 0x300000
+#define SMI_OFFSET 0x600000
+#define BSC1_OFFSET 0x804000 /* BSC1 I2C/TWI */
+#define USB_OFFSET 0x980000 /* DTC_OTG USB controller */
+#define DMA15_OFFSET 0xE05000 /* DMA controller, channel 15 */
+
+/* GPU interrupts */
+#define INTERRUPT_TIMER0 0
+#define INTERRUPT_TIMER1 1
+#define INTERRUPT_TIMER2 2
+#define INTERRUPT_TIMER3 3
+#define INTERRUPT_CODEC0 4
+#define INTERRUPT_CODEC1 5
+#define INTERRUPT_CODEC2 6
+#define INTERRUPT_JPEG 7
+#define INTERRUPT_ISP 8
+#define INTERRUPT_USB 9
+#define INTERRUPT_3D 10
+#define INTERRUPT_TRANSPOSER 11
+#define INTERRUPT_MULTICORESYNC0 12
+#define INTERRUPT_MULTICORESYNC1 13
+#define INTERRUPT_MULTICORESYNC2 14
+#define INTERRUPT_MULTICORESYNC3 15
+#define INTERRUPT_DMA0 16
+#define INTERRUPT_DMA1 17
+#define INTERRUPT_DMA2 18
+#define INTERRUPT_DMA3 19
+#define INTERRUPT_DMA4 20
+#define INTERRUPT_DMA5 21
+#define INTERRUPT_DMA6 22
+#define INTERRUPT_DMA7 23
+#define INTERRUPT_DMA8 24
+#define INTERRUPT_DMA9 25
+#define INTERRUPT_DMA10 26
+#define INTERRUPT_DMA11 27
+#define INTERRUPT_DMA12 28
+#define INTERRUPT_AUX 29
+#define INTERRUPT_ARM 30
+#define INTERRUPT_VPUDMA 31
+#define INTERRUPT_HOSTPORT 32
+#define INTERRUPT_VIDEOSCALER 33
+#define INTERRUPT_CCP2TX 34
+#define INTERRUPT_SDC 35
+#define INTERRUPT_DSI0 36
+#define INTERRUPT_AVE 37
+#define INTERRUPT_CAM0 38
+#define INTERRUPT_CAM1 39
+#define INTERRUPT_HDMI0 40
+#define INTERRUPT_HDMI1 41
+#define INTERRUPT_PIXELVALVE1 42
+#define INTERRUPT_I2CSPISLV 43
+#define INTERRUPT_DSI1 44
+#define INTERRUPT_PWA0 45
+#define INTERRUPT_PWA1 46
+#define INTERRUPT_CPR 47
+#define INTERRUPT_SMI 48
+#define INTERRUPT_GPIO0 49
+#define INTERRUPT_GPIO1 50
+#define INTERRUPT_GPIO2 51
+#define INTERRUPT_GPIO3 52
+#define INTERRUPT_I2C 53
+#define INTERRUPT_SPI 54
+#define INTERRUPT_I2SPCM 55
+#define INTERRUPT_SDIO 56
+#define INTERRUPT_UART 57
+#define INTERRUPT_SLIMBUS 58
+#define INTERRUPT_VEC 59
+#define INTERRUPT_CPG 60
+#define INTERRUPT_RNG 61
+#define INTERRUPT_ARASANSDIO 62
+#define INTERRUPT_AVSPMON 63
+
+/* ARM CPU IRQs use a private number space */
+#define INTERRUPT_ARM_TIMER 0
+#define INTERRUPT_ARM_MAILBOX 1
+#define INTERRUPT_ARM_DOORBELL_0 2
+#define INTERRUPT_ARM_DOORBELL_1 3
+#define INTERRUPT_VPU0_HALTED 4
+#define INTERRUPT_VPU1_HALTED 5
+#define INTERRUPT_ILLEGAL_TYPE0 6
+#define INTERRUPT_ILLEGAL_TYPE1 7
--
2.5.3
next prev parent reply other threads:[~2016-01-15 23:59 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-15 23:58 [Qemu-devel] [PATCH v4 0/8] Raspberry Pi 2 support Andrew Baumann
2016-01-15 23:58 ` [Qemu-devel] [PATCH v4 1/8] bcm2835_mbox: add BCM2835 mailboxes Andrew Baumann
2016-01-26 5:54 ` Peter Crosthwaite
2016-01-15 23:58 ` [Qemu-devel] [PATCH v4 2/8] bcm2835_property: add bcm2835 property channel Andrew Baumann
2016-01-26 6:03 ` Peter Crosthwaite
2016-01-15 23:58 ` [Qemu-devel] [PATCH v4 3/8] bcm2835_ic: add bcm2835 interrupt controller Andrew Baumann
2016-01-15 23:58 ` Andrew Baumann [this message]
2016-01-26 6:14 ` [Qemu-devel] [PATCH v4 4/8] bcm2835_peripherals: add rollup device for bcm2835 peripherals Peter Crosthwaite
2016-01-26 6:23 ` Andrew Baumann
2016-01-26 8:03 ` Peter Crosthwaite
2016-01-26 19:12 ` Andrew Baumann
2016-01-26 19:40 ` Peter Maydell
2016-01-15 23:58 ` [Qemu-devel] [PATCH v4 5/8] bcm2836_control: add bcm2836 ARM control logic Andrew Baumann
2016-01-29 4:37 ` Peter Crosthwaite
2016-01-29 4:42 ` Andrew Baumann
2016-01-15 23:58 ` [Qemu-devel] [PATCH v4 6/8] bcm2836: add bcm2836 soc device Andrew Baumann
2016-01-29 4:50 ` Peter Crosthwaite
2016-01-15 23:58 ` [Qemu-devel] [PATCH v4 7/8] arm/boot: move highbank secure board setup code to common routine Andrew Baumann
2016-01-29 7:11 ` Peter Crosthwaite
[not found] ` <1452902337-13844-9-git-send-email-Andrew.Baumann@microsoft.com>
2016-01-29 7:31 ` [Qemu-devel] [PATCH v4 8/8] raspi: add raspberry pi 2 machine Peter Crosthwaite
2016-01-29 21:50 ` Andrew Baumann
2016-01-29 22:22 ` Peter Crosthwaite
2016-01-29 22:28 ` Andrew Baumann
2016-01-29 22:40 ` Peter Crosthwaite
2016-01-29 22:43 ` Andrew Baumann
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=1452902337-13844-5-git-send-email-Andrew.Baumann@microsoft.com \
--to=andrew.baumann@microsoft.com \
--cc=crosthwaite.peter@gmail.com \
--cc=gregory.estrade@gmail.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=robh@kernel.org \
--cc=sw@weilnetz.de \
/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.