Skip to contentSkip to conversation

RFC: Mezzanine handling for 96boards

PATCH New Linus Walleij 11 participants 37 messages Jun 18, 2018 – Jul 16, 2018

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover RFC: Mezzanine handling for 96boards

This is a proposal for how to handle the non-discoverable 96boards plug-in expansion boards called "mezzanines" in the Linux kernel. It is a working RFC series meant for discussion at the moment.

The RFC was done on the brand new Ultra96 board from Xilinx with a Secure96 mezzanine expansion board. The main part is in patch 4, the rest is enabling and examples.

The code can be obtained from here:
https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git/log/?h=ultra96

You can for example probably augment the DTS file for any upstream-supported 96board and get the Secure96 going with it with minor efforts.

TODO:

- Proper device tree bindings for the connector, for now look at the example.

- Discuss whether to actually do this or just take it all and flush it down the drain because the community doesn't like it. I'm not one of those especially infatuated with my own code, I always stay by the old programming project management mantra to calculate to make one version and throw it away as stepping stone to a good final design.

- Placement: putting this in drivers/bus is just an example. drivers/platform/96boards-mezzanines is fine too, maybe better?

- I am especially curious about input from Andy and Mika from the Intel/ACPI camp on what they have seen for non-discoverable plug-in boards. Does this problem even exist in the Intel world, or not...

Background:

- These boards connect on a custom connector on this family of boards. The relationship is many-to-many with the connector as nexus. The electronic standard for the connector is specified:
https://github.com/96boards/documentation/blob/master/Specifications/96Boards-CE-Specification.pdf
Example mezzanines:
https://www.96boards.org/documentation/mezzanine/

- These boards have siblings on other platforms, the problem scope is similar with BeagleBone "capes":
https://beagleboard.org/capes
Raspberry Pi expansion boards:
https://www.abelectronics.co.uk/products/18/raspberry-pi-expansion-boards
Intel Edison, Galileo, Joule also have expansion boards.

Idea: add a driver for the connector itself and tie it in to the device tree with a compatible string. Since the boards are non-discoverable two mechanisms are provided to discover them:

- Add a very simple device tree node with just a compatible string for the board in the node. This will be simple to add from e.g. a boot loader or as an overlay from userspace.

  board {
        compatible = "96boards,secure96";
  };

- Echo 1 > boardname into a sysfs file to populate the board and echo 0 > boardname to depopulate it. This makes it easy to even switch out expansion boards at runtime, if allowed by the electronics.

Quoted 2 lines

cd /sys/devices/platform/connector
echo 1 > secure96

lscon connector: called mezzanine_store on secure96 lscon connector: populate secure96
at24 1-0050: 2048 byte 24c128 EEPROM, writable, 128 bytes/write atmel-ecc 1-0060: configuration zone is unlocked tpm_tis_spi spi0.0: 2.0 TPM (device-id 0x1B, rev-id 16) (...)

What this patch set does not do:

- It does not use device tree or ACPI DSDT or any other hardware decription language to model the contents of the board per se. Instead the boards buses are populated directly with platform devices.

Predictable complaints about this design:

Q: This is not device tree overlays. Why is it not device
tree overlays?

A1: Right tool for the job, overlays are complex and the
plan to get it in place seems to be spanning years, this is a few devices on simple busses and it works today. Using this approach I can already work on shaping up drivers for the mezzanine board devices as proved by:
https://marc.info/?l=linux-crypto-vger&m=152820660120590&w=2
https://marc.info/?l=linux-crypto-vger&m=152820662820595&w=2
(...)

I can work on drivers for the chips on the Secure96 mezzanine board. It's just an example of what the mezzanine community can do.
Now they are hacking around in userspace instead of doing/reusing kernel drivers for their stuff:
https://github.com/jbech-linaro/secure96

This way we can bring developers for these components into the kernel community instead of telling them to wait for some big infrastructure that comes later before they can contribute their stuff.

A2: Overlays does not solve the problem if the system runs
ACPI, and what about if the same connector[s] appear on a server board, servers use ACPI. Also notice that Intel have development boards with non-discoverable expansion boards as well. They just will not use device tree.

A3: Overlays is Big Upfront Design.
https://en.wikipedia.org/wiki/Big_Design_Up_Front
This way of designing things is associated with the (pejorative term) "waterfall model" which is out of fashion as a way of doing development. I think I am not the only one slightly annoyed by the fact that device tree overlays is now starting to look like a very big very upfront design. It's just not possible to get something up and running in small iterative steps with device tree overlays. Instead huge efforts are required and it involves major possible showstoppers and uncertain outcome as indicated by Frank's TODO:
https://elinux.org/Frank's_Evolving_Overlay_Thoughts

This appears also in our work process documents:
Documentation/process/4.Coding.rst
"experience has shown that excessive or premature
abstraction can be just as harmful as premature optimization. Abstraction should be used to the level required and no further."

So for that reason, or other predictable statements such as "you're reinventing board files", I'd like to have an open discussion on how to actually support these boards with the mainline kernel and work on device drivers common with other systems now, and not in 2020 when they are already obsolete.

Yeah it is a bit controversial, but what we are doing right now for non-discoverable expansion boards isn't working in my opinion, so I have to throw something out there, and this is it.

Linus Walleij (5):
RFC: gpio: Add API to explicitly name a consumer
RFC: eeprom: at24: Allow passing gpiodesc from pdata
RFC: spi: Make of_find_spi_device_by_node() available
RFC: bus: 96boards Low-Speed Connector
RFC: ARM64: dts: Add Low-Speed Connector to ZCU100

 .../boot/dts/xilinx/zynqmp-zcu100-revC.dts    |  27 +-
 .../96boards-ls-connector.c                   | 307 ++++++++++++++++++
 .../96boards-mezzanines/96boards-mezzanines.h |  46 +++
 .../96boards-mezzanines/96boards-secure96.c   | 249 ++++++++++++++
 drivers/bus/96boards-mezzanines/Kconfig       |  36 ++
 drivers/bus/96boards-mezzanines/Makefile      |   6 +
 drivers/bus/Kconfig                           |   2 +
 drivers/bus/Makefile                          |   4 +-
 drivers/gpio/gpiolib.c                        |  13 +
 drivers/misc/eeprom/at24.c                    |   6 +-
 drivers/spi/spi.c                             |  33 +-
 include/linux/gpio/consumer.h                 |   7 +
 include/linux/platform_data/at24.h            |   2 +
 include/linux/spi/spi.h                       |   4 +
 14 files changed, 723 insertions(+), 19 deletions(-)
 create mode 100644 drivers/bus/96boards-mezzanines/96boards-ls-connector.c
 create mode 100644 drivers/bus/96boards-mezzanines/96boards-mezzanines.h
 create mode 100644 drivers/bus/96boards-mezzanines/96boards-secure96.c
 create mode 100644 drivers/bus/96boards-mezzanines/Kconfig
 create mode 100644 drivers/bus/96boards-mezzanines/Makefile
Signature · 1 line
2.17.0
#1 lore raw

PATCH 1/5 RFC: gpio: Add API to explicitly name a consumer

The GPIO (descriptor) API registers a "label" naming what is currently using the GPIO line. Typically this is taken from things like the device tree node, so "reset-gpios" will result in he line being labeled "reset".

The technical effect is pretty much zero: the use is for debug and introspection, such as "lsgpio" and debugfs files.

However sometimes the user want this cuddly feeling of listing all GPIO lines and seeing exactly what they are for and it gives a very fulfilling sense of control. Especially in the cases when the device tree node doesn't provide a good name, or anonymous GPIO lines assigned just to "gpios" in the device tree because the usage is implicit.

For these cases it may be nice to be able to label the line directly and explicitly.

---
 drivers/gpio/gpiolib.c        | 13 +++++++++++++
 include/linux/gpio/consumer.h |  7 +++++++
 2 files changed, 20 insertions(+)
drivers/gpio/gpiolib.c +13 -0
index e11a3bb03820..c6f77e806cb8 100644
@@ -3193,6 +3193,19 @@ int gpiod_cansleep(const struct gpio_desc *desc)
 }
 EXPORT_SYMBOL_GPL(gpiod_cansleep);
 
+/**
+ * gpiod_set_consumer_name() - set the consumer name for the descriptor
+ * @desc: gpio to set the consumer name on
+ * @name: the new consumer name
+ */
+void gpiod_set_consumer_name(struct gpio_desc *desc, const char *name)
+{
+	VALIDATE_DESC_VOID(desc);
+	/* Just overwrite whatever the previous name was */
+	desc->label = name;
+}
+EXPORT_SYMBOL_GPL(gpiod_set_consumer_name);
+
 /**
  * gpiod_to_irq() - return the IRQ corresponding to a GPIO
  * @desc: gpio whose IRQ will be returned (already requested)
include/linux/gpio/consumer.h +7 -0
index 243112c7fa7d..e8aaf34dd65d 100644
@@ -145,6 +145,7 @@ int gpiod_is_active_low(const struct gpio_desc *desc);
 int gpiod_cansleep(const struct gpio_desc *desc);
 
 int gpiod_to_irq(const struct gpio_desc *desc);
+void gpiod_set_consumer_name(struct gpio_desc *desc, const char *name);
 
 /* Convert between the old gpio_ and new gpiod_ interfaces */
 struct gpio_desc *gpio_to_desc(unsigned gpio);
@@ -467,6 +468,12 @@ static inline int gpiod_to_irq(const struct gpio_desc *desc)
 	return -EINVAL;
 }
 
+static inline void gpiod_set_consumer_name(struct gpio_desc *desc, const char *name)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+}
+
 static inline struct gpio_desc *gpio_to_desc(unsigned gpio)
 {
 	return ERR_PTR(-EINVAL);
Signature · 1 line
2.17.0
#2 lore raw

PATCH 2/5 RFC: eeprom: at24: Allow passing gpiodesc from pdata

In reply to Linus Walleij

This makes it possible to pass an initialized GPIO descriptor to the driver through platform data.

This is useful when we are dealing with EEPROMs on expansion boards where the GPIO has to be looked up indirectly using a connector abstraction (several systems using the same connector) so the machine descriptor tables cannot be used to associate the descriptor with the device and we then want to pass this descriptor on to the EEPROM driver this way instead.

---
 drivers/misc/eeprom/at24.c         | 6 +++++-
 include/linux/platform_data/at24.h | 2 ++
 2 files changed, 7 insertions(+), 1 deletion(-)
drivers/misc/eeprom/at24.c +5 -1
index f5cc517d1131..d577cdbe221e 100644
@@ -662,7 +662,11 @@ static int at24_probe(struct i2c_client *client)
 	at24->client[0].client = client;
 	at24->client[0].regmap = regmap;
 
-	at24->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_HIGH);
+	if (pdata.wp_gpiod)
+		at24->wp_gpio = pdata.wp_gpiod;
+	else
+		at24->wp_gpio =
+			devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_HIGH);
 	if (IS_ERR(at24->wp_gpio))
 		return PTR_ERR(at24->wp_gpio);
 
include/linux/platform_data/at24.h +2 -0
index 63507ff464ee..5606fb2ef76c 100644
@@ -11,6 +11,7 @@
 #include <linux/types.h>
 #include <linux/nvmem-consumer.h>
 #include <linux/bitops.h>
+#include <linux/gpio/consumer.h>
 
 /**
  * struct at24_platform_data - data to set up at24 (generic eeprom) driver
@@ -55,6 +56,7 @@ struct at24_platform_data {
 
 	void		(*setup)(struct nvmem_device *nvmem, void *context);
 	void		*context;
+	struct gpio_desc *wp_gpiod;
 };
 
 #endif /* _LINUX_AT24_H */
Signature · 1 line
2.17.0
#3 lore raw

PATCH 2/5 RFC: eeprom: at24: Allow passing gpiodesc from pdata

Quoted 10 lines · Linus Walleij

This makes it possible to pass an initialized GPIO descriptor to the driver through platform data.

This is useful when we are dealing with EEPROMs on expansion boards where the GPIO has to be looked up indirectly using a connector abstraction (several systems using the same connector) so the machine descriptor tables cannot be used to associate the descriptor with the device and we then want to pass this descriptor on to the EEPROM driver this way instead.

How this descriptor is supposed to be created?
Whenever we probe the device we might add properties to it (consider how MFD does instansiate them), I guess same way GPIO lookup tables work. No?

P.S. I really would like to hear a _strong_ argument why it can't be done using other means like built-in device properties or GPIO lookup tables (which on my opinion have to work in the similar way at run time).

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#4 lore raw

PATCH 3/5 RFC: spi: Make of_find_spi_device_by_node() available

In reply to Linus Walleij

This externalizes and exports the symbol of_find_spi_device_by_node() from the SPI core akin to how of_find_i2c_adapter_by_node() is already available. As we will need this also for non-dynamic OF setups, we move it under a CONFIG_OF check.

---
 drivers/spi/spi.c       | 33 ++++++++++++++++++---------------
 include/linux/spi/spi.h |  4 ++++
 2 files changed, 22 insertions(+), 15 deletions(-)
drivers/spi/spi.c +18 -15
index ec395a6baf9c..6a1085077317 100644
@@ -3314,27 +3314,14 @@ EXPORT_SYMBOL_GPL(spi_write_then_read);
 
 /*-------------------------------------------------------------------------*/
 
-#if IS_ENABLED(CONFIG_OF_DYNAMIC)
-static int __spi_of_device_match(struct device *dev, void *data)
-{
-	return dev->of_node == data;
-}
-
-/* must call put_device() when done with returned spi_device device */
-static struct spi_device *of_find_spi_device_by_node(struct device_node *node)
-{
-	struct device *dev = bus_find_device(&spi_bus_type, NULL, node,
-						__spi_of_device_match);
-	return dev ? to_spi_device(dev) : NULL;
-}
-
+#if IS_ENABLED(CONFIG_OF)
 static int __spi_of_controller_match(struct device *dev, const void *data)
 {
 	return dev->of_node == data;
 }
 
 /* the spi controllers are not using spi_bus, so we find it with another way */
-static struct spi_controller *of_find_spi_controller_by_node(struct device_node *node)
+struct spi_controller *of_find_spi_controller_by_node(struct device_node *node)
 {
 	struct device *dev;
 
@@ -3349,6 +3336,22 @@ static struct spi_controller *of_find_spi_controller_by_node(struct device_node
 	/* reference got in class_find_device */
 	return container_of(dev, struct spi_controller, dev);
 }
+EXPORT_SYMBOL_GPL(of_find_spi_controller_by_node);
+#endif
+
+#if IS_ENABLED(CONFIG_OF_DYNAMIC)
+static int __spi_of_device_match(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+/* must call put_device() when done with returned spi_device device */
+static struct spi_device *of_find_spi_device_by_node(struct device_node *node)
+{
+	struct device *dev = bus_find_device(&spi_bus_type, NULL, node,
+						__spi_of_device_match);
+	return dev ? to_spi_device(dev) : NULL;
+}
 
 static int of_spi_notify(struct notifier_block *nb, unsigned long action,
 			 void *arg)
include/linux/spi/spi.h +4 -0
index a64235e05321..c2be93224bd1 100644
@@ -639,6 +639,10 @@ extern int devm_spi_register_controller(struct device *dev,
 					struct spi_controller *ctlr);
 extern void spi_unregister_controller(struct spi_controller *ctlr);
 
+#if IS_ENABLED(CONFIG_OF)
+struct spi_controller *of_find_spi_controller_by_node(struct device_node *node);
+#endif
+
 extern struct spi_controller *spi_busnum_to_master(u16 busnum);
 
 /*
Signature · 1 line
2.17.0
#5 lore raw

PATCH 4/5 RFC: bus: 96boards Low-Speed Connector

In reply to Linus Walleij

This illustrates my idea for using a small connector driver to plug in "mezzanine boards" on the 96boards low-speed connector.

These "mezzanine boards" are no different than "capes", "logic modules", etc. This thing, a non-discoverable connector where a user can plug in a few peripherals has been reinvented a few times.

As a proof-of-concept we add the Secure96, a quite minimal mezzanine board.

Users can register their boards in a simple way. Either just add their compatible-string in the device tree:

board {
        compatible = "96boards,secure96";
};

And if they can't even change three lines in their device tree, or if they at runtime decide to plug in some board and test it, they can use sysfs, as exemplified by plugging in the secure96 security board at runtime:

Quoted 2 lines

cd /sys/devices/platform/connector
echo 1 > secure96

[   61.014629] lscon connector: called mezzanine_store on secure96
[   61.020530] lscon connector: populate secure96
[   61.027081] at24 1-0050: 2048 byte 24c128 EEPROM, writable, 128 bytes/write
[   61.053569] atmel-ecc 1-0060: configuration zone is unlocked
[   61.502535] tpm_tis_spi spi0.0: 2.0 TPM (device-id 0x1B, rev-id 16)

(...)

The plug-in board can be removed from sysfs and added back again multiple times like this with the devices being runtime added and removed by two writes to sysfs.

Quoted 3 lines

echo 0 > secure96
echo 1 > secure96
echo 0 > secure96

(...)

I certainly see some scalability problems with this particular code for example, but the fact is: it pretty much works. The devices need hooks in I2C and SPI, and need to be able to accept initialized GPIO descriptors passed in as platform data.

Any discussions related to the concept compared to doing device tree overlays/fragments etc: please discuss in patch 0 (the cover letter).

---
 .../96boards-ls-connector.c                   | 307 ++++++++++++++++++
 .../96boards-mezzanines/96boards-mezzanines.h |  46 +++
 .../96boards-mezzanines/96boards-secure96.c   | 249 ++++++++++++++
 drivers/bus/96boards-mezzanines/Kconfig       |  36 ++
 drivers/bus/96boards-mezzanines/Makefile      |   6 +
 drivers/bus/Kconfig                           |   2 +
 drivers/bus/Makefile                          |   4 +-
 7 files changed, 649 insertions(+), 1 deletion(-)
 create mode 100644 drivers/bus/96boards-mezzanines/96boards-ls-connector.c
 create mode 100644 drivers/bus/96boards-mezzanines/96boards-mezzanines.h
 create mode 100644 drivers/bus/96boards-mezzanines/96boards-secure96.c
 create mode 100644 drivers/bus/96boards-mezzanines/Kconfig
 create mode 100644 drivers/bus/96boards-mezzanines/Makefile
drivers/bus/96boards-mezzanines/96boards-ls-connector.c new file +307 -0
new file mode 100644
index 000000000000..1a012b0cd457
@@ -0,0 +1,307 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * 96boards Low-speed Connector driver
+ * (C) 2018 Linus Walleij <[email protected]>
+ */
+
+#include <linux/init.h>
+#include <linux/sysfs.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include "96boards-mezzanines.h"
+
+/**
+ * struct mezzanine - daughter boards (mezzanines) data
+ * Having dynamic data here means that we can only plug ONE board
+ * of each type. Stacking two different boards is fine. This
+ * should be fixed using a linked list of mezzanines if we
+ * go for this solution.
+ */
+struct mezzanine {
+	const char *compatible;
+	const char *sysfs_name;
+	struct dev_ext_attribute ext_attr;
+	void * (*populate) (struct lscon *ls);
+	void (*depopulate) (void *data);
+	void *data;
+};
+
+static struct mezzanine mezzanines[] = {
+#if IS_ENABLED(96BOARDS_SECURE96)
+	{
+		.compatible = "96boards,secure96",
+		.sysfs_name = "secure96",
+		.populate = secure96_populate,
+		.depopulate = secure96_depopulate,
+	},
+#endif
+	/* Add any other mezzanines here */
+};
+
+struct gpio_desc *mezzanine_ls_get_gpiod(struct lscon *ls,
+					 enum mezzanine_ls_gpio pin,
+					 const char *consumer_name,
+					 enum gpiod_flags flags)
+{
+	struct gpio_desc *retdesc;
+
+	/*
+	 * TODO: get all the LS GPIOs as an array on probe() then
+	 * the consumers can skip error handling of IS_ERR() descriptors
+	 * and this need only set the consumer name.
+	 */
+	retdesc = devm_gpiod_get_index(ls->dev, NULL, pin, flags);
+	if (!IS_ERR(retdesc) && consumer_name)
+		gpiod_set_consumer_name(retdesc, consumer_name);
+
+	return retdesc;
+}
+EXPORT_SYMBOL_GPL(mezzanine_ls_get_gpiod);
+
+/*
+ * Mezzanine boards will call this to orderly remove their claimed
+ * gpio descriptors, since we acquired them all with devm_gpiod_get()
+ * they will eventually be released once this connector device
+ * disappears if the board do not release them in order.
+ */
+void mezzanine_ls_put_gpiod(struct lscon *ls, struct gpio_desc *gpiod)
+{
+	devm_gpiod_put(ls->dev, gpiod);
+}
+EXPORT_SYMBOL_GPL(mezzanine_ls_put_gpiod);
+
+static ssize_t mezzanine_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	struct lscon *ls = dev_get_drvdata(dev);
+	struct dev_ext_attribute *d = container_of(attr,
+						   struct dev_ext_attribute,
+						   attr);
+	struct mezzanine *mez = d->var;
+
+	dev_info(ls->dev, "called %s on %s\n", __func__, mez->sysfs_name);
+	return 0;
+}
+
+static ssize_t mezzanine_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct lscon *ls = dev_get_drvdata(dev);
+	struct dev_ext_attribute *d = container_of(attr,
+						   struct dev_ext_attribute,
+						   attr);
+	struct mezzanine *mez = d->var;
+	unsigned long state;
+	int ret;
+
+	dev_info(ls->dev, "called %s on %s\n", __func__, mez->sysfs_name);
+
+	ret = kstrtoul(buf, 0, &state);
+	if (ret)
+		return ret;
+
+	if (state == 1) {
+		void *data;
+
+		/* Already populated */
+		if (mez->data)
+			return count;
+
+		data = mez->populate(ls);
+		if (IS_ERR(data))
+			return PTR_ERR(data);
+		mez->data = data;
+		return count;
+	}
+
+	if (state == 0) {
+		/* Not populated so nothing to do here */
+		if (!mez->data)
+			return count;
+		mez->depopulate(mez->data);
+		mez->data = NULL;
+		return count;
+	}
+
+	return -EINVAL;
+}
+
+/**
+ * This adds one sysfs file per mezzanine board that we support, so they
+ * can be probed and added from userspace.
+ */
+static int lscon_add_sysfs_mezzanines(struct lscon *ls)
+{
+	struct mezzanine *mez;
+	struct dev_ext_attribute *ext_attr;
+	int ret;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mezzanines); i++) {
+		mez = &mezzanines[i];
+		ext_attr = &mez->ext_attr;
+
+		ext_attr->var = mez;
+		ext_attr->attr.attr.name = mez->sysfs_name;
+		ext_attr->attr.attr.mode = VERIFY_OCTAL_PERMISSIONS(0644);
+		ext_attr->attr.show = mezzanine_show;
+		ext_attr->attr.store = mezzanine_store;
+		ret = device_create_file(ls->dev, &ext_attr->attr);
+		if (ret)
+			dev_err(ls->dev, "unable to create sysfs entries\n");
+
+	}
+
+	return 0;
+}
+
+static int lscon_probe_of_mezzanine(struct lscon *ls, struct device_node *np)
+{
+	struct mezzanine *mez;
+	void *data;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mezzanines); i++) {
+		mez = &mezzanines[i];
+		if (of_device_is_compatible(np, mez->compatible)) {
+			dev_info(ls->dev, "found %s\n", mez->compatible);
+			data = mez->populate(ls);
+			if (IS_ERR(data))
+				return PTR_ERR(data);
+			mez->data = data;
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+static int lscon_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *child;
+	struct spi_controller *spi;
+	struct mezzanine *mez;
+	struct lscon *ls;
+	int ret;
+	int i;
+
+	ls = devm_kzalloc(dev, sizeof(*ls), GFP_KERNEL);
+	if (!ls)
+		return -ENOMEM;
+	ls->dev = dev;
+
+	/* Bridge I2C busses */
+	child = of_parse_phandle(np, "i2c0", 0);
+	if (!child) {
+		dev_err(dev, "no i2c0 phandle\n");
+		return -ENODEV;
+	}
+	ls->i2c0 = of_get_i2c_adapter_by_node(child);
+	if (!ls->i2c0) {
+		dev_err(dev, "no i2c0 adapter, deferring\n");
+		return -EPROBE_DEFER;
+	}
+
+	child = of_parse_phandle(np, "i2c1", 0);
+	if (!child) {
+		dev_err(dev, "no i2c1 phandle\n");
+		ret = -ENODEV;
+		goto out_put_i2c0;
+	}
+	ls->i2c1 = of_get_i2c_adapter_by_node(child);
+	if (!ls->i2c1) {
+		dev_err(dev, "no i2c0 adapter, deferring\n");
+		ret = -EPROBE_DEFER;
+		goto out_put_i2c0;
+	}
+
+	/* Bride SPI bus */
+	child = of_parse_phandle(np, "spi", 0);
+	if (!child) {
+		dev_err(dev, "no spi phandle\n");
+		ret = -ENODEV;
+		goto out_put_i2c1;
+	}
+	spi = of_find_spi_controller_by_node(child);
+	if (!spi) {
+		dev_err(dev, "no spi controller, deferring\n");
+		ret = -EPROBE_DEFER;
+		goto out_put_i2c1;
+	}
+	ls->spi = spi_controller_get(spi);
+	if (!ls->spi) {
+		dev_err(dev, "no spi reference\n");
+		ret = -ENODEV;
+		goto out_put_i2c1;
+	}
+
+	platform_set_drvdata(pdev, ls);
+
+	/* Get the mezzanine boards, stacking possible */
+	for_each_available_child_of_node(np, child)
+		lscon_probe_of_mezzanine(ls, child);
+
+	ret = lscon_add_sysfs_mezzanines(ls);
+	if (ret)
+		goto out_remove_mezzanines;
+
+	return 0;
+
+out_remove_mezzanines:
+	/* Depopulate any populated boards */
+	for (i = 0; i < ARRAY_SIZE(mezzanines); i++) {
+		mez = &mezzanines[i];
+		if (mez->data)
+			mez->depopulate(mez->data);
+		mez->data = NULL;
+	}
+out_put_i2c1:
+	i2c_put_adapter(ls->i2c1);
+out_put_i2c0:
+	i2c_put_adapter(ls->i2c0);
+	return ret;
+}
+
+static int lscon_remove(struct platform_device *pdev)
+{
+	struct lscon *ls = platform_get_drvdata(pdev);
+	struct mezzanine *mez;
+	int i;
+
+	/* Depopulate any populated boards */
+	for (i = 0; i < ARRAY_SIZE(mezzanines); i++) {
+		mez = &mezzanines[i];
+		if (mez->data)
+			mez->depopulate(mez->data);
+		mez->data = NULL;
+	}
+
+	spi_controller_put(ls->spi);
+	i2c_put_adapter(ls->i2c1);
+	i2c_put_adapter(ls->i2c0);
+
+	return 0;
+}
+
+static const struct of_device_id lscon_of_match[] = {
+	{
+		.compatible = "96boards,low-speed-connector",
+	},
+};
+
+static struct platform_driver lscon_driver = {
+	.driver = {
+		.name = "lscon",
+		.of_match_table = of_match_ptr(lscon_of_match),
+	},
+	.probe  = lscon_probe,
+	.remove = lscon_remove,
+};
+builtin_platform_driver(lscon_driver);
drivers/bus/96boards-mezzanines/96boards-mezzanines.h new file +46 -0

46 lines not on this page · raw message

drivers/bus/96boards-mezzanines/96boards-secure96.c new file +249 -0

249 lines not on this page · raw message

drivers/bus/96boards-mezzanines/Kconfig new file +36 -0
new file mode 100644
index 000000000000..18f94e9ec0f8
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# 96boards mezzanine connectors and drivers
+
+menuconfig 96BOARDS_MEZZANINES
+	bool "96boards mezzanine boards"
+
+if 96BOARDS_MEZZANINES
+
+config 96BOARDS_LS_CONNECTOR
+	bool "96boards low speed connector driver"
+	depends on OF
+	depends on I2C
+	depends on SPI_MASTER
+	depends on GPIOLIB
+	help
+	 Driver for the 96boards low speed connector
+
+config 96BOARDS_SECURE96
+	bool "96boards Secure96 board driver"
+	depends on 96BOARDS_LS_CONNECTOR
+	select NEW_LEDS
+	select LEDS_CLASS
+	select LEDS_GPIO
+	select EEPROM_AT24
+	select CRYPTO_HW
+	select CRYPTO_DEV_ATMEL_ECC
+	select HW_RANDOM
+	select TCG_TPM
+	select HW_RANDOM_TPM
+	select TCG_TIS
+	select TCG_TIS_SPI
+	help
+	 Driver for the 96boards Secure96 mezzanine
+
+endif
drivers/bus/96boards-mezzanines/Makefile new file +6 -0
new file mode 100644
index 000000000000..a6e1f3507672
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the 96boards mezzanines
+#
+obj-$(CONFIG_96BOARDS_LS_CONNECTOR)	+= 96boards-ls-connector.o
+obj-$(CONFIG_96BOARDS_SECURE96)		+= 96boards-secure96.o
drivers/bus/Kconfig +2 -0
index d1c0b60e9326..46f7785f27e9 100644
@@ -173,4 +173,6 @@ config DA8XX_MSTPRI
 
 source "drivers/bus/fsl-mc/Kconfig"
 
+source "drivers/bus/96boards-mezzanines/Kconfig"
+
 endmenu
drivers/bus/Makefile +3 -1
index b8f036cca7ff..f6d080a63bd7 100644
@@ -29,5 +29,7 @@ obj-$(CONFIG_TI_SYSC)		+= ti-sysc.o
 obj-$(CONFIG_TS_NBUS)		+= ts-nbus.o
 obj-$(CONFIG_UNIPHIER_SYSTEM_BUS)	+= uniphier-system-bus.o
 obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-config.o
-
 obj-$(CONFIG_DA8XX_MSTPRI)	+= da8xx-mstpri.o
+
+# 96boards mezzanines
+obj-$(CONFIG_96BOARDS_MEZZANINES)	+= 96boards-mezzanines/
Signature · 1 line
2.17.0
#6 lore raw

PATCH 4/5 RFC: bus: 96boards Low-Speed Connector

Quoted 32 lines · Linus Walleij

This illustrates my idea for using a small connector driver to plug in "mezzanine boards" on the 96boards low-speed connector.

These "mezzanine boards" are no different than "capes", "logic modules", etc. This thing, a non-discoverable connector where a user can plug in a few peripherals has been reinvented a few times.

As a proof-of-concept we add the Secure96, a quite minimal mezzanine board.

Users can register their boards in a simple way. Either just add their compatible-string in the device tree:

board {
        compatible = "96boards,secure96";
};

And if they can't even change three lines in their device tree, or if they at runtime decide to plug in some board and test it, they can use sysfs, as exemplified by plugging in the secure96 security board at runtime:

Quoted 2 lines

cd /sys/devices/platform/connector
echo 1 > secure96

[   61.014629] lscon connector: called mezzanine_store on secure96
[   61.020530] lscon connector: populate secure96
[   61.027081] at24 1-0050: 2048 byte 24c128 EEPROM, writable, 128 bytes/write
[   61.053569] atmel-ecc 1-0060: configuration zone is unlocked
[   61.502535] tpm_tis_spi spi0.0: 2.0 TPM (device-id 0x1B, rev-id 16)

(...)

Quoted 8 lines

The plug-in board can be removed from sysfs and added back again multiple times like this with the devices being runtime added and removed by two writes to sysfs.

Quoted 3 lines

echo 0 > secure96
echo 1 > secure96
echo 0 > secure96

(...)

Having a sysfs interface is useful (I certainly love being able to use sysfs to manage ad-hoc I2C chains).

However it feels like the current blurring between connector device and mezzanine device is shining through in this interface if only because the look and feel is very different to instantiating an I2C device from user-space.

Daniel.

#7 lore raw

PATCH 5/5 RFC: ARM64: dts: Add Low-Speed Connector to ZCU100

In reply to Linus Walleij

This adds the low-speed connector to the ZCU100 rev C device tree (also known as the Ultra96 board).

This is a proof-of-concept only, showing how it is possible to populate a Secure96 board using the other patches in the series.

If you comment out or delete the board {} node, you can populate/depopulate the board from sysfs instead.

---
 .../boot/dts/xilinx/zynqmp-zcu100-revC.dts    | 27 +++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts +25 -2
index d62276e0e0a9..fc30497f248d 100644
@@ -110,6 +110,28 @@
 		compatible = "mmc-pwrseq-simple";
 		reset-gpios = <&gpio 7 GPIO_ACTIVE_LOW>; /* WIFI_EN */
 	};
