From: Vitaly Andrianov <vitalya@ti.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [U-Boot:RESEND][[PATCH 6/7] k2hk: add support for k2hk SOC and EVM
Date: Mon, 10 Feb 2014 20:44:01 -0500 [thread overview]
Message-ID: <52F98061.5090902@ti.com> (raw)
In-Reply-To: <20140210212539.GA7049@bill-the-cat>
On 02/10/2014 04:25 PM, Tom Rini wrote:
> On Fri, Feb 07, 2014 at 06:23:13PM -0500, Murali Karicheri wrote:
>
>> k2hk EVM is based on Texas Instruments Keystone2 Hawking/Kepler
>> SoC. Keystone2 SoC has ARM v7 Cortex-A15 MPCore processor. Please
>> refer the ti/k2hk_evm/README for details on the board, build and other
>> information.
>>
>> This patch add support for keystone architecture and k2hk evm.
> Globally, only use
> /*
> * Multiline comments like this
> */
I'll fix this.
>> +++ b/arch/arm/cpu/armv7/keystone/Makefile
>> @@ -0,0 +1,18 @@
>> +#
>> +# (C) Copyright 2012-2014
>> +# Texas Instruments Incorporated, <www.ti.com>
>> +#
>> +# SPDX-License-Identifier: GPL-2.0+
>> +#
>> +
>> +obj-y += aemif.o
>> +obj-y += init.o
>> +obj-y += psc.o
>> +obj-y += clock.o
>> +obj-y += cmd_clock.o
>> +obj-y += cmd_mon.o
>> +obj-y += msmc.o
>> +obj-y += lowlevel_init.o
>> +obj-$(CONFIG_SPL_BUILD) += spl.o
>> +obj-y += ddr3.o
> Mix of space and tab, just tab it all out to line up please.
Will fix.
>> +++ b/arch/arm/cpu/armv7/keystone/aemif.c
>> @@ -0,0 +1,79 @@
>> +/*
>> + * Keystone2: Asynchronous EMIF Configuration
>> + *
>> + * (C) Copyright 2012-2014
>> + * Texas Instruments Incorporated, <www.ti.com>
>> + *
>> + * SPDX-License-Identifier: GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <asm/io.h>
>> +#include <asm/arch/clock.h>
>> +
>> +#ifdef CONFIG_SOC_K2HK
>> +#define ASYNC_EMIF_BASE K2HK_ASYNC_EMIF_CNTRL_BASE
>> +#endif
> So, does Keystone 1 have this in a different location?
That is not for Keystone1. K2HK is for Hawking and Kepler SoC.
The ASYNC_EMIF_BASE may be different for other SOC of the Keystone2 family.
>> +#define ASYNC_EMIF_CONFIG(cs) (ASYNC_EMIF_BASE+0x10+(cs)*4)
>> +#define ASYNC_EMIF_ONENAND_CONTROL (ASYNC_EMIF_BASE+0x5c)
>> +#define ASYNC_EMIF_NAND_CONTROL (ASYNC_EMIF_BASE+0x60)
>> +#define ASYNC_EMIF_WAITCYCLE_CONFIG (ASYNC_EMIF_BASE+0x4)
> Register access is done over structs not define of base + offset, please
> rework.
This style was taken form Davinci code. Shall we rework it?
>> +#define CONFIG_SELECT_STROBE(v) ((v) ? 1 << 31 : 0)
>> +#define CONFIG_EXTEND_WAIT(v) ((v) ? 1 << 30 : 0)
>> +#define CONFIG_WR_SETUP(v) (((v) & 0x0f) << 26)
>> +#define CONFIG_WR_STROBE(v) (((v) & 0x3f) << 20)
>> +#define CONFIG_WR_HOLD(v) (((v) & 0x07) << 17)
>> +#define CONFIG_RD_SETUP(v) (((v) & 0x0f) << 13)
>> +#define CONFIG_RD_STROBE(v) (((v) & 0x3f) << 7)
>> +#define CONFIG_RD_HOLD(v) (((v) & 0x07) << 4)
>> +#define CONFIG_TURN_AROUND(v) (((v) & 0x03) << 2)
>> +#define CONFIG_WIDTH(v) (((v) & 0x03) << 0)
> To avoid confusion please do AEMIF_CONFIG_... or AEMIF_CFG_... or maybe
> just CFG_...
Agree and will change.
>> +++ b/arch/arm/cpu/armv7/keystone/clock-k2hk.c
> [snip]
>> + prediv = (tmp & 0x3f) + 1;
>> + mult = (((tmp & 0x7f000) >> 6) | (pllctl_reg_read(pll,
>> + mult) & 0x3f)) + 1;
>> + output_div = ((pllctl_reg_read(pll, secctl) >> 19) &
>> + 0xf) + 1;
> Please define magic numbers, check globally.
OK
>
>> + return ret;
>> +}
>> +
>> +
>> +
>> +
>> +unsigned long clk_get_rate(unsigned int clk)
> Extra empty lines.
Will remove.
>> +++ b/arch/arm/cpu/armv7/keystone/clock.c
> [snip]
>> +static void pll_delay(unsigned int loop_count)
>> +{
>> + while (loop_count--)
>> + asm(" NOP");
>> +}
> If we cannot use udelay yet use sdelay.
>
>> +#include "clock-k2hk.c"
> Please use function prototypes, header files and then build the right
> SoC clock file itself.
The idea was to have common clock.h for all Keystone2 family and include
in to
it a specific for each SoC include file. Are you asking to remove that
specific include
from the clock.h?
>> +++ b/arch/arm/cpu/armv7/keystone/cmd_clock.c
> We just added a generic
I'll check it out.
>> @@ -0,0 +1,139 @@
>> +/*
>> + * keystone2: commands for clocks
>> + *
>> + * (C) Copyright 2012-2014
>> + * Texas Instruments Incorporated, <www.ti.com>
>> + *
>> + * SPDX-License-Identifier: GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <command.h>
>> +#include <asm/arch/hardware.h>
>> +#include <asm/arch/clock.h>
>> +#include <asm/arch/psc_defs.h>
>> +
>> +static u32 atoui(char *pstr)
>> +{
>> + u32 res = 0;
>> +
>> + for (; *pstr != 0; pstr++) {
>> + if (*pstr < '0' || *pstr > '9')
>> + break;
>> +
>> + res = (res * 10) + (*pstr - '0');
>> + }
>> +
>> + return res;
>> +}
>> +
>> +struct pll_init_data cmd_pll_data = {
>> + .pll = MAIN_PLL,
>> + .pll_m = 16,
>> + .pll_d = 1,
>> + .pll_od = 2,
>> +};
>> +
>> +int do_pll_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>> +{
>> + if (argc != 5)
>> + goto pll_cmd_usage;
>> +
>> + if (strncmp(argv[1], "pa", 2) == 0)
>> + cmd_pll_data.pll = PASS_PLL;
>> + else if (strncmp(argv[1], "arm", 3) == 0)
>> + cmd_pll_data.pll = TETRIS_PLL;
>> + else if (strncmp(argv[1], "ddr3a", 5) == 0)
>> + cmd_pll_data.pll = DDR3A_PLL;
>> + else if (strncmp(argv[1], "ddr3b", 5) == 0)
>> + cmd_pll_data.pll = DDR3B_PLL;
>> + else
>> + goto pll_cmd_usage;
>> +
>> + cmd_pll_data.pll_m = atoui(argv[2]);
>> + cmd_pll_data.pll_d = atoui(argv[3]);
>> + cmd_pll_data.pll_od = atoui(argv[4]);
> Why not simple_strtoul(argv[n], NULL, 10) ?
>
>> +
>> + printf("Trying to set pll %d; mult %d; div %d; OD %d\n",
>> + cmd_pll_data.pll, cmd_pll_data.pll_m,
>> + cmd_pll_data.pll_d, cmd_pll_data.pll_od);
>> + init_pll(&cmd_pll_data);
>> +
>> + return 0;
>> +
>> +pll_cmd_usage:
>> + return cmd_usage(cmdtp);
>> +}
>> +
>> +U_BOOT_CMD(
>> + pllset, 5, 0, do_pll_cmd,
>> + "set pll multiplier and pre divider",
>> + "<pa|arm|ddr3a|ddr3b> <mult> <div> <OD>\n"
>> +);
> Wolfgang, if we add another command that takes decimal not hexidecimal
> inputs, you're going to hit me with a ruler, aren't you? Even for a
> clock command?
>
>> +U_BOOT_CMD(
>> + getclk, 2, 0, do_getclk_cmd,
>> + "get clock rate",
>> + "<clk index>\n"
>> + "See the 'enum clk_e' in the k2hk clock.h for clk indexes\n"
>> +);
> This would fit with the generic clk command and 'dump' which we just
> added.
>
>> +++ b/arch/arm/cpu/armv7/keystone/config.mk
>> @@ -0,0 +1,14 @@
>> +# (C) Copyright 2012-2014
>> +# Texas Instruments Incorporated, <www.ti.com>
>> +# SPDX-License-Identifier: GPL-2.0+
>> +#
>> +
>> +PLATFORM_RELFLAGS += -fno-common -ffixed-r8 -msoft-float
>> +
>> +# =========================================================================
>> +#
>> +# Supply options according to compiler version
>> +#
>> +# =========================================================================
>> +PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,\
>> + $(call cc-option,-malignment-traps,))
> You need to do this as:
> PF_CPPFLAGS_SLB := ...
> PLATFORM_RELFALGS += $(PF_CPPFLAGS_SLB)
>
> The way you have it causes an evaluation per file and the above is a one
> time evaluation.
>
>> diff --git a/arch/arm/cpu/armv7/keystone/ddr3.c b/arch/arm/cpu/armv7/keystone/ddr3.c
>> new file mode 100644
>> index 0000000..4875db7
>> --- /dev/null
>> +++ b/arch/arm/cpu/armv7/keystone/ddr3.c
> Part of me wonders just how close/far this is from the omap-common
> EMIF/DDR code. Some parts look pretty familiar (and makes me wonder if
> you don't have some corner-case bugs around not setting shadow registers
> and initially setting some of the values to max, then setting them
> optimally due to which bits cause a refresh cycle).
This code is based on AVV test code and is very specific to SOC DDR3
controller,
which as I know is different from OMAP.
>> +++ b/arch/arm/cpu/armv7/keystone/lowlevel_init.S
> Is there a reason you don't use arch/arm/cpu/armv7/lowlevel_init.S and
> the s_init calling sequence?
>
>> +++ b/board/ti/k2hk_evm/board.c
> [snip]
>> +/* Byte swap the 32-bit data if the device is BE */
>> +int cpu_to_bus(u32 *ptr, u32 length)
>> +{
>> + u32 i;
>> +
>> + if (device_big_endian)
>> + for (i = 0; i < length; i++, ptr++)
>> + *ptr = __swab32(*ptr);
>> +
>> + return 0;
>> +}
> cpu_to_be32() ?
>
>> +int board_init(void)
>> +{
>> + gd->bd->bi_arch_number = -1;
> Just don't set it?
>
>> +void enable_caches(void)
>> +{
>> +#ifndef CONFIG_SYS_DCACHE_OFF
>> + /* Enable D-cache. I-cache is already enabled in start.S */
>> + dcache_enable();
>> +#endif
>> +}
> This belongs in one of the arch/arm/cpu/armv7/keystone/ files
>
>> +++ b/drivers/i2c/keystone_i2c.c
>> @@ -0,0 +1,372 @@
>> +/*
>> + * TI Keystone i2c driver
>> + * Based on TI DaVinci (TMS320DM644x) I2C driver.
> And how different is it really? Can we not reuse the davinci driver?
>
It is reworked a little bit and also supports multiple ports, while
davinci driver
supports only one.
I'll check out other comment as well.
Thanks,
Vitaly
next prev parent reply other threads:[~2014-02-11 1:44 UTC|newest]
Thread overview: 129+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <yes>
2009-07-28 16:34 ` [U-Boot] [RFC 0/3] uboot-doc User's Manual Generation Tool John Schmoller
2009-07-28 17:49 ` Wolfgang Denk
2009-07-28 20:40 ` jschmoller
2009-07-28 21:27 ` Wolfgang Denk
2009-07-28 22:16 ` Robin Getz
2009-07-30 9:59 ` Detlev Zundel
2009-07-30 18:45 ` Wolfgang Denk
2009-07-30 19:50 ` Robin Getz
2009-07-30 19:55 ` Wolfgang Denk
2009-07-31 1:49 ` Robin Getz
2009-08-13 7:32 ` Mike Frysinger
2009-07-29 14:48 ` jschmoller
2009-07-28 16:34 ` [U-Boot] [RFC 1/3] uboot-doc: Initial support of user documentation generator John Schmoller
2009-07-28 16:34 ` [U-Boot] [RFC 2/3] uboot-doc: Add example support for uboot-doc John Schmoller
2009-07-28 17:52 ` Wolfgang Denk
2009-07-28 20:42 ` jschmoller
2009-07-28 21:37 ` Wolfgang Denk
2009-07-28 16:34 ` [U-Boot] [RFC 3/3] xpedite5370: Add uboot-doc support John Schmoller
2011-05-02 21:01 ` [U-Boot] [PATCH v4 0/5] Add support for LaCie NAS Network Space v2 Simon Guinot
2011-05-02 21:29 ` Wolfgang Denk
2011-05-02 22:46 ` Simon Guinot
2011-05-02 21:01 ` [U-Boot] [PATCH v4 1/5] sf: disable write protection for Macronix flash Simon Guinot
2011-05-02 21:07 ` Mike Frysinger
2011-05-02 21:01 ` [U-Boot] [PATCH v4 2/5] Kirkwood: allow to override CONFIG_SYS_TCLK Simon Guinot
2011-05-02 21:01 ` [U-Boot] [PATCH v4 3/5] mv-common.h: fix DRAM banks configuration Simon Guinot
2011-05-02 21:01 ` [U-Boot] [PATCH v4 4/5] netconsole: remove `serverip' check Simon Guinot
2011-05-02 21:01 ` [U-Boot] [PATCH v4 5/5] Add support for Network Space v2 Simon Guinot
2011-05-02 22:42 ` [U-Boot] [PATCH v5 0/5] Add support for LaCie NAS " Simon Guinot
2011-05-03 9:59 ` Prafulla Wadaskar
2011-05-02 22:42 ` [U-Boot] [PATCH v5 1/5] sf: disable write protection for Macronix flash Simon Guinot
2011-07-08 20:32 ` [U-Boot] [PATCH v6] sf: macronix: disable write protection when initializing Mike Frysinger
2011-08-02 20:02 ` Wolfgang Denk
2011-05-02 22:42 ` [U-Boot] [PATCH v5 2/5] Kirkwood: allow to override CONFIG_SYS_TCLK Simon Guinot
2011-05-03 12:09 ` Prafulla Wadaskar
2011-05-02 22:42 ` [U-Boot] [PATCH v5 3/5] mv-common.h: fix DRAM banks configuration Simon Guinot
2011-05-03 12:09 ` Prafulla Wadaskar
2011-05-02 22:42 ` [U-Boot] [PATCH v5 4/5] netconsole: remove `serverip' check Simon Guinot
2011-05-02 22:42 ` [U-Boot] [PATCH v5 5/5] Add support for Network Space v2 Simon Guinot
2011-05-03 13:19 ` Simon Guinot
2011-05-12 17:24 ` Wolfgang Denk
2012-02-16 2:59 ` [U-Boot] [PATCH 0/5] Support for qualcomm msm7630 board mohamed.haneef at lntinfotech.com
2012-02-23 8:59 ` [U-Boot] reminder for " Mohamed Haneef
2012-10-26 21:15 ` [U-Boot] " Albert ARIBAUD
2012-02-16 2:59 ` [U-Boot] [PATCH 1/5] msm7x30: Add support for low speed uart on msm7x30 mohamed.haneef at lntinfotech.com
2012-02-28 23:44 ` Albert ARIBAUD
2012-03-05 14:34 ` [U-Boot] [PATCH v2 1/5] msm7x30: Add Support " Mohamed Haneef
2012-03-22 8:50 ` [U-Boot] reminder for [PATCH 0/5] Support for qualcomm msm7630 board mohamed.haneef at lntinfotech.com
2012-04-23 9:24 ` [U-Boot] (no subject) mohamed.haneef at lntinfotech.com
2012-04-23 9:31 ` [U-Boot] msm7630 mainline request mohamed.haneef at lntinfotech.com
2012-05-03 0:09 ` Marek Vasut
2012-02-16 2:59 ` [U-Boot] [PATCH 2/5] msm7x30: Add support for interprocessor communication mohamed.haneef at lntinfotech.com
2012-02-28 23:46 ` Albert ARIBAUD
2012-03-05 14:33 ` Mohamed Haneef
2012-02-16 2:59 ` [U-Boot] [PATCH 3/5] msm7x30: Add support for Qualcomm msm7630 soc mohamed.haneef at lntinfotech.com
2012-02-29 0:00 ` Albert ARIBAUD
2012-03-05 14:39 ` [U-Boot] [PATCH v2 3/5] msm7x30: Add support for msm7x30 SoC Mohamed Haneef
2012-02-16 2:59 ` [U-Boot] [PATCH 4/5] Add support for mmc read and writes mohamed.haneef at lntinfotech.com
2012-02-29 0:03 ` Albert ARIBAUD
2012-03-05 14:40 ` [U-Boot] [PATCH v2 4/5] Add Support for qc_mmc MMC Controller Mohamed Haneef
2012-05-03 22:05 ` Andy Fleming
2012-05-10 11:37 ` Mohamed Haneef
2012-02-16 2:59 ` [U-Boot] [PATCH 5/5] msm7x30: Add support for msm7630_surf board mohamed.haneef at lntinfotech.com
2012-10-03 8:19 ` Albert ARIBAUD
2014-02-07 23:23 ` [U-Boot] [U-Boot: RESEND][PATCH 0/7] Add support for Keystone2 SoC and K2HK EVM Murali Karicheri
2014-02-07 23:23 ` [U-Boot] [U-Boot:RESEND][[PATCH 1/7] fdt: call ft_board_setup_ex() at the end of image_setup_libfdt() Murali Karicheri
2014-02-10 21:25 ` Tom Rini
2014-02-11 1:05 ` Vitaly Andrianov
2014-02-07 23:23 ` [U-Boot] [U-Boot:RESEND][[PATCH 2/7] tools: sort the entries in Makefile Murali Karicheri
2014-02-07 23:23 ` [U-Boot] [U-Boot:RESEND][[PATCH 3/7 v1] tools: mkimage: add support for gpimage format Murali Karicheri
2014-02-07 23:23 ` [U-Boot] [U-Boot:RESEND][[PATCH 4/7 v1] arm: add support for arch timer Murali Karicheri
2014-02-07 23:23 ` [U-Boot] [U-Boot:RESEND][[PATCH 5/7 v1] NAND: DaVinci: allow forced disable of subpage writes Murali Karicheri
2014-02-07 23:23 ` [U-Boot] [U-Boot:RESEND][[PATCH 6/7] k2hk: add support for k2hk SOC and EVM Murali Karicheri
2014-02-10 21:25 ` Tom Rini
2014-02-11 1:44 ` Vitaly Andrianov [this message]
2014-02-12 12:53 ` Tom Rini
2014-02-17 21:19 ` Andrianov, Vitaly
2014-02-17 21:57 ` Tom Rini
2014-02-20 17:27 ` Andrianov, Vitaly
2014-02-10 8:32 ` [U-Boot] [U-Boot: RESEND][PATCH 0/7] Add support for Keystone2 SoC and K2HK EVM Albert ARIBAUD
2014-02-10 17:22 ` Murali Karicheri
2014-02-10 18:01 ` Albert ARIBAUD
2014-02-10 19:42 ` Murali Karicheri
2014-02-10 19:58 ` Albert ARIBAUD
2014-02-10 21:23 ` Tom Rini
2014-02-20 17:55 ` [U-Boot] [U-Boot PATCH v2 00/12] Add support for keystone2 " Murali Karicheri
2014-02-20 17:55 ` [U-Boot] [U-Boot PATCH v2 01/12] fdt: call ft_board_setup_ex() at the end of image_setup_libfdt() Murali Karicheri
2014-02-25 22:10 ` Tom Rini
2014-02-20 17:55 ` [U-Boot] [U-Boot PATCH v2 02/12] tools: sort the entries in Makefile Murali Karicheri
2014-02-25 22:10 ` Tom Rini
2014-02-20 17:55 ` [U-Boot] [U-Boot PATCH v2 03/12] tools: mkimage: add support for gpimage format Murali Karicheri
2014-02-25 22:11 ` Tom Rini
2014-02-20 17:55 ` [U-Boot] [U-Boot PATCH v2 04/12] arm: add support for arch timer Murali Karicheri
2014-02-25 22:11 ` Tom Rini
2014-02-20 17:55 ` [U-Boot] [U-Boot PATCH v2 05/12] NAND: DaVinci: allow forced disable of subpage writes Murali Karicheri
2014-02-25 22:11 ` Tom Rini
2014-02-26 4:01 ` Scott Wood
2014-02-27 16:38 ` Murali Karicheri
[not found] ` <3E54258959B69E4282D79E01AB1F32B7046C27D5@DFLE11.ent.ti.com>
2014-02-27 19:21 ` Scott Wood
2014-02-27 21:20 ` Murali Karicheri
2014-02-20 17:55 ` [U-Boot] [U-Boot PATCH v2 06/12] i2c, davinci: move i2c_defs.h to the drivers/i2c directory Murali Karicheri
2014-02-25 22:11 ` Tom Rini
2014-02-20 17:55 ` [U-Boot] [U-Boot PATCH v2 07/12] i2c, davinci: add support for multiple i2c buses Murali Karicheri
2014-02-25 22:11 ` Tom Rini
2014-02-20 17:55 ` [U-Boot] [U-Boot PATCH v2 08/12] k2hk: add support for k2hk SOC and EVM Murali Karicheri
2014-02-25 22:11 ` Tom Rini
2014-03-03 18:20 ` Murali Karicheri
2014-03-03 18:29 ` Tom Rini
2014-03-06 19:09 ` Andrianov, Vitaly
2014-03-06 19:29 ` Tom Rini
2014-03-07 16:41 ` Andrianov, Vitaly
2014-03-07 16:50 ` Tom Rini
2014-03-07 21:21 ` Murali Karicheri
2014-03-07 21:27 ` Tom Rini
2014-02-20 17:55 ` [U-Boot] [U-Boot PATCH v2 09/12] keystone2: add keystone multicore navigator driver Murali Karicheri
2014-02-25 22:12 ` Tom Rini
2014-02-20 17:55 ` [U-Boot] [U-Boot PATCH v2 10/12] keystone2: net: add keystone ethernet driver Murali Karicheri
2014-02-25 22:11 ` Tom Rini
2014-03-12 19:04 ` Murali Karicheri
2014-03-12 20:01 ` Tom Rini
2014-02-20 17:55 ` [U-Boot] [U-Boot PATCH v2 11/12] spi: davinci: add support for multiple bus and chip select Murali Karicheri
2014-02-25 22:12 ` Tom Rini
2014-02-20 17:55 ` [U-Boot] [U-Boot PATCH v2 12/12] k2hk-evm: add configuration for spi1 and spi2 support Murali Karicheri
2014-02-25 22:12 ` Tom Rini
2014-02-25 22:10 ` [U-Boot] [U-Boot PATCH v2 00/12] Add support for keystone2 SoC and K2HK EVM Tom Rini
2014-02-27 16:18 ` Karicheri, Muralidharan
2014-03-12 19:21 ` Murali Karicheri
2014-03-12 19:35 ` Tom Rini
2014-02-25 22:49 ` Karicheri, Muralidharan
2014-02-25 22:51 ` Tom Rini
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=52F98061.5090902@ti.com \
--to=vitalya@ti.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox