* [PATCH] nvmem: k3: add fuse support
@ 2025-11-25 11:40 Sascha Hauer
2025-11-25 12:47 ` Ahmad Fatoum
0 siblings, 1 reply; 2+ messages in thread
From: Sascha Hauer @ 2025-11-25 11:40 UTC (permalink / raw)
To: Barebox List
This driver reads/writes to the extended OTP area using TF-A calls.
The driver has been tested on AM625 and AM62L, but should work on other
SoCs as well. The driver needs the SIP calls K3_SIP_OTP_READ and
K3_SIP_OTP_WRITE. These are currently only implemented in the TI
downstream TF-A for AM62L. For AM625 these calls need to be enabled with
additional TF-A patches. The driver is activated in the AM62L/AM625
device trees, but due to the limited availability of the SIP calls
the driver remains silent when the TF-A doesn't have support for
manipulating fuses.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/dts/k3-am625.dtsi | 4 +
arch/arm/dts/k3-am62l-barebox.dtsi | 4 +
drivers/nvmem/Kconfig | 7 +
drivers/nvmem/Makefile | 1 +
drivers/nvmem/k3-fuse.c | 229 +++++++++++++++++++++++++++++
5 files changed, 245 insertions(+)
create mode 100644 drivers/nvmem/k3-fuse.c
diff --git a/arch/arm/dts/k3-am625.dtsi b/arch/arm/dts/k3-am625.dtsi
index a67b9f5d9a..bb0f046fd6 100644
--- a/arch/arm/dts/k3-am625.dtsi
+++ b/arch/arm/dts/k3-am625.dtsi
@@ -7,6 +7,10 @@ chosen {
barebox,bootsource-mmc1 = &sdhci1;
barebox,bootsource-mmc2 = &sdhci2;
};
+
+ otp: otp {
+ compatible = "ti,am62x-otp";
+ };
};
&wkup_conf {
diff --git a/arch/arm/dts/k3-am62l-barebox.dtsi b/arch/arm/dts/k3-am62l-barebox.dtsi
index 2c1cbb3871..949e2746d5 100644
--- a/arch/arm/dts/k3-am62l-barebox.dtsi
+++ b/arch/arm/dts/k3-am62l-barebox.dtsi
@@ -64,4 +64,8 @@ secure_ddr: optee@80200000 {
no-map;
};
};
+
+ otp: otp {
+ compatible = "ti,am62l-otp";
+ };
};
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 49f90452df..d66c4a88fe 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -136,4 +136,11 @@ config NVMEM_ATMEL_I2C
bool
select BITREVERSE
+config TI_K3_OTP
+ bool "TI K3 OTP"
+ depends on ARCH_K3
+ select ARM_SMCCC
+ help
+ This adds support for the TI K3 SMC call based OTP found on AM62L SoCs.
+
endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 9cdc669a96..cb5e6d6330 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -36,3 +36,4 @@ obj-$(CONFIG_STARFIVE_OTP) += starfive-otp.o
obj-$(CONFIG_IMX_OCOTP_ELE) += imx-ocotp-ele.o
obj-$(CONFIG_NVMEM_ATMEL_I2C) += atmel-i2c.o
obj-$(CONFIG_NVMEM_ATMEL_SHA204A) += atmel-sha204a.o
+obj-$(CONFIG_TI_K3_OTP) += k3-fuse.o
diff --git a/drivers/nvmem/k3-fuse.c b/drivers/nvmem/k3-fuse.c
new file mode 100644
index 0000000000..c14dbf7cda
--- /dev/null
+++ b/drivers/nvmem/k3-fuse.c
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <driver.h>
+#include <malloc.h>
+#include <xfuncs.h>
+#include <errno.h>
+#include <init.h>
+#include <io.h>
+#include <of.h>
+#include <linux/regmap.h>
+#include <linux/nvmem-provider.h>
+#include <linux/arm-smccc.h>
+#include <linux/bitmap.h>
+
+/*
+ * These SIP calls are currently only supported in the TI downstream
+ * TF-A
+ */
+#define K3_SIP_OTP_READ 0xC2000002
+#define K3_SIP_OTP_WRITE 0xC2000001
+
+struct ti_k3_otp_driver_data {
+ unsigned int skip_init;
+ unsigned int bits_per_row;
+ unsigned int nrows;
+};
+
+struct ti_k3_otp {
+ struct device *dev;
+ uint32_t *map;
+ const struct ti_k3_otp_driver_data *data;
+};
+
+static int ti_k3_otp_read_raw(unsigned int word, unsigned int *val)
+{
+ struct arm_smccc_res res;
+ unsigned int bank = 0;
+
+ /* TF-A ignores bank argument */
+ arm_smccc_smc(K3_SIP_OTP_READ, bank, word,
+ 0, 0, 0, 0, 0, &res);
+
+ if ((long)res.a0 == -1) /* SMC_UNK */
+ return -EOPNOTSUPP;
+
+ if (res.a0 != 0)
+ return -EIO;
+
+ *val = res.a1;
+
+ return 0;
+}
+
+/*
+ * Fuses are organized in rows where each row has a SoC specific number
+ * of fuses (25 on most K3 devices). When writing a fuse we always write
+ * to a single row of fuses. This means the upper 7 bits of each 32 bit word
+ * are unused. When reading from fuses these gaps are skipped, meaning the first
+ * word we read has 25 bits from row0 in the lower bits and 7 bits from row1
+ * in the upper bits.
+ * Additionally on some SoCs the very first n fuses are reserved. These bits
+ * cannot be written and are skipped while reading.
+ * These effects are reversed here which means that we actually provide a
+ * consistent register map between writing and reading.
+ *
+ * Rather than adjusting the write map we adjust the read map, because this
+ * way we provide one fuse row in each 32bit word and a fuse row is the granularity
+ * for write protection.
+ *
+ * The TI-SCI firmware updates the registers we read from only after a reset,
+ * so it doesn't hurt us when we read all registers upfront, you can't read
+ * back the values you've just written anyway.
+ */
+static int ti_k3_otp_read_map(struct ti_k3_otp *priv)
+{
+ uint32_t *map_raw;
+ int i, ret;
+ unsigned int bits_per_row = priv->data->bits_per_row;
+ unsigned int mask = (1 << bits_per_row) - 1;
+ unsigned long *bitmap = NULL;
+ int nbits = 32 * 32;
+ int nrows = priv->data->nrows;
+
+ map_raw = xzalloc(sizeof(uint32_t) * nrows);
+
+ for (i = 0; i < 32; i++) {
+ unsigned int val;
+
+ ret = ti_k3_otp_read_raw(i, &val);
+ if (ret)
+ goto out;
+
+ map_raw[i] = val;
+ }
+
+ bitmap = bitmap_xzalloc(nbits);
+ bitmap_from_arr32(bitmap, map_raw, nbits);
+
+ if (priv->data->skip_init)
+ bitmap_shift_left(bitmap, bitmap, priv->data->skip_init, nbits);
+
+ for (i = 0; i < priv->data->nrows; i++) {
+ priv->map[i] = bitmap[0] & mask;
+ bitmap_shift_right(bitmap, bitmap, bits_per_row, nbits);
+ }
+
+ ret = 0;
+
+out:
+ free(bitmap);
+ free(map_raw);
+ return ret;
+}
+
+/*
+ * offset and size are assumed aligned to the size of the fuses (32-bit).
+ */
+static int ti_k3_otp_read(void *ctx, unsigned int offset, unsigned int *val)
+{
+ struct ti_k3_otp *priv = ctx;
+ unsigned int word = offset >> 2;
+
+ *val = priv->map[word];
+
+ return 0;
+}
+
+static int ti_k3_otp_write(void *ctx, unsigned int offset, unsigned int val)
+{
+ struct ti_k3_otp *priv = ctx;
+ struct arm_smccc_res res;
+ unsigned int bank = 0;
+ unsigned int word = offset >> 2;
+ unsigned int mask = val;
+
+ if (word == 0 && priv->data->skip_init) {
+ unsigned int skip_mask = GENMASK(priv->data->skip_init, 0);
+ if (val & skip_mask) {
+ dev_err(priv->dev, "Lower %d bits of word 0 cannot be written\n",
+ priv->data->skip_init);
+ return -EINVAL;
+ }
+ }
+
+ if (val & GENMASK(31, priv->data->bits_per_row)) {
+ dev_err(priv->dev, "Each row only has %d bits",
+ priv->data->bits_per_row);
+ return -EINVAL;
+ }
+
+ arm_smccc_smc(K3_SIP_OTP_WRITE, bank, word,
+ val, mask, 0, 0, 0, &res);
+
+ if (res.a0 != 0) {
+ dev_err(priv->dev, "Writing fuse 0x%08x failed with: %lu\n",
+ offset, res.a0);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static struct regmap_bus ti_k3_otp_regmap_bus = {
+ .reg_read = ti_k3_otp_read,
+ .reg_write = ti_k3_otp_write,
+};
+
+static int ti_k3_otp_probe(struct device *dev)
+{
+ struct ti_k3_otp *priv;
+ struct regmap_config config = {};
+ struct regmap *map;
+ int ret;
+
+ priv = xzalloc(sizeof(*priv));
+ priv->data = device_get_match_data(dev);
+ priv->dev = dev;
+ priv->map = xzalloc(sizeof(uint32_t) * priv->data->nrows);
+
+ config.name = "k3-otp";
+ config.reg_bits = 32;
+ config.val_bits = 32;
+ config.reg_stride = 4;
+ config.max_register = sizeof(uint32_t) * priv->data->nrows - 1;
+
+ ret = ti_k3_otp_read_map(priv);
+ if (ret) {
+ /*
+ * Reading fuses is only supported by TI downstream TF-A and
+ * only on AM62L. Do not bother the user with error messages
+ * when it's not supported.
+ */
+ if (ret == -EOPNOTSUPP)
+ return -ENODEV;
+ return ret;
+ }
+
+ map = regmap_init(dev, &ti_k3_otp_regmap_bus, priv, &config);
+ if (IS_ERR(map))
+ return PTR_ERR(map);
+
+ return PTR_ERR_OR_ZERO(nvmem_regmap_register(map, "ti-k3-otp"));
+}
+
+struct ti_k3_otp_driver_data am62x_data = {
+ .skip_init = 2,
+ .bits_per_row = 25,
+ .nrows = 42,
+};
+
+struct ti_k3_otp_driver_data am62l_data = {
+ .skip_init = 0,
+ .bits_per_row = 25,
+ .nrows = 42,
+};
+
+static struct of_device_id ti_k3_otp_dt_ids[] = {
+ { .compatible = "ti,am62x-otp", .data = &am62x_data },
+ { .compatible = "ti,am62l-otp", .data = &am62l_data },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ti_k3_otp_dt_ids);
+
+static struct driver ti_k3_otp_driver = {
+ .name = "ti-k3-otp",
+ .probe = ti_k3_otp_probe,
+ .of_compatible = ti_k3_otp_dt_ids,
+};
+device_platform_driver(ti_k3_otp_driver);
--
2.47.3
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] nvmem: k3: add fuse support
2025-11-25 11:40 [PATCH] nvmem: k3: add fuse support Sascha Hauer
@ 2025-11-25 12:47 ` Ahmad Fatoum
0 siblings, 0 replies; 2+ messages in thread
From: Ahmad Fatoum @ 2025-11-25 12:47 UTC (permalink / raw)
To: Sascha Hauer, Barebox List
On 11/25/25 12:40 PM, Sascha Hauer wrote:
> This driver reads/writes to the extended OTP area using TF-A calls.
>
> The driver has been tested on AM625 and AM62L, but should work on other
> SoCs as well. The driver needs the SIP calls K3_SIP_OTP_READ and
> K3_SIP_OTP_WRITE. These are currently only implemented in the TI
> downstream TF-A for AM62L. For AM625 these calls need to be enabled with
> additional TF-A patches. The driver is activated in the AM62L/AM625
> device trees, but due to the limited availability of the SIP calls
> the driver remains silent when the TF-A doesn't have support for
> manipulating fuses.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> arch/arm/dts/k3-am625.dtsi | 4 +
> arch/arm/dts/k3-am62l-barebox.dtsi | 4 +
> drivers/nvmem/Kconfig | 7 +
> drivers/nvmem/Makefile | 1 +
> drivers/nvmem/k3-fuse.c | 229 +++++++++++++++++++++++++++++
> 5 files changed, 245 insertions(+)
> create mode 100644 drivers/nvmem/k3-fuse.c
>
> diff --git a/arch/arm/dts/k3-am625.dtsi b/arch/arm/dts/k3-am625.dtsi
> index a67b9f5d9a..bb0f046fd6 100644
> --- a/arch/arm/dts/k3-am625.dtsi
> +++ b/arch/arm/dts/k3-am625.dtsi
> @@ -7,6 +7,10 @@ chosen {
> barebox,bootsource-mmc1 = &sdhci1;
> barebox,bootsource-mmc2 = &sdhci2;
> };
> +
> + otp: otp {
> + compatible = "ti,am62x-otp";
> + };
> };
>
> &wkup_conf {
> diff --git a/arch/arm/dts/k3-am62l-barebox.dtsi b/arch/arm/dts/k3-am62l-barebox.dtsi
> index 2c1cbb3871..949e2746d5 100644
> --- a/arch/arm/dts/k3-am62l-barebox.dtsi
> +++ b/arch/arm/dts/k3-am62l-barebox.dtsi
> @@ -64,4 +64,8 @@ secure_ddr: optee@80200000 {
> no-map;
> };
> };
> +
> + otp: otp {
> + compatible = "ti,am62l-otp";
> + };
> };
> diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
> index 49f90452df..d66c4a88fe 100644
> --- a/drivers/nvmem/Kconfig
> +++ b/drivers/nvmem/Kconfig
> @@ -136,4 +136,11 @@ config NVMEM_ATMEL_I2C
> bool
> select BITREVERSE
>
> +config TI_K3_OTP
> + bool "TI K3 OTP"
> + depends on ARCH_K3
> + select ARM_SMCCC
> + help
> + This adds support for the TI K3 SMC call based OTP found on AM62L SoCs.
> +
> endif
> diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
> index 9cdc669a96..cb5e6d6330 100644
> --- a/drivers/nvmem/Makefile
> +++ b/drivers/nvmem/Makefile
> @@ -36,3 +36,4 @@ obj-$(CONFIG_STARFIVE_OTP) += starfive-otp.o
> obj-$(CONFIG_IMX_OCOTP_ELE) += imx-ocotp-ele.o
> obj-$(CONFIG_NVMEM_ATMEL_I2C) += atmel-i2c.o
> obj-$(CONFIG_NVMEM_ATMEL_SHA204A) += atmel-sha204a.o
> +obj-$(CONFIG_TI_K3_OTP) += k3-fuse.o
> diff --git a/drivers/nvmem/k3-fuse.c b/drivers/nvmem/k3-fuse.c
> new file mode 100644
> index 0000000000..c14dbf7cda
> --- /dev/null
> +++ b/drivers/nvmem/k3-fuse.c
> @@ -0,0 +1,229 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +
> +#include <driver.h>
> +#include <malloc.h>
> +#include <xfuncs.h>
> +#include <errno.h>
> +#include <init.h>
> +#include <io.h>
> +#include <of.h>
> +#include <linux/regmap.h>
> +#include <linux/nvmem-provider.h>
> +#include <linux/arm-smccc.h>
> +#include <linux/bitmap.h>
> +
> +/*
> + * These SIP calls are currently only supported in the TI downstream
> + * TF-A
> + */
> +#define K3_SIP_OTP_READ 0xC2000002
> +#define K3_SIP_OTP_WRITE 0xC2000001
> +
> +struct ti_k3_otp_driver_data {
> + unsigned int skip_init;
> + unsigned int bits_per_row;
> + unsigned int nrows;
> +};
> +
> +struct ti_k3_otp {
> + struct device *dev;
> + uint32_t *map;
> + const struct ti_k3_otp_driver_data *data;
> +};
> +
> +static int ti_k3_otp_read_raw(unsigned int word, unsigned int *val)
> +{
> + struct arm_smccc_res res;
> + unsigned int bank = 0;
> +
> + /* TF-A ignores bank argument */
> + arm_smccc_smc(K3_SIP_OTP_READ, bank, word,
> + 0, 0, 0, 0, 0, &res);
> +
> + if ((long)res.a0 == -1) /* SMC_UNK */
> + return -EOPNOTSUPP;
> +
> + if (res.a0 != 0)
> + return -EIO;
> +
> + *val = res.a1;
> +
> + return 0;
> +}
> +
> +/*
> + * Fuses are organized in rows where each row has a SoC specific number
> + * of fuses (25 on most K3 devices). When writing a fuse we always write
> + * to a single row of fuses. This means the upper 7 bits of each 32 bit word
> + * are unused. When reading from fuses these gaps are skipped, meaning the first
> + * word we read has 25 bits from row0 in the lower bits and 7 bits from row1
> + * in the upper bits.
> + * Additionally on some SoCs the very first n fuses are reserved. These bits
> + * cannot be written and are skipped while reading.
> + * These effects are reversed here which means that we actually provide a
> + * consistent register map between writing and reading.
> + *
> + * Rather than adjusting the write map we adjust the read map, because this
> + * way we provide one fuse row in each 32bit word and a fuse row is the granularity
> + * for write protection.
> + *
> + * The TI-SCI firmware updates the registers we read from only after a reset,
> + * so it doesn't hurt us when we read all registers upfront, you can't read
> + * back the values you've just written anyway.
> + */
> +static int ti_k3_otp_read_map(struct ti_k3_otp *priv)
> +{
> + uint32_t *map_raw;
> + int i, ret;
> + unsigned int bits_per_row = priv->data->bits_per_row;
> + unsigned int mask = (1 << bits_per_row) - 1;
> + unsigned long *bitmap = NULL;
> + int nbits = 32 * 32;
> + int nrows = priv->data->nrows;
> +
> + map_raw = xzalloc(sizeof(uint32_t) * nrows);
> +
> + for (i = 0; i < 32; i++) {
> + unsigned int val;
> +
> + ret = ti_k3_otp_read_raw(i, &val);
> + if (ret)
> + goto out;
> +
> + map_raw[i] = val;
> + }
> +
> + bitmap = bitmap_xzalloc(nbits);
> + bitmap_from_arr32(bitmap, map_raw, nbits);
> +
> + if (priv->data->skip_init)
> + bitmap_shift_left(bitmap, bitmap, priv->data->skip_init, nbits);
Why bother reading them in the first place?
> +
> + for (i = 0; i < priv->data->nrows; i++) {
> + priv->map[i] = bitmap[0] & mask;
> + bitmap_shift_right(bitmap, bitmap, bits_per_row, nbits);
I find the logic a bit confusing to be honest, but if you tried the
nested loop variant and found it more confusing, then we can go with this..
> + }
> +
> + ret = 0;
> +
> +out:
> + free(bitmap);
> + free(map_raw);
> + return ret;
> +}
> +
> +/*
> + * offset and size are assumed aligned to the size of the fuses (32-bit).
> + */
> +static int ti_k3_otp_read(void *ctx, unsigned int offset, unsigned int *val)
> +{
> + struct ti_k3_otp *priv = ctx;
> + unsigned int word = offset >> 2;
> +
> + *val = priv->map[word];
> +
> + return 0;
> +}
> +
> +static int ti_k3_otp_write(void *ctx, unsigned int offset, unsigned int val)
> +{
> + struct ti_k3_otp *priv = ctx;
> + struct arm_smccc_res res;
> + unsigned int bank = 0;
> + unsigned int word = offset >> 2;
> + unsigned int mask = val;
> +
> + if (word == 0 && priv->data->skip_init) {
> + unsigned int skip_mask = GENMASK(priv->data->skip_init, 0);
> + if (val & skip_mask) {
> + dev_err(priv->dev, "Lower %d bits of word 0 cannot be written\n",
> + priv->data->skip_init);
> + return -EINVAL;
> + }
> + }
> +
> + if (val & GENMASK(31, priv->data->bits_per_row)) {
> + dev_err(priv->dev, "Each row only has %d bits",
> + priv->data->bits_per_row);
> + return -EINVAL;
> + }
> +
> + arm_smccc_smc(K3_SIP_OTP_WRITE, bank, word,
> + val, mask, 0, 0, 0, &res);
> +
> + if (res.a0 != 0) {
> + dev_err(priv->dev, "Writing fuse 0x%08x failed with: %lu\n",
> + offset, res.a0);
> + return -EIO;
> + }
> +
> + return 0;
> +}
> +
> +static struct regmap_bus ti_k3_otp_regmap_bus = {
> + .reg_read = ti_k3_otp_read,
> + .reg_write = ti_k3_otp_write,
> +};
> +
> +static int ti_k3_otp_probe(struct device *dev)
> +{
> + struct ti_k3_otp *priv;
> + struct regmap_config config = {};
> + struct regmap *map;
> + int ret;
> +
> + priv = xzalloc(sizeof(*priv));
> + priv->data = device_get_match_data(dev);
> + priv->dev = dev;
> + priv->map = xzalloc(sizeof(uint32_t) * priv->data->nrows);
> +
> + config.name = "k3-otp";
> + config.reg_bits = 32;
> + config.val_bits = 32;
> + config.reg_stride = 4;
> + config.max_register = sizeof(uint32_t) * priv->data->nrows - 1;
Shouldn't this be sizeof(uint32_t) * (priv->data->nrows - 1) ?
> +
> + ret = ti_k3_otp_read_map(priv);
> + if (ret) {
> + /*
> + * Reading fuses is only supported by TI downstream TF-A and
> + * only on AM62L. Do not bother the user with error messages
> + * when it's not supported.
> + */
> + if (ret == -EOPNOTSUPP)
> + return -ENODEV;
I think this is still worth a message, even if not at error level.
It would be confusing otherwise.
> + return ret;
> + }
> +
> + map = regmap_init(dev, &ti_k3_otp_regmap_bus, priv, &config);
> + if (IS_ERR(map))
> + return PTR_ERR(map);
> +
> + return PTR_ERR_OR_ZERO(nvmem_regmap_register(map, "ti-k3-otp"));
> +}
> +
> +struct ti_k3_otp_driver_data am62x_data = {
> + .skip_init = 2,
> + .bits_per_row = 25,
> + .nrows = 42,
> +};
> +
> +struct ti_k3_otp_driver_data am62l_data = {
> + .skip_init = 0,
> + .bits_per_row = 25,
> + .nrows = 42,
> +};
> +
> +static struct of_device_id ti_k3_otp_dt_ids[] = {
> + { .compatible = "ti,am62x-otp", .data = &am62x_data },
> + { .compatible = "ti,am62l-otp", .data = &am62l_data },
> + { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, ti_k3_otp_dt_ids);
> +
> +static struct driver ti_k3_otp_driver = {
> + .name = "ti-k3-otp",
> + .probe = ti_k3_otp_probe,
> + .of_compatible = ti_k3_otp_dt_ids,
> +};
> +device_platform_driver(ti_k3_otp_driver);
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2025-11-25 12:48 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-11-25 11:40 [PATCH] nvmem: k3: add fuse support Sascha Hauer
2025-11-25 12:47 ` Ahmad Fatoum
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox