From 8f6d162cda9972b4b3136b70abc8821dedc9a7cb Mon Sep 17 00:00:00 2001 From: Kevin Mihelich Date: Tue, 13 Mar 2018 00:38:59 +0000 Subject: [PATCH] core/linux-armv7-rc to 4.16.rc5-1 --- ...ags-add-support-for-Marvell-s-u-boot.patch | 6 +- ...trieve-MAC-addresses-from-Marvell-bo.patch | 8 +- .../0003-SMILE-Plug-device-tree-file.patch | 10 +- .../0004-fix-mvsdio-eMMC-timing.patch | 6 +- ...ow-mac-address-to-be-set-as-a-parame.patch | 7 +- ...-set-default-cubietruck-led-triggers.patch | 6 +- ...d-set-higher-minimum-buck2-regulator.patch | 10 +- .../0008-disable-USB3-port-on-ODROID-XU.patch | 10 +- ...9-ARM-dove-enable-ethernet-on-D3Plug.patch | 6 +- ...010-power-add-power-sequence-library.patch | 790 ++++++++++++++++++ ...er-sequence-handling-for-USB-devices.patch | 164 ++++ ...dl-Enable-usb-node-children-with-reg.patch | 49 ++ ...udoo.dtsi-fix-onboard-USB-HUB-proper.patch | 80 ++ ...imx6q-evi-Fix-onboard-hub-reset-line.patch | 74 ++ core/linux-armv7-rc/PKGBUILD | 41 +- core/linux-armv7-rc/config | 4 +- 16 files changed, 1223 insertions(+), 48 deletions(-) create mode 100644 core/linux-armv7-rc/0010-power-add-power-sequence-library.patch create mode 100644 core/linux-armv7-rc/0011-usb-core-add-power-sequence-handling-for-USB-devices.patch create mode 100644 core/linux-armv7-rc/0012-ARM-dts-imx6qdl-Enable-usb-node-children-with-reg.patch create mode 100644 core/linux-armv7-rc/0013-ARM-dts-imx6qdl-udoo.dtsi-fix-onboard-USB-HUB-proper.patch create mode 100644 core/linux-armv7-rc/0014-ARM-dts-imx6q-evi-Fix-onboard-hub-reset-line.patch diff --git a/core/linux-armv7-rc/0001-ARM-atags-add-support-for-Marvell-s-u-boot.patch b/core/linux-armv7-rc/0001-ARM-atags-add-support-for-Marvell-s-u-boot.patch index 44147d56d..472c394b5 100644 --- a/core/linux-armv7-rc/0001-ARM-atags-add-support-for-Marvell-s-u-boot.patch +++ b/core/linux-armv7-rc/0001-ARM-atags-add-support-for-Marvell-s-u-boot.patch @@ -1,7 +1,7 @@ -From 3d479a6cad6ee5f618ab002a35688ac33ef7b9ac Mon Sep 17 00:00:00 2001 +From cfaf96614497debcf1bc54ed9b4c45678eee282e Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 2 Dec 2012 19:59:28 +0100 -Subject: [PATCH 1/9] ARM: atags: add support for Marvell's u-boot +Subject: [PATCH 01/14] ARM: atags: add support for Marvell's u-boot Marvell uses a specific atag in its u-boot which includes among other information the MAC addresses for up to 4 network interfaces. @@ -47,5 +47,5 @@ index 6b335a9ff8c8..614150b53643 100644 }; -- -2.15.0 +2.16.2 diff --git a/core/linux-armv7-rc/0002-ARM-atags-fdt-retrieve-MAC-addresses-from-Marvell-bo.patch b/core/linux-armv7-rc/0002-ARM-atags-fdt-retrieve-MAC-addresses-from-Marvell-bo.patch index d4ea8ae81..c1e416d7e 100644 --- a/core/linux-armv7-rc/0002-ARM-atags-fdt-retrieve-MAC-addresses-from-Marvell-bo.patch +++ b/core/linux-armv7-rc/0002-ARM-atags-fdt-retrieve-MAC-addresses-from-Marvell-bo.patch @@ -1,8 +1,8 @@ -From 8ec093bead331ec76f615d82faeac4c0e9345a34 Mon Sep 17 00:00:00 2001 +From e47ba83e454cf97a7b3d33e5b5b625682ae1cd49 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 2 Dec 2012 19:56:58 +0100 -Subject: [PATCH 2/9] ARM: atags/fdt: retrieve MAC addresses from Marvell boot - loader +Subject: [PATCH 02/14] ARM: atags/fdt: retrieve MAC addresses from Marvell + boot loader The atags are parsed and if a Marvell atag is found, up to 4 MAC addresses are extracted there and assigned to node aliases eth0..3 @@ -43,5 +43,5 @@ index 41fa7316c52b..807ed160a4b9 100644 } -- -2.15.0 +2.16.2 diff --git a/core/linux-armv7-rc/0003-SMILE-Plug-device-tree-file.patch b/core/linux-armv7-rc/0003-SMILE-Plug-device-tree-file.patch index 244b6c619..f80c20393 100644 --- a/core/linux-armv7-rc/0003-SMILE-Plug-device-tree-file.patch +++ b/core/linux-armv7-rc/0003-SMILE-Plug-device-tree-file.patch @@ -1,7 +1,7 @@ -From 1db539cd4527e19bd48e08e5cb608373b3ccabd0 Mon Sep 17 00:00:00 2001 +From 51132fdfa4b66feb87499903f568132b7ec92785 Mon Sep 17 00:00:00 2001 From: Kevin Mihelich Date: Fri, 5 Sep 2014 15:41:19 -0600 -Subject: [PATCH 3/9] SMILE Plug device tree file +Subject: [PATCH 03/14] SMILE Plug device tree file This adds a dts file for the SMILE Plug, which only differs from the Mirabox dts with the LED definitions. @@ -14,10 +14,10 @@ Signed-off-by: Kevin Mihelich create mode 100644 arch/arm/boot/dts/armada-370-smileplug.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index d0381e9caf21..e142999e7cff 100644 +index ade7a38543dc..4bd5a6614e93 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile -@@ -1046,6 +1046,7 @@ dtb-$(CONFIG_MACH_ARMADA_370) += \ +@@ -1072,6 +1072,7 @@ dtb-$(CONFIG_MACH_ARMADA_370) += \ armada-370-db.dtb \ armada-370-dlink-dns327l.dtb \ armada-370-mirabox.dtb \ @@ -205,5 +205,5 @@ index 000000000000..d01308ab848b + }; +}; -- -2.15.0 +2.16.2 diff --git a/core/linux-armv7-rc/0004-fix-mvsdio-eMMC-timing.patch b/core/linux-armv7-rc/0004-fix-mvsdio-eMMC-timing.patch index 114698878..3cf45b89a 100644 --- a/core/linux-armv7-rc/0004-fix-mvsdio-eMMC-timing.patch +++ b/core/linux-armv7-rc/0004-fix-mvsdio-eMMC-timing.patch @@ -1,7 +1,7 @@ -From 854e80dbac1cb0a665dc856fdf918085d7d599ae Mon Sep 17 00:00:00 2001 +From ab62597d0e8a83ba11af33f294a58b4462e9369a Mon Sep 17 00:00:00 2001 From: Kevin Mihelich Date: Fri, 5 Sep 2014 15:43:56 -0600 -Subject: [PATCH 4/9] fix mvsdio eMMC timing +Subject: [PATCH 04/14] fix mvsdio eMMC timing These changes from Globalscale change the MMC timing to allow the eMMC versions of the Mirabox and SMILE Plug to work. @@ -34,5 +34,5 @@ index 210247b3d11a..1a1802dc9ef4 100644 host->clock = ios->clock; host->ns_per_clk = 1000000000 / (host->base_clock / (m+1)); -- -2.15.0 +2.16.2 diff --git a/core/linux-armv7-rc/0005-net-smsc95xx-Allow-mac-address-to-be-set-as-a-parame.patch b/core/linux-armv7-rc/0005-net-smsc95xx-Allow-mac-address-to-be-set-as-a-parame.patch index c47cbf2c2..8567d5630 100644 --- a/core/linux-armv7-rc/0005-net-smsc95xx-Allow-mac-address-to-be-set-as-a-parame.patch +++ b/core/linux-armv7-rc/0005-net-smsc95xx-Allow-mac-address-to-be-set-as-a-parame.patch @@ -1,7 +1,8 @@ -From 86bded5995f2dd4fab28d7b8d63a4caa4db107ed Mon Sep 17 00:00:00 2001 +From 8bb2616581e4e5aa7395bec730995629be259954 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 18 Feb 2014 01:43:50 -0300 -Subject: [PATCH 5/9] net/smsc95xx: Allow mac address to be set as a parameter +Subject: [PATCH 05/14] net/smsc95xx: Allow mac address to be set as a + parameter --- drivers/net/usb/smsc95xx.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ @@ -91,5 +92,5 @@ index 309b88acd3d0..7bc9feb891a1 100644 /* maybe the boot loader passed the MAC address in devicetree */ -- -2.15.0 +2.16.2 diff --git a/core/linux-armv7-rc/0006-set-default-cubietruck-led-triggers.patch b/core/linux-armv7-rc/0006-set-default-cubietruck-led-triggers.patch index 9e78cf6f6..0db11377c 100644 --- a/core/linux-armv7-rc/0006-set-default-cubietruck-led-triggers.patch +++ b/core/linux-armv7-rc/0006-set-default-cubietruck-led-triggers.patch @@ -1,7 +1,7 @@ -From 4b8a8edc859c1ce4131958c798fbfad5efff90dd Mon Sep 17 00:00:00 2001 +From 877e229054b1ecdcb350356475f2654e66c13288 Mon Sep 17 00:00:00 2001 From: Kevin Mihelich Date: Sat, 14 Feb 2015 12:32:27 +0100 -Subject: [PATCH 6/9] set default cubietruck led triggers +Subject: [PATCH 06/14] set default cubietruck led triggers Signed-off-by: Kevin Mihelich --- @@ -29,5 +29,5 @@ index 8c9bedc602ec..b3a765ba03fd 100644 }; -- -2.15.0 +2.16.2 diff --git a/core/linux-armv7-rc/0007-exynos4412-odroid-set-higher-minimum-buck2-regulator.patch b/core/linux-armv7-rc/0007-exynos4412-odroid-set-higher-minimum-buck2-regulator.patch index 30ca22378..c9c28889f 100644 --- a/core/linux-armv7-rc/0007-exynos4412-odroid-set-higher-minimum-buck2-regulator.patch +++ b/core/linux-armv7-rc/0007-exynos4412-odroid-set-higher-minimum-buck2-regulator.patch @@ -1,7 +1,7 @@ -From f11286dd3d8513aaa1bb98f4a5eb3b167b3156a1 Mon Sep 17 00:00:00 2001 +From 75c68a3a6868e6e0891e807b51249523bdfae611 Mon Sep 17 00:00:00 2001 From: Kevin Mihelich Date: Thu, 11 Aug 2016 00:42:37 -0600 -Subject: [PATCH 7/9] exynos4412-odroid: set higher minimum buck2 regulator +Subject: [PATCH 07/14] exynos4412-odroid: set higher minimum buck2 regulator voltage Set a higher minimum voltage to help reboot issue. @@ -13,10 +13,10 @@ Signed-off-by: Kevin Mihelich 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi -index a21be71000c1..65cdf0d9c512 100644 +index 556ea78b8e32..f3a3fe4af289 100644 --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi -@@ -421,7 +421,7 @@ +@@ -418,7 +418,7 @@ buck2_reg: BUCK2 { regulator-name = "vdd_arm"; @@ -26,5 +26,5 @@ index a21be71000c1..65cdf0d9c512 100644 regulator-always-on; regulator-boot-on; -- -2.15.0 +2.16.2 diff --git a/core/linux-armv7-rc/0008-disable-USB3-port-on-ODROID-XU.patch b/core/linux-armv7-rc/0008-disable-USB3-port-on-ODROID-XU.patch index 692591b3d..d02eb97a3 100644 --- a/core/linux-armv7-rc/0008-disable-USB3-port-on-ODROID-XU.patch +++ b/core/linux-armv7-rc/0008-disable-USB3-port-on-ODROID-XU.patch @@ -1,7 +1,7 @@ -From 7468a7c2c552024e2b243fe655b953e292cb111e Mon Sep 17 00:00:00 2001 +From 9a85fa9cf0ef8be764999f5df641c220467232b5 Mon Sep 17 00:00:00 2001 From: Kevin Mihelich Date: Sat, 25 Feb 2017 19:39:51 -0700 -Subject: [PATCH 8/9] disable USB3 port on ODROID-XU +Subject: [PATCH 08/14] disable USB3 port on ODROID-XU Ports report over-current condition and are non-operable. @@ -11,10 +11,10 @@ Signed-off-by: Kevin Mihelich 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/exynos5410-odroidxu.dts b/arch/arm/boot/dts/exynos5410-odroidxu.dts -index a45eaae33f8f..7f7de094724e 100644 +index a2046f5f998c..efc02014fa6c 100644 --- a/arch/arm/boot/dts/exynos5410-odroidxu.dts +++ b/arch/arm/boot/dts/exynos5410-odroidxu.dts -@@ -630,6 +630,7 @@ +@@ -627,6 +627,7 @@ &usbdrd_dwc3_0 { dr_mode = "host"; @@ -23,5 +23,5 @@ index a45eaae33f8f..7f7de094724e 100644 &usbdrd_dwc3_1 { -- -2.15.0 +2.16.2 diff --git a/core/linux-armv7-rc/0009-ARM-dove-enable-ethernet-on-D3Plug.patch b/core/linux-armv7-rc/0009-ARM-dove-enable-ethernet-on-D3Plug.patch index afd91bfb0..255a76d7f 100644 --- a/core/linux-armv7-rc/0009-ARM-dove-enable-ethernet-on-D3Plug.patch +++ b/core/linux-armv7-rc/0009-ARM-dove-enable-ethernet-on-D3Plug.patch @@ -1,7 +1,7 @@ -From ecfc4a9cba2d67cd44f9a66b0777d44dd711c498 Mon Sep 17 00:00:00 2001 +From d5da8eab317388c83c10f0726fe96192fc86de74 Mon Sep 17 00:00:00 2001 From: Kevin Mihelich Date: Sun, 7 May 2017 13:32:25 -0600 -Subject: [PATCH 9/9] ARM: dove: enable ethernet on D3Plug +Subject: [PATCH 09/14] ARM: dove: enable ethernet on D3Plug Signed-off-by: Kevin Mihelich --- @@ -27,5 +27,5 @@ index 826026c28f90..a4c9963e1261 100644 /* Samsung M8G2F eMMC */ &sdio0 { -- -2.15.0 +2.16.2 diff --git a/core/linux-armv7-rc/0010-power-add-power-sequence-library.patch b/core/linux-armv7-rc/0010-power-add-power-sequence-library.patch new file mode 100644 index 000000000..f48a56883 --- /dev/null +++ b/core/linux-armv7-rc/0010-power-add-power-sequence-library.patch @@ -0,0 +1,790 @@ +From 3817af7ecb4ca4e73a4f04ff5577bf5d92eb44ce Mon Sep 17 00:00:00 2001 +From: Peter Chen +Date: Wed, 21 Jun 2017 14:42:03 +0800 +Subject: [PATCH 10/14] power: add power sequence library + +We have an well-known problem that the device needs to do some power +sequence before it can be recognized by related host, the typical +example like hard-wired mmc devices and usb devices. + +This power sequence is hard to be described at device tree and handled by +related host driver, so we have created a common power sequence +library to cover this requirement. The core code has supplied +some common helpers for host driver, and individual power sequence +libraries handle kinds of power sequence for devices. The pwrseq +librares always need to allocate extra instance for compatible +string match. + +pwrseq_generic is intended for general purpose of power sequence, which +handles gpios and clocks currently, and can cover other controls in +future. The host driver just needs to call of_pwrseq_on/of_pwrseq_off +if only one power sequence is needed, else call of_pwrseq_on_list +/of_pwrseq_off_list instead (eg, USB hub driver). + +For new power sequence library, it needs to add its compatible string +and allocation function at pwrseq_match_table_list, then the pwrseq +core will match it with DT's, and choose this library at runtime. + +Signed-off-by: Peter Chen +Tested-by: Maciej S. Szmigiero +Tested-by Joshua Clayton +Reviewed-by: Matthias Kaehlcke +Tested-by: Matthias Kaehlcke +--- + Documentation/power/power-sequence/design.rst | 54 +++++ + MAINTAINERS | 9 + + drivers/power/Kconfig | 1 + + drivers/power/Makefile | 1 + + drivers/power/pwrseq/Kconfig | 20 ++ + drivers/power/pwrseq/Makefile | 2 + + drivers/power/pwrseq/core.c | 293 ++++++++++++++++++++++++++ + drivers/power/pwrseq/pwrseq_generic.c | 210 ++++++++++++++++++ + include/linux/power/pwrseq.h | 84 ++++++++ + 9 files changed, 674 insertions(+) + create mode 100644 Documentation/power/power-sequence/design.rst + create mode 100644 drivers/power/pwrseq/Kconfig + create mode 100644 drivers/power/pwrseq/Makefile + create mode 100644 drivers/power/pwrseq/core.c + create mode 100644 drivers/power/pwrseq/pwrseq_generic.c + create mode 100644 include/linux/power/pwrseq.h + +diff --git a/Documentation/power/power-sequence/design.rst b/Documentation/power/power-sequence/design.rst +new file mode 100644 +index 000000000000..554608e5f3b6 +--- /dev/null ++++ b/Documentation/power/power-sequence/design.rst +@@ -0,0 +1,54 @@ ++==================================== ++Power Sequence Library ++==================================== ++ ++:Date: Feb, 2017 ++:Author: Peter Chen ++ ++ ++Introduction ++============ ++ ++We have an well-known problem that the device needs to do a power ++sequence before it can be recognized by related host, the typical ++examples are hard-wired mmc devices and usb devices. The host controller ++can't know what kinds of this device is in its bus if the power ++sequence has not done, since the related devices driver's probe calling ++is determined by runtime according to eunumeration results. Besides, ++the devices may have custom power sequence, so the power sequence library ++which is independent with the devices is needed. ++ ++Design ++============ ++ ++The power sequence library includes the core file and customer power ++sequence library. The core file exports interfaces are called by ++host controller driver for power sequence and customer power sequence ++library files to register its power sequence instance to global ++power sequence list. The custom power sequence library creates power ++sequence instance and implement custom power sequence. ++ ++Since the power sequence describes hardware design, the description is ++located at board description file, eg, device tree dts file. And ++a specific power sequence belongs to device, so its description ++is under the device node, please refer to: ++Documentation/devicetree/bindings/power/pwrseq/pwrseq-generic.txt ++ ++Custom power sequence library allocates one power sequence instance at ++bootup periods using postcore_initcall, this static allocated instance is ++used to compare with device-tree (DT) node to see if this library can be ++used for the node or not. When the result is matched, the core API will ++try to get resourses (->get, implemented at each library) for power ++sequence, if all resources are got, it will try to allocate another ++instance for next possible request from host driver. ++ ++Then, the host controller driver can carry out power sequence on for this ++DT node, the library will do corresponding operations, like open clocks, ++toggle gpio, etc. The power sequence off routine will close and free the ++resources, and is called when the parent is removed. And the power ++sequence suspend and resume routine can be called at host driver's ++suspend and resume routine if needed. ++ ++The exported interfaces ++.. kernel-doc:: drivers/power/pwrseq/core.c ++ :export: +diff --git a/MAINTAINERS b/MAINTAINERS +index 4623caf8d72d..7569287f8b33 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -11086,6 +11086,15 @@ F: drivers/firmware/psci*.c + F: include/linux/psci.h + F: include/uapi/linux/psci.h + ++POWER SEQUENCE LIBRARY ++M: Peter Chen ++T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git ++L: linux-pm@vger.kernel.org ++S: Maintained ++F: Documentation/devicetree/bindings/power/pwrseq/ ++F: drivers/power/pwrseq/ ++F: include/linux/power/pwrseq.h ++ + POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS + M: Sebastian Reichel + L: linux-pm@vger.kernel.org +diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig +index 63454b5cac27..c1bb0465f956 100644 +--- a/drivers/power/Kconfig ++++ b/drivers/power/Kconfig +@@ -1,3 +1,4 @@ + source "drivers/power/avs/Kconfig" + source "drivers/power/reset/Kconfig" + source "drivers/power/supply/Kconfig" ++source "drivers/power/pwrseq/Kconfig" +diff --git a/drivers/power/Makefile b/drivers/power/Makefile +index ff35c712d824..7db80354b691 100644 +--- a/drivers/power/Makefile ++++ b/drivers/power/Makefile +@@ -1,3 +1,4 @@ + obj-$(CONFIG_POWER_AVS) += avs/ + obj-$(CONFIG_POWER_RESET) += reset/ + obj-$(CONFIG_POWER_SUPPLY) += supply/ ++obj-$(CONFIG_POWER_SEQUENCE) += pwrseq/ +diff --git a/drivers/power/pwrseq/Kconfig b/drivers/power/pwrseq/Kconfig +new file mode 100644 +index 000000000000..c6b356926cca +--- /dev/null ++++ b/drivers/power/pwrseq/Kconfig +@@ -0,0 +1,20 @@ ++# ++# Power Sequence library ++# ++ ++menuconfig POWER_SEQUENCE ++ bool "Power sequence control" ++ help ++ It is used for drivers which needs to do power sequence ++ (eg, turn on clock, toggle reset gpio) before the related ++ devices can be found by hardware, eg, USB bus. ++ ++if POWER_SEQUENCE ++ ++config PWRSEQ_GENERIC ++ bool "Generic power sequence control" ++ depends on OF ++ help ++ This is the generic power sequence control library, and is ++ supposed to support common power sequence usage. ++endif +diff --git a/drivers/power/pwrseq/Makefile b/drivers/power/pwrseq/Makefile +new file mode 100644 +index 000000000000..ad82389028c2 +--- /dev/null ++++ b/drivers/power/pwrseq/Makefile +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_POWER_SEQUENCE) += core.o ++obj-$(CONFIG_PWRSEQ_GENERIC) += pwrseq_generic.o +diff --git a/drivers/power/pwrseq/core.c b/drivers/power/pwrseq/core.c +new file mode 100644 +index 000000000000..6b78a6691683 +--- /dev/null ++++ b/drivers/power/pwrseq/core.c +@@ -0,0 +1,293 @@ ++/* ++ * core.c power sequence core file ++ * ++ * Copyright (C) 2016 Freescale Semiconductor, Inc. ++ * Author: Peter Chen ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 of ++ * the License as published by the Free Software Foundation. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * Static power sequence match table ++ * - Add compatible (the same with dts node) and related allocation function. ++ * - Update related binding doc. ++ */ ++static const struct of_device_id pwrseq_match_table_list[] = { ++ { .compatible = "usb424,2513", .data = &pwrseq_generic_alloc_instance}, ++ { .compatible = "usb424,2514", .data = &pwrseq_generic_alloc_instance}, ++ { /* sentinel */ } ++}; ++ ++static int pwrseq_get(struct device_node *np, struct pwrseq *p) ++{ ++ if (p && p->get) ++ return p->get(np, p); ++ ++ return -ENOTSUPP; ++} ++ ++static int pwrseq_on(struct pwrseq *p) ++{ ++ if (p && p->on) ++ return p->on(p); ++ ++ return -ENOTSUPP; ++} ++ ++static void pwrseq_off(struct pwrseq *p) ++{ ++ if (p && p->off) ++ p->off(p); ++} ++ ++static void pwrseq_put(struct pwrseq *p) ++{ ++ if (p && p->put) ++ p->put(p); ++} ++ ++/** ++ * of_pwrseq_on - Carry out power sequence on for device node ++ * ++ * @np: the device node would like to power on ++ * ++ * Carry out a single device power on. If multiple devices ++ * need to be handled, use of_pwrseq_on_list() instead. ++ * ++ * Return a pointer to the power sequence instance on success, or NULL if ++ * not exist, or an error code on failure. ++ */ ++struct pwrseq *of_pwrseq_on(struct device_node *np) ++{ ++ struct pwrseq *pwrseq; ++ int ret; ++ const struct of_device_id *of_id; ++ struct pwrseq *(*alloc_instance)(void); ++ ++ of_id = of_match_node(pwrseq_match_table_list, np); ++ if (!of_id) ++ return NULL; ++ ++ alloc_instance = of_id->data; ++ /* Allocate pwrseq instance */ ++ pwrseq = alloc_instance(); ++ if (IS_ERR(pwrseq)) ++ return pwrseq; ++ ++ ret = pwrseq_get(np, pwrseq); ++ if (ret) ++ goto pwr_put; ++ ++ ret = pwrseq_on(pwrseq); ++ if (ret) ++ goto pwr_put; ++ ++ return pwrseq; ++ ++pwr_put: ++ pwrseq_put(pwrseq); ++ return ERR_PTR(ret); ++} ++EXPORT_SYMBOL_GPL(of_pwrseq_on); ++ ++/** ++ * of_pwrseq_off - Carry out power sequence off for this pwrseq instance ++ * ++ * @pwrseq: the pwrseq instance which related device would like to be off ++ * ++ * This API is used to power off single device, it is the opposite ++ * operation for of_pwrseq_on. ++ */ ++void of_pwrseq_off(struct pwrseq *pwrseq) ++{ ++ pwrseq_off(pwrseq); ++ pwrseq_put(pwrseq); ++} ++EXPORT_SYMBOL_GPL(of_pwrseq_off); ++ ++/** ++ * of_pwrseq_on_list - Carry out power sequence on for list ++ * ++ * @np: the device node would like to power on ++ * @head: the list head for pwrseq list on this bus ++ * ++ * This API is used to power on multiple devices at single bus. ++ * If there are several devices on bus (eg, USB bus), uses this ++ * this API. Otherwise, use of_pwrseq_on instead. After the device ++ * is powered on successfully, it will be added to pwrseq list for ++ * this bus. The caller needs to use mutex_lock for concurrent. ++ * ++ * Return 0 on success, or -ENOENT if not exist, or an error value on failure. ++ */ ++int of_pwrseq_on_list(struct device_node *np, struct list_head *head) ++{ ++ struct pwrseq *pwrseq; ++ struct pwrseq_list_per_dev *pwrseq_list_node; ++ ++ pwrseq_list_node = kzalloc(sizeof(*pwrseq_list_node), GFP_KERNEL); ++ if (!pwrseq_list_node) ++ return -ENOMEM; ++ ++ pwrseq = of_pwrseq_on(np); ++ if (!pwrseq) ++ return -ENOENT; ++ ++ if (IS_ERR(pwrseq)) { ++ kfree(pwrseq_list_node); ++ return PTR_ERR(pwrseq); ++ } ++ ++ pwrseq_list_node->pwrseq = pwrseq; ++ list_add(&pwrseq_list_node->list, head); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(of_pwrseq_on_list); ++ ++/** ++ * of_pwrseq_off_list - Carry out power sequence off for the list ++ * ++ * @head: the list head for pwrseq instance list on this bus ++ * ++ * This API is used to power off all devices on this bus, it is ++ * the opposite operation for of_pwrseq_on_list. ++ * The caller needs to use mutex_lock for concurrent. ++ */ ++void of_pwrseq_off_list(struct list_head *head) ++{ ++ struct pwrseq *pwrseq; ++ struct pwrseq_list_per_dev *pwrseq_list_node, *tmp_node; ++ ++ list_for_each_entry_safe(pwrseq_list_node, tmp_node, head, list) { ++ pwrseq = pwrseq_list_node->pwrseq; ++ of_pwrseq_off(pwrseq); ++ list_del(&pwrseq_list_node->list); ++ kfree(pwrseq_list_node); ++ } ++} ++EXPORT_SYMBOL_GPL(of_pwrseq_off_list); ++ ++/** ++ * pwrseq_suspend - Carry out power sequence suspend for this pwrseq instance ++ * ++ * @pwrseq: the pwrseq instance ++ * ++ * This API is used to do suspend operation on pwrseq instance. ++ * ++ * Return 0 on success, or an error value otherwise. ++ */ ++int pwrseq_suspend(struct pwrseq *p) ++{ ++ int ret = 0; ++ ++ if (p && p->suspend) ++ ret = p->suspend(p); ++ else ++ return ret; ++ ++ if (!ret) ++ p->suspended = true; ++ else ++ pr_err("%s failed\n", __func__); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(pwrseq_suspend); ++ ++/** ++ * pwrseq_resume - Carry out power sequence resume for this pwrseq instance ++ * ++ * @pwrseq: the pwrseq instance ++ * ++ * This API is used to do resume operation on pwrseq instance. ++ * ++ * Return 0 on success, or an error value otherwise. ++ */ ++int pwrseq_resume(struct pwrseq *p) ++{ ++ int ret = 0; ++ ++ if (p && p->resume) ++ ret = p->resume(p); ++ else ++ return ret; ++ ++ if (!ret) ++ p->suspended = false; ++ else ++ pr_err("%s failed\n", __func__); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(pwrseq_resume); ++ ++/** ++ * pwrseq_suspend_list - Carry out power sequence suspend for list ++ * ++ * @head: the list head for pwrseq instance list on this bus ++ * ++ * This API is used to do suspend on all power sequence instances on this bus. ++ * The caller needs to use mutex_lock for concurrent. ++ */ ++int pwrseq_suspend_list(struct list_head *head) ++{ ++ struct pwrseq *pwrseq; ++ struct pwrseq_list_per_dev *pwrseq_list_node; ++ int ret = 0; ++ ++ list_for_each_entry(pwrseq_list_node, head, list) { ++ ret = pwrseq_suspend(pwrseq_list_node->pwrseq); ++ if (ret) ++ break; ++ } ++ ++ if (ret) { ++ list_for_each_entry(pwrseq_list_node, head, list) { ++ pwrseq = pwrseq_list_node->pwrseq; ++ if (pwrseq->suspended) ++ pwrseq_resume(pwrseq); ++ } ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(pwrseq_suspend_list); ++ ++/** ++ * pwrseq_resume_list - Carry out power sequence resume for the list ++ * ++ * @head: the list head for pwrseq instance list on this bus ++ * ++ * This API is used to do resume on all power sequence instances on this bus. ++ * The caller needs to use mutex_lock for concurrent. ++ */ ++int pwrseq_resume_list(struct list_head *head) ++{ ++ struct pwrseq_list_per_dev *pwrseq_list_node; ++ int ret = 0; ++ ++ list_for_each_entry(pwrseq_list_node, head, list) { ++ ret = pwrseq_resume(pwrseq_list_node->pwrseq); ++ if (ret) ++ break; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(pwrseq_resume_list); +diff --git a/drivers/power/pwrseq/pwrseq_generic.c b/drivers/power/pwrseq/pwrseq_generic.c +new file mode 100644 +index 000000000000..b7bbd6c5b47d +--- /dev/null ++++ b/drivers/power/pwrseq/pwrseq_generic.c +@@ -0,0 +1,210 @@ ++/* ++ * pwrseq_generic.c Generic power sequence handling ++ * ++ * Copyright (C) 2016 Freescale Semiconductor, Inc. ++ * Author: Peter Chen ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 of ++ * the License as published by the Free Software Foundation. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++struct pwrseq_generic { ++ struct pwrseq pwrseq; ++ struct gpio_desc *gpiod_reset; ++ struct clk *clks[PWRSEQ_MAX_CLKS]; ++ u32 duration_us; ++ bool suspended; ++}; ++ ++#define to_generic_pwrseq(p) container_of(p, struct pwrseq_generic, pwrseq) ++ ++static int pwrseq_generic_suspend(struct pwrseq *pwrseq) ++{ ++ struct pwrseq_generic *pwrseq_gen = to_generic_pwrseq(pwrseq); ++ int clk; ++ ++ for (clk = PWRSEQ_MAX_CLKS - 1; clk >= 0; clk--) ++ clk_disable_unprepare(pwrseq_gen->clks[clk]); ++ ++ pwrseq_gen->suspended = true; ++ return 0; ++} ++ ++static int pwrseq_generic_resume(struct pwrseq *pwrseq) ++{ ++ struct pwrseq_generic *pwrseq_gen = to_generic_pwrseq(pwrseq); ++ int clk, ret = 0; ++ ++ for (clk = 0; clk < PWRSEQ_MAX_CLKS && pwrseq_gen->clks[clk]; clk++) { ++ ret = clk_prepare_enable(pwrseq_gen->clks[clk]); ++ if (ret) { ++ pr_err("Can't enable clock, ret=%d\n", ret); ++ goto err_disable_clks; ++ } ++ } ++ ++ pwrseq_gen->suspended = false; ++ return ret; ++ ++err_disable_clks: ++ while (--clk >= 0) ++ clk_disable_unprepare(pwrseq_gen->clks[clk]); ++ ++ return ret; ++} ++ ++static void pwrseq_generic_put(struct pwrseq *pwrseq) ++{ ++ struct pwrseq_generic *pwrseq_gen = to_generic_pwrseq(pwrseq); ++ int clk; ++ ++ if (pwrseq_gen->gpiod_reset) ++ gpiod_put(pwrseq_gen->gpiod_reset); ++ ++ for (clk = 0; clk < PWRSEQ_MAX_CLKS; clk++) ++ clk_put(pwrseq_gen->clks[clk]); ++ ++ kfree(pwrseq_gen); ++} ++ ++static void pwrseq_generic_off(struct pwrseq *pwrseq) ++{ ++ struct pwrseq_generic *pwrseq_gen = to_generic_pwrseq(pwrseq); ++ int clk; ++ ++ if (pwrseq_gen->suspended) ++ return; ++ ++ for (clk = PWRSEQ_MAX_CLKS - 1; clk >= 0; clk--) ++ clk_disable_unprepare(pwrseq_gen->clks[clk]); ++} ++ ++static int pwrseq_generic_on(struct pwrseq *pwrseq) ++{ ++ struct pwrseq_generic *pwrseq_gen = to_generic_pwrseq(pwrseq); ++ int clk, ret = 0; ++ struct gpio_desc *gpiod_reset = pwrseq_gen->gpiod_reset; ++ ++ for (clk = 0; clk < PWRSEQ_MAX_CLKS && pwrseq_gen->clks[clk]; clk++) { ++ ret = clk_prepare_enable(pwrseq_gen->clks[clk]); ++ if (ret) { ++ pr_err("Can't enable clock, ret=%d\n", ret); ++ goto err_disable_clks; ++ } ++ } ++ ++ if (gpiod_reset) { ++ u32 duration_us = pwrseq_gen->duration_us; ++ ++ if (duration_us <= 10) ++ udelay(10); ++ else ++ usleep_range(duration_us, duration_us + 100); ++ gpiod_set_value(gpiod_reset, 0); ++ } ++ ++ return ret; ++ ++err_disable_clks: ++ while (--clk >= 0) ++ clk_disable_unprepare(pwrseq_gen->clks[clk]); ++ ++ return ret; ++} ++ ++static int pwrseq_generic_get(struct device_node *np, struct pwrseq *pwrseq) ++{ ++ struct pwrseq_generic *pwrseq_gen = to_generic_pwrseq(pwrseq); ++ enum of_gpio_flags flags; ++ int reset_gpio, clk, ret = 0; ++ ++ for (clk = 0; clk < PWRSEQ_MAX_CLKS; clk++) { ++ pwrseq_gen->clks[clk] = of_clk_get(np, clk); ++ if (IS_ERR(pwrseq_gen->clks[clk])) { ++ ret = PTR_ERR(pwrseq_gen->clks[clk]); ++ if (ret != -ENOENT) ++ goto err_put_clks; ++ pwrseq_gen->clks[clk] = NULL; ++ break; ++ } ++ } ++ ++ reset_gpio = of_get_named_gpio_flags(np, "reset-gpios", 0, &flags); ++ if (gpio_is_valid(reset_gpio)) { ++ unsigned long gpio_flags; ++ ++ if (flags & OF_GPIO_ACTIVE_LOW) ++ gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_LOW; ++ else ++ gpio_flags = GPIOF_OUT_INIT_HIGH; ++ ++ ret = gpio_request_one(reset_gpio, gpio_flags, ++ "pwrseq-reset-gpios"); ++ if (ret) ++ goto err_put_clks; ++ ++ pwrseq_gen->gpiod_reset = gpio_to_desc(reset_gpio); ++ of_property_read_u32(np, "reset-duration-us", ++ &pwrseq_gen->duration_us); ++ } else if (reset_gpio == -ENOENT) { ++ ; /* no such gpio */ ++ } else { ++ ret = reset_gpio; ++ pr_err("Failed to get reset gpio on %s, err = %d\n", ++ np->full_name, reset_gpio); ++ goto err_put_clks; ++ } ++ ++ return 0; ++ ++err_put_clks: ++ while (--clk >= 0) ++ clk_put(pwrseq_gen->clks[clk]); ++ return ret; ++} ++ ++/** ++ * pwrseq_generic_alloc_instance - power sequence instance allocation ++ * ++ * This function is used to allocate one generic power sequence instance, ++ * it is called when the system boots up and after one power sequence ++ * instance is got successfully. ++ * ++ * Return zero on success or an error code otherwise. ++ */ ++struct pwrseq *pwrseq_generic_alloc_instance(void) ++{ ++ struct pwrseq_generic *pwrseq_gen; ++ ++ pwrseq_gen = kzalloc(sizeof(*pwrseq_gen), GFP_KERNEL); ++ if (!pwrseq_gen) ++ return ERR_PTR(-ENOMEM); ++ ++ pwrseq_gen->pwrseq.get = pwrseq_generic_get; ++ pwrseq_gen->pwrseq.on = pwrseq_generic_on; ++ pwrseq_gen->pwrseq.off = pwrseq_generic_off; ++ pwrseq_gen->pwrseq.put = pwrseq_generic_put; ++ pwrseq_gen->pwrseq.suspend = pwrseq_generic_suspend; ++ pwrseq_gen->pwrseq.resume = pwrseq_generic_resume; ++ ++ return &pwrseq_gen->pwrseq; ++} +diff --git a/include/linux/power/pwrseq.h b/include/linux/power/pwrseq.h +new file mode 100644 +index 000000000000..c5b278f5f2ae +--- /dev/null ++++ b/include/linux/power/pwrseq.h +@@ -0,0 +1,84 @@ ++#ifndef __LINUX_PWRSEQ_H ++#define __LINUX_PWRSEQ_H ++ ++#include ++ ++#define PWRSEQ_MAX_CLKS 3 ++ ++/** ++ * struct pwrseq - the power sequence structure ++ * @pwrseq_of_match_table: the OF device id table this pwrseq library supports ++ * @node: the list pointer to be added to pwrseq list ++ * @get: the API is used to get pwrseq instance from the device node ++ * @on: do power on for this pwrseq instance ++ * @off: do power off for this pwrseq instance ++ * @put: release the resources on this pwrseq instance ++ * @suspend: do suspend operation on this pwrseq instance ++ * @resume: do resume operation on this pwrseq instance ++ */ ++struct pwrseq { ++ const struct of_device_id *pwrseq_of_match_table; ++ struct list_head node; ++ int (*get)(struct device_node *np, struct pwrseq *p); ++ int (*on)(struct pwrseq *p); ++ void (*off)(struct pwrseq *p); ++ void (*put)(struct pwrseq *p); ++ int (*suspend)(struct pwrseq *p); ++ int (*resume)(struct pwrseq *p); ++ bool suspended; ++}; ++ ++/* used for power sequence instance list in one driver */ ++struct pwrseq_list_per_dev { ++ struct pwrseq *pwrseq; ++ struct list_head list; ++}; ++ ++#if IS_ENABLED(CONFIG_POWER_SEQUENCE) ++struct pwrseq *of_pwrseq_on(struct device_node *np); ++void of_pwrseq_off(struct pwrseq *pwrseq); ++int of_pwrseq_on_list(struct device_node *np, struct list_head *head); ++void of_pwrseq_off_list(struct list_head *head); ++int pwrseq_suspend(struct pwrseq *p); ++int pwrseq_resume(struct pwrseq *p); ++int pwrseq_suspend_list(struct list_head *head); ++int pwrseq_resume_list(struct list_head *head); ++#else ++static inline struct pwrseq *of_pwrseq_on(struct device_node *np) ++{ ++ return NULL; ++} ++static void of_pwrseq_off(struct pwrseq *pwrseq) {} ++static int of_pwrseq_on_list(struct device_node *np, struct list_head *head) ++{ ++ return 0; ++} ++static void of_pwrseq_off_list(struct list_head *head) {} ++static int pwrseq_suspend(struct pwrseq *p) ++{ ++ return 0; ++} ++static int pwrseq_resume(struct pwrseq *p) ++{ ++ return 0; ++} ++static int pwrseq_suspend_list(struct list_head *head) ++{ ++ return 0; ++} ++static int pwrseq_resume_list(struct list_head *head) ++{ ++ return 0; ++} ++#endif /* CONFIG_POWER_SEQUENCE */ ++ ++#if IS_ENABLED(CONFIG_PWRSEQ_GENERIC) ++extern struct pwrseq *pwrseq_generic_alloc_instance(void); ++#else ++static inline struct pwrseq *pwrseq_generic_alloc_instance(void) ++{ ++ return ERR_PTR(-ENOTSUPP); ++} ++#endif /* CONFIG_PWRSEQ_GENERIC */ ++ ++#endif /* __LINUX_PWRSEQ_H */ +-- +2.16.2 + diff --git a/core/linux-armv7-rc/0011-usb-core-add-power-sequence-handling-for-USB-devices.patch b/core/linux-armv7-rc/0011-usb-core-add-power-sequence-handling-for-USB-devices.patch new file mode 100644 index 000000000..a0f0ab9b5 --- /dev/null +++ b/core/linux-armv7-rc/0011-usb-core-add-power-sequence-handling-for-USB-devices.patch @@ -0,0 +1,164 @@ +From c858d0c22e0e345c0d5659435c2393772ddfec7a Mon Sep 17 00:00:00 2001 +From: Peter Chen +Date: Wed, 21 Jun 2017 14:42:05 +0800 +Subject: [PATCH 11/14] usb: core: add power sequence handling for USB devices + +Some hard-wired USB devices need to do power sequence to let the +device work normally, the typical power sequence like: enable USB +PHY clock, toggle reset pin, etc. But current Linux USB driver +lacks of such code to do it, it may cause some hard-wired USB devices +works abnormal or can't be recognized by controller at all. + +In this patch, it calls power sequence library APIs to finish +the power sequence events. It will do power on sequence at hub's +probe for all devices under this hub (includes root hub). +At hub_disconnect, it will do power off sequence which is at powered +on list. + +Signed-off-by: Peter Chen +Tested-by Joshua Clayton +Tested-by: Maciej S. Szmigiero +Reviewed-by: Vaibhav Hiremath +Acked-by: Alan Stern +--- + drivers/usb/Kconfig | 1 + + drivers/usb/core/hub.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---- + drivers/usb/core/hub.h | 1 + + 3 files changed, 47 insertions(+), 4 deletions(-) + +diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig +index 148f3ee70286..575a866422be 100644 +--- a/drivers/usb/Kconfig ++++ b/drivers/usb/Kconfig +@@ -45,6 +45,7 @@ config USB + tristate "Support for Host-side USB" + depends on USB_ARCH_HAS_HCD + select USB_COMMON ++ select POWER_SEQUENCE + select NLS # for UTF-8 strings + ---help--- + Universal Serial Bus (USB) is a specification for a serial bus +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index c5c1f6cf3228..a7de648c3f76 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -1649,6 +1650,7 @@ static void hub_disconnect(struct usb_interface *intf) + hub->error = 0; + hub_quiesce(hub, HUB_DISCONNECT); + ++ of_pwrseq_off_list(&hub->pwrseq_list); + mutex_lock(&usb_port_peer_mutex); + + /* Avoid races with recursively_mark_NOTATTACHED() */ +@@ -1695,11 +1697,41 @@ static bool hub_descriptor_is_sane(struct usb_host_interface *desc) + return true; + } + ++#ifdef CONFIG_OF ++static int hub_of_pwrseq_on(struct usb_hub *hub) ++{ ++ struct device *parent; ++ struct usb_device *hdev = hub->hdev; ++ struct device_node *np; ++ int ret; ++ ++ if (hdev->parent) ++ parent = &hdev->dev; ++ else ++ parent = bus_to_hcd(hdev->bus)->self.sysdev; ++ ++ for_each_child_of_node(parent->of_node, np) { ++ ret = of_pwrseq_on_list(np, &hub->pwrseq_list); ++ /* Maybe no power sequence library is chosen */ ++ if (ret && ret != -ENOENT) ++ return ret; ++ } ++ ++ return 0; ++} ++#else ++static int hub_of_pwrseq_on(struct usb_hub *hub) ++{ ++ return 0; ++} ++#endif ++ + static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) + { + struct usb_host_interface *desc; + struct usb_device *hdev; + struct usb_hub *hub; ++ int ret = -ENODEV; + + desc = intf->cur_altsetting; + hdev = interface_to_usbdev(intf); +@@ -1790,6 +1822,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) + INIT_DELAYED_WORK(&hub->leds, led_work); + INIT_DELAYED_WORK(&hub->init_work, NULL); + INIT_WORK(&hub->events, hub_event); ++ INIT_LIST_HEAD(&hub->pwrseq_list); + usb_get_intf(intf); + usb_get_dev(hdev); + +@@ -1803,11 +1836,14 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) + if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND) + hub->quirk_check_port_auto_suspend = 1; + +- if (hub_configure(hub, &desc->endpoint[0].desc) >= 0) +- return 0; ++ if (hub_configure(hub, &desc->endpoint[0].desc) >= 0) { ++ ret = hub_of_pwrseq_on(hub); ++ if (!ret) ++ return 0; ++ } + + hub_disconnect(intf); +- return -ENODEV; ++ return ret; + } + + static int +@@ -3621,14 +3657,19 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) + + /* stop hub_wq and related activity */ + hub_quiesce(hub, HUB_SUSPEND); +- return 0; ++ return pwrseq_suspend_list(&hub->pwrseq_list); + } + + static int hub_resume(struct usb_interface *intf) + { + struct usb_hub *hub = usb_get_intfdata(intf); ++ int ret; + + dev_dbg(&intf->dev, "%s\n", __func__); ++ ret = pwrseq_resume_list(&hub->pwrseq_list); ++ if (ret) ++ return ret; ++ + hub_activate(hub, HUB_RESUME); + return 0; + } +diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h +index 2a700ccc868c..3a0e6e6b22b0 100644 +--- a/drivers/usb/core/hub.h ++++ b/drivers/usb/core/hub.h +@@ -70,6 +70,7 @@ struct usb_hub { + struct delayed_work init_work; + struct work_struct events; + struct usb_port **ports; ++ struct list_head pwrseq_list; /* powered pwrseq node list */ + }; + + /** +-- +2.16.2 + diff --git a/core/linux-armv7-rc/0012-ARM-dts-imx6qdl-Enable-usb-node-children-with-reg.patch b/core/linux-armv7-rc/0012-ARM-dts-imx6qdl-Enable-usb-node-children-with-reg.patch new file mode 100644 index 000000000..7ada9ac4a --- /dev/null +++ b/core/linux-armv7-rc/0012-ARM-dts-imx6qdl-Enable-usb-node-children-with-reg.patch @@ -0,0 +1,49 @@ +From 817d706c93a52c710a10c9f8219943d01f3716d9 Mon Sep 17 00:00:00 2001 +From: Joshua Clayton +Date: Wed, 21 Jun 2017 14:42:06 +0800 +Subject: [PATCH 12/14] ARM: dts: imx6qdl: Enable usb node children with + +Give usb nodes #address and #size attributes, so that a child node +representing a permanently connected device such as an onboard hub may +be addressed with a attribute + +Signed-off-by: Joshua Clayton +Signed-off-by: Peter Chen +--- + arch/arm/boot/dts/imx6qdl.dtsi | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi +index 59ff86695a14..a4957bf2a82f 100644 +--- a/arch/arm/boot/dts/imx6qdl.dtsi ++++ b/arch/arm/boot/dts/imx6qdl.dtsi +@@ -983,6 +983,8 @@ + + usbh1: usb@2184200 { + compatible = "fsl,imx6q-usb", "fsl,imx27-usb"; ++ #address-cells = <1>; ++ #size-cells = <0>; + reg = <0x02184200 0x200>; + interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6QDL_CLK_USBOH3>; +@@ -997,6 +999,8 @@ + + usbh2: usb@2184400 { + compatible = "fsl,imx6q-usb", "fsl,imx27-usb"; ++ #address-cells = <1>; ++ #size-cells = <0>; + reg = <0x02184400 0x200>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6QDL_CLK_USBOH3>; +@@ -1010,6 +1014,8 @@ + + usbh3: usb@2184600 { + compatible = "fsl,imx6q-usb", "fsl,imx27-usb"; ++ #address-cells = <1>; ++ #size-cells = <0>; + reg = <0x02184600 0x200>; + interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6QDL_CLK_USBOH3>; +-- +2.16.2 + diff --git a/core/linux-armv7-rc/0013-ARM-dts-imx6qdl-udoo.dtsi-fix-onboard-USB-HUB-proper.patch b/core/linux-armv7-rc/0013-ARM-dts-imx6qdl-udoo.dtsi-fix-onboard-USB-HUB-proper.patch new file mode 100644 index 000000000..be2897af1 --- /dev/null +++ b/core/linux-armv7-rc/0013-ARM-dts-imx6qdl-udoo.dtsi-fix-onboard-USB-HUB-proper.patch @@ -0,0 +1,80 @@ +From 3609fea57f0de5b7361a4c7532cfa81591c4d773 Mon Sep 17 00:00:00 2001 +From: Peter Chen +Date: Wed, 21 Jun 2017 14:42:07 +0800 +Subject: [PATCH 13/14] ARM: dts: imx6qdl-udoo.dtsi: fix onboard USB HUB + property + +The current dts describes USB HUB's property at USB controller's +entry, it is improper. The USB HUB should be the child node +under USB controller, and power sequence properties are under +it. Besides, using gpio pinctrl setting for USB2415's reset pin. + +Signed-off-by: Peter Chen +Signed-off-by: Joshua Clayton +Tested-by: Maciej S. Szmigiero +--- + arch/arm/boot/dts/imx6qdl-udoo.dtsi | 26 ++++++++++++-------------- + 1 file changed, 12 insertions(+), 14 deletions(-) + +diff --git a/arch/arm/boot/dts/imx6qdl-udoo.dtsi b/arch/arm/boot/dts/imx6qdl-udoo.dtsi +index 4161b7d4323a..442a6d69ede8 100644 +--- a/arch/arm/boot/dts/imx6qdl-udoo.dtsi ++++ b/arch/arm/boot/dts/imx6qdl-udoo.dtsi +@@ -9,6 +9,8 @@ + * + */ + ++#include ++ + / { + aliases { + backlight = &backlight; +@@ -65,17 +67,6 @@ + #address-cells = <1>; + #size-cells = <0>; + +- reg_usb_h1_vbus: regulator@0 { +- compatible = "regulator-fixed"; +- reg = <0>; +- regulator-name = "usb_h1_vbus"; +- regulator-min-microvolt = <5000000>; +- regulator-max-microvolt = <5000000>; +- enable-active-high; +- startup-delay-us = <2>; /* USB2415 requires a POR of 1 us minimum */ +- gpio = <&gpio7 12 0>; +- }; +- + reg_panel: regulator@1 { + compatible = "regulator-fixed"; + reg = <1>; +@@ -201,7 +192,7 @@ + + pinctrl_usbh: usbhgrp { + fsl,pins = < +- MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 ++ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b0b0 + MX6QDL_PAD_NANDF_CS2__CCM_CLKO2 0x130b0 + >; + }; +@@ -272,9 +263,16 @@ + &usbh1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbh>; +- vbus-supply = <®_usb_h1_vbus>; +- clocks = <&clks IMX6QDL_CLK_CKO>; + status = "okay"; ++ ++ usb2415: hub@1 { ++ compatible = "usb424,2514"; ++ reg = <1>; ++ ++ clocks = <&clks IMX6QDL_CLK_CKO>; ++ reset-gpios = <&gpio7 12 GPIO_ACTIVE_LOW>; ++ reset-duration-us = <3000>; ++ }; + }; + + &usdhc3 { +-- +2.16.2 + diff --git a/core/linux-armv7-rc/0014-ARM-dts-imx6q-evi-Fix-onboard-hub-reset-line.patch b/core/linux-armv7-rc/0014-ARM-dts-imx6q-evi-Fix-onboard-hub-reset-line.patch new file mode 100644 index 000000000..9466ed524 --- /dev/null +++ b/core/linux-armv7-rc/0014-ARM-dts-imx6q-evi-Fix-onboard-hub-reset-line.patch @@ -0,0 +1,74 @@ +From 5388af518978d7cb99e142930fce4b6e7f515862 Mon Sep 17 00:00:00 2001 +From: Joshua Clayton +Date: Wed, 21 Jun 2017 14:42:08 +0800 +Subject: [PATCH 14/14] ARM: dts: imx6q-evi: Fix onboard hub reset line + +Previously the onboard hub was made to work by treating its +reset gpio as a regulator enable. +Get rid of that kludge now that pwseq has added reset gpio support +Move pin muxing the hub reset pin into the usbh1 group + +Signed-off-by: Joshua Clayton +Signed-off-by: Peter Chen +--- + arch/arm/boot/dts/imx6q-evi.dts | 25 +++++++------------------ + 1 file changed, 7 insertions(+), 18 deletions(-) + +diff --git a/arch/arm/boot/dts/imx6q-evi.dts b/arch/arm/boot/dts/imx6q-evi.dts +index e0aea782c666..6f3afffc8faa 100644 +--- a/arch/arm/boot/dts/imx6q-evi.dts ++++ b/arch/arm/boot/dts/imx6q-evi.dts +@@ -54,18 +54,6 @@ + reg = <0x10000000 0x40000000>; + }; + +- reg_usbh1_vbus: regulator-usbhubreset { +- compatible = "regulator-fixed"; +- regulator-name = "usbh1_vbus"; +- regulator-min-microvolt = <5000000>; +- regulator-max-microvolt = <5000000>; +- enable-active-high; +- startup-delay-us = <2>; +- pinctrl-names = "default"; +- pinctrl-0 = <&pinctrl_usbh1_hubreset>; +- gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>; +- }; +- + reg_usb_otg_vbus: regulator-usbotgvbus { + compatible = "regulator-fixed"; + regulator-name = "usb_otg_vbus"; +@@ -213,12 +201,18 @@ + }; + + &usbh1 { +- vbus-supply = <®_usbh1_vbus>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbh1>; + dr_mode = "host"; + disable-over-current; + status = "okay"; ++ ++ usb2415host: hub@1 { ++ compatible = "usb424,2513"; ++ reg = <1>; ++ reset-gpios = <&gpio7 12 GPIO_ACTIVE_LOW>; ++ reset-duration-us = <3000>; ++ }; + }; + + &usbotg { +@@ -481,11 +475,6 @@ + MX6QDL_PAD_GPIO_3__USB_H1_OC 0x1b0b0 + /* usbh1_b OC */ + MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0 +- >; +- }; +- +- pinctrl_usbh1_hubreset: usbh1hubresetgrp { +- fsl,pins = < + MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b0b0 + >; + }; +-- +2.16.2 + diff --git a/core/linux-armv7-rc/PKGBUILD b/core/linux-armv7-rc/PKGBUILD index a6ededa6a..e71f78a91 100644 --- a/core/linux-armv7-rc/PKGBUILD +++ b/core/linux-armv7-rc/PKGBUILD @@ -4,7 +4,7 @@ buildarch=4 _rcver=4.16 -_rcrel=4 +_rcrel=5 _rcnrel=armv7-x0 pkgbase=linux-armv7-rc @@ -29,24 +29,34 @@ source=("https://git.kernel.org/torvalds/t/${_srcname}.tar.gz" '0007-exynos4412-odroid-set-higher-minimum-buck2-regulator.patch' '0008-disable-USB3-port-on-ODROID-XU.patch' '0009-ARM-dove-enable-ethernet-on-D3Plug.patch' + '0010-power-add-power-sequence-library.patch' + '0011-usb-core-add-power-sequence-handling-for-USB-devices.patch' + '0012-ARM-dts-imx6qdl-Enable-usb-node-children-with-reg.patch' + '0013-ARM-dts-imx6qdl-udoo.dtsi-fix-onboard-USB-HUB-proper.patch' + '0014-ARM-dts-imx6q-evi-Fix-onboard-hub-reset-line.patch' 'config' 'kernel.its' 'kernel.keyblock' 'kernel_data_key.vbprivk' 'linux.preset' '99-linux.hook') -md5sums=('963a757f2efaf80fc851c95fd141cc19' - 'af5110db66c1d39139064927a807a0d8' - '7fe0862ef33a0c05a7cfc586a4f1dfe1' - '6a4f027a2558741fa932b2bbc0de27eb' - 'd5759bba814aaf3fe0ec4d230cca28e9' - '2bb3aff035d47e86654c4e17cf8b220a' - '1681a4a5f47477ab6e02b0f17021482f' - '13878f989bf23cf92ec3136121948fa4' - '3ae78bd2c88a5beaf85d3f9ff53289d0' - 'd7aee2b9e035fbc7e8ed2142251cba05' - 'ce8d5eed57e2841ae3021dd375b9ca8a' - 'c1fdc1a3cac57edee6cd177f7ad9ebbd' +md5sums=('2ca30f78f9bb36ef7999d64748671a96' + '22b8634a5615366f0e7b984e8edd206a' + 'a5cc265aa1828fa0c1bc232e120840c1' + '77406a7abd87c218e1f56936c89081b6' + '378bfcee7a20b4197151431ed3bb68f3' + 'e077ad92226ccabee1d6ff269477714d' + '725c5979f93698370901fed2d98844b3' + 'de18b694f5e66fffafb126aeb54430aa' + 'a9e89dba6435e61a18fd31628f0f6c54' + '66d29d01e77052bd73bc2afdb2ec67b3' + 'c47442cdd494a931f63c0d243a114c90' + '9e56e2d9aa0f9dc3335529a36e8e5a31' + '4ac71ad4e96bbf59126c14f490039864' + 'b5294786095a75de4cc6ec4aed12d96e' + '6e35fc341ed114fbe785ec204cec9525' + '3293d4da6b2629f9ebb9738c56ccba08' + 'f45ffbfe89218af75d8fbed1f920fe16' '4f2379ed84258050edb858ee8d281678' '61c5ff73c136ed07a7aadbf58db3d96a' '584777ae88bce2c5659960151b64c7d8' @@ -70,6 +80,11 @@ prepare() { git apply ../0007-exynos4412-odroid-set-higher-minimum-buck2-regulator.patch git apply ../0008-disable-USB3-port-on-ODROID-XU.patch git apply ../0009-ARM-dove-enable-ethernet-on-D3Plug.patch + git apply ../0010-power-add-power-sequence-library.patch + git apply ../0011-usb-core-add-power-sequence-handling-for-USB-devices.patch + git apply ../0012-ARM-dts-imx6qdl-Enable-usb-node-children-with-reg.patch + git apply ../0013-ARM-dts-imx6qdl-udoo.dtsi-fix-onboard-USB-HUB-proper.patch + git apply ../0014-ARM-dts-imx6q-evi-Fix-onboard-hub-reset-line.patch cat "${srcdir}/config" > ./.config diff --git a/core/linux-armv7-rc/config b/core/linux-armv7-rc/config index 52087dbe6..25919ec25 100644 --- a/core/linux-armv7-rc/config +++ b/core/linux-armv7-rc/config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 4.16.0-rc4-1 Kernel Configuration +# Linux/arm 4.16.0-rc4-2 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -4124,6 +4124,8 @@ CONFIG_CHARGER_TPS65090=m # CONFIG_CHARGER_TPS65217 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set # CONFIG_CHARGER_RT9455 is not set +CONFIG_POWER_SEQUENCE=y +CONFIG_PWRSEQ_GENERIC=y CONFIG_HWMON=y CONFIG_HWMON_VID=m # CONFIG_HWMON_DEBUG_CHIP is not set