+
+	lscon: connector {
+		compatible = "96boards,low-speed-connector";
+		i2c0 = <&i2csw_0>;
+		i2c1 = <&i2csw_1>;
+		spi = <&spi0>;
+		gpios = <&gpio 36 GPIO_ACTIVE_HIGH>, /* GPIO-A */
+		        <&gpio 37 GPIO_ACTIVE_HIGH>, /* GPIO-B */
+			<&gpio 39 GPIO_ACTIVE_HIGH>, /* GPIO-C */
+			<&gpio 40 GPIO_ACTIVE_HIGH>, /* GPIO-D */
+			<&gpio 44 GPIO_ACTIVE_HIGH>, /* GPIO-E */
+			<&gpio 45 GPIO_ACTIVE_HIGH>, /* GPIO-F */
+			<&gpio 78 GPIO_ACTIVE_HIGH>, /* GPIO-G */
+			<&gpio 79 GPIO_ACTIVE_HIGH>, /* GPIO-H */
+			<&gpio 80 GPIO_ACTIVE_HIGH>, /* GPIO-I */
+			<&gpio 81 GPIO_ACTIVE_HIGH>, /* GPIO-J */
+			<&gpio 82 GPIO_ACTIVE_HIGH>, /* GPIO-K */
+			<&gpio 83 GPIO_ACTIVE_HIGH>; /* GPIO-L */
+		board {
+			compatible = "96boards,secure96";
+		};
+	};
 };
 
 &dcc {
@@ -134,8 +156,9 @@
 			  "USB1_DIR", "USB1_DATA2", "USB1_NXT", "USB1_DATA0", "USB1_DATA1",
 			  "USB1_STP", "USB1_DATA3", "USB1_DATA4", "USB1_DATA5", "USB1_DATA6",
 			  "USB_DATA7", "WLAN_IRQ", "PMIC_IRQ", /* MIO end and EMIO start */
-			  "", "",
-			  "", "", "", "", "", "", "", "", "", "",
+			  "GPIO-G", "GPIO-H",
+			  "GPIO-I", "GPIO-J", "GPIO-K", "GPIO-L",
+			  "", "", "", "", "", "",
 			  "", "", "", "", "", "", "", "", "", "",
 			  "", "", "", "", "", "", "", "", "", "",
 			  "", "", "", "", "", "", "", "", "", "",
Signature · 1 line
2.17.0
#8 lore raw

PATCH 5/5 RFC: ARM64: dts: Add Low-Speed Connector to ZCU100

+David G

Quoted 20 lines · Linus Walleij

This adds the low-speed connector to the ZCU100 rev C device tree (also known as the Ultra96 board).

This is a proof-of-concept only, showing how it is possible to populate a Secure96 board using the other patches in the series.

If you comment out or delete the board {} node, you can populate/depopulate the board from sysfs instead.

---
 .../boot/dts/xilinx/zynqmp-zcu100-revC.dts    | 27 +++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts +0 -0
index d62276e0e0a9..fc30497f248d 100644

arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts line 118

Quoted 9 lines
arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts +6 -0
@@ -110,6 +110,28 @@
                compatible = "mmc-pwrseq-simple";
                reset-gpios = <&gpio 7 GPIO_ACTIVE_LOW>; /* WIFI_EN */
        };
+
+       lscon: connector {
+               compatible = "96boards,low-speed-connector";
+               i2c0 = <&i2csw_0>;
+               i2c1 = <&i2csw_1>;
+               spi = <&spi0>;

David had suggested having an aliases node here for mapping things like SPI and I2C. That actually seems like a good use for aliases compared to the usual abuse to make Linux provide fixed numbering.

arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts line 119

Quoted 1 line
arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts +1 -0
+               gpios = <&gpio 36 GPIO_ACTIVE_HIGH>, /* GPIO-A */

Why aren't you using gpio-map? This is what it was defined for.

arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts line 132

Quoted 13 lines
arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts +13 -0
+                       <&gpio 37 GPIO_ACTIVE_HIGH>, /* GPIO-B */
+                       <&gpio 39 GPIO_ACTIVE_HIGH>, /* GPIO-C */
+                       <&gpio 40 GPIO_ACTIVE_HIGH>, /* GPIO-D */
+                       <&gpio 44 GPIO_ACTIVE_HIGH>, /* GPIO-E */
+                       <&gpio 45 GPIO_ACTIVE_HIGH>, /* GPIO-F */
+                       <&gpio 78 GPIO_ACTIVE_HIGH>, /* GPIO-G */
+                       <&gpio 79 GPIO_ACTIVE_HIGH>, /* GPIO-H */
+                       <&gpio 80 GPIO_ACTIVE_HIGH>, /* GPIO-I */
+                       <&gpio 81 GPIO_ACTIVE_HIGH>, /* GPIO-J */
+                       <&gpio 82 GPIO_ACTIVE_HIGH>, /* GPIO-K */
+                       <&gpio 83 GPIO_ACTIVE_HIGH>; /* GPIO-L */
+               board {
+                       compatible = "96boards,secure96";

I'm all for putting things in the kernel/drivers for things we can't nail down bindings for, but it really seems like you are punting all the problems. Plus if we fully define how to handle the different bindings, we'll likely end up with something different and incompatible with what you have here.

Rob

#9 lore raw

PATCH 5/5 RFC: ARM64: dts: Add Low-Speed Connector to ZCU100

In reply to Linus Walleij
Quoted 31 lines · Linus Walleij

This adds the low-speed connector to the ZCU100 rev C device tree (also known as the Ultra96 board).

This is a proof-of-concept only, showing how it is possible to populate a Secure96 board using the other patches in the series.

If you comment out or delete the board {} node, you can populate/depopulate the board from sysfs instead.

---
 .../boot/dts/xilinx/zynqmp-zcu100-revC.dts    | 27 +++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts +8 -0
index d62276e0e0a9..fc30497f248d 100644
@@ -110,6 +110,28 @@
 		compatible = "mmc-pwrseq-simple";
 		reset-gpios = <&gpio 7 GPIO_ACTIVE_LOW>; /* WIFI_EN */
 	};
+
+	lscon: connector {
+		compatible = "96boards,low-speed-connector";
+		i2c0 = <&i2csw_0>;
+		i2c1 = <&i2csw_1>;
+		spi = <&spi0>;
+		gpios = <&gpio 36 GPIO_ACTIVE_HIGH>, /* GPIO-A */
+		        <&gpio 37 GPIO_ACTIVE_HIGH>, /* GPIO-B */

arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts line 130

Quoted 10 lines
arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts +10 -0
+			<&gpio 39 GPIO_ACTIVE_HIGH>, /* GPIO-C */
+			<&gpio 40 GPIO_ACTIVE_HIGH>, /* GPIO-D */
+			<&gpio 44 GPIO_ACTIVE_HIGH>, /* GPIO-E */
+			<&gpio 45 GPIO_ACTIVE_HIGH>, /* GPIO-F */
+			<&gpio 78 GPIO_ACTIVE_HIGH>, /* GPIO-G */
+			<&gpio 79 GPIO_ACTIVE_HIGH>, /* GPIO-H */
+			<&gpio 80 GPIO_ACTIVE_HIGH>, /* GPIO-I */
+			<&gpio 81 GPIO_ACTIVE_HIGH>, /* GPIO-J */
+			<&gpio 82 GPIO_ACTIVE_HIGH>, /* GPIO-K */
+			<&gpio 83 GPIO_ACTIVE_HIGH>; /* GPIO-L */

This connector has also 2 uarts which you should have here too.

Thanks,
Michal

Quoted 20 lines
arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts +7 -2
+		board {
+			compatible = "96boards,secure96";
+		};
+	};
 };
 
 &dcc {
@@ -134,8 +156,9 @@
 			  "USB1_DIR", "USB1_DATA2", "USB1_NXT", "USB1_DATA0", "USB1_DATA1",
 			  "USB1_STP", "USB1_DATA3", "USB1_DATA4", "USB1_DATA5", "USB1_DATA6",
 			  "USB_DATA7", "WLAN_IRQ", "PMIC_IRQ", /* MIO end and EMIO start */
-			  "", "",
-			  "", "", "", "", "", "", "", "", "", "",
+			  "GPIO-G", "GPIO-H",
+			  "GPIO-I", "GPIO-J", "GPIO-K", "GPIO-L",
+			  "", "", "", "", "", "",
 			  "", "", "", "", "", "", "", "", "", "",
 			  "", "", "", "", "", "", "", "", "", "",
 			  "", "", "", "", "", "", "", "", "", "",
maintainer
#10 lore raw

cover RFC: Mezzanine handling for 96boards

In reply to Linus Walleij
Quoted 9 lines · Linus Walleij

This is a proposal for how to handle the non-discoverable 96boards plug-in expansion boards called "mezzanines" in the Linux kernel. It is a working RFC series meant for discussion at the moment.

The RFC was done on the brand new Ultra96 board from Xilinx with a Secure96 mezzanine expansion board. The main part is in patch 4, the rest is enabling and examples.

Quoted 6 lines

The code can be obtained from here:
https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git/log/?h=ultra96

You can for example probably augment the DTS file for any upstream-supported 96board and get the Secure96 going with it with minor efforts.

Hi Linus,

Thanks for your work on solving this long-standing problem. I've just read through your patches briefly and have a few thoughts:

- I really like the idea of having C code deal with the mezzanine connector itself, acting as an intermediate to tie a number of boards to a number of add-on cards, this seems much simpler than trying to do everything with overlays or one of the other more generic mechanisms.

- I don't like the idea of having the bus driver contain a list of possible add-ons, this seems to go against our usual driver model. What I think we want instead is to make the connector itself a proper bus_type, to allow drivers to register against it as loadable modules, and devices (maybe limited to one device) being created as probed from DT or some other method as you describe.

- You export symbols in the mezzanine_* namespace, which I think is a bit too generic and should perhaps contain something related to 96boards in its name to make it less ambiguous. I suspect we would add a number of further connectors for hats, capes, lures etc, which could all be described as mezzanines. One open question is how we structure the commonality between the various connectors, but we can defer that until we have more than one or two of them.

Arnd

#11 lore raw

cover RFC: Mezzanine handling for 96boards

Quoted 35 lines · Arnd Bergmann
Quoted 9 lines · Linus Walleij

This is a proposal for how to handle the non-discoverable 96boards plug-in expansion boards called "mezzanines" in the Linux kernel. It is a working RFC series meant for discussion at the moment.

The RFC was done on the brand new Ultra96 board from Xilinx with a Secure96 mezzanine expansion board. The main part is in patch 4, the rest is enabling and examples.

Quoted 6 lines

The code can be obtained from here:
https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git/log/?h=ultra96

You can for example probably augment the DTS file for any upstream-supported 96board and get the Secure96 going with it with minor efforts.

Hi Linus,

Thanks for your work on solving this long-standing problem. I've just read through your patches briefly and have a few thoughts:

- I really like the idea of having C code deal with the mezzanine connector itself, acting as an intermediate to tie a number of boards to a number of add-on cards, this seems much simpler than trying to do everything with overlays or one of the other more generic mechanisms.

- I don't like the idea of having the bus driver contain a list of possible add-ons, this seems to go against our usual driver model. What I think we want instead is to make the connector itself a proper bus_type, to allow drivers to register against it as loadable modules, and devices (maybe limited to one device) being created as probed from DT or some other method as you describe.

Quoted 9 lines

- You export symbols in the mezzanine_* namespace, which I think is a bit too generic and should perhaps contain something related to 96boards in its name to make it less ambiguous. I suspect we would add a number of further connectors for hats, capes, lures etc, which could all be described as mezzanines. One open question is how we structure the commonality between the various connectors, but we can defer that until we have more than one or two of them.

Hello all,

We should also consider firmware use of the mezzanines. For instance, the Secure96 has a RNG which UEFI may want to use so the early boot code can access is for KASLR. It also has a TPM, which should not be reset/reinitialized/etc by the OS if we want to make meaningful use of it.

Also, given that we can (and do) already describe topologies involving mezzanines by ignoring the connector altogether (which is not entirely unreasonable given the fact that we [as Linaro/96boards] dropped the ball on this one and did not mandate discoverability for mezzanines). So ideally, DTs can be expressed such that older kernels can still use those peripherals.

maintainer
#12 lore raw

cover RFC: Mezzanine handling for 96boards

Quoted 9 lines · Ard Biesheuvel
Quoted 1 line · Arnd Bergmann

On Mon, Jun 18, 2018 at 9:45 AM, Linus Walleij <[email protected]> wrote:

Also, given that we can (and do) already describe topologies involving mezzanines by ignoring the connector altogether (which is not entirely unreasonable given the fact that we [as Linaro/96boards] dropped the ball on this one and did not mandate discoverability for mezzanines). So ideally, DTs can be expressed such that older kernels can still use those peripherals.

Not sure. Modeling the connector as a device with its own driver does seem like a significant advantage, which to me weighs more than backward compatibility with old kernels. We can clearly always describe the devices behind the connector individually and ignore the connector on old kernels and we should still allow running DT files that work with the old kernels on new kernels, but I don't see running new DT files on old kernels as essential in this case. Many platforms don't actually care about that case at all today (but some do of course).

Arnd

#13 lore raw

cover RFC: Mezzanine handling for 96boards

Quoted 12 lines · Arnd Bergmann
Quoted 9 lines · Ard Biesheuvel
Quoted 1 line · Arnd Bergmann

On Mon, Jun 18, 2018 at 9:45 AM, Linus Walleij <[email protected]> wrote:

Also, given that we can (and do) already describe topologies involving mezzanines by ignoring the connector altogether (which is not entirely unreasonable given the fact that we [as Linaro/96boards] dropped the ball on this one and did not mandate discoverability for mezzanines). So ideally, DTs can be expressed such that older kernels can still use those peripherals.

Quoted 8 lines

Not sure. Modeling the connector as a device with its own driver does seem like a significant advantage, which to me weighs more than backward compatibility with old kernels. We can clearly always describe the devices behind the connector individually and ignore the connector on old kernels and we should still allow running DT files that work with the old kernels on new kernels, but I don't see running new DT files on old kernels as essential in this case. Many platforms don't actually care about that case at all today (but some do of course).

Linus choose Ultra96 board which is showing that "standard" 96boards connector doesn't need to be standard in all cases.
If you look at board schematics that you will see that loaded bitstream/configuration is making these connector compatible with 96boards spec.
Almost the whole HS connector is connected to programmable logic and low speed connector is pretty much flexible too.

Also resource/power saving case should be considered.
I will take uart mezzanine as an example which requires only 6 uart pins and one gpio. In Ultra96 that means that doesn't make sense to waste your fpga resources for something what you don't need. (Truth is that for low speed it is just about wires but with High speed connector MIPI is in PL part which consume a logic).
And both connectors should also be handled together because some mezzanine cards require both of them.

Thanks,
Michal

#14 lore raw
In reply to Ard Biesheuvel
Quoted 57 lines · Ard Biesheuvel
Quoted 1 line · Arnd Bergmann

On Mon, Jun 18, 2018 at 9:45 AM, Linus Walleij <[email protected]>

Quoted 11 lines · wrote:
Quoted 11 lines

This is a proposal for how to handle the non-discoverable 96boards plug-in expansion boards called "mezzanines" in the Linux kernel. It is a working RFC series meant for discussion at the moment.

The RFC was done on the brand new Ultra96 board from Xilinx with a Secure96 mezzanine expansion board. The main part is in patch 4, the rest is enabling and examples.

The code can be obtained from here:
https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux

-integrator.git/log/?h=ultra96

Quoted 10 lines
Quoted 4 lines

You can for example probably augment the DTS file for any upstream-supported 96board and get the Secure96 going with it with minor efforts.

Hi Linus,

Thanks for your work on solving this long-standing problem. I've just read through your patches briefly and have a few thoughts:

Quoted 7 lines

- I really like the idea of having C code deal with the mezzanine connector itself, acting as an intermediate to tie a number of boards to a number of add-on cards, this seems much simpler than trying to do everything with overlays or one of the other more generic mechanisms.

- I don't like the idea of having the bus driver contain a list of

possible

Quoted 6 lines

add-ons, this seems to go against our usual driver model. What I think we want instead is to make the connector itself a proper bus_type, to allow drivers to register against it as loadable modules, and devices (maybe limited to one device) being created as probed from DT or some other method as you describe.

Quoted 9 lines

- You export symbols in the mezzanine_* namespace, which I think is a bit too generic and should perhaps contain something related to 96boards in its name to make it less ambiguous. I suspect we would add a number of further connectors for hats, capes, lures etc, which could all be described as mezzanines. One open question is how we structure the commonality between the various connectors, but we can defer that until we have more than one or two of them.

Hello all,

We should also consider firmware use of the mezzanines. For instance, the Secure96 has a RNG which UEFI may want to use so the early boot code can access is for KASLR. It also has a TPM, which should not be reset/reinitialized/etc by the OS if we want to make meaningful use of it.

Quoted 5 lines

Also, given that we can (and do) already describe topologies involving mezzanines by ignoring the connector altogether (which is not entirely unreasonable given the fact that we [as Linaro/96boards] dropped the ball on this one and did not mandate discoverability for mezzanines).

The design guideline has been reviewed by many inside/outside linaro through the [email protected] and 96b-spec-sig < [email protected]> published as recommended/strongly recommended item from day one. 'dropping the ball' is a strong conclusion.

https://www.96boards.org/documentation/mezzanine/

Quoted 7 lines

So ideally, DTs can be expressed such that older kernels can still use those peripherals.
_______________________________________________
Dev mailing list
[email protected]
https://lists.96boards.org/mailman/listinfo/dev

#15 lore raw

cover RFC: Mezzanine handling for 96boards

Quoted 67 lines · Yang Zhang
Quoted 58 lines · Ard Biesheuvel
Quoted 38 lines · Arnd Bergmann
Quoted 9 lines · Linus Walleij

This is a proposal for how to handle the non-discoverable 96boards plug-in expansion boards called "mezzanines" in the Linux kernel. It is a working RFC series meant for discussion at the moment.

The RFC was done on the brand new Ultra96 board from Xilinx with a Secure96 mezzanine expansion board. The main part is in patch 4, the rest is enabling and examples.

Quoted 7 lines

The code can be obtained from here:

https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git/log/?h=ultra96

You can for example probably augment the DTS file for any upstream-supported 96board and get the Secure96 going with it with minor efforts.

Hi Linus,

Thanks for your work on solving this long-standing problem. I've just read through your patches briefly and have a few thoughts:

- I really like the idea of having C code deal with the mezzanine connector itself, acting as an intermediate to tie a number of boards to a number of add-on cards, this seems much simpler than trying to do everything with overlays or one of the other more generic mechanisms.

- I don't like the idea of having the bus driver contain a list of possible
add-ons, this seems to go against our usual driver model. What I think we want instead is to make the connector itself a proper bus_type, to allow drivers to register against it as loadable modules, and devices (maybe limited to one device) being created as probed from DT or some other method as you describe.

Quoted 9 lines

- You export symbols in the mezzanine_* namespace, which I think is a bit too generic and should perhaps contain something related to 96boards in its name to make it less ambiguous. I suspect we would add a number of further connectors for hats, capes, lures etc, which could all be described as mezzanines. One open question is how we structure the commonality between the various connectors, but we can defer that until we have more than one or two of them.

Hello all,

We should also consider firmware use of the mezzanines. For instance, the Secure96 has a RNG which UEFI may want to use so the early boot code can access is for KASLR. It also has a TPM, which should not be reset/reinitialized/etc by the OS if we want to make meaningful use of it.

Quoted 4 lines

Also, given that we can (and do) already describe topologies involving mezzanines by ignoring the connector altogether (which is not entirely unreasonable given the fact that we [as Linaro/96boards] dropped the ball on this one and did not mandate discoverability for mezzanines).

Quoted 5 lines

The design guideline has been reviewed by many inside/outside linaro through the mezzanine at lists.96boards.org and 96b-spec-sig <[email protected]> published as recommended/strongly recommended item from day one. 'dropping the ball' is a strong conclusion.

Apologies for using a term that you seem to take issue with. Are you saying the spec currently recommends it?

#16 lore raw

Yes.

https://github.com/96boards/documentation/blob/master/mezzanine/files/mezzanine-design-guidelines.pdf

Under Configuration data section

Quoted 83 lines · Ard Biesheuvel
Quoted 3 lines · Yang Zhang

On 18 June 2018 at 14:22, Ard Biesheuvel <[email protected]>

Quoted 9 lines · wrote:
Quoted 9 lines · Arnd Bergmann
Quoted 7 lines
Quoted 5 lines · Linus Walleij

This is a proposal for how to handle the non-discoverable 96boards plug-in expansion boards called "mezzanines" in the Linux kernel. It is a working RFC series meant for discussion at the moment.

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

The RFC was done on the brand new Ultra96 board from Xilinx with a Secure96 mezzanine expansion board. The main part is in patch 4, the rest is enabling and examples.

The code can be obtained from here:

https://git.kernel.org/pub/scm/linux/kernel/git/linusw/

linux-integrator.git/log/?h=ultra96

Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 4 lines

You can for example probably augment the DTS file for any upstream-supported 96board and get the Secure96 going with it with minor efforts.

Hi Linus,

Thanks for your work on solving this long-standing problem. I've just read through your patches briefly and have a few thoughts:

- I really like the idea of having C code deal with the mezzanine connector itself, acting as an intermediate to tie a number of boards to a number of add-on cards, this seems much simpler than trying to do everything with overlays or one of the other more generic mechanisms.

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

- I don't like the idea of having the bus driver contain a list of possible
add-ons, this seems to go against our usual driver model. What I think we want instead is to make the connector itself a proper bus_type, to allow drivers to register against it as loadable

modules,

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

and devices (maybe limited to one device) being created as probed from DT or some other method as you describe.

- You export symbols in the mezzanine_* namespace, which I think is a bit too generic and should perhaps contain something related to 96boards in its name to make it less ambiguous. I suspect we would add a number of further connectors for hats, capes, lures

etc,

Quoted 14 lines
Quoted 14 lines
Quoted 5 lines

which could all be described as mezzanines. One open question is how we structure the commonality between the various connectors, but we can defer that until we have more than one or two of them.

Hello all,

We should also consider firmware use of the mezzanines. For instance, the Secure96 has a RNG which UEFI may want to use so the early boot code can access is for KASLR. It also has a TPM, which should not be reset/reinitialized/etc by the OS if we want to make meaningful use of it.

Quoted 7 lines
Quoted 4 lines

Also, given that we can (and do) already describe topologies involving mezzanines by ignoring the connector altogether (which is not entirely unreasonable given the fact that we [as Linaro/96boards] dropped the ball on this one and did not mandate discoverability for mezzanines).

The design guideline has been reviewed by many inside/outside linaro

through

Quoted 2 lines

the [email protected] and 96b-spec-sig <[email protected]> published as recommended/strongly

recommended

Quoted 2 lines

item from day one. 'dropping the ball' is a strong conclusion.

Apologies for using a term that you seem to take issue with. Are you saying the spec currently recommends it?

#17 lore raw

cover RFC: Mezzanine handling for 96boards

Quoted 6 lines · Yang Zhang

Yes.

https://github.com/96boards/documentation/blob/master/mezzanine/files/mezzanine-design-guidelines.pdf

Under Configuration data section

OK, fair enough. Do any such mezzanines exist yet? Should we offer more guidance on how exactly this discovery should be implemented?

Quoted 86 lines · Ard Biesheuvel
Quoted 83 lines · Yang Zhang
Quoted 71 lines
Quoted 61 lines · Ard Biesheuvel
Quoted 40 lines · Arnd Bergmann
Quoted 9 lines · Linus Walleij

This is a proposal for how to handle the non-discoverable 96boards plug-in expansion boards called "mezzanines" in the Linux kernel. It is a working RFC series meant for discussion at the moment.

The RFC was done on the brand new Ultra96 board from Xilinx with a Secure96 mezzanine expansion board. The main part is in patch 4, the rest is enabling and examples.

Quoted 8 lines

The code can be obtained from here:

https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git/log/?h=ultra96

You can for example probably augment the DTS file for any upstream-supported 96board and get the Secure96 going with it with minor efforts.

Hi Linus,

Thanks for your work on solving this long-standing problem. I've just read through your patches briefly and have a few thoughts:

- I really like the idea of having C code deal with the mezzanine connector itself, acting as an intermediate to tie a number of boards to a number of add-on cards, this seems much simpler than trying to do everything with overlays or one of the other more generic mechanisms.

- I don't like the idea of having the bus driver contain a list of possible
add-ons, this seems to go against our usual driver model. What I think we want instead is to make the connector itself a proper bus_type, to allow drivers to register against it as loadable
modules,
and devices (maybe limited to one device) being created as probed from DT or some other method as you describe.

Quoted 10 lines

- You export symbols in the mezzanine_* namespace, which I think is a bit too generic and should perhaps contain something related to 96boards in its name to make it less ambiguous. I suspect we would add a number of further connectors for hats, capes, lures
etc,
which could all be described as mezzanines. One open question is how we structure the commonality between the various connectors, but we can defer that until we have more than one or two of them.

Hello all,

We should also consider firmware use of the mezzanines. For instance, the Secure96 has a RNG which UEFI may want to use so the early boot code can access is for KASLR. It also has a TPM, which should not be reset/reinitialized/etc by the OS if we want to make meaningful use of it.

Quoted 4 lines

Also, given that we can (and do) already describe topologies involving mezzanines by ignoring the connector altogether (which is not entirely unreasonable given the fact that we [as Linaro/96boards] dropped the ball on this one and did not mandate discoverability for mezzanines).

Quoted 7 lines

The design guideline has been reviewed by many inside/outside linaro through
the mezzanine at lists.96boards.org and 96b-spec-sig <[email protected]> published as recommended/strongly recommended
item from day one. 'dropping the ball' is a strong conclusion.

Apologies for using a term that you seem to take issue with. Are you saying the spec currently recommends it?

#18 lore raw
Quoted 13 lines · Ard Biesheuvel
Quoted 3 lines · Yang Zhang

Yes.

https://github.com/96boards/documentation/blob/master/

mezzanine/files/mezzanine-design-guidelines.pdf

Quoted 3 lines

Under Configuration data section

OK, fair enough. Do any such mezzanines exist yet? Should we offer more guidance on how exactly this discovery should be implemented?

I can't be sure, could look into it - I know there were couple of from Arrow and ST were supporting this.

Yes, more details guidance of "How to" is always welcome :-).

Quoted 97 lines
Quoted 1 line

On 19 June 2018 at 16:25, Ard Biesheuvel <[email protected]>

Quoted 15 lines · wrote:
Quoted 15 lines · Yang Zhang
Quoted 13 lines
Quoted 9 lines · Ard Biesheuvel
Quoted 7 lines · Arnd Bergmann
Quoted 5 lines · Linus Walleij

This is a proposal for how to handle the non-discoverable 96boards plug-in expansion boards called "mezzanines" in the Linux kernel. It is a working RFC series meant for discussion at the moment.

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

The RFC was done on the brand new Ultra96 board from Xilinx with a Secure96 mezzanine expansion board. The main part is in patch 4, the rest is enabling and examples.

The code can be obtained from here:

https://git.kernel.org/pub/scm/linux/kernel/git/linusw/

linux-integrator.git/log/?h=ultra96

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 4 lines

You can for example probably augment the DTS file for any upstream-supported 96board and get the Secure96 going with it with minor efforts.

Hi Linus,

Thanks for your work on solving this long-standing problem. I've

just

Quoted 17 lines
Quoted 17 lines
Quoted 17 lines
Quoted 17 lines
Quoted 17 lines

read through your patches briefly and have a few thoughts:

- I really like the idea of having C code deal with the mezzanine connector itself, acting as an intermediate to tie a number of boards to a number of add-on cards, this seems much simpler than trying to do everything with overlays or one of the other more generic mechanisms.

- I don't like the idea of having the bus driver contain a list of possible
add-ons, this seems to go against our usual driver model. What I think we want instead is to make the connector itself a proper bus_type, to allow drivers to register against it as loadable
modules,
and devices (maybe limited to one device) being created as probed from DT or some other method as you describe.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

- You export symbols in the mezzanine_* namespace, which I think is a bit too generic and should perhaps contain something

related

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines

to 96boards in its name to make it less ambiguous. I suspect we would add a number of further connectors for hats, capes, lures
etc,
which could all be described as mezzanines. One open question is how we structure the commonality between the various connectors, but we can defer that until we have more than one or two of them.

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

Hello all,

We should also consider firmware use of the mezzanines. For instance, the Secure96 has a RNG which UEFI may want to use so the early boot code can access is for KASLR. It also has a TPM, which should not be reset/reinitialized/etc by the OS if we want to make meaningful use

of

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

it.

Also, given that we can (and do) already describe topologies

involving

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

mezzanines by ignoring the connector altogether (which is not

entirely

Quoted 19 lines
Quoted 14 lines
Quoted 11 lines
Quoted 2 lines

unreasonable given the fact that we [as Linaro/96boards] dropped the ball on this one and did not mandate discoverability for mezzanines).

The design guideline has been reviewed by many inside/outside linaro through
the [email protected] and 96b-spec-sig <[email protected]> published as recommended/strongly recommended
item from day one. 'dropping the ball' is a strong conclusion.

Apologies for using a term that you seem to take issue with. Are you saying the spec currently recommends it?

#19 lore raw

cover RFC: Mezzanine handling for 96boards

Quoted 11 lines · Yang Zhang
Quoted 9 lines · Ard Biesheuvel
Quoted 3 lines · Yang Zhang

Yes.

https://github.com/96boards/documentation/blob/master/

mezzanine/files/mezzanine-design-guidelines.pdf

Quoted 3 lines

Under Configuration data section

Quoted 8 lines
Quoted 4 lines

OK, fair enough. Do any such mezzanines exist yet? Should we offer more guidance on how exactly this discovery should be implemented?

I can't be sure, could look into it - I know there were couple of from Arrow and ST were supporting this.

Yes, more details guidance of "How to" is always welcome :-).

Unfortunately this is not saying i2c address and also how to handle stacked solution.

I have told to Linus what Xilinx is using for FMC connector present on the most of xilinx development boards.
These on board FMC eeproms contain information in FRU format. Also there incomplete support fmc support in the kernel in drivers/fmc which was added by Alessandro Rubini in 2013.

At least these eeprom could reuse FRU data format.

Thanks,
Michal

#20 lore raw

cover RFC: Mezzanine handling for 96boards

Quoted 7 lines · Michal Simek

I have told to Linus what Xilinx is using for FMC connector present on the most of xilinx development boards.
These on board FMC eeproms contain information in FRU format. Also there incomplete support fmc support in the kernel in drivers/fmc which was added by Alessandro Rubini in 2013.

At least these eeprom could reuse FRU data format.

The FRU is a very tasteful design IMO and since it is a discoverable (plug and play!) bus I think we should have a clean FRU bus driver along Alessandro's suggestion to support them and spawn devices much like I do, as long as there is interest and some person who spends time writing the bus driver for it.

Yours,
Linus Walleij

#21 lore raw

cover RFC: Mezzanine handling for 96boards

In reply to Ard Biesheuvel
Quoted 5 lines · Ard Biesheuvel

We should also consider firmware use of the mezzanines. For instance, the Secure96 has a RNG which UEFI may want to use so the early boot code can access is for KASLR. It also has a TPM, which should not be reset/reinitialized/etc by the OS if we want to make meaningful use of it.

This problem: sharing or dedicating a piece of hardware to UEFI or the TrustZone secure world is a generic problem not related to mezzanines or plug-in boards specifically.

c.f.
arch/arm64/boot/dts/arm/juno-motherboard.dtsi:

flash at 0,00000000 {
        /* 2 * 32MiB NOR Flash memory mounted on CS0 */
        compatible = "arm,vexpress-flash", "cfi-flash";
        linux,part-probe = "afs";
        reg = <0 0x00000000 0x04000000>;
        bank-width = <4>;
        /*
         * Unfortunately, accessing the flash disturbs
         * the CPU idle states (suspend) and CPU
         * hotplug of the platform. For this reason,
         * flash hardware access is disabled by default.
         */
        status = "disabled";
};

What we need for this is something like

status = "secure-world-exclusive";
status = "UEFI-exclusive";

