linux-iio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] iio: dps310: Add pressure sensing capability
@ 2019-05-01 14:43 Eddie James
  2019-05-03  2:34 ` Joel Stanley
  0 siblings, 1 reply; 4+ messages in thread
From: Eddie James @ 2019-05-01 14:43 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-iio, joel, pmeerw, lars, knaack.h, jic23, Eddie James

The DPS310 supports measurement of pressure, so support that in the
driver. Use background measurement like the temperature sensing and
default to lowest precision and lowest measurement rate.

Signed-off-by: Eddie James <eajames@linux.ibm.com>
---
 drivers/iio/pressure/dps310.c | 350 +++++++++++++++++++++++++++++++++++++-----
 1 file changed, 314 insertions(+), 36 deletions(-)

diff --git a/drivers/iio/pressure/dps310.c b/drivers/iio/pressure/dps310.c
index beb8b11..48cf83c 100644
--- a/drivers/iio/pressure/dps310.c
+++ b/drivers/iio/pressure/dps310.c
@@ -23,6 +23,7 @@
  */
 
 #include <linux/i2c.h>
+#include <linux/math64.h>
 #include <linux/module.h>
 #include <linux/regmap.h>
 
@@ -36,13 +37,15 @@
 #define DPS310_TMP_B1		0x04
 #define DPS310_TMP_B2		0x05
 #define DPS310_PRS_CFG		0x06
+#define  DPS310_PRS_RATE_BITS	GENMASK(6, 4)
+#define  DPS310_PRS_PRC_BITS	GENMASK(3, 0)
 #define DPS310_TMP_CFG		0x07
 #define  DPS310_TMP_RATE_BITS	GENMASK(6, 4)
 #define  DPS310_TMP_PRC_BITS	GENMASK(3, 0)
 #define  DPS310_TMP_EXT		BIT(7)
 #define DPS310_MEAS_CFG		0x08
 #define  DPS310_MEAS_CTRL_BITS	GENMASK(2, 0)
-#define   DPS310_PRESSURE_EN	BIT(0)
+#define   DPS310_PRS_EN		BIT(0)
 #define   DPS310_TEMP_EN	BIT(1)
 #define   DPS310_BACKGROUND	BIT(2)
 #define  DPS310_PRS_RDY		BIT(4)
@@ -58,16 +61,17 @@
 #define DPS310_RESET		0x0c
 #define  DPS310_RESET_MAGIC	(BIT(0) | BIT(3))
 #define DPS310_COEF_BASE	0x10
+#define DPS310_NUM_COEF_REGS	0x12
 
 #define DPS310_PRS_BASE		DPS310_PRS_B0
 #define DPS310_TMP_BASE		DPS310_TMP_B0
 
-#define DPS310_TMP_RATE(_n)	ilog2(_n)
-#define DPS310_TMP_PRC(_n)	ilog2(_n)
+#define DPS310_CALC_RATE(_n)	ilog2(_n)
+#define DPS310_CALC_PRC(_n)	ilog2(_n)
 
 #define MCELSIUS_PER_CELSIUS	1000
 
-const int scale_factor[] = {
+static const int scale_factor[] = {
 	 524288,
 	1572864,
 	3670016,
@@ -83,6 +87,8 @@ struct dps310_data {
 	struct regmap *regmap;
 
 	s32 c0, c1;
+	s32 c00, c10, c20, c30, c01, c11, c21;
+	s32 pressure_raw;
 	s32 temp_raw;
 };
 
@@ -95,33 +101,80 @@ struct dps310_data {
 			BIT(IIO_CHAN_INFO_SAMP_FREQ) |
 			BIT(IIO_CHAN_INFO_RAW),
 	},
+	{
+		.type = IIO_PRESSURE,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
+			BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+			BIT(IIO_CHAN_INFO_RAW),
+	},
 };
 
-/* To be called after checking the TMP_RDY bit in MEAS_CFG */
-static int dps310_get_temp_coef(struct dps310_data *data)
+/* To be called after checking the COEF_RDY bit in MEAS_CFG */
+static int dps310_get_coefs(struct dps310_data *data)
 {
 	struct regmap *regmap = data->regmap;
-	uint8_t coef[3] = {0};
 	int r;
+	u8 coef[DPS310_NUM_COEF_REGS] = {0};
 	u32 c0, c1;
+	u32 c00, c10, c20, c30, c01, c11, c21;
 
-	/*
-	 * Read temperature calibration coefficients c0 and c1 from the
-	 * COEF register. The numbers are 12-bit 2's compliment numbers
-	 */
-	r = regmap_bulk_read(regmap, DPS310_COEF_BASE, coef, 3);
+	/* Read all sensor calibration coefficients from the COEF registers. */
+	r = regmap_bulk_read(regmap, DPS310_COEF_BASE, coef,
+			     DPS310_NUM_COEF_REGS);
 	if (r < 0)
 		return r;
 
+	/*
+	 * Calculate temperature calibration coefficients c0 and c1. The numbers
+	 * are 12-bit 2's complement numbers.
+	 */
 	c0 = (coef[0] << 4) | (coef[1] >> 4);
 	data->c0 = sign_extend32(c0, 11);
 
 	c1 = ((coef[1] & GENMASK(3, 0)) << 8) | coef[2];
 	data->c1 = sign_extend32(c1, 11);
 
+	/*
+	 * Calculate pressure calibration coefficients. c00 and c10 are 20 bit
+	 * 2's complement numbers, while the rest are 16 bit 2's complement
+	 * numbers.
+	 */
+	c00 = (coef[3] << 12) | (coef[4] << 4) | (coef[5] >> 4);
+	data->c00 = sign_extend32(c00, 19);
+
+	c10 = ((coef[5] & GENMASK(3, 0)) << 16) | (coef[6] << 8) | coef[7];
+	data->c10 = sign_extend32(c10, 19);
+
+	c01 = (coef[8] << 8) | coef[9];
+	data->c01 = sign_extend32(c01, 15);
+
+	c11 = (coef[10] << 8) | coef[11];
+	data->c11 = sign_extend32(c11, 15);
+
+	c20 = (coef[12] << 8) | coef[13];
+	data->c20 = sign_extend32(c20, 15);
+
+	c21 = (coef[14] << 8) | coef[15];
+	data->c21 = sign_extend32(c21, 15);
+
+	c30 = (coef[16] << 8) | coef[17];
+	data->c30 = sign_extend32(c30, 15);
+
 	return 0;
 }
 
+static int dps310_get_pres_precision(struct dps310_data *data)
+{
+	int val, r;
+
+	r = regmap_read(data->regmap, DPS310_PRS_CFG, &val);
+	if (r < 0)
+		return r;
+
+	return BIT(val & GENMASK(2, 0));
+}
+
 static int dps310_get_temp_precision(struct dps310_data *data)
 {
 	int val, r;
@@ -137,6 +190,24 @@ static int dps310_get_temp_precision(struct dps310_data *data)
 	return BIT(val & GENMASK(2, 0));
 }
 
+static int dps310_set_pres_precision(struct dps310_data *data, int val)
+{
+	int ret;
+	u8 shift_en;
+
+	if (val < 0 || val > 128)
+		return -EINVAL;
+
+	shift_en = val >= 16 ? DPS310_PRS_SHIFT_EN : 0;
+	ret = regmap_write_bits(data->regmap, DPS310_CFG_REG,
+				DPS310_PRS_SHIFT_EN, shift_en);
+	if (ret)
+		return ret;
+
+	return regmap_update_bits(data->regmap, DPS310_PRS_CFG,
+				  DPS310_PRS_PRC_BITS, DPS310_CALC_PRC(val));
+}
+
 static int dps310_set_temp_precision(struct dps310_data *data, int val)
 {
 	int ret;
@@ -147,13 +218,26 @@ static int dps310_set_temp_precision(struct dps310_data *data, int val)
 
 	shift_en = val >= 16 ? DPS310_TMP_SHIFT_EN : 0;
 	ret = regmap_write_bits(data->regmap, DPS310_CFG_REG,
-			DPS310_TMP_SHIFT_EN,
-			shift_en);
+				DPS310_TMP_SHIFT_EN, shift_en);
+
 	if (ret)
 		return ret;
 
 	return regmap_update_bits(data->regmap, DPS310_TMP_CFG,
-			DPS310_TMP_PRC_BITS, DPS310_TMP_PRC(val));
+				  DPS310_TMP_PRC_BITS, DPS310_CALC_PRC(val));
+}
+
+static int dps310_set_pres_samp_freq(struct dps310_data *data, int freq)
+{
+	u8 val;
+
+	if (freq < 0 || freq > 128)
+		return -EINVAL;
+
+	val = DPS310_CALC_RATE(freq) << 4;
+
+	return regmap_update_bits(data->regmap, DPS310_PRS_CFG,
+				  DPS310_PRS_RATE_BITS, val);
 }
 
 static int dps310_set_temp_samp_freq(struct dps310_data *data, int freq)
@@ -163,12 +247,23 @@ static int dps310_set_temp_samp_freq(struct dps310_data *data, int freq)
 	if (freq < 0 || freq > 128)
 		return -EINVAL;
 
-	val = DPS310_TMP_RATE(freq) << 4;
+	val = DPS310_CALC_RATE(freq) << 4;
 
 	return regmap_update_bits(data->regmap, DPS310_TMP_CFG,
 			DPS310_TMP_RATE_BITS, val);
 }
 
+static int dps310_get_pres_samp_freq(struct dps310_data *data)
+{
+	int val, r;
+
+	r = regmap_read(data->regmap, DPS310_PRS_CFG, &val);
+	if (r < 0)
+		return r;
+
+	return BIT((val & DPS310_PRS_RATE_BITS) >> 4);
+}
+
 static int dps310_get_temp_samp_freq(struct dps310_data *data)
 {
 	int val, r;
@@ -180,12 +275,53 @@ static int dps310_get_temp_samp_freq(struct dps310_data *data)
 	return BIT((val & DPS310_TMP_RATE_BITS) >> 4);
 }
 
+static int dps310_get_pres_k(struct dps310_data *data)
+{
+	int r = dps310_get_pres_precision(data);
+
+	if (r < 0)
+		return r;
+
+	return scale_factor[DPS310_CALC_PRC(r)];
+}
+
 static int dps310_get_temp_k(struct dps310_data *data)
 {
-	return scale_factor[DPS310_TMP_PRC(dps310_get_temp_precision(data))];
+	int r = dps310_get_temp_precision(data);
+
+	if (r < 0)
+		return r;
+
+	return scale_factor[DPS310_CALC_PRC(r)];
+}
+
+static int dps310_read_pres_raw(struct dps310_data *data)
+{
+	struct device *dev = &data->client->dev;
+	int r, ready;
+	u8 val[3];
+	s32 raw;
+
+	r = regmap_read(data->regmap, DPS310_MEAS_CFG, &ready);
+	if (r < 0)
+		return r;
+
+	if (!(ready & DPS310_PRS_RDY)) {
+		dev_dbg(dev, "pressure not ready\n");
+		return -EAGAIN;
+	}
+
+	r = regmap_bulk_read(data->regmap, DPS310_PRS_BASE, val, 3);
+	if (r < 0)
+		return r;
+
+	raw = (val[0] << 16) | (val[1] << 8) | val[2];
+	data->pressure_raw = sign_extend32(raw, 23);
+
+	return 0;
 }
 
-static int dps310_read_temp(struct dps310_data *data)
+static int dps310_read_temp_raw(struct dps310_data *data)
 {
 	struct device *dev = &data->client->dev;
 	struct regmap *regmap = data->regmap;
@@ -251,26 +387,139 @@ static int dps310_write_raw(struct iio_dev *iio,
 {
 	struct dps310_data *data = iio_priv(iio);
 
-	if (chan->type != IIO_TEMP)
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		switch (chan->type) {
+		case IIO_PRESSURE:
+			return dps310_set_pres_samp_freq(data, val);
+
+		case IIO_TEMP:
+			return dps310_set_temp_samp_freq(data, val);
+
+		default:
+			return -EINVAL;
+		}
+
+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+		switch (chan->type) {
+		case IIO_PRESSURE:
+			return dps310_set_pres_precision(data, val);
+
+		case IIO_TEMP:
+			return dps310_set_temp_precision(data, val);
+
+		default:
+			return -EINVAL;
+		}
+
+	default:
 		return -EINVAL;
+	}
+}
+
+static int dps310_calculate_pressure(struct dps310_data *data)
+{
+	int i;
+	int kpi = dps310_get_pres_k(data);
+	int kti = dps310_get_temp_k(data);
+	s64 rem = 0ULL;
+	s64 pressure = 0ULL;
+	s64 p;
+	s64 t;
+	s64 denoms[7];
+	s64 nums[7];
+	s64 rems[7];
+	s64 kp;
+	s64 kt;
+
+	if (kpi < 0)
+		return kpi;
+
+	if (kti < 0)
+		return kti;
+
+	kp = (s64)kpi;
+	kt = (s64)kti;
+
+	/* Ignore errors and use the latest temperature */
+	dps310_read_temp_raw(data);
+
+	p = (s64)data->pressure_raw;
+	t = (s64)data->temp_raw;
+
+	/* Section 4.9.1 of the DPS310 spec; algebra'd to avoid underflow */
+	nums[0] = (s64)data->c00;
+	denoms[0] = 1LL;
+	nums[1] = p * (s64)data->c10;
+	denoms[1] = kp;
+	nums[2] = p * p * (s64)data->c20;
+	denoms[2] = kp * kp;
+	nums[3] = p * p * p * (s64)data->c30;
+	denoms[3] = kp * kp * kp;
+	nums[4] = t * (s64)data->c01;
+	denoms[4] = kt;
+	nums[5] = t * p * (s64)data->c11;
+	denoms[5] = kp * kt;
+	nums[6] = t * p * p * (s64)data->c21;
+	denoms[6] = kp * kp * kt;
+
+	/* Kernel lacks a div64_s64_rem function; denoms are all positive */
+	for (i = 0; i < 7; ++i) {
+		u64 rem;
+
+		if (nums[i] < 0LL) {
+			pressure -= div64_u64_rem(-nums[i], denoms[i], &rem);
+			rems[i] = -rem;
+		} else {
+			pressure += div64_u64_rem(nums[i], denoms[i], &rem);
+			rems[i] = (s64)rem;
+		}
+	}
+
+	/* Increase precision and calculate the remainder sum */
+	for (i = 0; i < 7; ++i)
+		rem += div64_s64((s64)rems[i] * 1000000000LL, denoms[i]);
+
+	pressure += div_s64(rem, 1000000000LL);
+
+	return (int)pressure;
+}
+
+static int dps310_read_pressure(struct dps310_data *data, int *val, int *val2,
+				long mask)
+{
+	int ret;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_SAMP_FREQ:
-		return dps310_set_temp_samp_freq(data, val);
+		*val = dps310_get_pres_samp_freq(data);
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_RAW:
+		ret = dps310_read_pres_raw(data);
+		if (ret)
+			return ret;
+
+		*val = dps310_calculate_pressure(data);
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_SCALE:
+		*val = 1;
+		*val2 = 1000; /* Convert Pa to KPa per IIO ABI */
+		return IIO_VAL_FRACTIONAL;
+
 	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
-		return dps310_set_temp_precision(data, val);
+		*val = dps310_get_pres_precision(data);
+		return IIO_VAL_INT;
+
 	default:
 		return -EINVAL;
 	}
-
-	return -EINVAL;
 }
 
-static int dps310_read_raw(struct iio_dev *iio,
-			   struct iio_chan_spec const *chan,
-			   int *val, int *val2, long mask)
+static int dps310_read_temp(struct dps310_data *data, int *val, int *val2,
+			    long mask)
 {
-	struct dps310_data *data = iio_priv(iio);
 	int ret;
 
 	switch (mask) {
@@ -279,7 +528,7 @@ static int dps310_read_raw(struct iio_dev *iio,
 		return IIO_VAL_INT;
 
 	case IIO_CHAN_INFO_RAW:
-		ret = dps310_read_temp(data);
+		ret = dps310_read_temp_raw(data);
 		if (ret)
 			return ret;
 
@@ -302,8 +551,24 @@ static int dps310_read_raw(struct iio_dev *iio,
 	default:
 		return -EINVAL;
 	}
+}
 
-	return -EINVAL;
+static int dps310_read_raw(struct iio_dev *iio,
+			   struct iio_chan_spec const *chan,
+			   int *val, int *val2, long mask)
+{
+	struct dps310_data *data = iio_priv(iio);
+
+	switch (chan->type) {
+	case IIO_PRESSURE:
+		return dps310_read_pressure(data, val, val2, mask);
+
+	case IIO_TEMP:
+		return dps310_read_temp(data, val, val2, mask);
+
+	default:
+		return -EINVAL;
+	}
 }
 
 static const struct regmap_config dps310_regmap_config = {
@@ -385,24 +650,37 @@ static int dps310_probe(struct i2c_client *client,
 		return PTR_ERR(data->regmap);
 
 	/*
+	 * Set up pressure sensor in single sample, one measurement per second
+	 * mode
+	 */
+	r = regmap_write(data->regmap, DPS310_PRS_CFG,
+			 DPS310_CALC_RATE(1) | DPS310_CALC_PRC(1));
+
+	/*
 	 * Set up external (MEMS) temperature sensor in single sample, one
 	 * measurement per second mode
 	 */
-	r = regmap_write(data->regmap, DPS310_TMP_CFG,
-			DPS310_TMP_EXT | DPS310_TMP_RATE(1) | DPS310_TMP_PRC(1));
+	r = regmap_write(data->regmap, DPS310_TMP_CFG, DPS310_TMP_EXT |
+		DPS310_CALC_RATE(1) | DPS310_CALC_PRC(1));
 	if (r < 0)
 		return r;
 
-	/* Temp shift is disabled when PRC <= 8 */
+	/* Temp and pressure shifts are disabled when PRC <= 8 */
 	r = regmap_write_bits(data->regmap, DPS310_CFG_REG,
-			DPS310_TMP_SHIFT_EN, 0);
+			      DPS310_TMP_SHIFT_EN | DPS310_PRS_SHIFT_EN, 0);
+	if (r < 0)
+		return r;
+
+	/* MEAS_CFG doesn't seem to update unless first written with 0 */
+	r = regmap_write_bits(data->regmap, DPS310_MEAS_CFG,
+			      DPS310_MEAS_CTRL_BITS, 0);
 	if (r < 0)
 		return r;
 
-	/* Turn on temperature measurement in the background */
+	/* Turn on temperature and pressure measurement in the background */
 	r = regmap_write_bits(data->regmap, DPS310_MEAS_CFG,
 			DPS310_MEAS_CTRL_BITS,
-			DPS310_TEMP_EN | DPS310_BACKGROUND);
+			DPS310_PRS_EN | DPS310_TEMP_EN | DPS310_BACKGROUND);
 	if (r < 0)
 		return r;
 
@@ -417,7 +695,7 @@ static int dps310_probe(struct i2c_client *client,
 	if (r < 0)
 		return r;
 
-	r = dps310_get_temp_coef(data);
+	r = dps310_get_coefs(data);
 	if (r < 0)
 		return r;
 
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] iio: dps310: Add pressure sensing capability
  2019-05-01 14:43 [PATCH] iio: dps310: Add pressure sensing capability Eddie James
@ 2019-05-03  2:34 ` Joel Stanley
  2019-05-05 12:09   ` Jonathan Cameron
  0 siblings, 1 reply; 4+ messages in thread
From: Joel Stanley @ 2019-05-03  2:34 UTC (permalink / raw)
  To: Eddie James
  Cc: Linux Kernel Mailing List, linux-iio, Peter Meerwald-Stadler,
	Lars-Peter Clausen, Hartmut Knaack, Jonathan Cameron

Hi Eddie,

On Wed, 1 May 2019 at 14:43, Eddie James <eajames@linux.ibm.com> wrote:
>
> The DPS310 supports measurement of pressure, so support that in the
> driver. Use background measurement like the temperature sensing and
> default to lowest precision and lowest measurement rate.

Upstream didn't accept my patch as they wanted it to support pressure
in addition to temperature first. I didn't ever get around to doing
that.

I suggest you send my original patch and device tree binding along
with this one as a series.

Cheers,

Joel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] iio: dps310: Add pressure sensing capability
  2019-05-03  2:34 ` Joel Stanley
