All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v3 1/3] drivers: Add board uclass
@ 2018-06-27  7:03 Mario Six
  2018-06-27  7:03 ` [U-Boot] [PATCH v3 2/3] board: Add gazerbeam driver Mario Six
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Mario Six @ 2018-06-27  7:03 UTC (permalink / raw)
  To: u-boot

Since there is no canonical "board device" that can be used in board
files, it is difficult to use DM function for board initialization in
these cases.

Hence, add a uclass that implements a simple "board device", which can
hold devices not suitable anywhere else in the device tree, and is also
able to read encoded information, e.g. hard-wired GPIOs on a GPIO
expander, read-only memory ICs, etc. that carry information about the
hardware.

The devices of this uclass expose methods to read generic data types
(integers, strings, booleans) to encode the information provided by the
hardware.

Signed-off-by: Mario Six <mario.six@gdsys.cc>

---

v2 -> v3:
* Expanded comment on detect()
* Added error handling in example
* Renamed get_board() to board_get()
* Fixed style violations
* Documented board_get
* Made comments conform with kernel-doc
* Fixed SPDC-License-Identifier position

v1 -> v2:
* Corrected description of dev parameter of devinfo_detect
* Added size parameter to devinfo_get_str
* Expanded uclass documentation
* Added function to get devinfo instance
* Renamed the uclass from devinfo to board

---
 drivers/Kconfig              |   2 +
 drivers/Makefile             |   1 +
 drivers/board/Kconfig        |  17 ++++++
 drivers/board/Makefile       |   6 ++
 drivers/board/board-uclass.c |  60 +++++++++++++++++++
 include/board.h              | 139 +++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h       |   1 +
 7 files changed, 226 insertions(+)
 create mode 100644 drivers/board/Kconfig
 create mode 100644 drivers/board/Makefile
 create mode 100644 drivers/board/board-uclass.c
 create mode 100644 include/board.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 9e21b28750..48f7302506 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -22,6 +22,8 @@ source "drivers/ddr/Kconfig"

 source "drivers/demo/Kconfig"

+source "drivers/board/Kconfig"
+
 source "drivers/ddr/fsl/Kconfig"

 source "drivers/dfu/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index a213ea9671..c2a363a66f 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -68,6 +68,7 @@ obj-y += ata/
 obj-$(CONFIG_DM_DEMO) += demo/
 obj-$(CONFIG_BIOSEMU) += bios_emulator/
 obj-y += block/
+obj-y += board/
 obj-$(CONFIG_BOOTCOUNT_LIMIT) += bootcount/
 obj-$(CONFIG_CPU) += cpu/
 obj-y += crypto/
diff --git a/drivers/board/Kconfig b/drivers/board/Kconfig
new file mode 100644
index 0000000000..cc1cf27205
--- /dev/null
+++ b/drivers/board/Kconfig
@@ -0,0 +1,17 @@
+menuconfig BOARD
+	bool "Device Information"
+	help
+	  Support methods to query hardware configurations from internal
+	  mechanisms (e.g. reading GPIO values, determining the presence of
+	  devices on busses, etc.). This enables the usage of U-Boot with
+	  modular board architectures.
+
+if BOARD
+
+
+config BOARD_GAZERBEAM
+	bool "Enable device information for the Gazerbeam board"
+	help
+	  Support querying device information for the gdsys Gazerbeam board.
+
+endif
diff --git a/drivers/board/Makefile b/drivers/board/Makefile
new file mode 100644
index 0000000000..12dd2030cf
--- /dev/null
+++ b/drivers/board/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier:	GPL-2.0+
+#
+# (C) Copyright 2017
+# Mario Six,  Guntermann & Drunck GmbH, mario.six at gdsys.cc
+obj-$(CONFIG_BOARD) += board-uclass.o
+obj-$(CONFIG_BOARD_GAZERBEAM) += gazerbeam.o
diff --git a/drivers/board/board-uclass.c b/drivers/board/board-uclass.c
new file mode 100644
index 0000000000..a516ba4962
--- /dev/null
+++ b/drivers/board/board-uclass.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2017
+ * Mario Six,  Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <board.h>
+
+int board_get(struct udevice **devp)
+{
+	return uclass_first_device_err(UCLASS_BOARD, devp);
+}
+
+int board_detect(struct udevice *dev)
+{
+	struct board_ops *ops = board_get_ops(dev);
+
+	if (!ops->detect)
+		return -ENOSYS;
+
+	return ops->detect(dev);
+}
+
+int board_get_bool(struct udevice *dev, int id, bool *val)
+{
+	struct board_ops *ops = board_get_ops(dev);
+
+	if (!ops->get_bool)
+		return -ENOSYS;
+
+	return ops->get_bool(dev, id, val);
+}
+
+int board_get_int(struct udevice *dev, int id, int *val)
+{
+	struct board_ops *ops = board_get_ops(dev);
+
+	if (!ops->get_int)
+		return -ENOSYS;
+
+	return ops->get_int(dev, id, val);
+}
+
+int board_get_str(struct udevice *dev, int id, size_t size, char *val)
+{
+	struct board_ops *ops = board_get_ops(dev);
+
+	if (!ops->get_str)
+		return -ENOSYS;
+
+	return ops->get_str(dev, id, size, val);
+}
+
+UCLASS_DRIVER(board) = {
+	.id		= UCLASS_BOARD,
+	.name		= "board",
+	.post_bind	= dm_scan_fdt_dev,
+};
diff --git a/include/board.h b/include/board.h
new file mode 100644
index 0000000000..9dc78684f8
--- /dev/null
+++ b/include/board.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2017
+ * Mario Six,  Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ */
+
+/*
+ * This uclass encapsulates hardware methods to gather information about a
+ * board or a specific device such as hard-wired GPIOs on GPIO expanders,
+ * read-only data in flash ICs, or similar.
+ *
+ * The interface offers functions to read the usual standard data types (bool,
+ * int, string) from the device, each of which is identified by a static
+ * numeric ID (which will usually be defined as a enum in a header file).
+ *
+ * If for example the board had a read-only serial number flash IC, we could
+ * call
+ *
+ * ret = board_detect(dev);
+ * if (ret) {
+ *	debug("board device not found.");
+ *	return ret;
+ * }
+ *
+ * ret = board_get_int(dev, ID_SERIAL_NUMBER, &serial);
+ * if (ret) {
+ *	debug("Error when reading serial number from device.");
+ *	return ret;
+ * }
+ *
+ * to read the serial number.
+ */
+
+struct board_ops {
+	/**
+	 * detect() - Run the hardware info detection procedure for this
+	 *	      device.
+	 * @dev:      The device containing the information
+	 *
+	 * This operation might take a long time (e.g. read from EEPROM,
+	 * check the presence of a device on a bus etc.), hence this is not
+	 * done in the probe() method, but later during operation in this
+	 * dedicated method.
+	 *
+	 * Return: 0 if OK, -ve on error.
+	 */
+	int (*detect)(struct udevice *dev);
+
+	/**
+	 * get_bool() - Read a specific bool data value that describes the
+	 *		hardware setup.
+	 * @dev:	The board instance to gather the data.
+	 * @id:		A unique identifier for the bool value to be read.
+	 * @val:	Pointer to a buffer that receives the value read.
+	 *
+	 * Return: 0 if OK, -ve on error.
+	 */
+	int (*get_bool)(struct udevice *dev, int id, bool *val);
+
+	/**
+	 * get_int() - Read a specific int data value that describes the
+	 *	       hardware setup.
+	 * @dev:       The board instance to gather the data.
+	 * @id:        A unique identifier for the int value to be read.
+	 * @val:       Pointer to a buffer that receives the value read.
+	 *
+	 * Return: 0 if OK, -ve on error.
+	 */
+	int (*get_int)(struct udevice *dev, int id, int *val);
+
+	/**
+	 * get_str() - Read a specific string data value that describes the
+	 *	       hardware setup.
+	 * @dev:	The board instance to gather the data.
+	 * @id:		A unique identifier for the string value to be read.
+	 * @size:	The size of the buffer to receive the string data.
+	 * @val:	Pointer to a buffer that receives the value read.
+	 *
+	 * Return: 0 if OK, -ve on error.
+	 */
+	int (*get_str)(struct udevice *dev, int id, size_t size, char *val);
+};
+
+#define board_get_ops(dev)	((struct board_ops *)(dev)->driver->ops)
+
+/**
+ * board_detect() - Run the hardware info detection procedure for this device.
+ *
+ * @dev:	The device containing the information
+ *
+ * Return: 0 if OK, -ve on error.
+ */
+int board_detect(struct udevice *dev);
+
+/**
+ * board_get_bool() - Read a specific bool data value that describes the
+ *		      hardware setup.
+ * @dev:	The board instance to gather the data.
+ * @id:		A unique identifier for the bool value to be read.
+ * @val:	Pointer to a buffer that receives the value read.
+ *
+ * Return: 0 if OK, -ve on error.
+ */
+int board_get_bool(struct udevice *dev, int id, bool *val);
+
+/**
+ * board_get_int() - Read a specific int data value that describes the
+ *		     hardware setup.
+ * @dev:	The board instance to gather the data.
+ * @id:		A unique identifier for the int value to be read.
+ * @val:	Pointer to a buffer that receives the value read.
+ *
+ * Return: 0 if OK, -ve on error.
+ */
+int board_get_int(struct udevice *dev, int id, int *val);
+
+/**
+ * board_get_str() - Read a specific string data value that describes the
+ *		     hardware setup.
+ * @dev:	The board instance to gather the data.
+ * @id:		A unique identifier for the string value to be read.
+ * @size:	The size of the buffer to receive the string data.
+ * @val:	Pointer to a buffer that receives the value read.
+ *
+ * Return: 0 if OK, -ve on error.
+ */
+int board_get_str(struct udevice *dev, int id, size_t size, char *val);
+
+/**
+ * board_get() - Return the board device for the board in question.
+ * @devp: Pointer to structure to receive the board device.
+ *
+ * Since there can only be at most one board instance, the API can supply a
+ * function that returns the unique device. This is especially useful for use
+ * in board files.
+ *
+ * Return: 0 if OK, -ve on error.
+ */
+int board_get(struct udevice **devp);
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index d7f9df3583..cddfc82d11 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -29,6 +29,7 @@ enum uclass_id {
 	UCLASS_ADC,		/* Analog-to-digital converter */
 	UCLASS_AHCI,		/* SATA disk controller */
 	UCLASS_BLK,		/* Block device */
+	UCLASS_BOARD,		/* Device information from hardware */
 	UCLASS_CLK,		/* Clock source, e.g. used by peripherals */
 	UCLASS_CPU,		/* CPU, typically part of an SoC */
 	UCLASS_CROS_EC,		/* Chrome OS EC */
--
2.11.0

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

* [U-Boot] [PATCH v3 2/3] board: Add gazerbeam driver
  2018-06-27  7:03 [U-Boot] [PATCH v3 1/3] drivers: Add board uclass Mario Six
@ 2018-06-27  7:03 ` Mario Six
  2018-06-27  7:03 ` [U-Boot] [PATCH v3 3/3] test: Add tests for board uclass Mario Six
  2018-06-27 21:03 ` [U-Boot] [PATCH v3 1/3] drivers: Add " Simon Glass
  2 siblings, 0 replies; 5+ messages in thread
From: Mario Six @ 2018-06-27  7:03 UTC (permalink / raw)
  To: u-boot

Add a board driver for the upcoming gdsys Gazerbeam board.

Signed-off-by: Mario Six <mario.six@gdsys.cc>

---

v2 -> v3:
* Set startup-finished GPIOs during probe
* Added driver binding file for gazerbeam board
* Improved error handling
* Improved error/debug output
* Improved documentation
* Turned magic numbers into named constants

v1 -> v2:
* Improved error handling
* Renamed DT properties
* Moved the driver over to the board uclass

---
 .../bindings/board/gdsys,board_gazerbeam.txt       |  46 ++++
 drivers/board/gazerbeam.c                          | 262 +++++++++++++++++++++
 drivers/board/gazerbeam.h                          |  18 ++
 3 files changed, 326 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/board/gdsys,board_gazerbeam.txt
 create mode 100644 drivers/board/gazerbeam.c
 create mode 100644 drivers/board/gazerbeam.h

diff --git a/Documentation/devicetree/bindings/board/gdsys,board_gazerbeam.txt b/Documentation/devicetree/bindings/board/gdsys,board_gazerbeam.txt
new file mode 100644
index 0000000000..28c1080d90
--- /dev/null
+++ b/Documentation/devicetree/bindings/board/gdsys,board_gazerbeam.txt
@@ -0,0 +1,46 @@
+gdsys Gazerbeam board driver
+
+This driver provides capabilities to access the gdsys Gazerbeam board's device
+information. Furthermore, phandles to some internal devices are provided for
+the board files.
+
+Required properties:
+- compatible:  should be "gdsys,board_gazerbeam"
+- csb:         phandle to the board's coherent system bus (CSB) device node
+- rxaui[0-3]:  phandles to the rxaui control device nodes
+- fpga[0-1]:   phandles to the board's gdsys FPGA device nodes
+- ioep[0-1]:   phandles to the board's IO endpoint device nodes
+- ver-gpios:   GPIO list to read the hardware version from
+- var-gpios:   GPIO list to read the hardware variant information from
+- reset-gpios: GPIO list for the board's reset GPIOs
+
+Example:
+
+
+board {
+	compatible = "gdsys,board_gazerbeam";
+	csb = <&board_soc>;
+	serdes = <&SERDES>;
+	rxaui0 = <&RXAUI0>;
+	rxaui1 = <&RXAUI1>;
+	rxaui2 = <&RXAUI2>;
+	rxaui3 = <&RXAUI3>;
+	fpga0 = <&FPGA0>;
+	fpga1 = <&FPGA1>;
+	ioep0 = <&IOEP0>;
+	ioep1 = <&IOEP1>;
+
+	ver-gpios = <&PPCPCA 12 0
+		     &PPCPCA 13 0
+		     &PPCPCA 14 0
+		     &PPCPCA 15 0>;
+
+	/* MC2/SC-Board */
+	var-gpios-mc2 = <&GPIO_VB0 0 0    /* VAR-MC_SC */
+			 &GPIO_VB0 11 0>; /* VAR-CON */
+	/* MC4-Board */
+	var-gpios-mc4 = <&GPIO_VB1 0 0    /* VAR-MC_SC */
+			 &GPIO_VB1 11 0>; /* VAR-CON */
+
+	reset-gpios = <&gpio0 1 0 &gpio0 2 1>;
+};
diff --git a/drivers/board/gazerbeam.c b/drivers/board/gazerbeam.c
new file mode 100644
index 0000000000..481cce8e80
--- /dev/null
+++ b/drivers/board/gazerbeam.c
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2017
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <board.h>
+#include <i2c.h>
+#include <asm/gpio.h>
+
+#include "gazerbeam.h"
+
+/* Sequence number of I2C bus that holds the GPIO expanders */
+static const int I2C_BUS_SEQ_NO = 1;
+
+/* I2C address of SC/MC2 expander */
+static const int MC2_EXPANDER_ADDR = 0x20;
+/* I2C address of MC4 expander */
+static const int MC4_EXPANDER_ADDR = 0x22;
+
+/* Number of the GPIO to read the SC data from */
+static const int SC_GPIO_NO;
+/* Number of the GPIO to read the CON data from */
+static const int CON_GPIO_NO = 1;
+
+/**
+ * struct board_gazerbeam_priv - Private data structure for the gazerbeam board
+ *				 driver.
+ * @reset_gpios:  GPIOs for the board's reset GPIOs.
+ * @var_gpios:	  GPIOs for the board's hardware variant GPIOs
+ * @ver_gpios:	  GPIOs for the board's hardware version GPIOs
+ * @variant:	  Container for the board's hardware variant (CON/CPU)
+ * @multichannel: Container for the board's multichannel variant (MC4/MC2/SC)
+ * @hwversion:	  Container for the board's hardware version
+ */
+struct board_gazerbeam_priv {
+	struct gpio_desc reset_gpios[2];
+	struct gpio_desc var_gpios[2];
+	struct gpio_desc ver_gpios[4];
+	int variant;
+	int multichannel;
+	int hwversion;
+};
+
+/**
+ * _read_board_variant_data() - Read variant information from the hardware.
+ * @dev: The board device for which to determine the multichannel and device
+ *	 type information.
+ *
+ * The data read from the board's hardware (mostly hard-wired GPIOs) is stored
+ * in the private data structure of the driver to be used by other driver
+ * methods.
+ *
+ * Return: 0 if OK, -ve on error.
+ */
+static int _read_board_variant_data(struct udevice *dev)
+{
+	struct board_gazerbeam_priv *priv = dev_get_priv(dev);
+	struct udevice *i2c_bus;
+	struct udevice *dummy;
+	char *listname;
+	int mc4, mc2, sc, con;
+	int gpio_num;
+	int res;
+
+	res = uclass_get_device_by_seq(UCLASS_I2C, I2C_BUS_SEQ_NO, &i2c_bus);
+	if (res) {
+		debug("%s: Could not get I2C bus %d (err = %d)\n",
+		      dev->name, I2C_BUS_SEQ_NO, res);
+		return res;
+	}
+
+	if (!i2c_bus) {
+		debug("%s: Could not get I2C bus %d\n",
+		      dev->name, I2C_BUS_SEQ_NO);
+		return -EIO;
+	}
+
+	mc2 = !dm_i2c_probe(i2c_bus, MC2_EXPANDER_ADDR, 0, &dummy);
+	mc4 = !dm_i2c_probe(i2c_bus, MC4_EXPANDER_ADDR, 0, &dummy);
+
+	if (mc2 && mc4) {
+		debug("%s: Board hardware configuration inconsistent.\n",
+		      dev->name);
+		return -EINVAL;
+	}
+
+	listname = mc2 ? "var-gpios-mc2" : "var-gpios-mc4";
+
+	gpio_num = gpio_request_list_by_name(dev, listname, priv->var_gpios,
+					     ARRAY_SIZE(priv->var_gpios),
+					     GPIOD_IS_IN);
+	if (gpio_num < 0) {
+		debug("%s: Requesting gpio list %s failed (err = %d).\n",
+		      dev->name, listname, gpio_num);
+		return gpio_num;
+	}
+
+	sc = dm_gpio_get_value(&priv->var_gpios[SC_GPIO_NO]);
+	if (sc < 0) {
+		debug("%s: Error while reading 'sc' GPIO (err = %d)",
+		      dev->name, sc);
+		return sc;
+	}
+
+	con = dm_gpio_get_value(&priv->var_gpios[CON_GPIO_NO]);
+	if (con < 0) {
+		debug("%s: Error while reading 'con' GPIO (err = %d)",
+		      dev->name, con);
+		return con;
+	}
+
+	if ((sc && mc2) || (sc && mc4) || (!sc && !mc2 && !mc4)) {
+		debug("%s: Board hardware configuration inconsistent.\n",
+		      dev->name);
+		return -EINVAL;
+	}
+
+	priv->variant = con ? VAR_CON : VAR_CPU;
+
+	priv->multichannel = mc4 ? 4 : (mc2 ? 2 : (sc ? 1 : 0));
+
+	return 0;
+}
+
+/**
+ * _read_hwversion() - Read the hardware version from the board.
+ * @dev: The board device for which to read the hardware version.
+ *
+ * The hardware version read from the board (from hard-wired GPIOs) is stored
+ * in the private data structure of the driver to be used by other driver
+ * methods.
+ *
+ * Return: 0 if OK, -ve on error.
+ */
+static int _read_hwversion(struct udevice *dev)
+{
+	struct board_gazerbeam_priv *priv = dev_get_priv(dev);
+	int res;
+
+	res = gpio_request_list_by_name(dev, "ver-gpios", priv->ver_gpios,
+					ARRAY_SIZE(priv->ver_gpios),
+					GPIOD_IS_IN);
+	if (res < 0) {
+		debug("%s: Error getting GPIO list 'ver-gpios' (err = %d)\n",
+		      dev->name, res);
+		return -ENODEV;
+	}
+
+	res = dm_gpio_get_values_as_int(priv->ver_gpios,
+					ARRAY_SIZE(priv->ver_gpios));
+	if (res < 0) {
+		debug("%s: Error reading HW version from expander (err = %d)\n",
+		      dev->name, res);
+		return res;
+	}
+
+	priv->hwversion = res;
+
+	res = gpio_free_list(dev, priv->ver_gpios, ARRAY_SIZE(priv->ver_gpios));
+	if (res < 0) {
+		debug("%s: Error freeing HW version GPIO list (err = %d)\n",
+		      dev->name, res);
+		return res;
+	}
+
+	return 0;
+}
+
+static int board_gazerbeam_detect(struct udevice *dev)
+{
+	int res;
+
+	res = _read_board_variant_data(dev);
+	if (res) {
+		debug("%s: Error reading multichannel variant (err = %d)\n",
+		      dev->name, res);
+		return res;
+	}
+
+	res = _read_hwversion(dev);
+	if (res) {
+		debug("%s: Error reading hardware version (err = %d)\n",
+		      dev->name, res);
+		return res;
+	}
+
+	return 0;
+}
+
+static int board_gazerbeam_get_int(struct udevice *dev, int id, int *val)
+{
+	struct board_gazerbeam_priv *priv = dev_get_priv(dev);
+
+	switch (id) {
+	case BOARD_MULTICHANNEL:
+		*val = priv->multichannel;
+		break;
+	case BOARD_VARIANT:
+		*val = priv->variant;
+		break;
+	case BOARD_HWVERSION:
+		*val = priv->hwversion;
+		break;
+	default:
+		debug("%s: Integer value %d unknown\n", dev->name, id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct udevice_id board_gazerbeam_ids[] = {
+	{ .compatible = "gdsys,board_gazerbeam" },
+	{ /* sentinel */ }
+};
+
+static const struct board_ops board_gazerbeam_ops = {
+	.detect = board_gazerbeam_detect,
+	.get_int = board_gazerbeam_get_int,
+};
+
+static int board_gazerbeam_probe(struct udevice *dev)
+{
+	struct board_gazerbeam_priv *priv = dev_get_priv(dev);
+	int gpio_num, i;
+
+	gpio_num = gpio_request_list_by_name(dev, "reset-gpios",
+					     priv->reset_gpios,
+					     ARRAY_SIZE(priv->reset_gpios),
+					     GPIOD_IS_OUT);
+
+	if (gpio_num < 0) {
+		debug("%s: Error getting GPIO list 'reset-gpios' (err = %d)\n",
+		      dev->name, gpio_num);
+		return gpio_num;
+	}
+
+	/* Set startup-finished GPIOs */
+	for (i = 0; i < ARRAY_SIZE(priv->reset_gpios); i++) {
+		int res = dm_gpio_set_value(&priv->reset_gpios[i], 0);
+
+		if (res) {
+			debug("%s: Error while setting GPIO %d (err = %d)\n",
+			      dev->name, i, res);
+			return res;
+		}
+	}
+
+	return 0;
+}
+
+U_BOOT_DRIVER(board_gazerbeam) = {
+	.name           = "board_gazerbeam",
+	.id             = UCLASS_BOARD,
+	.of_match       = board_gazerbeam_ids,
+	.ops		= &board_gazerbeam_ops,
+	.priv_auto_alloc_size = sizeof(struct board_gazerbeam_priv),
+	.probe          = board_gazerbeam_probe,
+};
diff --git a/drivers/board/gazerbeam.h b/drivers/board/gazerbeam.h
new file mode 100644
index 0000000000..0ca003a373
--- /dev/null
+++ b/drivers/board/gazerbeam.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2017
+ * Mario Six,  Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+enum {
+	BOARD_MULTICHANNEL,
+	BOARD_VARIANT,
+	BOARD_HWVERSION,
+};
+
+enum {
+	VAR_CON,
+	VAR_CPU,
+};
--
2.11.0

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

* [U-Boot] [PATCH v3 3/3] test: Add tests for board uclass
  2018-06-27  7:03 [U-Boot] [PATCH v3 1/3] drivers: Add board uclass Mario Six
  2018-06-27  7:03 ` [U-Boot] [PATCH v3 2/3] board: Add gazerbeam driver Mario Six
@ 2018-06-27  7:03 ` Mario Six
  2018-06-27 21:03 ` [U-Boot] [PATCH v3 1/3] drivers: Add " Simon Glass
  2 siblings, 0 replies; 5+ messages in thread
From: Mario Six @ 2018-06-27  7:03 UTC (permalink / raw)
  To: u-boot

Add tests for the new board uclass.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Mario Six <mario.six@gdsys.cc>

---

v2 -> v3:
* Accomodated get_board() rename
* Fixed style violations

v1 -> v2:
New in v2

---
 arch/sandbox/dts/test.dts          |   4 ++
 configs/sandbox64_defconfig        |   2 +
 configs/sandbox_defconfig          |   2 +
 configs/sandbox_flattree_defconfig |   2 +
 configs/sandbox_noblk_defconfig    |   2 +
 configs/sandbox_spl_defconfig      |   2 +
 drivers/board/Kconfig              |   7 ++-
 drivers/board/Makefile             |   1 +
 drivers/board/sandbox.c            | 107 +++++++++++++++++++++++++++++++++++++
 drivers/board/sandbox.h            |  12 +++++
 test/dm/Makefile                   |   1 +
 test/dm/board.c                    |  57 ++++++++++++++++++++
 12 files changed, 198 insertions(+), 1 deletion(-)
 create mode 100644 drivers/board/sandbox.c
 create mode 100644 drivers/board/sandbox.h
 create mode 100644 test/dm/board.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 5752bf547e..692140f0b1 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -563,6 +563,10 @@
 			};
 		};
 	};
+
+	board {
+		compatible = "sandbox,board_sandbox";
+	};
 };

 #include "sandbox_pmic.dtsi"
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 20a2ab3ffb..65993bb33c 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -86,6 +86,8 @@ CONFIG_CPU=y
 CONFIG_DM_DEMO=y
 CONFIG_DM_DEMO_SIMPLE=y
 CONFIG_DM_DEMO_SHAPE=y
+CONFIG_BOARD=y
+CONFIG_BOARD_SANDBOX=y
 CONFIG_PM8916_GPIO=y
 CONFIG_SANDBOX_GPIO=y
 CONFIG_DM_I2C_COMPAT=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 2fc84a16c9..dc048cd48c 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -86,6 +86,8 @@ CONFIG_CPU=y
 CONFIG_DM_DEMO=y
 CONFIG_DM_DEMO_SIMPLE=y
 CONFIG_DM_DEMO_SHAPE=y
+CONFIG_BOARD=y
+CONFIG_BOARD_SANDBOX=y
 CONFIG_PM8916_GPIO=y
 CONFIG_SANDBOX_GPIO=y
 CONFIG_DM_I2C_COMPAT=y
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index e922c4b38f..10b9967b94 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -69,6 +69,8 @@ CONFIG_CPU=y
 CONFIG_DM_DEMO=y
 CONFIG_DM_DEMO_SIMPLE=y
 CONFIG_DM_DEMO_SHAPE=y
+CONFIG_BOARD=y
+CONFIG_BOARD_SANDBOX=y
 CONFIG_PM8916_GPIO=y
 CONFIG_SANDBOX_GPIO=y
 CONFIG_DM_I2C_COMPAT=y
diff --git a/configs/sandbox_noblk_defconfig b/configs/sandbox_noblk_defconfig
index 8bdd4edcda..5e8a448547 100644
--- a/configs/sandbox_noblk_defconfig
+++ b/configs/sandbox_noblk_defconfig
@@ -76,6 +76,8 @@ CONFIG_CPU=y
 CONFIG_DM_DEMO=y
 CONFIG_DM_DEMO_SIMPLE=y
 CONFIG_DM_DEMO_SHAPE=y
+CONFIG_BOARD=y
+CONFIG_BOARD_SANDBOX=y
 CONFIG_PM8916_GPIO=y
 CONFIG_SANDBOX_GPIO=y
 CONFIG_DM_I2C_COMPAT=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index fb6bb4baa2..aadff7943f 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -90,6 +90,8 @@ CONFIG_CPU=y
 CONFIG_DM_DEMO=y
 CONFIG_DM_DEMO_SIMPLE=y
 CONFIG_DM_DEMO_SHAPE=y
+CONFIG_BOARD=y
+CONFIG_BOARD_SANDBOX=y
 CONFIG_PM8916_GPIO=y
 CONFIG_SANDBOX_GPIO=y
 CONFIG_DM_I2C_COMPAT=y
diff --git a/drivers/board/Kconfig b/drivers/board/Kconfig
index cc1cf27205..2a3fc9c049 100644
--- a/drivers/board/Kconfig
+++ b/drivers/board/Kconfig
@@ -10,8 +10,13 @@ if BOARD


 config BOARD_GAZERBEAM
-	bool "Enable device information for the Gazerbeam board"
+	bool "Enable board driver for the Gazerbeam board"
 	help
 	  Support querying device information for the gdsys Gazerbeam board.

+config BOARD_SANDBOX
+	bool "Enable board driver for the Sandbox board"
+	help
+	  Support querying device information for the Sandbox boards.
+
 endif
diff --git a/drivers/board/Makefile b/drivers/board/Makefile
index 12dd2030cf..22243380af 100644
--- a/drivers/board/Makefile
+++ b/drivers/board/Makefile
@@ -4,3 +4,4 @@
 # Mario Six,  Guntermann & Drunck GmbH, mario.six at gdsys.cc
 obj-$(CONFIG_BOARD) += board-uclass.o
 obj-$(CONFIG_BOARD_GAZERBEAM) += gazerbeam.o
+obj-$(CONFIG_BOARD_SANDBOX) += sandbox.o
diff --git a/drivers/board/sandbox.c b/drivers/board/sandbox.c
new file mode 100644
index 0000000000..50621e47a4
--- /dev/null
+++ b/drivers/board/sandbox.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <board.h>
+
+#include "sandbox.h"
+
+struct board_sandbox_priv {
+	bool called_detect;
+	int test_i1;
+	int test_i2;
+};
+
+char vacation_spots[][64] = {"R'lyeh", "Dreamlands", "Plateau of Leng",
+			     "Carcosa", "Yuggoth", "The Nameless City"};
+
+int board_sandbox_detect(struct udevice *dev)
+{
+	struct board_sandbox_priv *priv = dev_get_priv(dev);
+
+	priv->called_detect = true;
+	priv->test_i2 = 100;
+
+	return 0;
+}
+
+int board_sandbox_get_bool(struct udevice *dev, int id, bool *val)
+{
+	struct board_sandbox_priv *priv = dev_get_priv(dev);
+
+	switch (id) {
+	case BOOL_CALLED_DETECT:
+		/* Checks if the dectect method has been called */
+		*val = priv->called_detect;
+		return 0;
+	}
+
+	return -ENOENT;
+}
+
+int board_sandbox_get_int(struct udevice *dev, int id, int *val)
+{
+	struct board_sandbox_priv *priv = dev_get_priv(dev);
+
+	switch (id) {
+	case INT_TEST1:
+		*val = priv->test_i1;
+		/* Increments with every call */
+		priv->test_i1++;
+		return 0;
+	case INT_TEST2:
+		*val = priv->test_i2;
+		/* Decrements with every call */
+		priv->test_i2--;
+		return 0;
+	}
+
+	return -ENOENT;
+}
+
+int board_sandbox_get_str(struct udevice *dev, int id, size_t size, char *val)
+{
+	struct board_sandbox_priv *priv = dev_get_priv(dev);
+	int i1 = priv->test_i1;
+	int i2 = priv->test_i2;
+	int index = (i1 * i2) % ARRAY_SIZE(vacation_spots);
+
+	switch (id) {
+	case STR_VACATIONSPOT:
+		/* Picks a vacation spot depending on i1 and i2 */
+		snprintf(val, size, vacation_spots[index]);
+		return 0;
+	}
+
+	return -ENOENT;
+}
+
+static const struct udevice_id board_sandbox_ids[] = {
+	{ .compatible = "sandbox,board_sandbox" },
+	{ /* sentinel */ }
+};
+
+static const struct board_ops board_sandbox_ops = {
+	.detect = board_sandbox_detect,
+	.get_bool = board_sandbox_get_bool,
+	.get_int = board_sandbox_get_int,
+	.get_str = board_sandbox_get_str,
+};
+
+int board_sandbox_probe(struct udevice *dev)
+{
+	return 0;
+}
+
+U_BOOT_DRIVER(board_sandbox) = {
+	.name           = "board_sandbox",
+	.id             = UCLASS_BOARD,
+	.of_match       = board_sandbox_ids,
+	.ops		= &board_sandbox_ops,
+	.priv_auto_alloc_size = sizeof(struct board_sandbox_priv),
+	.probe          = board_sandbox_probe,
+};
diff --git a/drivers/board/sandbox.h b/drivers/board/sandbox.h
new file mode 100644
index 0000000000..2cff494f56
--- /dev/null
+++ b/drivers/board/sandbox.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018
+ * Mario Six,  Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ */
+
+enum {
+	BOOL_CALLED_DETECT,
+	INT_TEST1,
+	INT_TEST2,
+	STR_VACATIONSPOT,
+};
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 5511a85700..78203fa797 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_UT_DM) += test-uclass.o
 obj-$(CONFIG_UT_DM) += core.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_BLK) += blk.o
+obj-$(CONFIG_BOARD) += board.o
 obj-$(CONFIG_CLK) += clk.o
 obj-$(CONFIG_DM_ETH) += eth.o
 obj-$(CONFIG_DM_GPIO) += gpio.o
diff --git a/test/dm/board.c b/test/dm/board.c
new file mode 100644
index 0000000000..0f267a1926
--- /dev/null
+++ b/test/dm/board.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <board.h>
+#include <test/ut.h>
+
+#include "../../drivers/board/sandbox.h"
+
+static int dm_test_board(struct unit_test_state *uts)
+{
+	struct udevice *board;
+	bool called_detect;
+	char str[64];
+	int i;
+
+	board_get(&board);
+	ut_assert(board);
+
+	board_get_bool(board, BOOL_CALLED_DETECT, &called_detect);
+	ut_assert(!called_detect);
+
+	board_detect(board);
+
+	board_get_bool(board, BOOL_CALLED_DETECT, &called_detect);
+	ut_assert(called_detect);
+
+	board_get_str(board, STR_VACATIONSPOT, sizeof(str), str);
+	ut_assertok(strcmp(str, "R'lyeh"));
+
+	board_get_int(board, INT_TEST1, &i);
+	ut_asserteq(0, i);
+
+	board_get_int(board, INT_TEST2, &i);
+	ut_asserteq(100, i);
+
+	board_get_str(board, STR_VACATIONSPOT, sizeof(str), str);
+	ut_assertok(strcmp(str, "Carcosa"));
+
+	board_get_int(board, INT_TEST1, &i);
+	ut_asserteq(1, i);
+
+	board_get_int(board, INT_TEST2, &i);
+	ut_asserteq(99, i);
+
+	board_get_str(board, STR_VACATIONSPOT, sizeof(str), str);
+	ut_assertok(strcmp(str, "Yuggoth"));
+
+	return 0;
+}
+
+DM_TEST(dm_test_board, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
--
2.11.0

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

* [U-Boot] [PATCH v3 1/3] drivers: Add board uclass
  2018-06-27  7:03 [U-Boot] [PATCH v3 1/3] drivers: Add board uclass Mario Six
  2018-06-27  7:03 ` [U-Boot] [PATCH v3 2/3] board: Add gazerbeam driver Mario Six
  2018-06-27  7:03 ` [U-Boot] [PATCH v3 3/3] test: Add tests for board uclass Mario Six
@ 2018-06-27 21:03 ` Simon Glass
  2018-07-31  9:38   ` Mario Six
  2 siblings, 1 reply; 5+ messages in thread
From: Simon Glass @ 2018-06-27 21:03 UTC (permalink / raw)
  To: u-boot

Hi Mario,

On 27 June 2018 at 00:03, Mario Six <mario.six@gdsys.cc> wrote:
>
> Since there is no canonical "board device" that can be used in board
> files, it is difficult to use DM function for board initialization in
> these cases.
>
> Hence, add a uclass that implements a simple "board device", which can
> hold devices not suitable anywhere else in the device tree, and is also
> able to read encoded information, e.g. hard-wired GPIOs on a GPIO
> expander, read-only memory ICs, etc. that carry information about the
> hardware.
>
> The devices of this uclass expose methods to read generic data types
> (integers, strings, booleans) to encode the information provided by the
> hardware.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>
> ---
>
> v2 -> v3:
> * Expanded comment on detect()
> * Added error handling in example
> * Renamed get_board() to board_get()
> * Fixed style violations
> * Documented board_get
> * Made comments conform with kernel-doc
> * Fixed SPDC-License-Identifier position
>
> v1 -> v2:
> * Corrected description of dev parameter of devinfo_detect
> * Added size parameter to devinfo_get_str
> * Expanded uclass documentation
> * Added function to get devinfo instance
> * Renamed the uclass from devinfo to board
>
> ---
>  drivers/Kconfig              |   2 +
>  drivers/Makefile             |   1 +
>  drivers/board/Kconfig        |  17 ++++++
>  drivers/board/Makefile       |   6 ++
>  drivers/board/board-uclass.c |  60 +++++++++++++++++++
>  include/board.h              | 139 +++++++++++++++++++++++++++++++++++++++++++
>  include/dm/uclass-id.h       |   1 +
>  7 files changed, 226 insertions(+)
>  create mode 100644 drivers/board/Kconfig
>  create mode 100644 drivers/board/Makefile
>  create mode 100644 drivers/board/board-uclass.c
>  create mode 100644 include/board.h

Reviewed-by: Simon Glass <sjg@chromium.org>

But please see below.

>
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index 9e21b28750..48f7302506 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -22,6 +22,8 @@ source "drivers/ddr/Kconfig"
>
>  source "drivers/demo/Kconfig"
>
> +source "drivers/board/Kconfig"
> +
>  source "drivers/ddr/fsl/Kconfig"
>
>  source "drivers/dfu/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index a213ea9671..c2a363a66f 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -68,6 +68,7 @@ obj-y += ata/
>  obj-$(CONFIG_DM_DEMO) += demo/
>  obj-$(CONFIG_BIOSEMU) += bios_emulator/
>  obj-y += block/
> +obj-y += board/
>  obj-$(CONFIG_BOOTCOUNT_LIMIT) += bootcount/
>  obj-$(CONFIG_CPU) += cpu/
>  obj-y += crypto/
> diff --git a/drivers/board/Kconfig b/drivers/board/Kconfig
> new file mode 100644
> index 0000000000..cc1cf27205
> --- /dev/null
> +++ b/drivers/board/Kconfig
> @@ -0,0 +1,17 @@
> +menuconfig BOARD
> +       bool "Device Information"
> +       help
> +         Support methods to query hardware configurations from internal
> +         mechanisms (e.g. reading GPIO values, determining the presence of
> +         devices on busses, etc.). This enables the usage of U-Boot with
> +         modular board architectures.
> +
> +if BOARD
> +
> +
> +config BOARD_GAZERBEAM
> +       bool "Enable device information for the Gazerbeam board"
> +       help
> +         Support querying device information for the gdsys Gazerbeam board.
> +

This should go in your board-specific patch, not the uclass.
[..]

Regards,
Simon

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

* [U-Boot] [PATCH v3 1/3] drivers: Add board uclass
  2018-06-27 21:03 ` [U-Boot] [PATCH v3 1/3] drivers: Add " Simon Glass
@ 2018-07-31  9:38   ` Mario Six
  0 siblings, 0 replies; 5+ messages in thread
From: Mario Six @ 2018-07-31  9:38 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Wed, Jun 27, 2018 at 11:03 PM, Simon Glass <sjg@chromium.org> wrote:
> Hi Mario,
>
> On 27 June 2018 at 00:03, Mario Six <mario.six@gdsys.cc> wrote:
>>
>> Since there is no canonical "board device" that can be used in board
>> files, it is difficult to use DM function for board initialization in
>> these cases.
>>
>> Hence, add a uclass that implements a simple "board device", which can
>> hold devices not suitable anywhere else in the device tree, and is also
>> able to read encoded information, e.g. hard-wired GPIOs on a GPIO
>> expander, read-only memory ICs, etc. that carry information about the
>> hardware.
>>
>> The devices of this uclass expose methods to read generic data types
>> (integers, strings, booleans) to encode the information provided by the
>> hardware.
>>
>> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>>
>> ---
>>
>> v2 -> v3:
>> * Expanded comment on detect()
>> * Added error handling in example
>> * Renamed get_board() to board_get()
>> * Fixed style violations
>> * Documented board_get
>> * Made comments conform with kernel-doc
>> * Fixed SPDC-License-Identifier position
>>
>> v1 -> v2:
>> * Corrected description of dev parameter of devinfo_detect
>> * Added size parameter to devinfo_get_str
>> * Expanded uclass documentation
>> * Added function to get devinfo instance
>> * Renamed the uclass from devinfo to board
>>
>> ---
>>  drivers/Kconfig              |   2 +
>>  drivers/Makefile             |   1 +
>>  drivers/board/Kconfig        |  17 ++++++
>>  drivers/board/Makefile       |   6 ++
>>  drivers/board/board-uclass.c |  60 +++++++++++++++++++
>>  include/board.h              | 139 +++++++++++++++++++++++++++++++++++++++++++
>>  include/dm/uclass-id.h       |   1 +
>>  7 files changed, 226 insertions(+)
>>  create mode 100644 drivers/board/Kconfig
>>  create mode 100644 drivers/board/Makefile
>>  create mode 100644 drivers/board/board-uclass.c
>>  create mode 100644 include/board.h
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> But please see below.
>
>>
>> diff --git a/drivers/Kconfig b/drivers/Kconfig
>> index 9e21b28750..48f7302506 100644
>> --- a/drivers/Kconfig
>> +++ b/drivers/Kconfig
>> @@ -22,6 +22,8 @@ source "drivers/ddr/Kconfig"
>>
>>  source "drivers/demo/Kconfig"
>>
>> +source "drivers/board/Kconfig"
>> +
>>  source "drivers/ddr/fsl/Kconfig"
>>
>>  source "drivers/dfu/Kconfig"
>> diff --git a/drivers/Makefile b/drivers/Makefile
>> index a213ea9671..c2a363a66f 100644
>> --- a/drivers/Makefile
>> +++ b/drivers/Makefile
>> @@ -68,6 +68,7 @@ obj-y += ata/
>>  obj-$(CONFIG_DM_DEMO) += demo/
>>  obj-$(CONFIG_BIOSEMU) += bios_emulator/
>>  obj-y += block/
>> +obj-y += board/
>>  obj-$(CONFIG_BOOTCOUNT_LIMIT) += bootcount/
>>  obj-$(CONFIG_CPU) += cpu/
>>  obj-y += crypto/
>> diff --git a/drivers/board/Kconfig b/drivers/board/Kconfig
>> new file mode 100644
>> index 0000000000..cc1cf27205
>> --- /dev/null
>> +++ b/drivers/board/Kconfig
>> @@ -0,0 +1,17 @@
>> +menuconfig BOARD
>> +       bool "Device Information"
>> +       help
>> +         Support methods to query hardware configurations from internal
>> +         mechanisms (e.g. reading GPIO values, determining the presence of
>> +         devices on busses, etc.). This enables the usage of U-Boot with
>> +         modular board architectures.
>> +
>> +if BOARD
>> +
>> +
>> +config BOARD_GAZERBEAM
>> +       bool "Enable device information for the Gazerbeam board"
>> +       help
>> +         Support querying device information for the gdsys Gazerbeam board.
>> +
>
> This should go in your board-specific patch, not the uclass.
> [..]
>

Indeed, that should be in the other patch.

Will be fixed in v4.

> Regards,
> Simon

Best regards,
Mario

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

end of thread, other threads:[~2018-07-31  9:38 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-27  7:03 [U-Boot] [PATCH v3 1/3] drivers: Add board uclass Mario Six
2018-06-27  7:03 ` [U-Boot] [PATCH v3 2/3] board: Add gazerbeam driver Mario Six
2018-06-27  7:03 ` [U-Boot] [PATCH v3 3/3] test: Add tests for board uclass Mario Six
2018-06-27 21:03 ` [U-Boot] [PATCH v3 1/3] drivers: Add " Simon Glass
2018-07-31  9:38   ` Mario Six

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.