-----Original Message----- From: Peter Robinson <pbrobin...@gmail.com> Sent: Wednesday, March 25, 2020 5:53 AM To: Tom Warren <twar...@nvidia.com> Cc: u-boot@lists.denx.de; Stephen Warren <swar...@nvidia.com>; Thierry Reding <tred...@nvidia.com>; Jonathan Hunter <jonath...@nvidia.com>; tomcwarren3...@gmail.com Subject: Re: [PATCH] ARM: tegra: Add NVIDIA Jetson Nano Developer Kit support
External email: Use caution opening links or attachments Hi Tom, Do you have this and the other patches you've posted on a git branch somewhere, for some reason they're not showing up in patchwork [1] which makes it less straight forward to test. Peter [1] http://patchwork.ozlabs.org/project/uboot/list/?q=tegra [Tom] That's weird, I sent them all using git send-email to u-boot@lists.denx.de. But you are right, I don't see any of them on Patchwork. TomR - any idea why? Peter - you can find all of the patches (plus a WIP fix for a couple of load address conflicts when loading an FDT from extlinux) in tegra/next upstream, just updated today. On Tue, Mar 24, 2020 at 7:03 PM <twar...@nvidia.com> wrote: > > From: Tom Warren <twar...@nvidia.com> > > The Jetson Nano Developer Kit is a Tegra X1-based development board. > It is similar to Jetson TX1 but it is not pin compatible. It features > 4GB of LPDDR4, a SPI NOR flash for early boot firmware and an SD card > slot used for storage. > > HDMI 2.0 or DP 1.2 are available for display, four USB ports (3 USB > 2.0 and 1 USB 3.0) can be used to attach a variety of peripherals and > a PCI Ethernet controller provides onboard network connectivity. NVMe > support has also been added. Env save is at the end of QSPI (4MB-8K). > > A 40-pin header on the board can be used to extend the capabilities > and exposed interfaces of the Jetson Nano. > > Signed-off-by: Thierry Reding <tred...@nvidia.com> > Signed-off-by: Tom Warren <twar...@nvidia.com> > --- > arch/arm/dts/Makefile | 3 +- > arch/arm/dts/tegra210-p3450-0000.dts | 147 +++++++++++++++++++++++++++++ > arch/arm/mach-tegra/board2.c | 25 +++++ > arch/arm/mach-tegra/tegra210/Kconfig | 7 ++ > board/nvidia/p3450-0000/Kconfig | 12 +++ > board/nvidia/p3450-0000/MAINTAINERS | 6 ++ > board/nvidia/p3450-0000/Makefile | 8 ++ > board/nvidia/p3450-0000/p3450-0000.c | 178 > +++++++++++++++++++++++++++++++++++ > configs/p3450-0000_defconfig | 64 +++++++++++++ > include/configs/p3450-0000.h | 46 +++++++++ > 10 files changed, 495 insertions(+), 1 deletion(-) create mode > 100644 arch/arm/dts/tegra210-p3450-0000.dts > create mode 100644 board/nvidia/p3450-0000/Kconfig create mode > 100644 board/nvidia/p3450-0000/MAINTAINERS > create mode 100644 board/nvidia/p3450-0000/Makefile create mode > 100644 board/nvidia/p3450-0000/p3450-0000.c > create mode 100644 configs/p3450-0000_defconfig create mode 100644 > include/configs/p3450-0000.h > > diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index > 9c593b2..820ee97 100644 > --- a/arch/arm/dts/Makefile > +++ b/arch/arm/dts/Makefile > @@ -180,7 +180,8 @@ dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \ > tegra210-e2220-1170.dtb \ > tegra210-p2371-0000.dtb \ > tegra210-p2371-2180.dtb \ > - tegra210-p2571.dtb > + tegra210-p2571.dtb \ > + tegra210-p3450-0000.dtb > > dtb-$(CONFIG_ARCH_MVEBU) += \ > armada-3720-db.dtb \ > diff --git a/arch/arm/dts/tegra210-p3450-0000.dts > b/arch/arm/dts/tegra210-p3450-0000.dts > new file mode 100644 > index 0000000..9ef744a > --- /dev/null > +++ b/arch/arm/dts/tegra210-p3450-0000.dts > @@ -0,0 +1,147 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * (C) Copyright 2019-2020 NVIDIA Corporation <www.nvidia.com> */ > +/dts-v1/; > + > +#include "tegra210.dtsi" > + > +/ { > + model = "NVIDIA Jetson Nano Developer Kit"; > + compatible = "nvidia,p3450-0000", "nvidia,tegra210"; > + > + chosen { > + stdout-path = &uarta; > + }; > + > + aliases { > + ethernet = "/pcie@1003000/pci@2,0/ethernet@0,0"; > + i2c0 = "/i2c@7000d000"; > + i2c2 = "/i2c@7000c400"; > + i2c3 = "/i2c@7000c500"; > + i2c4 = "/i2c@7000c700"; > + mmc0 = "/sdhci@700b0600"; > + mmc1 = "/sdhci@700b0000"; > + spi0 = "/spi@70410000"; > + usb0 = "/usb@7d000000"; > + }; > + > + memory { > + reg = <0x0 0x80000000 0x0 0xc0000000>; > + }; > + > + pcie@1003000 { > + status = "okay"; > + > + pci@1,0 { > + status = "okay"; > + }; > + > + pci@2,0 { > + status = "okay"; > + > + ethernet@0,0 { > + reg = <0x000000 0 0 0 0>; > + local-mac-address = [ 00 00 00 00 00 00 ]; > + }; > + }; > + }; > + > + serial@70006000 { > + status = "okay"; > + }; > + > + padctl@7009f000 { > + pinctrl-0 = <&padctl_default>; > + pinctrl-names = "default"; > + > + padctl_default: pinmux { > + xusb { > + nvidia,lanes = "otg-1", "otg-2"; > + nvidia,function = "xusb"; > + nvidia,iddq = <0>; > + }; > + > + usb3 { > + nvidia,lanes = "pcie-5", "pcie-6"; > + nvidia,function = "usb3"; > + nvidia,iddq = <0>; > + }; > + > + pcie-x1 { > + nvidia,lanes = "pcie-0"; > + nvidia,function = "pcie-x1"; > + nvidia,iddq = <0>; > + }; > + > + pcie-x4 { > + nvidia,lanes = "pcie-1", "pcie-2", > + "pcie-3", "pcie-4"; > + nvidia,function = "pcie-x4"; > + nvidia,iddq = <0>; > + }; > + > + sata { > + nvidia,lanes = "sata-0"; > + nvidia,function = "sata"; > + nvidia,iddq = <0>; > + }; > + }; > + }; > + > + sdhci@700b0000 { > + status = "okay"; > + cd-gpios = <&gpio TEGRA_GPIO(Z, 1) GPIO_ACTIVE_LOW>; > + power-gpios = <&gpio TEGRA_GPIO(Z, 3) GPIO_ACTIVE_HIGH>; > + bus-width = <4>; > + }; > + > + sdhci@700b0600 { > + status = "okay"; > + bus-width = <8>; > + non-removable; > + }; > + > + i2c@7000c400 { > + status = "okay"; > + clock-frequency = <400000>; > + }; > + > + i2c@7000c500 { > + status = "okay"; > + clock-frequency = <400000>; > + }; > + > + i2c@7000c700 { > + status = "okay"; > + clock-frequency = <400000>; > + }; > + > + i2c@7000d000 { > + status = "okay"; > + clock-frequency = <400000>; > + }; > + > + spi@70410000 { > + status = "okay"; > + spi-max-frequency = <80000000>; > + }; > + > + usb@7d000000 { > + status = "okay"; > + dr_mode = "peripheral"; > + }; > + > + clocks { > + compatible = "simple-bus"; > + #address-cells = <1>; > + #size-cells = <0>; > + > + clk32k_in: clock@0 { > + compatible = "fixed-clock"; > + reg = <0>; > + #clock-cells = <0>; > + clock-frequency = <32768>; > + }; > + }; > +}; > diff --git a/arch/arm/mach-tegra/board2.c > b/arch/arm/mach-tegra/board2.c index 787ff97..224efc9 100644 > --- a/arch/arm/mach-tegra/board2.c > +++ b/arch/arm/mach-tegra/board2.c > @@ -217,6 +217,31 @@ int board_early_init_f(void) > arch_timer_init(); > #endif > > +#if defined(CONFIG_DISABLE_SDMMC1_EARLY) > + /* > + * Turn off (reset/disable) SDMMC1 on Nano here, before GPIO INIT. > + * We do this because earlier bootloaders have enabled power to > + * SDMMC1 on Nano, and toggling power-gpio (PZ3) in pinmux_init() > + * results in power being back-driven into the SD-card and SDMMC1 > + * HW, which is 'bad' as per the HW team. > + * > + * From the HW team: "LDO2 from the PMIC has already been set to 3.3v > in > + * nvtboot/CBoot on Nano (for SD-card boot). So when U-Boot's > GPIO_INIT > + * table sets PZ3 to OUT0 as per the pinmux spreadsheet, it turns off > + * the loadswitch. When PZ3 is 0 and not driving, essentially the > SDCard > + * voltage turns off. Since the SDCard voltage is no longer there, the > + * SDMMC CLK/DAT lines are backdriving into what essentially is a > + * powered-off SDCard, that's why the voltage drops from 3.3V to > ~1.6V" > + * > + * Note that this can probably be removed when we change over to > storing > + * all BL components on QSPI on Nano, and U-Boot then becomes the > first > + * one to turn on SDMMC1 power. Another fix would be to have CBoot > + * disable power/gate SDMMC1 off before handing off to U-Boot/kernel. > + */ > + reset_set_enable(PERIPH_ID_SDMMC1, 1); > + clock_set_enable(PERIPH_ID_SDMMC1, 0); #endif /* > +CONFIG_DISABLE_SDMMC1_EARLY */ > + > pinmux_init(); > board_init_uart_f(); > > diff --git a/arch/arm/mach-tegra/tegra210/Kconfig > b/arch/arm/mach-tegra/tegra210/Kconfig > index 3637473..97ed8e0 100644 > --- a/arch/arm/mach-tegra/tegra210/Kconfig > +++ b/arch/arm/mach-tegra/tegra210/Kconfig > @@ -35,6 +35,12 @@ config TARGET_P2571 > help > P2571 is a P2530 married to a P1963 I/O board > > +config TARGET_P3450_0000 > + bool "NVIDIA Jetson Nano Developer Kit" > + select BOARD_LATE_INIT > + help > + P3450-0000 is a P3448 CPU board married to a P3449 I/O board. > + > endchoice > > config SYS_SOC > @@ -44,5 +50,6 @@ source "board/nvidia/e2220-1170/Kconfig" > source "board/nvidia/p2371-0000/Kconfig" > source "board/nvidia/p2371-2180/Kconfig" > source "board/nvidia/p2571/Kconfig" > +source "board/nvidia/p3450-0000/Kconfig" > > endif > diff --git a/board/nvidia/p3450-0000/Kconfig > b/board/nvidia/p3450-0000/Kconfig new file mode 100644 index > 0000000..7a08cd8 > --- /dev/null > +++ b/board/nvidia/p3450-0000/Kconfig > @@ -0,0 +1,12 @@ > +if TARGET_P3450_0000 > + > +config SYS_BOARD > + default "p3450-0000" > + > +config SYS_VENDOR > + default "nvidia" > + > +config SYS_CONFIG_NAME > + default "p3450-0000" > + > +endif > diff --git a/board/nvidia/p3450-0000/MAINTAINERS > b/board/nvidia/p3450-0000/MAINTAINERS > new file mode 100644 > index 0000000..4070006 > --- /dev/null > +++ b/board/nvidia/p3450-0000/MAINTAINERS > @@ -0,0 +1,6 @@ > +P3450-0000 BOARD > +M: Tom Warren <twar...@nvidia.com> > +S: Maintained > +F: board/nvidia/p3450-0000/ > +F: include/configs/p3450-0000.h > +F: configs/p3450-0000_defconfig > diff --git a/board/nvidia/p3450-0000/Makefile > b/board/nvidia/p3450-0000/Makefile > new file mode 100644 > index 0000000..993c506 > --- /dev/null > +++ b/board/nvidia/p3450-0000/Makefile > @@ -0,0 +1,8 @@ > +# > +# (C) Copyright 2018 > +# NVIDIA Corporation <www.nvidia.com> # > +# SPDX-License-Identifier: GPL-2.0+ > +# > + > +obj-y += p3450-0000.o > diff --git a/board/nvidia/p3450-0000/p3450-0000.c > b/board/nvidia/p3450-0000/p3450-0000.c > new file mode 100644 > index 0000000..f4212ab > --- /dev/null > +++ b/board/nvidia/p3450-0000/p3450-0000.c > @@ -0,0 +1,178 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * (C) Copyright 2018-2019 > + * NVIDIA Corporation <www.nvidia.com> > + * > + */ > + > +#include <common.h> > +#include <fdtdec.h> > +#include <i2c.h> > +#include <linux/libfdt.h> > +#include <pca953x.h> > +#include <asm/arch-tegra/cboot.h> > +#include <asm/arch/gpio.h> > +#include <asm/arch/pinmux.h> > +#include "../p2571/max77620_init.h" > + > +void pin_mux_mmc(void) > +{ > + struct udevice *dev; > + uchar val; > + int ret; > + > + /* Turn on MAX77620 LDO2 to 3.3V for SD card power */ > + debug("%s: Set LDO2 for VDDIO_SDMMC_AP power to 3.3V\n", __func__); > + ret = i2c_get_chip_for_busnum(0, MAX77620_I2C_ADDR_7BIT, 1, &dev); > + if (ret) { > + printf("%s: Cannot find MAX77620 I2C chip\n", __func__); > + return; > + } > + /* 0xF2 for 3.3v, enabled: bit7:6 = 11 = enable, bit5:0 = voltage */ > + val = 0xF2; > + ret = dm_i2c_write(dev, MAX77620_CNFG1_L2_REG, &val, 1); > + if (ret) > + printf("i2c_write 0 0x3c 0x27 failed: %d\n", ret); > + > + /* Disable LDO4 discharge */ > + ret = dm_i2c_read(dev, MAX77620_CNFG2_L4_REG, &val, 1); > + if (ret) { > + printf("i2c_read 0 0x3c 0x2c failed: %d\n", ret); > + } else { > + val &= ~BIT(1); /* ADE */ > + ret = dm_i2c_write(dev, MAX77620_CNFG2_L4_REG, &val, 1); > + if (ret) > + printf("i2c_write 0 0x3c 0x2c failed: %d\n", ret); > + } > + > + /* Set MBLPD */ > + ret = dm_i2c_read(dev, MAX77620_CNFGGLBL1_REG, &val, 1); > + if (ret) { > + printf("i2c_write 0 0x3c 0x00 failed: %d\n", ret); > + } else { > + val |= BIT(6); /* MBLPD */ > + ret = dm_i2c_write(dev, MAX77620_CNFGGLBL1_REG, &val, 1); > + if (ret) > + printf("i2c_write 0 0x3c 0x00 failed: %d\n", ret); > + } > +} > + > +#ifdef CONFIG_PCI_TEGRA > +int tegra_pcie_board_init(void) > +{ > + struct udevice *dev; > + uchar val; > + int ret; > + > + /* Turn on MAX77620 LDO1 to 1.05V for PEX power */ > + debug("%s: Set LDO1 for PEX power to 1.05V\n", __func__); > + ret = i2c_get_chip_for_busnum(0, MAX77620_I2C_ADDR_7BIT, 1, &dev); > + if (ret) { > + printf("%s: Cannot find MAX77620 I2C chip\n", __func__); > + return -1; > + } > + /* 0xCA for 1.05v, enabled: bit7:6 = 11 = enable, bit5:0 = voltage */ > + val = 0xCA; > + ret = dm_i2c_write(dev, MAX77620_CNFG1_L1_REG, &val, 1); > + if (ret) > + printf("i2c_write 0 0x3c 0x25 failed: %d\n", ret); > + > + return 0; > +} > +#endif /* PCI */ > + > +static void ft_mac_address_setup(void *fdt) { > + const void *cboot_fdt = (const void *)cboot_boot_x0; > + uint8_t mac[ETH_ALEN], local_mac[ETH_ALEN]; > + const char *path; > + int offset, err; > + > + err = cboot_get_ethaddr(cboot_fdt, local_mac); > + if (err < 0) > + memset(local_mac, 0, ETH_ALEN); > + > + path = fdt_get_alias(fdt, "ethernet"); > + if (!path) > + return; > + > + debug("ethernet alias found: %s\n", path); > + > + offset = fdt_path_offset(fdt, path); > + if (offset < 0) { > + printf("ethernet alias points to absent node %s\n", path); > + return; > + } > + > + if (is_valid_ethaddr(local_mac)) { > + err = fdt_setprop(fdt, offset, "local-mac-address", local_mac, > + ETH_ALEN); > + if (!err) > + debug("Local MAC address set: %pM\n", local_mac); > + } > + > + if (eth_env_get_enetaddr("ethaddr", mac)) { > + if (memcmp(local_mac, mac, ETH_ALEN) != 0) { > + err = fdt_setprop(fdt, offset, "mac-address", mac, > + ETH_ALEN); > + if (!err) > + debug("MAC address set: %pM\n", mac); > + } > + } > +} > + > +static int ft_copy_carveout(void *dst, const void *src, const char > +*node) { > + struct fdt_memory fb; > + int err; > + > + err = fdtdec_get_carveout(src, node, "memory-region", 0, &fb); > + if (err < 0) { > + if (err != -FDT_ERR_NOTFOUND) > + printf("failed to get carveout for %s: %d\n", node, > + err); > + > + return err; > + } > + > + err = fdtdec_set_carveout(dst, node, "memory-region", 0, > "framebuffer", > + &fb); > + if (err < 0) { > + printf("failed to set carveout for %s: %d\n", node, err); > + return err; > + } > + > + return 0; > +} > + > +static void ft_carveout_setup(void *fdt) { > + const void *cboot_fdt = (const void *)cboot_boot_x0; > + static const char * const nodes[] = { > + "/host1x@50000000/dc@54200000", > + "/host1x@50000000/dc@54240000", > + }; > + unsigned int i; > + int err; > + > + for (i = 0; i < ARRAY_SIZE(nodes); i++) { > + printf("copying carveout for %s...\n", nodes[i]); > + > + err = ft_copy_carveout(fdt, cboot_fdt, nodes[i]); > + if (err < 0) { > + if (err != -FDT_ERR_NOTFOUND) > + printf("failed to copy carveout for %s: %d\n", > + nodes[i], err); > + > + continue; > + } > + } > +} > + > +int ft_board_setup(void *fdt, bd_t *bd) { > + ft_mac_address_setup(fdt); > + ft_carveout_setup(fdt); > + > + return 0; > +} > diff --git a/configs/p3450-0000_defconfig > b/configs/p3450-0000_defconfig new file mode 100644 index > 0000000..c861d13 > --- /dev/null > +++ b/configs/p3450-0000_defconfig > @@ -0,0 +1,64 @@ > +CONFIG_ARM=y > +CONFIG_TEGRA=y > +CONFIG_SYS_TEXT_BASE=0x80080000 > +CONFIG_TEGRA210=y > +CONFIG_TARGET_P3450_0000=y > +CONFIG_NR_DRAM_BANKS=2 > +CONFIG_OF_SYSTEM_SETUP=y > +CONFIG_OF_BOARD_SETUP=y > +CONFIG_CONSOLE_MUX=y > +CONFIG_SYS_STDIO_DEREGISTER=y > +CONFIG_SYS_PROMPT="Tegra210 (P3450-0000) # " > +# CONFIG_CMD_IMI is not set > +CONFIG_CMD_DFU=y > +# CONFIG_CMD_FLASH is not set > +CONFIG_CMD_GPIO=y > +CONFIG_CMD_I2C=y > +CONFIG_CMD_MMC=y > +CONFIG_CMD_PCI=y > +CONFIG_CMD_SF=y > +CONFIG_CMD_SPI=y > +CONFIG_CMD_USB=y > +CONFIG_CMD_USB_MASS_STORAGE=y > +# CONFIG_CMD_SETEXPR is not set > +# CONFIG_CMD_NFS is not set > +CONFIG_CMD_EXT4_WRITE=y > +CONFIG_OF_LIVE=y > +CONFIG_DEFAULT_DEVICE_TREE="tegra210-p3450-0000" > +CONFIG_DFU_MMC=y > +CONFIG_DFU_RAM=y > +CONFIG_DFU_SF=y > +CONFIG_SYS_I2C_TEGRA=y > +CONFIG_SPI_FLASH=y > +CONFIG_SPI_FLASH_MACRONIX=y > +CONFIG_SPI_FLASH_USE_4K_SECTORS=y > +CONFIG_SF_DEFAULT_MODE=0 > +CONFIG_SF_DEFAULT_SPEED=24000000 > +CONFIG_RTL8169=y > +CONFIG_PCI=y > +CONFIG_DM_PCI=y > +CONFIG_DM_PCI_COMPAT=y > +CONFIG_PCI_TEGRA=y > +CONFIG_SYS_NS16550=y > +CONFIG_TEGRA114_SPI=y > +CONFIG_TEGRA210_QSPI=y > +CONFIG_USB=y > +CONFIG_DM_USB=y > +CONFIG_USB_EHCI_HCD=y > +CONFIG_USB_EHCI_TEGRA=y > +CONFIG_USB_GADGET=y > +CONFIG_USB_GADGET_MANUFACTURER="NVIDIA" > +CONFIG_USB_GADGET_VENDOR_NUM=0x0955 > +CONFIG_USB_GADGET_PRODUCT_NUM=0x701a > +CONFIG_CI_UDC=y > +CONFIG_USB_GADGET_DOWNLOAD=y > +CONFIG_USB_HOST_ETHER=y > +CONFIG_USB_ETHER_ASIX=y > +# CONFIG_ENV_IS_IN_MMC is not set > +CONFIG_ENV_IS_IN_SPI_FLASH=y > +CONFIG_ENV_SIZE=0x2000 > +CONFIG_ENV_SECT_SIZE=0x1000 > +CONFIG_ENV_OFFSET=0xFFFFE000 > +CONFIG_BOOTP_PREFER_SERVERIP=y > +CONFIG_DISABLE_SDMMC1_EARLY=y > +CONFIG_NVME=y > diff --git a/include/configs/p3450-0000.h > b/include/configs/p3450-0000.h new file mode 100644 index > 0000000..7f05beb > --- /dev/null > +++ b/include/configs/p3450-0000.h > @@ -0,0 +1,46 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > +/* > + * (C) Copyright 2018-2019 NVIDIA Corporation. > + */ > + > +#ifndef _P3450_0000_H > +#define _P3450_0000_H > + > +#include <linux/sizes.h> > + > +#include "tegra210-common.h" > + > +/* High-level configuration options */ > +#define CONFIG_TEGRA_BOARD_STRING "NVIDIA P3450-0000" > + > +/* Board-specific serial config */ > +#define CONFIG_TEGRA_ENABLE_UARTA > + > +/* Only MMC/PXE/DHCP for now, add USB back in later when supported */ > +#define BOOT_TARGET_DEVICES(func) \ > + func(MMC, mmc, 1) \ > + func(MMC, mmc, 0) \ > + func(PXE, pxe, na) \ > + func(DHCP, dhcp, na) > + > +/* Environment at end of QSPI, in the VER partition */ > +#define CONFIG_ENV_SPI_MAX_HZ 48000000 > +#define CONFIG_ENV_SPI_MODE SPI_MODE_0 > +#define CONFIG_SPI_FLASH_SIZE (4 << 20) > + > +#define CONFIG_PREBOOT > + > +#define BOARD_EXTRA_ENV_SETTINGS \ > + "preboot=if test -e mmc 1:1 /u-boot-preboot.scr; then " \ > + "load mmc 1:1 ${scriptaddr} /u-boot-preboot.scr; " \ > + "source ${scriptaddr}; " \ > + "fi\0" > + > +/* General networking support */ > +#include "tegra-common-usb-gadget.h" > +#include "tegra-common-post.h" > + > +/* Crystal is 38.4MHz. clk_m runs at half that rate */ > +#define COUNTER_FREQUENCY 19200000 > + > +#endif /* _P3450_0000_H */ > -- > 1.8.2.1.610.g562af5b > > > ---------------------------------------------------------------------- > ------------- This email message is for the sole use of the intended > recipient(s) and may contain confidential information. Any > unauthorized review, use, disclosure or distribution is prohibited. > If you are not the intended recipient, please contact the sender by > reply email and destroy all copies of the original message. > ---------------------------------------------------------------------- > -------------