All of lore.kernel.org
 help / color / mirror / Atom feed
* Add Allwinner Q8 tablets hardware manager
@ 2016-10-14  7:53 ` Hans de Goede
  0 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-14  7:53 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland, Arnd Bergmann, Greg Kroah-Hartman
  Cc: Maxime Ripard, Chen-Yu Tsai,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree

Hi Rob, Mark, et al.,

Here is a first non RFC posting of my q8 tablet hardwaremanager work,
both the bindings as well as the in kernel implementation of it.

Mark, I know that we discussed this at ELCE and you clearly indicated
that according to you this does not belong in the kernel. I was a bit
surprised by this part of the discussion.

I had posted a RFC earlier and Rob had indicated that given that the q8
tablets are a special case, as my code uses actual probing rather then some
pre-arranged id mechanism with say an eeprom, that doing this in a
non-generic manner would be ok for my special case.

So at ELCE I did not have all the arguments I had to do this in the kernel
ready. I did actually make a concious choice for the kernel before starting
work on this, thinking about this more I remembered most of the arguments I
had when making my u-boot vs kernel decision. I still believe the kernel is
the right place for this. See the list of reasons below.

Regardless of where the implementation should go, please do review the
bindings (the first patch in the set), as we need those regardless of where
the actual code dealing with this is going to live.

So on to why I believe that the kernel is the best place to do this, at least
for my special use-case:

1. Configurability

Since the q8 tablets do not have any id mechanism I'm probing i2c busses to
generate i2c client dt nodes with the right address and compatible.
Some info in these nodes (e.g. touchscreen firmware-name) is not probable at
all and gets set by heuristics. This heuristics may get things wrong.
So my current implementation offers kernel cmdline options to override this.

Although having to specify kernel cmdline options is not the plug and play
experience I want to give end-users most distros do have documentation on
how to do this and doing this is relatively easy for end-users. Moving this
to the bootloader means moving to some bootloader specific config mechanism
which is going to be quite hard (and possibly dangerous) for users to use.

This alone to me is the reason to post the kernel implentation of my work
for upstream inclusion despite of Mark's objections.

2. Upgradability

Most users treat the bootloader like they treat an x86 machine BIOS/EFI,
they will never upgrade it unless they really have to. This means that it
will be very difficult to get users to actual benefit from bug-fixes /
improvements done to the probing code. Where as the kernel on boards running
e.g. Debian or Fedora gets regular updates together with the rest of the
system.

3. Infrastructure

The kernel simply has better infrastructure for doing these kind of things.
Yes we could improve the bootloader, but the kernel is also improving and
likely at a faster rate. Besides that the purpose of the bootloader is
mostly to be simple and small, load the kernel and get out of the way, not
to be a general purpose os kernel. So it will simply always have less
infrastructure and that is a good thing, otherwise we will be writing
another general purpose os which is a waste of effort.

4. This is not a new board file

Mark, at ELCE I got the feeling that your biggest worry / objection is
that this will bring back board files, but that is not the case, if you
look at the actual code it is nothing like a board-file at all. Where a
board file was instantiating device after device after device from c-code,
with maybe a few if-s in there to deal with board revisions. This code is
all about figuring out which accelerometer and touchscreen there are,
to then add nodes to the dt for this 2 devices, almost all the code is
probing, the actual dt modifying code is tiny and no direct device
instantiation is done at all.

5. This is an exception, not the rule

Yes this is introducing board (family of boards) specific c-code into the
kernel, so in a way it is reminiscent of board files. But sometimes this is
necessary, just look at all the vendor / platform specific code in the kernel
in drivers/platform/x86, or all the places where DMI strings are used to
uniquely identify a x86 board and adjust behavior.

But this really is the exception, not the rule. I've written/upstreamed a
number of drivers for q8 tablets hardware and if you look at e.g. the
silead touchscreen driver then in linux-next this is already used for 5
ARM dts files where no board specific C-code is involved at all.

So this again is very different from the board file era, where C-code
had to be used to fill device specific platform-data structs, here all
necessary info is contained in the dt-binding and there are many users
who do not need any board specific C-code in the kernel at all.

So dt is working as it should and is avoiding board specific C-code for
the majority of the cases. But sometimes hardware is not as we ideally
would like it to be; and for those *exceptions* we are sometimes going
to need C-code in the kernel, just like there is "board" specific C-code
in the x86 code.

Regards,

Hans

p.s.

Note that the patches actually implementing the q8 hardware manager depend
on Pantelis' "of: changesets" patches which are not upstream yet, so if we
can agree on doing this in the kernel then this cannot be merged until those
are merged. If we get a concensus on doing this in kernel being ok, then
I'll post a new version of those patches unless Pantelis' beats me to it.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-14  7:53 ` Hans de Goede
  0 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-14  7:53 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Rob, Mark, et al.,

Here is a first non RFC posting of my q8 tablet hardwaremanager work,
both the bindings as well as the in kernel implementation of it.

Mark, I know that we discussed this at ELCE and you clearly indicated
that according to you this does not belong in the kernel. I was a bit
surprised by this part of the discussion.

I had posted a RFC earlier and Rob had indicated that given that the q8
tablets are a special case, as my code uses actual probing rather then some
pre-arranged id mechanism with say an eeprom, that doing this in a
non-generic manner would be ok for my special case.

So at ELCE I did not have all the arguments I had to do this in the kernel
ready. I did actually make a concious choice for the kernel before starting
work on this, thinking about this more I remembered most of the arguments I
had when making my u-boot vs kernel decision. I still believe the kernel is
the right place for this. See the list of reasons below.

Regardless of where the implementation should go, please do review the
bindings (the first patch in the set), as we need those regardless of where
the actual code dealing with this is going to live.

So on to why I believe that the kernel is the best place to do this, at least
for my special use-case:

1. Configurability

Since the q8 tablets do not have any id mechanism I'm probing i2c busses to
generate i2c client dt nodes with the right address and compatible.
Some info in these nodes (e.g. touchscreen firmware-name) is not probable at
all and gets set by heuristics. This heuristics may get things wrong.
So my current implementation offers kernel cmdline options to override this.

Although having to specify kernel cmdline options is not the plug and play
experience I want to give end-users most distros do have documentation on
how to do this and doing this is relatively easy for end-users. Moving this
to the bootloader means moving to some bootloader specific config mechanism
which is going to be quite hard (and possibly dangerous) for users to use.

This alone to me is the reason to post the kernel implentation of my work
for upstream inclusion despite of Mark's objections.

2. Upgradability

Most users treat the bootloader like they treat an x86 machine BIOS/EFI,
they will never upgrade it unless they really have to. This means that it
will be very difficult to get users to actual benefit from bug-fixes /
improvements done to the probing code. Where as the kernel on boards running
e.g. Debian or Fedora gets regular updates together with the rest of the
system.

3. Infrastructure

The kernel simply has better infrastructure for doing these kind of things.
Yes we could improve the bootloader, but the kernel is also improving and
likely at a faster rate. Besides that the purpose of the bootloader is
mostly to be simple and small, load the kernel and get out of the way, not
to be a general purpose os kernel. So it will simply always have less
infrastructure and that is a good thing, otherwise we will be writing
another general purpose os which is a waste of effort.

4. This is not a new board file

Mark, at ELCE I got the feeling that your biggest worry / objection is
that this will bring back board files, but that is not the case, if you
look at the actual code it is nothing like a board-file at all. Where a
board file was instantiating device after device after device from c-code,
with maybe a few if-s in there to deal with board revisions. This code is
all about figuring out which accelerometer and touchscreen there are,
to then add nodes to the dt for this 2 devices, almost all the code is
probing, the actual dt modifying code is tiny and no direct device
instantiation is done at all.

5. This is an exception, not the rule

Yes this is introducing board (family of boards) specific c-code into the
kernel, so in a way it is reminiscent of board files. But sometimes this is
necessary, just look at all the vendor / platform specific code in the kernel
in drivers/platform/x86, or all the places where DMI strings are used to
uniquely identify a x86 board and adjust behavior.

But this really is the exception, not the rule. I've written/upstreamed a
number of drivers for q8 tablets hardware and if you look at e.g. the
silead touchscreen driver then in linux-next this is already used for 5
ARM dts files where no board specific C-code is involved at all.

So this again is very different from the board file era, where C-code
had to be used to fill device specific platform-data structs, here all
necessary info is contained in the dt-binding and there are many users
who do not need any board specific C-code in the kernel at all.

So dt is working as it should and is avoiding board specific C-code for
the majority of the cases. But sometimes hardware is not as we ideally
would like it to be; and for those *exceptions* we are sometimes going
to need C-code in the kernel, just like there is "board" specific C-code
in the x86 code.

Regards,

Hans

p.s.

Note that the patches actually implementing the q8 hardware manager depend
on Pantelis' "of: changesets" patches which are not upstream yet, so if we
can agree on doing this in the kernel then this cannot be merged until those
are merged. If we get a concensus on doing this in kernel being ok, then
I'll post a new version of those patches unless Pantelis' beats me to it.

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

* [PATCH 1/6] dt: bindings: Add Allwinner Q8 tablets hardware manager bindings
  2016-10-14  7:53 ` Hans de Goede
@ 2016-10-14  7:53     ` Hans de Goede
  -1 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-14  7:53 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland, Arnd Bergmann, Greg Kroah-Hartman
  Cc: Maxime Ripard, Chen-Yu Tsai,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
	Hans de Goede

Allwinnner A13 / A23 / A33 based Q8 tablets are popular cheap 7" tablets
of which a new batch is produced every few weeks. Each batch uses a
different mix of touchscreen, accelerometer and wifi peripherals.

Given that each batch is different creating a devicetree for each variant
is not desirable, work is being done on a Q8 tablet hardware manager which
auto-detects the touchscreen and accelerometer and will update the dt with
what it has found, so that a single generic dt can be used for these tablets.

This commit adds dt-bindings for this hardware manager.

Note the wifi is connected to a discoverable bus (sdio or usb) and will be
autodetected by the mmc resp. usb subsystems.

Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 .../misc/allwinner,sunxi-q8-hardwaremgr.txt        | 71 ++++++++++++++++++++++
 1 file changed, 71 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt

diff --git a/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt b/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt
new file mode 100644
index 0000000..a81b258
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt
@@ -0,0 +1,71 @@
+Q8 tablet hardware manager
+--------------------------
+
+Allwinnner A13 / A23 / A33 based Q8 tablets are popular cheap 7" tablets of
+which a new batch is produced every few weeks. Each batch uses a different
+mix of touchscreen, accelerometer and wifi peripherals.
+
+Given that each batch is different creating a devicetree for each variant is
+not desirable. The Q8 tablet hardware manager bindings are bindings for an os
+module which auto-detects the touchscreen and accelerometer so that a single
+generic dts can be used for these tablets.
+
+The wifi is connected to a discoverable bus and will be autodetected by the os.
+
+Required properties:
+ - toplevel / machine compatible, one of:
+	"allwinner,q8-a13"
+	"allwinner,q8-a23"
+	"allwinner,q8-a33"
+ - touchscreen node   : There must be a template touchscreen node named
+			"touchscreen", this must be a child node of the
+			touchscreen i2c bus
+ - accelerometer node : There must be a template accelerometer node named
+			"accelerometer", this must be a child node of the
+			accelerometer i2c bus
+
+touchscreen node required properties:
+ - interrupt-parent   : phandle pointing to the interrupt controller
+			serving the touchscreen interrupt
+ - interrupts         : interrupt specification for the touchscreen interrupt
+ - power-gpios        : Specification for the pin connected to the touchscreen's
+			enable / wake pin. This needs to be driven high to
+			enable the touchscreen controller
+
+touchscreen node optional properties:
+ - vddio-supply       : regulator phandle for the touchscreen vddio supply
+
+accelerometer node optional properties:
+ - interrupt-parent   : phandle pointing to the interrupt controller
+			serving the accelerometer interrupt
+ - interrupts         : interrupt specification for the accelerometer interrupt
+
+Example:
+
+/ {
+	compatible = "allwinner,q8-a23", "allwinner,sun8i-a23";
+};
+
+&i2c0 {
+	touchscreen: touchscreen@0 {
+		interrupt-parent = <&pio>;
+		interrupts = <1 5 IRQ_TYPE_EDGE_FALLING>; /* PB5 */
+		power-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
+		vddio-supply = <&reg_ldo_io1>;
+		/*
+		 * Enabled by sunxi-q8-hardwaremgr if it detects a
+		 * known model touchscreen.
+		 */
+		status = "disabled";
+	};
+};
+
+&i2c1 {
+	accelerometer: accelerometer@0 {
+		/*
+		 * Enabled by sunxi-q8-hardwaremgr if it detects a
+		 * known model accelerometer.
+		 */
+		status = "disabled";
+	};
+};
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 1/6] dt: bindings: Add Allwinner Q8 tablets hardware manager bindings
@ 2016-10-14  7:53     ` Hans de Goede
  0 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-14  7:53 UTC (permalink / raw)
  To: linux-arm-kernel

Allwinnner A13 / A23 / A33 based Q8 tablets are popular cheap 7" tablets
of which a new batch is produced every few weeks. Each batch uses a
different mix of touchscreen, accelerometer and wifi peripherals.

Given that each batch is different creating a devicetree for each variant
is not desirable, work is being done on a Q8 tablet hardware manager which
auto-detects the touchscreen and accelerometer and will update the dt with
what it has found, so that a single generic dt can be used for these tablets.

This commit adds dt-bindings for this hardware manager.

Note the wifi is connected to a discoverable bus (sdio or usb) and will be
autodetected by the mmc resp. usb subsystems.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 .../misc/allwinner,sunxi-q8-hardwaremgr.txt        | 71 ++++++++++++++++++++++
 1 file changed, 71 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt

diff --git a/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt b/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt
new file mode 100644
index 0000000..a81b258
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt
@@ -0,0 +1,71 @@
+Q8 tablet hardware manager
+--------------------------
+
+Allwinnner A13 / A23 / A33 based Q8 tablets are popular cheap 7" tablets of
+which a new batch is produced every few weeks. Each batch uses a different
+mix of touchscreen, accelerometer and wifi peripherals.
+
+Given that each batch is different creating a devicetree for each variant is
+not desirable. The Q8 tablet hardware manager bindings are bindings for an os
+module which auto-detects the touchscreen and accelerometer so that a single
+generic dts can be used for these tablets.
+
+The wifi is connected to a discoverable bus and will be autodetected by the os.
+
+Required properties:
+ - toplevel / machine compatible, one of:
+	"allwinner,q8-a13"
+	"allwinner,q8-a23"
+	"allwinner,q8-a33"
+ - touchscreen node   : There must be a template touchscreen node named
+			"touchscreen", this must be a child node of the
+			touchscreen i2c bus
+ - accelerometer node : There must be a template accelerometer node named
+			"accelerometer", this must be a child node of the
+			accelerometer i2c bus
+
+touchscreen node required properties:
+ - interrupt-parent   : phandle pointing to the interrupt controller
+			serving the touchscreen interrupt
+ - interrupts         : interrupt specification for the touchscreen interrupt
+ - power-gpios        : Specification for the pin connected to the touchscreen's
+			enable / wake pin. This needs to be driven high to
+			enable the touchscreen controller
+
+touchscreen node optional properties:
+ - vddio-supply       : regulator phandle for the touchscreen vddio supply
+
+accelerometer node optional properties:
+ - interrupt-parent   : phandle pointing to the interrupt controller
+			serving the accelerometer interrupt
+ - interrupts         : interrupt specification for the accelerometer interrupt
+
+Example:
+
+/ {
+	compatible = "allwinner,q8-a23", "allwinner,sun8i-a23";
+};
+
+&i2c0 {
+	touchscreen: touchscreen at 0 {
+		interrupt-parent = <&pio>;
+		interrupts = <1 5 IRQ_TYPE_EDGE_FALLING>; /* PB5 */
+		power-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
+		vddio-supply = <&reg_ldo_io1>;
+		/*
+		 * Enabled by sunxi-q8-hardwaremgr if it detects a
+		 * known model touchscreen.
+		 */
+		status = "disabled";
+	};
+};
+
+&i2c1 {
+	accelerometer: accelerometer at 0 {
+		/*
+		 * Enabled by sunxi-q8-hardwaremgr if it detects a
+		 * known model accelerometer.
+		 */
+		status = "disabled";
+	};
+};
-- 
2.9.3

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

* [PATCH 2/6] misc: Add Allwinner Q8 tablet hardware manager
  2016-10-14  7:53 ` Hans de Goede
@ 2016-10-14  7:53     ` Hans de Goede
  -1 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-14  7:53 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland, Arnd Bergmann, Greg Kroah-Hartman
  Cc: Maxime Ripard, Chen-Yu Tsai,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
	Hans de Goede

Allwinnner A13 / A23 / A33 based Q8 tablets are popular cheap 7" tablets
of which a new batch is produced every few weeks. Each batch uses a
different mix of touchscreen, accelerometer and wifi peripherals.

Given that each batch is different creating a devicetree for each variant
is not desirable. This commit adds a Q8 tablet hardware manager which
auto-detects the touchscreen and accelerometer so that a single generic
dts can be used for these tablets.

The wifi is connected to a discoverable bus (sdio or usb) and will be
autodetected by the mmc resp. usb subsystems.

Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 drivers/misc/Kconfig          |  11 +
 drivers/misc/Makefile         |   1 +
 drivers/misc/q8-hardwaremgr.c | 581 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 593 insertions(+)
 create mode 100644 drivers/misc/q8-hardwaremgr.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index d002528..d6c1529 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -794,6 +794,17 @@ config PANEL_BOOT_MESSAGE
 	  An empty message will only clear the display at driver init time. Any other
 	  printf()-formatted message is valid with newline and escape codes.
 
+config Q8_HARDWAREMGR
+	bool "Allwinner Q8 tablet hardware manager"
+	depends on I2C
+	depends on (ARCH_SUNXI && GPIOLIB && OF && OF_DYNAMIC) || COMPILE_TEST
+	default	n
+	help
+	  This option enables support for autodetecting the touchscreen
+	  on Allwinner Q8 tablets.
+
+	  If unsure, say N.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index fb32516..1a0ebb0 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_ECHO)		+= echo/
 obj-$(CONFIG_VEXPRESS_SYSCFG)	+= vexpress-syscfg.o
 obj-$(CONFIG_CXL_BASE)		+= cxl/
 obj-$(CONFIG_PANEL)             += panel.o
+obj-$(CONFIG_Q8_HARDWAREMGR)    += q8-hardwaremgr.o
 
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_core.o
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_bugs.o
diff --git a/drivers/misc/q8-hardwaremgr.c b/drivers/misc/q8-hardwaremgr.c
new file mode 100644
index 0000000..346102d
--- /dev/null
+++ b/drivers/misc/q8-hardwaremgr.c
@@ -0,0 +1,581 @@
+/*
+ * Allwinner q8 formfactor tablet hardware manager
+ *
+ * Copyright (C) 2016 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/unaligned.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+/*
+ * We can detect which touchscreen controller is used automatically,
+ * but some controllers can be wired up differently depending on the
+ * q8 PCB variant used, so they need different firmware files / settings.
+ *
+ * We allow the user to specify a firmware_variant to select a config
+ * from a list of known configs. We also allow overriding each setting
+ * individually.
+ */
+
+static int touchscreen_variant = -1;
+module_param(touchscreen_variant, int, 0444);
+MODULE_PARM_DESC(touchscreen_variant, "Touchscreen variant 0-x, -1 for auto");
+
+static int touchscreen_width = -1;
+module_param(touchscreen_width, int, 0444);
+MODULE_PARM_DESC(touchscreen_width, "Touchscreen width, -1 for auto");
+
+static int touchscreen_height = -1;
+module_param(touchscreen_height, int, 0444);
+MODULE_PARM_DESC(touchscreen_height, "Touchscreen height, -1 for auto");
+
+static int touchscreen_invert_x = -1;
+module_param(touchscreen_invert_x, int, 0444);
+MODULE_PARM_DESC(touchscreen_invert_x, "Touchscreen invert x, -1 for auto");
+
+static int touchscreen_invert_y = -1;
+module_param(touchscreen_invert_y, int, 0444);
+MODULE_PARM_DESC(touchscreen_invert_y, "Touchscreen invert y, -1 for auto");
+
+static int touchscreen_swap_x_y = -1;
+module_param(touchscreen_swap_x_y, int, 0444);
+MODULE_PARM_DESC(touchscreen_swap_x_y, "Touchscreen swap x y, -1 for auto");
+
+static char *touchscreen_fw_name;
+module_param(touchscreen_fw_name, charp, 0444);
+MODULE_PARM_DESC(touchscreen_fw_name, "Touchscreen firmware filename");
+
+enum soc {
+	a13,
+	a23,
+	a33,
+};
+
+#define TOUCHSCREEN_POWER_ON_DELAY	20
+#define SILEAD_REG_ID			0xFC
+#define EKTF2127_RESPONSE		0x52
+#define EKTF2127_REQUEST		0x53
+#define EKTF2127_WIDTH			0x63
+
+enum {
+	touchscreen_unknown,
+	gsl1680_a082,
+	gsl1680_b482,
+	ektf2127,
+	zet6251,
+};
+
+struct q8_hardwaremgr_device {
+	int model;
+	int addr;
+	const char *compatible;
+	bool delete_regulator;
+};
+
+struct q8_hardwaremgr_data {
+	struct device *dev;
+	enum soc soc;
+	struct q8_hardwaremgr_device touchscreen;
+	int touchscreen_variant;
+	int touchscreen_width;
+	int touchscreen_height;
+	int touchscreen_invert_x;
+	int touchscreen_invert_y;
+	int touchscreen_swap_x_y;
+	const char *touchscreen_fw_name;
+};
+
+typedef int (*bus_probe_func)(struct q8_hardwaremgr_data *data,
+			      struct i2c_adapter *adap);
+typedef int (*client_probe_func)(struct q8_hardwaremgr_data *data,
+				 struct i2c_client *client);
+
+static struct device_node *q8_hardware_mgr_apply_common(
+	struct q8_hardwaremgr_device *dev, struct of_changeset *cset,
+	const char *prefix)
+{
+	struct device_node *np;
+
+	np = of_find_node_by_name(of_root, prefix);
+	/* Never happens already checked in q8_hardwaremgr_do_probe() */
+	if (WARN_ON(!np))
+		return NULL;
+
+	of_changeset_init(cset);
+	of_changeset_add_property_u32(cset, np, "reg", dev->addr);
+	of_changeset_add_property_string(cset, np, "compatible",
+					 dev->compatible);
+	of_changeset_update_property_string(cset, np, "status", "okay");
+
+	if (dev->delete_regulator) {
+		struct property *p;
+
+		p = of_find_property(np, "vddio-supply", NULL);
+		/* Never happens already checked in q8_hardwaremgr_do_probe() */
+		if (WARN_ON(!p))
+			return np;
+
+		of_changeset_remove_property(cset, np, p);
+	}
+
+	return np; /* Allow the caller to make further changes */
+}
+
+static int q8_hardwaremgr_probe_client(struct q8_hardwaremgr_data *data,
+				       struct q8_hardwaremgr_device *dev,
+				       struct i2c_adapter *adap, u16 addr,
+				       client_probe_func client_probe)
+{
+	struct i2c_client *client;
+	int ret;
+
+	client = i2c_new_dummy(adap, addr);
+	if (!client)
+		return -ENOMEM;
+
+	/* ret will be one of 0: Success, -ETIMEDOUT: Bus stuck or -ENODEV */
+	ret = client_probe(data, client);
+	if (ret == 0)
+		dev->addr = addr;
+
+	i2c_unregister_device(client);
+
+	return ret;
+}
+
+#define PROBE_CLIENT(dev, addr, probe) \
+{ \
+	int ret = q8_hardwaremgr_probe_client(data, dev, adap, addr, probe); \
+	if (ret != -ENODEV) \
+		return ret; \
+}
+
+static int q8_hardwaremgr_probe_silead(struct q8_hardwaremgr_data *data,
+				       struct i2c_client *client)
+{
+	__le32 chip_id;
+	int ret;
+
+	ret = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_ID,
+					    sizeof(chip_id), (u8 *)&chip_id);
+	if (ret != sizeof(chip_id))
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+
+	switch (le32_to_cpu(chip_id)) {
+	case 0xa0820000:
+		data->touchscreen.compatible = "silead,gsl1680";
+		data->touchscreen.model = gsl1680_a082;
+		dev_info(data->dev, "Silead touchscreen ID: 0xa0820000\n");
+		return 0;
+	case 0xb4820000:
+		data->touchscreen.compatible = "silead,gsl1680";
+		data->touchscreen.model = gsl1680_b482;
+		dev_info(data->dev, "Silead touchscreen ID: 0xb4820000\n");
+		return 0;
+	default:
+		dev_warn(data->dev, "Silead? touchscreen with unknown ID: 0x%08x\n",
+			 le32_to_cpu(chip_id));
+	}
+
+	return -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_ektf2127(struct q8_hardwaremgr_data *data,
+					 struct i2c_client *client)
+{
+	unsigned char buff[4];
+	int ret;
+
+	/* Read hello, ignore data, depends on initial power state */
+	ret = i2c_master_recv(client, buff, 4);
+	if (ret != 4)
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+
+	/* Request width */
+	buff[0] = EKTF2127_REQUEST;
+	buff[1] = EKTF2127_WIDTH;
+	buff[2] = 0x00;
+	buff[3] = 0x00;
+	ret = i2c_master_send(client, buff, 4);
+	if (ret != 4)
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+
+	msleep(20);
+
+	/* Read response */
+	ret = i2c_master_recv(client, buff, 4);
+	if (ret != 4)
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+
+	if (buff[0] == EKTF2127_RESPONSE && buff[1] == EKTF2127_WIDTH) {
+		data->touchscreen.compatible = "elan,ektf2127";
+		data->touchscreen.model = ektf2127;
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_zet6251(struct q8_hardwaremgr_data *data,
+					struct i2c_client *client)
+{
+	unsigned char buff[4];
+	int ret;
+
+	/*
+	 * We only do a simple read finger data packet test, because some
+	 * versions require firmware to be loaded. If no firmware is loaded
+	 * the buffer will be filed with 0xff, so we ignore the contents.
+	 */
+	ret = i2c_master_recv(client, buff, 24);
+	if (ret != 24)
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+
+	data->touchscreen.compatible = "zeitec,zet6251";
+	data->touchscreen.model = zet6251;
+	return 0;
+}
+
+static int q8_hardwaremgr_probe_touchscreen(struct q8_hardwaremgr_data *data,
+					    struct i2c_adapter *adap)
+{
+	msleep(TOUCHSCREEN_POWER_ON_DELAY);
+
+	PROBE_CLIENT(&data->touchscreen, 0x40, q8_hardwaremgr_probe_silead);
+	PROBE_CLIENT(&data->touchscreen, 0x15, q8_hardwaremgr_probe_ektf2127);
+	PROBE_CLIENT(&data->touchscreen, 0x76, q8_hardwaremgr_probe_zet6251);
+
+	return -ENODEV;
+}
+
+static void q8_hardwaremgr_apply_gsl1680_a082_variant(
+	struct q8_hardwaremgr_data *data)
+{
+	if (touchscreen_variant != -1)
+		data->touchscreen_variant = touchscreen_variant;
+
+	switch (data->touchscreen_variant) {
+	default:
+		dev_warn(data->dev, "Error unknown touchscreen_variant %d using 0\n",
+			 touchscreen_variant);
+		/* Fall through */
+	case 0:
+		data->touchscreen_width = 1024;
+		data->touchscreen_height = 600;
+		data->touchscreen_fw_name = "gsl1680-a082-q8-700.fw";
+		break;
+	case 1:
+		data->touchscreen_width = 480;
+		data->touchscreen_height = 800;
+		data->touchscreen_swap_x_y = 1;
+		data->touchscreen_fw_name = "gsl1680-a082-q8-a70.fw";
+		break;
+	}
+}
+
+static void q8_hardwaremgr_apply_gsl1680_b482_variant(
+	struct q8_hardwaremgr_data *data)
+{
+	if (touchscreen_variant != -1)
+		data->touchscreen_variant = touchscreen_variant;
+
+	switch (data->touchscreen_variant) {
+	default:
+		dev_warn(data->dev, "Error unknown touchscreen_variant %d using 0\n",
+			 touchscreen_variant);
+		/* Fall through */
+	case 0:
+		data->touchscreen_width = 960;
+		data->touchscreen_height = 640;
+		data->touchscreen_fw_name = "gsl1680-b482-q8-d702.fw";
+		break;
+	case 1:
+		data->touchscreen_width = 960;
+		data->touchscreen_height = 640;
+		data->touchscreen_fw_name = "gsl1680-b482-q8-a70.fw";
+		break;
+	}
+}
+
+static void q8_hardwaremgr_issue_gsl1680_warning(
+	struct q8_hardwaremgr_data *data)
+{
+	dev_warn(data->dev, "gsl1680 touchscreen may require kernel cmdline parameters to function properly\n");
+	dev_warn(data->dev, "Try q8_hardwaremgr.touchscreen_invert_x=%d if x coordinates are inverted\n",
+		 !data->touchscreen_invert_x);
+	dev_warn(data->dev, "Try q8_hardwaremgr.touchscreen_variant=%d if coordinates are all over the place\n",
+		 !data->touchscreen_variant);
+
+#define	show(x) \
+	dev_info(data->dev, #x " %d (%s)\n", data->x, \
+		 (x == -1) ? "auto" : "user supplied")
+
+	show(touchscreen_variant);
+	show(touchscreen_width);
+	show(touchscreen_height);
+	show(touchscreen_invert_x);
+	show(touchscreen_invert_y);
+	show(touchscreen_swap_x_y);
+	dev_info(data->dev, "touchscreen_fw_name %s (%s)\n",
+		 data->touchscreen_fw_name,
+		 (touchscreen_fw_name == NULL) ? "auto" : "user supplied");
+#undef show
+}
+
+static void q8_hardwaremgr_apply_touchscreen(struct q8_hardwaremgr_data *data)
+{
+	struct of_changeset cset;
+	struct device_node *np;
+
+	switch (data->touchscreen.model) {
+	case touchscreen_unknown:
+		return;
+	case gsl1680_a082:
+		q8_hardwaremgr_apply_gsl1680_a082_variant(data);
+		break;
+	case gsl1680_b482:
+		q8_hardwaremgr_apply_gsl1680_b482_variant(data);
+		break;
+	case ektf2127:
+	case zet6251:
+		/* These have only 1 variant */
+		break;
+	}
+
+	if (touchscreen_width != -1)
+		data->touchscreen_width = touchscreen_width;
+
+	if (touchscreen_height != -1)
+		data->touchscreen_height = touchscreen_height;
+
+	if (touchscreen_invert_x != -1)
+		data->touchscreen_invert_x = touchscreen_invert_x;
+
+	if (touchscreen_invert_y != -1)
+		data->touchscreen_invert_y = touchscreen_invert_y;
+
+	if (touchscreen_swap_x_y != -1)
+		data->touchscreen_swap_x_y = touchscreen_swap_x_y;
+
+	if (touchscreen_fw_name)
+		data->touchscreen_fw_name = touchscreen_fw_name;
+
+	if (data->touchscreen.model == gsl1680_a082 ||
+	    data->touchscreen.model == gsl1680_b482)
+		q8_hardwaremgr_issue_gsl1680_warning(data);
+
+	np = q8_hardware_mgr_apply_common(&data->touchscreen, &cset,
+					  "touchscreen");
+	if (!np)
+		return;
+
+	if (data->touchscreen_width)
+		of_changeset_add_property_u32(&cset, np, "touchscreen-size-x",
+					      data->touchscreen_width);
+	if (data->touchscreen_height)
+		of_changeset_add_property_u32(&cset, np, "touchscreen-size-y",
+					      data->touchscreen_height);
+	if (data->touchscreen_invert_x)
+		of_changeset_add_property_bool(&cset, np,
+					       "touchscreen-inverted-x");
+	if (data->touchscreen_invert_y)
+		of_changeset_add_property_bool(&cset, np,
+					       "touchscreen-inverted-y");
+	if (data->touchscreen_swap_x_y)
+		of_changeset_add_property_bool(&cset, np,
+					       "touchscreen-swapped-x-y");
+	if (data->touchscreen_fw_name)
+		of_changeset_add_property_string(&cset, np, "firmware-name",
+						 data->touchscreen_fw_name);
+
+	of_changeset_apply(&cset);
+
+	of_node_put(np);
+}
+
+static int q8_hardwaremgr_do_probe(struct q8_hardwaremgr_data *data,
+				   struct q8_hardwaremgr_device *dev,
+				   const char *prefix, bus_probe_func func)
+{
+	struct device_node *np;
+	struct i2c_adapter *adap;
+	struct regulator *reg;
+	struct gpio_desc *gpio;
+	int ret = 0;
+
+	np = of_find_node_by_name(of_root, prefix);
+	if (!np) {
+		dev_err(data->dev, "Error %s node is missing\n", prefix);
+		return -EINVAL;
+	}
+
+	/*
+	 * Patch the dt_node into our device since there is no device for
+	 * the probed hw yet (status = disabled) .
+	 */
+	data->dev->of_node = np;
+
+	ret = pinctrl_bind_pins(data->dev);
+	if (ret)
+		goto put_node;
+
+	adap = of_get_i2c_adapter_by_node(np->parent);
+	if (!adap) {
+		ret = -EPROBE_DEFER;
+		goto put_pins;
+	}
+
+	reg = regulator_get_optional(data->dev, "vddio");
+	if (IS_ERR(reg)) {
+		ret = PTR_ERR(reg);
+		if (ret == -EPROBE_DEFER)
+			goto put_adapter;
+		reg = NULL;
+	}
+
+	gpio = fwnode_get_named_gpiod(&np->fwnode, "power-gpios");
+	if (IS_ERR(gpio)) {
+		ret = PTR_ERR(gpio);
+		if (ret == -EPROBE_DEFER)
+			goto put_reg;
+		gpio = NULL;
+	}
+
+	/* First try with only the power gpio driven high */
+	if (gpio) {
+		ret = gpiod_direction_output(gpio, 1);
+		if (ret)
+			goto put_gpio;
+	}
+
+	dev_info(data->dev, "Probing %s without a regulator\n", prefix);
+	ret = func(data, adap);
+	if (ret != 0 && reg) {
+		/* Second try, also enable the regulator */
+		ret = regulator_enable(reg);
+		if (ret)
+			goto restore_gpio;
+
+		dev_info(data->dev, "Probing %s with a regulator\n", prefix);
+		ret = func(data, adap);
+
+		regulator_disable(reg);
+	} else if (reg)
+		dev->delete_regulator = true; /* Regulator not needed */
+
+	if (ret == 0)
+		dev_info(data->dev, "Found %s at 0x%02x\n",
+			 dev->compatible, dev->addr);
+	else
+		ret = 0; /* Not finding a device is not an error */
+
+restore_gpio:
+	if (gpio)
+		gpiod_direction_output(gpio, 0);
+put_gpio:
+	if (gpio)
+		gpiod_put(gpio);
+put_reg:
+	if (reg)
+		regulator_put(reg);
+put_adapter:
+	i2c_put_adapter(adap);
+
+put_pins:
+	/* Undo our manual pinctrl_bind_pins() */
+	if (data->dev->pins) {
+		devm_pinctrl_put(data->dev->pins->p);
+		devm_kfree(data->dev, data->dev->pins);
+		data->dev->pins = NULL;
+	}
+
+put_node:
+	data->dev->of_node = NULL;
+	of_node_put(np);
+
+	return ret;
+}
+
+static int q8_hardwaremgr_probe(struct platform_device *pdev)
+{
+	struct q8_hardwaremgr_data *data;
+	int ret = 0;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->dev = &pdev->dev;
+	data->soc = (long)pdev->dev.platform_data;
+
+	ret = q8_hardwaremgr_do_probe(data, &data->touchscreen, "touchscreen",
+				      q8_hardwaremgr_probe_touchscreen);
+	if (ret)
+		goto error;
+
+	q8_hardwaremgr_apply_touchscreen(data);
+
+error:
+	kfree(data);
+
+	return ret;
+}
+
+static struct platform_driver q8_hardwaremgr_driver = {
+	.driver = {
+		.name	= "q8-hwmgr",
+	},
+	.probe	= q8_hardwaremgr_probe,
+};
+
+static int __init q8_hardwaremgr_init(void)
+{
+	struct platform_device *pdev;
+	enum soc soc;
+	int ret;
+
+	if (of_machine_is_compatible("allwinner,q8-a13"))
+		soc = a13;
+	else if (of_machine_is_compatible("allwinner,q8-a23"))
+		soc = a23;
+	else if (of_machine_is_compatible("allwinner,q8-a33"))
+		soc = a33;
+	else
+		return 0;
+
+	pdev = platform_device_alloc("q8-hwmgr", 0);
+	if (!pdev)
+		return -ENOMEM;
+
+	pdev->dev.platform_data = (void *)(long)soc;
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		return ret;
+
+	return platform_driver_register(&q8_hardwaremgr_driver);
+}
+
+device_initcall(q8_hardwaremgr_init);
+
+MODULE_DESCRIPTION("Allwinner q8 formfactor tablet hardware manager");
+MODULE_AUTHOR("Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>");
+MODULE_LICENSE("GPL");
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 2/6] misc: Add Allwinner Q8 tablet hardware manager
@ 2016-10-14  7:53     ` Hans de Goede
  0 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-14  7:53 UTC (permalink / raw)
  To: linux-arm-kernel

Allwinnner A13 / A23 / A33 based Q8 tablets are popular cheap 7" tablets
of which a new batch is produced every few weeks. Each batch uses a
different mix of touchscreen, accelerometer and wifi peripherals.

Given that each batch is different creating a devicetree for each variant
is not desirable. This commit adds a Q8 tablet hardware manager which
auto-detects the touchscreen and accelerometer so that a single generic
dts can be used for these tablets.

The wifi is connected to a discoverable bus (sdio or usb) and will be
autodetected by the mmc resp. usb subsystems.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/misc/Kconfig          |  11 +
 drivers/misc/Makefile         |   1 +
 drivers/misc/q8-hardwaremgr.c | 581 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 593 insertions(+)
 create mode 100644 drivers/misc/q8-hardwaremgr.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index d002528..d6c1529 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -794,6 +794,17 @@ config PANEL_BOOT_MESSAGE
 	  An empty message will only clear the display at driver init time. Any other
 	  printf()-formatted message is valid with newline and escape codes.
 
+config Q8_HARDWAREMGR
+	bool "Allwinner Q8 tablet hardware manager"
+	depends on I2C
+	depends on (ARCH_SUNXI && GPIOLIB && OF && OF_DYNAMIC) || COMPILE_TEST
+	default	n
+	help
+	  This option enables support for autodetecting the touchscreen
+	  on Allwinner Q8 tablets.
+
+	  If unsure, say N.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index fb32516..1a0ebb0 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_ECHO)		+= echo/
 obj-$(CONFIG_VEXPRESS_SYSCFG)	+= vexpress-syscfg.o
 obj-$(CONFIG_CXL_BASE)		+= cxl/
 obj-$(CONFIG_PANEL)             += panel.o
+obj-$(CONFIG_Q8_HARDWAREMGR)    += q8-hardwaremgr.o
 
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_core.o
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_bugs.o
diff --git a/drivers/misc/q8-hardwaremgr.c b/drivers/misc/q8-hardwaremgr.c
new file mode 100644
index 0000000..346102d
--- /dev/null
+++ b/drivers/misc/q8-hardwaremgr.c
@@ -0,0 +1,581 @@
+/*
+ * Allwinner q8 formfactor tablet hardware manager
+ *
+ * Copyright (C) 2016 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/unaligned.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+/*
+ * We can detect which touchscreen controller is used automatically,
+ * but some controllers can be wired up differently depending on the
+ * q8 PCB variant used, so they need different firmware files / settings.
+ *
+ * We allow the user to specify a firmware_variant to select a config
+ * from a list of known configs. We also allow overriding each setting
+ * individually.
+ */
+
+static int touchscreen_variant = -1;
+module_param(touchscreen_variant, int, 0444);
+MODULE_PARM_DESC(touchscreen_variant, "Touchscreen variant 0-x, -1 for auto");
+
+static int touchscreen_width = -1;
+module_param(touchscreen_width, int, 0444);
+MODULE_PARM_DESC(touchscreen_width, "Touchscreen width, -1 for auto");
+
+static int touchscreen_height = -1;
+module_param(touchscreen_height, int, 0444);
+MODULE_PARM_DESC(touchscreen_height, "Touchscreen height, -1 for auto");
+
+static int touchscreen_invert_x = -1;
+module_param(touchscreen_invert_x, int, 0444);
+MODULE_PARM_DESC(touchscreen_invert_x, "Touchscreen invert x, -1 for auto");
+
+static int touchscreen_invert_y = -1;
+module_param(touchscreen_invert_y, int, 0444);
+MODULE_PARM_DESC(touchscreen_invert_y, "Touchscreen invert y, -1 for auto");
+
+static int touchscreen_swap_x_y = -1;
+module_param(touchscreen_swap_x_y, int, 0444);
+MODULE_PARM_DESC(touchscreen_swap_x_y, "Touchscreen swap x y, -1 for auto");
+
+static char *touchscreen_fw_name;
+module_param(touchscreen_fw_name, charp, 0444);
+MODULE_PARM_DESC(touchscreen_fw_name, "Touchscreen firmware filename");
+
+enum soc {
+	a13,
+	a23,
+	a33,
+};
+
+#define TOUCHSCREEN_POWER_ON_DELAY	20
+#define SILEAD_REG_ID			0xFC
+#define EKTF2127_RESPONSE		0x52
+#define EKTF2127_REQUEST		0x53
+#define EKTF2127_WIDTH			0x63
+
+enum {
+	touchscreen_unknown,
+	gsl1680_a082,
+	gsl1680_b482,
+	ektf2127,
+	zet6251,
+};
+
+struct q8_hardwaremgr_device {
+	int model;
+	int addr;
+	const char *compatible;
+	bool delete_regulator;
+};
+
+struct q8_hardwaremgr_data {
+	struct device *dev;
+	enum soc soc;
+	struct q8_hardwaremgr_device touchscreen;
+	int touchscreen_variant;
+	int touchscreen_width;
+	int touchscreen_height;
+	int touchscreen_invert_x;
+	int touchscreen_invert_y;
+	int touchscreen_swap_x_y;
+	const char *touchscreen_fw_name;
+};
+
+typedef int (*bus_probe_func)(struct q8_hardwaremgr_data *data,
+			      struct i2c_adapter *adap);
+typedef int (*client_probe_func)(struct q8_hardwaremgr_data *data,
+				 struct i2c_client *client);
+
+static struct device_node *q8_hardware_mgr_apply_common(
+	struct q8_hardwaremgr_device *dev, struct of_changeset *cset,
+	const char *prefix)
+{
+	struct device_node *np;
+
+	np = of_find_node_by_name(of_root, prefix);
+	/* Never happens already checked in q8_hardwaremgr_do_probe() */
+	if (WARN_ON(!np))
+		return NULL;
+
+	of_changeset_init(cset);
+	of_changeset_add_property_u32(cset, np, "reg", dev->addr);
+	of_changeset_add_property_string(cset, np, "compatible",
+					 dev->compatible);
+	of_changeset_update_property_string(cset, np, "status", "okay");
+
+	if (dev->delete_regulator) {
+		struct property *p;
+
+		p = of_find_property(np, "vddio-supply", NULL);
+		/* Never happens already checked in q8_hardwaremgr_do_probe() */
+		if (WARN_ON(!p))
+			return np;
+
+		of_changeset_remove_property(cset, np, p);
+	}
+
+	return np; /* Allow the caller to make further changes */
+}
+
+static int q8_hardwaremgr_probe_client(struct q8_hardwaremgr_data *data,
+				       struct q8_hardwaremgr_device *dev,
+				       struct i2c_adapter *adap, u16 addr,
+				       client_probe_func client_probe)
+{
+	struct i2c_client *client;
+	int ret;
+
+	client = i2c_new_dummy(adap, addr);
+	if (!client)
+		return -ENOMEM;
+
+	/* ret will be one of 0: Success, -ETIMEDOUT: Bus stuck or -ENODEV */
+	ret = client_probe(data, client);
+	if (ret == 0)
+		dev->addr = addr;
+
+	i2c_unregister_device(client);
+
+	return ret;
+}
+
+#define PROBE_CLIENT(dev, addr, probe) \
+{ \
+	int ret = q8_hardwaremgr_probe_client(data, dev, adap, addr, probe); \
+	if (ret != -ENODEV) \
+		return ret; \
+}
+
+static int q8_hardwaremgr_probe_silead(struct q8_hardwaremgr_data *data,
+				       struct i2c_client *client)
+{
+	__le32 chip_id;
+	int ret;
+
+	ret = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_ID,
+					    sizeof(chip_id), (u8 *)&chip_id);
+	if (ret != sizeof(chip_id))
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+
+	switch (le32_to_cpu(chip_id)) {
+	case 0xa0820000:
+		data->touchscreen.compatible = "silead,gsl1680";
+		data->touchscreen.model = gsl1680_a082;
+		dev_info(data->dev, "Silead touchscreen ID: 0xa0820000\n");
+		return 0;
+	case 0xb4820000:
+		data->touchscreen.compatible = "silead,gsl1680";
+		data->touchscreen.model = gsl1680_b482;
+		dev_info(data->dev, "Silead touchscreen ID: 0xb4820000\n");
+		return 0;
+	default:
+		dev_warn(data->dev, "Silead? touchscreen with unknown ID: 0x%08x\n",
+			 le32_to_cpu(chip_id));
+	}
+
+	return -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_ektf2127(struct q8_hardwaremgr_data *data,
+					 struct i2c_client *client)
+{
+	unsigned char buff[4];
+	int ret;
+
+	/* Read hello, ignore data, depends on initial power state */
+	ret = i2c_master_recv(client, buff, 4);
+	if (ret != 4)
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+
+	/* Request width */
+	buff[0] = EKTF2127_REQUEST;
+	buff[1] = EKTF2127_WIDTH;
+	buff[2] = 0x00;
+	buff[3] = 0x00;
+	ret = i2c_master_send(client, buff, 4);
+	if (ret != 4)
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+
+	msleep(20);
+
+	/* Read response */
+	ret = i2c_master_recv(client, buff, 4);
+	if (ret != 4)
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+
+	if (buff[0] == EKTF2127_RESPONSE && buff[1] == EKTF2127_WIDTH) {
+		data->touchscreen.compatible = "elan,ektf2127";
+		data->touchscreen.model = ektf2127;
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_zet6251(struct q8_hardwaremgr_data *data,
+					struct i2c_client *client)
+{
+	unsigned char buff[4];
+	int ret;
+
+	/*
+	 * We only do a simple read finger data packet test, because some
+	 * versions require firmware to be loaded. If no firmware is loaded
+	 * the buffer will be filed with 0xff, so we ignore the contents.
+	 */
+	ret = i2c_master_recv(client, buff, 24);
+	if (ret != 24)
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+
+	data->touchscreen.compatible = "zeitec,zet6251";
+	data->touchscreen.model = zet6251;
+	return 0;
+}
+
+static int q8_hardwaremgr_probe_touchscreen(struct q8_hardwaremgr_data *data,
+					    struct i2c_adapter *adap)
+{
+	msleep(TOUCHSCREEN_POWER_ON_DELAY);
+
+	PROBE_CLIENT(&data->touchscreen, 0x40, q8_hardwaremgr_probe_silead);
+	PROBE_CLIENT(&data->touchscreen, 0x15, q8_hardwaremgr_probe_ektf2127);
+	PROBE_CLIENT(&data->touchscreen, 0x76, q8_hardwaremgr_probe_zet6251);
+
+	return -ENODEV;
+}
+
+static void q8_hardwaremgr_apply_gsl1680_a082_variant(
+	struct q8_hardwaremgr_data *data)
+{
+	if (touchscreen_variant != -1)
+		data->touchscreen_variant = touchscreen_variant;
+
+	switch (data->touchscreen_variant) {
+	default:
+		dev_warn(data->dev, "Error unknown touchscreen_variant %d using 0\n",
+			 touchscreen_variant);
+		/* Fall through */
+	case 0:
+		data->touchscreen_width = 1024;
+		data->touchscreen_height = 600;
+		data->touchscreen_fw_name = "gsl1680-a082-q8-700.fw";
+		break;
+	case 1:
+		data->touchscreen_width = 480;
+		data->touchscreen_height = 800;
+		data->touchscreen_swap_x_y = 1;
+		data->touchscreen_fw_name = "gsl1680-a082-q8-a70.fw";
+		break;
+	}
+}
+
+static void q8_hardwaremgr_apply_gsl1680_b482_variant(
+	struct q8_hardwaremgr_data *data)
+{
+	if (touchscreen_variant != -1)
+		data->touchscreen_variant = touchscreen_variant;
+
+	switch (data->touchscreen_variant) {
+	default:
+		dev_warn(data->dev, "Error unknown touchscreen_variant %d using 0\n",
+			 touchscreen_variant);
+		/* Fall through */
+	case 0:
+		data->touchscreen_width = 960;
+		data->touchscreen_height = 640;
+		data->touchscreen_fw_name = "gsl1680-b482-q8-d702.fw";
+		break;
+	case 1:
+		data->touchscreen_width = 960;
+		data->touchscreen_height = 640;
+		data->touchscreen_fw_name = "gsl1680-b482-q8-a70.fw";
+		break;
+	}
+}
+
+static void q8_hardwaremgr_issue_gsl1680_warning(
+	struct q8_hardwaremgr_data *data)
+{
+	dev_warn(data->dev, "gsl1680 touchscreen may require kernel cmdline parameters to function properly\n");
+	dev_warn(data->dev, "Try q8_hardwaremgr.touchscreen_invert_x=%d if x coordinates are inverted\n",
+		 !data->touchscreen_invert_x);
+	dev_warn(data->dev, "Try q8_hardwaremgr.touchscreen_variant=%d if coordinates are all over the place\n",
+		 !data->touchscreen_variant);
+
+#define	show(x) \
+	dev_info(data->dev, #x " %d (%s)\n", data->x, \
+		 (x == -1) ? "auto" : "user supplied")
+
+	show(touchscreen_variant);
+	show(touchscreen_width);
+	show(touchscreen_height);
+	show(touchscreen_invert_x);
+	show(touchscreen_invert_y);
+	show(touchscreen_swap_x_y);
+	dev_info(data->dev, "touchscreen_fw_name %s (%s)\n",
+		 data->touchscreen_fw_name,
+		 (touchscreen_fw_name == NULL) ? "auto" : "user supplied");
+#undef show
+}
+
+static void q8_hardwaremgr_apply_touchscreen(struct q8_hardwaremgr_data *data)
+{
+	struct of_changeset cset;
+	struct device_node *np;
+
+	switch (data->touchscreen.model) {
+	case touchscreen_unknown:
+		return;
+	case gsl1680_a082:
+		q8_hardwaremgr_apply_gsl1680_a082_variant(data);
+		break;
+	case gsl1680_b482:
+		q8_hardwaremgr_apply_gsl1680_b482_variant(data);
+		break;
+	case ektf2127:
+	case zet6251:
+		/* These have only 1 variant */
+		break;
+	}
+
+	if (touchscreen_width != -1)
+		data->touchscreen_width = touchscreen_width;
+
+	if (touchscreen_height != -1)
+		data->touchscreen_height = touchscreen_height;
+
+	if (touchscreen_invert_x != -1)
+		data->touchscreen_invert_x = touchscreen_invert_x;
+
+	if (touchscreen_invert_y != -1)
+		data->touchscreen_invert_y = touchscreen_invert_y;
+
+	if (touchscreen_swap_x_y != -1)
+		data->touchscreen_swap_x_y = touchscreen_swap_x_y;
+
+	if (touchscreen_fw_name)
+		data->touchscreen_fw_name = touchscreen_fw_name;
+
+	if (data->touchscreen.model == gsl1680_a082 ||
+	    data->touchscreen.model == gsl1680_b482)
+		q8_hardwaremgr_issue_gsl1680_warning(data);
+
+	np = q8_hardware_mgr_apply_common(&data->touchscreen, &cset,
+					  "touchscreen");
+	if (!np)
+		return;
+
+	if (data->touchscreen_width)
+		of_changeset_add_property_u32(&cset, np, "touchscreen-size-x",
+					      data->touchscreen_width);
+	if (data->touchscreen_height)
+		of_changeset_add_property_u32(&cset, np, "touchscreen-size-y",
+					      data->touchscreen_height);
+	if (data->touchscreen_invert_x)
+		of_changeset_add_property_bool(&cset, np,
+					       "touchscreen-inverted-x");
+	if (data->touchscreen_invert_y)
+		of_changeset_add_property_bool(&cset, np,
+					       "touchscreen-inverted-y");
+	if (data->touchscreen_swap_x_y)
+		of_changeset_add_property_bool(&cset, np,
+					       "touchscreen-swapped-x-y");
+	if (data->touchscreen_fw_name)
+		of_changeset_add_property_string(&cset, np, "firmware-name",
+						 data->touchscreen_fw_name);
+
+	of_changeset_apply(&cset);
+
+	of_node_put(np);
+}
+
+static int q8_hardwaremgr_do_probe(struct q8_hardwaremgr_data *data,
+				   struct q8_hardwaremgr_device *dev,
+				   const char *prefix, bus_probe_func func)
+{
+	struct device_node *np;
+	struct i2c_adapter *adap;
+	struct regulator *reg;
+	struct gpio_desc *gpio;
+	int ret = 0;
+
+	np = of_find_node_by_name(of_root, prefix);
+	if (!np) {
+		dev_err(data->dev, "Error %s node is missing\n", prefix);
+		return -EINVAL;
+	}
+
+	/*
+	 * Patch the dt_node into our device since there is no device for
+	 * the probed hw yet (status = disabled) .
+	 */
+	data->dev->of_node = np;
+
+	ret = pinctrl_bind_pins(data->dev);
+	if (ret)
+		goto put_node;
+
+	adap = of_get_i2c_adapter_by_node(np->parent);
+	if (!adap) {
+		ret = -EPROBE_DEFER;
+		goto put_pins;
+	}
+
+	reg = regulator_get_optional(data->dev, "vddio");
+	if (IS_ERR(reg)) {
+		ret = PTR_ERR(reg);
+		if (ret == -EPROBE_DEFER)
+			goto put_adapter;
+		reg = NULL;
+	}
+
+	gpio = fwnode_get_named_gpiod(&np->fwnode, "power-gpios");
+	if (IS_ERR(gpio)) {
+		ret = PTR_ERR(gpio);
+		if (ret == -EPROBE_DEFER)
+			goto put_reg;
+		gpio = NULL;
+	}
+
+	/* First try with only the power gpio driven high */
+	if (gpio) {
+		ret = gpiod_direction_output(gpio, 1);
+		if (ret)
+			goto put_gpio;
+	}
+
+	dev_info(data->dev, "Probing %s without a regulator\n", prefix);
+	ret = func(data, adap);
+	if (ret != 0 && reg) {
+		/* Second try, also enable the regulator */
+		ret = regulator_enable(reg);
+		if (ret)
+			goto restore_gpio;
+
+		dev_info(data->dev, "Probing %s with a regulator\n", prefix);
+		ret = func(data, adap);
+
+		regulator_disable(reg);
+	} else if (reg)
+		dev->delete_regulator = true; /* Regulator not needed */
+
+	if (ret == 0)
+		dev_info(data->dev, "Found %s at 0x%02x\n",
+			 dev->compatible, dev->addr);
+	else
+		ret = 0; /* Not finding a device is not an error */
+
+restore_gpio:
+	if (gpio)
+		gpiod_direction_output(gpio, 0);
+put_gpio:
+	if (gpio)
+		gpiod_put(gpio);
+put_reg:
+	if (reg)
+		regulator_put(reg);
+put_adapter:
+	i2c_put_adapter(adap);
+
+put_pins:
+	/* Undo our manual pinctrl_bind_pins() */
+	if (data->dev->pins) {
+		devm_pinctrl_put(data->dev->pins->p);
+		devm_kfree(data->dev, data->dev->pins);
+		data->dev->pins = NULL;
+	}
+
+put_node:
+	data->dev->of_node = NULL;
+	of_node_put(np);
+
+	return ret;
+}
+
+static int q8_hardwaremgr_probe(struct platform_device *pdev)
+{
+	struct q8_hardwaremgr_data *data;
+	int ret = 0;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->dev = &pdev->dev;
+	data->soc = (long)pdev->dev.platform_data;
+
+	ret = q8_hardwaremgr_do_probe(data, &data->touchscreen, "touchscreen",
+				      q8_hardwaremgr_probe_touchscreen);
+	if (ret)
+		goto error;
+
+	q8_hardwaremgr_apply_touchscreen(data);
+
+error:
+	kfree(data);
+
+	return ret;
+}
+
+static struct platform_driver q8_hardwaremgr_driver = {
+	.driver = {
+		.name	= "q8-hwmgr",
+	},
+	.probe	= q8_hardwaremgr_probe,
+};
+
+static int __init q8_hardwaremgr_init(void)
+{
+	struct platform_device *pdev;
+	enum soc soc;
+	int ret;
+
+	if (of_machine_is_compatible("allwinner,q8-a13"))
+		soc = a13;
+	else if (of_machine_is_compatible("allwinner,q8-a23"))
+		soc = a23;
+	else if (of_machine_is_compatible("allwinner,q8-a33"))
+		soc = a33;
+	else
+		return 0;
+
+	pdev = platform_device_alloc("q8-hwmgr", 0);
+	if (!pdev)
+		return -ENOMEM;
+
+	pdev->dev.platform_data = (void *)(long)soc;
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		return ret;
+
+	return platform_driver_register(&q8_hardwaremgr_driver);
+}
+
+device_initcall(q8_hardwaremgr_init);
+
+MODULE_DESCRIPTION("Allwinner q8 formfactor tablet hardware manager");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL");
-- 
2.9.3

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

* [PATCH 3/6] misc: q8-hardwaremgr: Add accelerometer detection
  2016-10-14  7:53 ` Hans de Goede
@ 2016-10-14  7:53     ` Hans de Goede
  -1 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-14  7:53 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland, Arnd Bergmann, Greg Kroah-Hartman
  Cc: Maxime Ripard, Chen-Yu Tsai,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
	Hans de Goede

Extend the q8-hardwaremgr with accelerometer detection.

Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 drivers/misc/Kconfig          |   2 +-
 drivers/misc/q8-hardwaremgr.c | 219 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 220 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index d6c1529..11b05b0 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -801,7 +801,7 @@ config Q8_HARDWAREMGR
 	default	n
 	help
 	  This option enables support for autodetecting the touchscreen
-	  on Allwinner Q8 tablets.
+	  and accelerometer on Allwinner Q8 tablets.
 
 	  If unsure, say N.
 
diff --git a/drivers/misc/q8-hardwaremgr.c b/drivers/misc/q8-hardwaremgr.c
index 346102d..8ed71a9 100644
--- a/drivers/misc/q8-hardwaremgr.c
+++ b/drivers/misc/q8-hardwaremgr.c
@@ -83,6 +83,48 @@ enum {
 	zet6251,
 };
 
+#define DA280_REG_CHIP_ID		0x01
+#define DA280_CHIP_ID			0x13
+#define DA311_REG_CHIP_ID		0x0f
+#define DA311_CHIP_ID			0x13
+
+#define DMARD06_CHIP_ID_REG		0x0f
+#define DMARD05_CHIP_ID			0x05
+#define DMARD06_CHIP_ID			0x06
+#define DMARD07_CHIP_ID			0x07
+#define DMARD09_REG_CHIPID		0x18
+#define DMARD09_CHIPID			0x95
+#define DMARD10_REG_STADR		0x12
+#define DMARD10_REG_STAINT		0x1c
+#define DMARD10_VALUE_STADR		0x55
+#define DMARD10_VALUE_STAINT		0xaa
+
+#define MC3230_REG_CHIP_ID		0x18
+#define MC3230_CHIP_ID			0x01
+#define MMA7660_CHIP_ID			0x00 /* Factory reserved on MMA7660 */
+#define MC3230_REG_PRODUCT_CODE		0x3b
+#define MMA7660_PRODUCT_CODE		0x00 /* Factory reserved on MMA7660 */
+#define MC3210_PRODUCT_CODE		0x90
+#define MC3230_PRODUCT_CODE		0x19
+
+#define MXC6225_REG_CHIP_ID		0x08
+#define MXC6225_CHIP_ID			0x05
+
+enum {
+	accel_unknown,
+	da280,
+	da311,
+	dmard05,
+	dmard06,
+	dmard07,
+	dmard09,
+	dmard10,
+	mc3210,
+	mc3230,
+	mma7660,
+	mxc6225,
+};
+
 struct q8_hardwaremgr_device {
 	int model;
 	int addr;
@@ -94,6 +136,7 @@ struct q8_hardwaremgr_data {
 	struct device *dev;
 	enum soc soc;
 	struct q8_hardwaremgr_device touchscreen;
+	struct q8_hardwaremgr_device accelerometer;
 	int touchscreen_variant;
 	int touchscreen_width;
 	int touchscreen_height;
@@ -411,6 +454,175 @@ static void q8_hardwaremgr_apply_touchscreen(struct q8_hardwaremgr_data *data)
 	of_node_put(np);
 }
 
+static int q8_hardwaremgr_probe_mxc6225(struct q8_hardwaremgr_data *data,
+					struct i2c_client *client)
+{
+	int id;
+
+	id = i2c_smbus_read_byte_data(client, MXC6225_REG_CHIP_ID);
+	/* Bits 7 - 5 of the chip-id register are undefined */
+	if (id >= 0 && (id & 0x1f) == MXC6225_CHIP_ID) {
+		data->accelerometer.compatible = "memsic,mxc6225";
+		data->accelerometer.model = mxc6225;
+		return 0;
+	}
+
+	return id == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_mc3230(struct q8_hardwaremgr_data *data,
+				       struct i2c_client *client)
+{
+	int id, pc = 0;
+
+	/* First check chip-id, then product-id */
+	id = i2c_smbus_read_byte_data(client, MC3230_REG_CHIP_ID);
+	if (id == MC3230_CHIP_ID || id == MMA7660_CHIP_ID) {
+		pc = i2c_smbus_read_byte_data(client, MC3230_REG_PRODUCT_CODE);
+		switch (pc) {
+		case MMA7660_PRODUCT_CODE:
+			data->accelerometer.compatible = "fsl,mma7660";
+			data->accelerometer.model = mma7660;
+			return 0;
+		case MC3210_PRODUCT_CODE:
+			data->accelerometer.compatible = "mcube,mc3210";
+			data->accelerometer.model = mc3210;
+			return 0;
+		case MC3230_PRODUCT_CODE:
+			data->accelerometer.compatible = "mcube,mc3230";
+			data->accelerometer.model = mc3230;
+			return 0;
+		case -ETIMEDOUT:
+			return -ETIMEDOUT; /* Bus stuck bail immediately */
+		}
+	}
+
+	return id == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_dmard06(struct q8_hardwaremgr_data *data,
+					struct i2c_client *client)
+{
+	int id;
+
+	id = i2c_smbus_read_byte_data(client, DMARD06_CHIP_ID_REG);
+	switch (id) {
+	case DMARD05_CHIP_ID:
+		data->accelerometer.compatible = "domintech,dmard05";
+		data->accelerometer.model = dmard05;
+		return 0;
+	case DMARD06_CHIP_ID:
+		data->accelerometer.compatible = "domintech,dmard06";
+		data->accelerometer.model = dmard06;
+		return 0;
+	case DMARD07_CHIP_ID:
+		data->accelerometer.compatible = "domintech,dmard07";
+		data->accelerometer.model = dmard07;
+		return 0;
+	}
+
+	return id == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_dmard09(struct q8_hardwaremgr_data *data,
+					struct i2c_client *client)
+{
+	int id;
+
+	id = i2c_smbus_read_byte_data(client, DMARD09_REG_CHIPID);
+	if (id == DMARD09_CHIPID) {
+		data->accelerometer.compatible = "domintech,dmard09";
+		data->accelerometer.model = dmard09;
+		return 0;
+	}
+
+	return id == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_dmard10(struct q8_hardwaremgr_data *data,
+					struct i2c_client *client)
+{
+	int stadr, staint = 0;
+
+	/* These 2 registers have special POR reset values used for id */
+	stadr = i2c_smbus_read_byte_data(client, DMARD10_REG_STADR);
+	if (stadr == DMARD10_VALUE_STADR) {
+		staint = i2c_smbus_read_byte_data(client, DMARD10_REG_STAINT);
+		switch (staint) {
+		case DMARD10_VALUE_STAINT:
+			data->accelerometer.compatible = "domintech,dmard10";
+			data->accelerometer.model = dmard10;
+			return 0;
+		case -ETIMEDOUT:
+			return -ETIMEDOUT; /* Bus stuck bail immediately */
+		}
+	}
+
+	return stadr == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_da280(struct q8_hardwaremgr_data *data,
+				      struct i2c_client *client)
+{
+	int id;
+
+	id = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID);
+	if (id == DA280_CHIP_ID) {
+		data->accelerometer.compatible = "miramems,da280";
+		data->accelerometer.model = da280;
+		return 0;
+	}
+
+	return id == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_da311(struct q8_hardwaremgr_data *data,
+				      struct i2c_client *client)
+{
+	int id;
+
+	id = i2c_smbus_read_byte_data(client, DA311_REG_CHIP_ID);
+	if (id == DA311_CHIP_ID) {
+		data->accelerometer.compatible = "miramems,da311";
+		data->accelerometer.model = da311;
+		return 0;
+	}
+
+	return id == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_accelerometer(struct q8_hardwaremgr_data *data,
+					      struct i2c_adapter *adap)
+{
+	PROBE_CLIENT(&data->accelerometer, 0x15, q8_hardwaremgr_probe_mxc6225);
+	PROBE_CLIENT(&data->accelerometer, 0x4c, q8_hardwaremgr_probe_mc3230);
+	PROBE_CLIENT(&data->accelerometer, 0x1c, q8_hardwaremgr_probe_dmard06);
+	PROBE_CLIENT(&data->accelerometer, 0x1d, q8_hardwaremgr_probe_dmard09);
+	PROBE_CLIENT(&data->accelerometer, 0x18, q8_hardwaremgr_probe_dmard10);
+	PROBE_CLIENT(&data->accelerometer, 0x26, q8_hardwaremgr_probe_da280);
+	PROBE_CLIENT(&data->accelerometer, 0x27, q8_hardwaremgr_probe_da311);
+
+	return -ENODEV;
+}
+
+static void q8_hardwaremgr_apply_accelerometer(struct q8_hardwaremgr_data *data)
+{
+	struct of_changeset cset;
+	struct device_node *np;
+
+	if (data->accelerometer.model == accel_unknown)
+		return;
+
+	np = q8_hardware_mgr_apply_common(&data->accelerometer, &cset,
+					  "accelerometer");
+	if (!np)
+		return;
+
+	of_changeset_apply(&cset);
+
+	of_node_put(np);
+}
+
 static int q8_hardwaremgr_do_probe(struct q8_hardwaremgr_data *data,
 				   struct q8_hardwaremgr_device *dev,
 				   const char *prefix, bus_probe_func func)
@@ -531,7 +743,14 @@ static int q8_hardwaremgr_probe(struct platform_device *pdev)
 	if (ret)
 		goto error;
 
+	ret = q8_hardwaremgr_do_probe(data, &data->accelerometer,
+				      "accelerometer",
+				      q8_hardwaremgr_probe_accelerometer);
+	if (ret)
+		goto error;
+
 	q8_hardwaremgr_apply_touchscreen(data);
+	q8_hardwaremgr_apply_accelerometer(data);
 
 error:
 	kfree(data);
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 3/6] misc: q8-hardwaremgr: Add accelerometer detection
@ 2016-10-14  7:53     ` Hans de Goede
  0 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-14  7:53 UTC (permalink / raw)
  To: linux-arm-kernel

Extend the q8-hardwaremgr with accelerometer detection.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/misc/Kconfig          |   2 +-
 drivers/misc/q8-hardwaremgr.c | 219 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 220 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index d6c1529..11b05b0 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -801,7 +801,7 @@ config Q8_HARDWAREMGR
 	default	n
 	help
 	  This option enables support for autodetecting the touchscreen
-	  on Allwinner Q8 tablets.
+	  and accelerometer on Allwinner Q8 tablets.
 
 	  If unsure, say N.
 
diff --git a/drivers/misc/q8-hardwaremgr.c b/drivers/misc/q8-hardwaremgr.c
index 346102d..8ed71a9 100644
--- a/drivers/misc/q8-hardwaremgr.c
+++ b/drivers/misc/q8-hardwaremgr.c
@@ -83,6 +83,48 @@ enum {
 	zet6251,
 };
 
+#define DA280_REG_CHIP_ID		0x01
+#define DA280_CHIP_ID			0x13
+#define DA311_REG_CHIP_ID		0x0f
+#define DA311_CHIP_ID			0x13
+
+#define DMARD06_CHIP_ID_REG		0x0f
+#define DMARD05_CHIP_ID			0x05
+#define DMARD06_CHIP_ID			0x06
+#define DMARD07_CHIP_ID			0x07
+#define DMARD09_REG_CHIPID		0x18
+#define DMARD09_CHIPID			0x95
+#define DMARD10_REG_STADR		0x12
+#define DMARD10_REG_STAINT		0x1c
+#define DMARD10_VALUE_STADR		0x55
+#define DMARD10_VALUE_STAINT		0xaa
+
+#define MC3230_REG_CHIP_ID		0x18
+#define MC3230_CHIP_ID			0x01
+#define MMA7660_CHIP_ID			0x00 /* Factory reserved on MMA7660 */
+#define MC3230_REG_PRODUCT_CODE		0x3b
+#define MMA7660_PRODUCT_CODE		0x00 /* Factory reserved on MMA7660 */
+#define MC3210_PRODUCT_CODE		0x90
+#define MC3230_PRODUCT_CODE		0x19
+
+#define MXC6225_REG_CHIP_ID		0x08
+#define MXC6225_CHIP_ID			0x05
+
+enum {
+	accel_unknown,
+	da280,
+	da311,
+	dmard05,
+	dmard06,
+	dmard07,
+	dmard09,
+	dmard10,
+	mc3210,
+	mc3230,
+	mma7660,
+	mxc6225,
+};
+
 struct q8_hardwaremgr_device {
 	int model;
 	int addr;
@@ -94,6 +136,7 @@ struct q8_hardwaremgr_data {
 	struct device *dev;
 	enum soc soc;
 	struct q8_hardwaremgr_device touchscreen;
+	struct q8_hardwaremgr_device accelerometer;
 	int touchscreen_variant;
 	int touchscreen_width;
 	int touchscreen_height;
@@ -411,6 +454,175 @@ static void q8_hardwaremgr_apply_touchscreen(struct q8_hardwaremgr_data *data)
 	of_node_put(np);
 }
 
+static int q8_hardwaremgr_probe_mxc6225(struct q8_hardwaremgr_data *data,
+					struct i2c_client *client)
+{
+	int id;
+
+	id = i2c_smbus_read_byte_data(client, MXC6225_REG_CHIP_ID);
+	/* Bits 7 - 5 of the chip-id register are undefined */
+	if (id >= 0 && (id & 0x1f) == MXC6225_CHIP_ID) {
+		data->accelerometer.compatible = "memsic,mxc6225";
+		data->accelerometer.model = mxc6225;
+		return 0;
+	}
+
+	return id == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_mc3230(struct q8_hardwaremgr_data *data,
+				       struct i2c_client *client)
+{
+	int id, pc = 0;
+
+	/* First check chip-id, then product-id */
+	id = i2c_smbus_read_byte_data(client, MC3230_REG_CHIP_ID);
+	if (id == MC3230_CHIP_ID || id == MMA7660_CHIP_ID) {
+		pc = i2c_smbus_read_byte_data(client, MC3230_REG_PRODUCT_CODE);
+		switch (pc) {
+		case MMA7660_PRODUCT_CODE:
+			data->accelerometer.compatible = "fsl,mma7660";
+			data->accelerometer.model = mma7660;
+			return 0;
+		case MC3210_PRODUCT_CODE:
+			data->accelerometer.compatible = "mcube,mc3210";
+			data->accelerometer.model = mc3210;
+			return 0;
+		case MC3230_PRODUCT_CODE:
+			data->accelerometer.compatible = "mcube,mc3230";
+			data->accelerometer.model = mc3230;
+			return 0;
+		case -ETIMEDOUT:
+			return -ETIMEDOUT; /* Bus stuck bail immediately */
+		}
+	}
+
+	return id == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_dmard06(struct q8_hardwaremgr_data *data,
+					struct i2c_client *client)
+{
+	int id;
+
+	id = i2c_smbus_read_byte_data(client, DMARD06_CHIP_ID_REG);
+	switch (id) {
+	case DMARD05_CHIP_ID:
+		data->accelerometer.compatible = "domintech,dmard05";
+		data->accelerometer.model = dmard05;
+		return 0;
+	case DMARD06_CHIP_ID:
+		data->accelerometer.compatible = "domintech,dmard06";
+		data->accelerometer.model = dmard06;
+		return 0;
+	case DMARD07_CHIP_ID:
+		data->accelerometer.compatible = "domintech,dmard07";
+		data->accelerometer.model = dmard07;
+		return 0;
+	}
+
+	return id == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_dmard09(struct q8_hardwaremgr_data *data,
+					struct i2c_client *client)
+{
+	int id;
+
+	id = i2c_smbus_read_byte_data(client, DMARD09_REG_CHIPID);
+	if (id == DMARD09_CHIPID) {
+		data->accelerometer.compatible = "domintech,dmard09";
+		data->accelerometer.model = dmard09;
+		return 0;
+	}
+
+	return id == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_dmard10(struct q8_hardwaremgr_data *data,
+					struct i2c_client *client)
+{
+	int stadr, staint = 0;
+
+	/* These 2 registers have special POR reset values used for id */
+	stadr = i2c_smbus_read_byte_data(client, DMARD10_REG_STADR);
+	if (stadr == DMARD10_VALUE_STADR) {
+		staint = i2c_smbus_read_byte_data(client, DMARD10_REG_STAINT);
+		switch (staint) {
+		case DMARD10_VALUE_STAINT:
+			data->accelerometer.compatible = "domintech,dmard10";
+			data->accelerometer.model = dmard10;
+			return 0;
+		case -ETIMEDOUT:
+			return -ETIMEDOUT; /* Bus stuck bail immediately */
+		}
+	}
+
+	return stadr == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_da280(struct q8_hardwaremgr_data *data,
+				      struct i2c_client *client)
+{
+	int id;
+
+	id = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID);
+	if (id == DA280_CHIP_ID) {
+		data->accelerometer.compatible = "miramems,da280";
+		data->accelerometer.model = da280;
+		return 0;
+	}
+
+	return id == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_da311(struct q8_hardwaremgr_data *data,
+				      struct i2c_client *client)
+{
+	int id;
+
+	id = i2c_smbus_read_byte_data(client, DA311_REG_CHIP_ID);
+	if (id == DA311_CHIP_ID) {
+		data->accelerometer.compatible = "miramems,da311";
+		data->accelerometer.model = da311;
+		return 0;
+	}
+
+	return id == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+}
+
+static int q8_hardwaremgr_probe_accelerometer(struct q8_hardwaremgr_data *data,
+					      struct i2c_adapter *adap)
+{
+	PROBE_CLIENT(&data->accelerometer, 0x15, q8_hardwaremgr_probe_mxc6225);
+	PROBE_CLIENT(&data->accelerometer, 0x4c, q8_hardwaremgr_probe_mc3230);
+	PROBE_CLIENT(&data->accelerometer, 0x1c, q8_hardwaremgr_probe_dmard06);
+	PROBE_CLIENT(&data->accelerometer, 0x1d, q8_hardwaremgr_probe_dmard09);
+	PROBE_CLIENT(&data->accelerometer, 0x18, q8_hardwaremgr_probe_dmard10);
+	PROBE_CLIENT(&data->accelerometer, 0x26, q8_hardwaremgr_probe_da280);
+	PROBE_CLIENT(&data->accelerometer, 0x27, q8_hardwaremgr_probe_da311);
+
+	return -ENODEV;
+}
+
+static void q8_hardwaremgr_apply_accelerometer(struct q8_hardwaremgr_data *data)
+{
+	struct of_changeset cset;
+	struct device_node *np;
+
+	if (data->accelerometer.model == accel_unknown)
+		return;
+
+	np = q8_hardware_mgr_apply_common(&data->accelerometer, &cset,
+					  "accelerometer");
+	if (!np)
+		return;
+
+	of_changeset_apply(&cset);
+
+	of_node_put(np);
+}
+
 static int q8_hardwaremgr_do_probe(struct q8_hardwaremgr_data *data,
 				   struct q8_hardwaremgr_device *dev,
 				   const char *prefix, bus_probe_func func)
@@ -531,7 +743,14 @@ static int q8_hardwaremgr_probe(struct platform_device *pdev)
 	if (ret)
 		goto error;
 
+	ret = q8_hardwaremgr_do_probe(data, &data->accelerometer,
+				      "accelerometer",
+				      q8_hardwaremgr_probe_accelerometer);
+	if (ret)
+		goto error;
+
 	q8_hardwaremgr_apply_touchscreen(data);
+	q8_hardwaremgr_apply_accelerometer(data);
 
 error:
 	kfree(data);
-- 
2.9.3

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

* [PATCH 4/6] misc: q8-hardwaremgr: Add rda599x wift/bt/fm radio combo detection
  2016-10-14  7:53 ` Hans de Goede
@ 2016-10-14  7:53     ` Hans de Goede
  -1 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-14  7:53 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland, Arnd Bergmann, Greg Kroah-Hartman
  Cc: Maxime Ripard, Chen-Yu Tsai,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
	Hans de Goede

Some q8s have a rda599x sdio wifi/bt + i2c fm radio chip with its
i2c interface connected to the same i2c bus as the accelerometer.

There is no kernel driver for these devices yet, but it is useful to
know if one is present for the touchscreen variant selection heuristics.

And when in the future we do get a driver, this detection code will also
be useful to automatically register i2c client dt nodes for these devices.

Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 drivers/misc/q8-hardwaremgr.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/misc/q8-hardwaremgr.c b/drivers/misc/q8-hardwaremgr.c
index 8ed71a9..21754f5 100644
--- a/drivers/misc/q8-hardwaremgr.c
+++ b/drivers/misc/q8-hardwaremgr.c
@@ -144,6 +144,7 @@ struct q8_hardwaremgr_data {
 	int touchscreen_invert_y;
 	int touchscreen_swap_x_y;
 	const char *touchscreen_fw_name;
+	bool has_rda599x;
 };
 
 typedef int (*bus_probe_func)(struct q8_hardwaremgr_data *data,
@@ -454,6 +455,28 @@ static void q8_hardwaremgr_apply_touchscreen(struct q8_hardwaremgr_data *data)
 	of_node_put(np);
 }
 
+static int q8_hardwaremgr_probe_rda599x(struct q8_hardwaremgr_data *data,
+					struct i2c_client *client)
+{
+	int id;
+
+	/*
+	 * Check for the (integrated) rda580x / rda5820 fm receiver at 0x11
+	 *
+	 * Alternatively we could check for the wifi_rf i2c interface at
+	 * address 0x14, by selecting page/bank 1 through:
+	 * smbus_write_word_swapped(0x3f, 0x01)
+	 * and then doing a smbus_read_word_swapped(0x20) which will
+	 * return 0x5990 for a rda5990. We prefer the fm detect method since
+	 * we want to avoid doing any smbus_writes while probing.
+	 */
+	id = i2c_smbus_read_word_swapped(client, 0x0c);
+	if (id == 0x5802 || id == 0x5803 || id == 0x5805 || id == 0x5820)
+		data->has_rda599x = true;
+
+	return id == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+}
+
 static int q8_hardwaremgr_probe_mxc6225(struct q8_hardwaremgr_data *data,
 					struct i2c_client *client)
 {
@@ -594,6 +617,8 @@ static int q8_hardwaremgr_probe_da311(struct q8_hardwaremgr_data *data,
 static int q8_hardwaremgr_probe_accelerometer(struct q8_hardwaremgr_data *data,
 					      struct i2c_adapter *adap)
 {
+	/* The rda599x wifi/bt/fm shares the i2c bus with the accelerometer */
+	PROBE_CLIENT(NULL,		   0x11, q8_hardwaremgr_probe_rda599x);
 	PROBE_CLIENT(&data->accelerometer, 0x15, q8_hardwaremgr_probe_mxc6225);
 	PROBE_CLIENT(&data->accelerometer, 0x4c, q8_hardwaremgr_probe_mc3230);
 	PROBE_CLIENT(&data->accelerometer, 0x1c, q8_hardwaremgr_probe_dmard06);
@@ -749,6 +774,9 @@ static int q8_hardwaremgr_probe(struct platform_device *pdev)
 	if (ret)
 		goto error;
 
+	if (data->has_rda599x)
+		dev_info(data->dev, "Found a rda599x sdio/i2c wifi/bt/fm combo chip\n");
+
 	q8_hardwaremgr_apply_touchscreen(data);
 	q8_hardwaremgr_apply_accelerometer(data);
 
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 4/6] misc: q8-hardwaremgr: Add rda599x wift/bt/fm radio combo detection
@ 2016-10-14  7:53     ` Hans de Goede
  0 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-14  7:53 UTC (permalink / raw)
  To: linux-arm-kernel

Some q8s have a rda599x sdio wifi/bt + i2c fm radio chip with its
i2c interface connected to the same i2c bus as the accelerometer.

There is no kernel driver for these devices yet, but it is useful to
know if one is present for the touchscreen variant selection heuristics.

And when in the future we do get a driver, this detection code will also
be useful to automatically register i2c client dt nodes for these devices.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/misc/q8-hardwaremgr.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/misc/q8-hardwaremgr.c b/drivers/misc/q8-hardwaremgr.c
index 8ed71a9..21754f5 100644
--- a/drivers/misc/q8-hardwaremgr.c
+++ b/drivers/misc/q8-hardwaremgr.c
@@ -144,6 +144,7 @@ struct q8_hardwaremgr_data {
 	int touchscreen_invert_y;
 	int touchscreen_swap_x_y;
 	const char *touchscreen_fw_name;
+	bool has_rda599x;
 };
 
 typedef int (*bus_probe_func)(struct q8_hardwaremgr_data *data,
@@ -454,6 +455,28 @@ static void q8_hardwaremgr_apply_touchscreen(struct q8_hardwaremgr_data *data)
 	of_node_put(np);
 }
 
+static int q8_hardwaremgr_probe_rda599x(struct q8_hardwaremgr_data *data,
+					struct i2c_client *client)
+{
+	int id;
+
+	/*
+	 * Check for the (integrated) rda580x / rda5820 fm receiver at 0x11
+	 *
+	 * Alternatively we could check for the wifi_rf i2c interface at
+	 * address 0x14, by selecting page/bank 1 through:
+	 * smbus_write_word_swapped(0x3f, 0x01)
+	 * and then doing a smbus_read_word_swapped(0x20) which will
+	 * return 0x5990 for a rda5990. We prefer the fm detect method since
+	 * we want to avoid doing any smbus_writes while probing.
+	 */
+	id = i2c_smbus_read_word_swapped(client, 0x0c);
+	if (id == 0x5802 || id == 0x5803 || id == 0x5805 || id == 0x5820)
+		data->has_rda599x = true;
+
+	return id == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+}
+
 static int q8_hardwaremgr_probe_mxc6225(struct q8_hardwaremgr_data *data,
 					struct i2c_client *client)
 {
@@ -594,6 +617,8 @@ static int q8_hardwaremgr_probe_da311(struct q8_hardwaremgr_data *data,
 static int q8_hardwaremgr_probe_accelerometer(struct q8_hardwaremgr_data *data,
 					      struct i2c_adapter *adap)
 {
+	/* The rda599x wifi/bt/fm shares the i2c bus with the accelerometer */
+	PROBE_CLIENT(NULL,		   0x11, q8_hardwaremgr_probe_rda599x);
 	PROBE_CLIENT(&data->accelerometer, 0x15, q8_hardwaremgr_probe_mxc6225);
 	PROBE_CLIENT(&data->accelerometer, 0x4c, q8_hardwaremgr_probe_mc3230);
 	PROBE_CLIENT(&data->accelerometer, 0x1c, q8_hardwaremgr_probe_dmard06);
@@ -749,6 +774,9 @@ static int q8_hardwaremgr_probe(struct platform_device *pdev)
 	if (ret)
 		goto error;
 
+	if (data->has_rda599x)
+		dev_info(data->dev, "Found a rda599x sdio/i2c wifi/bt/fm combo chip\n");
+
 	q8_hardwaremgr_apply_touchscreen(data);
 	q8_hardwaremgr_apply_accelerometer(data);
 
-- 
2.9.3

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

* [PATCH 5/6] misc: q8-hardwaremgr: Better touchscreen defaults based on heuristics
  2016-10-14  7:53 ` Hans de Goede
@ 2016-10-14  7:53     ` Hans de Goede
  -1 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-14  7:53 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland, Arnd Bergmann, Greg Kroah-Hartman
  Cc: Maxime Ripard, Chen-Yu Tsai,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
	Hans de Goede

Some q8s with gsl1680 touchscreens need to use an alterternative
firmware file and/or need their x/y axis inverted.

This commit adds some heuristics to pick defaults based on other detected
tablet properties (mostly which accelerometer is detected) and sets
defaults based on this.

Although there is not necessarily any relationship between these
settings, this does give us the right defaults on all known model q8
tablets, making the touchscreen work out of the box without requiring
any kernel commandline options to be set.

Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 drivers/misc/q8-hardwaremgr.c | 81 +++++++++++++++++++++++++++++++++++++++----
 1 file changed, 74 insertions(+), 7 deletions(-)

diff --git a/drivers/misc/q8-hardwaremgr.c b/drivers/misc/q8-hardwaremgr.c
index 21754f5..95cdaf2 100644
--- a/drivers/misc/q8-hardwaremgr.c
+++ b/drivers/misc/q8-hardwaremgr.c
@@ -84,7 +84,12 @@ enum {
 };
 
 #define DA280_REG_CHIP_ID		0x01
+#define DA280_REG_ACC_Z_LSB		0x06
+#define DA280_REG_MODE_BW		0x11
 #define DA280_CHIP_ID			0x13
+#define DA280_MODE_ENABLE		0x1e
+#define DA280_MODE_DISABLE		0x9e
+
 #define DA311_REG_CHIP_ID		0x0f
 #define DA311_CHIP_ID			0x13
 
@@ -112,6 +117,7 @@ enum {
 
 enum {
 	accel_unknown,
+	da226,
 	da280,
 	da311,
 	dmard05,
@@ -313,8 +319,23 @@ static int q8_hardwaremgr_probe_touchscreen(struct q8_hardwaremgr_data *data,
 static void q8_hardwaremgr_apply_gsl1680_a082_variant(
 	struct q8_hardwaremgr_data *data)
 {
-	if (touchscreen_variant != -1)
+	if (touchscreen_variant != -1) {
 		data->touchscreen_variant = touchscreen_variant;
+	} else {
+		/*
+		 * These accelerometer based heuristics select the best
+		 * default based on known q8 tablets.
+		 */
+		switch (data->accelerometer.model) {
+		case mc3230:
+			data->touchscreen_invert_x = 1;
+			break;
+		case dmard10:
+		case mxc6225:
+			data->touchscreen_variant = 1;
+			break;
+		}
+	}
 
 	switch (data->touchscreen_variant) {
 	default:
@@ -338,8 +359,30 @@ static void q8_hardwaremgr_apply_gsl1680_a082_variant(
 static void q8_hardwaremgr_apply_gsl1680_b482_variant(
 	struct q8_hardwaremgr_data *data)
 {
-	if (touchscreen_variant != -1)
+	if (touchscreen_variant != -1) {
 		data->touchscreen_variant = touchscreen_variant;
+	} else {
+		/*
+		 * These accelerometer based heuristics select the best
+		 * default based on known q8 tablets.
+		 */
+		switch (data->accelerometer.model) {
+		case da280:
+			if (data->accelerometer.addr == 0x27)
+				; /* No-op */
+			else if (data->has_rda599x)
+				data->touchscreen_invert_x = 1;
+			else
+				data->touchscreen_invert_y = 1;
+			break;
+		case dmard09:
+			data->touchscreen_invert_x = 1;
+			break;
+		case mxc6225:
+			data->touchscreen_variant = 1;
+			break;
+		}
+	}
 
 	switch (data->touchscreen_variant) {
 	default:
@@ -587,16 +630,39 @@ static int q8_hardwaremgr_probe_dmard10(struct q8_hardwaremgr_data *data,
 static int q8_hardwaremgr_probe_da280(struct q8_hardwaremgr_data *data,
 				      struct i2c_client *client)
 {
-	int id;
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID);
+	if (ret != DA280_CHIP_ID)
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
 
-	id = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID);
-	if (id == DA280_CHIP_ID) {
+	/* da226 (2-axis) or da280 (3-axis) ? measure once to detect */
+	ret = i2c_smbus_write_byte_data(client, DA280_REG_MODE_BW,
+					DA280_MODE_ENABLE);
+	if (ret)
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+
+	msleep(10);
+
+	ret = i2c_smbus_read_word_data(client, DA280_REG_ACC_Z_LSB);
+	if (ret < 0)
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+
+	/* If not present Z reports max pos value (14 bits, 2 low bits 0) */
+	if (ret == 32764) {
+		data->accelerometer.compatible = "miramems,da226";
+		data->accelerometer.model = da226;
+	} else {
 		data->accelerometer.compatible = "miramems,da280";
 		data->accelerometer.model = da280;
-		return 0;
 	}
 
-	return id == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+	ret = i2c_smbus_write_byte_data(client, DA280_REG_MODE_BW,
+					DA280_MODE_DISABLE);
+	if (ret)
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+
+	return 0;
 }
 
 static int q8_hardwaremgr_probe_da311(struct q8_hardwaremgr_data *data,
@@ -625,6 +691,7 @@ static int q8_hardwaremgr_probe_accelerometer(struct q8_hardwaremgr_data *data,
 	PROBE_CLIENT(&data->accelerometer, 0x1d, q8_hardwaremgr_probe_dmard09);
 	PROBE_CLIENT(&data->accelerometer, 0x18, q8_hardwaremgr_probe_dmard10);
 	PROBE_CLIENT(&data->accelerometer, 0x26, q8_hardwaremgr_probe_da280);
+	PROBE_CLIENT(&data->accelerometer, 0x27, q8_hardwaremgr_probe_da280);
 	PROBE_CLIENT(&data->accelerometer, 0x27, q8_hardwaremgr_probe_da311);
 
 	return -ENODEV;
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 5/6] misc: q8-hardwaremgr: Better touchscreen defaults based on heuristics
@ 2016-10-14  7:53     ` Hans de Goede
  0 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-14  7:53 UTC (permalink / raw)
  To: linux-arm-kernel

Some q8s with gsl1680 touchscreens need to use an alterternative
firmware file and/or need their x/y axis inverted.

This commit adds some heuristics to pick defaults based on other detected
tablet properties (mostly which accelerometer is detected) and sets
defaults based on this.

Although there is not necessarily any relationship between these
settings, this does give us the right defaults on all known model q8
tablets, making the touchscreen work out of the box without requiring
any kernel commandline options to be set.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/misc/q8-hardwaremgr.c | 81 +++++++++++++++++++++++++++++++++++++++----
 1 file changed, 74 insertions(+), 7 deletions(-)

diff --git a/drivers/misc/q8-hardwaremgr.c b/drivers/misc/q8-hardwaremgr.c
index 21754f5..95cdaf2 100644
--- a/drivers/misc/q8-hardwaremgr.c
+++ b/drivers/misc/q8-hardwaremgr.c
@@ -84,7 +84,12 @@ enum {
 };
 
 #define DA280_REG_CHIP_ID		0x01
+#define DA280_REG_ACC_Z_LSB		0x06
+#define DA280_REG_MODE_BW		0x11
 #define DA280_CHIP_ID			0x13
+#define DA280_MODE_ENABLE		0x1e
+#define DA280_MODE_DISABLE		0x9e
+
 #define DA311_REG_CHIP_ID		0x0f
 #define DA311_CHIP_ID			0x13
 
@@ -112,6 +117,7 @@ enum {
 
 enum {
 	accel_unknown,
+	da226,
 	da280,
 	da311,
 	dmard05,
@@ -313,8 +319,23 @@ static int q8_hardwaremgr_probe_touchscreen(struct q8_hardwaremgr_data *data,
 static void q8_hardwaremgr_apply_gsl1680_a082_variant(
 	struct q8_hardwaremgr_data *data)
 {
-	if (touchscreen_variant != -1)
+	if (touchscreen_variant != -1) {
 		data->touchscreen_variant = touchscreen_variant;
+	} else {
+		/*
+		 * These accelerometer based heuristics select the best
+		 * default based on known q8 tablets.
+		 */
+		switch (data->accelerometer.model) {
+		case mc3230:
+			data->touchscreen_invert_x = 1;
+			break;
+		case dmard10:
+		case mxc6225:
+			data->touchscreen_variant = 1;
+			break;
+		}
+	}
 
 	switch (data->touchscreen_variant) {
 	default:
@@ -338,8 +359,30 @@ static void q8_hardwaremgr_apply_gsl1680_a082_variant(
 static void q8_hardwaremgr_apply_gsl1680_b482_variant(
 	struct q8_hardwaremgr_data *data)
 {
-	if (touchscreen_variant != -1)
+	if (touchscreen_variant != -1) {
 		data->touchscreen_variant = touchscreen_variant;
+	} else {
+		/*
+		 * These accelerometer based heuristics select the best
+		 * default based on known q8 tablets.
+		 */
+		switch (data->accelerometer.model) {
+		case da280:
+			if (data->accelerometer.addr == 0x27)
+				; /* No-op */
+			else if (data->has_rda599x)
+				data->touchscreen_invert_x = 1;
+			else
+				data->touchscreen_invert_y = 1;
+			break;
+		case dmard09:
+			data->touchscreen_invert_x = 1;
+			break;
+		case mxc6225:
+			data->touchscreen_variant = 1;
+			break;
+		}
+	}
 
 	switch (data->touchscreen_variant) {
 	default:
@@ -587,16 +630,39 @@ static int q8_hardwaremgr_probe_dmard10(struct q8_hardwaremgr_data *data,
 static int q8_hardwaremgr_probe_da280(struct q8_hardwaremgr_data *data,
 				      struct i2c_client *client)
 {
-	int id;
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID);
+	if (ret != DA280_CHIP_ID)
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
 
-	id = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID);
-	if (id == DA280_CHIP_ID) {
+	/* da226 (2-axis) or da280 (3-axis) ? measure once to detect */
+	ret = i2c_smbus_write_byte_data(client, DA280_REG_MODE_BW,
+					DA280_MODE_ENABLE);
+	if (ret)
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+
+	msleep(10);
+
+	ret = i2c_smbus_read_word_data(client, DA280_REG_ACC_Z_LSB);
+	if (ret < 0)
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+
+	/* If not present Z reports max pos value (14 bits, 2 low bits 0) */
+	if (ret == 32764) {
+		data->accelerometer.compatible = "miramems,da226";
+		data->accelerometer.model = da226;
+	} else {
 		data->accelerometer.compatible = "miramems,da280";
 		data->accelerometer.model = da280;
-		return 0;
 	}
 
-	return id == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+	ret = i2c_smbus_write_byte_data(client, DA280_REG_MODE_BW,
+					DA280_MODE_DISABLE);
+	if (ret)
+		return ret == -ETIMEDOUT ? -ETIMEDOUT : -ENODEV;
+
+	return 0;
 }
 
 static int q8_hardwaremgr_probe_da311(struct q8_hardwaremgr_data *data,
@@ -625,6 +691,7 @@ static int q8_hardwaremgr_probe_accelerometer(struct q8_hardwaremgr_data *data,
 	PROBE_CLIENT(&data->accelerometer, 0x1d, q8_hardwaremgr_probe_dmard09);
 	PROBE_CLIENT(&data->accelerometer, 0x18, q8_hardwaremgr_probe_dmard10);
 	PROBE_CLIENT(&data->accelerometer, 0x26, q8_hardwaremgr_probe_da280);
+	PROBE_CLIENT(&data->accelerometer, 0x27, q8_hardwaremgr_probe_da280);
 	PROBE_CLIENT(&data->accelerometer, 0x27, q8_hardwaremgr_probe_da311);
 
 	return -ENODEV;
-- 
2.9.3

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

* [PATCH 6/6] misc: q8-hardwaremgr: Add quirk handling
  2016-10-14  7:53 ` Hans de Goede
@ 2016-10-14  7:53     ` Hans de Goede
  -1 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-14  7:53 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland, Arnd Bergmann, Greg Kroah-Hartman
  Cc: Maxime Ripard, Chen-Yu Tsai,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
	Hans de Goede

Some models require some special handling, e.g. one q8 tablet I've needs
esp,crystal-26M-en = <1> in the sdio_wifi dt node for the wifi to work
properly.

Add a q8_hardwaremgr_apply_quirks() helper function which identifies the
tablet based on the detected soc, touchscreen, accelerometer combo and
applies model specific quirks where necessary.

Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 drivers/misc/q8-hardwaremgr.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/misc/q8-hardwaremgr.c b/drivers/misc/q8-hardwaremgr.c
index 95cdaf2..cbf4f61 100644
--- a/drivers/misc/q8-hardwaremgr.c
+++ b/drivers/misc/q8-hardwaremgr.c
@@ -715,6 +715,28 @@ static void q8_hardwaremgr_apply_accelerometer(struct q8_hardwaremgr_data *data)
 	of_node_put(np);
 }
 
+static void q8_hardwaremgr_apply_quirks(struct q8_hardwaremgr_data *data)
+{
+	struct device_node *np;
+	struct of_changeset cset;
+
+	/* This A33 tzx-723q4 PCB tablet with esp8089 needs crystal_26M_en=1 */
+	if (data->soc == a33 && data->touchscreen.model == gsl1680_b482 &&
+	    data->accelerometer.model == dmard09 && !data->has_rda599x) {
+		dev_info(data->dev, "Applying crystal_26M_en=1 sdio_wifi quirk\n");
+		np = of_find_node_by_name(of_root, "sdio_wifi");
+		if (!np) {
+			dev_warn(data->dev, "Could not find sdio_wifi dt node\n");
+			return;
+		}
+		of_changeset_init(&cset);
+		of_changeset_add_property_u32(&cset, np,
+					      "esp,crystal-26M-en", 1);
+		of_changeset_apply(&cset);
+		of_node_put(np);
+	}
+}
+
 static int q8_hardwaremgr_do_probe(struct q8_hardwaremgr_data *data,
 				   struct q8_hardwaremgr_device *dev,
 				   const char *prefix, bus_probe_func func)
@@ -846,6 +868,7 @@ static int q8_hardwaremgr_probe(struct platform_device *pdev)
 
 	q8_hardwaremgr_apply_touchscreen(data);
 	q8_hardwaremgr_apply_accelerometer(data);
+	q8_hardwaremgr_apply_quirks(data);
 
 error:
 	kfree(data);
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 6/6] misc: q8-hardwaremgr: Add quirk handling
@ 2016-10-14  7:53     ` Hans de Goede
  0 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-14  7:53 UTC (permalink / raw)
  To: linux-arm-kernel

Some models require some special handling, e.g. one q8 tablet I've needs
esp,crystal-26M-en = <1> in the sdio_wifi dt node for the wifi to work
properly.

Add a q8_hardwaremgr_apply_quirks() helper function which identifies the
tablet based on the detected soc, touchscreen, accelerometer combo and
applies model specific quirks where necessary.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/misc/q8-hardwaremgr.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/misc/q8-hardwaremgr.c b/drivers/misc/q8-hardwaremgr.c
index 95cdaf2..cbf4f61 100644
--- a/drivers/misc/q8-hardwaremgr.c
+++ b/drivers/misc/q8-hardwaremgr.c
@@ -715,6 +715,28 @@ static void q8_hardwaremgr_apply_accelerometer(struct q8_hardwaremgr_data *data)
 	of_node_put(np);
 }
 
+static void q8_hardwaremgr_apply_quirks(struct q8_hardwaremgr_data *data)
+{
+	struct device_node *np;
+	struct of_changeset cset;
+
+	/* This A33 tzx-723q4 PCB tablet with esp8089 needs crystal_26M_en=1 */
+	if (data->soc == a33 && data->touchscreen.model == gsl1680_b482 &&
+	    data->accelerometer.model == dmard09 && !data->has_rda599x) {
+		dev_info(data->dev, "Applying crystal_26M_en=1 sdio_wifi quirk\n");
+		np = of_find_node_by_name(of_root, "sdio_wifi");
+		if (!np) {
+			dev_warn(data->dev, "Could not find sdio_wifi dt node\n");
+			return;
+		}
+		of_changeset_init(&cset);
+		of_changeset_add_property_u32(&cset, np,
+					      "esp,crystal-26M-en", 1);
+		of_changeset_apply(&cset);
+		of_node_put(np);
+	}
+}
+
 static int q8_hardwaremgr_do_probe(struct q8_hardwaremgr_data *data,
 				   struct q8_hardwaremgr_device *dev,
 				   const char *prefix, bus_probe_func func)
@@ -846,6 +868,7 @@ static int q8_hardwaremgr_probe(struct platform_device *pdev)
 
 	q8_hardwaremgr_apply_touchscreen(data);
 	q8_hardwaremgr_apply_accelerometer(data);
+	q8_hardwaremgr_apply_quirks(data);
 
 error:
 	kfree(data);
-- 
2.9.3

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

* Re: Add Allwinner Q8 tablets hardware manager
  2016-10-14  7:53 ` Hans de Goede
@ 2016-10-24 17:39     ` Mark Rutland
  -1 siblings, 0 replies; 48+ messages in thread
From: Mark Rutland @ 2016-10-24 17:39 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Rob Herring, Arnd Bergmann, Greg Kroah-Hartman, Maxime Ripard,
	Chen-Yu Tsai, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree

On Fri, Oct 14, 2016 at 09:53:31AM +0200, Hans de Goede wrote:
> Hi Rob, Mark, et al.,

Hi Hans,

Apologies for the delay in replying to this.

I'd like to be clear that I do understand that there is a problem that
needs to be addressed here. However, I do not believe that the *current*
in-kernel approach is correct. More on that below.

> Mark, I know that we discussed this at ELCE and you clearly indicated
> that according to you this does not belong in the kernel. I was a bit
> surprised by this part of the discussion.
> 
> I had posted a RFC earlier and Rob had indicated that given that the q8
> tablets are a special case, as my code uses actual probing rather then some
> pre-arranged id mechanism with say an eeprom, that doing this in a
> non-generic manner would be ok for my special case.

To some extent, Rob and I may have differing views here; I'm not
entirely sure what Rob's view is, and I cannot talk on his behalf. I
certainly must apologise for having not commented on said RFC, however.

> So on to why I believe that the kernel is the best place to do this, at least
> for my special use-case:
> 
> 1. Configurability
> 
> Since the q8 tablets do not have any id mechanism I'm probing i2c busses to
> generate i2c client dt nodes with the right address and compatible.
> Some info in these nodes (e.g. touchscreen firmware-name) is not probable at
> all and gets set by heuristics. This heuristics may get things wrong.
> So my current implementation offers kernel cmdline options to override this.

As I mentioned at ELCE, one major concern I have with this approach is
this probing, which in part relies on a collection of heuristics.

I'm worried that this is very fragile, and sets us up for having to
maintain a much larger collection of heuristics and/or a database of
particular boards in future. This is fragile, defeats much of the gain
from DT.

Worse, this could be completely incompatible with some arbitrary board
that comes by in future, because the kernel assumed something that was
not true, which it would not have done if things were explicitly
described to the kernel.

As I mentioned at ELCE, I'm not opposed to the concept of the kernel
applying overlays or fixups based on a well-defined set of criteria;
having some of that embedded in the DT itself would be remarkably
helpful. However, I am very much not keen on loosely defined criteria as
with here, as it couples the DT and kernel, and creates problems longer
term, as described above.

> Although having to specify kernel cmdline options is not the plug and play
> experience I want to give end-users most distros do have documentation on
> how to do this and doing this is relatively easy for end-users. Moving this
> to the bootloader means moving to some bootloader specific config mechanism
> which is going to be quite hard (and possibly dangerous) for users to use.

I have to ask, why is it more dangerous?

Perhaps more difficult, but that can be solved, if the manual
corrections are simply a set of options to be passed to the kernel, I
don't see why the bootloader cannot pick this up.

> 2. Upgradability
> 
> Most users treat the bootloader like they treat an x86 machine BIOS/EFI,
> they will never upgrade it unless they really have to. This means that it
> will be very difficult to get users to actual benefit from bug-fixes /
> improvements done to the probing code. Where as the kernel on boards running
> e.g. Debian or Fedora gets regular updates together with the rest of the
> system.

Given that DTBs are supposed to remain supported, users should find
themselves with a system that continues to work, but may not have all
the bells and whistles it could, much like elsewhere.

While it's true that we have issues in this area, I don't think that's
an argument for putting things into the kernel for this specific set of
boards.

> 3. Infrastructure
> 
> The kernel simply has better infrastructure for doing these kind of things.

At least on the DT front, a lot of work has gone into improving the
infrastructure, e.g. the work that Free Electrons have done [1]. I
appreciate that the infrastructure for things like poking SPI may not be
as advanced.

Which bits of infrastructure do you find lacking today?

> Yes we could improve the bootloader, but the kernel is also improving
> and likely at a faster rate. Besides that the purpose of the
> bootloader is mostly to be simple and small, load the kernel and get
> out of the way, not to be a general purpose os kernel. So it will
> simply always have less infrastructure and that is a good thing,
> otherwise we will be writing another general purpose os which is a
> waste of effort.

I think this conflates a number of details. Yes, we'd like firmware and
bootloaders to be small, and yes, their infrastructure and feature
support will be smaller than a general purpose OS.

That doesn't imply that they cannot have features necessary to boostrap
an OS.

It's also not strictly necessary that the firmware or bootloader have
the capability to do all this probing, as that could be contained in
another part (e.g. a U-Boot application which is run once to detect the
board details, logging this into a file).

It's also possible to ship an intermediary stage (e.g. like the
impedance matcher) which can be upgradeable independently of the kernel.

> 4. This is not a new board file
> 
> Mark, at ELCE I got the feeling that your biggest worry / objection is
> that this will bring back board files, but that is not the case, if you
> look at the actual code it is nothing like a board-file at all. Where a
> board file was instantiating device after device after device from c-code,
> with maybe a few if-s in there to deal with board revisions. This code is
> all about figuring out which accelerometer and touchscreen there are,
> to then add nodes to the dt for this 2 devices, almost all the code is
> probing, the actual dt modifying code is tiny and no direct device
> instantiation is done at all.

Sorry, but I must disagree. This code:

(a) identifies a set of boards based on a top-level compatible string.
    i.e. it's sole purpose is to handle those boards.

(b) assumes non-general properties of those boards (e.g. that poking
    certain SPI endpoints is safe).

(c) applies arbitrary properties to the DT, applying in-built knowledge
    of those boards (in addition to deep structural knowledge of the
    DTB in question).

To me, given the implicit knowledge, that qualifies as a "board file".

As I mentioned at ELCE, if this had no knowledge of the boards in
question, I would be less concerned. e.g. if there was a well-defined
identification mechanism, describe in the DT, with fixups also defined
in the DT.

> 5. This is an exception, not the rule
> 
> Yes this is introducing board (family of boards) specific c-code into the
> kernel, so in a way it is reminiscent of board files. But sometimes this is
> necessary, just look at all the vendor / platform specific code in the kernel
> in drivers/platform/x86, or all the places where DMI strings are used to
> uniquely identify a x86 board and adjust behavior.
> 
> But this really is the exception, not the rule. I've written/upstreamed a
> number of drivers for q8 tablets hardware and if you look at e.g. the
> silead touchscreen driver then in linux-next this is already used for 5
> ARM dts files where no board specific C-code is involved at all.
> 
> So this again is very different from the board file era, where C-code
> had to be used to fill device specific platform-data structs, here all
> necessary info is contained in the dt-binding and there are many users
> who do not need any board specific C-code in the kernel at all.
> 
> So dt is working as it should and is avoiding board specific C-code for
> the majority of the cases. But sometimes hardware is not as we ideally
> would like it to be; and for those *exceptions* we are sometimes going
> to need C-code in the kernel, just like there is "board" specific C-code
> in the x86 code.

Your talk convinced me that we're both going to see more variation
within this family of boards, and that we'll see more families of boards
following a similar patter. Given that, I think that we need a more
general solution, as I commented on the RFC.

That doesn't necessarily mean that this can't happen in the kernel, but
it certainly needs to be more strictly defined, e.g. with match criteria
and fixups explicit in the DTB.

Thanks,
Mark.

[1] http://free-electrons.com/blog/dt-overlay-uboot-libfdt/
[2] https://github.com/zonque/pxa-impedance-matcher
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-24 17:39     ` Mark Rutland
  0 siblings, 0 replies; 48+ messages in thread
From: Mark Rutland @ 2016-10-24 17:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 14, 2016 at 09:53:31AM +0200, Hans de Goede wrote:
> Hi Rob, Mark, et al.,

Hi Hans,

Apologies for the delay in replying to this.

I'd like to be clear that I do understand that there is a problem that
needs to be addressed here. However, I do not believe that the *current*
in-kernel approach is correct. More on that below.

> Mark, I know that we discussed this at ELCE and you clearly indicated
> that according to you this does not belong in the kernel. I was a bit
> surprised by this part of the discussion.
> 
> I had posted a RFC earlier and Rob had indicated that given that the q8
> tablets are a special case, as my code uses actual probing rather then some
> pre-arranged id mechanism with say an eeprom, that doing this in a
> non-generic manner would be ok for my special case.

To some extent, Rob and I may have differing views here; I'm not
entirely sure what Rob's view is, and I cannot talk on his behalf. I
certainly must apologise for having not commented on said RFC, however.

> So on to why I believe that the kernel is the best place to do this, at least
> for my special use-case:
> 
> 1. Configurability
> 
> Since the q8 tablets do not have any id mechanism I'm probing i2c busses to
> generate i2c client dt nodes with the right address and compatible.
> Some info in these nodes (e.g. touchscreen firmware-name) is not probable at
> all and gets set by heuristics. This heuristics may get things wrong.
> So my current implementation offers kernel cmdline options to override this.

As I mentioned at ELCE, one major concern I have with this approach is
this probing, which in part relies on a collection of heuristics.

I'm worried that this is very fragile, and sets us up for having to
maintain a much larger collection of heuristics and/or a database of
particular boards in future. This is fragile, defeats much of the gain
from DT.

Worse, this could be completely incompatible with some arbitrary board
that comes by in future, because the kernel assumed something that was
not true, which it would not have done if things were explicitly
described to the kernel.

As I mentioned at ELCE, I'm not opposed to the concept of the kernel
applying overlays or fixups based on a well-defined set of criteria;
having some of that embedded in the DT itself would be remarkably
helpful. However, I am very much not keen on loosely defined criteria as
with here, as it couples the DT and kernel, and creates problems longer
term, as described above.

> Although having to specify kernel cmdline options is not the plug and play
> experience I want to give end-users most distros do have documentation on
> how to do this and doing this is relatively easy for end-users. Moving this
> to the bootloader means moving to some bootloader specific config mechanism
> which is going to be quite hard (and possibly dangerous) for users to use.

I have to ask, why is it more dangerous?

Perhaps more difficult, but that can be solved, if the manual
corrections are simply a set of options to be passed to the kernel, I
don't see why the bootloader cannot pick this up.

> 2. Upgradability
> 
> Most users treat the bootloader like they treat an x86 machine BIOS/EFI,
> they will never upgrade it unless they really have to. This means that it
> will be very difficult to get users to actual benefit from bug-fixes /
> improvements done to the probing code. Where as the kernel on boards running
> e.g. Debian or Fedora gets regular updates together with the rest of the
> system.

Given that DTBs are supposed to remain supported, users should find
themselves with a system that continues to work, but may not have all
the bells and whistles it could, much like elsewhere.

While it's true that we have issues in this area, I don't think that's
an argument for putting things into the kernel for this specific set of
boards.

> 3. Infrastructure
> 
> The kernel simply has better infrastructure for doing these kind of things.

At least on the DT front, a lot of work has gone into improving the
infrastructure, e.g. the work that Free Electrons have done [1]. I
appreciate that the infrastructure for things like poking SPI may not be
as advanced.

Which bits of infrastructure do you find lacking today?

> Yes we could improve the bootloader, but the kernel is also improving
> and likely at a faster rate. Besides that the purpose of the
> bootloader is mostly to be simple and small, load the kernel and get
> out of the way, not to be a general purpose os kernel. So it will
> simply always have less infrastructure and that is a good thing,
> otherwise we will be writing another general purpose os which is a
> waste of effort.

I think this conflates a number of details. Yes, we'd like firmware and
bootloaders to be small, and yes, their infrastructure and feature
support will be smaller than a general purpose OS.

That doesn't imply that they cannot have features necessary to boostrap
an OS.

It's also not strictly necessary that the firmware or bootloader have
the capability to do all this probing, as that could be contained in
another part (e.g. a U-Boot application which is run once to detect the
board details, logging this into a file).

It's also possible to ship an intermediary stage (e.g. like the
impedance matcher) which can be upgradeable independently of the kernel.

> 4. This is not a new board file
> 
> Mark, at ELCE I got the feeling that your biggest worry / objection is
> that this will bring back board files, but that is not the case, if you
> look at the actual code it is nothing like a board-file at all. Where a
> board file was instantiating device after device after device from c-code,
> with maybe a few if-s in there to deal with board revisions. This code is
> all about figuring out which accelerometer and touchscreen there are,
> to then add nodes to the dt for this 2 devices, almost all the code is
> probing, the actual dt modifying code is tiny and no direct device
> instantiation is done at all.

Sorry, but I must disagree. This code:

(a) identifies a set of boards based on a top-level compatible string.
    i.e. it's sole purpose is to handle those boards.

(b) assumes non-general properties of those boards (e.g. that poking
    certain SPI endpoints is safe).

(c) applies arbitrary properties to the DT, applying in-built knowledge
    of those boards (in addition to deep structural knowledge of the
    DTB in question).

To me, given the implicit knowledge, that qualifies as a "board file".

As I mentioned at ELCE, if this had no knowledge of the boards in
question, I would be less concerned. e.g. if there was a well-defined
identification mechanism, describe in the DT, with fixups also defined
in the DT.

> 5. This is an exception, not the rule
> 
> Yes this is introducing board (family of boards) specific c-code into the
> kernel, so in a way it is reminiscent of board files. But sometimes this is
> necessary, just look at all the vendor / platform specific code in the kernel
> in drivers/platform/x86, or all the places where DMI strings are used to
> uniquely identify a x86 board and adjust behavior.
> 
> But this really is the exception, not the rule. I've written/upstreamed a
> number of drivers for q8 tablets hardware and if you look at e.g. the
> silead touchscreen driver then in linux-next this is already used for 5
> ARM dts files where no board specific C-code is involved at all.
> 
> So this again is very different from the board file era, where C-code
> had to be used to fill device specific platform-data structs, here all
> necessary info is contained in the dt-binding and there are many users
> who do not need any board specific C-code in the kernel at all.
> 
> So dt is working as it should and is avoiding board specific C-code for
> the majority of the cases. But sometimes hardware is not as we ideally
> would like it to be; and for those *exceptions* we are sometimes going
> to need C-code in the kernel, just like there is "board" specific C-code
> in the x86 code.

Your talk convinced me that we're both going to see more variation
within this family of boards, and that we'll see more families of boards
following a similar patter. Given that, I think that we need a more
general solution, as I commented on the RFC.

That doesn't necessarily mean that this can't happen in the kernel, but
it certainly needs to be more strictly defined, e.g. with match criteria
and fixups explicit in the DTB.

Thanks,
Mark.

[1] http://free-electrons.com/blog/dt-overlay-uboot-libfdt/
[2] https://github.com/zonque/pxa-impedance-matcher

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

* Re: Add Allwinner Q8 tablets hardware manager
  2016-10-24 17:39     ` Mark Rutland
@ 2016-10-26 11:46       ` Hans de Goede
  -1 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-26 11:46 UTC (permalink / raw)
  To: Mark Rutland
  Cc: devicetree, Arnd Bergmann, Greg Kroah-Hartman, Pantelis Antoniou,
	Chen-Yu Tsai, Rob Herring, Maxime Ripard, linux-arm-kernel

Hi,

On 24-10-16 19:39, Mark Rutland wrote:
> On Fri, Oct 14, 2016 at 09:53:31AM +0200, Hans de Goede wrote:
>> Hi Rob, Mark, et al.,
>
> Hi Hans,
>
> Apologies for the delay in replying to this.

No worries, I believe that 1 week is actually a pretty good
turn around time, esp. directly after a conference.

> I'd like to be clear that I do understand that there is a problem that
> needs to be addressed here. However, I do not believe that the *current*
> in-kernel approach is correct. More on that below.

Ok.

>> Mark, I know that we discussed this at ELCE and you clearly indicated
>> that according to you this does not belong in the kernel. I was a bit
>> surprised by this part of the discussion.
>>
>> I had posted a RFC earlier and Rob had indicated that given that the q8
>> tablets are a special case, as my code uses actual probing rather then some
>> pre-arranged id mechanism with say an eeprom, that doing this in a
>> non-generic manner would be ok for my special case.
>
> To some extent, Rob and I may have differing views here; I'm not
> entirely sure what Rob's view is, and I cannot talk on his behalf. I
> certainly must apologise for having not commented on said RFC, however.
>
>> So on to why I believe that the kernel is the best place to do this, at least
>> for my special use-case:
>>
>> 1. Configurability
>>
>> Since the q8 tablets do not have any id mechanism I'm probing i2c busses to
>> generate i2c client dt nodes with the right address and compatible.
>> Some info in these nodes (e.g. touchscreen firmware-name) is not probable at
>> all and gets set by heuristics. This heuristics may get things wrong.
>> So my current implementation offers kernel cmdline options to override this.
>
> As I mentioned at ELCE, one major concern I have with this approach is
> this probing, which in part relies on a collection of heuristics.

This is quite use-case specific, anyways, the probing is a 2 step process:

1) Identify which hardware there is in the tablet, this is pretty
reliable, we only detect a fix set of known possible touchscreens
and accelerometers, at known addresses and almost all have an id
register to check.

2) Determine *defaults* for various none probable settings, like guessing
which firmware to load into the touchscreen controllers, as there are
at least 2 ways the gsl1680 is wired up on these tablets and this
requires 2 different firmware files. This uses heuristics, to, as said,
determine the defaults all of the non-probable bits are overidable
through config options (currently kernel module options). Getting these
wrong is not dangerous to the hardware, but will work in a non-functional
or misbehaving (wrong coordinates) touchscreen.

Note with the models I've access to so far the heuristics score 100%
but I'm not sure how representative the 16 models I've access to are
(they are all different and have been bought over a span of multiple
years).

> I'm worried that this is very fragile, and sets us up for having to
> maintain a much larger collection of heuristics and/or a database of
> particular boards in future. This is fragile, defeats much of the gain
> from DT.

I understand your worries, as said I'm confident the actual probing
is safe and getting the heuristics wrong will result in misbehavior,
but not in any hardware damage or such.

> Worse, this could be completely incompatible with some arbitrary board
> that comes by in future,

I assume you mean an arbitrary q8 tablet here, as the probe code does
bind by board/machine compatible, so for a really arbitrary board
this code will never activate.

> because the kernel assumed something that was
> not true, which it would not have done if things were explicitly
> described to the kernel.

I understand your worry, but moving the probing code to say u-boot
will not change any of this, the kernel will get the explicit
description created by the u-boot probe code, but it would be
just as wrong.

So maybe we need to answer 2 questions in a row:

1) Do we want such probe code at all ?

My answer to this is yes, these (cheap) tablets are interesting to
e.g. the maker community and I would like them to run mainline
(and run mainline well), but given the way there are put together
this require some code to dynamically adapt to the batch of the
month somewhere

2) Where do we put this code ?

If we agree on 1 (I assume we do) then this becomes the real
question, at which point your worries about the kernel assuming
something which is not true because the probe code got it wrong
may become true regardless where the code lives.

So wrt this worries is all I can do is ask you to trust me to
not mess things up, just like we all trust driver authors, etc.
all the time to not mess things up.

> As I mentioned at ELCE, I'm not opposed to the concept of the kernel
> applying overlays or fixups based on a well-defined set of criteria;
> having some of that embedded in the DT itself would be remarkably
> helpful.  However, I am very much not keen on loosely defined criteria as
> with here, as it couples the DT and kernel, and creates problems longer
> term, as described above.

Right, so again I think we need to split the discussion in 2 steps:

1) How do we apply the fixups, currently I'm using free-form changes
done from C-code. I can envision moving to something like the quirk
mechanism suggested by Pantelis in the past. Note this is not a perfect
fit for my rather corner-case use-case, but I can understand that in
general you want the variants to be described in dt, and activated
in some way, rather then have c-code make free-form changes to the dt

2) How do we select which fixups to apply. Again I can understand
you wanting some well defined mechanism for this, but again my
use-case is special and simply does not allow for this as there
is no id-eeprom to read or some such.

>> Although having to specify kernel cmdline options is not the plug and play
>> experience I want to give end-users most distros do have documentation on
>> how to do this and doing this is relatively easy for end-users. Moving this
>> to the bootloader means moving to some bootloader specific config mechanism
>> which is going to be quite hard (and possibly dangerous) for users to use.
>
> I have to ask, why is it more dangerous?

Because for normal end users meddling with the bootloader / with u-boot's
environment is like flashing a PC BIOS. Most (non technical) end users will
want to install u-boot once (or not at all) and then just have it work.

> Perhaps more difficult, but that can be solved,

More difficult means not doable for many users.

> if the manual
> corrections are simply a set of options to be passed to the kernel, I
> don't see why the bootloader cannot pick this up.
>
>> 2. Upgradability
>>
>> Most users treat the bootloader like they treat an x86 machine BIOS/EFI,
>> they will never upgrade it unless they really have to. This means that it
>> will be very difficult to get users to actual benefit from bug-fixes /
>> improvements done to the probing code. Where as the kernel on boards running
>> e.g. Debian or Fedora gets regular updates together with the rest of the
>> system.
>
> Given that DTBs are supposed to remain supported, users should find
> themselves with a system that continues to work, but may not have all
> the bells and whistles it could, much like elsewhere.
>
> While it's true that we have issues in this area, I don't think that's
> an argument for putting things into the kernel for this specific set of
> boards.

It is an argument to put much of the dynamic (dt) hardware support in
the kernel in general.

>> 3. Infrastructure
>>
>> The kernel simply has better infrastructure for doing these kind of things.
>
> At least on the DT front, a lot of work has gone into improving the
> infrastructure, e.g. the work that Free Electrons have done [1]. I
> appreciate that the infrastructure for things like poking SPI may not be
> as advanced.
>
> Which bits of infrastructure do you find lacking today?

Nothing really specific (I've not yet tried porting the probe code
to u-boot), but I just find working within the kernel easier in general,
since there really just is a lot more infrastructure. Note I'm the
upstream u-boot maintainer for the allwinner SoC support, so this
is not due to me being unfamiliar with u-boot.

>> Yes we could improve the bootloader, but the kernel is also improving
>> and likely at a faster rate. Besides that the purpose of the
>> bootloader is mostly to be simple and small, load the kernel and get
>> out of the way, not to be a general purpose os kernel. So it will
>> simply always have less infrastructure and that is a good thing,
>> otherwise we will be writing another general purpose os which is a
>> waste of effort.
>
> I think this conflates a number of details. Yes, we'd like firmware and
> bootloaders to be small, and yes, their infrastructure and feature
> support will be smaller than a general purpose OS.
>
> That doesn't imply that they cannot have features necessary to boostrap
> an OS.
>
> It's also not strictly necessary that the firmware or bootloader have
> the capability to do all this probing, as that could be contained in
> another part (e.g. a U-Boot application which is run once to detect the
> board details, logging this into a file).
>
> It's also possible to ship an intermediary stage (e.g. like the
> impedance matcher) which can be upgradeable independently of the kernel.

Yes there are other solutions, but they all involve a lot more
moving pieces (and thus will break) then a single isolated .c file
in the kernel, which is all this series adds.

Esp the intermediate solution just adds a ton of complexity with 0
gain.

>> 4. This is not a new board file
>>
>> Mark, at ELCE I got the feeling that your biggest worry / objection is
>> that this will bring back board files, but that is not the case, if you
>> look at the actual code it is nothing like a board-file at all. Where a
>> board file was instantiating device after device after device from c-code,
>> with maybe a few if-s in there to deal with board revisions. This code is
>> all about figuring out which accelerometer and touchscreen there are,
>> to then add nodes to the dt for this 2 devices, almost all the code is
>> probing, the actual dt modifying code is tiny and no direct device
>> instantiation is done at all.
>
> Sorry, but I must disagree. This code:
>
> (a) identifies a set of boards based on a top-level compatible string.
>     i.e. it's sole purpose is to handle those boards.
>
> (b) assumes non-general properties of those boards (e.g. that poking
>     certain SPI endpoints is safe).
>
> (c) applies arbitrary properties to the DT, applying in-built knowledge
>     of those boards (in addition to deep structural knowledge of the
>     DTB in question).
>
> To me, given the implicit knowledge, that qualifies as a "board file".
>
> As I mentioned at ELCE, if this had no knowledge of the boards in
> question, I would be less concerned. e.g. if there was a well-defined
> identification mechanism, describe in the DT, with fixups also defined
> in the DT.

And as I tried to explain before, for this specific use-case describing
all this board specific knowledge in a generic manner in dt is simply
impossible, unless we add a turing complete language to dt aka aml.

I've a feeling that you're mixing this, rather special, use-case with
the more generic use-case of daughter-boards for various small-board-computers
I agree that for the SBC use-case it makes sense to try and come up with
a shared core / dt bindings for much of this. Note that even this boards
will still need a board (or board-family) specific method for getting
the actual id from a daughter-board, but this board specific code could
then pass the id to some more general hw-manager core which starts applying
dt changes based on the id. But this assumes there is a single id to
uniquely identify the extensions, which in my case there simply is not.

>> 5. This is an exception, not the rule
>>
>> Yes this is introducing board (family of boards) specific c-code into the
>> kernel, so in a way it is reminiscent of board files. But sometimes this is
>> necessary, just look at all the vendor / platform specific code in the kernel
>> in drivers/platform/x86, or all the places where DMI strings are used to
>> uniquely identify a x86 board and adjust behavior.
>>
>> But this really is the exception, not the rule. I've written/upstreamed a
>> number of drivers for q8 tablets hardware and if you look at e.g. the
>> silead touchscreen driver then in linux-next this is already used for 5
>> ARM dts files where no board specific C-code is involved at all.
>>
>> So this again is very different from the board file era, where C-code
>> had to be used to fill device specific platform-data structs, here all
>> necessary info is contained in the dt-binding and there are many users
>> who do not need any board specific C-code in the kernel at all.
>>
>> So dt is working as it should and is avoiding board specific C-code for
>> the majority of the cases. But sometimes hardware is not as we ideally
>> would like it to be; and for those *exceptions* we are sometimes going
>> to need C-code in the kernel, just like there is "board" specific C-code
>> in the x86 code.
>
> Your talk convinced me that we're both going to see more variation
> within this family of boards, and that we'll see more families of boards
> following a similar patter. Given that, I think that we need a more
> general solution, as I commented on the RFC.
>
> That doesn't necessarily mean that this can't happen in the kernel, but
> it certainly needs to be more strictly defined, e.g. with match criteria
> and fixups explicit in the DTB.

The only answer I've to: "with match criteria and fixups explicit in the DTB"
is: ok, give my a turing complete language inside DTB then, anything else
will not suffice. So either we are doomed to reinvent ACPI; or we must
accept some board(family) specific C-code in the kernel.

Regards,

Hans

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-26 11:46       ` Hans de Goede
  0 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-26 11:46 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 24-10-16 19:39, Mark Rutland wrote:
> On Fri, Oct 14, 2016 at 09:53:31AM +0200, Hans de Goede wrote:
>> Hi Rob, Mark, et al.,
>
> Hi Hans,
>
> Apologies for the delay in replying to this.

No worries, I believe that 1 week is actually a pretty good
turn around time, esp. directly after a conference.

> I'd like to be clear that I do understand that there is a problem that
> needs to be addressed here. However, I do not believe that the *current*
> in-kernel approach is correct. More on that below.

Ok.

>> Mark, I know that we discussed this at ELCE and you clearly indicated
>> that according to you this does not belong in the kernel. I was a bit
>> surprised by this part of the discussion.
>>
>> I had posted a RFC earlier and Rob had indicated that given that the q8
>> tablets are a special case, as my code uses actual probing rather then some
>> pre-arranged id mechanism with say an eeprom, that doing this in a
>> non-generic manner would be ok for my special case.
>
> To some extent, Rob and I may have differing views here; I'm not
> entirely sure what Rob's view is, and I cannot talk on his behalf. I
> certainly must apologise for having not commented on said RFC, however.
>
>> So on to why I believe that the kernel is the best place to do this, at least
>> for my special use-case:
>>
>> 1. Configurability
>>
>> Since the q8 tablets do not have any id mechanism I'm probing i2c busses to
>> generate i2c client dt nodes with the right address and compatible.
>> Some info in these nodes (e.g. touchscreen firmware-name) is not probable at
>> all and gets set by heuristics. This heuristics may get things wrong.
>> So my current implementation offers kernel cmdline options to override this.
>
> As I mentioned at ELCE, one major concern I have with this approach is
> this probing, which in part relies on a collection of heuristics.

This is quite use-case specific, anyways, the probing is a 2 step process:

1) Identify which hardware there is in the tablet, this is pretty
reliable, we only detect a fix set of known possible touchscreens
and accelerometers, at known addresses and almost all have an id
register to check.

2) Determine *defaults* for various none probable settings, like guessing
which firmware to load into the touchscreen controllers, as there are
at least 2 ways the gsl1680 is wired up on these tablets and this
requires 2 different firmware files. This uses heuristics, to, as said,
determine the defaults all of the non-probable bits are overidable
through config options (currently kernel module options). Getting these
wrong is not dangerous to the hardware, but will work in a non-functional
or misbehaving (wrong coordinates) touchscreen.

Note with the models I've access to so far the heuristics score 100%
but I'm not sure how representative the 16 models I've access to are
(they are all different and have been bought over a span of multiple
years).

> I'm worried that this is very fragile, and sets us up for having to
> maintain a much larger collection of heuristics and/or a database of
> particular boards in future. This is fragile, defeats much of the gain
> from DT.

I understand your worries, as said I'm confident the actual probing
is safe and getting the heuristics wrong will result in misbehavior,
but not in any hardware damage or such.

> Worse, this could be completely incompatible with some arbitrary board
> that comes by in future,

I assume you mean an arbitrary q8 tablet here, as the probe code does
bind by board/machine compatible, so for a really arbitrary board
this code will never activate.

> because the kernel assumed something that was
> not true, which it would not have done if things were explicitly
> described to the kernel.

I understand your worry, but moving the probing code to say u-boot
will not change any of this, the kernel will get the explicit
description created by the u-boot probe code, but it would be
just as wrong.

So maybe we need to answer 2 questions in a row:

1) Do we want such probe code at all ?

My answer to this is yes, these (cheap) tablets are interesting to
e.g. the maker community and I would like them to run mainline
(and run mainline well), but given the way there are put together
this require some code to dynamically adapt to the batch of the
month somewhere

2) Where do we put this code ?

If we agree on 1 (I assume we do) then this becomes the real
question, at which point your worries about the kernel assuming
something which is not true because the probe code got it wrong
may become true regardless where the code lives.

So wrt this worries is all I can do is ask you to trust me to
not mess things up, just like we all trust driver authors, etc.
all the time to not mess things up.

> As I mentioned at ELCE, I'm not opposed to the concept of the kernel
> applying overlays or fixups based on a well-defined set of criteria;
> having some of that embedded in the DT itself would be remarkably
> helpful.  However, I am very much not keen on loosely defined criteria as
> with here, as it couples the DT and kernel, and creates problems longer
> term, as described above.

Right, so again I think we need to split the discussion in 2 steps:

1) How do we apply the fixups, currently I'm using free-form changes
done from C-code. I can envision moving to something like the quirk
mechanism suggested by Pantelis in the past. Note this is not a perfect
fit for my rather corner-case use-case, but I can understand that in
general you want the variants to be described in dt, and activated
in some way, rather then have c-code make free-form changes to the dt

2) How do we select which fixups to apply. Again I can understand
you wanting some well defined mechanism for this, but again my
use-case is special and simply does not allow for this as there
is no id-eeprom to read or some such.

>> Although having to specify kernel cmdline options is not the plug and play
>> experience I want to give end-users most distros do have documentation on
>> how to do this and doing this is relatively easy for end-users. Moving this
>> to the bootloader means moving to some bootloader specific config mechanism
>> which is going to be quite hard (and possibly dangerous) for users to use.
>
> I have to ask, why is it more dangerous?

Because for normal end users meddling with the bootloader / with u-boot's
environment is like flashing a PC BIOS. Most (non technical) end users will
want to install u-boot once (or not at all) and then just have it work.

> Perhaps more difficult, but that can be solved,

More difficult means not doable for many users.

> if the manual
> corrections are simply a set of options to be passed to the kernel, I
> don't see why the bootloader cannot pick this up.
>
>> 2. Upgradability
>>
>> Most users treat the bootloader like they treat an x86 machine BIOS/EFI,
>> they will never upgrade it unless they really have to. This means that it
>> will be very difficult to get users to actual benefit from bug-fixes /
>> improvements done to the probing code. Where as the kernel on boards running
>> e.g. Debian or Fedora gets regular updates together with the rest of the
>> system.
>
> Given that DTBs are supposed to remain supported, users should find
> themselves with a system that continues to work, but may not have all
> the bells and whistles it could, much like elsewhere.
>
> While it's true that we have issues in this area, I don't think that's
> an argument for putting things into the kernel for this specific set of
> boards.

It is an argument to put much of the dynamic (dt) hardware support in
the kernel in general.

>> 3. Infrastructure
>>
>> The kernel simply has better infrastructure for doing these kind of things.
>
> At least on the DT front, a lot of work has gone into improving the
> infrastructure, e.g. the work that Free Electrons have done [1]. I
> appreciate that the infrastructure for things like poking SPI may not be
> as advanced.
>
> Which bits of infrastructure do you find lacking today?

Nothing really specific (I've not yet tried porting the probe code
to u-boot), but I just find working within the kernel easier in general,
since there really just is a lot more infrastructure. Note I'm the
upstream u-boot maintainer for the allwinner SoC support, so this
is not due to me being unfamiliar with u-boot.

>> Yes we could improve the bootloader, but the kernel is also improving
>> and likely at a faster rate. Besides that the purpose of the
>> bootloader is mostly to be simple and small, load the kernel and get
>> out of the way, not to be a general purpose os kernel. So it will
>> simply always have less infrastructure and that is a good thing,
>> otherwise we will be writing another general purpose os which is a
>> waste of effort.
>
> I think this conflates a number of details. Yes, we'd like firmware and
> bootloaders to be small, and yes, their infrastructure and feature
> support will be smaller than a general purpose OS.
>
> That doesn't imply that they cannot have features necessary to boostrap
> an OS.
>
> It's also not strictly necessary that the firmware or bootloader have
> the capability to do all this probing, as that could be contained in
> another part (e.g. a U-Boot application which is run once to detect the
> board details, logging this into a file).
>
> It's also possible to ship an intermediary stage (e.g. like the
> impedance matcher) which can be upgradeable independently of the kernel.

Yes there are other solutions, but they all involve a lot more
moving pieces (and thus will break) then a single isolated .c file
in the kernel, which is all this series adds.

Esp the intermediate solution just adds a ton of complexity with 0
gain.

>> 4. This is not a new board file
>>
>> Mark, at ELCE I got the feeling that your biggest worry / objection is
>> that this will bring back board files, but that is not the case, if you
>> look at the actual code it is nothing like a board-file at all. Where a
>> board file was instantiating device after device after device from c-code,
>> with maybe a few if-s in there to deal with board revisions. This code is
>> all about figuring out which accelerometer and touchscreen there are,
>> to then add nodes to the dt for this 2 devices, almost all the code is
>> probing, the actual dt modifying code is tiny and no direct device
>> instantiation is done at all.
>
> Sorry, but I must disagree. This code:
>
> (a) identifies a set of boards based on a top-level compatible string.
>     i.e. it's sole purpose is to handle those boards.
>
> (b) assumes non-general properties of those boards (e.g. that poking
>     certain SPI endpoints is safe).
>
> (c) applies arbitrary properties to the DT, applying in-built knowledge
>     of those boards (in addition to deep structural knowledge of the
>     DTB in question).
>
> To me, given the implicit knowledge, that qualifies as a "board file".
>
> As I mentioned at ELCE, if this had no knowledge of the boards in
> question, I would be less concerned. e.g. if there was a well-defined
> identification mechanism, describe in the DT, with fixups also defined
> in the DT.

And as I tried to explain before, for this specific use-case describing
all this board specific knowledge in a generic manner in dt is simply
impossible, unless we add a turing complete language to dt aka aml.

I've a feeling that you're mixing this, rather special, use-case with
the more generic use-case of daughter-boards for various small-board-computers
I agree that for the SBC use-case it makes sense to try and come up with
a shared core / dt bindings for much of this. Note that even this boards
will still need a board (or board-family) specific method for getting
the actual id from a daughter-board, but this board specific code could
then pass the id to some more general hw-manager core which starts applying
dt changes based on the id. But this assumes there is a single id to
uniquely identify the extensions, which in my case there simply is not.

>> 5. This is an exception, not the rule
>>
>> Yes this is introducing board (family of boards) specific c-code into the
>> kernel, so in a way it is reminiscent of board files. But sometimes this is
>> necessary, just look at all the vendor / platform specific code in the kernel
>> in drivers/platform/x86, or all the places where DMI strings are used to
>> uniquely identify a x86 board and adjust behavior.
>>
>> But this really is the exception, not the rule. I've written/upstreamed a
>> number of drivers for q8 tablets hardware and if you look at e.g. the
>> silead touchscreen driver then in linux-next this is already used for 5
>> ARM dts files where no board specific C-code is involved at all.
>>
>> So this again is very different from the board file era, where C-code
>> had to be used to fill device specific platform-data structs, here all
>> necessary info is contained in the dt-binding and there are many users
>> who do not need any board specific C-code in the kernel at all.
>>
>> So dt is working as it should and is avoiding board specific C-code for
>> the majority of the cases. But sometimes hardware is not as we ideally
>> would like it to be; and for those *exceptions* we are sometimes going
>> to need C-code in the kernel, just like there is "board" specific C-code
>> in the x86 code.
>
> Your talk convinced me that we're both going to see more variation
> within this family of boards, and that we'll see more families of boards
> following a similar patter. Given that, I think that we need a more
> general solution, as I commented on the RFC.
>
> That doesn't necessarily mean that this can't happen in the kernel, but
> it certainly needs to be more strictly defined, e.g. with match criteria
> and fixups explicit in the DTB.

The only answer I've to: "with match criteria and fixups explicit in the DTB"
is: ok, give my a turing complete language inside DTB then, anything else
will not suffice. So either we are doomed to reinvent ACPI; or we must
accept some board(family) specific C-code in the kernel.

Regards,

Hans

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

* Re: [PATCH 1/6] dt: bindings: Add Allwinner Q8 tablets hardware manager bindings
  2016-10-14  7:53     ` Hans de Goede
@ 2016-10-26 20:39         ` Rob Herring
  -1 siblings, 0 replies; 48+ messages in thread
From: Rob Herring @ 2016-10-26 20:39 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Mark Rutland, Arnd Bergmann, Greg Kroah-Hartman, Maxime Ripard,
	Chen-Yu Tsai, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree

On Fri, Oct 14, 2016 at 09:53:32AM +0200, Hans de Goede wrote:
> Allwinnner A13 / A23 / A33 based Q8 tablets are popular cheap 7" tablets
> of which a new batch is produced every few weeks. Each batch uses a
> different mix of touchscreen, accelerometer and wifi peripherals.
> 
> Given that each batch is different creating a devicetree for each variant
> is not desirable, work is being done on a Q8 tablet hardware manager which
> auto-detects the touchscreen and accelerometer and will update the dt with
> what it has found, so that a single generic dt can be used for these tablets.
> 
> This commit adds dt-bindings for this hardware manager.
> 
> Note the wifi is connected to a discoverable bus (sdio or usb) and will be
> autodetected by the mmc resp. usb subsystems.
> 
> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
>  .../misc/allwinner,sunxi-q8-hardwaremgr.txt        | 71 ++++++++++++++++++++++
>  1 file changed, 71 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt
> 
> diff --git a/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt b/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt
> new file mode 100644
> index 0000000..a81b258
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt
> @@ -0,0 +1,71 @@
> +Q8 tablet hardware manager
> +--------------------------
> +
> +Allwinnner A13 / A23 / A33 based Q8 tablets are popular cheap 7" tablets of
> +which a new batch is produced every few weeks. Each batch uses a different
> +mix of touchscreen, accelerometer and wifi peripherals.
> +
> +Given that each batch is different creating a devicetree for each variant is
> +not desirable. The Q8 tablet hardware manager bindings are bindings for an os
> +module which auto-detects the touchscreen and accelerometer so that a single
> +generic dts can be used for these tablets.
> +
> +The wifi is connected to a discoverable bus and will be autodetected by the os.
> +
> +Required properties:
> + - toplevel / machine compatible, one of:
> +	"allwinner,q8-a13"
> +	"allwinner,q8-a23"
> +	"allwinner,q8-a33"
> + - touchscreen node   : There must be a template touchscreen node named
> +			"touchscreen", this must be a child node of the
> +			touchscreen i2c bus
> + - accelerometer node : There must be a template accelerometer node named
> +			"accelerometer", this must be a child node of the
> +			accelerometer i2c bus
> +
> +touchscreen node required properties:
> + - interrupt-parent   : phandle pointing to the interrupt controller
> +			serving the touchscreen interrupt
> + - interrupts         : interrupt specification for the touchscreen interrupt
> + - power-gpios        : Specification for the pin connected to the touchscreen's
> +			enable / wake pin. This needs to be driven high to
> +			enable the touchscreen controller

enable-gpios is the common name.

I was going to say you need to list possible compatible strings here 
also. However, I now wonder if this binding doc is even needed. The 
binding docs should just be the bindings for each touchscreen or 
accelerometer. The fact that the node is completed at run-time whether 
the bootloader or kernel doesn't matter for the binding definition. When 
and it is completed is orthogonal to the binding definition.

Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 1/6] dt: bindings: Add Allwinner Q8 tablets hardware manager bindings
@ 2016-10-26 20:39         ` Rob Herring
  0 siblings, 0 replies; 48+ messages in thread
From: Rob Herring @ 2016-10-26 20:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 14, 2016 at 09:53:32AM +0200, Hans de Goede wrote:
> Allwinnner A13 / A23 / A33 based Q8 tablets are popular cheap 7" tablets
> of which a new batch is produced every few weeks. Each batch uses a
> different mix of touchscreen, accelerometer and wifi peripherals.
> 
> Given that each batch is different creating a devicetree for each variant
> is not desirable, work is being done on a Q8 tablet hardware manager which
> auto-detects the touchscreen and accelerometer and will update the dt with
> what it has found, so that a single generic dt can be used for these tablets.
> 
> This commit adds dt-bindings for this hardware manager.
> 
> Note the wifi is connected to a discoverable bus (sdio or usb) and will be
> autodetected by the mmc resp. usb subsystems.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  .../misc/allwinner,sunxi-q8-hardwaremgr.txt        | 71 ++++++++++++++++++++++
>  1 file changed, 71 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt
> 
> diff --git a/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt b/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt
> new file mode 100644
> index 0000000..a81b258
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/misc/allwinner,sunxi-q8-hardwaremgr.txt
> @@ -0,0 +1,71 @@
> +Q8 tablet hardware manager
> +--------------------------
> +
> +Allwinnner A13 / A23 / A33 based Q8 tablets are popular cheap 7" tablets of
> +which a new batch is produced every few weeks. Each batch uses a different
> +mix of touchscreen, accelerometer and wifi peripherals.
> +
> +Given that each batch is different creating a devicetree for each variant is
> +not desirable. The Q8 tablet hardware manager bindings are bindings for an os
> +module which auto-detects the touchscreen and accelerometer so that a single
> +generic dts can be used for these tablets.
> +
> +The wifi is connected to a discoverable bus and will be autodetected by the os.
> +
> +Required properties:
> + - toplevel / machine compatible, one of:
> +	"allwinner,q8-a13"
> +	"allwinner,q8-a23"
> +	"allwinner,q8-a33"
> + - touchscreen node   : There must be a template touchscreen node named
> +			"touchscreen", this must be a child node of the
> +			touchscreen i2c bus
> + - accelerometer node : There must be a template accelerometer node named
> +			"accelerometer", this must be a child node of the
> +			accelerometer i2c bus
> +
> +touchscreen node required properties:
> + - interrupt-parent   : phandle pointing to the interrupt controller
> +			serving the touchscreen interrupt
> + - interrupts         : interrupt specification for the touchscreen interrupt
> + - power-gpios        : Specification for the pin connected to the touchscreen's
> +			enable / wake pin. This needs to be driven high to
> +			enable the touchscreen controller

enable-gpios is the common name.

I was going to say you need to list possible compatible strings here 
also. However, I now wonder if this binding doc is even needed. The 
binding docs should just be the bindings for each touchscreen or 
accelerometer. The fact that the node is completed at run-time whether 
the bootloader or kernel doesn't matter for the binding definition. When 
and it is completed is orthogonal to the binding definition.

Rob

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

* Re: Add Allwinner Q8 tablets hardware manager
  2016-10-24 17:39     ` Mark Rutland
@ 2016-10-26 20:54       ` Rob Herring
  -1 siblings, 0 replies; 48+ messages in thread
From: Rob Herring @ 2016-10-26 20:54 UTC (permalink / raw)
  To: Mark Rutland, Hans de Goede
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Maxime Ripard, Chen-Yu Tsai,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree

On Mon, Oct 24, 2016 at 06:39:01PM +0100, Mark Rutland wrote:
> On Fri, Oct 14, 2016 at 09:53:31AM +0200, Hans de Goede wrote:
> > Hi Rob, Mark, et al.,
> 
> Hi Hans,
> 
> Apologies for the delay in replying to this.
> 
> I'd like to be clear that I do understand that there is a problem that
> needs to be addressed here. However, I do not believe that the *current*
> in-kernel approach is correct. More on that below.
> 
> > Mark, I know that we discussed this at ELCE and you clearly indicated
> > that according to you this does not belong in the kernel. I was a bit
> > surprised by this part of the discussion.
> > 
> > I had posted a RFC earlier and Rob had indicated that given that the q8
> > tablets are a special case, as my code uses actual probing rather then some
> > pre-arranged id mechanism with say an eeprom, that doing this in a
> > non-generic manner would be ok for my special case.
> 
> To some extent, Rob and I may have differing views here; I'm not
> entirely sure what Rob's view is, and I cannot talk on his behalf. I
> certainly must apologise for having not commented on said RFC, however.

I've focused mainly on the bindings which I certainly had issues with 
how the RFC was done. As to where this should be done, keeping all the 
dirty bits in firmware/bootloader is certainly appealing. However, there 
are cases where data alone can't abstract out board differences and we 
need board code. Whether this is one of them, well, that is Hans' job to 
convince Mark.

Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-26 20:54       ` Rob Herring
  0 siblings, 0 replies; 48+ messages in thread
From: Rob Herring @ 2016-10-26 20:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Oct 24, 2016 at 06:39:01PM +0100, Mark Rutland wrote:
> On Fri, Oct 14, 2016 at 09:53:31AM +0200, Hans de Goede wrote:
> > Hi Rob, Mark, et al.,
> 
> Hi Hans,
> 
> Apologies for the delay in replying to this.
> 
> I'd like to be clear that I do understand that there is a problem that
> needs to be addressed here. However, I do not believe that the *current*
> in-kernel approach is correct. More on that below.
> 
> > Mark, I know that we discussed this at ELCE and you clearly indicated
> > that according to you this does not belong in the kernel. I was a bit
> > surprised by this part of the discussion.
> > 
> > I had posted a RFC earlier and Rob had indicated that given that the q8
> > tablets are a special case, as my code uses actual probing rather then some
> > pre-arranged id mechanism with say an eeprom, that doing this in a
> > non-generic manner would be ok for my special case.
> 
> To some extent, Rob and I may have differing views here; I'm not
> entirely sure what Rob's view is, and I cannot talk on his behalf. I
> certainly must apologise for having not commented on said RFC, however.

I've focused mainly on the bindings which I certainly had issues with 
how the RFC was done. As to where this should be done, keeping all the 
dirty bits in firmware/bootloader is certainly appealing. However, there 
are cases where data alone can't abstract out board differences and we 
need board code. Whether this is one of them, well, that is Hans' job to 
convince Mark.

Rob

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

* Re: Add Allwinner Q8 tablets hardware manager
  2016-10-26 20:54       ` Rob Herring
@ 2016-10-27  8:10         ` Pierre-Hugues Husson
  -1 siblings, 0 replies; 48+ messages in thread
From: Pierre-Hugues Husson @ 2016-10-27  8:10 UTC (permalink / raw)
  To: Rob Herring
  Cc: Mark Rutland, devicetree, Arnd Bergmann, Greg Kroah-Hartman,
	Hans de Goede, Chen-Yu Tsai, Maxime Ripard, linux-arm-kernel

Hi,

(mail resent, because it had been filtered out by linux-arm-kernel and
and devicetree because it contained an HTML part, sorry about that)

2016-10-26 13:46 GMT+02:00 Hans de Goede <hdegoede@redhat.com>:

> And as I tried to explain before, for this specific use-case describing
> all this board specific knowledge in a generic manner in dt is simply
> impossible, unless we add a turing complete language to dt aka aml.


You keep saying this is a "specific use-case", but I don't agree.
Most of cheap phone and tablets SoC manufacturer's Linux variant that
I know of have (rather stupid) auto-detection methods.
Not every phone manufacturer use it, because some have proper and
constant supply chain, but still, that's not always the case.
For instance you might look at this dts:
https://github.com/Dee-UK/RK3288_Lollipop_Kernel/commit/9e056a10b0a773d285e8d2ae819e7c2451816492#diff-b25e1abc92522c85e9ef28704bf9284aR410
This DTS is meant, like what you do, to be compatible with as many
devices as possible at once.
So it declares 4 different PMICs (and no they will never all be there
at the same time), and two different accelerometers, 3 audio codecs,
and two touchscreens.
Or you can look at CodeAurora (Qualcomm public opensource tree) DTSs
and see that a standard DTS support at least three different panels (
see https://github.com/omnirom/android_kernel_oppo_msm8974/blob/27080b724f4cf281d598e7830abc5fc1292b5803/arch/arm/boot/dts/msm8974-mtp.dtsi#L15
)
And that's the fairly clean examples. Some SoC kernels are still using
good old platform_data detection methods.

Thus I believe that having a board-specific driver is not a good
thing, because we would get many of those.

When it comes to detection, I've witnessed various things.
It can be kernel-side or bootloader-side "global setting" reading
(like an ADC/resistor value, or an OTP), it can be bootloader doing
the "brute-force", or it can be the kernel doing all the probes.

For instance, as of today, on a Spreadtrum ODM tree, the bootloader
will detect the screen by testing all knowns screens, the
screen-drivers declare a get_id function, and the bootloader probes
until the get_id matches the id declared by the screen driver.
And then the bootloader tells the kernel, via cmdline, which screen is
actually there (but auto-detection is also coded in kernel).
Finally all possible sensors/touchscreen/camera are declared in DTS,
and probe will filter-out N/C ones in the kernel.

Now the big difference between my experience and what Hans is trying
to do, is that I've always worked with devices with "safely" queriable
IDs, either on i2c or dsi. I've never encountered SPI. This makes
probing inherently more dangerous, but I believe the question roughly
remains the same.

I understand Mark's will of taking care of this "earlier" (either
bootloader or a later kernel-loader (pxa-impedance-matcher)), but I
feel like this is only giving the problem to someone else.
I think that those auto-detection methods should be declared in a
device-tree, though as Hans noted, this might end to be a
turing-complete language.
In my experience, I have never encountered a device requiring more
than ordered probes, but backward compatibility was expected. (i.e. if
IDs couldn't help distinguish two devices, the manufacturer would add
another way to identify)

As to whether this is bootloader's job or kernel's job, I don't have a
really strong opinion.
On one side, the kernel has all the drivers and probe functions, this
would need little work to make this work.
On the other side, if the "rules" are something like "read bus XXX,
address YYY, expect ZZZ", the bootloader can handle it as well. But I
don't think it is a good idea to have the bootloader know all the
gsensor/screen/camera/... drivers (even if they are partial drivers
dedicated to detection only)

Regards,

2016-10-26 22:54 GMT+02:00 Rob Herring <robh@kernel.org>:
> On Mon, Oct 24, 2016 at 06:39:01PM +0100, Mark Rutland wrote:
>> On Fri, Oct 14, 2016 at 09:53:31AM +0200, Hans de Goede wrote:
>> > Hi Rob, Mark, et al.,
>>
>> Hi Hans,
>>
>> Apologies for the delay in replying to this.
>>
>> I'd like to be clear that I do understand that there is a problem that
>> needs to be addressed here. However, I do not believe that the *current*
>> in-kernel approach is correct. More on that below.
>>
>> > Mark, I know that we discussed this at ELCE and you clearly indicated
>> > that according to you this does not belong in the kernel. I was a bit
>> > surprised by this part of the discussion.
>> >
>> > I had posted a RFC earlier and Rob had indicated that given that the q8
>> > tablets are a special case, as my code uses actual probing rather then some
>> > pre-arranged id mechanism with say an eeprom, that doing this in a
>> > non-generic manner would be ok for my special case.
>>
>> To some extent, Rob and I may have differing views here; I'm not
>> entirely sure what Rob's view is, and I cannot talk on his behalf. I
>> certainly must apologise for having not commented on said RFC, however.
>
> I've focused mainly on the bindings which I certainly had issues with
> how the RFC was done. As to where this should be done, keeping all the
> dirty bits in firmware/bootloader is certainly appealing. However, there
> are cases where data alone can't abstract out board differences and we
> need board code. Whether this is one of them, well, that is Hans' job to
> convince Mark.
>
> Rob
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-27  8:10         ` Pierre-Hugues Husson
  0 siblings, 0 replies; 48+ messages in thread
From: Pierre-Hugues Husson @ 2016-10-27  8:10 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

(mail resent, because it had been filtered out by linux-arm-kernel and
and devicetree because it contained an HTML part, sorry about that)

2016-10-26 13:46 GMT+02:00 Hans de Goede <hdegoede@redhat.com>:

> And as I tried to explain before, for this specific use-case describing
> all this board specific knowledge in a generic manner in dt is simply
> impossible, unless we add a turing complete language to dt aka aml.


You keep saying this is a "specific use-case", but I don't agree.
Most of cheap phone and tablets SoC manufacturer's Linux variant that
I know of have (rather stupid) auto-detection methods.
Not every phone manufacturer use it, because some have proper and
constant supply chain, but still, that's not always the case.
For instance you might look at this dts:
https://github.com/Dee-UK/RK3288_Lollipop_Kernel/commit/9e056a10b0a773d285e8d2ae819e7c2451816492#diff-b25e1abc92522c85e9ef28704bf9284aR410
This DTS is meant, like what you do, to be compatible with as many
devices as possible at once.
So it declares 4 different PMICs (and no they will never all be there
at the same time), and two different accelerometers, 3 audio codecs,
and two touchscreens.
Or you can look at CodeAurora (Qualcomm public opensource tree) DTSs
and see that a standard DTS support at least three different panels (
see https://github.com/omnirom/android_kernel_oppo_msm8974/blob/27080b724f4cf281d598e7830abc5fc1292b5803/arch/arm/boot/dts/msm8974-mtp.dtsi#L15
)
And that's the fairly clean examples. Some SoC kernels are still using
good old platform_data detection methods.

Thus I believe that having a board-specific driver is not a good
thing, because we would get many of those.

When it comes to detection, I've witnessed various things.
It can be kernel-side or bootloader-side "global setting" reading
(like an ADC/resistor value, or an OTP), it can be bootloader doing
the "brute-force", or it can be the kernel doing all the probes.

For instance, as of today, on a Spreadtrum ODM tree, the bootloader
will detect the screen by testing all knowns screens, the
screen-drivers declare a get_id function, and the bootloader probes
until the get_id matches the id declared by the screen driver.
And then the bootloader tells the kernel, via cmdline, which screen is
actually there (but auto-detection is also coded in kernel).
Finally all possible sensors/touchscreen/camera are declared in DTS,
and probe will filter-out N/C ones in the kernel.

Now the big difference between my experience and what Hans is trying
to do, is that I've always worked with devices with "safely" queriable
IDs, either on i2c or dsi. I've never encountered SPI. This makes
probing inherently more dangerous, but I believe the question roughly
remains the same.

I understand Mark's will of taking care of this "earlier" (either
bootloader or a later kernel-loader (pxa-impedance-matcher)), but I
feel like this is only giving the problem to someone else.
I think that those auto-detection methods should be declared in a
device-tree, though as Hans noted, this might end to be a
turing-complete language.
In my experience, I have never encountered a device requiring more
than ordered probes, but backward compatibility was expected. (i.e. if
IDs couldn't help distinguish two devices, the manufacturer would add
another way to identify)

As to whether this is bootloader's job or kernel's job, I don't have a
really strong opinion.
On one side, the kernel has all the drivers and probe functions, this
would need little work to make this work.
On the other side, if the "rules" are something like "read bus XXX,
address YYY, expect ZZZ", the bootloader can handle it as well. But I
don't think it is a good idea to have the bootloader know all the
gsensor/screen/camera/... drivers (even if they are partial drivers
dedicated to detection only)

Regards,

2016-10-26 22:54 GMT+02:00 Rob Herring <robh@kernel.org>:
> On Mon, Oct 24, 2016 at 06:39:01PM +0100, Mark Rutland wrote:
>> On Fri, Oct 14, 2016 at 09:53:31AM +0200, Hans de Goede wrote:
>> > Hi Rob, Mark, et al.,
>>
>> Hi Hans,
>>
>> Apologies for the delay in replying to this.
>>
>> I'd like to be clear that I do understand that there is a problem that
>> needs to be addressed here. However, I do not believe that the *current*
>> in-kernel approach is correct. More on that below.
>>
>> > Mark, I know that we discussed this at ELCE and you clearly indicated
>> > that according to you this does not belong in the kernel. I was a bit
>> > surprised by this part of the discussion.
>> >
>> > I had posted a RFC earlier and Rob had indicated that given that the q8
>> > tablets are a special case, as my code uses actual probing rather then some
>> > pre-arranged id mechanism with say an eeprom, that doing this in a
>> > non-generic manner would be ok for my special case.
>>
>> To some extent, Rob and I may have differing views here; I'm not
>> entirely sure what Rob's view is, and I cannot talk on his behalf. I
>> certainly must apologise for having not commented on said RFC, however.
>
> I've focused mainly on the bindings which I certainly had issues with
> how the RFC was done. As to where this should be done, keeping all the
> dirty bits in firmware/bootloader is certainly appealing. However, there
> are cases where data alone can't abstract out board differences and we
> need board code. Whether this is one of them, well, that is Hans' job to
> convince Mark.
>
> Rob
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: Add Allwinner Q8 tablets hardware manager
       [not found]       ` <CAJ-oXjQbOkrkNToEXYmPUZOgYBGbxQREZ4NL4bMcZmG=KP2vQQ@mail.gmail.com>
@ 2016-10-27  9:14             ` Hans de Goede
  0 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-27  9:14 UTC (permalink / raw)
  To: Pierre-Hugues Husson
  Cc: Mark Rutland, devicetree, Arnd Bergmann, Greg Kroah-Hartman,
	Pantelis Antoniou, Chen-Yu Tsai, Rob Herring, Maxime Ripard,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi,

On 27-10-16 01:45, Pierre-Hugues Husson wrote:
> Hi,
>
> 2016-10-26 13:46 GMT+02:00 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org <mailto:hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>>:
>
>> And as I tried to explain before, for this specific use-case describing
>> all this board specific knowledge in a generic manner in dt is simply
>> impossible, unless we add a turing complete language to dt aka aml.
>
>
> You keep saying this is a "specific use-case", but I don't agree.
> Most of cheap phone and tablets SoC manufacturer's Linux variant that I know of have (rather stupid) auto-detection methods.

True.

> Not every phone manufacturer use it, because some have proper and constant supply chain, but still, that's not always the case.
> For instance you might look at this dts: https://github.com/Dee-UK/RK3288_Lollipop_Kernel/commit/9e056a10b0a773d285e8d2ae819e7c2451816492#diff-b25e1abc92522c85e9ef28704bf9284aR410
> This DTS is meant, like what you do, to be compatible with as many devices as possible at once.
> So it declares 4 different PMICs (and no they will never all be there at the same time), and two different accelerometers, 3 audio codecs, and two touchscreens.
> Or you can look at CodeAurora (Qualcomm public opensource tree) DTSs and see that a standard DTS support at least three different panels ( see https://github.com/omnirom/android_kernel_oppo_msm8974/blob/27080b724f4cf281d598e7830abc5fc1292b5803/arch/arm/boot/dts/msm8974-mtp.dtsi#L15 )
> And that's the fairly clean examples. Some SoC kernels are still using good old platform_data detection methods.
>
> Thus I believe that having a board-specific driver is not a good thing, because we would get many of those.

In my experience with these cheap boards, there is a mix of auto-probing +
device / revision specific os-image modifications. I keep coming back to
the touchscreen controller firmware (but also the orientation), for the
gsl1680 controller I need at least 2 different firmware files (per gsl1680
revision) to make all q8 tablets I have working. This is simply not solved
by the vendor android code, they just shove the right firmware into the
os-image. Likewise for the touchscreen orientation (x-mirored, y-mirored,
etc) too is just a hard-coded setting in the os-image.

Thinking more about this, we may be able to come up with a generic way to
deal with i2c device detection, just like many vendor os-images are doing.

The kernel actually already has a detect() method in struct i2c_driver,
we could use that (we would need to implement it in drivers which do not
have it yet). Note on second thought it seems it may be better to use
probe() for this, see below.

Then we could have something like this in dt:

&i2c0 {
	touchscreen1: gsl1680@40 {
		reg = <0x40>;
		compatible = "silead,gsl1680";
		enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
		status = "disabled";
	};

	touchscreen2: ektf2127@15 {
		reg = <0x15>;
		compatible = "elan,ektf2127";
		enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
		status = "disabled";
	};

	i2c-probe-stop-at-first-match = <&touchscreen1>, <&touchscreen2>;
}

Which would make the i2c subsys call detect (*) on each device, until
a device is found. Likewise we could have a "i2c-probe-all" property
which also walks a list of phandles but does not stop on the first
match.

Mark would something like this scheme work for you ?

Note that things are not this simple though, there are multiple challenges
with this approach:

1) pinctrl, even the detect() method of the driver may need to use
e.g. some gpios so we would need to activate pinctrl as normally the
kernel device core would do this before calling probe(). This is solvable,
but I wonder if we need to mention anything about this in the bindings
docs ? Note this would be solved by just instantiating the client / device
and then try probe().

2) Note the enable-gpios, those will need to be handled in the detect()
method, but this requires a device to be instantiated to call devm_get_...
on, likewise for other resources.

Alternatively the probe code could know about this (as part of the
i2c-probe-stop-at-first-match binding) and enable it before probing ?

3) Optional regulators, I've one q8 tablet where the touchscreen is
powered by a separate regulator, currently my hardware-mgr simply
first tries to probe all possible models with the regulator disabled
(and stops at -ETIMEDOUT which means the i2c bus is stuck and further
  probing without enabling the regulator is useless).

How do we deal with this? This is a tricky one do we do this in
the code which walks over the i2c-probe-stop-at-first-match list,
or do we punt this to the driver?

Sofar I've only seen this with one type of touchscreen so an easy cop-out
would be to add an "optional-vddio-supply" to the the bindings for the
specific touchscreen use and put all the necessary logic in the driver.

This does require propagating the learned need for the regulator
from the drivers detect() callback to probe() or alternatively I'm
thinking we should just use probe() instead of detect()to begin with,
that will save a lot of duplication with things
like code for enable gpio-s and regulators.

So assuming we go for the cop-out option for 3. (I'm ok with that),
this would be a pretty clean solution adding just the 2 new:
i2c-probe-stop-at-first-match and i2c-probe-all properties to
the i2c-bus bindings. One problem here is that we may want to have
multiple i2c-probe-stop-at-first-match phandle lists on a single bus
(e.g. try 3 touchscreens + 6 accelerometers on the same bus, stop at
first touchscreen / first accelerometer), anyone have any ideas for
that?


*) Yes this sounds Linux specific, but it really is just "execute to-be-probed
device compatible specific detection method"


> When it comes to detection, I've witnessed various things.
> It can be kernel-side or bootloader-side "global setting" reading (like an ADC/resistor value, or an OTP), it can be bootloader doing the "brute-force", or it can be the kernel doing all the probes.
>
> For instance, as of today, on a Spreadtrum ODM tree, the bootloader will detect the screen by testing all knowns screens, the screen-drivers declare a get_id function, and the bootloader probes until the get_id matches the id declared by the screen driver.
> And then the bootloader tells the kernel, via cmdline, which screen is actually there (but auto-detection is also coded in kernel).
> Finally all possible sensors/touchscreen/camera are declared in DTS, and probe will filter-out N/C ones in the kernel.
>
> Now the big difference between my experience and what Hans is trying to do, is that I've always worked with devices with "safely" queriable IDs, either on i2c or dsi. I've never encountered SPI. This makes probing inherently more dangerous, but I believe the question roughly remains the same.

I'm dealing with i2c too, Mark mistakenly used SPI in his reply,
which I think is what got you thinking I've SPI.

> I understand Mark's will of taking care of this "earlier" (either bootloader or a later kernel-loader (pxa-impedance-matcher)), but I feel like this is only giving the problem to someone else.

Big ack to this, moving this to the bootloader is not solving the
problem, it just moves the problem elsewhere.

> I think that those auto-detection methods should be declared in a device-tree, though as Hans noted, this might end to be a turing-complete language.

See above, I think that we can make this work by delegating the actual
detection to the driver (so each compatible can have a different detect method / code).

So with this we can remove a big part of drivers/misc/q8-hardwaremgr.c, but not all
of it. We still need board specific code somewhere to deal with things like picking
the right touchscreen firmware and touchscreen orientation. This is all somewhat
gsl1680 specific.

I actually have the same problem on x86 where the ACPI description of the device
basically says: "There is a gsl1680 at this bus at this address" and does not say
anything about firmware / orientation (again this is simply hardcoded
in the os-image these devices ship with).

For x86 my plan is to have an array of configs in the driver and select the right
one based on DMI strings, which is in essence putting board specific info in the
driver.

I can imagine mirroring this for ARM, and have an array of configs in the driver
there too (for cases where cannot simply hardcode everything in dt only) and have
some board specific code (activated by of_machine_is_compatible()) to select the
right config.

> In my experience, I have never encountered a device requiring more than ordered probes, but backward compatibility was expected. (i.e. if IDs couldn't help distinguish two devices, the manufacturer would add another way to identify)
>
> As to whether this is bootloader's job or kernel's job, I don't have a really strong opinion.
> On one side, the kernel has all the drivers and probe functions, this would need little work to make this work.
> On the other side, if the "rules" are something like "read bus XXX, address YYY, expect ZZZ", the bootloader can handle it as well. But I don't think it is a good idea to have the bootloader know all the gsensor/screen/camera/... drivers (even if they are partial drivers dedicated to detection only)

Ack I to really believe this belongs in the kernel. Thank you for your reply,
it has made me realized that there are 2 problems here:

1) auto-detect of i2c-devices from a fixed list of i2c devices the board may
have, for this we really need 2 bits: a) generic mechanism to describe this,
call the driver detect methods b) hardware (compatible) specific detection
routines. b) really belongs in the driver, and since things like sensor
drivers (another good example btw) do not belong in the bootloader we
really need this bit in the kernel.

If we can get some consensus on this I'm willing to work on this
(as time allows, this is a spare time project). At least up to feature parity
with my current hard-coded q8-hardwaremgr.c, which in hind-sight indeed is
ugly as the detect code really belongs in the driver (I've been copy and
pasting about 10 - 30 lines from each driver into q8-hardwaremgr.c).

2) miscellaneous extra config on top of figuring out which ICs are connected,
basically the kind of stuff many vendors simply hard-code in their device
specific os-image. This one is much more difficult to deal with and I think
we need to figure this out on a case by case basis. This will require board
specific code (just like the kernel has tons of DMI string activated board
specific code on x86) and what is the best code for this place to live will
be a case by case thing too.

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-27  9:14             ` Hans de Goede
  0 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-27  9:14 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 27-10-16 01:45, Pierre-Hugues Husson wrote:
> Hi,
>
> 2016-10-26 13:46 GMT+02:00 Hans de Goede <hdegoede at redhat.com <mailto:hdegoede@redhat.com>>:
>
>> And as I tried to explain before, for this specific use-case describing
>> all this board specific knowledge in a generic manner in dt is simply
>> impossible, unless we add a turing complete language to dt aka aml.
>
>
> You keep saying this is a "specific use-case", but I don't agree.
> Most of cheap phone and tablets SoC manufacturer's Linux variant that I know of have (rather stupid) auto-detection methods.

True.

> Not every phone manufacturer use it, because some have proper and constant supply chain, but still, that's not always the case.
> For instance you might look at this dts: https://github.com/Dee-UK/RK3288_Lollipop_Kernel/commit/9e056a10b0a773d285e8d2ae819e7c2451816492#diff-b25e1abc92522c85e9ef28704bf9284aR410
> This DTS is meant, like what you do, to be compatible with as many devices as possible at once.
> So it declares 4 different PMICs (and no they will never all be there at the same time), and two different accelerometers, 3 audio codecs, and two touchscreens.
> Or you can look at CodeAurora (Qualcomm public opensource tree) DTSs and see that a standard DTS support at least three different panels ( see https://github.com/omnirom/android_kernel_oppo_msm8974/blob/27080b724f4cf281d598e7830abc5fc1292b5803/arch/arm/boot/dts/msm8974-mtp.dtsi#L15 )
> And that's the fairly clean examples. Some SoC kernels are still using good old platform_data detection methods.
>
> Thus I believe that having a board-specific driver is not a good thing, because we would get many of those.

In my experience with these cheap boards, there is a mix of auto-probing +
device / revision specific os-image modifications. I keep coming back to
the touchscreen controller firmware (but also the orientation), for the
gsl1680 controller I need at least 2 different firmware files (per gsl1680
revision) to make all q8 tablets I have working. This is simply not solved
by the vendor android code, they just shove the right firmware into the
os-image. Likewise for the touchscreen orientation (x-mirored, y-mirored,
etc) too is just a hard-coded setting in the os-image.

Thinking more about this, we may be able to come up with a generic way to
deal with i2c device detection, just like many vendor os-images are doing.

The kernel actually already has a detect() method in struct i2c_driver,
we could use that (we would need to implement it in drivers which do not
have it yet). Note on second thought it seems it may be better to use
probe() for this, see below.

Then we could have something like this in dt:

&i2c0 {
	touchscreen1: gsl1680 at 40 {
		reg = <0x40>;
		compatible = "silead,gsl1680";
		enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
		status = "disabled";
	};

	touchscreen2: ektf2127 at 15 {
		reg = <0x15>;
		compatible = "elan,ektf2127";
		enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
		status = "disabled";
	};

	i2c-probe-stop-at-first-match = <&touchscreen1>, <&touchscreen2>;
}

Which would make the i2c subsys call detect (*) on each device, until
a device is found. Likewise we could have a "i2c-probe-all" property
which also walks a list of phandles but does not stop on the first
match.

Mark would something like this scheme work for you ?

Note that things are not this simple though, there are multiple challenges
with this approach:

1) pinctrl, even the detect() method of the driver may need to use
e.g. some gpios so we would need to activate pinctrl as normally the
kernel device core would do this before calling probe(). This is solvable,
but I wonder if we need to mention anything about this in the bindings
docs ? Note this would be solved by just instantiating the client / device
and then try probe().

2) Note the enable-gpios, those will need to be handled in the detect()
method, but this requires a device to be instantiated to call devm_get_...
on, likewise for other resources.

Alternatively the probe code could know about this (as part of the
i2c-probe-stop-at-first-match binding) and enable it before probing ?

3) Optional regulators, I've one q8 tablet where the touchscreen is
powered by a separate regulator, currently my hardware-mgr simply
first tries to probe all possible models with the regulator disabled
(and stops at -ETIMEDOUT which means the i2c bus is stuck and further
  probing without enabling the regulator is useless).

How do we deal with this? This is a tricky one do we do this in
the code which walks over the i2c-probe-stop-at-first-match list,
or do we punt this to the driver?

Sofar I've only seen this with one type of touchscreen so an easy cop-out
would be to add an "optional-vddio-supply" to the the bindings for the
specific touchscreen use and put all the necessary logic in the driver.

This does require propagating the learned need for the regulator
from the drivers detect() callback to probe() or alternatively I'm
thinking we should just use probe() instead of detect()to begin with,
that will save a lot of duplication with things
like code for enable gpio-s and regulators.

So assuming we go for the cop-out option for 3. (I'm ok with that),
this would be a pretty clean solution adding just the 2 new:
i2c-probe-stop-at-first-match and i2c-probe-all properties to
the i2c-bus bindings. One problem here is that we may want to have
multiple i2c-probe-stop-at-first-match phandle lists on a single bus
(e.g. try 3 touchscreens + 6 accelerometers on the same bus, stop at
first touchscreen / first accelerometer), anyone have any ideas for
that?


*) Yes this sounds Linux specific, but it really is just "execute to-be-probed
device compatible specific detection method"


> When it comes to detection, I've witnessed various things.
> It can be kernel-side or bootloader-side "global setting" reading (like an ADC/resistor value, or an OTP), it can be bootloader doing the "brute-force", or it can be the kernel doing all the probes.
>
> For instance, as of today, on a Spreadtrum ODM tree, the bootloader will detect the screen by testing all knowns screens, the screen-drivers declare a get_id function, and the bootloader probes until the get_id matches the id declared by the screen driver.
> And then the bootloader tells the kernel, via cmdline, which screen is actually there (but auto-detection is also coded in kernel).
> Finally all possible sensors/touchscreen/camera are declared in DTS, and probe will filter-out N/C ones in the kernel.
>
> Now the big difference between my experience and what Hans is trying to do, is that I've always worked with devices with "safely" queriable IDs, either on i2c or dsi. I've never encountered SPI. This makes probing inherently more dangerous, but I believe the question roughly remains the same.

I'm dealing with i2c too, Mark mistakenly used SPI in his reply,
which I think is what got you thinking I've SPI.

> I understand Mark's will of taking care of this "earlier" (either bootloader or a later kernel-loader (pxa-impedance-matcher)), but I feel like this is only giving the problem to someone else.

Big ack to this, moving this to the bootloader is not solving the
problem, it just moves the problem elsewhere.

> I think that those auto-detection methods should be declared in a device-tree, though as Hans noted, this might end to be a turing-complete language.

See above, I think that we can make this work by delegating the actual
detection to the driver (so each compatible can have a different detect method / code).

So with this we can remove a big part of drivers/misc/q8-hardwaremgr.c, but not all
of it. We still need board specific code somewhere to deal with things like picking
the right touchscreen firmware and touchscreen orientation. This is all somewhat
gsl1680 specific.

I actually have the same problem on x86 where the ACPI description of the device
basically says: "There is a gsl1680 at this bus at this address" and does not say
anything about firmware / orientation (again this is simply hardcoded
in the os-image these devices ship with).

For x86 my plan is to have an array of configs in the driver and select the right
one based on DMI strings, which is in essence putting board specific info in the
driver.

I can imagine mirroring this for ARM, and have an array of configs in the driver
there too (for cases where cannot simply hardcode everything in dt only) and have
some board specific code (activated by of_machine_is_compatible()) to select the
right config.

> In my experience, I have never encountered a device requiring more than ordered probes, but backward compatibility was expected. (i.e. if IDs couldn't help distinguish two devices, the manufacturer would add another way to identify)
>
> As to whether this is bootloader's job or kernel's job, I don't have a really strong opinion.
> On one side, the kernel has all the drivers and probe functions, this would need little work to make this work.
> On the other side, if the "rules" are something like "read bus XXX, address YYY, expect ZZZ", the bootloader can handle it as well. But I don't think it is a good idea to have the bootloader know all the gsensor/screen/camera/... drivers (even if they are partial drivers dedicated to detection only)

Ack I to really believe this belongs in the kernel. Thank you for your reply,
it has made me realized that there are 2 problems here:

1) auto-detect of i2c-devices from a fixed list of i2c devices the board may
have, for this we really need 2 bits: a) generic mechanism to describe this,
call the driver detect methods b) hardware (compatible) specific detection
routines. b) really belongs in the driver, and since things like sensor
drivers (another good example btw) do not belong in the bootloader we
really need this bit in the kernel.

If we can get some consensus on this I'm willing to work on this
(as time allows, this is a spare time project). At least up to feature parity
with my current hard-coded q8-hardwaremgr.c, which in hind-sight indeed is
ugly as the detect code really belongs in the driver (I've been copy and
pasting about 10 - 30 lines from each driver into q8-hardwaremgr.c).

2) miscellaneous extra config on top of figuring out which ICs are connected,
basically the kind of stuff many vendors simply hard-code in their device
specific os-image. This one is much more difficult to deal with and I think
we need to figure this out on a case by case basis. This will require board
specific code (just like the kernel has tons of DMI string activated board
specific code on x86) and what is the best code for this place to live will
be a case by case thing too.

Regards,

Hans

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

* Re: Add Allwinner Q8 tablets hardware manager
  2016-10-27  9:14             ` Hans de Goede
@ 2016-10-27 12:57               ` Pierre-Hugues Husson
  -1 siblings, 0 replies; 48+ messages in thread
From: Pierre-Hugues Husson @ 2016-10-27 12:57 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Mark Rutland, devicetree, Arnd Bergmann, Greg Kroah-Hartman,
	Pantelis Antoniou, Chen-Yu Tsai, Rob Herring, Maxime Ripard,
	linux-arm-kernel

2016-10-27 11:14 GMT+02:00 Hans de Goede <hdegoede@redhat.com>:
> In my experience with these cheap boards, there is a mix of auto-probing +
> device / revision specific os-image modifications. I keep coming back to
> the touchscreen controller firmware (but also the orientation), for the
> gsl1680 controller I need at least 2 different firmware files (per gsl1680
> revision) to make all q8 tablets I have working. This is simply not solved
> by the vendor android code, they just shove the right firmware into the
> os-image. Likewise for the touchscreen orientation (x-mirored, y-mirored,
> etc) too is just a hard-coded setting in the os-image.
Reading your patch, it looks like to handle the two different firmware
files, you're simply adding a command-line switch, there is no
detection involved.
Am I understanding correctly?
If this is the case, two things:
1. I'm not too sure having the user choose this via cmdline is the
right way. I think I'd rather have it set by userspace. (though that's
not a strong opinion).
Or if cmdline is being changed... how about having DTS (or just an
overlay on top of it) being changed instead?

2. This could still be declared by DTS. For instance, assuming your
i2c-probe-stop-at-first-match:
&i2c0 {
        touchscreen1: gsl1680@40 {
                reg = <0x40>;
                compatible = "silead,gsl1680";
                enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
                touchscreen-size = <1024 600>;
                touchscreen-fw = "gsl1680-a082-q8-700.fw";
                filter-names = "touchscreen_variant";
                filter-0 = "none", "gsl1680-a082-q8-700";
                id = <0xa0820000>;
                status = "disabled";
        };
        touchscreen2: gsl1680@40 {
                reg = <0x40>;
                compatible = "silead,gsl1680";
                enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
                touchscreen-size = <480 800>;
                touchscreen-fw = "gsl1680-a082-q8-a70.fw";
                filter-names = "touchscreen_variant";
                filter-0 = "gsl1680-a082-q8-a70";
                id = <0xa0820000>;
               status = "disabled";
        };
        touchscreen2: gsl1680@40 {
                reg = <0x40>;
                compatible = "silead,gsl1680";
                enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
                touchscreen-size = <960 640>;
                touchscreen-fw = "gsl1680-b482-q8-d702.fw";
                filter-names = "touchscreen_variant";
                filter-0 = "gsl1680-b482-q8-d702";
                id = <0xb4820000>;
               status = "disabled";
        };
        i2c-probe-stop-at-first-match = <&touchscreen1>,
<&touchscreen2>, <&touchscreen3>;
}

With "none" value being the value when the "touchscreen_variant"
option is not defined in cmdline.

Please note that I'm not too sure whether SILEAD_REG_ID represents an
OTP which can be changed by OEM, or if it's more of a hardware
revision. Depending on this, this would either fit into a id =
<0xa0820000> DTS line, or a compatible = "silead,gsl1680_a082",
"silead,gsl1680"; DTS line.

> Sofar I've only seen this with one type of touchscreen so an easy cop-out
> would be to add an "optional-vddio-supply" to the the bindings for the
> specific touchscreen use and put all the necessary logic in the driver.
>
> This does require propagating the learned need for the regulator
> from the drivers detect() callback to probe() or alternatively I'm
> thinking we should just use probe() instead of detect()to begin with,
> that will save a lot of duplication with things
> like code for enable gpio-s and regulators.
>
> So assuming we go for the cop-out option for 3. (I'm ok with that),
> this would be a pretty clean solution adding just the 2 new:
> i2c-probe-stop-at-first-match and i2c-probe-all properties to
> the i2c-bus bindings. One problem here is that we may want to have
> multiple i2c-probe-stop-at-first-match phandle lists on a single bus
> (e.g. try 3 touchscreens + 6 accelerometers on the same bus, stop at
> first touchscreen / first accelerometer), anyone have any ideas for
> that?
How about something like:

&i2c1 {
    touchscreen1....
    touchscreen2....
    touchscreen3....
    accelerometer1....
    accelerometer2....
    accelerometer3....
    accelerometer4....

    select-one {
       compatible = "i2c-select;
       group-names = "touchscreen", "accelerometer";
       group-0 = <&touchscreen1>, <&touchscreen2>, <&touchscreen3>;
       group-1 = <&accelerometer1>, <&accelerometer2>,
<&accelerometer3>, <&accelerometer4>;
    };
};

>> When it comes to detection, I've witnessed various things.
>> It can be kernel-side or bootloader-side "global setting" reading (like an
>> ADC/resistor value, or an OTP), it can be bootloader doing the
>> "brute-force", or it can be the kernel doing all the probes.
>>
>> For instance, as of today, on a Spreadtrum ODM tree, the bootloader will
>> detect the screen by testing all knowns screens, the screen-drivers declare
>> a get_id function, and the bootloader probes until the get_id matches the id
>> declared by the screen driver.
>> And then the bootloader tells the kernel, via cmdline, which screen is
>> actually there (but auto-detection is also coded in kernel).
>> Finally all possible sensors/touchscreen/camera are declared in DTS, and
>> probe will filter-out N/C ones in the kernel.
>>
>> Now the big difference between my experience and what Hans is trying to
>> do, is that I've always worked with devices with "safely" queriable IDs,
>> either on i2c or dsi. I've never encountered SPI. This makes probing
>> inherently more dangerous, but I believe the question roughly remains the
>> same.
>
>
> I'm dealing with i2c too, Mark mistakenly used SPI in his reply,
> which I think is what got you thinking I've SPI.
Right, so let's concentrate on reasonable bus-es first then. (I can
think of I2C and DSI)

> See above, I think that we can make this work by delegating the actual
> detection to the driver (so each compatible can have a different detect
> method / code).
> So with this we can remove a big part of drivers/misc/q8-hardwaremgr.c, but
> not all
> of it. We still need board specific code somewhere to deal with things like
> picking
> the right touchscreen firmware and touchscreen orientation. This is all
> somewhat
> gsl1680 specific.
> I actually have the same problem on x86 where the ACPI description of the
> device
> basically says: "There is a gsl1680 at this bus at this address" and does
> not say
> anything about firmware / orientation (again this is simply hardcoded
> in the os-image these devices ship with).
>
> For x86 my plan is to have an array of configs in the driver and select the
> right
> one based on DMI strings, which is in essence putting board specific info in
> the
> driver.
>
> I can imagine mirroring this for ARM, and have an array of configs in the
> driver
> there too (for cases where cannot simply hardcode everything in dt only) and
> have
> some board specific code (activated by of_machine_is_compatible()) to select
> the
> right config.
I do believe this can all be done in DTS, and at the moment, what
you're describing seem to happen often enough to be worth writing
generic code for.
But then, I can't really tell which makes the most sense between
source-based and devicetree-based.
I prefer doing it in device-tree, since it means that any OEM can have
his device supported by only providing DTB, and won't need to provide
kernel patches.

> 2) miscellaneous extra config on top of figuring out which ICs are
> connected,
> basically the kind of stuff many vendors simply hard-code in their device
> specific os-image. This one is much more difficult to deal with and I think
> we need to figure this out on a case by case basis. This will require board
> specific code (just like the kernel has tons of DMI string activated board
> specific code on x86) and what is the best code for this place to live will
> be a case by case thing too.

With things like mount-matrix devicetree property, the goal is to have
such informations in the DTS.
I'm not seeing every cases should be handled in DTS, but ATM I see no
good reason.

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-27 12:57               ` Pierre-Hugues Husson
  0 siblings, 0 replies; 48+ messages in thread
From: Pierre-Hugues Husson @ 2016-10-27 12:57 UTC (permalink / raw)
  To: linux-arm-kernel

2016-10-27 11:14 GMT+02:00 Hans de Goede <hdegoede@redhat.com>:
> In my experience with these cheap boards, there is a mix of auto-probing +
> device / revision specific os-image modifications. I keep coming back to
> the touchscreen controller firmware (but also the orientation), for the
> gsl1680 controller I need at least 2 different firmware files (per gsl1680
> revision) to make all q8 tablets I have working. This is simply not solved
> by the vendor android code, they just shove the right firmware into the
> os-image. Likewise for the touchscreen orientation (x-mirored, y-mirored,
> etc) too is just a hard-coded setting in the os-image.
Reading your patch, it looks like to handle the two different firmware
files, you're simply adding a command-line switch, there is no
detection involved.
Am I understanding correctly?
If this is the case, two things:
1. I'm not too sure having the user choose this via cmdline is the
right way. I think I'd rather have it set by userspace. (though that's
not a strong opinion).
Or if cmdline is being changed... how about having DTS (or just an
overlay on top of it) being changed instead?

2. This could still be declared by DTS. For instance, assuming your
i2c-probe-stop-at-first-match:
&i2c0 {
        touchscreen1: gsl1680 at 40 {
                reg = <0x40>;
                compatible = "silead,gsl1680";
                enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
                touchscreen-size = <1024 600>;
                touchscreen-fw = "gsl1680-a082-q8-700.fw";
                filter-names = "touchscreen_variant";
                filter-0 = "none", "gsl1680-a082-q8-700";
                id = <0xa0820000>;
                status = "disabled";
        };
        touchscreen2: gsl1680 at 40 {
                reg = <0x40>;
                compatible = "silead,gsl1680";
                enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
                touchscreen-size = <480 800>;
                touchscreen-fw = "gsl1680-a082-q8-a70.fw";
                filter-names = "touchscreen_variant";
                filter-0 = "gsl1680-a082-q8-a70";
                id = <0xa0820000>;
               status = "disabled";
        };
        touchscreen2: gsl1680 at 40 {
                reg = <0x40>;
                compatible = "silead,gsl1680";
                enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
                touchscreen-size = <960 640>;
                touchscreen-fw = "gsl1680-b482-q8-d702.fw";
                filter-names = "touchscreen_variant";
                filter-0 = "gsl1680-b482-q8-d702";
                id = <0xb4820000>;
               status = "disabled";
        };
        i2c-probe-stop-at-first-match = <&touchscreen1>,
<&touchscreen2>, <&touchscreen3>;
}

With "none" value being the value when the "touchscreen_variant"
option is not defined in cmdline.

Please note that I'm not too sure whether SILEAD_REG_ID represents an
OTP which can be changed by OEM, or if it's more of a hardware
revision. Depending on this, this would either fit into a id =
<0xa0820000> DTS line, or a compatible = "silead,gsl1680_a082",
"silead,gsl1680"; DTS line.

> Sofar I've only seen this with one type of touchscreen so an easy cop-out
> would be to add an "optional-vddio-supply" to the the bindings for the
> specific touchscreen use and put all the necessary logic in the driver.
>
> This does require propagating the learned need for the regulator
> from the drivers detect() callback to probe() or alternatively I'm
> thinking we should just use probe() instead of detect()to begin with,
> that will save a lot of duplication with things
> like code for enable gpio-s and regulators.
>
> So assuming we go for the cop-out option for 3. (I'm ok with that),
> this would be a pretty clean solution adding just the 2 new:
> i2c-probe-stop-at-first-match and i2c-probe-all properties to
> the i2c-bus bindings. One problem here is that we may want to have
> multiple i2c-probe-stop-at-first-match phandle lists on a single bus
> (e.g. try 3 touchscreens + 6 accelerometers on the same bus, stop at
> first touchscreen / first accelerometer), anyone have any ideas for
> that?
How about something like:

&i2c1 {
    touchscreen1....
    touchscreen2....
    touchscreen3....
    accelerometer1....
    accelerometer2....
    accelerometer3....
    accelerometer4....

    select-one {
       compatible = "i2c-select;
       group-names = "touchscreen", "accelerometer";
       group-0 = <&touchscreen1>, <&touchscreen2>, <&touchscreen3>;
       group-1 = <&accelerometer1>, <&accelerometer2>,
<&accelerometer3>, <&accelerometer4>;
    };
};

>> When it comes to detection, I've witnessed various things.
>> It can be kernel-side or bootloader-side "global setting" reading (like an
>> ADC/resistor value, or an OTP), it can be bootloader doing the
>> "brute-force", or it can be the kernel doing all the probes.
>>
>> For instance, as of today, on a Spreadtrum ODM tree, the bootloader will
>> detect the screen by testing all knowns screens, the screen-drivers declare
>> a get_id function, and the bootloader probes until the get_id matches the id
>> declared by the screen driver.
>> And then the bootloader tells the kernel, via cmdline, which screen is
>> actually there (but auto-detection is also coded in kernel).
>> Finally all possible sensors/touchscreen/camera are declared in DTS, and
>> probe will filter-out N/C ones in the kernel.
>>
>> Now the big difference between my experience and what Hans is trying to
>> do, is that I've always worked with devices with "safely" queriable IDs,
>> either on i2c or dsi. I've never encountered SPI. This makes probing
>> inherently more dangerous, but I believe the question roughly remains the
>> same.
>
>
> I'm dealing with i2c too, Mark mistakenly used SPI in his reply,
> which I think is what got you thinking I've SPI.
Right, so let's concentrate on reasonable bus-es first then. (I can
think of I2C and DSI)

> See above, I think that we can make this work by delegating the actual
> detection to the driver (so each compatible can have a different detect
> method / code).
> So with this we can remove a big part of drivers/misc/q8-hardwaremgr.c, but
> not all
> of it. We still need board specific code somewhere to deal with things like
> picking
> the right touchscreen firmware and touchscreen orientation. This is all
> somewhat
> gsl1680 specific.
> I actually have the same problem on x86 where the ACPI description of the
> device
> basically says: "There is a gsl1680 at this bus at this address" and does
> not say
> anything about firmware / orientation (again this is simply hardcoded
> in the os-image these devices ship with).
>
> For x86 my plan is to have an array of configs in the driver and select the
> right
> one based on DMI strings, which is in essence putting board specific info in
> the
> driver.
>
> I can imagine mirroring this for ARM, and have an array of configs in the
> driver
> there too (for cases where cannot simply hardcode everything in dt only) and
> have
> some board specific code (activated by of_machine_is_compatible()) to select
> the
> right config.
I do believe this can all be done in DTS, and at the moment, what
you're describing seem to happen often enough to be worth writing
generic code for.
But then, I can't really tell which makes the most sense between
source-based and devicetree-based.
I prefer doing it in device-tree, since it means that any OEM can have
his device supported by only providing DTB, and won't need to provide
kernel patches.

> 2) miscellaneous extra config on top of figuring out which ICs are
> connected,
> basically the kind of stuff many vendors simply hard-code in their device
> specific os-image. This one is much more difficult to deal with and I think
> we need to figure this out on a case by case basis. This will require board
> specific code (just like the kernel has tons of DMI string activated board
> specific code on x86) and what is the best code for this place to live will
> be a case by case thing too.

With things like mount-matrix devicetree property, the goal is to have
such informations in the DTS.
I'm not seeing every cases should be handled in DTS, but ATM I see no
good reason.

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

* Re: Add Allwinner Q8 tablets hardware manager
  2016-10-27 12:57               ` Pierre-Hugues Husson
@ 2016-10-27 14:53                 ` Hans de Goede
  -1 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-27 14:53 UTC (permalink / raw)
  To: Pierre-Hugues Husson
  Cc: Mark Rutland, devicetree, Arnd Bergmann, Greg Kroah-Hartman,
	Pantelis Antoniou, Chen-Yu Tsai, Rob Herring, Maxime Ripard,
	linux-arm-kernel

Hi,

On 27-10-16 14:57, Pierre-Hugues Husson wrote:
> 2016-10-27 11:14 GMT+02:00 Hans de Goede <hdegoede@redhat.com>:
>> In my experience with these cheap boards, there is a mix of auto-probing +
>> device / revision specific os-image modifications. I keep coming back to
>> the touchscreen controller firmware (but also the orientation), for the
>> gsl1680 controller I need at least 2 different firmware files (per gsl1680
>> revision) to make all q8 tablets I have working. This is simply not solved
>> by the vendor android code, they just shove the right firmware into the
>> os-image. Likewise for the touchscreen orientation (x-mirored, y-mirored,
>> etc) too is just a hard-coded setting in the os-image.
> Reading your patch, it looks like to handle the two different firmware
> files, you're simply adding a command-line switch, there is no
> detection involved.
> Am I understanding correctly?

No, the firmware-name (and matching resolution as different firmwares
report different axis-ranges for the same digitizer) is selected
primarily by the touchscreen_variant which sets: touchscreen_fw_name,
touchscreen_width and touchscreen_height.

The touchscreen_variant module option defaults to -1 which means "auto",
when it is auto it gets set based on the touchscreen / accelerometer
combination (which more or less uniquely identifies boards sofar),
likewise all the other touchscreen module options default to -1,
but can be overridden from the commandline.

The intention is for things to just work, the commandline options are
there as a fallback.

> If this is the case, two things:
> 1. I'm not too sure having the user choose this via cmdline is the
> right way. I think I'd rather have it set by userspace. (though that's
> not a strong opinion).
> Or if cmdline is being changed... how about having DTS (or just an
> overlay on top of it) being changed instead?
>
> 2. This could still be declared by DTS. For instance, assuming your
> i2c-probe-stop-at-first-match:
> &i2c0 {
>         touchscreen1: gsl1680@40 {
>                 reg = <0x40>;
>                 compatible = "silead,gsl1680";
>                 enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
>                 touchscreen-size = <1024 600>;
>                 touchscreen-fw = "gsl1680-a082-q8-700.fw";
>                 filter-names = "touchscreen_variant";
>                 filter-0 = "none", "gsl1680-a082-q8-700";
>                 id = <0xa0820000>;
>                 status = "disabled";
>         };
>         touchscreen2: gsl1680@40 {
>                 reg = <0x40>;
>                 compatible = "silead,gsl1680";
>                 enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
>                 touchscreen-size = <480 800>;
>                 touchscreen-fw = "gsl1680-a082-q8-a70.fw";
>                 filter-names = "touchscreen_variant";
>                 filter-0 = "gsl1680-a082-q8-a70";
>                 id = <0xa0820000>;
>                status = "disabled";
>         };
>         touchscreen2: gsl1680@40 {
>                 reg = <0x40>;
>                 compatible = "silead,gsl1680";
>                 enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
>                 touchscreen-size = <960 640>;
>                 touchscreen-fw = "gsl1680-b482-q8-d702.fw";
>                 filter-names = "touchscreen_variant";
>                 filter-0 = "gsl1680-b482-q8-d702";
>                 id = <0xb4820000>;
>                status = "disabled";
>         };
>         i2c-probe-stop-at-first-match = <&touchscreen1>,
> <&touchscreen2>, <&touchscreen3>;
> }
>
> With "none" value being the value when the "touchscreen_variant"
> option is not defined in cmdline.
>
> Please note that I'm not too sure whether SILEAD_REG_ID represents an
> OTP which can be changed by OEM, or if it's more of a hardware
> revision. Depending on this, this would either fit into a id =
> <0xa0820000> DTS line, or a compatible = "silead,gsl1680_a082",
> "silead,gsl1680"; DTS line.
>
>> Sofar I've only seen this with one type of touchscreen so an easy cop-out
>> would be to add an "optional-vddio-supply" to the the bindings for the
>> specific touchscreen use and put all the necessary logic in the driver.
>>
>> This does require propagating the learned need for the regulator
>> from the drivers detect() callback to probe() or alternatively I'm
>> thinking we should just use probe() instead of detect()to begin with,
>> that will save a lot of duplication with things
>> like code for enable gpio-s and regulators.
>>
>> So assuming we go for the cop-out option for 3. (I'm ok with that),
>> this would be a pretty clean solution adding just the 2 new:
>> i2c-probe-stop-at-first-match and i2c-probe-all properties to
>> the i2c-bus bindings. One problem here is that we may want to have
>> multiple i2c-probe-stop-at-first-match phandle lists on a single bus
>> (e.g. try 3 touchscreens + 6 accelerometers on the same bus, stop at
>> first touchscreen / first accelerometer), anyone have any ideas for
>> that?
> How about something like:
>
> &i2c1 {
>     touchscreen1....
>     touchscreen2....
>     touchscreen3....
>     accelerometer1....
>     accelerometer2....
>     accelerometer3....
>     accelerometer4....
>
>     select-one {
>        compatible = "i2c-select;
>        group-names = "touchscreen", "accelerometer";
>        group-0 = <&touchscreen1>, <&touchscreen2>, <&touchscreen3>;
>        group-1 = <&accelerometer1>, <&accelerometer2>,
> <&accelerometer3>, <&accelerometer4>;
>     };
> };

We could just have:

	i2c-probe-stop-at-first-match-0 = <&touchscreen1>, <&touchscreen2>, <&touchscreen3>;
	i2c-probe-stop-at-first-match-1 = <&accelerometer1>, <&accelerometer2>;

And have the i2c bus code look for an i2c-probe-stop-at-first-match-[i++] property
until it is not found. Having a child-node with its own compatible for this
feels wrong, as it uses a hierarchy where there really is none.

>>> When it comes to detection, I've witnessed various things.
>>> It can be kernel-side or bootloader-side "global setting" reading (like an
>>> ADC/resistor value, or an OTP), it can be bootloader doing the
>>> "brute-force", or it can be the kernel doing all the probes.
>>>
>>> For instance, as of today, on a Spreadtrum ODM tree, the bootloader will
>>> detect the screen by testing all knowns screens, the screen-drivers declare
>>> a get_id function, and the bootloader probes until the get_id matches the id
>>> declared by the screen driver.
>>> And then the bootloader tells the kernel, via cmdline, which screen is
>>> actually there (but auto-detection is also coded in kernel).
>>> Finally all possible sensors/touchscreen/camera are declared in DTS, and
>>> probe will filter-out N/C ones in the kernel.
>>>
>>> Now the big difference between my experience and what Hans is trying to
>>> do, is that I've always worked with devices with "safely" queriable IDs,
>>> either on i2c or dsi. I've never encountered SPI. This makes probing
>>> inherently more dangerous, but I believe the question roughly remains the
>>> same.
>>
>>
>> I'm dealing with i2c too, Mark mistakenly used SPI in his reply,
>> which I think is what got you thinking I've SPI.
> Right, so let's concentrate on reasonable bus-es first then. (I can
> think of I2C and DSI)
>
>> See above, I think that we can make this work by delegating the actual
>> detection to the driver (so each compatible can have a different detect
>> method / code).
>> So with this we can remove a big part of drivers/misc/q8-hardwaremgr.c, but
>> not all
>> of it. We still need board specific code somewhere to deal with things like
>> picking
>> the right touchscreen firmware and touchscreen orientation. This is all
>> somewhat
>> gsl1680 specific.
>> I actually have the same problem on x86 where the ACPI description of the
>> device
>> basically says: "There is a gsl1680 at this bus at this address" and does
>> not say
>> anything about firmware / orientation (again this is simply hardcoded
>> in the os-image these devices ship with).
>>
>> For x86 my plan is to have an array of configs in the driver and select the
>> right
>> one based on DMI strings, which is in essence putting board specific info in
>> the
>> driver.
>>
>> I can imagine mirroring this for ARM, and have an array of configs in the
>> driver
>> there too (for cases where cannot simply hardcode everything in dt only) and
>> have
>> some board specific code (activated by of_machine_is_compatible()) to select
>> the
>> right config.
> I do believe this can all be done in DTS

Well x86 does not have DTS.

> and at the moment, what
> you're describing seem to happen often enough to be worth writing
> generic code for.

Let me quote some of the auto-code currently in q8-hardwaremgr.c :

                 /*
                  * These accelerometer based heuristics select the best
                  * default based on known q8 tablets.
                  */
                 switch (data->accelerometer.model) {
                 case da280:
                         if (data->accelerometer.addr == 0x27)
                                 ; /* No-op */
                         else if (data->has_rda599x)
                                 data->touchscreen_invert_x = 1;
                         else
                                 data->touchscreen_invert_y = 1;
                         break;
                 case dmard09:
                         data->touchscreen_invert_x = 1;
                         break;
                 case mxc6225:
                         data->touchscreen_variant = 1;
                         break;
                 }

(Non set data->touchscreen_foo are left at 0).

So this would require us to be able to filter (to use your example)
on if another i2c device is found and on which address it is found,
that does not even take the rda559x check into account and is
going to cause interesting ordering issues, how do we know when
we can actually do the filtering if some of the variables we are
filtering on are set by other auto-detected paths. Which auto-detect /
i2c-probe-stop-at-first-match list do we execute first ? Worse
actually for accelerometer orientation I will likely need to
set the mount-matrix based on the detected touchscreen ...

The rda559x here is a sdio wifi chip, which is also connected to the
i2c, and currently is detected through i2c to be able to separately
identify 2 q8 boards which share the same touchscreen + accelerometer
combination and who knows what other checks I or other people can
come up with to differentiate board variants which do not have
a simple eeprom to uniquely id them.

So as said before, no this cannot be all done in dt without
adding a turing complete language to dt, and that is just to
select which touchscreen_variant to use.

Then there also the probem of the combinatorial explosion having
not only 2 firmware files but also invert-x and invert-y flags causes:
We have 2 revisions with each 2 different firmware-files (more actually
but I've reduced the set since some firmwares are compatible) with each
both the x- and / or y axis as normal or inverted, for a total of:
2 (revision) * 2 (firmware-files) * 2 (x-inverted or not) * 2 (y...) = 16
touchscreen variants, which means dt nodes for touchscreen1 to touchscreen16
and that is just the silead gsl1680, some of these tablets also have
elan or zeitec touchscreen controllers.

Now imagine what happens if a new board comes out which needs a 3th firmware
file... I hope you can understand this is not a route I want to go.

Another problem is that if a user encounters the need for a new firmware
variant he can now not easily try this (where as before we had
module options to separately override firmware-name, the size, etc.

As written in my previous mail, this is all rather gsl1680 specific,
and esp. being able to override the firmware-name, the size, etc.
through module options is going to be useful (to ask endusers to test
stuff without recompiling) on x86 too. So we will likely want to add
most of the necessary stuff to the silead driver anyways.

> But then, I can't really tell which makes the most sense between
> source-based and devicetree-based.
> I prefer doing it in device-tree, since it means that any OEM can have
> his device supported by only providing DTB, and won't need to provide
> kernel patches.

If the OEM provides a DTB the OEM can just directly have the right
parameters in there without relying on any auto-detection, this is
already supported and the e.g. gsl1680 driver already happily
works on several tablets where there is not so much hardware
variance.

Even if the OEM needs to deal with e.g. different touchscreens on
different board revisions, hopefully the simple auto-detect code will
be enough, and he does not need e.g. different firmware-name settings
for otherwise the same touchscreen controller. If that is not the
case then he the OEM will have to provide a separate static
(non probing) DTB per variant.

>> 2) miscellaneous extra config on top of figuring out which ICs are
>> connected,
>> basically the kind of stuff many vendors simply hard-code in their device
>> specific os-image. This one is much more difficult to deal with and I think
>> we need to figure this out on a case by case basis. This will require board
>> specific code (just like the kernel has tons of DMI string activated board
>> specific code on x86) and what is the best code for this place to live will
>> be a case by case thing too.
>
> With things like mount-matrix devicetree property, the goal is to have
> such informations in the DTS.

Right and all the info I'm talking about can already be in the DTS and
is already specified this way for various existing boards, this is
obviously how we want things to work, this is the normal case /
the straight code path.

Now lets get back to your mount-matrix example, the problem here is 2 board
variants where the same accelerometer is used, but on a newer revision
of the board it is mounted with a different orientation and otherwise
almost nothing is changed on the board, certainly not something as
useful as an id eeprom.

Lets assume that we can however still somehow differ the 2 revisions,
then try to imagine how many different ways there are to differ
between 2 board revisions if there is no easy way to do so,
some crazy examples:
-The 2nd revision has an external loopback on unused audio out / in
  pins for testing purposes, we could play + record sound and do
  a (rough) waveform match to see if the loopback is present
-On the 2nd revision a pin from a pin compatible part which
  allows putting it in fully compatible mode, or allow new features
  mode, is now hooked up to a gpio instead of hardwired to compatible
  mode, we could change the device to new features mode and try
  to read/modify/write some register bit on the chip which is only
  writable in this mode
-Etc.

Now try to design a way to express this in dt and we're back to
needing a turing complete language (with a library for accessing
various busses) again.

Regards,

Hans

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-27 14:53                 ` Hans de Goede
  0 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-27 14:53 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 27-10-16 14:57, Pierre-Hugues Husson wrote:
> 2016-10-27 11:14 GMT+02:00 Hans de Goede <hdegoede@redhat.com>:
>> In my experience with these cheap boards, there is a mix of auto-probing +
>> device / revision specific os-image modifications. I keep coming back to
>> the touchscreen controller firmware (but also the orientation), for the
>> gsl1680 controller I need at least 2 different firmware files (per gsl1680
>> revision) to make all q8 tablets I have working. This is simply not solved
>> by the vendor android code, they just shove the right firmware into the
>> os-image. Likewise for the touchscreen orientation (x-mirored, y-mirored,
>> etc) too is just a hard-coded setting in the os-image.
> Reading your patch, it looks like to handle the two different firmware
> files, you're simply adding a command-line switch, there is no
> detection involved.
> Am I understanding correctly?

No, the firmware-name (and matching resolution as different firmwares
report different axis-ranges for the same digitizer) is selected
primarily by the touchscreen_variant which sets: touchscreen_fw_name,
touchscreen_width and touchscreen_height.

The touchscreen_variant module option defaults to -1 which means "auto",
when it is auto it gets set based on the touchscreen / accelerometer
combination (which more or less uniquely identifies boards sofar),
likewise all the other touchscreen module options default to -1,
but can be overridden from the commandline.

The intention is for things to just work, the commandline options are
there as a fallback.

> If this is the case, two things:
> 1. I'm not too sure having the user choose this via cmdline is the
> right way. I think I'd rather have it set by userspace. (though that's
> not a strong opinion).
> Or if cmdline is being changed... how about having DTS (or just an
> overlay on top of it) being changed instead?
>
> 2. This could still be declared by DTS. For instance, assuming your
> i2c-probe-stop-at-first-match:
> &i2c0 {
>         touchscreen1: gsl1680 at 40 {
>                 reg = <0x40>;
>                 compatible = "silead,gsl1680";
>                 enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
>                 touchscreen-size = <1024 600>;
>                 touchscreen-fw = "gsl1680-a082-q8-700.fw";
>                 filter-names = "touchscreen_variant";
>                 filter-0 = "none", "gsl1680-a082-q8-700";
>                 id = <0xa0820000>;
>                 status = "disabled";
>         };
>         touchscreen2: gsl1680 at 40 {
>                 reg = <0x40>;
>                 compatible = "silead,gsl1680";
>                 enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
>                 touchscreen-size = <480 800>;
>                 touchscreen-fw = "gsl1680-a082-q8-a70.fw";
>                 filter-names = "touchscreen_variant";
>                 filter-0 = "gsl1680-a082-q8-a70";
>                 id = <0xa0820000>;
>                status = "disabled";
>         };
>         touchscreen2: gsl1680 at 40 {
>                 reg = <0x40>;
>                 compatible = "silead,gsl1680";
>                 enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
>                 touchscreen-size = <960 640>;
>                 touchscreen-fw = "gsl1680-b482-q8-d702.fw";
>                 filter-names = "touchscreen_variant";
>                 filter-0 = "gsl1680-b482-q8-d702";
>                 id = <0xb4820000>;
>                status = "disabled";
>         };
>         i2c-probe-stop-at-first-match = <&touchscreen1>,
> <&touchscreen2>, <&touchscreen3>;
> }
>
> With "none" value being the value when the "touchscreen_variant"
> option is not defined in cmdline.
>
> Please note that I'm not too sure whether SILEAD_REG_ID represents an
> OTP which can be changed by OEM, or if it's more of a hardware
> revision. Depending on this, this would either fit into a id =
> <0xa0820000> DTS line, or a compatible = "silead,gsl1680_a082",
> "silead,gsl1680"; DTS line.
>
>> Sofar I've only seen this with one type of touchscreen so an easy cop-out
>> would be to add an "optional-vddio-supply" to the the bindings for the
>> specific touchscreen use and put all the necessary logic in the driver.
>>
>> This does require propagating the learned need for the regulator
>> from the drivers detect() callback to probe() or alternatively I'm
>> thinking we should just use probe() instead of detect()to begin with,
>> that will save a lot of duplication with things
>> like code for enable gpio-s and regulators.
>>
>> So assuming we go for the cop-out option for 3. (I'm ok with that),
>> this would be a pretty clean solution adding just the 2 new:
>> i2c-probe-stop-at-first-match and i2c-probe-all properties to
>> the i2c-bus bindings. One problem here is that we may want to have
>> multiple i2c-probe-stop-at-first-match phandle lists on a single bus
>> (e.g. try 3 touchscreens + 6 accelerometers on the same bus, stop at
>> first touchscreen / first accelerometer), anyone have any ideas for
>> that?
> How about something like:
>
> &i2c1 {
>     touchscreen1....
>     touchscreen2....
>     touchscreen3....
>     accelerometer1....
>     accelerometer2....
>     accelerometer3....
>     accelerometer4....
>
>     select-one {
>        compatible = "i2c-select;
>        group-names = "touchscreen", "accelerometer";
>        group-0 = <&touchscreen1>, <&touchscreen2>, <&touchscreen3>;
>        group-1 = <&accelerometer1>, <&accelerometer2>,
> <&accelerometer3>, <&accelerometer4>;
>     };
> };

We could just have:

	i2c-probe-stop-at-first-match-0 = <&touchscreen1>, <&touchscreen2>, <&touchscreen3>;
	i2c-probe-stop-at-first-match-1 = <&accelerometer1>, <&accelerometer2>;

And have the i2c bus code look for an i2c-probe-stop-at-first-match-[i++] property
until it is not found. Having a child-node with its own compatible for this
feels wrong, as it uses a hierarchy where there really is none.

>>> When it comes to detection, I've witnessed various things.
>>> It can be kernel-side or bootloader-side "global setting" reading (like an
>>> ADC/resistor value, or an OTP), it can be bootloader doing the
>>> "brute-force", or it can be the kernel doing all the probes.
>>>
>>> For instance, as of today, on a Spreadtrum ODM tree, the bootloader will
>>> detect the screen by testing all knowns screens, the screen-drivers declare
>>> a get_id function, and the bootloader probes until the get_id matches the id
>>> declared by the screen driver.
>>> And then the bootloader tells the kernel, via cmdline, which screen is
>>> actually there (but auto-detection is also coded in kernel).
>>> Finally all possible sensors/touchscreen/camera are declared in DTS, and
>>> probe will filter-out N/C ones in the kernel.
>>>
>>> Now the big difference between my experience and what Hans is trying to
>>> do, is that I've always worked with devices with "safely" queriable IDs,
>>> either on i2c or dsi. I've never encountered SPI. This makes probing
>>> inherently more dangerous, but I believe the question roughly remains the
>>> same.
>>
>>
>> I'm dealing with i2c too, Mark mistakenly used SPI in his reply,
>> which I think is what got you thinking I've SPI.
> Right, so let's concentrate on reasonable bus-es first then. (I can
> think of I2C and DSI)
>
>> See above, I think that we can make this work by delegating the actual
>> detection to the driver (so each compatible can have a different detect
>> method / code).
>> So with this we can remove a big part of drivers/misc/q8-hardwaremgr.c, but
>> not all
>> of it. We still need board specific code somewhere to deal with things like
>> picking
>> the right touchscreen firmware and touchscreen orientation. This is all
>> somewhat
>> gsl1680 specific.
>> I actually have the same problem on x86 where the ACPI description of the
>> device
>> basically says: "There is a gsl1680 at this bus at this address" and does
>> not say
>> anything about firmware / orientation (again this is simply hardcoded
>> in the os-image these devices ship with).
>>
>> For x86 my plan is to have an array of configs in the driver and select the
>> right
>> one based on DMI strings, which is in essence putting board specific info in
>> the
>> driver.
>>
>> I can imagine mirroring this for ARM, and have an array of configs in the
>> driver
>> there too (for cases where cannot simply hardcode everything in dt only) and
>> have
>> some board specific code (activated by of_machine_is_compatible()) to select
>> the
>> right config.
> I do believe this can all be done in DTS

Well x86 does not have DTS.

> and at the moment, what
> you're describing seem to happen often enough to be worth writing
> generic code for.

Let me quote some of the auto-code currently in q8-hardwaremgr.c :

                 /*
                  * These accelerometer based heuristics select the best
                  * default based on known q8 tablets.
                  */
                 switch (data->accelerometer.model) {
                 case da280:
                         if (data->accelerometer.addr == 0x27)
                                 ; /* No-op */
                         else if (data->has_rda599x)
                                 data->touchscreen_invert_x = 1;
                         else
                                 data->touchscreen_invert_y = 1;
                         break;
                 case dmard09:
                         data->touchscreen_invert_x = 1;
                         break;
                 case mxc6225:
                         data->touchscreen_variant = 1;
                         break;
                 }

(Non set data->touchscreen_foo are left at 0).

So this would require us to be able to filter (to use your example)
on if another i2c device is found and on which address it is found,
that does not even take the rda559x check into account and is
going to cause interesting ordering issues, how do we know when
we can actually do the filtering if some of the variables we are
filtering on are set by other auto-detected paths. Which auto-detect /
i2c-probe-stop-at-first-match list do we execute first ? Worse
actually for accelerometer orientation I will likely need to
set the mount-matrix based on the detected touchscreen ...

The rda559x here is a sdio wifi chip, which is also connected to the
i2c, and currently is detected through i2c to be able to separately
identify 2 q8 boards which share the same touchscreen + accelerometer
combination and who knows what other checks I or other people can
come up with to differentiate board variants which do not have
a simple eeprom to uniquely id them.

So as said before, no this cannot be all done in dt without
adding a turing complete language to dt, and that is just to
select which touchscreen_variant to use.

Then there also the probem of the combinatorial explosion having
not only 2 firmware files but also invert-x and invert-y flags causes:
We have 2 revisions with each 2 different firmware-files (more actually
but I've reduced the set since some firmwares are compatible) with each
both the x- and / or y axis as normal or inverted, for a total of:
2 (revision) * 2 (firmware-files) * 2 (x-inverted or not) * 2 (y...) = 16
touchscreen variants, which means dt nodes for touchscreen1 to touchscreen16
and that is just the silead gsl1680, some of these tablets also have
elan or zeitec touchscreen controllers.

Now imagine what happens if a new board comes out which needs a 3th firmware
file... I hope you can understand this is not a route I want to go.

Another problem is that if a user encounters the need for a new firmware
variant he can now not easily try this (where as before we had
module options to separately override firmware-name, the size, etc.

As written in my previous mail, this is all rather gsl1680 specific,
and esp. being able to override the firmware-name, the size, etc.
through module options is going to be useful (to ask endusers to test
stuff without recompiling) on x86 too. So we will likely want to add
most of the necessary stuff to the silead driver anyways.

> But then, I can't really tell which makes the most sense between
> source-based and devicetree-based.
> I prefer doing it in device-tree, since it means that any OEM can have
> his device supported by only providing DTB, and won't need to provide
> kernel patches.

If the OEM provides a DTB the OEM can just directly have the right
parameters in there without relying on any auto-detection, this is
already supported and the e.g. gsl1680 driver already happily
works on several tablets where there is not so much hardware
variance.

Even if the OEM needs to deal with e.g. different touchscreens on
different board revisions, hopefully the simple auto-detect code will
be enough, and he does not need e.g. different firmware-name settings
for otherwise the same touchscreen controller. If that is not the
case then he the OEM will have to provide a separate static
(non probing) DTB per variant.

>> 2) miscellaneous extra config on top of figuring out which ICs are
>> connected,
>> basically the kind of stuff many vendors simply hard-code in their device
>> specific os-image. This one is much more difficult to deal with and I think
>> we need to figure this out on a case by case basis. This will require board
>> specific code (just like the kernel has tons of DMI string activated board
>> specific code on x86) and what is the best code for this place to live will
>> be a case by case thing too.
>
> With things like mount-matrix devicetree property, the goal is to have
> such informations in the DTS.

Right and all the info I'm talking about can already be in the DTS and
is already specified this way for various existing boards, this is
obviously how we want things to work, this is the normal case /
the straight code path.

Now lets get back to your mount-matrix example, the problem here is 2 board
variants where the same accelerometer is used, but on a newer revision
of the board it is mounted with a different orientation and otherwise
almost nothing is changed on the board, certainly not something as
useful as an id eeprom.

Lets assume that we can however still somehow differ the 2 revisions,
then try to imagine how many different ways there are to differ
between 2 board revisions if there is no easy way to do so,
some crazy examples:
-The 2nd revision has an external loopback on unused audio out / in
  pins for testing purposes, we could play + record sound and do
  a (rough) waveform match to see if the loopback is present
-On the 2nd revision a pin from a pin compatible part which
  allows putting it in fully compatible mode, or allow new features
  mode, is now hooked up to a gpio instead of hardwired to compatible
  mode, we could change the device to new features mode and try
  to read/modify/write some register bit on the chip which is only
  writable in this mode
-Etc.

Now try to design a way to express this in dt and we're back to
needing a turing complete language (with a library for accessing
various busses) again.

Regards,

Hans

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

* Re: Add Allwinner Q8 tablets hardware manager
  2016-10-26 11:46       ` Hans de Goede
@ 2016-10-27 15:52           ` Pantelis Antoniou
  -1 siblings, 0 replies; 48+ messages in thread
From: Pantelis Antoniou @ 2016-10-27 15:52 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Mark Rutland, Rob Herring, Arnd Bergmann, Greg Kroah-Hartman,
	Maxime Ripard, Chen-Yu Tsai,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree

Hi Hans,

> On Oct 26, 2016, at 14:46 , Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> 
> Hi,
> 
> On 24-10-16 19:39, Mark Rutland wrote:
>> On Fri, Oct 14, 2016 at 09:53:31AM +0200, Hans de Goede wrote:
>>> Hi Rob, Mark, et al.,
>> 
>> Hi Hans,
>> 
>> Apologies for the delay in replying to this.
> 
> No worries, I believe that 1 week is actually a pretty good
> turn around time, esp. directly after a conference.
> 

Conferences are a deadline killer. Just got around taking a look.

>> I'd like to be clear that I do understand that there is a problem that
>> needs to be addressed here. However, I do not believe that the *current*
>> in-kernel approach is correct. More on that below.
> 
> Ok.
> 
>>> Mark, I know that we discussed this at ELCE and you clearly indicated
>>> that according to you this does not belong in the kernel. I was a bit
>>> surprised by this part of the discussion.
>>> 
>>> I had posted a RFC earlier and Rob had indicated that given that the q8
>>> tablets are a special case, as my code uses actual probing rather then some
>>> pre-arranged id mechanism with say an eeprom, that doing this in a
>>> non-generic manner would be ok for my special case.
>> 
>> To some extent, Rob and I may have differing views here; I'm not
>> entirely sure what Rob's view is, and I cannot talk on his behalf. I
>> certainly must apologise for having not commented on said RFC, however.
>> 
>>> So on to why I believe that the kernel is the best place to do this, at least
>>> for my special use-case:
>>> 
>>> 1. Configurability
>>> 
>>> Since the q8 tablets do not have any id mechanism I'm probing i2c busses to
>>> generate i2c client dt nodes with the right address and compatible.
>>> Some info in these nodes (e.g. touchscreen firmware-name) is not probable at
>>> all and gets set by heuristics. This heuristics may get things wrong.
>>> So my current implementation offers kernel cmdline options to override this.
>> 
>> As I mentioned at ELCE, one major concern I have with this approach is
>> this probing, which in part relies on a collection of heuristics.
> 
> This is quite use-case specific, anyways, the probing is a 2 step process:
> 
> 1) Identify which hardware there is in the tablet, this is pretty
> reliable, we only detect a fix set of known possible touchscreens
> and accelerometers, at known addresses and almost all have an id
> register to check.
> 
> 2) Determine *defaults* for various none probable settings, like guessing
> which firmware to load into the touchscreen controllers, as there are
> at least 2 ways the gsl1680 is wired up on these tablets and this
> requires 2 different firmware files. This uses heuristics, to, as said,
> determine the defaults all of the non-probable bits are overidable
> through config options (currently kernel module options). Getting these
> wrong is not dangerous to the hardware, but will work in a non-functional
> or misbehaving (wrong coordinates) touchscreen.
> 
> Note with the models I've access to so far the heuristics score 100%
> but I'm not sure how representative the 16 models I've access to are
> (they are all different and have been bought over a span of multiple
> years).

> 
>> I'm worried that this is very fragile, and sets us up for having to
>> maintain a much larger collection of heuristics and/or a database of
>> particular boards in future. This is fragile, defeats much of the gain
>> from DT.
> 
> I understand your worries, as said I'm confident the actual probing
> is safe and getting the heuristics wrong will result in misbehavior,
> but not in any hardware damage or such.
> 
>> Worse, this could be completely incompatible with some arbitrary board
>> that comes by in future,
> 
> I assume you mean an arbitrary q8 tablet here, as the probe code does
> bind by board/machine compatible, so for a really arbitrary board
> this code will never activate.
> 
>> because the kernel assumed something that was
>> not true, which it would not have done if things were explicitly
>> described to the kernel.
> 
> I understand your worry, but moving the probing code to say u-boot
> will not change any of this, the kernel will get the explicit
> description created by the u-boot probe code, but it would be
> just as wrong.
> 
> So maybe we need to answer 2 questions in a row:
> 
> 1) Do we want such probe code at all ?
> 
> My answer to this is yes, these (cheap) tablets are interesting to
> e.g. the maker community and I would like them to run mainline
> (and run mainline well), but given the way there are put together
> this require some code to dynamically adapt to the batch of the
> month somewhere
> 
> 2) Where do we put this code ?
> 
> If we agree on 1 (I assume we do) then this becomes the real
> question, at which point your worries about the kernel assuming
> something which is not true because the probe code got it wrong
> may become true regardless where the code lives.
> 
> So wrt this worries is all I can do is ask you to trust me to
> not mess things up, just like we all trust driver authors, etc.
> all the time to not mess things up.
> 
>> As I mentioned at ELCE, I'm not opposed to the concept of the kernel
>> applying overlays or fixups based on a well-defined set of criteria;
>> having some of that embedded in the DT itself would be remarkably
>> helpful.  However, I am very much not keen on loosely defined criteria as
>> with here, as it couples the DT and kernel, and creates problems longer
>> term, as described above.
> 
> Right, so again I think we need to split the discussion in 2 steps:
> 
> 1) How do we apply the fixups, currently I'm using free-form changes
> done from C-code. I can envision moving to something like the quirk
> mechanism suggested by Pantelis in the past. Note this is not a perfect
> fit for my rather corner-case use-case, but I can understand that in
> general you want the variants to be described in dt, and activated
> in some way, rather then have c-code make free-form changes to the dt
> 

We’ve had this discussion before, so I guess here it goes again.

I think the biggest objection is the programmatic way of applying
every quirk by ‘hand’.

If there was a way to keep the probing mechanism but just spit out
a ‘model’ number we could reasonably map it to an overlay to apply
with a generic overlay manager.

From an internal s/w standpoint having an expansion board or soldered
parts makes no difference. 


> 2) How do we select which fixups to apply. Again I can understand
> you wanting some well defined mechanism for this, but again my
> use-case is special and simply does not allow for this as there
> is no id-eeprom to read or some such.
> 

Yes there is no EEPROM but you might be able to map probing results to
a fake ‘model’ number.

Let me expand a bit:

Assume that you have a number of probing steps, for example A, B, C each
returning true or false, and C being executed only when B is ‘true’ you
could do this to generate a bit field that identifies it.

For example let’s assume that model FOO’s probing steps are

A false, B true, C false -> 010

Model’s BAR

A true, B false, C don’t care -> 10x

Mapping these to models could be

Model FOO, (010 & 111) == 010 (all three probing steps must match)

Model BAR, (10x & 110) = 100 (the first two probing steps must match)

>>> Although having to specify kernel cmdline options is not the plug and play
>>> experience I want to give end-users most distros do have documentation on
>>> how to do this and doing this is relatively easy for end-users. Moving this
>>> to the bootloader means moving to some bootloader specific config mechanism
>>> which is going to be quite hard (and possibly dangerous) for users to use.
>> 
>> I have to ask, why is it more dangerous?
> 
> Because for normal end users meddling with the bootloader / with u-boot's
> environment is like flashing a PC BIOS. Most (non technical) end users will
> want to install u-boot once (or not at all) and then just have it work.
> 

Users do *not* want to deal with the bootloader. They don’t even want to
know that it’s there. As far they're concerned if you need to drop in
the bootloader to do something -> broken.
 
>> Perhaps more difficult, but that can be solved,
> 
> More difficult means not doable for many users.
> 

+1

>> if the manual
>> corrections are simply a set of options to be passed to the kernel, I
>> don't see why the bootloader cannot pick this up.
>> 
>>> 2. Upgradability
>>> 
>>> Most users treat the bootloader like they treat an x86 machine BIOS/EFI,
>>> they will never upgrade it unless they really have to. This means that it
>>> will be very difficult to get users to actual benefit from bug-fixes /
>>> improvements done to the probing code. Where as the kernel on boards running
>>> e.g. Debian or Fedora gets regular updates together with the rest of the
>>> system.
>> 
>> Given that DTBs are supposed to remain supported, users should find
>> themselves with a system that continues to work, but may not have all
>> the bells and whistles it could, much like elsewhere.
>> 
>> While it's true that we have issues in this area, I don't think that's
>> an argument for putting things into the kernel for this specific set of
>> boards.
> 
> It is an argument to put much of the dynamic (dt) hardware support in
> the kernel in general.
> 
>>> 3. Infrastructure
>>> 
>>> The kernel simply has better infrastructure for doing these kind of things.
>> 
>> At least on the DT front, a lot of work has gone into improving the
>> infrastructure, e.g. the work that Free Electrons have done [1]. I
>> appreciate that the infrastructure for things like poking SPI may not be
>> as advanced.
>> 
>> Which bits of infrastructure do you find lacking today?
> 
> Nothing really specific (I've not yet tried porting the probe code
> to u-boot), but I just find working within the kernel easier in general,
> since there really just is a lot more infrastructure. Note I'm the
> upstream u-boot maintainer for the allwinner SoC support, so this
> is not due to me being unfamiliar with u-boot.
> 
>>> Yes we could improve the bootloader, but the kernel is also improving
>>> and likely at a faster rate. Besides that the purpose of the
>>> bootloader is mostly to be simple and small, load the kernel and get
>>> out of the way, not to be a general purpose os kernel. So it will
>>> simply always have less infrastructure and that is a good thing,
>>> otherwise we will be writing another general purpose os which is a
>>> waste of effort.
>> 
>> I think this conflates a number of details. Yes, we'd like firmware and
>> bootloaders to be small, and yes, their infrastructure and feature
>> support will be smaller than a general purpose OS.
>> 
>> That doesn't imply that they cannot have features necessary to boostrap
>> an OS.
>> 
>> It's also not strictly necessary that the firmware or bootloader have
>> the capability to do all this probing, as that could be contained in
>> another part (e.g. a U-Boot application which is run once to detect the
>> board details, logging this into a file).
>> 
>> It's also possible to ship an intermediary stage (e.g. like the
>> impedance matcher) which can be upgradeable independently of the kernel.
> 
> Yes there are other solutions, but they all involve a lot more
> moving pieces (and thus will break) then a single isolated .c file
> in the kernel, which is all this series adds.
> 
> Esp the intermediate solution just adds a ton of complexity with 0
> gain.

Simple is the way to go. Putting things in the kernel is the simplest
solution for the users, for the distro maintainers and the board support
people.
> 
>>> 4. This is not a new board file
>>> 
>>> Mark, at ELCE I got the feeling that your biggest worry / objection is
>>> that this will bring back board files, but that is not the case, if you
>>> look at the actual code it is nothing like a board-file at all. Where a
>>> board file was instantiating device after device after device from c-code,
>>> with maybe a few if-s in there to deal with board revisions. This code is
>>> all about figuring out which accelerometer and touchscreen there are,
>>> to then add nodes to the dt for this 2 devices, almost all the code is
>>> probing, the actual dt modifying code is tiny and no direct device
>>> instantiation is done at all.
>> 
>> Sorry, but I must disagree. This code:
>> 
>> (a) identifies a set of boards based on a top-level compatible string.
>>    i.e. it's sole purpose is to handle those boards.
>> 
>> (b) assumes non-general properties of those boards (e.g. that poking
>>    certain SPI endpoints is safe).
>> 
>> (c) applies arbitrary properties to the DT, applying in-built knowledge
>>    of those boards (in addition to deep structural knowledge of the
>>    DTB in question).
>> 
>> To me, given the implicit knowledge, that qualifies as a "board file".
>> 
>> As I mentioned at ELCE, if this had no knowledge of the boards in
>> question, I would be less concerned. e.g. if there was a well-defined
>> identification mechanism, describe in the DT, with fixups also defined
>> in the DT.
> 
> And as I tried to explain before, for this specific use-case describing
> all this board specific knowledge in a generic manner in dt is simply
> impossible, unless we add a turing complete language to dt aka aml.
> 
> I've a feeling that you're mixing this, rather special, use-case with
> the more generic use-case of daughter-boards for various small-board-computers
> I agree that for the SBC use-case it makes sense to try and come up with
> a shared core / dt bindings for much of this. Note that even this boards
> will still need a board (or board-family) specific method for getting
> the actual id from a daughter-board, but this board specific code could
> then pass the id to some more general hw-manager core which starts applying
> dt changes based on the id. But this assumes there is a single id to
> uniquely identify the extensions, which in my case there simply is not.
> 

^ read above.

>>> 5. This is an exception, not the rule
>>> 
>>> Yes this is introducing board (family of boards) specific c-code into the
>>> kernel, so in a way it is reminiscent of board files. But sometimes this is
>>> necessary, just look at all the vendor / platform specific code in the kernel
>>> in drivers/platform/x86, or all the places where DMI strings are used to
>>> uniquely identify a x86 board and adjust behavior.
>>> 
>>> But this really is the exception, not the rule. I've written/upstreamed a
>>> number of drivers for q8 tablets hardware and if you look at e.g. the
>>> silead touchscreen driver then in linux-next this is already used for 5
>>> ARM dts files where no board specific C-code is involved at all.
>>> 
>>> So this again is very different from the board file era, where C-code
>>> had to be used to fill device specific platform-data structs, here all
>>> necessary info is contained in the dt-binding and there are many users
>>> who do not need any board specific C-code in the kernel at all.
>>> 
>>> So dt is working as it should and is avoiding board specific C-code for
>>> the majority of the cases. But sometimes hardware is not as we ideally
>>> would like it to be; and for those *exceptions* we are sometimes going
>>> to need C-code in the kernel, just like there is "board" specific C-code
>>> in the x86 code.
>> 
>> Your talk convinced me that we're both going to see more variation
>> within this family of boards, and that we'll see more families of boards
>> following a similar patter. Given that, I think that we need a more
>> general solution, as I commented on the RFC.
>> 
>> That doesn't necessarily mean that this can't happen in the kernel, but
>> it certainly needs to be more strictly defined, e.g. with match criteria
>> and fixups explicit in the DTB.
> 
> The only answer I've to: "with match criteria and fixups explicit in the DTB"
> is: ok, give my a turing complete language inside DTB then, anything else
> will not suffice. So either we are doomed to reinvent ACPI; or we must
> accept some board(family) specific C-code in the kernel.
> 

Please don’t let DT stagnate. We don’t have to repeat mistakes and we don’t
have to remain true to the spirit of what DT was supposed to be more than
a decade ago.

The problems we deal now are different, the industry is different and the
users are different.

We have to evolve along with them.

> Regards,
> 
> Hans

Regards

— Pantelis--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-27 15:52           ` Pantelis Antoniou
  0 siblings, 0 replies; 48+ messages in thread
From: Pantelis Antoniou @ 2016-10-27 15:52 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Hans,

> On Oct 26, 2016, at 14:46 , Hans de Goede <hdegoede@redhat.com> wrote:
> 
> Hi,
> 
> On 24-10-16 19:39, Mark Rutland wrote:
>> On Fri, Oct 14, 2016 at 09:53:31AM +0200, Hans de Goede wrote:
>>> Hi Rob, Mark, et al.,
>> 
>> Hi Hans,
>> 
>> Apologies for the delay in replying to this.
> 
> No worries, I believe that 1 week is actually a pretty good
> turn around time, esp. directly after a conference.
> 

Conferences are a deadline killer. Just got around taking a look.

>> I'd like to be clear that I do understand that there is a problem that
>> needs to be addressed here. However, I do not believe that the *current*
>> in-kernel approach is correct. More on that below.
> 
> Ok.
> 
>>> Mark, I know that we discussed this at ELCE and you clearly indicated
>>> that according to you this does not belong in the kernel. I was a bit
>>> surprised by this part of the discussion.
>>> 
>>> I had posted a RFC earlier and Rob had indicated that given that the q8
>>> tablets are a special case, as my code uses actual probing rather then some
>>> pre-arranged id mechanism with say an eeprom, that doing this in a
>>> non-generic manner would be ok for my special case.
>> 
>> To some extent, Rob and I may have differing views here; I'm not
>> entirely sure what Rob's view is, and I cannot talk on his behalf. I
>> certainly must apologise for having not commented on said RFC, however.
>> 
>>> So on to why I believe that the kernel is the best place to do this, at least
>>> for my special use-case:
>>> 
>>> 1. Configurability
>>> 
>>> Since the q8 tablets do not have any id mechanism I'm probing i2c busses to
>>> generate i2c client dt nodes with the right address and compatible.
>>> Some info in these nodes (e.g. touchscreen firmware-name) is not probable at
>>> all and gets set by heuristics. This heuristics may get things wrong.
>>> So my current implementation offers kernel cmdline options to override this.
>> 
>> As I mentioned at ELCE, one major concern I have with this approach is
>> this probing, which in part relies on a collection of heuristics.
> 
> This is quite use-case specific, anyways, the probing is a 2 step process:
> 
> 1) Identify which hardware there is in the tablet, this is pretty
> reliable, we only detect a fix set of known possible touchscreens
> and accelerometers, at known addresses and almost all have an id
> register to check.
> 
> 2) Determine *defaults* for various none probable settings, like guessing
> which firmware to load into the touchscreen controllers, as there are
> at least 2 ways the gsl1680 is wired up on these tablets and this
> requires 2 different firmware files. This uses heuristics, to, as said,
> determine the defaults all of the non-probable bits are overidable
> through config options (currently kernel module options). Getting these
> wrong is not dangerous to the hardware, but will work in a non-functional
> or misbehaving (wrong coordinates) touchscreen.
> 
> Note with the models I've access to so far the heuristics score 100%
> but I'm not sure how representative the 16 models I've access to are
> (they are all different and have been bought over a span of multiple
> years).

> 
>> I'm worried that this is very fragile, and sets us up for having to
>> maintain a much larger collection of heuristics and/or a database of
>> particular boards in future. This is fragile, defeats much of the gain
>> from DT.
> 
> I understand your worries, as said I'm confident the actual probing
> is safe and getting the heuristics wrong will result in misbehavior,
> but not in any hardware damage or such.
> 
>> Worse, this could be completely incompatible with some arbitrary board
>> that comes by in future,
> 
> I assume you mean an arbitrary q8 tablet here, as the probe code does
> bind by board/machine compatible, so for a really arbitrary board
> this code will never activate.
> 
>> because the kernel assumed something that was
>> not true, which it would not have done if things were explicitly
>> described to the kernel.
> 
> I understand your worry, but moving the probing code to say u-boot
> will not change any of this, the kernel will get the explicit
> description created by the u-boot probe code, but it would be
> just as wrong.
> 
> So maybe we need to answer 2 questions in a row:
> 
> 1) Do we want such probe code at all ?
> 
> My answer to this is yes, these (cheap) tablets are interesting to
> e.g. the maker community and I would like them to run mainline
> (and run mainline well), but given the way there are put together
> this require some code to dynamically adapt to the batch of the
> month somewhere
> 
> 2) Where do we put this code ?
> 
> If we agree on 1 (I assume we do) then this becomes the real
> question, at which point your worries about the kernel assuming
> something which is not true because the probe code got it wrong
> may become true regardless where the code lives.
> 
> So wrt this worries is all I can do is ask you to trust me to
> not mess things up, just like we all trust driver authors, etc.
> all the time to not mess things up.
> 
>> As I mentioned at ELCE, I'm not opposed to the concept of the kernel
>> applying overlays or fixups based on a well-defined set of criteria;
>> having some of that embedded in the DT itself would be remarkably
>> helpful.  However, I am very much not keen on loosely defined criteria as
>> with here, as it couples the DT and kernel, and creates problems longer
>> term, as described above.
> 
> Right, so again I think we need to split the discussion in 2 steps:
> 
> 1) How do we apply the fixups, currently I'm using free-form changes
> done from C-code. I can envision moving to something like the quirk
> mechanism suggested by Pantelis in the past. Note this is not a perfect
> fit for my rather corner-case use-case, but I can understand that in
> general you want the variants to be described in dt, and activated
> in some way, rather then have c-code make free-form changes to the dt
> 

We?ve had this discussion before, so I guess here it goes again.

I think the biggest objection is the programmatic way of applying
every quirk by ?hand?.

If there was a way to keep the probing mechanism but just spit out
a ?model? number we could reasonably map it to an overlay to apply
with a generic overlay manager.

>From an internal s/w standpoint having an expansion board or soldered
parts makes no difference. 


> 2) How do we select which fixups to apply. Again I can understand
> you wanting some well defined mechanism for this, but again my
> use-case is special and simply does not allow for this as there
> is no id-eeprom to read or some such.
> 

Yes there is no EEPROM but you might be able to map probing results to
a fake ?model? number.

Let me expand a bit:

Assume that you have a number of probing steps, for example A, B, C each
returning true or false, and C being executed only when B is ?true? you
could do this to generate a bit field that identifies it.

For example let?s assume that model FOO?s probing steps are

A false, B true, C false -> 010

Model?s BAR

A true, B false, C don?t care -> 10x

Mapping these to models could be

Model FOO, (010 & 111) == 010 (all three probing steps must match)

Model BAR, (10x & 110) = 100 (the first two probing steps must match)

>>> Although having to specify kernel cmdline options is not the plug and play
>>> experience I want to give end-users most distros do have documentation on
>>> how to do this and doing this is relatively easy for end-users. Moving this
>>> to the bootloader means moving to some bootloader specific config mechanism
>>> which is going to be quite hard (and possibly dangerous) for users to use.
>> 
>> I have to ask, why is it more dangerous?
> 
> Because for normal end users meddling with the bootloader / with u-boot's
> environment is like flashing a PC BIOS. Most (non technical) end users will
> want to install u-boot once (or not at all) and then just have it work.
> 

Users do *not* want to deal with the bootloader. They don?t even want to
know that it?s there. As far they're concerned if you need to drop in
the bootloader to do something -> broken.
 
>> Perhaps more difficult, but that can be solved,
> 
> More difficult means not doable for many users.
> 

+1

>> if the manual
>> corrections are simply a set of options to be passed to the kernel, I
>> don't see why the bootloader cannot pick this up.
>> 
>>> 2. Upgradability
>>> 
>>> Most users treat the bootloader like they treat an x86 machine BIOS/EFI,
>>> they will never upgrade it unless they really have to. This means that it
>>> will be very difficult to get users to actual benefit from bug-fixes /
>>> improvements done to the probing code. Where as the kernel on boards running
>>> e.g. Debian or Fedora gets regular updates together with the rest of the
>>> system.
>> 
>> Given that DTBs are supposed to remain supported, users should find
>> themselves with a system that continues to work, but may not have all
>> the bells and whistles it could, much like elsewhere.
>> 
>> While it's true that we have issues in this area, I don't think that's
>> an argument for putting things into the kernel for this specific set of
>> boards.
> 
> It is an argument to put much of the dynamic (dt) hardware support in
> the kernel in general.
> 
>>> 3. Infrastructure
>>> 
>>> The kernel simply has better infrastructure for doing these kind of things.
>> 
>> At least on the DT front, a lot of work has gone into improving the
>> infrastructure, e.g. the work that Free Electrons have done [1]. I
>> appreciate that the infrastructure for things like poking SPI may not be
>> as advanced.
>> 
>> Which bits of infrastructure do you find lacking today?
> 
> Nothing really specific (I've not yet tried porting the probe code
> to u-boot), but I just find working within the kernel easier in general,
> since there really just is a lot more infrastructure. Note I'm the
> upstream u-boot maintainer for the allwinner SoC support, so this
> is not due to me being unfamiliar with u-boot.
> 
>>> Yes we could improve the bootloader, but the kernel is also improving
>>> and likely at a faster rate. Besides that the purpose of the
>>> bootloader is mostly to be simple and small, load the kernel and get
>>> out of the way, not to be a general purpose os kernel. So it will
>>> simply always have less infrastructure and that is a good thing,
>>> otherwise we will be writing another general purpose os which is a
>>> waste of effort.
>> 
>> I think this conflates a number of details. Yes, we'd like firmware and
>> bootloaders to be small, and yes, their infrastructure and feature
>> support will be smaller than a general purpose OS.
>> 
>> That doesn't imply that they cannot have features necessary to boostrap
>> an OS.
>> 
>> It's also not strictly necessary that the firmware or bootloader have
>> the capability to do all this probing, as that could be contained in
>> another part (e.g. a U-Boot application which is run once to detect the
>> board details, logging this into a file).
>> 
>> It's also possible to ship an intermediary stage (e.g. like the
>> impedance matcher) which can be upgradeable independently of the kernel.
> 
> Yes there are other solutions, but they all involve a lot more
> moving pieces (and thus will break) then a single isolated .c file
> in the kernel, which is all this series adds.
> 
> Esp the intermediate solution just adds a ton of complexity with 0
> gain.

Simple is the way to go. Putting things in the kernel is the simplest
solution for the users, for the distro maintainers and the board support
people.
> 
>>> 4. This is not a new board file
>>> 
>>> Mark, at ELCE I got the feeling that your biggest worry / objection is
>>> that this will bring back board files, but that is not the case, if you
>>> look at the actual code it is nothing like a board-file at all. Where a
>>> board file was instantiating device after device after device from c-code,
>>> with maybe a few if-s in there to deal with board revisions. This code is
>>> all about figuring out which accelerometer and touchscreen there are,
>>> to then add nodes to the dt for this 2 devices, almost all the code is
>>> probing, the actual dt modifying code is tiny and no direct device
>>> instantiation is done at all.
>> 
>> Sorry, but I must disagree. This code:
>> 
>> (a) identifies a set of boards based on a top-level compatible string.
>>    i.e. it's sole purpose is to handle those boards.
>> 
>> (b) assumes non-general properties of those boards (e.g. that poking
>>    certain SPI endpoints is safe).
>> 
>> (c) applies arbitrary properties to the DT, applying in-built knowledge
>>    of those boards (in addition to deep structural knowledge of the
>>    DTB in question).
>> 
>> To me, given the implicit knowledge, that qualifies as a "board file".
>> 
>> As I mentioned at ELCE, if this had no knowledge of the boards in
>> question, I would be less concerned. e.g. if there was a well-defined
>> identification mechanism, describe in the DT, with fixups also defined
>> in the DT.
> 
> And as I tried to explain before, for this specific use-case describing
> all this board specific knowledge in a generic manner in dt is simply
> impossible, unless we add a turing complete language to dt aka aml.
> 
> I've a feeling that you're mixing this, rather special, use-case with
> the more generic use-case of daughter-boards for various small-board-computers
> I agree that for the SBC use-case it makes sense to try and come up with
> a shared core / dt bindings for much of this. Note that even this boards
> will still need a board (or board-family) specific method for getting
> the actual id from a daughter-board, but this board specific code could
> then pass the id to some more general hw-manager core which starts applying
> dt changes based on the id. But this assumes there is a single id to
> uniquely identify the extensions, which in my case there simply is not.
> 

^ read above.

>>> 5. This is an exception, not the rule
>>> 
>>> Yes this is introducing board (family of boards) specific c-code into the
>>> kernel, so in a way it is reminiscent of board files. But sometimes this is
>>> necessary, just look at all the vendor / platform specific code in the kernel
>>> in drivers/platform/x86, or all the places where DMI strings are used to
>>> uniquely identify a x86 board and adjust behavior.
>>> 
>>> But this really is the exception, not the rule. I've written/upstreamed a
>>> number of drivers for q8 tablets hardware and if you look at e.g. the
>>> silead touchscreen driver then in linux-next this is already used for 5
>>> ARM dts files where no board specific C-code is involved at all.
>>> 
>>> So this again is very different from the board file era, where C-code
>>> had to be used to fill device specific platform-data structs, here all
>>> necessary info is contained in the dt-binding and there are many users
>>> who do not need any board specific C-code in the kernel at all.
>>> 
>>> So dt is working as it should and is avoiding board specific C-code for
>>> the majority of the cases. But sometimes hardware is not as we ideally
>>> would like it to be; and for those *exceptions* we are sometimes going
>>> to need C-code in the kernel, just like there is "board" specific C-code
>>> in the x86 code.
>> 
>> Your talk convinced me that we're both going to see more variation
>> within this family of boards, and that we'll see more families of boards
>> following a similar patter. Given that, I think that we need a more
>> general solution, as I commented on the RFC.
>> 
>> That doesn't necessarily mean that this can't happen in the kernel, but
>> it certainly needs to be more strictly defined, e.g. with match criteria
>> and fixups explicit in the DTB.
> 
> The only answer I've to: "with match criteria and fixups explicit in the DTB"
> is: ok, give my a turing complete language inside DTB then, anything else
> will not suffice. So either we are doomed to reinvent ACPI; or we must
> accept some board(family) specific C-code in the kernel.
> 

Please don?t let DT stagnate. We don?t have to repeat mistakes and we don?t
have to remain true to the spirit of what DT was supposed to be more than
a decade ago.

The problems we deal now are different, the industry is different and the
users are different.

We have to evolve along with them.

> Regards,
> 
> Hans

Regards

? Pantelis

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

* Re: Add Allwinner Q8 tablets hardware manager
  2016-10-27 14:53                 ` Hans de Goede
@ 2016-10-27 16:27                     ` Pantelis Antoniou
  -1 siblings, 0 replies; 48+ messages in thread
From: Pantelis Antoniou @ 2016-10-27 16:27 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Pierre-Hugues Husson, Mark Rutland, devicetree, Arnd Bergmann,
	Greg Kroah-Hartman, Chen-Yu Tsai, Rob Herring, Maxime Ripard,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi Hans,

Nice to see other people coming up with similar problems.
It’s not a new thing at all, hacks like this have been around
since for ever (but safely tucked away in product specific areas).

> On Oct 27, 2016, at 17:53 , Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> 
> Hi,
> 
> On 27-10-16 14:57, Pierre-Hugues Husson wrote:
>> 2016-10-27 11:14 GMT+02:00 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
>>> In my experience with these cheap boards, there is a mix of auto-probing +
>>> device / revision specific os-image modifications. I keep coming back to
>>> the touchscreen controller firmware (but also the orientation), for the
>>> gsl1680 controller I need at least 2 different firmware files (per gsl1680
>>> revision) to make all q8 tablets I have working. This is simply not solved
>>> by the vendor android code, they just shove the right firmware into the
>>> os-image. Likewise for the touchscreen orientation (x-mirored, y-mirored,
>>> etc) too is just a hard-coded setting in the os-image.
>> Reading your patch, it looks like to handle the two different firmware
>> files, you're simply adding a command-line switch, there is no
>> detection involved.
>> Am I understanding correctly?
> 
> No, the firmware-name (and matching resolution as different firmwares
> report different axis-ranges for the same digitizer) is selected
> primarily by the touchscreen_variant which sets: touchscreen_fw_name,
> touchscreen_width and touchscreen_height.
> 
> The touchscreen_variant module option defaults to -1 which means "auto",
> when it is auto it gets set based on the touchscreen / accelerometer
> combination (which more or less uniquely identifies boards sofar),
> likewise all the other touchscreen module options default to -1,
> but can be overridden from the commandline.
> 
> The intention is for things to just work, the commandline options are
> there as a fallback.
> 
>> If this is the case, two things:
>> 1. I'm not too sure having the user choose this via cmdline is the
>> right way. I think I'd rather have it set by userspace. (though that's
>> not a strong opinion).
>> Or if cmdline is being changed... how about having DTS (or just an
>> overlay on top of it) being changed instead?
>> 
>> 2. This could still be declared by DTS. For instance, assuming your
>> i2c-probe-stop-at-first-match:
>> &i2c0 {
>>        touchscreen1: gsl1680@40 {
>>                reg = <0x40>;
>>                compatible = "silead,gsl1680";
>>                enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
>>                touchscreen-size = <1024 600>;
>>                touchscreen-fw = "gsl1680-a082-q8-700.fw";
>>                filter-names = "touchscreen_variant";
>>                filter-0 = "none", "gsl1680-a082-q8-700";
>>                id = <0xa0820000>;
>>                status = "disabled";
>>        };
>>        touchscreen2: gsl1680@40 {
>>                reg = <0x40>;
>>                compatible = "silead,gsl1680";
>>                enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
>>                touchscreen-size = <480 800>;
>>                touchscreen-fw = "gsl1680-a082-q8-a70.fw";
>>                filter-names = "touchscreen_variant";
>>                filter-0 = "gsl1680-a082-q8-a70";
>>                id = <0xa0820000>;
>>               status = "disabled";
>>        };
>>        touchscreen2: gsl1680@40 {
>>                reg = <0x40>;
>>                compatible = "silead,gsl1680";
>>                enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
>>                touchscreen-size = <960 640>;
>>                touchscreen-fw = "gsl1680-b482-q8-d702.fw";
>>                filter-names = "touchscreen_variant";
>>                filter-0 = "gsl1680-b482-q8-d702";
>>                id = <0xb4820000>;
>>               status = "disabled";
>>        };
>>        i2c-probe-stop-at-first-match = <&touchscreen1>,
>> <&touchscreen2>, <&touchscreen3>;
>> }
>> 
>> With "none" value being the value when the "touchscreen_variant"
>> option is not defined in cmdline.
>> 
>> Please note that I'm not too sure whether SILEAD_REG_ID represents an
>> OTP which can be changed by OEM, or if it's more of a hardware
>> revision. Depending on this, this would either fit into a id =
>> <0xa0820000> DTS line, or a compatible = "silead,gsl1680_a082",
>> "silead,gsl1680"; DTS line.
>> 
>>> Sofar I've only seen this with one type of touchscreen so an easy cop-out
>>> would be to add an "optional-vddio-supply" to the the bindings for the
>>> specific touchscreen use and put all the necessary logic in the driver.
>>> 
>>> This does require propagating the learned need for the regulator
>>> from the drivers detect() callback to probe() or alternatively I'm
>>> thinking we should just use probe() instead of detect()to begin with,
>>> that will save a lot of duplication with things
>>> like code for enable gpio-s and regulators.
>>> 
>>> So assuming we go for the cop-out option for 3. (I'm ok with that),
>>> this would be a pretty clean solution adding just the 2 new:
>>> i2c-probe-stop-at-first-match and i2c-probe-all properties to
>>> the i2c-bus bindings. One problem here is that we may want to have
>>> multiple i2c-probe-stop-at-first-match phandle lists on a single bus
>>> (e.g. try 3 touchscreens + 6 accelerometers on the same bus, stop at
>>> first touchscreen / first accelerometer), anyone have any ideas for
>>> that?
>> How about something like:
>> 
>> &i2c1 {
>>    touchscreen1....
>>    touchscreen2....
>>    touchscreen3....
>>    accelerometer1....
>>    accelerometer2....
>>    accelerometer3....
>>    accelerometer4....
>> 
>>    select-one {
>>       compatible = "i2c-select;
>>       group-names = "touchscreen", "accelerometer";
>>       group-0 = <&touchscreen1>, <&touchscreen2>, <&touchscreen3>;
>>       group-1 = <&accelerometer1>, <&accelerometer2>,
>> <&accelerometer3>, <&accelerometer4>;
>>    };
>> };
> 
> We could just have:
> 
> 	i2c-probe-stop-at-first-match-0 = <&touchscreen1>, <&touchscreen2>, <&touchscreen3>;
> 	i2c-probe-stop-at-first-match-1 = <&accelerometer1>, <&accelerometer2>;
> 
> And have the i2c bus code look for an i2c-probe-stop-at-first-match-[i++] property
> until it is not found. Having a child-node with its own compatible for this
> feels wrong, as it uses a hierarchy where there really is none.
> 

>>>> When it comes to detection, I've witnessed various things.
>>>> It can be kernel-side or bootloader-side "global setting" reading (like an
>>>> ADC/resistor value, or an OTP), it can be bootloader doing the
>>>> "brute-force", or it can be the kernel doing all the probes.
>>>> 
>>>> For instance, as of today, on a Spreadtrum ODM tree, the bootloader will
>>>> detect the screen by testing all knowns screens, the screen-drivers declare
>>>> a get_id function, and the bootloader probes until the get_id matches the id
>>>> declared by the screen driver.
>>>> And then the bootloader tells the kernel, via cmdline, which screen is
>>>> actually there (but auto-detection is also coded in kernel).
>>>> Finally all possible sensors/touchscreen/camera are declared in DTS, and
>>>> probe will filter-out N/C ones in the kernel.
>>>> 
>>>> Now the big difference between my experience and what Hans is trying to
>>>> do, is that I've always worked with devices with "safely" queriable IDs,
>>>> either on i2c or dsi. I've never encountered SPI. This makes probing
>>>> inherently more dangerous, but I believe the question roughly remains the
>>>> same.
>>> 
>>> 
>>> I'm dealing with i2c too, Mark mistakenly used SPI in his reply,
>>> which I think is what got you thinking I've SPI.
>> Right, so let's concentrate on reasonable bus-es first then. (I can
>> think of I2C and DSI)
>> 
>>> See above, I think that we can make this work by delegating the actual
>>> detection to the driver (so each compatible can have a different detect
>>> method / code).
>>> So with this we can remove a big part of drivers/misc/q8-hardwaremgr.c, but
>>> not all
>>> of it. We still need board specific code somewhere to deal with things like
>>> picking
>>> the right touchscreen firmware and touchscreen orientation. This is all
>>> somewhat
>>> gsl1680 specific.
>>> I actually have the same problem on x86 where the ACPI description of the
>>> device
>>> basically says: "There is a gsl1680 at this bus at this address" and does
>>> not say
>>> anything about firmware / orientation (again this is simply hardcoded
>>> in the os-image these devices ship with).
>>> 
>>> For x86 my plan is to have an array of configs in the driver and select the
>>> right
>>> one based on DMI strings, which is in essence putting board specific info in
>>> the
>>> driver.
>>> 
>>> I can imagine mirroring this for ARM, and have an array of configs in the
>>> driver
>>> there too (for cases where cannot simply hardcode everything in dt only) and
>>> have
>>> some board specific code (activated by of_machine_is_compatible()) to select
>>> the
>>> right config.
>> I do believe this can all be done in DTS
> 
> Well x86 does not have DTS.
> 

Says who? :)

x86 _can_ have DT and there’s no problem using it at all.
For custom boards no one wants to go through the insane ACPI limitations.

FWIW all the x86 mobile parts used it (but are now RIP).

>> and at the moment, what
>> you're describing seem to happen often enough to be worth writing
>> generic code for.
> 
> Let me quote some of the auto-code currently in q8-hardwaremgr.c :
> 
>                /*
>                 * These accelerometer based heuristics select the best
>                 * default based on known q8 tablets.
>                 */
>                switch (data->accelerometer.model) {
>                case da280:
>                        if (data->accelerometer.addr == 0x27)
>                                ; /* No-op */
>                        else if (data->has_rda599x)
>                                data->touchscreen_invert_x = 1;
>                        else
>                                data->touchscreen_invert_y = 1;
>                        break;
>                case dmard09:
>                        data->touchscreen_invert_x = 1;
>                        break;
>                case mxc6225:
>                        data->touchscreen_variant = 1;
>                        break;
>                }
> 
> (Non set data->touchscreen_foo are left at 0).
> 
> So this would require us to be able to filter (to use your example)
> on if another i2c device is found and on which address it is found,
> that does not even take the rda559x check into account and is
> going to cause interesting ordering issues, how do we know when
> we can actually do the filtering if some of the variables we are
> filtering on are set by other auto-detected paths. Which auto-detect /
> i2c-probe-stop-at-first-match list do we execute first ? Worse
> actually for accelerometer orientation I will likely need to
> set the mount-matrix based on the detected touchscreen ...
> 
> The rda559x here is a sdio wifi chip, which is also connected to the
> i2c, and currently is detected through i2c to be able to separately
> identify 2 q8 boards which share the same touchscreen + accelerometer
> combination and who knows what other checks I or other people can
> come up with to differentiate board variants which do not have
> a simple eeprom to uniquely id them.
> 
> So as said before, no this cannot be all done in dt without
> adding a turing complete language to dt, and that is just to
> select which touchscreen_variant to use.
> 
> Then there also the probem of the combinatorial explosion having
> not only 2 firmware files but also invert-x and invert-y flags causes:
> We have 2 revisions with each 2 different firmware-files (more actually
> but I've reduced the set since some firmwares are compatible) with each
> both the x- and / or y axis as normal or inverted, for a total of:
> 2 (revision) * 2 (firmware-files) * 2 (x-inverted or not) * 2 (y...) = 16
> touchscreen variants, which means dt nodes for touchscreen1 to touchscreen16
> and that is just the silead gsl1680, some of these tablets also have
> elan or zeitec touchscreen controllers.
> 

There is a combinatorial explosion, but only a finite number of _known_ 
board versions.

> Now imagine what happens if a new board comes out which needs a 3th firmware
> file... I hope you can understand this is not a route I want to go.
> 
> Another problem is that if a user encounters the need for a new firmware
> variant he can now not easily try this (where as before we had
> module options to separately override firmware-name, the size, etc.
> 
> As written in my previous mail, this is all rather gsl1680 specific,
> and esp. being able to override the firmware-name, the size, etc.
> through module options is going to be useful (to ask endusers to test
> stuff without recompiling) on x86 too. So we will likely want to add
> most of the necessary stuff to the silead driver anyways.
> 
>> But then, I can't really tell which makes the most sense between
>> source-based and devicetree-based.
>> I prefer doing it in device-tree, since it means that any OEM can have
>> his device supported by only providing DTB, and won't need to provide
>> kernel patches.
> 
> If the OEM provides a DTB the OEM can just directly have the right
> parameters in there without relying on any auto-detection, this is
> already supported and the e.g. gsl1680 driver already happily
> works on several tablets where there is not so much hardware
> variance.
> 
> Even if the OEM needs to deal with e.g. different touchscreens on
> different board revisions, hopefully the simple auto-detect code will
> be enough, and he does not need e.g. different firmware-name settings
> for otherwise the same touchscreen controller. If that is not the
> case then he the OEM will have to provide a separate static
> (non probing) DTB per variant.
> 
>>> 2) miscellaneous extra config on top of figuring out which ICs are
>>> connected,
>>> basically the kind of stuff many vendors simply hard-code in their device
>>> specific os-image. This one is much more difficult to deal with and I think
>>> we need to figure this out on a case by case basis. This will require board
>>> specific code (just like the kernel has tons of DMI string activated board
>>> specific code on x86) and what is the best code for this place to live will
>>> be a case by case thing too.
>> 
>> With things like mount-matrix devicetree property, the goal is to have
>> such informations in the DTS.
> 
> Right and all the info I'm talking about can already be in the DTS and
> is already specified this way for various existing boards, this is
> obviously how we want things to work, this is the normal case /
> the straight code path.
> 
> Now lets get back to your mount-matrix example, the problem here is 2 board
> variants where the same accelerometer is used, but on a newer revision
> of the board it is mounted with a different orientation and otherwise
> almost nothing is changed on the board, certainly not something as
> useful as an id eeprom.
> 
> Lets assume that we can however still somehow differ the 2 revisions,
> then try to imagine how many different ways there are to differ
> between 2 board revisions if there is no easy way to do so,
> some crazy examples:
> -The 2nd revision has an external loopback on unused audio out / in
> pins for testing purposes, we could play + record sound and do
> a (rough) waveform match to see if the loopback is present
> -On the 2nd revision a pin from a pin compatible part which
> allows putting it in fully compatible mode, or allow new features
> mode, is now hooked up to a gpio instead of hardwired to compatible
> mode, we could change the device to new features mode and try
> to read/modify/write some register bit on the chip which is only
> writable in this mode
> -Etc.
> 
> Now try to design a way to express this in dt and we're back to
> needing a turing complete language (with a library for accessing
> various busses) again.
> 

No, not turing complete. This is going to require a little bit more
digging up but I think we can handle this with the method I described.

> Regards,
> 
> Hans

Regards

— Pantelis

P.S. Damn too much content to read.--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-27 16:27                     ` Pantelis Antoniou
  0 siblings, 0 replies; 48+ messages in thread
From: Pantelis Antoniou @ 2016-10-27 16:27 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Hans,

Nice to see other people coming up with similar problems.
It?s not a new thing at all, hacks like this have been around
since for ever (but safely tucked away in product specific areas).

> On Oct 27, 2016, at 17:53 , Hans de Goede <hdegoede@redhat.com> wrote:
> 
> Hi,
> 
> On 27-10-16 14:57, Pierre-Hugues Husson wrote:
>> 2016-10-27 11:14 GMT+02:00 Hans de Goede <hdegoede@redhat.com>:
>>> In my experience with these cheap boards, there is a mix of auto-probing +
>>> device / revision specific os-image modifications. I keep coming back to
>>> the touchscreen controller firmware (but also the orientation), for the
>>> gsl1680 controller I need at least 2 different firmware files (per gsl1680
>>> revision) to make all q8 tablets I have working. This is simply not solved
>>> by the vendor android code, they just shove the right firmware into the
>>> os-image. Likewise for the touchscreen orientation (x-mirored, y-mirored,
>>> etc) too is just a hard-coded setting in the os-image.
>> Reading your patch, it looks like to handle the two different firmware
>> files, you're simply adding a command-line switch, there is no
>> detection involved.
>> Am I understanding correctly?
> 
> No, the firmware-name (and matching resolution as different firmwares
> report different axis-ranges for the same digitizer) is selected
> primarily by the touchscreen_variant which sets: touchscreen_fw_name,
> touchscreen_width and touchscreen_height.
> 
> The touchscreen_variant module option defaults to -1 which means "auto",
> when it is auto it gets set based on the touchscreen / accelerometer
> combination (which more or less uniquely identifies boards sofar),
> likewise all the other touchscreen module options default to -1,
> but can be overridden from the commandline.
> 
> The intention is for things to just work, the commandline options are
> there as a fallback.
> 
>> If this is the case, two things:
>> 1. I'm not too sure having the user choose this via cmdline is the
>> right way. I think I'd rather have it set by userspace. (though that's
>> not a strong opinion).
>> Or if cmdline is being changed... how about having DTS (or just an
>> overlay on top of it) being changed instead?
>> 
>> 2. This could still be declared by DTS. For instance, assuming your
>> i2c-probe-stop-at-first-match:
>> &i2c0 {
>>        touchscreen1: gsl1680 at 40 {
>>                reg = <0x40>;
>>                compatible = "silead,gsl1680";
>>                enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
>>                touchscreen-size = <1024 600>;
>>                touchscreen-fw = "gsl1680-a082-q8-700.fw";
>>                filter-names = "touchscreen_variant";
>>                filter-0 = "none", "gsl1680-a082-q8-700";
>>                id = <0xa0820000>;
>>                status = "disabled";
>>        };
>>        touchscreen2: gsl1680 at 40 {
>>                reg = <0x40>;
>>                compatible = "silead,gsl1680";
>>                enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
>>                touchscreen-size = <480 800>;
>>                touchscreen-fw = "gsl1680-a082-q8-a70.fw";
>>                filter-names = "touchscreen_variant";
>>                filter-0 = "gsl1680-a082-q8-a70";
>>                id = <0xa0820000>;
>>               status = "disabled";
>>        };
>>        touchscreen2: gsl1680 at 40 {
>>                reg = <0x40>;
>>                compatible = "silead,gsl1680";
>>                enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
>>                touchscreen-size = <960 640>;
>>                touchscreen-fw = "gsl1680-b482-q8-d702.fw";
>>                filter-names = "touchscreen_variant";
>>                filter-0 = "gsl1680-b482-q8-d702";
>>                id = <0xb4820000>;
>>               status = "disabled";
>>        };
>>        i2c-probe-stop-at-first-match = <&touchscreen1>,
>> <&touchscreen2>, <&touchscreen3>;
>> }
>> 
>> With "none" value being the value when the "touchscreen_variant"
>> option is not defined in cmdline.
>> 
>> Please note that I'm not too sure whether SILEAD_REG_ID represents an
>> OTP which can be changed by OEM, or if it's more of a hardware
>> revision. Depending on this, this would either fit into a id =
>> <0xa0820000> DTS line, or a compatible = "silead,gsl1680_a082",
>> "silead,gsl1680"; DTS line.
>> 
>>> Sofar I've only seen this with one type of touchscreen so an easy cop-out
>>> would be to add an "optional-vddio-supply" to the the bindings for the
>>> specific touchscreen use and put all the necessary logic in the driver.
>>> 
>>> This does require propagating the learned need for the regulator
>>> from the drivers detect() callback to probe() or alternatively I'm
>>> thinking we should just use probe() instead of detect()to begin with,
>>> that will save a lot of duplication with things
>>> like code for enable gpio-s and regulators.
>>> 
>>> So assuming we go for the cop-out option for 3. (I'm ok with that),
>>> this would be a pretty clean solution adding just the 2 new:
>>> i2c-probe-stop-at-first-match and i2c-probe-all properties to
>>> the i2c-bus bindings. One problem here is that we may want to have
>>> multiple i2c-probe-stop-at-first-match phandle lists on a single bus
>>> (e.g. try 3 touchscreens + 6 accelerometers on the same bus, stop at
>>> first touchscreen / first accelerometer), anyone have any ideas for
>>> that?
>> How about something like:
>> 
>> &i2c1 {
>>    touchscreen1....
>>    touchscreen2....
>>    touchscreen3....
>>    accelerometer1....
>>    accelerometer2....
>>    accelerometer3....
>>    accelerometer4....
>> 
>>    select-one {
>>       compatible = "i2c-select;
>>       group-names = "touchscreen", "accelerometer";
>>       group-0 = <&touchscreen1>, <&touchscreen2>, <&touchscreen3>;
>>       group-1 = <&accelerometer1>, <&accelerometer2>,
>> <&accelerometer3>, <&accelerometer4>;
>>    };
>> };
> 
> We could just have:
> 
> 	i2c-probe-stop-at-first-match-0 = <&touchscreen1>, <&touchscreen2>, <&touchscreen3>;
> 	i2c-probe-stop-at-first-match-1 = <&accelerometer1>, <&accelerometer2>;
> 
> And have the i2c bus code look for an i2c-probe-stop-at-first-match-[i++] property
> until it is not found. Having a child-node with its own compatible for this
> feels wrong, as it uses a hierarchy where there really is none.
> 

>>>> When it comes to detection, I've witnessed various things.
>>>> It can be kernel-side or bootloader-side "global setting" reading (like an
>>>> ADC/resistor value, or an OTP), it can be bootloader doing the
>>>> "brute-force", or it can be the kernel doing all the probes.
>>>> 
>>>> For instance, as of today, on a Spreadtrum ODM tree, the bootloader will
>>>> detect the screen by testing all knowns screens, the screen-drivers declare
>>>> a get_id function, and the bootloader probes until the get_id matches the id
>>>> declared by the screen driver.
>>>> And then the bootloader tells the kernel, via cmdline, which screen is
>>>> actually there (but auto-detection is also coded in kernel).
>>>> Finally all possible sensors/touchscreen/camera are declared in DTS, and
>>>> probe will filter-out N/C ones in the kernel.
>>>> 
>>>> Now the big difference between my experience and what Hans is trying to
>>>> do, is that I've always worked with devices with "safely" queriable IDs,
>>>> either on i2c or dsi. I've never encountered SPI. This makes probing
>>>> inherently more dangerous, but I believe the question roughly remains the
>>>> same.
>>> 
>>> 
>>> I'm dealing with i2c too, Mark mistakenly used SPI in his reply,
>>> which I think is what got you thinking I've SPI.
>> Right, so let's concentrate on reasonable bus-es first then. (I can
>> think of I2C and DSI)
>> 
>>> See above, I think that we can make this work by delegating the actual
>>> detection to the driver (so each compatible can have a different detect
>>> method / code).
>>> So with this we can remove a big part of drivers/misc/q8-hardwaremgr.c, but
>>> not all
>>> of it. We still need board specific code somewhere to deal with things like
>>> picking
>>> the right touchscreen firmware and touchscreen orientation. This is all
>>> somewhat
>>> gsl1680 specific.
>>> I actually have the same problem on x86 where the ACPI description of the
>>> device
>>> basically says: "There is a gsl1680 at this bus at this address" and does
>>> not say
>>> anything about firmware / orientation (again this is simply hardcoded
>>> in the os-image these devices ship with).
>>> 
>>> For x86 my plan is to have an array of configs in the driver and select the
>>> right
>>> one based on DMI strings, which is in essence putting board specific info in
>>> the
>>> driver.
>>> 
>>> I can imagine mirroring this for ARM, and have an array of configs in the
>>> driver
>>> there too (for cases where cannot simply hardcode everything in dt only) and
>>> have
>>> some board specific code (activated by of_machine_is_compatible()) to select
>>> the
>>> right config.
>> I do believe this can all be done in DTS
> 
> Well x86 does not have DTS.
> 

Says who? :)

x86 _can_ have DT and there?s no problem using it at all.
For custom boards no one wants to go through the insane ACPI limitations.

FWIW all the x86 mobile parts used it (but are now RIP).

>> and at the moment, what
>> you're describing seem to happen often enough to be worth writing
>> generic code for.
> 
> Let me quote some of the auto-code currently in q8-hardwaremgr.c :
> 
>                /*
>                 * These accelerometer based heuristics select the best
>                 * default based on known q8 tablets.
>                 */
>                switch (data->accelerometer.model) {
>                case da280:
>                        if (data->accelerometer.addr == 0x27)
>                                ; /* No-op */
>                        else if (data->has_rda599x)
>                                data->touchscreen_invert_x = 1;
>                        else
>                                data->touchscreen_invert_y = 1;
>                        break;
>                case dmard09:
>                        data->touchscreen_invert_x = 1;
>                        break;
>                case mxc6225:
>                        data->touchscreen_variant = 1;
>                        break;
>                }
> 
> (Non set data->touchscreen_foo are left at 0).
> 
> So this would require us to be able to filter (to use your example)
> on if another i2c device is found and on which address it is found,
> that does not even take the rda559x check into account and is
> going to cause interesting ordering issues, how do we know when
> we can actually do the filtering if some of the variables we are
> filtering on are set by other auto-detected paths. Which auto-detect /
> i2c-probe-stop-at-first-match list do we execute first ? Worse
> actually for accelerometer orientation I will likely need to
> set the mount-matrix based on the detected touchscreen ...
> 
> The rda559x here is a sdio wifi chip, which is also connected to the
> i2c, and currently is detected through i2c to be able to separately
> identify 2 q8 boards which share the same touchscreen + accelerometer
> combination and who knows what other checks I or other people can
> come up with to differentiate board variants which do not have
> a simple eeprom to uniquely id them.
> 
> So as said before, no this cannot be all done in dt without
> adding a turing complete language to dt, and that is just to
> select which touchscreen_variant to use.
> 
> Then there also the probem of the combinatorial explosion having
> not only 2 firmware files but also invert-x and invert-y flags causes:
> We have 2 revisions with each 2 different firmware-files (more actually
> but I've reduced the set since some firmwares are compatible) with each
> both the x- and / or y axis as normal or inverted, for a total of:
> 2 (revision) * 2 (firmware-files) * 2 (x-inverted or not) * 2 (y...) = 16
> touchscreen variants, which means dt nodes for touchscreen1 to touchscreen16
> and that is just the silead gsl1680, some of these tablets also have
> elan or zeitec touchscreen controllers.
> 

There is a combinatorial explosion, but only a finite number of _known_ 
board versions.

> Now imagine what happens if a new board comes out which needs a 3th firmware
> file... I hope you can understand this is not a route I want to go.
> 
> Another problem is that if a user encounters the need for a new firmware
> variant he can now not easily try this (where as before we had
> module options to separately override firmware-name, the size, etc.
> 
> As written in my previous mail, this is all rather gsl1680 specific,
> and esp. being able to override the firmware-name, the size, etc.
> through module options is going to be useful (to ask endusers to test
> stuff without recompiling) on x86 too. So we will likely want to add
> most of the necessary stuff to the silead driver anyways.
> 
>> But then, I can't really tell which makes the most sense between
>> source-based and devicetree-based.
>> I prefer doing it in device-tree, since it means that any OEM can have
>> his device supported by only providing DTB, and won't need to provide
>> kernel patches.
> 
> If the OEM provides a DTB the OEM can just directly have the right
> parameters in there without relying on any auto-detection, this is
> already supported and the e.g. gsl1680 driver already happily
> works on several tablets where there is not so much hardware
> variance.
> 
> Even if the OEM needs to deal with e.g. different touchscreens on
> different board revisions, hopefully the simple auto-detect code will
> be enough, and he does not need e.g. different firmware-name settings
> for otherwise the same touchscreen controller. If that is not the
> case then he the OEM will have to provide a separate static
> (non probing) DTB per variant.
> 
>>> 2) miscellaneous extra config on top of figuring out which ICs are
>>> connected,
>>> basically the kind of stuff many vendors simply hard-code in their device
>>> specific os-image. This one is much more difficult to deal with and I think
>>> we need to figure this out on a case by case basis. This will require board
>>> specific code (just like the kernel has tons of DMI string activated board
>>> specific code on x86) and what is the best code for this place to live will
>>> be a case by case thing too.
>> 
>> With things like mount-matrix devicetree property, the goal is to have
>> such informations in the DTS.
> 
> Right and all the info I'm talking about can already be in the DTS and
> is already specified this way for various existing boards, this is
> obviously how we want things to work, this is the normal case /
> the straight code path.
> 
> Now lets get back to your mount-matrix example, the problem here is 2 board
> variants where the same accelerometer is used, but on a newer revision
> of the board it is mounted with a different orientation and otherwise
> almost nothing is changed on the board, certainly not something as
> useful as an id eeprom.
> 
> Lets assume that we can however still somehow differ the 2 revisions,
> then try to imagine how many different ways there are to differ
> between 2 board revisions if there is no easy way to do so,
> some crazy examples:
> -The 2nd revision has an external loopback on unused audio out / in
> pins for testing purposes, we could play + record sound and do
> a (rough) waveform match to see if the loopback is present
> -On the 2nd revision a pin from a pin compatible part which
> allows putting it in fully compatible mode, or allow new features
> mode, is now hooked up to a gpio instead of hardwired to compatible
> mode, we could change the device to new features mode and try
> to read/modify/write some register bit on the chip which is only
> writable in this mode
> -Etc.
> 
> Now try to design a way to express this in dt and we're back to
> needing a turing complete language (with a library for accessing
> various busses) again.
> 

No, not turing complete. This is going to require a little bit more
digging up but I think we can handle this with the method I described.

> Regards,
> 
> Hans

Regards

? Pantelis

P.S. Damn too much content to read.

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

* Re: Add Allwinner Q8 tablets hardware manager
  2016-10-27 15:52           ` Pantelis Antoniou
@ 2016-10-27 16:59               ` Pierre-Hugues Husson
  -1 siblings, 0 replies; 48+ messages in thread
From: Pierre-Hugues Husson @ 2016-10-27 16:59 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Hans de Goede, Mark Rutland, devicetree, Arnd Bergmann,
	Greg Kroah-Hartman, Chen-Yu Tsai, Rob Herring, Maxime Ripard,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

2016-10-27 17:52 GMT+02:00 Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/HQFizaE/u3fw@public.gmane.orgm>:
> Yes there is no EEPROM but you might be able to map probing results to
> a fake ‘model’ number.
>
> Let me expand a bit:
>
> Assume that you have a number of probing steps, for example A, B, C each
> returning true or false, and C being executed only when B is ‘true’ you
> could do this to generate a bit field that identifies it.
>
> For example let’s assume that model FOO’s probing steps are
>
> A false, B true, C false -> 010
>
> Model’s BAR
>
> A true, B false, C don’t care -> 10x
>
> Mapping these to models could be
>
> Model FOO, (010 & 111) == 010 (all three probing steps must match)
>
> Model BAR, (10x & 110) = 100 (the first two probing steps must match)

This method looks too complex on multiple grounds.
Assuming your method, I'm not too sure how this would actually be
described in a DTS.
Such probing steps should include reading/matching IDs in an EEPROM/on
an ADC, but it should also include the result of a driver's probe.
Also, drivers should have a way to report an ID/OTP instead of just a
boolean.

As you mentioned, it is a way to distinguish models, not just a set of
parameters.
Does this mean that this DT would lead to loading various DT based on
the matching model, which would look like a FIT?
Also there is a modularity problem there. If I have phones with either
screen A or screen B, and with either accelerometer A or accelerometer
B, I would have to implement all four combinations.

I'm starting to agree with Hans, and to be able to implement
everything he needs, would require a turing complete device-tree,
which can include and apply device-tree overlays.
This doesn't mean it can't be done, nor that it shouldn't be done, but
that's a lot of work.

Hans' i2c-probe-stop-at-first-match does make sense for most usecases,
but I have two problems with it:
1. It is I2C specific (as I've mentioned earlier, I have the same
needs with DSI panels)
2. This looks like a temporary solution if a turing-complete solution
is to be implemented.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-27 16:59               ` Pierre-Hugues Husson
  0 siblings, 0 replies; 48+ messages in thread
From: Pierre-Hugues Husson @ 2016-10-27 16:59 UTC (permalink / raw)
  To: linux-arm-kernel

2016-10-27 17:52 GMT+02:00 Pantelis Antoniou <pantelis.antoniou@konsulko.com>:
> Yes there is no EEPROM but you might be able to map probing results to
> a fake ?model? number.
>
> Let me expand a bit:
>
> Assume that you have a number of probing steps, for example A, B, C each
> returning true or false, and C being executed only when B is ?true? you
> could do this to generate a bit field that identifies it.
>
> For example let?s assume that model FOO?s probing steps are
>
> A false, B true, C false -> 010
>
> Model?s BAR
>
> A true, B false, C don?t care -> 10x
>
> Mapping these to models could be
>
> Model FOO, (010 & 111) == 010 (all three probing steps must match)
>
> Model BAR, (10x & 110) = 100 (the first two probing steps must match)

This method looks too complex on multiple grounds.
Assuming your method, I'm not too sure how this would actually be
described in a DTS.
Such probing steps should include reading/matching IDs in an EEPROM/on
an ADC, but it should also include the result of a driver's probe.
Also, drivers should have a way to report an ID/OTP instead of just a
boolean.

As you mentioned, it is a way to distinguish models, not just a set of
parameters.
Does this mean that this DT would lead to loading various DT based on
the matching model, which would look like a FIT?
Also there is a modularity problem there. If I have phones with either
screen A or screen B, and with either accelerometer A or accelerometer
B, I would have to implement all four combinations.

I'm starting to agree with Hans, and to be able to implement
everything he needs, would require a turing complete device-tree,
which can include and apply device-tree overlays.
This doesn't mean it can't be done, nor that it shouldn't be done, but
that's a lot of work.

Hans' i2c-probe-stop-at-first-match does make sense for most usecases,
but I have two problems with it:
1. It is I2C specific (as I've mentioned earlier, I have the same
needs with DSI panels)
2. This looks like a temporary solution if a turing-complete solution
is to be implemented.

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

* Re: Add Allwinner Q8 tablets hardware manager
  2016-10-27 16:59               ` Pierre-Hugues Husson
@ 2016-10-27 17:11                   ` Pantelis Antoniou
  -1 siblings, 0 replies; 48+ messages in thread
From: Pantelis Antoniou @ 2016-10-27 17:11 UTC (permalink / raw)
  To: Pierre-Hugues Husson
  Cc: Hans de Goede, Mark Rutland, devicetree, Arnd Bergmann,
	Greg Kroah-Hartman, Chen-Yu Tsai, Rob Herring, Maxime Ripard,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi Pierre,

> On Oct 27, 2016, at 19:59 , Pierre-Hugues Husson <phh-8tEavu1zA38@public.gmane.org> wrote:
> 
> 2016-10-27 17:52 GMT+02:00 Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>:
>> Yes there is no EEPROM but you might be able to map probing results to
>> a fake ‘model’ number.
>> 
>> Let me expand a bit:
>> 
>> Assume that you have a number of probing steps, for example A, B, C each
>> returning true or false, and C being executed only when B is ‘true’ you
>> could do this to generate a bit field that identifies it.
>> 
>> For example let’s assume that model FOO’s probing steps are
>> 
>> A false, B true, C false -> 010
>> 
>> Model’s BAR
>> 
>> A true, B false, C don’t care -> 10x
>> 
>> Mapping these to models could be
>> 
>> Model FOO, (010 & 111) == 010 (all three probing steps must match)
>> 
>> Model BAR, (10x & 110) = 100 (the first two probing steps must match)
> 
> This method looks too complex on multiple grounds.
> Assuming your method, I'm not too sure how this would actually be
> described in a DTS.
> Such probing steps should include reading/matching IDs in an EEPROM/on
> an ADC, but it should also include the result of a driver's probe.
> Also, drivers should have a way to report an ID/OTP instead of just a
> boolean.
> 

Err, I don’t think you got the point.

The probing steps are done by a board specific probe driver.
This driver performs the probing steps (which is exactly what Hans’s
method now does) but instead of applying changes to the device tree
programmatically generates a model string.

This model string can be used by a general purpose overlay manager to apply
the overlay(s) for the specific board. The plural part is important - read
below.

> As you mentioned, it is a way to distinguish models, not just a set of
> parameters.
> Does this mean that this DT would lead to loading various DT based on
> the matching model, which would look like a FIT?
> Also there is a modularity problem there. If I have phones with either
> screen A or screen B, and with either accelerometer A or accelerometer
> B, I would have to implement all four combinations.
> 

The model lookup need not result in a simple overlay to apply.

So for your case it would be:

model corp,0 -> overlay screen A + overlay accel A
model corp,1 -> overlay screen A + overlay accel B
model corp,2 -> overlay screen B + overlay accel A
model corp,3 -> overlay screen B + overlay accel B

You don’t need the combinatorial number of overlays.

> I'm starting to agree with Hans, and to be able to implement
> everything he needs, would require a turing complete device-tree,
> which can include and apply device-tree overlays.
> This doesn't mean it can't be done, nor that it shouldn't be done, but
> that's a lot of work.
> 
> Hans' i2c-probe-stop-at-first-match does make sense for most usecases,
> but I have two problems with it:
> 1. It is I2C specific (as I've mentioned earlier, I have the same
> needs with DSI panels)
> 2. This looks like a temporary solution if a turing-complete solution
> is to be implemented.

A custom I2C method would not be optimal IMO.

Regards

— Pantelis

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-27 17:11                   ` Pantelis Antoniou
  0 siblings, 0 replies; 48+ messages in thread
From: Pantelis Antoniou @ 2016-10-27 17:11 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Pierre,

> On Oct 27, 2016, at 19:59 , Pierre-Hugues Husson <phh@phh.me> wrote:
> 
> 2016-10-27 17:52 GMT+02:00 Pantelis Antoniou <pantelis.antoniou@konsulko.com>:
>> Yes there is no EEPROM but you might be able to map probing results to
>> a fake ?model? number.
>> 
>> Let me expand a bit:
>> 
>> Assume that you have a number of probing steps, for example A, B, C each
>> returning true or false, and C being executed only when B is ?true? you
>> could do this to generate a bit field that identifies it.
>> 
>> For example let?s assume that model FOO?s probing steps are
>> 
>> A false, B true, C false -> 010
>> 
>> Model?s BAR
>> 
>> A true, B false, C don?t care -> 10x
>> 
>> Mapping these to models could be
>> 
>> Model FOO, (010 & 111) == 010 (all three probing steps must match)
>> 
>> Model BAR, (10x & 110) = 100 (the first two probing steps must match)
> 
> This method looks too complex on multiple grounds.
> Assuming your method, I'm not too sure how this would actually be
> described in a DTS.
> Such probing steps should include reading/matching IDs in an EEPROM/on
> an ADC, but it should also include the result of a driver's probe.
> Also, drivers should have a way to report an ID/OTP instead of just a
> boolean.
> 

Err, I don?t think you got the point.

The probing steps are done by a board specific probe driver.
This driver performs the probing steps (which is exactly what Hans?s
method now does) but instead of applying changes to the device tree
programmatically generates a model string.

This model string can be used by a general purpose overlay manager to apply
the overlay(s) for the specific board. The plural part is important - read
below.

> As you mentioned, it is a way to distinguish models, not just a set of
> parameters.
> Does this mean that this DT would lead to loading various DT based on
> the matching model, which would look like a FIT?
> Also there is a modularity problem there. If I have phones with either
> screen A or screen B, and with either accelerometer A or accelerometer
> B, I would have to implement all four combinations.
> 

The model lookup need not result in a simple overlay to apply.

So for your case it would be:

model corp,0 -> overlay screen A + overlay accel A
model corp,1 -> overlay screen A + overlay accel B
model corp,2 -> overlay screen B + overlay accel A
model corp,3 -> overlay screen B + overlay accel B

You don?t need the combinatorial number of overlays.

> I'm starting to agree with Hans, and to be able to implement
> everything he needs, would require a turing complete device-tree,
> which can include and apply device-tree overlays.
> This doesn't mean it can't be done, nor that it shouldn't be done, but
> that's a lot of work.
> 
> Hans' i2c-probe-stop-at-first-match does make sense for most usecases,
> but I have two problems with it:
> 1. It is I2C specific (as I've mentioned earlier, I have the same
> needs with DSI panels)
> 2. This looks like a temporary solution if a turing-complete solution
> is to be implemented.

A custom I2C method would not be optimal IMO.

Regards

? Pantelis

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

* Re: Add Allwinner Q8 tablets hardware manager
  2016-10-27 14:53                 ` Hans de Goede
@ 2016-10-27 17:31                     ` Pierre-Hugues Husson
  -1 siblings, 0 replies; 48+ messages in thread
From: Pierre-Hugues Husson @ 2016-10-27 17:31 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Mark Rutland, devicetree, Arnd Bergmann, Greg Kroah-Hartman,
	Pantelis Antoniou, Chen-Yu Tsai, Rob Herring, Maxime Ripard,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

2016-10-27 16:53 GMT+02:00 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> Hi,
>
> No, the firmware-name (and matching resolution as different firmwares
> report different axis-ranges for the same digitizer) is selected
> primarily by the touchscreen_variant which sets: touchscreen_fw_name,
> touchscreen_width and touchscreen_height.
>
> The touchscreen_variant module option defaults to -1 which means "auto",
> when it is auto it gets set based on the touchscreen / accelerometer
> combination (which more or less uniquely identifies boards sofar),
> likewise all the other touchscreen module options default to -1,
> but can be overridden from the commandline.
>
> The intention is for things to just work, the commandline options are
> there as a fallback.
Ok, so I was really off. Sorry.
Now I think I understand the full complexity of the problem.

> We could just have:
>
>         i2c-probe-stop-at-first-match-0 = <&touchscreen1>, <&touchscreen2>,
> <&touchscreen3>;
>         i2c-probe-stop-at-first-match-1 = <&accelerometer1>,
> <&accelerometer2>;
>
> And have the i2c bus code look for an i2c-probe-stop-at-first-match-[i++]
> property
> until it is not found. Having a child-node with its own compatible for this
> feels wrong, as it uses a hierarchy where there really is none.
Ok, looks much better indeed.
I had one case where accelerometers could be on either i2c1 or i2c5.
Do you think this could be handled as well, or this makes things much
more complicated to fit in the i2c driver?

> So this would require us to be able to filter (to use your example)
> on if another i2c device is found and on which address it is found,
> that does not even take the rda559x check into account and is
> going to cause interesting ordering issues, how do we know when
> we can actually do the filtering if some of the variables we are
> filtering on are set by other auto-detected paths. Which auto-detect /
> i2c-probe-stop-at-first-match list do we execute first ? Worse
> actually for accelerometer orientation I will likely need to
> set the mount-matrix based on the detected touchscreen ...
>
> The rda559x here is a sdio wifi chip, which is also connected to the
> i2c, and currently is detected through i2c to be able to separately
> identify 2 q8 boards which share the same touchscreen + accelerometer
> combination and who knows what other checks I or other people can
> come up with to differentiate board variants which do not have
> a simple eeprom to uniquely id them.
>
> So as said before, no this cannot be all done in dt without
> adding a turing complete language to dt, and that is just to
> select which touchscreen_variant to use.
Ok, now that I understand the scope of your needs.
I agree with you, this needs a (close to) turing complete language.
I'm still not really happy about doing it in a driver, but I agree the
full scope you need is scarce enough.
Assuming this is done in a driver, there would need to be some
plumbing between i2c-probe-stop-at-first-match, device's probe
function and your driver, so that your driver only does the various
if/cases and DT changes, but there is no actual device communication
done in that driver.

> Then there also the probem of the combinatorial explosion having
> not only 2 firmware files but also invert-x and invert-y flags causes:
> We have 2 revisions with each 2 different firmware-files (more actually
> but I've reduced the set since some firmwares are compatible) with each
> both the x- and / or y axis as normal or inverted, for a total of:
> 2 (revision) * 2 (firmware-files) * 2 (x-inverted or not) * 2 (y...) = 16
> touchscreen variants, which means dt nodes for touchscreen1 to touchscreen16
> and that is just the silead gsl1680, some of these tablets also have
> elan or zeitec touchscreen controllers.
>
> Now imagine what happens if a new board comes out which needs a 3th firmware
> file... I hope you can understand this is not a route I want to go.
Right, I agree with you.
> Another problem is that if a user encounters the need for a new firmware
> variant he can now not easily try this (where as before we had
> module options to separately override firmware-name, the size, etc.
>
> As written in my previous mail, this is all rather gsl1680 specific,
> and esp. being able to override the firmware-name, the size, etc.
> through module options is going to be useful (to ask endusers to test
> stuff without recompiling) on x86 too. So we will likely want to add
> most of the necessary stuff to the silead driver anyways.

That's not currently the case, but can't we assume it will become easy
for users to install a DT overlay?
This would drop all your needs of module parameters, and would
actually be more modulable than your current scheme.
It is a more longer term thought, and could instead apply to further
boards having the same sort of troubles as you, rather than for this
first driver.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-27 17:31                     ` Pierre-Hugues Husson
  0 siblings, 0 replies; 48+ messages in thread
From: Pierre-Hugues Husson @ 2016-10-27 17:31 UTC (permalink / raw)
  To: linux-arm-kernel

2016-10-27 16:53 GMT+02:00 Hans de Goede <hdegoede@redhat.com>:
> Hi,
>
> No, the firmware-name (and matching resolution as different firmwares
> report different axis-ranges for the same digitizer) is selected
> primarily by the touchscreen_variant which sets: touchscreen_fw_name,
> touchscreen_width and touchscreen_height.
>
> The touchscreen_variant module option defaults to -1 which means "auto",
> when it is auto it gets set based on the touchscreen / accelerometer
> combination (which more or less uniquely identifies boards sofar),
> likewise all the other touchscreen module options default to -1,
> but can be overridden from the commandline.
>
> The intention is for things to just work, the commandline options are
> there as a fallback.
Ok, so I was really off. Sorry.
Now I think I understand the full complexity of the problem.

> We could just have:
>
>         i2c-probe-stop-at-first-match-0 = <&touchscreen1>, <&touchscreen2>,
> <&touchscreen3>;
>         i2c-probe-stop-at-first-match-1 = <&accelerometer1>,
> <&accelerometer2>;
>
> And have the i2c bus code look for an i2c-probe-stop-at-first-match-[i++]
> property
> until it is not found. Having a child-node with its own compatible for this
> feels wrong, as it uses a hierarchy where there really is none.
Ok, looks much better indeed.
I had one case where accelerometers could be on either i2c1 or i2c5.
Do you think this could be handled as well, or this makes things much
more complicated to fit in the i2c driver?

> So this would require us to be able to filter (to use your example)
> on if another i2c device is found and on which address it is found,
> that does not even take the rda559x check into account and is
> going to cause interesting ordering issues, how do we know when
> we can actually do the filtering if some of the variables we are
> filtering on are set by other auto-detected paths. Which auto-detect /
> i2c-probe-stop-at-first-match list do we execute first ? Worse
> actually for accelerometer orientation I will likely need to
> set the mount-matrix based on the detected touchscreen ...
>
> The rda559x here is a sdio wifi chip, which is also connected to the
> i2c, and currently is detected through i2c to be able to separately
> identify 2 q8 boards which share the same touchscreen + accelerometer
> combination and who knows what other checks I or other people can
> come up with to differentiate board variants which do not have
> a simple eeprom to uniquely id them.
>
> So as said before, no this cannot be all done in dt without
> adding a turing complete language to dt, and that is just to
> select which touchscreen_variant to use.
Ok, now that I understand the scope of your needs.
I agree with you, this needs a (close to) turing complete language.
I'm still not really happy about doing it in a driver, but I agree the
full scope you need is scarce enough.
Assuming this is done in a driver, there would need to be some
plumbing between i2c-probe-stop-at-first-match, device's probe
function and your driver, so that your driver only does the various
if/cases and DT changes, but there is no actual device communication
done in that driver.

> Then there also the probem of the combinatorial explosion having
> not only 2 firmware files but also invert-x and invert-y flags causes:
> We have 2 revisions with each 2 different firmware-files (more actually
> but I've reduced the set since some firmwares are compatible) with each
> both the x- and / or y axis as normal or inverted, for a total of:
> 2 (revision) * 2 (firmware-files) * 2 (x-inverted or not) * 2 (y...) = 16
> touchscreen variants, which means dt nodes for touchscreen1 to touchscreen16
> and that is just the silead gsl1680, some of these tablets also have
> elan or zeitec touchscreen controllers.
>
> Now imagine what happens if a new board comes out which needs a 3th firmware
> file... I hope you can understand this is not a route I want to go.
Right, I agree with you.
> Another problem is that if a user encounters the need for a new firmware
> variant he can now not easily try this (where as before we had
> module options to separately override firmware-name, the size, etc.
>
> As written in my previous mail, this is all rather gsl1680 specific,
> and esp. being able to override the firmware-name, the size, etc.
> through module options is going to be useful (to ask endusers to test
> stuff without recompiling) on x86 too. So we will likely want to add
> most of the necessary stuff to the silead driver anyways.

That's not currently the case, but can't we assume it will become easy
for users to install a DT overlay?
This would drop all your needs of module parameters, and would
actually be more modulable than your current scheme.
It is a more longer term thought, and could instead apply to further
boards having the same sort of troubles as you, rather than for this
first driver.

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

* Re: Add Allwinner Q8 tablets hardware manager
  2016-10-27 17:11                   ` Pantelis Antoniou
@ 2016-10-27 19:04                       ` Pierre-Hugues Husson
  -1 siblings, 0 replies; 48+ messages in thread
From: Pierre-Hugues Husson @ 2016-10-27 19:04 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Hans de Goede, Mark Rutland, devicetree, Arnd Bergmann,
	Greg Kroah-Hartman, Chen-Yu Tsai, Rob Herring, Maxime Ripard,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

2016-10-27 19:11 GMT+02:00 Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/HQFizaE/u3fw@public.gmane.orgm>:
>
> Hi Pierre,
>
> > On Oct 27, 2016, at 19:59 , Pierre-Hugues Husson <phh-8tEavu1zA38@public.gmane.org> wrote:
> >
> > 2016-10-27 17:52 GMT+02:00 Pantelis Antoniou <pantelis.antoniou@konsulko.com>:
> >> Yes there is no EEPROM but you might be able to map probing results to
> >> a fake ‘model’ number.
> >>
> >> Let me expand a bit:
> >>
> >> Assume that you have a number of probing steps, for example A, B, C each
> >> returning true or false, and C being executed only when B is ‘true’ you
> >> could do this to generate a bit field that identifies it.
> >>
> >> For example let’s assume that model FOO’s probing steps are
> >>
> >> A false, B true, C false -> 010
> >>
> >> Model’s BAR
> >>
> >> A true, B false, C don’t care -> 10x
> >>
> >> Mapping these to models could be
> >>
> >> Model FOO, (010 & 111) == 010 (all three probing steps must match)
> >>
> >> Model BAR, (10x & 110) = 100 (the first two probing steps must match)
> >
> > This method looks too complex on multiple grounds.
> > Assuming your method, I'm not too sure how this would actually be
> > described in a DTS.
> > Such probing steps should include reading/matching IDs in an EEPROM/on
> > an ADC, but it should also include the result of a driver's probe.
> > Also, drivers should have a way to report an ID/OTP instead of just a
> > boolean.
> >
>
> Err, I don’t think you got the point.
>
> The probing steps are done by a board specific probe driver.
> This driver performs the probing steps (which is exactly what Hans’s
> method now does) but instead of applying changes to the device tree
> programmatically generates a model string.
>
> This model string can be used by a general purpose overlay manager to apply
> the overlay(s) for the specific board. The plural part is important - read
> below.

Ok, I agree I didn't get the point, and I'm not sure I do now.
If I understand correctly, the difference between your method and
Hans', is that instead of manipulating directly OF properties based on
heuristics, there will be a heuristic to determine model revision, and
THEN apply overlays based on determined model revision.

If this is the correct interpretation, this means that for boards with
two possible accelerometers, a new driver is required, while something
as simple as i2c-probe-stop-at-first-match wouldn't require a new
driver.

> > As you mentioned, it is a way to distinguish models, not just a set of
> > parameters.
> > Does this mean that this DT would lead to loading various DT based on
> > the matching model, which would look like a FIT?
> > Also there is a modularity problem there. If I have phones with either
> > screen A or screen B, and with either accelerometer A or accelerometer
> > B, I would have to implement all four combinations.
> >
>
> The model lookup need not result in a simple overlay to apply.
>
> So for your case it would be:
>
> model corp,0 -> overlay screen A + overlay accel A
> model corp,1 -> overlay screen A + overlay accel B
> model corp,2 -> overlay screen B + overlay accel A
> model corp,3 -> overlay screen B + overlay accel B
>
> You don’t need the combinatorial number of overlays.

My worry initially was that all 4 "model corp" are needed, while with
using a simple approach like i2c-probe-stop-at-first-match, this
wouldn't be needed.
But now that I'm thinking of it again, for such a case to happen, this
would require to have OEMs picking random components for tablets of
one production batch. This wouldn't make any sense.
So I agree a model-based method should cover sufficient cases to be worthwhile.
I think it covers every device I've met.

Regards,
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-27 19:04                       ` Pierre-Hugues Husson
  0 siblings, 0 replies; 48+ messages in thread
From: Pierre-Hugues Husson @ 2016-10-27 19:04 UTC (permalink / raw)
  To: linux-arm-kernel

2016-10-27 19:11 GMT+02:00 Pantelis Antoniou <pantelis.antoniou@konsulko.com>:
>
> Hi Pierre,
>
> > On Oct 27, 2016, at 19:59 , Pierre-Hugues Husson <phh@phh.me> wrote:
> >
> > 2016-10-27 17:52 GMT+02:00 Pantelis Antoniou <pantelis.antoniou@konsulko.com>:
> >> Yes there is no EEPROM but you might be able to map probing results to
> >> a fake ?model? number.
> >>
> >> Let me expand a bit:
> >>
> >> Assume that you have a number of probing steps, for example A, B, C each
> >> returning true or false, and C being executed only when B is ?true? you
> >> could do this to generate a bit field that identifies it.
> >>
> >> For example let?s assume that model FOO?s probing steps are
> >>
> >> A false, B true, C false -> 010
> >>
> >> Model?s BAR
> >>
> >> A true, B false, C don?t care -> 10x
> >>
> >> Mapping these to models could be
> >>
> >> Model FOO, (010 & 111) == 010 (all three probing steps must match)
> >>
> >> Model BAR, (10x & 110) = 100 (the first two probing steps must match)
> >
> > This method looks too complex on multiple grounds.
> > Assuming your method, I'm not too sure how this would actually be
> > described in a DTS.
> > Such probing steps should include reading/matching IDs in an EEPROM/on
> > an ADC, but it should also include the result of a driver's probe.
> > Also, drivers should have a way to report an ID/OTP instead of just a
> > boolean.
> >
>
> Err, I don?t think you got the point.
>
> The probing steps are done by a board specific probe driver.
> This driver performs the probing steps (which is exactly what Hans?s
> method now does) but instead of applying changes to the device tree
> programmatically generates a model string.
>
> This model string can be used by a general purpose overlay manager to apply
> the overlay(s) for the specific board. The plural part is important - read
> below.

Ok, I agree I didn't get the point, and I'm not sure I do now.
If I understand correctly, the difference between your method and
Hans', is that instead of manipulating directly OF properties based on
heuristics, there will be a heuristic to determine model revision, and
THEN apply overlays based on determined model revision.

If this is the correct interpretation, this means that for boards with
two possible accelerometers, a new driver is required, while something
as simple as i2c-probe-stop-at-first-match wouldn't require a new
driver.

> > As you mentioned, it is a way to distinguish models, not just a set of
> > parameters.
> > Does this mean that this DT would lead to loading various DT based on
> > the matching model, which would look like a FIT?
> > Also there is a modularity problem there. If I have phones with either
> > screen A or screen B, and with either accelerometer A or accelerometer
> > B, I would have to implement all four combinations.
> >
>
> The model lookup need not result in a simple overlay to apply.
>
> So for your case it would be:
>
> model corp,0 -> overlay screen A + overlay accel A
> model corp,1 -> overlay screen A + overlay accel B
> model corp,2 -> overlay screen B + overlay accel A
> model corp,3 -> overlay screen B + overlay accel B
>
> You don?t need the combinatorial number of overlays.

My worry initially was that all 4 "model corp" are needed, while with
using a simple approach like i2c-probe-stop-at-first-match, this
wouldn't be needed.
But now that I'm thinking of it again, for such a case to happen, this
would require to have OEMs picking random components for tablets of
one production batch. This wouldn't make any sense.
So I agree a model-based method should cover sufficient cases to be worthwhile.
I think it covers every device I've met.

Regards,

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

* Re: Add Allwinner Q8 tablets hardware manager
  2016-10-27 19:04                       ` Pierre-Hugues Husson
@ 2016-10-27 19:23                           ` Pantelis Antoniou
  -1 siblings, 0 replies; 48+ messages in thread
From: Pantelis Antoniou @ 2016-10-27 19:23 UTC (permalink / raw)
  To: Pierre-Hugues Husson
  Cc: Hans de Goede, Mark Rutland, devicetree, Arnd Bergmann,
	Greg Kroah-Hartman, Chen-Yu Tsai, Rob Herring, Maxime Ripard,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi Pierre,

> On Oct 27, 2016, at 22:04 , Pierre-Hugues Husson <phh-8tEavu1zA38@public.gmane.org> wrote:
> 
> 2016-10-27 19:11 GMT+02:00 Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>:
>> 
>> Hi Pierre,
>> 
>>> On Oct 27, 2016, at 19:59 , Pierre-Hugues Husson <phh-8tEavu1zA38@public.gmane.org> wrote:
>>> 
>>> 2016-10-27 17:52 GMT+02:00 Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>:
>>>> Yes there is no EEPROM but you might be able to map probing results to
>>>> a fake ‘model’ number.
>>>> 
>>>> Let me expand a bit:
>>>> 
>>>> Assume that you have a number of probing steps, for example A, B, C each
>>>> returning true or false, and C being executed only when B is ‘true’ you
>>>> could do this to generate a bit field that identifies it.
>>>> 
>>>> For example let’s assume that model FOO’s probing steps are
>>>> 
>>>> A false, B true, C false -> 010
>>>> 
>>>> Model’s BAR
>>>> 
>>>> A true, B false, C don’t care -> 10x
>>>> 
>>>> Mapping these to models could be
>>>> 
>>>> Model FOO, (010 & 111) == 010 (all three probing steps must match)
>>>> 
>>>> Model BAR, (10x & 110) = 100 (the first two probing steps must match)
>>> 
>>> This method looks too complex on multiple grounds.
>>> Assuming your method, I'm not too sure how this would actually be
>>> described in a DTS.
>>> Such probing steps should include reading/matching IDs in an EEPROM/on
>>> an ADC, but it should also include the result of a driver's probe.
>>> Also, drivers should have a way to report an ID/OTP instead of just a
>>> boolean.
>>> 
>> 
>> Err, I don’t think you got the point.
>> 
>> The probing steps are done by a board specific probe driver.
>> This driver performs the probing steps (which is exactly what Hans’s
>> method now does) but instead of applying changes to the device tree
>> programmatically generates a model string.
>> 
>> This model string can be used by a general purpose overlay manager to apply
>> the overlay(s) for the specific board. The plural part is important - read
>> below.
> 
> Ok, I agree I didn't get the point, and I'm not sure I do now.
> If I understand correctly, the difference between your method and
> Hans', is that instead of manipulating directly OF properties based on
> heuristics, there will be a heuristic to determine model revision, and
> THEN apply overlays based on determined model revision.
> 
> If this is the correct interpretation, this means that for boards with
> two possible accelerometers, a new driver is required, while something
> as simple as i2c-probe-stop-at-first-match wouldn't require a new
> driver.
> 

It does require a new driver, but the driver is simple a probing method
driver; it does not require to modify the actual drivers that are going
to be instantiated.

In DT terms for a board specific probe driver:

bpm: board_probe_method {
	compatible = “foocorp,bar-board-probe”;
};

genm: generic_model_manager {
	compatible = “generic-model-manager”;
	
	probe-method = <&bpm>;

	/* list of models and overlays to apply in sequence */
	models {
		foo-model-0 = “foo,bar,screen-A”, “foo,bar,accel-A”;
		foo-model-1 = “foo,bar,screen-A”, “foo,bar,accel-B”;
		foo-model-2 = “foo,bar,screen-B”, “foo,bar,accel-A”;
		foo-model-3 = “foo,bar,screen-B”, “foo,bar,accel-B”;
	};
};

The manager can call the single exported method which could be as simple
as:

const char *probe_identify();

In fact for things like i2c probe a generic probe method might suffice.

i2c_generic_bpm: generic_i2c_probe_method {
	compatible = “i2c-generic-probe-method”;

	models {
		model@0 {
			result = “foo-model-0”;
			/* match when read at address 12 returns 5 */
			/* and read at address 14 returns 0 */
			/* format is command, bus, address, argument */
			match = <MATCH_READ &i2c0 12 5>, <MATCH_READ &i2c0 0 14 0>;
			… etc ...
		};
	};
};


>>> As you mentioned, it is a way to distinguish models, not just a set of
>>> parameters.
>>> Does this mean that this DT would lead to loading various DT based on
>>> the matching model, which would look like a FIT?
>>> Also there is a modularity problem there. If I have phones with either
>>> screen A or screen B, and with either accelerometer A or accelerometer
>>> B, I would have to implement all four combinations.
>>> 
>> 
>> The model lookup need not result in a simple overlay to apply.
>> 
>> So for your case it would be:
>> 
>> model corp,0 -> overlay screen A + overlay accel A
>> model corp,1 -> overlay screen A + overlay accel B
>> model corp,2 -> overlay screen B + overlay accel A
>> model corp,3 -> overlay screen B + overlay accel B
>> 
>> You don’t need the combinatorial number of overlays.
> 
> My worry initially was that all 4 "model corp" are needed, while with
> using a simple approach like i2c-probe-stop-at-first-match, this
> wouldn't be needed.
> But now that I'm thinking of it again, for such a case to happen, this
> would require to have OEMs picking random components for tablets of
> one production batch. This wouldn't make any sense.
> So I agree a model-based method should cover sufficient cases to be worthwhile.
> I think it covers every device I've met.
> 

Yeah, model number in this case means both model and revision.
If components change you change the internal model number.

> Regards,

Regards

— Pantelis

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-27 19:23                           ` Pantelis Antoniou
  0 siblings, 0 replies; 48+ messages in thread
From: Pantelis Antoniou @ 2016-10-27 19:23 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Pierre,

> On Oct 27, 2016, at 22:04 , Pierre-Hugues Husson <phh@phh.me> wrote:
> 
> 2016-10-27 19:11 GMT+02:00 Pantelis Antoniou <pantelis.antoniou@konsulko.com>:
>> 
>> Hi Pierre,
>> 
>>> On Oct 27, 2016, at 19:59 , Pierre-Hugues Husson <phh@phh.me> wrote:
>>> 
>>> 2016-10-27 17:52 GMT+02:00 Pantelis Antoniou <pantelis.antoniou@konsulko.com>:
>>>> Yes there is no EEPROM but you might be able to map probing results to
>>>> a fake ?model? number.
>>>> 
>>>> Let me expand a bit:
>>>> 
>>>> Assume that you have a number of probing steps, for example A, B, C each
>>>> returning true or false, and C being executed only when B is ?true? you
>>>> could do this to generate a bit field that identifies it.
>>>> 
>>>> For example let?s assume that model FOO?s probing steps are
>>>> 
>>>> A false, B true, C false -> 010
>>>> 
>>>> Model?s BAR
>>>> 
>>>> A true, B false, C don?t care -> 10x
>>>> 
>>>> Mapping these to models could be
>>>> 
>>>> Model FOO, (010 & 111) == 010 (all three probing steps must match)
>>>> 
>>>> Model BAR, (10x & 110) = 100 (the first two probing steps must match)
>>> 
>>> This method looks too complex on multiple grounds.
>>> Assuming your method, I'm not too sure how this would actually be
>>> described in a DTS.
>>> Such probing steps should include reading/matching IDs in an EEPROM/on
>>> an ADC, but it should also include the result of a driver's probe.
>>> Also, drivers should have a way to report an ID/OTP instead of just a
>>> boolean.
>>> 
>> 
>> Err, I don?t think you got the point.
>> 
>> The probing steps are done by a board specific probe driver.
>> This driver performs the probing steps (which is exactly what Hans?s
>> method now does) but instead of applying changes to the device tree
>> programmatically generates a model string.
>> 
>> This model string can be used by a general purpose overlay manager to apply
>> the overlay(s) for the specific board. The plural part is important - read
>> below.
> 
> Ok, I agree I didn't get the point, and I'm not sure I do now.
> If I understand correctly, the difference between your method and
> Hans', is that instead of manipulating directly OF properties based on
> heuristics, there will be a heuristic to determine model revision, and
> THEN apply overlays based on determined model revision.
> 
> If this is the correct interpretation, this means that for boards with
> two possible accelerometers, a new driver is required, while something
> as simple as i2c-probe-stop-at-first-match wouldn't require a new
> driver.
> 

It does require a new driver, but the driver is simple a probing method
driver; it does not require to modify the actual drivers that are going
to be instantiated.

In DT terms for a board specific probe driver:

bpm: board_probe_method {
	compatible = ?foocorp,bar-board-probe?;
};

genm: generic_model_manager {
	compatible = ?generic-model-manager?;
	
	probe-method = <&bpm>;

	/* list of models and overlays to apply in sequence */
	models {
		foo-model-0 = ?foo,bar,screen-A?, ?foo,bar,accel-A?;
		foo-model-1 = ?foo,bar,screen-A?, ?foo,bar,accel-B?;
		foo-model-2 = ?foo,bar,screen-B?, ?foo,bar,accel-A?;
		foo-model-3 = ?foo,bar,screen-B?, ?foo,bar,accel-B?;
	};
};

The manager can call the single exported method which could be as simple
as:

const char *probe_identify();

In fact for things like i2c probe a generic probe method might suffice.

i2c_generic_bpm: generic_i2c_probe_method {
	compatible = ?i2c-generic-probe-method?;

	models {
		model at 0 {
			result = ?foo-model-0?;
			/* match when read at address 12 returns 5 */
			/* and read at address 14 returns 0 */
			/* format is command, bus, address, argument */
			match = <MATCH_READ &i2c0 12 5>, <MATCH_READ &i2c0 0 14 0>;
			? etc ...
		};
	};
};


>>> As you mentioned, it is a way to distinguish models, not just a set of
>>> parameters.
>>> Does this mean that this DT would lead to loading various DT based on
>>> the matching model, which would look like a FIT?
>>> Also there is a modularity problem there. If I have phones with either
>>> screen A or screen B, and with either accelerometer A or accelerometer
>>> B, I would have to implement all four combinations.
>>> 
>> 
>> The model lookup need not result in a simple overlay to apply.
>> 
>> So for your case it would be:
>> 
>> model corp,0 -> overlay screen A + overlay accel A
>> model corp,1 -> overlay screen A + overlay accel B
>> model corp,2 -> overlay screen B + overlay accel A
>> model corp,3 -> overlay screen B + overlay accel B
>> 
>> You don?t need the combinatorial number of overlays.
> 
> My worry initially was that all 4 "model corp" are needed, while with
> using a simple approach like i2c-probe-stop-at-first-match, this
> wouldn't be needed.
> But now that I'm thinking of it again, for such a case to happen, this
> would require to have OEMs picking random components for tablets of
> one production batch. This wouldn't make any sense.
> So I agree a model-based method should cover sufficient cases to be worthwhile.
> I think it covers every device I've met.
> 

Yeah, model number in this case means both model and revision.
If components change you change the internal model number.

> Regards,

Regards

? Pantelis

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

* Re: Add Allwinner Q8 tablets hardware manager
  2016-10-27 15:52           ` Pantelis Antoniou
@ 2016-10-27 21:10               ` Hans de Goede
  -1 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-27 21:10 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Mark Rutland, Rob Herring, Arnd Bergmann, Greg Kroah-Hartman,
	Maxime Ripard, Chen-Yu Tsai,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree

Hi,

On 27-10-16 17:52, Pantelis Antoniou wrote:
> Hi Hans,

<snip>

>> Right, so again I think we need to split the discussion in 2 steps:
>>
>> 1) How do we apply the fixups, currently I'm using free-form changes
>> done from C-code. I can envision moving to something like the quirk
>> mechanism suggested by Pantelis in the past. Note this is not a perfect
>> fit for my rather corner-case use-case, but I can understand that in
>> general you want the variants to be described in dt, and activated
>> in some way, rather then have c-code make free-form changes to the dt
>>
>
> We’ve had this discussion before, so I guess here it goes again.
>
> I think the biggest objection is the programmatic way of applying
> every quirk by ‘hand’.
>
> If there was a way to keep the probing mechanism but just spit out
> a ‘model’ number we could reasonably map it to an overlay to apply
> with a generic overlay manager.
>
> From an internal s/w standpoint having an expansion board or soldered
> parts makes no difference.

I disagree, with soldered parts it often is the board has
one of "accelerometer a", "b" or "c", where in the simple case
my suggested i2c-probe-stop-at-first-match property will
just work for a new board by creating a new dtb without needing any
kernel changes, where as your suggested model-string generator
C-code module would need updating.

I think that there is a need for both really.

>> 2) How do we select which fixups to apply. Again I can understand
>> you wanting some well defined mechanism for this, but again my
>> use-case is special and simply does not allow for this as there
>> is no id-eeprom to read or some such.
>>
>
> Yes there is no EEPROM but you might be able to map probing results to
> a fake ‘model’ number.
>
> Let me expand a bit:
>
> Assume that you have a number of probing steps, for example A, B, C each
> returning true or false, and C being executed only when B is ‘true’ you
> could do this to generate a bit field that identifies it.
>
> For example let’s assume that model FOO’s probing steps are
>
> A false, B true, C false -> 010
>
> Model’s BAR
>
> A true, B false, C don’t care -> 10x
>
> Mapping these to models could be
>
> Model FOO, (010 & 111) == 010 (all three probing steps must match)
>
> Model BAR, (10x & 110) = 100 (the first two probing steps must match)

Interesting this is actually the same direction my thoughts on this
lead me in my reply in the other thread on this started by
Antoine Tenart.

Only difference is that I suggested putting the model-string
generation in the bootloader, so it will just be there when the kernel
boots. But I agree that given things like upgradability having
the model-string generation code in the kernel is better.

<snip>

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-27 21:10               ` Hans de Goede
  0 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-27 21:10 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 27-10-16 17:52, Pantelis Antoniou wrote:
> Hi Hans,

<snip>

>> Right, so again I think we need to split the discussion in 2 steps:
>>
>> 1) How do we apply the fixups, currently I'm using free-form changes
>> done from C-code. I can envision moving to something like the quirk
>> mechanism suggested by Pantelis in the past. Note this is not a perfect
>> fit for my rather corner-case use-case, but I can understand that in
>> general you want the variants to be described in dt, and activated
>> in some way, rather then have c-code make free-form changes to the dt
>>
>
> We?ve had this discussion before, so I guess here it goes again.
>
> I think the biggest objection is the programmatic way of applying
> every quirk by ?hand?.
>
> If there was a way to keep the probing mechanism but just spit out
> a ?model? number we could reasonably map it to an overlay to apply
> with a generic overlay manager.
>
> From an internal s/w standpoint having an expansion board or soldered
> parts makes no difference.

I disagree, with soldered parts it often is the board has
one of "accelerometer a", "b" or "c", where in the simple case
my suggested i2c-probe-stop-at-first-match property will
just work for a new board by creating a new dtb without needing any
kernel changes, where as your suggested model-string generator
C-code module would need updating.

I think that there is a need for both really.

>> 2) How do we select which fixups to apply. Again I can understand
>> you wanting some well defined mechanism for this, but again my
>> use-case is special and simply does not allow for this as there
>> is no id-eeprom to read or some such.
>>
>
> Yes there is no EEPROM but you might be able to map probing results to
> a fake ?model? number.
>
> Let me expand a bit:
>
> Assume that you have a number of probing steps, for example A, B, C each
> returning true or false, and C being executed only when B is ?true? you
> could do this to generate a bit field that identifies it.
>
> For example let?s assume that model FOO?s probing steps are
>
> A false, B true, C false -> 010
>
> Model?s BAR
>
> A true, B false, C don?t care -> 10x
>
> Mapping these to models could be
>
> Model FOO, (010 & 111) == 010 (all three probing steps must match)
>
> Model BAR, (10x & 110) = 100 (the first two probing steps must match)

Interesting this is actually the same direction my thoughts on this
lead me in my reply in the other thread on this started by
Antoine Tenart.

Only difference is that I suggested putting the model-string
generation in the bootloader, so it will just be there when the kernel
boots. But I agree that given things like upgradability having
the model-string generation code in the kernel is better.

<snip>

Regards,

Hans

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

* Re: Add Allwinner Q8 tablets hardware manager
  2016-10-27 17:31                     ` Pierre-Hugues Husson
@ 2016-10-27 21:15                         ` Hans de Goede
  -1 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-27 21:15 UTC (permalink / raw)
  To: Pierre-Hugues Husson
  Cc: Mark Rutland, devicetree, Arnd Bergmann, Greg Kroah-Hartman,
	Pantelis Antoniou, Chen-Yu Tsai, Rob Herring, Maxime Ripard,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi,

On 27-10-16 19:31, Pierre-Hugues Husson wrote:
> 2016-10-27 16:53 GMT+02:00 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:

<snip>

>> We could just have:
>>
>>         i2c-probe-stop-at-first-match-0 = <&touchscreen1>, <&touchscreen2>,
>> <&touchscreen3>;
>>         i2c-probe-stop-at-first-match-1 = <&accelerometer1>,
>> <&accelerometer2>;
>>
>> And have the i2c bus code look for an i2c-probe-stop-at-first-match-[i++]
>> property
>> until it is not found. Having a child-node with its own compatible for this
>> feels wrong, as it uses a hierarchy where there really is none.
> Ok, looks much better indeed.
> I had one case where accelerometers could be on either i2c1 or i2c5.
> Do you think this could be handled as well, or this makes things much
> more complicated to fit in the i2c driver?

Handling that is easy, just add a i2c-probe-stop-at-first-match to
both busses (with separate child nodes to be probed under each bus),
the on one bus the probe-code will just read the end of the list
and stop, I believe we should not treat that as an error anyways
(even if there is only 1 bus).

>
>> So this would require us to be able to filter (to use your example)
>> on if another i2c device is found and on which address it is found,
>> that does not even take the rda559x check into account and is
>> going to cause interesting ordering issues, how do we know when
>> we can actually do the filtering if some of the variables we are
>> filtering on are set by other auto-detected paths. Which auto-detect /
>> i2c-probe-stop-at-first-match list do we execute first ? Worse
>> actually for accelerometer orientation I will likely need to
>> set the mount-matrix based on the detected touchscreen ...
>>
>> The rda559x here is a sdio wifi chip, which is also connected to the
>> i2c, and currently is detected through i2c to be able to separately
>> identify 2 q8 boards which share the same touchscreen + accelerometer
>> combination and who knows what other checks I or other people can
>> come up with to differentiate board variants which do not have
>> a simple eeprom to uniquely id them.
>>
>> So as said before, no this cannot be all done in dt without
>> adding a turing complete language to dt, and that is just to
>> select which touchscreen_variant to use.
> Ok, now that I understand the scope of your needs.
> I agree with you, this needs a (close to) turing complete language.
> I'm still not really happy about doing it in a driver, but I agree the
> full scope you need is scarce enough.
> Assuming this is done in a driver, there would need to be some
> plumbing between i2c-probe-stop-at-first-match, device's probe
> function and your driver, so that your driver only does the various
> if/cases and DT changes, but there is no actual device communication
> done in that driver.

Ah, no I meant dealing with this in the actual device driver,
not in some special intermediate driver, just like the actual x86
device drivers (sometimes) apply quirks based on board DMI strings.

<snip>

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Add Allwinner Q8 tablets hardware manager
@ 2016-10-27 21:15                         ` Hans de Goede
  0 siblings, 0 replies; 48+ messages in thread
From: Hans de Goede @ 2016-10-27 21:15 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 27-10-16 19:31, Pierre-Hugues Husson wrote:
> 2016-10-27 16:53 GMT+02:00 Hans de Goede <hdegoede@redhat.com>:

<snip>

>> We could just have:
>>
>>         i2c-probe-stop-at-first-match-0 = <&touchscreen1>, <&touchscreen2>,
>> <&touchscreen3>;
>>         i2c-probe-stop-at-first-match-1 = <&accelerometer1>,
>> <&accelerometer2>;
>>
>> And have the i2c bus code look for an i2c-probe-stop-at-first-match-[i++]
>> property
>> until it is not found. Having a child-node with its own compatible for this
>> feels wrong, as it uses a hierarchy where there really is none.
> Ok, looks much better indeed.
> I had one case where accelerometers could be on either i2c1 or i2c5.
> Do you think this could be handled as well, or this makes things much
> more complicated to fit in the i2c driver?

Handling that is easy, just add a i2c-probe-stop-at-first-match to
both busses (with separate child nodes to be probed under each bus),
the on one bus the probe-code will just read the end of the list
and stop, I believe we should not treat that as an error anyways
(even if there is only 1 bus).

>
>> So this would require us to be able to filter (to use your example)
>> on if another i2c device is found and on which address it is found,
>> that does not even take the rda559x check into account and is
>> going to cause interesting ordering issues, how do we know when
>> we can actually do the filtering if some of the variables we are
>> filtering on are set by other auto-detected paths. Which auto-detect /
>> i2c-probe-stop-at-first-match list do we execute first ? Worse
>> actually for accelerometer orientation I will likely need to
>> set the mount-matrix based on the detected touchscreen ...
>>
>> The rda559x here is a sdio wifi chip, which is also connected to the
>> i2c, and currently is detected through i2c to be able to separately
>> identify 2 q8 boards which share the same touchscreen + accelerometer
>> combination and who knows what other checks I or other people can
>> come up with to differentiate board variants which do not have
>> a simple eeprom to uniquely id them.
>>
>> So as said before, no this cannot be all done in dt without
>> adding a turing complete language to dt, and that is just to
>> select which touchscreen_variant to use.
> Ok, now that I understand the scope of your needs.
> I agree with you, this needs a (close to) turing complete language.
> I'm still not really happy about doing it in a driver, but I agree the
> full scope you need is scarce enough.
> Assuming this is done in a driver, there would need to be some
> plumbing between i2c-probe-stop-at-first-match, device's probe
> function and your driver, so that your driver only does the various
> if/cases and DT changes, but there is no actual device communication
> done in that driver.

Ah, no I meant dealing with this in the actual device driver,
not in some special intermediate driver, just like the actual x86
device drivers (sometimes) apply quirks based on board DMI strings.

<snip>

Regards,

Hans

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

end of thread, other threads:[~2016-10-27 21:15 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-14  7:53 Add Allwinner Q8 tablets hardware manager Hans de Goede
2016-10-14  7:53 ` Hans de Goede
     [not found] ` <20161014075337.10452-1-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-14  7:53   ` [PATCH 1/6] dt: bindings: Add Allwinner Q8 tablets hardware manager bindings Hans de Goede
2016-10-14  7:53     ` Hans de Goede
     [not found]     ` <20161014075337.10452-2-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-26 20:39       ` Rob Herring
2016-10-26 20:39         ` Rob Herring
2016-10-14  7:53   ` [PATCH 2/6] misc: Add Allwinner Q8 tablet hardware manager Hans de Goede
2016-10-14  7:53     ` Hans de Goede
2016-10-14  7:53   ` [PATCH 3/6] misc: q8-hardwaremgr: Add accelerometer detection Hans de Goede
2016-10-14  7:53     ` Hans de Goede
2016-10-14  7:53   ` [PATCH 4/6] misc: q8-hardwaremgr: Add rda599x wift/bt/fm radio combo detection Hans de Goede
2016-10-14  7:53     ` Hans de Goede
2016-10-14  7:53   ` [PATCH 5/6] misc: q8-hardwaremgr: Better touchscreen defaults based on heuristics Hans de Goede
2016-10-14  7:53     ` Hans de Goede
2016-10-14  7:53   ` [PATCH 6/6] misc: q8-hardwaremgr: Add quirk handling Hans de Goede
2016-10-14  7:53     ` Hans de Goede
2016-10-24 17:39   ` Add Allwinner Q8 tablets hardware manager Mark Rutland
2016-10-24 17:39     ` Mark Rutland
2016-10-26 11:46     ` Hans de Goede
2016-10-26 11:46       ` Hans de Goede
     [not found]       ` <CAJ-oXjQbOkrkNToEXYmPUZOgYBGbxQREZ4NL4bMcZmG=KP2vQQ@mail.gmail.com>
     [not found]         ` <CAJ-oXjQbOkrkNToEXYmPUZOgYBGbxQREZ4NL4bMcZmG=KP2vQQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-10-27  9:14           ` Hans de Goede
2016-10-27  9:14             ` Hans de Goede
2016-10-27 12:57             ` Pierre-Hugues Husson
2016-10-27 12:57               ` Pierre-Hugues Husson
2016-10-27 14:53               ` Hans de Goede
2016-10-27 14:53                 ` Hans de Goede
     [not found]                 ` <4cfdd415-1965-7be9-b204-86a9931683a6-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-27 16:27                   ` Pantelis Antoniou
2016-10-27 16:27                     ` Pantelis Antoniou
2016-10-27 17:31                   ` Pierre-Hugues Husson
2016-10-27 17:31                     ` Pierre-Hugues Husson
     [not found]                     ` <CAJ-oXjRJrs77yE-skpZ-V4e=rdhRyfNve9bibf1VOaZYy2=tRA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-10-27 21:15                       ` Hans de Goede
2016-10-27 21:15                         ` Hans de Goede
     [not found]       ` <4cfbedb2-0249-e881-3577-dda0b0d4cabe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-27 15:52         ` Pantelis Antoniou
2016-10-27 15:52           ` Pantelis Antoniou
     [not found]           ` <9B288597-7812-459D-A5C7-B61107751DA6-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
2016-10-27 16:59             ` Pierre-Hugues Husson
2016-10-27 16:59               ` Pierre-Hugues Husson
     [not found]               ` <CAJ-oXjT=eVwEk7t5WoZAhjMhiZZkq0NN5tFLidSnUNO97D62zQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-10-27 17:11                 ` Pantelis Antoniou
2016-10-27 17:11                   ` Pantelis Antoniou
     [not found]                   ` <D75CB7DE-4165-4D2F-B40B-D2B6875C0172-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
2016-10-27 19:04                     ` Pierre-Hugues Husson
2016-10-27 19:04                       ` Pierre-Hugues Husson
     [not found]                       ` <CAJ-oXjS_=k4qE25t2b9eNnuqvVHf-1g7CZr81pPJx==aftF4xw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-10-27 19:23                         ` Pantelis Antoniou
2016-10-27 19:23                           ` Pantelis Antoniou
2016-10-27 21:10             ` Hans de Goede
2016-10-27 21:10               ` Hans de Goede
2016-10-26 20:54     ` Rob Herring
2016-10-26 20:54       ` Rob Herring
2016-10-27  8:10       ` Pierre-Hugues Husson
2016-10-27  8:10         ` Pierre-Hugues Husson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.