From: Lucas Stach <l.stach@pengutronix.de>
To: Shawn Guo <shawnguo@kernel.org>, Rob Herring <robh+dt@kernel.org>
Cc: NXP Linux Team <linux-imx@nxp.com>,
Adam Ford <aford173@gmail.com>,
Frieder Schrempf <frieder.schrempf@kontron.de>,
Peng Fan <peng.fan@nxp.com>, Marek Vasut <marex@denx.de>,
devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
kernel@pengutronix.de, patchwork-lst@pengutronix.de
Subject: [PATCH v2 02/18] soc: imx: gpcv2: Turn domain->pgc into bitfield
Date: Wed, 21 Jul 2021 22:46:47 +0200 [thread overview]
Message-ID: <20210721204703.1424034-3-l.stach@pengutronix.de> (raw)
In-Reply-To: <20210721204703.1424034-1-l.stach@pengutronix.de>
From: Marek Vasut <marex@denx.de>
There is currently the MX8MM GPU domain, which is in fact a composite domain
for both GPU2D and GPU3D. To correctly configure this domain, it is necessary
to control both GPC_PGC_nCTRL(GPU_2D) and GPC_PGC_nCTRL(GPU_3D) at the same
time. This is currently not possible.
Turn the domain->pgc from value into bitfield and use for_each_set_bit() to
iterate over all bits set in domain->pgc when configuring GPC_PGC_nCTRL
register array. This way it is possible to configure all GPC_PGC_nCTRL
registers required in a particular domain.
This is a preparatory patch, no functional change.
Signed-off-by: Marek Vasut <marex@denx.de>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
v2 (Lucas Stach):
- rebase on top of reverted reset sequence change
- also convert i.MX8MN domains
---
drivers/soc/imx/gpcv2.c | 72 ++++++++++++++++++++++-------------------
1 file changed, 38 insertions(+), 34 deletions(-)
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
index 8b7a01773aec..c7826ce92f0d 100644
--- a/drivers/soc/imx/gpcv2.c
+++ b/drivers/soc/imx/gpcv2.c
@@ -192,7 +192,7 @@ struct imx_pgc_domain {
struct clk_bulk_data *clks;
int num_clks;
- unsigned int pgc;
+ unsigned long pgc;
const struct {
u32 pxx;
@@ -220,7 +220,7 @@ to_imx_pgc_domain(struct generic_pm_domain *genpd)
static int imx_pgc_power_up(struct generic_pm_domain *genpd)
{
struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd);
- u32 reg_val;
+ u32 reg_val, pgc;
int ret;
ret = pm_runtime_get_sync(domain->dev);
@@ -264,8 +264,10 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
}
/* disable power control */
- regmap_clear_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
- GPC_PGC_CTRL_PCR);
+ for_each_set_bit(pgc, &domain->pgc, 32) {
+ regmap_clear_bits(domain->regmap, GPC_PGC_CTRL(pgc),
+ GPC_PGC_CTRL_PCR);
+ }
}
/* delay for reset to propagate */
@@ -311,7 +313,7 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
static int imx_pgc_power_down(struct generic_pm_domain *genpd)
{
struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd);
- u32 reg_val;
+ u32 reg_val, pgc;
int ret;
/* Enable reset clocks for all devices in the domain */
@@ -338,8 +340,10 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
if (domain->bits.pxx) {
/* enable power control */
- regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
- GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
+ for_each_set_bit(pgc, &domain->pgc, 32) {
+ regmap_update_bits(domain->regmap, GPC_PGC_CTRL(pgc),
+ GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
+ }
/* request the domain to power down */
regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PDN_REQ,
@@ -389,7 +393,7 @@ static const struct imx_pgc_domain imx7_pgc_domains[] = {
.map = IMX7_MIPI_PHY_A_CORE_DOMAIN,
},
.voltage = 1000000,
- .pgc = IMX7_PGC_MIPI,
+ .pgc = BIT(IMX7_PGC_MIPI),
},
[IMX7_POWER_DOMAIN_PCIE_PHY] = {
@@ -401,7 +405,7 @@ static const struct imx_pgc_domain imx7_pgc_domains[] = {
.map = IMX7_PCIE_PHY_A_CORE_DOMAIN,
},
.voltage = 1000000,
- .pgc = IMX7_PGC_PCIE,
+ .pgc = BIT(IMX7_PGC_PCIE),
},
[IMX7_POWER_DOMAIN_USB_HSIC_PHY] = {
@@ -413,7 +417,7 @@ static const struct imx_pgc_domain imx7_pgc_domains[] = {
.map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN,
},
.voltage = 1200000,
- .pgc = IMX7_PGC_USB_HSIC,
+ .pgc = BIT(IMX7_PGC_USB_HSIC),
},
};
@@ -448,7 +452,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
.pxx = IMX8M_MIPI_SW_Pxx_REQ,
.map = IMX8M_MIPI_A53_DOMAIN,
},
- .pgc = IMX8M_PGC_MIPI,
+ .pgc = BIT(IMX8M_PGC_MIPI),
},
[IMX8M_POWER_DOMAIN_PCIE1] = {
@@ -459,7 +463,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
.pxx = IMX8M_PCIE1_SW_Pxx_REQ,
.map = IMX8M_PCIE1_A53_DOMAIN,
},
- .pgc = IMX8M_PGC_PCIE1,
+ .pgc = BIT(IMX8M_PGC_PCIE1),
},
[IMX8M_POWER_DOMAIN_USB_OTG1] = {
@@ -470,7 +474,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
.pxx = IMX8M_OTG1_SW_Pxx_REQ,
.map = IMX8M_OTG1_A53_DOMAIN,
},
- .pgc = IMX8M_PGC_OTG1,
+ .pgc = BIT(IMX8M_PGC_OTG1),
},
[IMX8M_POWER_DOMAIN_USB_OTG2] = {
@@ -481,7 +485,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
.pxx = IMX8M_OTG2_SW_Pxx_REQ,
.map = IMX8M_OTG2_A53_DOMAIN,
},
- .pgc = IMX8M_PGC_OTG2,
+ .pgc = BIT(IMX8M_PGC_OTG2),
},
[IMX8M_POWER_DOMAIN_DDR1] = {
@@ -492,7 +496,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
.pxx = IMX8M_DDR1_SW_Pxx_REQ,
.map = IMX8M_DDR2_A53_DOMAIN,
},
- .pgc = IMX8M_PGC_DDR1,
+ .pgc = BIT(IMX8M_PGC_DDR1),
},
[IMX8M_POWER_DOMAIN_GPU] = {
@@ -505,7 +509,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
.hskreq = IMX8M_GPU_HSK_PWRDNREQN,
.hskack = IMX8M_GPU_HSK_PWRDNACKN,
},
- .pgc = IMX8M_PGC_GPU,
+ .pgc = BIT(IMX8M_PGC_GPU),
},
[IMX8M_POWER_DOMAIN_VPU] = {
@@ -518,7 +522,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
.hskreq = IMX8M_VPU_HSK_PWRDNREQN,
.hskack = IMX8M_VPU_HSK_PWRDNACKN,
},
- .pgc = IMX8M_PGC_VPU,
+ .pgc = BIT(IMX8M_PGC_VPU),
},
[IMX8M_POWER_DOMAIN_DISP] = {
@@ -531,7 +535,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
.hskreq = IMX8M_DISP_HSK_PWRDNREQN,
.hskack = IMX8M_DISP_HSK_PWRDNACKN,
},
- .pgc = IMX8M_PGC_DISP,
+ .pgc = BIT(IMX8M_PGC_DISP),
},
[IMX8M_POWER_DOMAIN_MIPI_CSI1] = {
@@ -542,7 +546,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
.pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ,
.map = IMX8M_MIPI_CSI1_A53_DOMAIN,
},
- .pgc = IMX8M_PGC_MIPI_CSI1,
+ .pgc = BIT(IMX8M_PGC_MIPI_CSI1),
},
[IMX8M_POWER_DOMAIN_MIPI_CSI2] = {
@@ -553,7 +557,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
.pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ,
.map = IMX8M_MIPI_CSI2_A53_DOMAIN,
},
- .pgc = IMX8M_PGC_MIPI_CSI2,
+ .pgc = BIT(IMX8M_PGC_MIPI_CSI2),
},
[IMX8M_POWER_DOMAIN_PCIE2] = {
@@ -564,7 +568,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
.pxx = IMX8M_PCIE2_SW_Pxx_REQ,
.map = IMX8M_PCIE2_A53_DOMAIN,
},
- .pgc = IMX8M_PGC_PCIE2,
+ .pgc = BIT(IMX8M_PGC_PCIE2),
},
};
@@ -627,7 +631,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
.pxx = IMX8MM_PCIE_SW_Pxx_REQ,
.map = IMX8MM_PCIE_A53_DOMAIN,
},
- .pgc = IMX8MM_PGC_PCIE,
+ .pgc = BIT(IMX8MM_PGC_PCIE),
},
[IMX8MM_POWER_DOMAIN_OTG1] = {
@@ -638,7 +642,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
.pxx = IMX8MM_OTG1_SW_Pxx_REQ,
.map = IMX8MM_OTG1_A53_DOMAIN,
},
- .pgc = IMX8MM_PGC_OTG1,
+ .pgc = BIT(IMX8MM_PGC_OTG1),
},
[IMX8MM_POWER_DOMAIN_OTG2] = {
@@ -649,7 +653,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
.pxx = IMX8MM_OTG2_SW_Pxx_REQ,
.map = IMX8MM_OTG2_A53_DOMAIN,
},
- .pgc = IMX8MM_PGC_OTG2,
+ .pgc = BIT(IMX8MM_PGC_OTG2),
},
[IMX8MM_POWER_DOMAIN_GPUMIX] = {
@@ -662,7 +666,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
.hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN,
.hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN,
},
- .pgc = IMX8MM_PGC_GPUMIX,
+ .pgc = BIT(IMX8MM_PGC_GPUMIX),
},
[IMX8MM_POWER_DOMAIN_GPU] = {
@@ -675,7 +679,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
.hskreq = IMX8MM_GPU_HSK_PWRDNREQN,
.hskack = IMX8MM_GPU_HSK_PWRDNACKN,
},
- .pgc = IMX8MM_PGC_GPU2D,
+ .pgc = BIT(IMX8MM_PGC_GPU2D),
},
[IMX8MM_POWER_DOMAIN_VPUMIX] = {
@@ -688,7 +692,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
.hskreq = IMX8MM_VPUMIX_HSK_PWRDNREQN,
.hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN,
},
- .pgc = IMX8MM_PGC_VPUMIX,
+ .pgc = BIT(IMX8MM_PGC_VPUMIX),
},
[IMX8MM_POWER_DOMAIN_VPUG1] = {
@@ -699,7 +703,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
.pxx = IMX8MM_VPUG1_SW_Pxx_REQ,
.map = IMX8MM_VPUG1_A53_DOMAIN,
},
- .pgc = IMX8MM_PGC_VPUG1,
+ .pgc = BIT(IMX8MM_PGC_VPUG1),
},
[IMX8MM_POWER_DOMAIN_VPUG2] = {
@@ -710,7 +714,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
.pxx = IMX8MM_VPUG2_SW_Pxx_REQ,
.map = IMX8MM_VPUG2_A53_DOMAIN,
},
- .pgc = IMX8MM_PGC_VPUG2,
+ .pgc = BIT(IMX8MM_PGC_VPUG2),
},
[IMX8MM_POWER_DOMAIN_VPUH1] = {
@@ -721,7 +725,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
.pxx = IMX8MM_VPUH1_SW_Pxx_REQ,
.map = IMX8MM_VPUH1_A53_DOMAIN,
},
- .pgc = IMX8MM_PGC_VPUH1,
+ .pgc = BIT(IMX8MM_PGC_VPUH1),
},
[IMX8MM_POWER_DOMAIN_DISPMIX] = {
@@ -734,7 +738,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
.hskreq = IMX8MM_DISPMIX_HSK_PWRDNREQN,
.hskack = IMX8MM_DISPMIX_HSK_PWRDNACKN,
},
- .pgc = IMX8MM_PGC_DISPMIX,
+ .pgc = BIT(IMX8MM_PGC_DISPMIX),
},
[IMX8MM_POWER_DOMAIN_MIPI] = {
@@ -745,7 +749,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
.pxx = IMX8MM_MIPI_SW_Pxx_REQ,
.map = IMX8MM_MIPI_A53_DOMAIN,
},
- .pgc = IMX8MM_PGC_MIPI,
+ .pgc = BIT(IMX8MM_PGC_MIPI),
},
};
@@ -812,7 +816,7 @@ static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
.pxx = IMX8MN_OTG1_SW_Pxx_REQ,
.map = IMX8MN_OTG1_A53_DOMAIN,
},
- .pgc = IMX8MN_PGC_OTG1,
+ .pgc = BIT(IMX8MN_PGC_OTG1),
},
[IMX8MN_POWER_DOMAIN_GPUMIX] = {
@@ -825,7 +829,7 @@ static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
.hskreq = IMX8MN_GPUMIX_HSK_PWRDNREQN,
.hskack = IMX8MN_GPUMIX_HSK_PWRDNACKN,
},
- .pgc = IMX8MN_PGC_GPUMIX,
+ .pgc = BIT(IMX8MN_PGC_GPUMIX),
},
};
--
2.30.2
next prev parent reply other threads:[~2021-07-21 20:47 UTC|newest]
Thread overview: 68+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-16 23:28 [PATCH 00/17] i.MX8MM GPC improvements and BLK_CTRL driver Lucas Stach
2021-07-16 23:29 ` [PATCH 01/17] Revert "soc: imx: gpcv2: move reset assert after requesting domain power up" Lucas Stach
2021-07-16 23:29 ` [PATCH 02/17] soc: imx: gpcv2: Turn domain->pgc into bitfield Lucas Stach
2021-07-16 23:29 ` [PATCH 03/17] soc: imx: gpcv2: Set both GPC_PGC_nCTRL(GPU_2D|GPU_3D) for MX8MM GPU domain Lucas Stach
2021-07-16 23:29 ` [PATCH 04/17] soc: imx: gpcv2: add lockdep annotation Lucas Stach
2021-07-16 23:29 ` [PATCH 05/17] soc: imx: gpcv2: add domain option to keep domain clocks enabled Lucas Stach
2021-07-16 23:29 ` [PATCH 06/17] soc: imx: gpcv2: keep i.MX8M* bus " Lucas Stach
2021-07-16 23:29 ` [PATCH 07/17] dt-bindings: soc: add binding for i.MX8MM VPU blk-ctrl Lucas Stach
2021-07-19 13:47 ` Rob Herring
2021-07-16 23:29 ` [PATCH 08/17] dt-bindings: power: imx8mm: add defines for VPU blk-ctrl domains Lucas Stach
2021-07-16 23:29 ` [PATCH 09/17] soc: imx: add i.MX8M blk-ctrl driver Lucas Stach
2021-07-19 6:12 ` Dan Carpenter
2021-07-19 9:11 ` Lucas Stach
2021-07-16 23:29 ` [PATCH 10/17] dt-bindings: soc: add binding for i.MX8MM DISP blk-ctrl Lucas Stach
2021-07-19 13:47 ` Rob Herring
2021-07-16 23:29 ` [PATCH 11/17] dt-bindings: power: imx8mm: add defines for DISP blk-ctrl domains Lucas Stach
2021-07-16 23:29 ` [PATCH 12/17] soc: imx: imx8m-blk-ctrl: add DISP blk-ctrl Lucas Stach
2021-07-16 23:29 ` [PATCH 13/17] arm64: dts: imx8mm: add GPC node Lucas Stach
2021-07-16 23:29 ` [PATCH 14/17] arm64: dts: imx8mm: put USB controllers into power-domains Lucas Stach
2021-07-16 23:29 ` [PATCH 15/17] arm64: dts: imx8mm: Add GPU nodes for 2D and 3D core Lucas Stach
2021-07-16 23:29 ` [PATCH 16/17] arm64: dts: imx8mm: add VPU blk-ctrl Lucas Stach
2021-07-16 23:29 ` [PATCH 17/17] arm64: dts: imx8mm: add DISP blk-ctrl Lucas Stach
2021-07-19 12:53 ` [PATCH 00/17] i.MX8MM GPC improvements and BLK_CTRL driver Peng Fan
2021-07-19 16:56 ` Lucas Stach
2021-07-21 11:21 ` Lucas Stach
2021-07-21 20:46 ` [PATCH v2 00/18] " Lucas Stach
2021-07-21 20:46 ` [PATCH v2 01/18] Revert "soc: imx: gpcv2: move reset assert after requesting domain power up" Lucas Stach
2021-08-05 9:37 ` Peng Fan
2021-07-21 20:46 ` Lucas Stach [this message]
2021-08-05 9:37 ` [PATCH v2 02/18] soc: imx: gpcv2: Turn domain->pgc into bitfield Peng Fan
2021-07-21 20:46 ` [PATCH v2 03/18] soc: imx: gpcv2: Set both GPC_PGC_nCTRL(GPU_2D|GPU_3D) for MX8MM GPU domain Lucas Stach
2021-08-05 9:37 ` Peng Fan
2021-07-21 20:46 ` [PATCH v2 04/18] soc: imx: gpcv2: add lockdep annotation Lucas Stach
2021-08-05 9:38 ` Peng Fan
2021-07-21 20:46 ` [PATCH v2 05/18] soc: imx: gpcv2: add domain option to keep domain clocks enabled Lucas Stach
2021-08-05 9:38 ` Peng Fan
2021-07-21 20:46 ` [PATCH v2 06/18] soc: imx: gpcv2: keep i.MX8M* bus " Lucas Stach
2021-08-05 9:39 ` Peng Fan
2021-07-21 20:46 ` [PATCH v2 07/18] soc: imx: gpcv2: support system suspend/resume Lucas Stach
2021-08-05 9:47 ` Peng Fan
2021-07-21 20:46 ` [PATCH v2 08/18] dt-bindings: soc: add binding for i.MX8MM VPU blk-ctrl Lucas Stach
2021-07-22 14:37 ` Rob Herring
2021-07-21 20:46 ` [PATCH v2 09/18] dt-bindings: power: imx8mm: add defines for VPU blk-ctrl domains Lucas Stach
2021-07-21 20:46 ` [PATCH v2 10/18] soc: imx: add i.MX8M blk-ctrl driver Lucas Stach
2021-08-05 9:54 ` Peng Fan
2021-07-21 20:46 ` [PATCH v2 11/18] dt-bindings: soc: add binding for i.MX8MM DISP blk-ctrl Lucas Stach
2021-07-22 14:37 ` Rob Herring
2021-07-21 20:46 ` [PATCH v2 12/18] dt-bindings: power: imx8mm: add defines for DISP blk-ctrl domains Lucas Stach
2021-07-21 20:46 ` [PATCH v2 13/18] soc: imx: imx8m-blk-ctrl: add DISP blk-ctrl Lucas Stach
2021-08-05 9:53 ` Peng Fan
2021-07-21 20:46 ` [PATCH v2 14/18] arm64: dts: imx8mm: add GPC node Lucas Stach
2021-08-05 9:54 ` Peng Fan
2021-07-21 20:47 ` [PATCH v2 15/18] arm64: dts: imx8mm: put USB controllers into power-domains Lucas Stach
2021-07-21 20:47 ` [PATCH v2 16/18] arm64: dts: imx8mm: Add GPU nodes for 2D and 3D core Lucas Stach
2021-07-21 20:47 ` [PATCH v2 17/18] arm64: dts: imx8mm: add VPU blk-ctrl Lucas Stach
2021-07-21 20:47 ` [PATCH v2 18/18] arm64: dts: imx8mm: add DISP blk-ctrl Lucas Stach
2021-08-05 9:35 ` [PATCH v2 00/18] i.MX8MM GPC improvements and BLK_CTRL driver Peng Fan (OSS)
2021-08-05 10:18 ` Frieder Schrempf
2021-08-05 18:56 ` Frieder Schrempf
2021-08-09 11:01 ` Lucas Stach
2021-08-09 11:50 ` Frieder Schrempf
2021-08-09 18:51 ` Adam Ford
2021-09-01 10:03 ` Frieder Schrempf
2021-09-01 12:16 ` Frieder Schrempf
2021-09-02 10:25 ` Lucas Stach
2021-09-06 7:49 ` Frieder Schrempf
2021-08-30 22:06 ` Tim Harvey
2021-09-01 10:30 ` Frieder Schrempf
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=20210721204703.1424034-3-l.stach@pengutronix.de \
--to=l.stach@pengutronix.de \
--cc=aford173@gmail.com \
--cc=devicetree@vger.kernel.org \
--cc=frieder.schrempf@kontron.de \
--cc=kernel@pengutronix.de \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-imx@nxp.com \
--cc=marex@denx.de \
--cc=patchwork-lst@pengutronix.de \
--cc=peng.fan@nxp.com \
--cc=robh+dt@kernel.org \
--cc=shawnguo@kernel.org \
/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;
as well as URLs for NNTP newsgroup(s).