@ 2019-05-05 12:09   ` Jonathan Cameron
  2019-05-06 21:03     ` Eddie James
  0 siblings, 1 reply; 4+ messages in thread
From: Jonathan Cameron @ 2019-05-05 12:09 UTC (permalink / raw)
  To: Joel Stanley
  Cc: Eddie James, Linux Kernel Mailing List, linux-iio,
	Peter Meerwald-Stadler, Lars-Peter Clausen, Hartmut Knaack

On Fri, 3 May 2019 02:34:30 +0000
Joel Stanley <joel@jms.id.au> wrote:

> Hi Eddie,
> 
> On Wed, 1 May 2019 at 14:43, Eddie James <eajames@linux.ibm.com> wrote:
> >
> > The DPS310 supports measurement of pressure, so support that in the
> > driver. Use background measurement like the temperature sensing and
> > default to lowest precision and lowest measurement rate.  
> 
> Upstream didn't accept my patch as they wanted it to support pressure
> in addition to temperature first. I didn't ever get around to doing
> that.
> 
> I suggest you send my original patch and device tree binding along
> with this one as a series.
> 
> Cheers,
> 
> Joel
Exactly as Joel says. Note there were some other minor bits and pieces
in the last review I can find of Joel's driver that will also need
tidying up..

Great to see this driver making progress.

