All of lore.kernel.org
 help / color / mirror / Atom feed
From: Heiko Schocher <hs@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v2 15/40] power: Add AMS AS3722 PMIC support
Date: Wed, 27 Aug 2014 07:26:12 +0200	[thread overview]
Message-ID: <53FD6BF4.9000601@denx.de> (raw)
In-Reply-To: <1409067268-956-16-git-send-email-thierry.reding@gmail.com>

Hello Thierry,

Am 26.08.2014 17:34, schrieb Thierry Reding:
> From: Thierry Reding<treding@nvidia.com>
>
> The AS3722 provides a number of DC/DC converters and LDOs as well as 8
> GPIOs.
>
> Signed-off-by: Thierry Reding<treding@nvidia.com>
> ---
>   drivers/power/Makefile |   1 +
>   drivers/power/as3722.c | 300 +++++++++++++++++++++++++++++++++++++++++++++++++
>   include/fdtdec.h       |   1 +
>   include/power/as3722.h |  27 +++++
>   lib/fdtdec.c           |   1 +
>   5 files changed, 330 insertions(+)
>   create mode 100644 drivers/power/as3722.c
>   create mode 100644 include/power/as3722.h
>
> diff --git a/drivers/power/Makefile b/drivers/power/Makefile
> index dc64e4d32bff..b3097316e27e 100644
> --- a/drivers/power/Makefile
> +++ b/drivers/power/Makefile
> @@ -5,6 +5,7 @@
>   # SPDX-License-Identifier:	GPL-2.0+
>   #
>
> +obj-$(CONFIG_AS3722_POWER)	+= as3722.o
>   obj-$(CONFIG_AXP152_POWER)	+= axp152.o
>   obj-$(CONFIG_AXP209_POWER)	+= axp209.o
>   obj-$(CONFIG_EXYNOS_TMU)	+= exynos-tmu.o
> diff --git a/drivers/power/as3722.c b/drivers/power/as3722.c
> new file mode 100644
> index 000000000000..59d1bf1b50b0
> --- /dev/null
> +++ b/drivers/power/as3722.c
> @@ -0,0 +1,300 @@
> +/*
> + * Copyright (C) 2014 NVIDIA Corporation
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#define pr_fmt(fmt) "as3722: " fmt
> +
> +#include<common.h>
> +#include<errno.h>
> +#include<fdtdec.h>
> +#include<i2c.h>
> +
> +#include<power/as3722.h>
> +
> +#define AS3722_SD_VOLTAGE(n) (0x00 + (n))
> +#define AS3722_GPIO_CONTROL(n) (0x08 + (n))
> +#define  AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH (1<<  0)
> +#define  AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL (7<<  0)
> +#define  AS3722_GPIO_CONTROL_INVERT (1<<  7)
> +#define AS3722_LDO_VOLTAGE(n) (0x10 + (n))
> +#define AS3722_GPIO_SIGNAL_OUT 0x20
> +#define AS3722_SD_CONTROL 0x4d
> +#define AS3722_LDO_CONTROL 0x4e
> +#define AS3722_ASIC_ID1 0x90
> +#define  AS3722_DEVICE_ID 0x0c
> +#define AS3722_ASIC_ID2 0x91
> +
> +struct as3722 {
> +	struct i2c_client client;
> +	u8 address;
> +};
> +
> +static struct as3722 as3722_pmic;
> +
> +static int as3722_read(struct as3722 *pmic, u8 reg, u8 *value)
> +{
> +	int err;
> +
> +	err = i2c_client_read(&pmic->client, reg, 1, value, 1);
> +	if (err<  0)
> +		return err;
> +
> +	return 0;
> +}
> +
> +static int as3722_write(struct as3722 *pmic, u8 reg, u8 value)
> +{
> +	int err;
> +
> +	err = i2c_client_write(&pmic->client, reg, 1,&value, 1);
> +	if (err<  0)
> +		return err;
> +
> +	return 0;
> +}
> +
> +static int as3722_read_id(struct as3722 *pmic, u8 *id, u8 *revision)
> +{
> +	int err;
> +
> +	err = as3722_read(pmic, AS3722_ASIC_ID1, id);
> +	if (err) {
> +		error("failed to read ID1 register: %d", err);
> +		return err;
> +	}
> +
> +	err = as3722_read(pmic, AS3722_ASIC_ID2, revision);
> +	if (err) {
> +		error("failed to read ID2 register: %d", err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +int as3722_sd_enable(struct as3722 *pmic, unsigned int sd)
> +{
> +	u8 value;
> +	int err;
> +
> +	if (sd>  6)
> +		return -EINVAL;
> +
> +	err = as3722_read(pmic, AS3722_SD_CONTROL,&value);
> +	if (err) {
> +		error("failed to read SD control register: %d", err);
> +		return err;
> +	}
> +
> +	value |= 1<<  sd;
> +
> +	err = as3722_write(pmic, AS3722_SD_CONTROL, value);
> +	if (err<  0) {
> +		error("failed to write SD control register: %d", err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +int as3722_sd_set_voltage(struct as3722 *pmic, unsigned int sd, u8 value)
> +{
> +	int err;
> +
> +	if (sd>  6)
> +		return -EINVAL;
> +
> +	err = as3722_write(pmic, AS3722_SD_VOLTAGE(sd), value);
> +	if (err<  0) {
> +		error("failed to write SD%u voltage register: %d", sd, err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +int as3722_ldo_enable(struct as3722 *pmic, unsigned int ldo)
> +{
> +	u8 value;
> +	int err;
> +
> +	if (ldo>  11)
> +		return -EINVAL;
> +
> +	err = as3722_read(pmic, AS3722_LDO_CONTROL,&value);
> +	if (err) {
> +		error("failed to read LDO control register: %d", err);
> +		return err;
> +	}
> +
> +	value |= 1<<  ldo;
> +
> +	err = as3722_write(pmic, AS3722_LDO_CONTROL, value);
> +	if (err<  0) {
> +		error("failed to write LDO control register: %d", err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +int as3722_ldo_set_voltage(struct as3722 *pmic, unsigned int ldo, u8 value)
> +{
> +	int err;
> +
> +	if (ldo>  11)
> +		return -EINVAL;
> +
> +	err = as3722_write(pmic, AS3722_LDO_VOLTAGE(ldo), value);
> +	if (err<  0) {
> +		error("failed to write LDO%u voltage register: %d", ldo,
> +		      err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +int as3722_gpio_configure(struct as3722 *pmic, unsigned int gpio,
> +			  unsigned long flags)
> +{
> +	u8 value = 0;
> +	int err;
> +
> +	if (flags&  AS3722_GPIO_OUTPUT_VDDH)
> +		value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
> +
> +	if (flags&  AS3722_GPIO_INVERT)
> +		value |= AS3722_GPIO_CONTROL_INVERT;
> +
> +	err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
> +	if (err) {
> +		error("failed to configure GPIO#%u: %d", gpio, err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +static int as3722_gpio_set(struct as3722 *pmic, unsigned int gpio,
> +			   unsigned int level)
> +{
> +	const char *l;
> +	u8 value;
> +	int err;
> +
> +	if (gpio>  7)
> +		return -EINVAL;
> +
> +	err = as3722_read(pmic, AS3722_GPIO_SIGNAL_OUT,&value);
> +	if (err<  0) {
> +		error("failed to read GPIO signal out register: %d", err);
> +		return err;
> +	}
> +
> +	if (level == 0) {
> +		value&= ~(1<<  gpio);
> +		l = "low";
> +	} else {
> +		value |= 1<<  gpio;
> +		l = "high";
> +	}
> +
> +	err = as3722_write(pmic, AS3722_GPIO_SIGNAL_OUT, value);
> +	if (err) {
> +		error("failed to set GPIO#%u %s: %d", gpio, l, err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +int as3722_gpio_direction_output(struct as3722 *pmic, unsigned int gpio,
> +				 unsigned int level)
> +{
> +	u8 value;
> +	int err;
> +
> +	if (gpio>  7)
> +		return -EINVAL;
> +
> +	if (level == 0)
> +		value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL;
> +	else
> +		value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
> +
> +	err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
> +	if (err) {
> +		error("failed to configure GPIO#%u as output: %d", gpio, err);
> +		return err;
> +	}
> +
> +	err = as3722_gpio_set(pmic, gpio, level);
> +	if (err<  0) {
> +		error("failed to set GPIO#%u high: %d", gpio, err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +int as3722_init(struct as3722 **pmicp, const void *fdt)
> +{
> +	struct as3722 *pmic =&as3722_pmic;
> +	int count, nodes[1], i;
> +	int err;
> +
> +	count = fdtdec_find_aliases_for_id(fdt, NULL, COMPAT_AMS_AS3722,
> +					   nodes, ARRAY_SIZE(nodes));
> +	for (i = 0; i<  count; i++) {
> +		int parent = fdt_parent_offset(fdt, nodes[i]), bus;
> +		struct i2c_adapter *adapter;
> +		fdt_addr_t address;
> +		u8 id, revision;
> +
> +		bus = i2c_get_bus_num_fdt(parent);
> +		if (bus<  0) {
> +			error("invalid bus %d", bus);
> +			continue;
> +		}
> +
> +		address = fdtdec_get_addr(fdt, nodes[i], "reg");
> +		if (address == FDT_ADDR_T_NONE) {
> +			error("slave address not found");
> +			continue;
> +		}
> +
> +		adapter = i2c_adapter_get(bus);
> +		if (!adapter) {
> +			error("I2C adapter for bus %d not found", bus);
> +			continue;
> +		}

Why is i2c_set_bus_num() not enough for you? Why introducing a new
API? If another uses this PMIC behind a i2c mux, this driver maybe
not work correctly.

bye,
Heiko
> +
> +		err = i2c_client_init(&pmic->client, adapter, address);
> +		if (err<  0) {
> +			error("failed to initialize I2C slave: %d", err);
> +			continue;
> +		}
> +
> +		err = as3722_read_id(pmic,&id,&revision);
> +		if (err<  0) {
> +			error("failed to read ID: %d", err);
> +			continue;
> +		}
> +
> +		if (id != AS3722_DEVICE_ID) {
> +			error("unknown device");
> +			continue;
> +		}
> +
> +		debug("AS3722 revision %#x found on I2C bus %u, address %#x\n",
> +		      revision, bus, address);
> +
> +		*pmicp = pmic;
> +		return 0;
> +	}
> +
> +	return -ENODEV;
> +}
> diff --git a/include/fdtdec.h b/include/fdtdec.h
> index 5c669a5c8e03..3c38375397df 100644
> --- a/include/fdtdec.h
> +++ b/include/fdtdec.h
> @@ -115,6 +115,7 @@ enum fdt_compat_id {
>   	COMPAT_SANDBOX_LCD_SDL,		/* Sandbox LCD emulation with SDL */
>   	COMPAT_TI_TPS65090,		/* Texas Instrument TPS65090 */
>   	COMPAT_NXP_PTN3460,		/* NXP PTN3460 DP/LVDS bridge */
> +	COMPAT_AMS_AS3722,		/* AMS AS3722 PMIC */
>
>   	COMPAT_COUNT,
>   };
> diff --git a/include/power/as3722.h b/include/power/as3722.h
> new file mode 100644
> index 000000000000..2c2e45a44bab
> --- /dev/null
> +++ b/include/power/as3722.h
> @@ -0,0 +1,27 @@
> +/*
> + * Copyright (C) 2014 NVIDIA Corporation
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#ifndef __POWER_AS3722_H__
> +#define __POWER_AS3722_H__
> +
> +#include<asm/types.h>
> +
> +#define AS3722_GPIO_OUTPUT_VDDH (1<<  0)
> +#define AS3722_GPIO_INVERT (1<<  1)
> +
> +struct as3722;
> +
> +int as3722_init(struct as3722 **pmic, const void *fdt);
> +int as3722_sd_enable(struct as3722 *pmic, unsigned int sd);
> +int as3722_sd_set_voltage(struct as3722 *pmic, unsigned int sd, u8 value);
> +int as3722_ldo_enable(struct as3722 *pmic, unsigned int ldo);
> +int as3722_ldo_set_voltage(struct as3722 *pmic, unsigned int ldo, u8 value);
> +int as3722_gpio_configure(struct as3722 *pmic, unsigned int gpio,
> +			  unsigned long flags);
> +int as3722_gpio_direction_output(struct as3722 *pmic, unsigned int gpio,
> +				 unsigned int level);
> +
> +#endif /* __POWER_AS3722_H__ */
> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
> index fa5da0c0147d..cddd86c3186f 100644
> --- a/lib/fdtdec.c
> +++ b/lib/fdtdec.c
> @@ -70,6 +70,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
>   	COMPAT(SANDBOX_LCD_SDL, "sandbox,lcd-sdl"),
>   	COMPAT(TI_TPS65090, "ti,tps65090"),
>   	COMPAT(COMPAT_NXP_PTN3460, "nxp,ptn3460"),
> +	COMPAT(AMS_AS3722, "ams,as3722"),
>   };
>
>   const char *fdtdec_get_compatible(enum fdt_compat_id id)

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

  reply	other threads:[~2014-08-27  5:26 UTC|newest]

Thread overview: 104+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
2014-08-26 15:33 ` [U-Boot] [PATCH v2 01/40] vsprintf: Add modifier for phys_addr_t Thierry Reding
2014-08-26 17:04   ` Stephen Warren
2014-08-27  7:01     ` Thierry Reding
2014-08-27 17:41       ` Stephen Warren
2014-08-28 10:38         ` Thierry Reding
2014-09-17  0:44           ` [U-Boot] [U-Boot, v2, " Tom Rini
2014-08-26 23:14   ` [U-Boot] [PATCH v2 " Simon Glass
2014-08-27  7:37     ` Thierry Reding
2014-08-27 15:24       ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 02/40] fdt: Add a function to count strings Thierry Reding
2014-08-27 18:51   ` Simon Glass
2014-09-08 15:01     ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 03/40] fdt: Add a function to get the index of a string Thierry Reding
2014-08-27 18:51   ` Simon Glass
2014-09-08 15:02     ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 04/40] fdt: Add functions to retrieve strings Thierry Reding
2014-08-27 18:53   ` Simon Glass
2014-09-08 15:02     ` Simon Glass
2015-03-25 23:23       ` Simon Glass
2015-07-14 19:48         ` Simon Glass
2015-07-15 11:17           ` Thierry Reding
2015-07-15 11:35             ` Albert ARIBAUD
2015-07-15 11:52               ` Thierry Reding
2014-08-26 15:33 ` [U-Boot] [PATCH v2 05/40] fdt: Add resource parsing functions Thierry Reding
2014-08-27 18:53   ` Simon Glass
2014-09-08 15:02   ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 06/40] fdt: Add a function to return PCI BDF triplet Thierry Reding
2014-09-08 15:03   ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 07/40] fdt: Add a subnodes iterator macro Thierry Reding
2014-09-08 15:03   ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 08/40] pci: Abort early if bus does not exist Thierry Reding
2014-08-26 15:33 ` [U-Boot] [PATCH v2 09/40] pci: Honour pci_skip_dev() Thierry Reding
2014-08-26 15:33 ` [U-Boot] [PATCH v2 10/40] Add pr_fmt() macro Thierry Reding
2014-08-26 15:33 ` [U-Boot] [PATCH v2 11/40] i2c: Initialize the correct bus Thierry Reding
2014-08-27  4:52   ` Heiko Schocher
2014-08-27  5:12     ` Thierry Reding
2014-08-27  5:26       ` Heiko Schocher
2014-08-26 15:34 ` [U-Boot] [PATCH v2 12/40] i2c: Refactor adapter initialization Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 13/40] i2c: Add high-level API Thierry Reding
2014-08-27  5:21   ` Heiko Schocher
2014-08-27  6:21     ` Thierry Reding
2014-08-27  7:07       ` Heiko Schocher
2014-08-27  8:51         ` Thierry Reding
2014-08-27  9:56           ` Heiko Schocher
2014-08-27 11:41             ` Thierry Reding
2014-08-27 19:10               ` Simon Glass
2014-08-28  9:53                 ` Heiko Schocher
2014-08-26 15:34 ` [U-Boot] [PATCH v2 14/40] i2c: tegra: Implement i2c_get_bus_num_fdt() Thierry Reding
2014-09-02 19:24   ` Simon Glass
2014-08-26 15:34 ` [U-Boot] [PATCH v2 15/40] power: Add AMS AS3722 PMIC support Thierry Reding
2014-08-27  5:26   ` Heiko Schocher [this message]
2014-08-27  6:28     ` Thierry Reding
2014-08-27  7:18       ` Heiko Schocher
2014-08-26 15:34 ` [U-Boot] [PATCH v2 16/40] ARM: tegra: Implement tegra_plle_enable() Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 17/40] ARM: tegra: Provide PCIEXCLK reset ID Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 18/40] ARM: tegra: Implement powergate support Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 19/40] ARM: tegra: Implement XUSB pad controller Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 20/40] ARM: tegra: Add XUSB pad controller on Tegra124 Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 21/40] ARM: tegra: Enable XUSB pad controller on Jetson TK1 Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 22/40] pci: tegra: Add Tegra PCIe driver Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 23/40] ARM: tegra: Add Tegra20 PCIe device tree node Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 24/40] ARM: tegra: Enable PCIe on TrimSlice Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 25/40] ARM: tegra: Add GIC for Tegra30 Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 26/40] ARM: tegra: Add Tegra30 PCIe device tree node Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 27/40] ARM: tegra: Enable PCIe on Cardhu Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 28/40] ARM: tegra: Enable PCIe on Beaver Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 29/40] ARM: tegra: Add GIC for Tegra124 Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 30/40] ARM: tegra: Add Tegra124 PCIe device tree node Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 31/40] ARM: tegra: Enable PCIe on Jetson TK1 Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 32/40] ARM: cache_v7: Various minor cleanups Thierry Reding
2014-08-27 18:56   ` Simon Glass
2014-11-08  8:30   ` Albert ARIBAUD
2014-08-26 15:34 ` [U-Boot] [PATCH v2 33/40] ARM: cache-cp15: Use more accurate types Thierry Reding
2014-08-27 18:57   ` Simon Glass
2014-11-08  8:31   ` Albert ARIBAUD
2014-08-26 15:34 ` [U-Boot] [PATCH v2 34/40] malloc: Output region when debugging Thierry Reding
2014-08-27 18:58   ` Simon Glass
2014-11-08  8:31   ` Albert ARIBAUD
2014-08-26 15:34 ` [U-Boot] [PATCH v2 35/40] ARM: Implement non-cached memory support Thierry Reding
2014-08-27 19:07   ` Simon Glass
2014-10-24 19:11   ` Stephen Warren
2014-11-12 15:49     ` Simon Glass
2014-08-26 15:34 ` [U-Boot] [PATCH v2 36/40] ARM: tegra: Enable non-cached memory Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 37/40] net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 38/40] net: rtl8169: Properly align buffers Thierry Reding
2014-11-12 23:37   ` Nobuhiro Iwamatsu
2014-08-26 15:34 ` [U-Boot] [PATCH v2 39/40] net: rtl8169: Use non-cached memory if available Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 40/40] net: rtl8169: Add support for RTL-8168/8111g Thierry Reding
2014-09-11 16:00 ` [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Albert ARIBAUD
2014-09-11 16:17   ` Stephen Warren
2014-09-11 19:20     ` Simon Glass
2014-09-18  8:43       ` Albert ARIBAUD
2014-09-18 18:01         ` Simon Glass
2014-10-23  3:07   ` Simon Glass
2014-10-23  8:11     ` Thierry Reding
2014-10-23 18:33       ` Simon Glass
2014-09-28 22:48 ` Simon Glass
2014-09-29  8:11   ` Thierry Reding
2014-09-29 13:54     ` Simon Glass
2014-10-06 12:24     ` Heiko Schocher
2014-10-26 19:07 ` Albert ARIBAUD
2014-10-26 19:29   ` Albert ARIBAUD
2014-10-27 23:55   ` Simon Glass

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=53FD6BF4.9000601@denx.de \
    --to=hs@denx.de \
    --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.