From: "Eric Bénard" <eric@eukrea.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v4 2/2] MarSBoard: add new board
Date: Sat, 29 Mar 2014 22:29:40 +0100 [thread overview]
Message-ID: <1396128580-11129-2-git-send-email-eric@eukrea.com> (raw)
In-Reply-To: <1396128580-11129-1-git-send-email-eric@eukrea.com>
this board is produced by Embest/Element 14 and is based on i.MX6 Dual
The following features are tested :
- UART2 (console)
- eMMC
- uSDCard
- Ethernet
- USB Host (through 2 ports hub)
- HDMI output
- I2C 1/2
- SPI NOR Flash
- LVDS TFT with LCD8000-97C from Embest/Element 14
Boot on SPI NOR and through USB loader are tested.
For more informations on this board :
http://www.embest-tech.com/shop/star/marsboard.html
As this board shares a lot with RiOTboard, both boards are supported by
the same code base which is renamed embest/mx6boards.
Signed-off-by: Eric B?nard <eric@eukrea.com>
---
v4: add LVDS TFT support
v3: switch to automatic board detection in c code to remove the #ifdef
#ifdef kept in the config file as one binary for both boards is not
possible actually since both boards use different RAM init.
board/embest/{riotboard => mx6boards}/Makefile | 2 +-
.../riotboard.c => mx6boards/mx6boards.c} | 118 ++++++++++++++++++---
boards.cfg | 3 +-
include/configs/{riotboard.h => embestmx6boards.h} | 58 ++++++++++
4 files changed, 166 insertions(+), 15 deletions(-)
rename board/embest/{riotboard => mx6boards}/Makefile (87%)
rename board/embest/{riotboard/riotboard.c => mx6boards/mx6boards.c} (81%)
rename include/configs/{riotboard.h => embestmx6boards.h} (84%)
diff --git a/board/embest/riotboard/Makefile b/board/embest/mx6boards/Makefile
similarity index 87%
rename from board/embest/riotboard/Makefile
rename to board/embest/mx6boards/Makefile
index 5f978c0..467fb50 100644
--- a/board/embest/riotboard/Makefile
+++ b/board/embest/mx6boards/Makefile
@@ -6,4 +6,4 @@
# SPDX-License-Identifier: GPL-2.0+
#
-obj-y := riotboard.o
+obj-y := mx6boards.o
diff --git a/board/embest/riotboard/riotboard.c b/board/embest/mx6boards/mx6boards.c
similarity index 81%
rename from board/embest/riotboard/riotboard.c
rename to board/embest/mx6boards/mx6boards.c
index 1627156..fc133c5 100644
--- a/board/embest/riotboard/riotboard.c
+++ b/board/embest/mx6boards/mx6boards.c
@@ -14,6 +14,7 @@
*/
#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/iomux.h>
#include <asm/arch/mx6-pins.h>
@@ -60,6 +61,13 @@ DECLARE_GLOBAL_DATA_PTR;
PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
PAD_CTL_ODE | PAD_CTL_SRE_FAST)
+#define SPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_SPEED_MED | \
+ PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
+
+static int board_type = -1;
+#define BOARD_IS_MARSBOARD 0
+#define BOARD_IS_RIOTBOARD 1
+
int dram_init(void)
{
gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
@@ -153,6 +161,9 @@ iomux_v3_cfg_t const usdhc3_pads[] = {
MX6_PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const riotboard_usdhc3_pads[] = {
MX6_PAD_SD3_DAT4__GPIO7_IO01 | MUX_PAD_CTRL(NO_PAD_CTRL), /* WP */
MX6_PAD_SD3_DAT5__GPIO7_IO00 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
};
@@ -188,7 +199,10 @@ int board_mmc_getcd(struct mmc *mmc)
ret = !gpio_get_value(USDHC2_CD_GPIO);
break;
case USDHC3_BASE_ADDR:
- ret = !gpio_get_value(USDHC3_CD_GPIO);
+ if (board_type == BOARD_IS_RIOTBOARD)
+ ret = !gpio_get_value(USDHC3_CD_GPIO);
+ else if (board_type == BOARD_IS_MARSBOARD)
+ ret = 1; /* eMMC/uSDHC3 is always present */
break;
case USDHC4_BASE_ADDR:
ret = 1; /* eMMC/uSDHC4 is always present */
@@ -206,9 +220,13 @@ int board_mmc_init(bd_t *bis)
/*
* According to the board_mmc_init() the following map is done:
* (U-boot device node) (Physical Port)
+ * ** RiOTboard :
* mmc0 SDCard slot (bottom)
* mmc1 uSDCard slot (top)
* mmc2 eMMC
+ * ** MarSBoard :
+ * mmc0 uSDCard slot (bottom)
+ * mmc1 eMMC
*/
for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) {
switch (i) {
@@ -222,7 +240,15 @@ int board_mmc_init(bd_t *bis)
case 1:
imx_iomux_v3_setup_multiple_pads(
usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
- gpio_direction_input(USDHC3_CD_GPIO);
+ if (board_type == BOARD_IS_RIOTBOARD) {
+ imx_iomux_v3_setup_multiple_pads(
+ riotboard_usdhc3_pads,
+ ARRAY_SIZE(riotboard_usdhc3_pads));
+ gpio_direction_input(USDHC3_CD_GPIO);
+ gpio_direction_output(IMX_GPIO_NR(7, 8) , 0);
+ udelay(250);
+ gpio_set_value(IMX_GPIO_NR(7, 8), 1);
+ }
usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
usdhc_cfg[1].max_bus_width = 4;
break;
@@ -249,6 +275,20 @@ int board_mmc_init(bd_t *bis)
}
#endif
+#ifdef CONFIG_MXC_SPI
+iomux_v3_cfg_t const ecspi1_pads[] = {
+ MX6_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
+ MX6_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
+ MX6_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
+ MX6_PAD_EIM_EB2__GPIO2_IO30 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+static void setup_spi(void)
+{
+ imx_iomux_v3_setup_multiple_pads(ecspi1_pads, ARRAY_SIZE(ecspi1_pads));
+}
+#endif
+
struct i2c_pads_info i2c_pad_info1 = {
.scl = {
.i2c_mode = MX6_PAD_CSI0_DAT9__I2C1_SCL
@@ -300,7 +340,7 @@ struct i2c_pads_info i2c_pad_info3 = {
}
};
-iomux_v3_cfg_t const tft_pads[] = {
+iomux_v3_cfg_t const tft_pads_riot[] = {
/* LCD_PWR_EN */
MX6_PAD_ENET_TXD1__GPIO1_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
/* TOUCH_INT */
@@ -311,6 +351,17 @@ iomux_v3_cfg_t const tft_pads[] = {
MX6_PAD_SD1_CMD__GPIO1_IO18 | MUX_PAD_CTRL(NO_PAD_CTRL),
};
+iomux_v3_cfg_t const tft_pads_mars[] = {
+ /* LCD_PWR_EN */
+ MX6_PAD_ENET_TXD1__GPIO1_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* TOUCH_INT */
+ MX6_PAD_NANDF_CS1__GPIO6_IO14 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* LED_PWR_EN */
+ MX6_PAD_NANDF_CS2__GPIO6_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* BL LEVEL (PWM4) */
+ MX6_PAD_SD4_DAT2__GPIO2_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
#if defined(CONFIG_VIDEO_IPUV3)
struct display_info_t {
int bus;
@@ -328,7 +379,10 @@ static void enable_lvds(struct display_info_t const *dev)
setbits_le32(&iomux->gpr[2],
IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT);
/* set backlight level to ON */
- gpio_direction_output(IMX_GPIO_NR(1, 18) , 1);
+ if (board_type == BOARD_IS_RIOTBOARD)
+ gpio_direction_output(IMX_GPIO_NR(1, 18) , 1);
+ else if (board_type == BOARD_IS_MARSBOARD)
+ gpio_direction_output(IMX_GPIO_NR(2, 10) , 1);
}
static void disable_lvds(struct display_info_t const *dev)
@@ -336,7 +390,10 @@ static void disable_lvds(struct display_info_t const *dev)
struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
/* set backlight level to OFF */
- gpio_direction_output(IMX_GPIO_NR(1, 18) , 0);
+ if (board_type == BOARD_IS_RIOTBOARD)
+ gpio_direction_output(IMX_GPIO_NR(1, 18) , 0);
+ else if (board_type == BOARD_IS_MARSBOARD)
+ gpio_direction_output(IMX_GPIO_NR(2, 10) , 0);
clrbits_le32(&iomux->gpr[2],
IOMUXC_GPR2_LVDS_CH0_MODE_MASK);
@@ -508,10 +565,25 @@ int board_eth_init(bd_t *bis)
int board_early_init_f(void)
{
+ u32 cputype = cpu_type(get_cpu_rev());
+
+ switch (cputype) {
+ case MXC_CPU_MX6SOLO:
+ board_type = BOARD_IS_RIOTBOARD;
+ break;
+ case MXC_CPU_MX6D:
+ board_type = BOARD_IS_MARSBOARD;
+ break;
+ }
+
setup_iomux_uart();
- imx_iomux_v3_setup_multiple_pads(
- tft_pads, ARRAY_SIZE(tft_pads));
+ if (board_type == BOARD_IS_RIOTBOARD)
+ imx_iomux_v3_setup_multiple_pads(
+ tft_pads_riot, ARRAY_SIZE(tft_pads_riot));
+ else if (board_type == BOARD_IS_MARSBOARD)
+ imx_iomux_v3_setup_multiple_pads(
+ tft_pads_mars, ARRAY_SIZE(tft_pads_mars));
#if defined(CONFIG_VIDEO_IPUV3)
/* power ON LCD */
gpio_direction_output(IMX_GPIO_NR(1, 29) , 1);
@@ -520,7 +592,10 @@ int board_early_init_f(void)
/* power ON backlight */
gpio_direction_output(IMX_GPIO_NR(6, 15) , 1);
/* set backlight level to off */
- gpio_direction_output(IMX_GPIO_NR(1, 18) , 0);
+ if (board_type == BOARD_IS_RIOTBOARD)
+ gpio_direction_output(IMX_GPIO_NR(1, 18) , 0);
+ else if (board_type == BOARD_IS_MARSBOARD)
+ gpio_direction_output(IMX_GPIO_NR(2, 10) , 0);
setup_display();
#endif
@@ -531,29 +606,39 @@ int board_init(void)
{
/* address of boot parameters */
gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
- /* i2c1 : PMIC, Audio codec */
+ /* i2c1 : PMIC, Audio codec on RiOT, Expansion connector on MarS */
setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
/* i2c2 : HDMI EDID */
setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
/* i2c3 : LVDS, Expansion connector */
setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info3);
-
+#ifdef CONFIG_MXC_SPI
+ setup_spi();
+#endif
return 0;
}
#ifdef CONFIG_CMD_BMODE
-static const struct boot_mode board_boot_modes[] = {
+static const struct boot_mode riotboard_boot_modes[] = {
{"sd2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
{"sd3", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
{"emmc", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)},
{NULL, 0},
};
+static const struct boot_mode marsboard_boot_modes[] = {
+ {"sd2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
+ {"emmc", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
+ {NULL, 0},
+};
#endif
int board_late_init(void)
{
#ifdef CONFIG_CMD_BMODE
- add_board_boot_modes(board_boot_modes);
+ if (board_type == BOARD_IS_RIOTBOARD)
+ add_board_boot_modes(riotboard_boot_modes);
+ else if (board_type == BOARD_IS_RIOTBOARD)
+ add_board_boot_modes(marsboard_boot_modes);
#endif
return 0;
@@ -561,6 +646,13 @@ int board_late_init(void)
int checkboard(void)
{
- puts("Board: RIoTboard\n");
+ puts("Board: ");
+ if (board_type == BOARD_IS_MARSBOARD)
+ puts("MarSBoard\n");
+ else if (board_type == BOARD_IS_RIOTBOARD)
+ puts("RIoTboard\n");
+ else
+ printf("unknown - cputype : %02x\n", cpu_type(get_cpu_rev()));
+
return 0;
}
diff --git a/boards.cfg b/boards.cfg
index a29417c..d211cda 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -323,7 +323,8 @@ Active arm armv7 mx6 freescale mx6sabresd
Active arm armv7 mx6 freescale mx6sabresd mx6qsabresd mx6sabresd:IMX_CONFIG=board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg,MX6Q Fabio Estevam <fabio.estevam@freescale.com>
Active arm armv7 mx6 freescale mx6slevk mx6slevk mx6slevk:IMX_CONFIG=board/freescale/mx6slevk/imximage.cfg,MX6SL Fabio Estevam <fabio.estevam@freescale.com>
Active arm armv7 mx6 solidrun hummingboard hummingboard_solo hummingboard:IMX_CONFIG=board/solidrun/hummingboard/solo.cfg,MX6S,DDR_MB=512 Jon Nettleton <jon.nettleton@gmail.com>
-Active arm armv7 mx6 embest riotboard riotboard riotboard:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6s1g.cfg,MX6S,DDR_MB=1024 Eric B?nard <eric@eukrea.com>
+Active arm armv7 mx6 embest mx6boards riotboard embestmx6boards:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6s1g.cfg,MX6S,DDR_MB=1024,RIOTBOARD Eric B?nard <eric@eukrea.com>
+Active arm armv7 mx6 embest mx6boards marsboard embestmx6boards:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6q.cfg,MX6Q,DDR_MB=1024,MARSBOARD Eric B?nard <eric@eukrea.com>
Active arm armv7 omap3 - overo omap3_overo - Steve Sakoman <sakoman@gmail.com>
Active arm armv7 omap3 - pandora omap3_pandora - Grazvydas Ignotas <notasas@gmail.com>
Active arm armv7 omap3 8dtech eco5pk eco5pk - Raphael Assenat <raph@8d.com>
diff --git a/include/configs/riotboard.h b/include/configs/embestmx6boards.h
similarity index 84%
rename from include/configs/riotboard.h
rename to include/configs/embestmx6boards.h
index 747ec79..07ea2d2 100644
--- a/include/configs/riotboard.h
+++ b/include/configs/embestmx6boards.h
@@ -22,10 +22,19 @@
#define CONFIG_MXC_UART_BASE UART2_BASE
#define CONFIG_CONSOLE_DEV "ttymxc0"
#define CONFIG_MMCROOT "/dev/mmcblk1p2"
+#ifdef CONFIG_RIOTBOARD
#define CONFIG_DEFAULT_FDT_FILE "imx6s-riotboard.dtb"
+#elif defined CONFIG_MARSBOARD
+#define CONFIG_DEFAULT_FDT_FILE "imx6q-marsboard.dtb"
+#else
+#error Please define a board (RIOTBOARD or MARSBOARD)
+#endif
+
#define PHYS_SDRAM_SIZE (1u * 1024 * 1024 * 1024)
+#ifdef CONFIG_RIOTBOARD
#define CONFIG_SUPPORT_EMMC_BOOT /* eMMC specific */
+#endif
#define CONFIG_MX6
@@ -96,6 +105,19 @@
#define CONFIG_PHYLIB
#define CONFIG_PHY_ATHEROS
+#ifdef CONFIG_MARSBOARD
+#define CONFIG_CMD_SF
+#ifdef CONFIG_CMD_SF
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI_FLASH_SST
+#define CONFIG_MXC_SPI
+#define CONFIG_SF_DEFAULT_BUS 0
+#define CONFIG_SF_DEFAULT_CS (0 | (IMX_GPIO_NR(2, 30) << 8))
+#define CONFIG_SF_DEFAULT_SPEED 20000000
+#define CONFIG_SF_DEFAULT_MODE SPI_MODE_0
+#endif
+#endif
+
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#define CONFIG_CONS_INDEX 1
@@ -134,6 +156,24 @@
#define EMMC_ENV ""
#endif
+#ifdef CONFIG_CMD_SF
+#define SF_ENV \
+ "update_spi_firmware=" \
+ "if test ${ip_dyn} = yes; then " \
+ "setenv get_cmd dhcp; " \
+ "else " \
+ "setenv get_cmd tftp; " \
+ "fi; " \
+ "if ${get_cmd} ${update_spi_firmware_filename}; then " \
+ "if sf probe; then " \
+ "sf erase 0 0xc0000; " \
+ "sf write ${loadaddr} 0x400 ${filesize}; " \
+ "fi; " \
+ "fi\0"
+#else
+#define SF_ENV ""
+#endif
+
#define CONFIG_EXTRA_ENV_SETTINGS \
"script=boot.scr\0" \
"image=zImage\0" \
@@ -161,6 +201,7 @@
"fi; " \
"fi\0" \
EMMC_ENV \
+ SF_ENV \
"mmcargs=setenv bootargs console=${console},${baudrate} " \
"root=${mmcroot}\0" \
"loadbootscript=" \
@@ -263,10 +304,22 @@
#define CONFIG_ENV_SIZE (8 * 1024)
+#ifdef CONFIG_RIOTBOARD
#define CONFIG_ENV_IS_IN_MMC
+#endif
+#ifdef CONFIG_MARSBOARD
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#endif
#if defined(CONFIG_ENV_IS_IN_MMC)
#define CONFIG_ENV_OFFSET (6 * 64 * 1024)
+#elif defined(CONFIG_ENV_IS_IN_SPI_FLASH)
+#define CONFIG_ENV_OFFSET (768 * 1024)
+#define CONFIG_ENV_SECT_SIZE (8 * 1024)
+#define CONFIG_ENV_SPI_BUS CONFIG_SF_DEFAULT_BUS
+#define CONFIG_ENV_SPI_CS CONFIG_SF_DEFAULT_CS
+#define CONFIG_ENV_SPI_MODE CONFIG_SF_DEFAULT_MODE
+#define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED
#endif
#define CONFIG_OF_LIBFDT
@@ -275,7 +328,12 @@
#define CONFIG_CMD_CACHE
#endif
+#ifdef CONFIG_RIOTBOARD
#define CONFIG_SYS_FSL_USDHC_NUM 3
+#elif defined(CONFIG_MARSBOARD)
+#define CONFIG_SYS_FSL_USDHC_NUM 2
+#endif
+
#if defined(CONFIG_ENV_IS_IN_MMC)
#define CONFIG_SYS_MMC_ENV_DEV 2 /* SDHC4 */
#endif
--
1.9.0
next prev parent reply other threads:[~2014-03-29 21:29 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-03-26 18:26 [U-Boot] [PATCH 1/2] RiOTboard: add new board Eric Bénard
2014-03-26 18:26 ` [U-Boot] [PATCH 2/2] MarSBoard: " Eric Bénard
2014-03-26 19:02 ` Wolfgang Denk
2014-03-26 19:26 ` Eric Bénard
2014-03-26 21:31 ` [U-Boot] [PATCH v2 1/2] RiOTboard: " Eric Bénard
2014-03-26 21:31 ` [U-Boot] [PATCH v2 2/2] MarSBoard: " Eric Bénard
2014-03-27 2:21 ` Otavio Salvador
2014-03-27 5:01 ` Fabio Estevam
2014-03-27 5:36 ` Wolfgang Denk
2014-03-27 12:44 ` Fabio Estevam
2014-03-27 12:50 ` Otavio Salvador
2014-03-27 16:04 ` Eric Bénard
2014-03-27 15:59 ` Eric Bénard
2014-03-27 16:34 ` Fabio Estevam
2014-03-27 16:42 ` Wolfgang Denk
2014-03-27 5:31 ` Wolfgang Denk
2014-03-27 7:05 ` Stefan Roese
2014-03-27 7:40 ` Eric Bénard
2014-03-27 17:10 ` [U-Boot] [PATCH v3 1/2] RiOTboard: " Eric Bénard
2014-03-27 17:10 ` [U-Boot] [PATCH v3 2/2] MarSBoard: " Eric Bénard
2014-03-28 7:30 ` Stefan Roese
2014-03-28 10:09 ` Wolfgang Denk
2014-03-28 10:01 ` [U-Boot] [PATCH v3 1/2] RiOTboard: " Wolfgang Denk
2014-03-29 21:29 ` [U-Boot] [PATCH v4 " Eric Bénard
2014-03-29 21:29 ` Eric Bénard [this message]
2014-03-30 16:20 ` Stefano Babic
2014-03-30 19:52 ` Eric Bénard
2014-03-31 6:55 ` Stefano Babic
2014-03-31 20:02 ` Eric Bénard
2014-04-01 8:41 ` Stefano Babic
2014-04-01 8:50 ` Eric Bénard
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=1396128580-11129-2-git-send-email-eric@eukrea.com \
--to=eric@eukrea.com \
--cc=u-boot@lists.denx.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.