Thanks,

Jonathan


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] iio: dps310: Add pressure sensing capability
  2019-05-05 12:09   ` Jonathan Cameron
@ 2019-05-06 21:03     ` Eddie James
  0 siblings, 0 replies; 4+ messages in thread
From: Eddie James @ 2019-05-06 21:03 UTC (permalink / raw)
  To: Jonathan Cameron, Joel Stanley
  Cc: Linux Kernel Mailing List, linux-iio, Peter Meerwald-Stadler,
	Lars-Peter Clausen, Hartmut Knaack


On 5/5/19 7:09 AM, Jonathan Cameron wrote:
> On Fri, 3 May 2019 02:34:30 +0000
> Joel Stanley <joel@jms.id.au> wrote:
>
>> Hi Eddie,
>>
>> On Wed, 1 May 2019 at 14:43, Eddie James <eajames@linux.ibm.com> wrote:
>>> The DPS310 supports measurement of pressure, so support that in the
>>> driver. Use background measurement like the temperature sensing and
>>> default to lowest precision and lowest measurement rate.
>> Upstream didn't accept my patch as they wanted it to support pressure
>> in addition to temperature first. I didn't ever get around to doing
>> that.
>>
>> I suggest you send my original patch and device tree binding along
>> with this one as a series.


The dps310 is already in the upstream witherspoon dts somehow :)


>>
>> Cheers,
>>
>> Joel
> Exactly as Joel says. Note there were some other minor bits and pieces
> in the last review I can find of Joel's driver that will also need
> tidying up..
>
> Great to see this driver making progress.


Thanks Joel and Jonathan, my mistake as I didn't base the patch on 
linux-next. I have submitted the series with a few cleanup changes for 
Joel's patch.


Thanks!

Eddie

>
> Thanks,
>
> Jonathan
>


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-05-06 21:04 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-01 14:43 [PATCH] iio: dps310: Add pressure sensing capability Eddie James
2019-05-03  2:34 ` Joel Stanley
2019-05-05 12:09   ` Jonathan Cameron
2019-05-06 21:03     ` Eddie James

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).