Or something like the same when using device tree.

If people probe this from sysfs (as in my example) they are obviously not novice users and they know what they are doing. For a simple user experience, I suspect device tree is what we want to use to populate defaults.

Quoted 2 lines

So ideally, DTs can be expressed such that older kernels can still use those peripherals.

That kind of expressions are possible already, such as putting the TPM DT node inside a SoC-specific I2C bus node. The boot loader can do that for example.

Then they can't also probe the same board from userspace, obviously. No matter whether they use the idea I present here or device tree overlays or anything else.

Yours,
Linus Walleij

#22 lore raw

cover RFC: Mezzanine handling for 96boards

Quoted 31 lines · Linus Walleij
Quoted 5 lines · Ard Biesheuvel

We should also consider firmware use of the mezzanines. For instance, the Secure96 has a RNG which UEFI may want to use so the early boot code can access is for KASLR. It also has a TPM, which should not be reset/reinitialized/etc by the OS if we want to make meaningful use of it.

This problem: sharing or dedicating a piece of hardware to UEFI or the TrustZone secure world is a generic problem not related to mezzanines or plug-in boards specifically.

c.f.
arch/arm64/boot/dts/arm/juno-motherboard.dtsi:

flash at 0,00000000 {
        /* 2 * 32MiB NOR Flash memory mounted on CS0 */
        compatible = "arm,vexpress-flash", "cfi-flash";
        linux,part-probe = "afs";
        reg = <0 0x00000000 0x04000000>;
        bank-width = <4>;
        /*
         * Unfortunately, accessing the flash disturbs
         * the CPU idle states (suspend) and CPU
         * hotplug of the platform. For this reason,
         * flash hardware access is disabled by default.
         */
        status = "disabled";
};
Quoted 7 lines

What we need for this is something like

status = "secure-world-exclusive";
status = "UEFI-exclusive";

Or something like the same when using device tree.

I agree that this is *also* a problem. But it is not what I was talking about.

My example is about peripherals that firmware and OS should both drive natively, and in the TPM case, the OS should be mindful of the fact that the measured state should be preserved. Also, it means that we may be duplicating functionality between the OS and firmware [as usual] so it might make sense to come up with something that takes both use cases into account.

Quoted 8 lines

If people probe this from sysfs (as in my example) they are obviously not novice users and they know what they are doing. For a simple user experience, I suspect device tree is what we want to use to populate defaults.

Quoted 2 lines

So ideally, DTs can be expressed such that older kernels can still use those peripherals.

Quoted 8 lines

That kind of expressions are possible already, such as putting the TPM DT node inside a SoC-specific I2C bus node. The boot loader can do that for example.

Then they can't also probe the same board from userspace, obviously. No matter whether they use the idea I present here or device tree overlays or anything else.

OK.

#23 lore raw

cover RFC: Mezzanine handling for 96boards

Quoted 13 lines · Ard Biesheuvel
Quoted 12 lines · Linus Walleij
Quoted 5 lines · Ard Biesheuvel

We should also consider firmware use of the mezzanines. For instance, the Secure96 has a RNG which UEFI may want to use so the early boot code can access is for KASLR. It also has a TPM, which should not be reset/reinitialized/etc by the OS if we want to make meaningful use of it.

This problem: sharing or dedicating a piece of hardware to UEFI or the TrustZone secure world is a generic problem not related to mezzanines or plug-in boards specifically.

(...)

Quoted 5 lines

I agree that this is *also* a problem. But it is not what I was talking about.

My example is about peripherals that firmware and OS should both drive natively, and in the TPM case, the OS should be mindful of the fact that the measured state should be preserved.

Ah I see.

In that case this is something the TPM driver should be doing I guess? I mean it is a "firmware plus OS TPM driver"-specific problem.

I guess that would be hard to duct-tape on if the peripheral is context-unaware and easy to do if the designer of the peripheral HW took multiple call-context into account. Whether TPM does this I don't know...

Quoted 4 lines

Also, it means that we
may be duplicating functionality between the OS and firmware [as usual] so it might make sense to come up with something that takes both use cases into account.

What we are doing now with Atmel's ECC chip is even worse:
duplicating functionality between OS and userspace. So I'm trying to solve that first.

Yours,
Linus Walleij

#24 lore raw

cover RFC: Mezzanine handling for 96boards

In reply to Arnd Bergmann
Quoted 5 lines · Arnd Bergmann

- I really like the idea of having C code deal with the mezzanine connector itself, acting as an intermediate to tie a number of boards to a number of add-on cards, this seems much simpler than trying to do everything with overlays or one of the other more generic mechanisms.

This is my point of view as well.

Quoted 6 lines

- I don't like the idea of having the bus driver contain a list of possible add-ons, this seems to go against our usual driver model. What I think we want instead is to make the connector itself a proper bus_type, to allow drivers to register against it as loadable modules, and devices (maybe limited to one device) being created as probed from DT or some other method as you describe.

OK I think I can do that. It will take some thinking and I would guess I should also move it to drivers/platform/*

My idea here would be to have a connector bus that some random add-on (such as a 96board mezzanine) would probe to, so we make it generic for any connector plug.

Quoted 5 lines

- You export symbols in the mezzanine_* namespace, which I think is a bit too generic and should perhaps contain something related to 96boards in its name to make it less ambiguous. I suspect we would add a number of further connectors for hats, capes, lures etc, which could all be described as mezzanines.

Michal also brings up the (discoverable!) FMC connectors Xilinx are using. So the idea would be to create something generic to help probe and populate them all whether partly discoverable or not.

Quoted 4 lines

One open question
is how we structure the commonality between the various connectors, but we can defer that until we have more than one or two of them.

I can clean up the namespace at least so it gets clear where to add them. I will try to be more generic in the next iteration.

Yours,
Linus Walleij

maintainer
#25 lore raw

cover RFC: Mezzanine handling for 96boards

Quoted 17 lines · Linus Walleij
Quoted 5 lines · Arnd Bergmann

- I really like the idea of having C code deal with the mezzanine connector itself, acting as an intermediate to tie a number of boards to a number of add-on cards, this seems much simpler than trying to do everything with overlays or one of the other more generic mechanisms.

This is my point of view as well.

Quoted 6 lines

- I don't like the idea of having the bus driver contain a list of possible add-ons, this seems to go against our usual driver model. What I think we want instead is to make the connector itself a proper bus_type, to allow drivers to register against it as loadable modules, and devices (maybe limited to one device) being created as probed from DT or some other method as you describe.

Quoted 2 lines

OK I think I can do that. It will take some thinking and I would guess I should also move it to drivers/platform/*

I'd probably leave it in drivers/bus/, though this might be one of the rare cases that drivers/platform makes sense for as well.

Quoted 3 lines

My idea here would be to have a connector bus that some random add-on (such as a 96board mezzanine) would probe to, so we make it generic for any connector plug.

The question here is whether we want one 'struct bus_type' instance shared by all connector types, or one for each type. I was actually leaning towards the latter here.

Quoted 9 lines
Quoted 5 lines

- You export symbols in the mezzanine_* namespace, which I think is a bit too generic and should perhaps contain something related to 96boards in its name to make it less ambiguous. I suspect we would add a number of further connectors for hats, capes, lures etc, which could all be described as mezzanines.

Michal also brings up the (discoverable!) FMC connectors Xilinx are using. So the idea would be to create something generic to help probe and populate them all whether partly discoverable or not.

If a bus is fully discoverable, I think it's better to use a separate bus_type that does not use DT based probing for its children. However, many buses (even USB and PCI) turn out to be only mostly discoverable, so we end up having to come up with a way to represent child devices in DT as well.

Arnd

maintainer
#26 lore raw

cover RFC: Mezzanine handling for 96boards

In reply to Linus Walleij
Quoted 11 lines · Linus Walleij
Quoted 5 lines · Arnd Bergmann

- You export symbols in the mezzanine_* namespace, which I think is a bit too generic and should perhaps contain something related to 96boards in its name to make it less ambiguous. I suspect we would add a number of further connectors for hats, capes, lures etc, which could all be described as mezzanines.

Michal also brings up the (discoverable!) FMC connectors Xilinx are using. So the idea would be to create something generic to help probe and populate them all whether partly discoverable or not.

There's also the plug in modules in the Wolfson Cragganmore, there's
enumeration support for that in mainline.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180626/61df6737/attachment.sig>

#27 lore raw
In reply to Arnd Bergmann
Quoted 19 lines · Arnd Bergmann
Quoted 9 lines · Linus Walleij

This is a proposal for how to handle the non-discoverable 96boards plug-in expansion boards called "mezzanines" in the Linux kernel. It is a working RFC series meant for discussion at the moment.

The RFC was done on the brand new Ultra96 board from Xilinx with a Secure96 mezzanine expansion board. The main part is in patch 4, the rest is enabling and examples.

Quoted 6 lines

The code can be obtained from here:
https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git/log/?h=ultra96

You can for example probably augment the DTS file for any upstream-supported 96board and get the Secure96 going with it with minor efforts.

Hi Linus,

Quoted 8 lines

Thanks for your work on solving this long-standing problem. I've just read through your patches briefly and have a few thoughts:

- I really like the idea of having C code deal with the mezzanine connector itself, acting as an intermediate to tie a number of boards to a number of add-on cards, this seems much simpler than trying to do everything with overlays or one of the other more generic mechanisms.

Certainly we need at least some code to trigger probing devices under a connector. I suspect some connectors can be handled generically and some will need connector specific drivers.

Quoted 6 lines

- I don't like the idea of having the bus driver contain a list of possible add-ons, this seems to go against our usual driver model. What I think we want instead is to make the connector itself a proper bus_type, to allow drivers to register against it as loadable modules, and devices (maybe limited to one device) being created as probed from DT or some other method as you describe.

Why a bus versus just a platform device? The infrastructure is already there to instantiate platform devices and match to compatible strings and a platform driver can create child devices. So what would we gain from a new bus?

We have 2 cases to consider I think: discoverable and non-discoverable boards. But discoverable here only provides us what overlay to load and/or driver to enumerate.

Quoted 11 lines

- You export symbols in the mezzanine_* namespace, which I think is a bit too generic and should perhaps contain something related to 96boards in its name to make it less ambiguous. I suspect we would add a number of further connectors for hats, capes, lures etc, which could all be described as mezzanines. One open question is how we structure the commonality between the various connectors, but we can defer that until we have more than one or two of them.

Arnd

#28 lore raw

cover RFC: Mezzanine handling for 96boards

In reply to Linus Walleij
Quoted 9 lines · Linus Walleij

This is a proposal for how to handle the non-discoverable 96boards plug-in expansion boards called "mezzanines" in the Linux kernel. It is a working RFC series meant for discussion at the moment.

The RFC was done on the brand new Ultra96 board from Xilinx with a Secure96 mezzanine expansion board. The main part is in patch 4, the rest is enabling and examples.

Quoted 6 lines

The code can be obtained from here:
https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git/log/?h=ultra96

You can for example probably augment the DTS file for any upstream-supported 96board and get the Secure96 going with it with minor efforts.

Like other commenters I'm rather like using C to solve this, and your comments Big Upfront Design are good backup in term of convincing me.

Quoted 12 lines

TODO:

- Proper device tree bindings for the connector, for now look at the example.

- Discuss whether to actually do this or just take it all and flush it down the drain because the community doesn't like it. I'm not one of those especially infatuated with my own code, I always stay by the old programming project management mantra to calculate to make one version and throw it away as stepping stone to a good final design.

Quoted 7 lines

- Placement: putting this in drivers/bus is just an example. drivers/platform/96boards-mezzanines is fine too, maybe better?

- I am especially curious about input from Andy and Mika from the Intel/ACPI camp on what they have seen for non-discoverable plug-in boards. Does this problem even exist in the Intel world, or not...

I'm also interested in the "what about ACPI" question?

Using C makes describing a board in ACPI fairly easy. AFAICT allocating IDs to a board rather than its included components is fairly natural for ACPI.

However I'm too ignorant to be able to figure out if the expansion connector itself could/should be described in the tables (e.g. if connector is a bus and the board is[1] a device, could the bus driver be instantiated in a reasonable way).

Daniel.

[1] ... or becomes a device, based on feedback in this thread ;-)

maintainer
#29 lore raw

cover RFC: Mezzanine handling for 96boards

Quoted 7 lines · Daniel Thompson
Quoted 4 lines · Linus Walleij

- I am especially curious about input from Andy and Mika from the Intel/ACPI camp on what they have seen for non-discoverable plug-in boards. Does this problem even exist in the Intel world, or not...

Quoted 5 lines

I'm also interested in the "what about ACPI" question?

Using C makes describing a board in ACPI fairly easy. AFAICT allocating IDs to a board rather than its included components is fairly natural for ACPI.

Yes, they have this problem - they have plug in modules on for example the minnowboard and some of their other reference platforms. They have overlays working for ACPI, these have their own problems in that they don't appear to have the equivalent of DMI data (at least the patches people are sending indicates that they don't) which is unfortuate as the idiomatic thing for ACPI is as you say to key huge chunks of data of quirk tables based on the DMI information for their boards.

They don't to my knowledge have generic connectors or anything like
that, it's just patches to the base ACPI.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180619/fed9da48/attachment-0001.sig>

#30 lore raw

cover RFC: Mezzanine handling for 96boards

In reply to Linus Walleij
Quoted 120 lines · Linus Walleij

This is a proposal for how to handle the non-discoverable 96boards plug-in expansion boards called "mezzanines" in the Linux kernel. It is a working RFC series meant for discussion at the moment.

The RFC was done on the brand new Ultra96 board from Xilinx with a Secure96 mezzanine expansion board. The main part is in patch 4, the rest is enabling and examples.

The code can be obtained from here:
https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git/log/?h=ultra96

You can for example probably augment the DTS file for any upstream-supported 96board and get the Secure96 going with it with minor efforts.

TODO:

- Proper device tree bindings for the connector, for now look at the example.

- Discuss whether to actually do this or just take it all and flush it down the drain because the community doesn't like it. I'm not one of those especially infatuated with my own code, I always stay by the old programming project management mantra to calculate to make one version and throw it away as stepping stone to a good final design.

- Placement: putting this in drivers/bus is just an example. drivers/platform/96boards-mezzanines is fine too, maybe better?

- I am especially curious about input from Andy and Mika from the Intel/ACPI camp on what they have seen for non-discoverable plug-in boards. Does this problem even exist in the Intel world, or not...

Background:

- These boards connect on a custom connector on this family of boards. The relationship is many-to-many with the connector as nexus. The electronic standard for the connector is specified:
https://github.com/96boards/documentation/blob/master/Specifications/96Boards-CE-Specification.pdf
Example mezzanines:
https://www.96boards.org/documentation/mezzanine/

- These boards have siblings on other platforms, the problem scope is similar with BeagleBone "capes":
https://beagleboard.org/capes
Raspberry Pi expansion boards:
https://www.abelectronics.co.uk/products/18/raspberry-pi-expansion-boards
Intel Edison, Galileo, Joule also have expansion boards.

Idea: add a driver for the connector itself and tie it in to the device tree with a compatible string. Since the boards are non-discoverable two mechanisms are provided to discover them:

- Add a very simple device tree node with just a compatible string for the board in the node. This will be simple to add from e.g. a boot loader or as an overlay from userspace.

  board {
        compatible = "96boards,secure96";
  };

- Echo 1 > boardname into a sysfs file to populate the board and echo 0 > boardname to depopulate it. This makes it easy to even switch out expansion boards at runtime, if allowed by the electronics.

Quoted 2 lines

cd /sys/devices/platform/connector
echo 1 > secure96

lscon connector: called mezzanine_store on secure96 lscon connector: populate secure96
at24 1-0050: 2048 byte 24c128 EEPROM, writable, 128 bytes/write atmel-ecc 1-0060: configuration zone is unlocked tpm_tis_spi spi0.0: 2.0 TPM (device-id 0x1B, rev-id 16) (...)

What this patch set does not do:

- It does not use device tree or ACPI DSDT or any other hardware decription language to model the contents of the board per se. Instead the boards buses are populated directly with platform devices.

Predictable complaints about this design:

Q: This is not device tree overlays. Why is it not device
tree overlays?

A1: Right tool for the job, overlays are complex and the
plan to get it in place seems to be spanning years, this is a few devices on simple busses and it works today. Using this approach I can already work on shaping up drivers for the mezzanine board devices as proved by:
https://marc.info/?l=linux-crypto-vger&m=152820660120590&w=2
https://marc.info/?l=linux-crypto-vger&m=152820662820595&w=2
(...)

I can work on drivers for the chips on the Secure96 mezzanine board. It's just an example of what the mezzanine community can do.
Now they are hacking around in userspace instead of doing/reusing kernel drivers for their stuff:
https://github.com/jbech-linaro/secure96

This way we can bring developers for these components into the kernel community instead of telling them to wait for some big infrastructure that comes later before they can contribute their stuff.

A2: Overlays does not solve the problem if the system runs
ACPI, and what about if the same connector[s] appear on a server board, servers use ACPI. Also notice that Intel have development boards with non-discoverable expansion boards as well. They just will not use device tree.

Quoted 13 lines

A3: Overlays is Big Upfront Design.
https://en.wikipedia.org/wiki/Big_Design_Up_Front
This way of designing things is associated with the (pejorative term) "waterfall model" which is out of fashion as a way of doing development. I think I am not the only one slightly annoyed by the fact that device tree overlays is now starting to look like a very big very upfront design. It's just not possible to get something up and running in small iterative steps with device tree overlays. Instead huge efforts are required and it involves major possible showstoppers and uncertain outcome as indicated by Frank's TODO:
https://elinux.org/Frank's_Evolving_Overlay_Thoughts

I don't agree. This can be broken down into various smaller mostly independent problems. Overlay handling is mostly an orthogonal problem. The exception is that we need to ensure bindings allow a decoupling of upstream of the connector and downstream of the connector so the downstream part can be a reusable overlay. Defining anything while ignoring this known criteria would be a mistake.

The list is roughly like this:

- Connector node binding and probing infrastructure
- GPIO (already done w/ gpio-map binding)
- I2C
- SPI
- Pinmux
- clocks
- OF graph (displays, cameras, etc.)
- USB (re-use the USB connector binding for non-standard connectors)
- Userspace interface

We don't have to support every interface from the start. The bindings and corresponding kernel support can be designed 1-by-1 for the most part. Start with something simple like a GPIO LED on a mezzanine. Once the base is functionality is there, the other parts can be worked on incrementally. We can punt any overlay handling to the bootloader initially. That punts all the issues around overlays like designing a userspace interface, where overlays are located (filesystem, passed from bootloader, built into the kernel), when they are loaded, and how to specify which overlays to load. Most of Frank's list is related to these issues.

Rob

#31 lore raw

cover RFC: Mezzanine handling for 96boards

Quoted 165 lines · Rob Herring
Quoted 120 lines · Linus Walleij

This is a proposal for how to handle the non-discoverable 96boards plug-in expansion boards called "mezzanines" in the Linux kernel. It is a working RFC series meant for discussion at the moment.

The RFC was done on the brand new Ultra96 board from Xilinx with a Secure96 mezzanine expansion board. The main part is in patch 4, the rest is enabling and examples.

The code can be obtained from here:
https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git/log/?h=ultra96

You can for example probably augment the DTS file for any upstream-supported 96board and get the Secure96 going with it with minor efforts.

TODO:

- Proper device tree bindings for the connector, for now look at the example.

- Discuss whether to actually do this or just take it all and flush it down the drain because the community doesn't like it. I'm not one of those especially infatuated with my own code, I always stay by the old programming project management mantra to calculate to make one version and throw it away as stepping stone to a good final design.

- Placement: putting this in drivers/bus is just an example. drivers/platform/96boards-mezzanines is fine too, maybe better?

- I am especially curious about input from Andy and Mika from the Intel/ACPI camp on what they have seen for non-discoverable plug-in boards. Does this problem even exist in the Intel world, or not...

Background:

- These boards connect on a custom connector on this family of boards. The relationship is many-to-many with the connector as nexus. The electronic standard for the connector is specified:
https://github.com/96boards/documentation/blob/master/Specifications/96Boards-CE-Specification.pdf
Example mezzanines:
https://www.96boards.org/documentation/mezzanine/

- These boards have siblings on other platforms, the problem scope is similar with BeagleBone "capes":
https://beagleboard.org/capes
Raspberry Pi expansion boards:
https://www.abelectronics.co.uk/products/18/raspberry-pi-expansion-boards
Intel Edison, Galileo, Joule also have expansion boards.

Idea: add a driver for the connector itself and tie it in to the device tree with a compatible string. Since the boards are non-discoverable two mechanisms are provided to discover them:

- Add a very simple device tree node with just a compatible string for the board in the node. This will be simple to add from e.g. a boot loader or as an overlay from userspace.

  board {
        compatible = "96boards,secure96";
  };

- Echo 1 > boardname into a sysfs file to populate the board and echo 0 > boardname to depopulate it. This makes it easy to even switch out expansion boards at runtime, if allowed by the electronics.

Quoted 2 lines

cd /sys/devices/platform/connector
echo 1 > secure96

lscon connector: called mezzanine_store on secure96 lscon connector: populate secure96
at24 1-0050: 2048 byte 24c128 EEPROM, writable, 128 bytes/write atmel-ecc 1-0060: configuration zone is unlocked tpm_tis_spi spi0.0: 2.0 TPM (device-id 0x1B, rev-id 16) (...)

What this patch set does not do:

- It does not use device tree or ACPI DSDT or any other hardware decription language to model the contents of the board per se. Instead the boards buses are populated directly with platform devices.

Predictable complaints about this design:

Q: This is not device tree overlays. Why is it not device
tree overlays?

A1: Right tool for the job, overlays are complex and the
plan to get it in place seems to be spanning years, this is a few devices on simple busses and it works today. Using this approach I can already work on shaping up drivers for the mezzanine board devices as proved by:
https://marc.info/?l=linux-crypto-vger&m=152820660120590&w=2
https://marc.info/?l=linux-crypto-vger&m=152820662820595&w=2
(...)

I can work on drivers for the chips on the Secure96 mezzanine board. It's just an example of what the mezzanine community can do.
Now they are hacking around in userspace instead of doing/reusing kernel drivers for their stuff:
https://github.com/jbech-linaro/secure96

This way we can bring developers for these components into the kernel community instead of telling them to wait for some big infrastructure that comes later before they can contribute their stuff.

A2: Overlays does not solve the problem if the system runs
ACPI, and what about if the same connector[s] appear on a server board, servers use ACPI. Also notice that Intel have development boards with non-discoverable expansion boards as well. They just will not use device tree.

Quoted 13 lines

A3: Overlays is Big Upfront Design.
https://en.wikipedia.org/wiki/Big_Design_Up_Front
This way of designing things is associated with the (pejorative term) "waterfall model" which is out of fashion as a way of doing development. I think I am not the only one slightly annoyed by the fact that device tree overlays is now starting to look like a very big very upfront design. It's just not possible to get something up and running in small iterative steps with device tree overlays. Instead huge efforts are required and it involves major possible showstoppers and uncertain outcome as indicated by Frank's TODO:
https://elinux.org/Frank's_Evolving_Overlay_Thoughts

I don't agree. This can be broken down into various smaller mostly independent problems. Overlay handling is mostly an orthogonal problem. The exception is that we need to ensure bindings allow a decoupling of upstream of the connector and downstream of the connector so the downstream part can be a reusable overlay. Defining anything while ignoring this known criteria would be a mistake.

The list is roughly like this:

- Connector node binding and probing infrastructure
- GPIO (already done w/ gpio-map binding)
- I2C
- SPI
- Pinmux
- clocks
- OF graph (displays, cameras, etc.)
- USB (re-use the USB connector binding for non-standard connectors)
- Userspace interface

We don't have to support every interface from the start. The bindings and corresponding kernel support can be designed 1-by-1 for the most part. Start with something simple like a GPIO LED on a mezzanine. Once the base is functionality is there, the other parts can be worked on incrementally. We can punt any overlay handling to the bootloader initially. That punts all the issues around overlays like designing a userspace interface, where overlays are located (filesystem, passed from bootloader, built into the kernel), when they are loaded, and how to specify which overlays to load. Most of Frank's list is related to these issues.

Quoted 2 lines

Rob

Agreeing with Rob (despite my other reply asking why the current devicetree mechanisms can't be used) that we do have a desire to have the ability to create bindings for connectors - this has been discussed before.

-Frank

#32 lore raw

cover RFC: Mezzanine handling for 96boards

Quoted 2 lines · Frank Rowand

Agreeing with Rob (despite my other reply asking why the current devicetree mechanisms can't be used)

I think I answer also your comments in my reply to Rob, please check!

Quoted 3 lines

that we do have a desire to
have the ability to create bindings for connectors - this has been discussed before.

Let's create bindings for connectors.

But I have this caveat: let's create a binding for connectors that does not stipulate that its children must be populated using overlays, but could optionally be bound to driver that populate the children any way the OS want to do this.

Yours,
Linus Walleij

#33 lore raw

cover RFC: Mezzanine handling for 96boards

In reply to Rob Herring
Quoted 3 lines · Rob Herring
Quoted 1 line · Linus Walleij

A3: Overlays is Big Upfront Design.

(...)

Quoted 6 lines

I don't agree. This can be broken down into various smaller mostly independent problems. Overlay handling is mostly an orthogonal problem. The exception is that we need to ensure bindings allow a decoupling of upstream of the connector and downstream of the connector so the downstream part can be a reusable overlay. Defining anything while ignoring this known criteria would be a mistake.

Hopefully we can make a connector binding that can be used in any way by the OS: either probe a board populating driver (such as in this patch set) or allow an overlay to be inserted (the aforementioned driver compiled out or inactive) further down the road. I would like to believe the board population problem is a both/and thing, not an either/or thing here.

Could be a simple as a compatible-string for the connector(s). We just keep it dirt simple.

Quoted 4 lines

The list is roughly like this:

- Connector node binding and probing infrastructure
- GPIO (already done w/ gpio-map binding)

I tested that actually, using the connector as nexus. It works fine. The problem I ran into was more practical
(see below).

Quoted 11 lines

- I2C
- SPI
- Pinmux
- clocks
- OF graph (displays, cameras, etc.)
- USB (re-use the USB connector binding for non-standard connectors)
- Userspace interface

We don't have to support every interface from the start. The bindings and corresponding kernel support can be designed 1-by-1 for the most part. Start with something simple like a GPIO LED on a mezzanine.

I have that working today, I just didn't go beyond that.

It's because of usability issues. (Described below.)

Quoted 4 lines

Once
the base is functionality is there, the other parts can be worked on incrementally. We can punt any overlay handling to the bootloader initially.

I didn't even do that. I just patched the DTS with a connector and booted it.

Quoted 1 line

From a user point of view whether having a

patched up DTS or a boot loader modifying the DTB at run-time does not really matter as these boards are non-discoverable anyway. The boot loader will now know if they are there or not. What should the user do? Should they send command line arguments to U-Boot to say that we have the secure96 board? Flash different boot loaders depending on what board(s) are connected? That is even more awkward (IMO) than just modifying and redeploying the DTB.

The bright side of this patch set is that the user boots and the kernel is aware of there being a connector and presents sysfs files to populate the boards.

User goes "hm OK I have a secure96":
cd /sys/bus/platform/devices/connector
echo 1 > secure96

And there it populates.

No special boot loaders. No special tools.

Quoted 5 lines

That punts all the issues around overlays like designing a userspace interface, where overlays are located (filesystem, passed from bootloader, built into the kernel), when they are loaded, and how to specify which overlays to load. Most of Frank's list is related to these issues.

And that is where the user (also me) stops short.

Now I want to plug this board. OK download device tree compiler, author a fragment, compile it, compile a special userspace for inserting it into the right node, flash filesystem with that new userpace tool, also do not forget the DTB fragment, parameterize that tool to load the fragment into the connector node. Maybe the user need to change stuff on the fly? Hm then they need a text editor and a DT compiler on the target too, OK things like that can be done.

Admittedly the above is more versatile. Probably awesome when you need to populate a device forest on an FPGA.

But is that even a realistic usecase? And what about the average plug-in board user? If they can do the population by compiling a kernel driver for their board and say it's there and populate it with a simple echo into a sysfs file they will be happy.

It doesn't exclude (IMHO if done right) the possibility for a more complex device tree fragment approach to
be substituted for this later, if it is better for the user. They just stop to compile in that kernel module for populating the board, or do not use the sysfs file.

IMO it is way better than "stop everything and fix fragments first". It's a stopgap thing, if overlays materialize later.

Yours,
Linus Walleij

maintainer
#34 lore raw

cover RFC: Mezzanine handling for 96boards

Quoted 13 lines · Linus Walleij
Quoted 3 lines · Rob Herring
Quoted 1 line · Linus Walleij

A3: Overlays is Big Upfront Design.

(...)

Quoted 6 lines

I don't agree. This can be broken down into various smaller mostly independent problems. Overlay handling is mostly an orthogonal problem. The exception is that we need to ensure bindings allow a decoupling of upstream of the connector and downstream of the connector so the downstream part can be a reusable overlay. Defining anything while ignoring this known criteria would be a mistake.

Quoted 7 lines

Hopefully we can make a connector binding that can be used in any way by the OS: either probe a board populating driver (such as in this patch set) or allow an overlay to be inserted (the aforementioned driver compiled out or inactive) further down the road. I would like to believe the board population problem is a both/and thing, not an either/or thing here.

Certainly both can be supported. The base DT should be the same. I don't think populating via DT needs to be a further down the road thing. We're already further down the road...

Quoted 2 lines

Could be a simple as a compatible-string for the connector(s). We just keep it dirt simple.

Yes, that would be the most simple case. Not really any work to do there, so what's the point? Soon enough, we'll need to support all the things listed below and what we certainly don't need is each connector doing things their own way.

Quoted 25 lines
Quoted 4 lines

The list is roughly like this:

- Connector node binding and probing infrastructure
- GPIO (already done w/ gpio-map binding)

I tested that actually, using the connector as nexus. It works fine. The problem I ran into was more practical
(see below).

Quoted 11 lines

- I2C
- SPI
- Pinmux
- clocks
- OF graph (displays, cameras, etc.)
- USB (re-use the USB connector binding for non-standard connectors)
- Userspace interface

We don't have to support every interface from the start. The bindings and corresponding kernel support can be designed 1-by-1 for the most part. Start with something simple like a GPIO LED on a mezzanine.

I have that working today, I just didn't go beyond that.

It's because of usability issues. (Described below.)

Quoted 7 lines
Quoted 4 lines

Once
the base is functionality is there, the other parts can be worked on incrementally. We can punt any overlay handling to the bootloader initially.

I didn't even do that. I just patched the DTS with a connector and booted it.

Yes, or just do that. In any case, don't blame overlays for avoiding more fully defining connector bindings.

Quoted 10 lines

From a user point of view whether having a patched up DTS or a boot loader modifying the DTB at run-time does not really matter as these boards are non-discoverable anyway. The boot loader will now know if they are there or not. What should the user do? Should they send command line arguments to U-Boot to say that we have the secure96 board? Flash different boot loaders depending on what board(s) are connected? That is even more awkward (IMO) than just modifying and redeploying the DTB.

Ideally, it would be as simple as editing a syslinux style menu text file or setting an EFI variable. But yes, we do need to define exactly how that is done. It's something on the todo list for EBBR, but not going to happen until after the 1st release.

Quoted 20 lines

The bright side of this patch set is that the user boots and the kernel is aware of there being a connector and presents sysfs files to populate the boards.

User goes "hm OK I have a secure96":
cd /sys/bus/platform/devices/connector
echo 1 > secure96

And there it populates.

No special boot loaders. No special tools.

Quoted 5 lines

That punts all the issues around overlays like designing a userspace interface, where overlays are located (filesystem, passed from bootloader, built into the kernel), when they are loaded, and how to specify which overlays to load. Most of Frank's list is related to these issues.

And that is where the user (also me) stops short.

Quoted 9 lines

Now I want to plug this board. OK download device tree compiler, author a fragment, compile it, compile a special userspace for inserting it into the right node, flash filesystem with that new userpace tool, also do not forget the DTB fragment, parameterize that tool to load the fragment into the connector node. Maybe the user need to change stuff on the fly? Hm then they need a text editor and a DT compiler on the target too, OK things like that can be done.

With your series, they'd just have to edit and rebuild the kernel...

Quoted 9 lines

Admittedly the above is more versatile. Probably awesome when you need to populate a device forest on an FPGA.

But is that even a realistic usecase? And what about the average plug-in board user? If they can do the population by compiling a kernel driver for their board and say it's there and populate it with a simple echo into a sysfs file they will be happy.

Only a kernel developer would think compiling a kernel driver makes for a good usecase.

For users, I think all the board dtbs have to be on the filesystem and the user only has to set which ones to apply (when there is no eeprom to allow doing that automatically). That's essentially what you have on RPi today (though I've got issues with some of their overlays, but that's a whole other can of worms).

The other user usecase I think is custom or prototyping boards. For those cases, we probably do want some run-time interface which could be a kernel driver (as you have) or configfs overlay interface. But I'd start with the first usecase and worry about this one later.

Rob

#35 lore raw

cover RFC: Mezzanine handling for 96boards

+Pantelis

Quoted 137 lines · Rob Herring
Quoted 13 lines · Linus Walleij
Quoted 3 lines · Rob Herring
Quoted 1 line · Linus Walleij

A3: Overlays is Big Upfront Design.

(...)

Quoted 6 lines

I don't agree. This can be broken down into various smaller mostly independent problems. Overlay handling is mostly an orthogonal problem. The exception is that we need to ensure bindings allow a decoupling of upstream of the connector and downstream of the connector so the downstream part can be a reusable overlay. Defining anything while ignoring this known criteria would be a mistake.

Quoted 7 lines

Hopefully we can make a connector binding that can be used in any way by the OS: either probe a board populating driver (such as in this patch set) or allow an overlay to be inserted (the aforementioned driver compiled out or inactive) further down the road. I would like to believe the board population problem is a both/and thing, not an either/or thing here.

Certainly both can be supported. The base DT should be the same. I don't think populating via DT needs to be a further down the road thing. We're already further down the road...

Quoted 2 lines

Could be a simple as a compatible-string for the connector(s). We just keep it dirt simple.

Yes, that would be the most simple case. Not really any work to do there, so what's the point? Soon enough, we'll need to support all the things listed below and what we certainly don't need is each connector doing things their own way.

Quoted 25 lines
Quoted 4 lines

The list is roughly like this:

- Connector node binding and probing infrastructure
- GPIO (already done w/ gpio-map binding)

I tested that actually, using the connector as nexus. It works fine. The problem I ran into was more practical
(see below).

Quoted 11 lines

- I2C
- SPI
- Pinmux
- clocks
- OF graph (displays, cameras, etc.)
- USB (re-use the USB connector binding for non-standard connectors)
- Userspace interface

We don't have to support every interface from the start. The bindings and corresponding kernel support can be designed 1-by-1 for the most part. Start with something simple like a GPIO LED on a mezzanine.

I have that working today, I just didn't go beyond that.

It's because of usability issues. (Described below.)

Quoted 7 lines
Quoted 4 lines

Once
the base is functionality is there, the other parts can be worked on incrementally. We can punt any overlay handling to the bootloader initially.

I didn't even do that. I just patched the DTS with a connector and booted it.

Yes, or just do that. In any case, don't blame overlays for avoiding more fully defining connector bindings.

Quoted 10 lines

From a user point of view whether having a patched up DTS or a boot loader modifying the DTB at run-time does not really matter as these boards are non-discoverable anyway. The boot loader will now know if they are there or not. What should the user do? Should they send command line arguments to U-Boot to say that we have the secure96 board? Flash different boot loaders depending on what board(s) are connected? That is even more awkward (IMO) than just modifying and redeploying the DTB.

Ideally, it would be as simple as editing a syslinux style menu text file or setting an EFI variable. But yes, we do need to define exactly how that is done. It's something on the todo list for EBBR, but not going to happen until after the 1st release.

Quoted 20 lines

The bright side of this patch set is that the user boots and the kernel is aware of there being a connector and presents sysfs files to populate the boards.

User goes "hm OK I have a secure96":
cd /sys/bus/platform/devices/connector
echo 1 > secure96

And there it populates.

No special boot loaders. No special tools.

Quoted 5 lines

That punts all the issues around overlays like designing a userspace interface, where overlays are located (filesystem, passed from bootloader, built into the kernel), when they are loaded, and how to specify which overlays to load. Most of Frank's list is related to these issues.

And that is where the user (also me) stops short.

Quoted 9 lines

Now I want to plug this board. OK download device tree compiler, author a fragment, compile it, compile a special userspace for inserting it into the right node, flash filesystem with that new userpace tool, also do not forget the DTB fragment, parameterize that tool to load the fragment into the connector node. Maybe the user need to change stuff on the fly? Hm then they need a text editor and a DT compiler on the target too, OK things like that can be done.

With your series, they'd just have to edit and rebuild the kernel...

Quoted 9 lines

Admittedly the above is more versatile. Probably awesome when you need to populate a device forest on an FPGA.

But is that even a realistic usecase? And what about the average plug-in board user? If they can do the population by compiling a kernel driver for their board and say it's there and populate it with a simple echo into a sysfs file they will be happy.

Only a kernel developer would think compiling a kernel driver makes for a good usecase.

For users, I think all the board dtbs have to be on the filesystem and the user only has to set which ones to apply (when there is no eeprom to allow doing that automatically). That's essentially what you have on RPi today (though I've got issues with some of their overlays, but that's a whole other can of worms).

Quoted 4 lines

The other user usecase I think is custom or prototyping boards. For those cases, we probably do want some run-time interface which could be a kernel driver (as you have) or configfs overlay interface. But I'd start with the first usecase and worry about this one later.

Pantelis had (I believe still have) configs overlay interface already. At least we are keep having it in xilinx soc tree.

Thanks,
Michal

#36 lore raw

cover RFC: Mezzanine handling for 96boards

In reply to Linus Walleij
Quoted 4 lines · Linus Walleij

This is a proposal for how to handle the non-discoverable 96boards plug-in expansion boards called "mezzanines" in the Linux kernel. It is a working RFC series meant for discussion at the moment.

< snip >

Quoted 11 lines

So for that reason, or other predictable statements such as "you're reinventing board files", I'd like to have an open discussion on how to actually support these boards with the mainline kernel and work on device drivers common with other systems now, and not in 2020 when they are already obsolete.

Yeah it is a bit controversial, but what we are doing right now for non-discoverable expansion boards isn't working in my opinion, so I have to throw something out there, and this is it.

< snip >

why can't a devicetree description of the devices on the mezzanine board be used?

I do understand the desire to describe interchangeable mezzanine boards separately from the base devicetree, such as in an overlay. Overlays can be applied today by U-boot before the Linux kernel is booted, so lack of being able to apply an overlay after Linux boot completes is not a blocker.

-Frank